1 | /* |
2 | * Copyright © 2017 Google, Inc. |
3 | * |
4 | * This is part of HarfBuzz, a text shaping library. |
5 | * |
6 | * Permission is hereby granted, without written agreement and without |
7 | * license or royalty fees, to use, copy, modify, and distribute this |
8 | * software and its documentation for any purpose, provided that the |
9 | * above copyright notice and the following two paragraphs appear in |
10 | * all copies of this software. |
11 | * |
12 | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
13 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
14 | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
15 | * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
16 | * DAMAGE. |
17 | * |
18 | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
19 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
20 | * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
21 | * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
22 | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
23 | * |
24 | * Google Author(s): Behdad Esfahbod |
25 | */ |
26 | |
27 | #ifndef HB_OT_VAR_FVAR_TABLE_HH |
28 | #define HB_OT_VAR_FVAR_TABLE_HH |
29 | |
30 | #include "hb-open-type-private.hh" |
31 | |
32 | namespace OT { |
33 | |
34 | |
35 | struct InstanceRecord |
36 | { |
37 | inline bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const |
38 | { |
39 | TRACE_SANITIZE (this); |
40 | return_trace (c->check_struct (this) && |
41 | c->check_array (coordinates, coordinates[0].static_size, axis_count)); |
42 | } |
43 | |
44 | protected: |
45 | UINT16 subfamilyNameID;/* The name ID for entries in the 'name' table |
46 | * that provide subfamily names for this instance. */ |
47 | UINT16 reserved; /* Reserved for future use — set to 0. */ |
48 | Fixed coordinates[VAR];/* The coordinates array for this instance. */ |
49 | //UINT16 postScriptNameIDX;/*Optional. The name ID for entries in the 'name' |
50 | // * table that provide PostScript names for this |
51 | // * instance. */ |
52 | |
53 | public: |
54 | DEFINE_SIZE_ARRAY (4, coordinates); |
55 | }; |
56 | |
57 | struct AxisRecord |
58 | { |
59 | inline bool sanitize (hb_sanitize_context_t *c) const |
60 | { |
61 | TRACE_SANITIZE (this); |
62 | return_trace (c->check_struct (this)); |
63 | } |
64 | |
65 | public: |
66 | Tag axisTag; /* Tag identifying the design variation for the axis. */ |
67 | Fixed minValue; /* The minimum coordinate value for the axis. */ |
68 | Fixed defaultValue; /* The default coordinate value for the axis. */ |
69 | Fixed maxValue; /* The maximum coordinate value for the axis. */ |
70 | UINT16 reserved; /* Reserved for future use — set to 0. */ |
71 | UINT16 axisNameID; /* The name ID for entries in the 'name' table that |
72 | * provide a display name for this axis. */ |
73 | |
74 | public: |
75 | DEFINE_SIZE_STATIC (20); |
76 | }; |
77 | |
78 | |
79 | /* |
80 | * fvar — Font Variations Table |
81 | */ |
82 | |
83 | #define HB_OT_TAG_fvar HB_TAG('f','v','a','r') |
84 | |
85 | struct fvar |
86 | { |
87 | static const hb_tag_t tableTag = HB_OT_TAG_fvar; |
88 | |
89 | inline bool sanitize (hb_sanitize_context_t *c) const |
90 | { |
91 | TRACE_SANITIZE (this); |
92 | return_trace (version.sanitize (c) && |
93 | likely (version.major == 1) && |
94 | c->check_struct (this) && |
95 | instanceSize >= axisCount * 4 + 4 && |
96 | axisSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */ |
97 | instanceSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */ |
98 | c->check_range (this, things) && |
99 | c->check_range (&StructAtOffset<char> (this, things), |
100 | axisCount * axisSize + instanceCount * instanceSize)); |
101 | } |
102 | |
103 | inline unsigned int get_axis_count (void) const |
104 | { return axisCount; } |
105 | |
106 | inline bool get_axis (unsigned int index, hb_ot_var_axis_t *info) const |
107 | { |
108 | if (unlikely (index >= axisCount)) |
109 | return false; |
110 | |
111 | if (info) |
112 | { |
113 | const AxisRecord &axis = get_axes ()[index]; |
114 | info->tag = axis.axisTag; |
115 | info->name_id = axis.axisNameID; |
116 | info->default_value = axis.defaultValue / 65536.; |
117 | /* Ensure order, to simplify client math. */ |
118 | info->min_value = MIN<float> (a: info->default_value, b: axis.minValue / 65536.); |
119 | info->max_value = MAX<float> (a: info->default_value, b: axis.maxValue / 65536.); |
120 | } |
121 | |
122 | return true; |
123 | } |
124 | |
125 | inline unsigned int get_axis_infos (unsigned int start_offset, |
126 | unsigned int *axes_count /* IN/OUT */, |
127 | hb_ot_var_axis_t *axes_array /* OUT */) const |
128 | { |
129 | if (axes_count) |
130 | { |
131 | unsigned int count = axisCount; |
132 | start_offset = MIN (a: start_offset, b: count); |
133 | |
134 | count -= start_offset; |
135 | axes_array += start_offset; |
136 | |
137 | count = MIN (a: count, b: *axes_count); |
138 | *axes_count = count; |
139 | |
140 | for (unsigned int i = 0; i < count; i++) |
141 | get_axis (index: start_offset + i, info: axes_array + i); |
142 | } |
143 | return axisCount; |
144 | } |
145 | |
146 | inline bool find_axis (hb_tag_t tag, unsigned int *index, hb_ot_var_axis_t *info) const |
147 | { |
148 | const AxisRecord *axes = get_axes (); |
149 | unsigned int count = get_axis_count (); |
150 | for (unsigned int i = 0; i < count; i++) |
151 | if (axes[i].axisTag == tag) |
152 | { |
153 | if (index) |
154 | *index = i; |
155 | return get_axis (index: i, info); |
156 | } |
157 | if (index) |
158 | *index = HB_OT_VAR_NO_AXIS_INDEX; |
159 | return false; |
160 | } |
161 | |
162 | inline int normalize_axis_value (unsigned int axis_index, float v) const |
163 | { |
164 | hb_ot_var_axis_t axis; |
165 | if (!get_axis (index: axis_index, info: &axis)) |
166 | return 0; |
167 | |
168 | v = MAX (a: MIN (a: v, b: axis.max_value), b: axis.min_value); /* Clamp. */ |
169 | |
170 | if (v == axis.default_value) |
171 | return 0; |
172 | else if (v < axis.default_value) |
173 | v = (v - axis.default_value) / (axis.default_value - axis.min_value); |
174 | else |
175 | v = (v - axis.default_value) / (axis.max_value - axis.default_value); |
176 | return (int) (v * 16384. + (v >= 0. ? .5 : -.5)); |
177 | } |
178 | |
179 | protected: |
180 | inline const AxisRecord * get_axes (void) const |
181 | { return &StructAtOffset<AxisRecord> (P: this, offset: things); } |
182 | |
183 | inline const InstanceRecord * get_instances (void) const |
184 | { return &StructAtOffset<InstanceRecord> (P: get_axes () + axisCount, offset: 0); } |
185 | |
186 | protected: |
187 | FixedVersion<>version; /* Version of the fvar table |
188 | * initially set to 0x00010000u */ |
189 | Offset16 things; /* Offset in bytes from the beginning of the table |
190 | * to the start of the AxisRecord array. */ |
191 | UINT16 reserved; /* This field is permanently reserved. Set to 2. */ |
192 | UINT16 axisCount; /* The number of variation axes in the font (the |
193 | * number of records in the axes array). */ |
194 | UINT16 axisSize; /* The size in bytes of each VariationAxisRecord — |
195 | * set to 20 (0x0014) for this version. */ |
196 | UINT16 instanceCount; /* The number of named instances defined in the font |
197 | * (the number of records in the instances array). */ |
198 | UINT16 instanceSize; /* The size in bytes of each InstanceRecord — set |
199 | * to either axisCount * sizeof(Fixed) + 4, or to |
200 | * axisCount * sizeof(Fixed) + 6. */ |
201 | |
202 | public: |
203 | DEFINE_SIZE_STATIC (16); |
204 | }; |
205 | |
206 | } /* namespace OT */ |
207 | |
208 | |
209 | #endif /* HB_OT_VAR_FVAR_TABLE_HH */ |
210 | |