38 |
39 |
39 |
40 |
40 namespace OT { |
41 namespace OT { |
41 |
42 |
42 |
43 |
43 struct hb_glyph_pair_t |
44 template <typename KernSubTableHeader> |
44 { |
45 struct KernSubTableFormat3 |
45 hb_codepoint_t left; |
46 { |
46 hb_codepoint_t right; |
47 int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const |
47 }; |
48 { |
48 |
49 hb_array_t<const FWORD> kernValue = kernValueZ.as_array (kernValueCount); |
49 struct KernPair |
50 hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8> > (kernValue).as_array (glyphCount); |
50 { |
51 hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8> > (leftClass).as_array (glyphCount); |
51 inline int get_kerning (void) const |
52 hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8> > (rightClass).as_array (leftClassCount * rightClassCount); |
52 { return value; } |
53 |
53 |
54 unsigned int leftC = leftClass[left]; |
54 inline int cmp (const hb_glyph_pair_t &o) const |
55 unsigned int rightC = rightClass[right]; |
55 { |
56 if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount)) |
56 int ret = left.cmp (o.left); |
57 return 0; |
57 if (ret) return ret; |
58 unsigned int i = leftC * rightClassCount + rightC; |
58 return right.cmp (o.right); |
59 return kernValue[kernIndex[i]]; |
59 } |
60 } |
60 |
61 |
61 inline bool sanitize (hb_sanitize_context_t *c) const |
62 bool apply (AAT::hb_aat_apply_context_t *c) const |
|
63 { |
|
64 TRACE_APPLY (this); |
|
65 |
|
66 if (!c->plan->requested_kerning) |
|
67 return false; |
|
68 |
|
69 if (header.coverage & header.Backwards) |
|
70 return false; |
|
71 |
|
72 hb_kern_machine_t<KernSubTableFormat3> machine (*this, header.coverage & header.CrossStream); |
|
73 machine.kern (c->font, c->buffer, c->plan->kern_mask); |
|
74 |
|
75 return_trace (true); |
|
76 } |
|
77 |
|
78 bool sanitize (hb_sanitize_context_t *c) const |
|
79 { |
|
80 TRACE_SANITIZE (this); |
|
81 return_trace (c->check_struct (this) && |
|
82 c->check_range (kernValueZ, |
|
83 kernValueCount * sizeof (FWORD) + |
|
84 glyphCount * 2 + |
|
85 leftClassCount * rightClassCount)); |
|
86 } |
|
87 |
|
88 protected: |
|
89 KernSubTableHeader header; |
|
90 HBUINT16 glyphCount; /* The number of glyphs in this font. */ |
|
91 HBUINT8 kernValueCount; /* The number of kerning values. */ |
|
92 HBUINT8 leftClassCount; /* The number of left-hand classes. */ |
|
93 HBUINT8 rightClassCount;/* The number of right-hand classes. */ |
|
94 HBUINT8 flags; /* Set to zero (reserved for future use). */ |
|
95 UnsizedArrayOf<FWORD> kernValueZ; /* The kerning values. |
|
96 * Length kernValueCount. */ |
|
97 #if 0 |
|
98 UnsizedArrayOf<HBUINT8>leftClass; /* The left-hand classes. |
|
99 * Length glyphCount. */ |
|
100 UnsizedArrayOf<HBUINT8>rightClass; /* The right-hand classes. |
|
101 * Length glyphCount. */ |
|
102 UnsizedArrayOf<HBUINT8>kernIndex; /* The indices into the kernValue array. |
|
103 * Length leftClassCount * rightClassCount */ |
|
104 #endif |
|
105 public: |
|
106 DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 6, kernValueZ); |
|
107 }; |
|
108 |
|
109 template <typename KernSubTableHeader> |
|
110 struct KernSubTable |
|
111 { |
|
112 unsigned int get_size () const { return u.header.length; } |
|
113 unsigned int get_type () const { return u.header.format; } |
|
114 |
|
115 int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const |
|
116 { |
|
117 switch (get_type ()) { |
|
118 /* This method hooks up to hb_font_t's get_h_kerning. Only support Format0. */ |
|
119 case 0: return u.format0.get_kerning (left, right); |
|
120 default:return 0; |
|
121 } |
|
122 } |
|
123 |
|
124 template <typename context_t> |
|
125 typename context_t::return_t dispatch (context_t *c) const |
|
126 { |
|
127 unsigned int subtable_type = get_type (); |
|
128 TRACE_DISPATCH (this, subtable_type); |
|
129 switch (subtable_type) { |
|
130 case 0: return_trace (c->dispatch (u.format0)); |
|
131 case 1: return_trace (u.header.apple ? c->dispatch (u.format1) : c->default_return_value ()); |
|
132 case 2: return_trace (c->dispatch (u.format2)); |
|
133 case 3: return_trace (u.header.apple ? c->dispatch (u.format3) : c->default_return_value ()); |
|
134 default: return_trace (c->default_return_value ()); |
|
135 } |
|
136 } |
|
137 |
|
138 bool sanitize (hb_sanitize_context_t *c) const |
|
139 { |
|
140 TRACE_SANITIZE (this); |
|
141 if (unlikely (!u.header.sanitize (c) || |
|
142 u.header.length < u.header.min_size || |
|
143 !c->check_range (this, u.header.length))) return_trace (false); |
|
144 |
|
145 return_trace (dispatch (c)); |
|
146 } |
|
147 |
|
148 public: |
|
149 union { |
|
150 KernSubTableHeader header; |
|
151 AAT::KerxSubTableFormat0<KernSubTableHeader> format0; |
|
152 AAT::KerxSubTableFormat1<KernSubTableHeader> format1; |
|
153 AAT::KerxSubTableFormat2<KernSubTableHeader> format2; |
|
154 KernSubTableFormat3<KernSubTableHeader> format3; |
|
155 } u; |
|
156 public: |
|
157 DEFINE_SIZE_MIN (KernSubTableHeader::static_size); |
|
158 }; |
|
159 |
|
160 |
|
161 struct KernOTSubTableHeader |
|
162 { |
|
163 static constexpr bool apple = false; |
|
164 typedef AAT::ObsoleteTypes Types; |
|
165 |
|
166 unsigned int tuple_count () const { return 0; } |
|
167 bool is_horizontal () const { return (coverage & Horizontal); } |
|
168 |
|
169 enum Coverage |
|
170 { |
|
171 Horizontal = 0x01u, |
|
172 Minimum = 0x02u, |
|
173 CrossStream = 0x04u, |
|
174 Override = 0x08u, |
|
175 |
|
176 /* Not supported: */ |
|
177 Backwards = 0x00u, |
|
178 Variation = 0x00u, |
|
179 }; |
|
180 |
|
181 bool sanitize (hb_sanitize_context_t *c) const |
62 { |
182 { |
63 TRACE_SANITIZE (this); |
183 TRACE_SANITIZE (this); |
64 return_trace (c->check_struct (this)); |
184 return_trace (c->check_struct (this)); |
65 } |
185 } |
66 |
186 |
|
187 public: |
|
188 HBUINT16 versionZ; /* Unused. */ |
|
189 HBUINT16 length; /* Length of the subtable (including this header). */ |
|
190 HBUINT8 format; /* Subtable format. */ |
|
191 HBUINT8 coverage; /* Coverage bits. */ |
|
192 public: |
|
193 DEFINE_SIZE_STATIC (6); |
|
194 }; |
|
195 |
|
196 struct KernOT : AAT::KerxTable<KernOT> |
|
197 { |
|
198 friend struct AAT::KerxTable<KernOT>; |
|
199 |
|
200 static constexpr hb_tag_t tableTag = HB_OT_TAG_kern; |
|
201 static constexpr unsigned minVersion = 0u; |
|
202 |
|
203 typedef KernOTSubTableHeader SubTableHeader; |
|
204 typedef SubTableHeader::Types Types; |
|
205 typedef KernSubTable<SubTableHeader> SubTable; |
|
206 |
67 protected: |
207 protected: |
68 GlyphID left; |
208 HBUINT16 version; /* Version--0x0000u */ |
69 GlyphID right; |
209 HBUINT16 tableCount; /* Number of subtables in the kerning table. */ |
70 FWORD value; |
210 SubTable firstSubTable; /* Subtables. */ |
71 public: |
211 public: |
72 DEFINE_SIZE_STATIC (6); |
212 DEFINE_SIZE_MIN (4); |
73 }; |
213 }; |
74 |
214 |
75 struct KernSubTableFormat0 |
215 |
76 { |
216 struct KernAATSubTableHeader |
77 inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const |
217 { |
78 { |
218 static constexpr bool apple = true; |
79 hb_glyph_pair_t pair = {left, right}; |
219 typedef AAT::ObsoleteTypes Types; |
80 int i = pairs.bsearch (pair); |
220 |
81 if (i == -1) |
221 unsigned int tuple_count () const { return 0; } |
82 return 0; |
222 bool is_horizontal () const { return !(coverage & Vertical); } |
83 return pairs[i].get_kerning (); |
223 |
84 } |
224 enum Coverage |
85 |
225 { |
86 inline bool sanitize (hb_sanitize_context_t *c) const |
226 Vertical = 0x80u, |
87 { |
227 CrossStream = 0x40u, |
88 TRACE_SANITIZE (this); |
228 Variation = 0x20u, |
89 return_trace (pairs.sanitize (c)); |
229 |
90 } |
230 /* Not supported: */ |
|
231 Backwards = 0x00u, |
|
232 }; |
|
233 |
|
234 bool sanitize (hb_sanitize_context_t *c) const |
|
235 { |
|
236 TRACE_SANITIZE (this); |
|
237 return_trace (c->check_struct (this)); |
|
238 } |
|
239 |
|
240 public: |
|
241 HBUINT32 length; /* Length of the subtable (including this header). */ |
|
242 HBUINT8 coverage; /* Coverage bits. */ |
|
243 HBUINT8 format; /* Subtable format. */ |
|
244 HBUINT16 tupleIndex; /* The tuple index (used for variations fonts). |
|
245 * This value specifies which tuple this subtable covers. |
|
246 * Note: We don't implement. */ |
|
247 public: |
|
248 DEFINE_SIZE_STATIC (8); |
|
249 }; |
|
250 |
|
251 struct KernAAT : AAT::KerxTable<KernAAT> |
|
252 { |
|
253 friend struct AAT::KerxTable<KernAAT>; |
|
254 |
|
255 static constexpr hb_tag_t tableTag = HB_OT_TAG_kern; |
|
256 static constexpr unsigned minVersion = 0x00010000u; |
|
257 |
|
258 typedef KernAATSubTableHeader SubTableHeader; |
|
259 typedef SubTableHeader::Types Types; |
|
260 typedef KernSubTable<SubTableHeader> SubTable; |
91 |
261 |
92 protected: |
262 protected: |
93 BinSearchArrayOf<KernPair> pairs; /* Array of kerning pairs. */ |
263 HBUINT32 version; /* Version--0x00010000u */ |
94 public: |
264 HBUINT32 tableCount; /* Number of subtables in the kerning table. */ |
95 DEFINE_SIZE_ARRAY (8, pairs); |
265 SubTable firstSubTable; /* Subtables. */ |
96 }; |
|
97 |
|
98 struct KernClassTable |
|
99 { |
|
100 inline unsigned int get_class (hb_codepoint_t g) const { return classes[g - firstGlyph]; } |
|
101 |
|
102 inline bool sanitize (hb_sanitize_context_t *c) const |
|
103 { |
|
104 TRACE_SANITIZE (this); |
|
105 return_trace (firstGlyph.sanitize (c) && classes.sanitize (c)); |
|
106 } |
|
107 |
|
108 protected: |
|
109 HBUINT16 firstGlyph; /* First glyph in class range. */ |
|
110 ArrayOf<HBUINT16> classes; /* Glyph classes. */ |
|
111 public: |
|
112 DEFINE_SIZE_ARRAY (4, classes); |
|
113 }; |
|
114 |
|
115 struct KernSubTableFormat2 |
|
116 { |
|
117 inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const |
|
118 { |
|
119 unsigned int l = (this+leftClassTable).get_class (left); |
|
120 unsigned int r = (this+rightClassTable).get_class (right); |
|
121 unsigned int offset = l * rowWidth + r * sizeof (FWORD); |
|
122 const FWORD *arr = &(this+array); |
|
123 if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end)) |
|
124 return 0; |
|
125 const FWORD *v = &StructAtOffset<FWORD> (arr, offset); |
|
126 if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end)) |
|
127 return 0; |
|
128 return *v; |
|
129 } |
|
130 |
|
131 inline bool sanitize (hb_sanitize_context_t *c) const |
|
132 { |
|
133 TRACE_SANITIZE (this); |
|
134 return_trace (rowWidth.sanitize (c) && |
|
135 leftClassTable.sanitize (c, this) && |
|
136 rightClassTable.sanitize (c, this) && |
|
137 array.sanitize (c, this)); |
|
138 } |
|
139 |
|
140 protected: |
|
141 HBUINT16 rowWidth; /* The width, in bytes, of a row in the table. */ |
|
142 OffsetTo<KernClassTable> |
|
143 leftClassTable; /* Offset from beginning of this subtable to |
|
144 * left-hand class table. */ |
|
145 OffsetTo<KernClassTable> |
|
146 rightClassTable;/* Offset from beginning of this subtable to |
|
147 * right-hand class table. */ |
|
148 OffsetTo<FWORD> |
|
149 array; /* Offset from beginning of this subtable to |
|
150 * the start of the kerning array. */ |
|
151 public: |
266 public: |
152 DEFINE_SIZE_MIN (8); |
267 DEFINE_SIZE_MIN (8); |
153 }; |
268 }; |
154 |
269 |
155 struct KernSubTable |
270 struct kern |
156 { |
271 { |
157 inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end, unsigned int format) const |
272 static constexpr hb_tag_t tableTag = HB_OT_TAG_kern; |
158 { |
273 |
159 switch (format) { |
274 bool has_data () const { return u.version32; } |
160 case 0: return u.format0.get_kerning (left, right); |
275 unsigned int get_type () const { return u.major; } |
161 case 2: return u.format2.get_kerning (left, right, end); |
276 |
|
277 bool has_state_machine () const |
|
278 { |
|
279 switch (get_type ()) { |
|
280 case 0: return u.ot.has_state_machine (); |
|
281 case 1: return u.aat.has_state_machine (); |
|
282 default:return false; |
|
283 } |
|
284 } |
|
285 |
|
286 bool has_cross_stream () const |
|
287 { |
|
288 switch (get_type ()) { |
|
289 case 0: return u.ot.has_cross_stream (); |
|
290 case 1: return u.aat.has_cross_stream (); |
|
291 default:return false; |
|
292 } |
|
293 } |
|
294 |
|
295 int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const |
|
296 { |
|
297 switch (get_type ()) { |
|
298 case 0: return u.ot.get_h_kerning (left, right); |
|
299 case 1: return u.aat.get_h_kerning (left, right); |
162 default:return 0; |
300 default:return 0; |
163 } |
301 } |
164 } |
302 } |
165 |
303 |
166 inline bool sanitize (hb_sanitize_context_t *c, unsigned int format) const |
304 bool apply (AAT::hb_aat_apply_context_t *c) const |
167 { |
305 { return dispatch (c); } |
168 TRACE_SANITIZE (this); |
306 |
169 switch (format) { |
307 template <typename context_t> |
170 case 0: return_trace (u.format0.sanitize (c)); |
308 typename context_t::return_t dispatch (context_t *c) const |
171 case 2: return_trace (u.format2.sanitize (c)); |
309 { |
172 default:return_trace (true); |
310 unsigned int subtable_type = get_type (); |
173 } |
311 TRACE_DISPATCH (this, subtable_type); |
|
312 switch (subtable_type) { |
|
313 case 0: return_trace (c->dispatch (u.ot)); |
|
314 case 1: return_trace (c->dispatch (u.aat)); |
|
315 default: return_trace (c->default_return_value ()); |
|
316 } |
|
317 } |
|
318 |
|
319 bool sanitize (hb_sanitize_context_t *c) const |
|
320 { |
|
321 TRACE_SANITIZE (this); |
|
322 if (!u.version32.sanitize (c)) return_trace (false); |
|
323 return_trace (dispatch (c)); |
174 } |
324 } |
175 |
325 |
176 protected: |
326 protected: |
177 union { |
327 union { |
178 KernSubTableFormat0 format0; |
328 HBUINT32 version32; |
179 KernSubTableFormat2 format2; |
|
180 } u; |
|
181 public: |
|
182 DEFINE_SIZE_MIN (0); |
|
183 }; |
|
184 |
|
185 |
|
186 template <typename T> |
|
187 struct KernSubTableWrapper |
|
188 { |
|
189 /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ |
|
190 inline const T* thiz (void) const { return static_cast<const T *> (this); } |
|
191 |
|
192 inline bool is_horizontal (void) const |
|
193 { return (thiz()->coverage & T::COVERAGE_CHECK_FLAGS) == T::COVERAGE_CHECK_HORIZONTAL; } |
|
194 |
|
195 inline bool is_override (void) const |
|
196 { return bool (thiz()->coverage & T::COVERAGE_OVERRIDE_FLAG); } |
|
197 |
|
198 inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const |
|
199 { return thiz()->subtable.get_kerning (left, right, end, thiz()->format); } |
|
200 |
|
201 inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const |
|
202 { return is_horizontal () ? get_kerning (left, right, end) : 0; } |
|
203 |
|
204 inline unsigned int get_size (void) const { return thiz()->length; } |
|
205 |
|
206 inline bool sanitize (hb_sanitize_context_t *c) const |
|
207 { |
|
208 TRACE_SANITIZE (this); |
|
209 return_trace (c->check_struct (thiz()) && |
|
210 thiz()->length >= T::min_size && |
|
211 c->check_array (thiz(), 1, thiz()->length) && |
|
212 thiz()->subtable.sanitize (c, thiz()->format)); |
|
213 } |
|
214 }; |
|
215 |
|
216 template <typename T> |
|
217 struct KernTable |
|
218 { |
|
219 /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ |
|
220 inline const T* thiz (void) const { return static_cast<const T *> (this); } |
|
221 |
|
222 inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const |
|
223 { |
|
224 int v = 0; |
|
225 const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data); |
|
226 unsigned int count = thiz()->nTables; |
|
227 for (unsigned int i = 0; i < count; i++) |
|
228 { |
|
229 if (st->is_override ()) |
|
230 v = 0; |
|
231 v += st->get_h_kerning (left, right, table_length + (const char *) this); |
|
232 st = &StructAfter<typename T::SubTableWrapper> (*st); |
|
233 } |
|
234 return v; |
|
235 } |
|
236 |
|
237 inline bool sanitize (hb_sanitize_context_t *c) const |
|
238 { |
|
239 TRACE_SANITIZE (this); |
|
240 if (unlikely (!c->check_struct (thiz()) || |
|
241 thiz()->version != T::VERSION)) |
|
242 return_trace (false); |
|
243 |
|
244 const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data); |
|
245 unsigned int count = thiz()->nTables; |
|
246 for (unsigned int i = 0; i < count; i++) |
|
247 { |
|
248 if (unlikely (!st->sanitize (c))) |
|
249 return_trace (false); |
|
250 st = &StructAfter<typename T::SubTableWrapper> (*st); |
|
251 } |
|
252 |
|
253 return_trace (true); |
|
254 } |
|
255 }; |
|
256 |
|
257 struct KernOT : KernTable<KernOT> |
|
258 { |
|
259 friend struct KernTable<KernOT>; |
|
260 |
|
261 static const uint16_t VERSION = 0x0000u; |
|
262 |
|
263 struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper> |
|
264 { |
|
265 friend struct KernSubTableWrapper<SubTableWrapper>; |
|
266 |
|
267 enum coverage_flags_t { |
|
268 COVERAGE_DIRECTION_FLAG = 0x01u, |
|
269 COVERAGE_MINIMUM_FLAG = 0x02u, |
|
270 COVERAGE_CROSSSTREAM_FLAG = 0x04u, |
|
271 COVERAGE_OVERRIDE_FLAG = 0x08u, |
|
272 |
|
273 COVERAGE_VARIATION_FLAG = 0x00u, /* Not supported. */ |
|
274 |
|
275 COVERAGE_CHECK_FLAGS = 0x07u, |
|
276 COVERAGE_CHECK_HORIZONTAL = 0x01u |
|
277 }; |
|
278 |
|
279 protected: |
|
280 HBUINT16 versionZ; /* Unused. */ |
|
281 HBUINT16 length; /* Length of the subtable (including this header). */ |
|
282 HBUINT8 format; /* Subtable format. */ |
|
283 HBUINT8 coverage; /* Coverage bits. */ |
|
284 KernSubTable subtable; /* Subtable data. */ |
|
285 public: |
|
286 DEFINE_SIZE_MIN (6); |
|
287 }; |
|
288 |
|
289 protected: |
|
290 HBUINT16 version; /* Version--0x0000u */ |
|
291 HBUINT16 nTables; /* Number of subtables in the kerning table. */ |
|
292 HBUINT8 data[VAR]; |
|
293 public: |
|
294 DEFINE_SIZE_ARRAY (4, data); |
|
295 }; |
|
296 |
|
297 struct KernAAT : KernTable<KernAAT> |
|
298 { |
|
299 friend struct KernTable<KernAAT>; |
|
300 |
|
301 static const uint32_t VERSION = 0x00010000u; |
|
302 |
|
303 struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper> |
|
304 { |
|
305 friend struct KernSubTableWrapper<SubTableWrapper>; |
|
306 |
|
307 enum coverage_flags_t { |
|
308 COVERAGE_DIRECTION_FLAG = 0x80u, |
|
309 COVERAGE_CROSSSTREAM_FLAG = 0x40u, |
|
310 COVERAGE_VARIATION_FLAG = 0x20u, |
|
311 |
|
312 COVERAGE_OVERRIDE_FLAG = 0x00u, /* Not supported. */ |
|
313 |
|
314 COVERAGE_CHECK_FLAGS = 0xE0u, |
|
315 COVERAGE_CHECK_HORIZONTAL = 0x00u |
|
316 }; |
|
317 |
|
318 protected: |
|
319 HBUINT32 length; /* Length of the subtable (including this header). */ |
|
320 HBUINT8 coverage; /* Coverage bits. */ |
|
321 HBUINT8 format; /* Subtable format. */ |
|
322 HBUINT16 tupleIndex; /* The tuple index (used for variations fonts). |
|
323 * This value specifies which tuple this subtable covers. */ |
|
324 KernSubTable subtable; /* Subtable data. */ |
|
325 public: |
|
326 DEFINE_SIZE_MIN (8); |
|
327 }; |
|
328 |
|
329 protected: |
|
330 HBUINT32 version; /* Version--0x00010000u */ |
|
331 HBUINT32 nTables; /* Number of subtables in the kerning table. */ |
|
332 HBUINT8 data[VAR]; |
|
333 public: |
|
334 DEFINE_SIZE_ARRAY (8, data); |
|
335 }; |
|
336 |
|
337 struct kern |
|
338 { |
|
339 static const hb_tag_t tableTag = HB_OT_TAG_kern; |
|
340 |
|
341 inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const |
|
342 { |
|
343 switch (u.major) { |
|
344 case 0: return u.ot.get_h_kerning (left, right, table_length); |
|
345 case 1: return u.aat.get_h_kerning (left, right, table_length); |
|
346 default:return 0; |
|
347 } |
|
348 } |
|
349 |
|
350 inline bool sanitize (hb_sanitize_context_t *c) const |
|
351 { |
|
352 TRACE_SANITIZE (this); |
|
353 if (!u.major.sanitize (c)) return_trace (false); |
|
354 switch (u.major) { |
|
355 case 0: return_trace (u.ot.sanitize (c)); |
|
356 case 1: return_trace (u.aat.sanitize (c)); |
|
357 default:return_trace (true); |
|
358 } |
|
359 } |
|
360 |
|
361 struct accelerator_t |
|
362 { |
|
363 inline void init (hb_face_t *face) |
|
364 { |
|
365 blob = Sanitizer<kern>().sanitize (face->reference_table (HB_OT_TAG_kern)); |
|
366 table = blob->as<kern> (); |
|
367 table_length = blob->length; |
|
368 } |
|
369 inline void fini (void) |
|
370 { |
|
371 hb_blob_destroy (blob); |
|
372 } |
|
373 |
|
374 inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const |
|
375 { return table->get_h_kerning (left, right, table_length); } |
|
376 |
|
377 private: |
|
378 hb_blob_t *blob; |
|
379 const kern *table; |
|
380 unsigned int table_length; |
|
381 }; |
|
382 |
|
383 protected: |
|
384 union { |
|
385 HBUINT16 major; |
329 HBUINT16 major; |
386 KernOT ot; |
330 KernOT ot; |
387 KernAAT aat; |
331 KernAAT aat; |
388 } u; |
332 } u; |
389 public: |
333 public: |
390 DEFINE_SIZE_UNION (2, major); |
334 DEFINE_SIZE_UNION (4, version32); |
391 }; |
335 }; |
392 |
336 |
393 } /* namespace OT */ |
337 } /* namespace OT */ |
394 |
338 |
395 |
339 |