OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2007,2008,2009 Red Hat, Inc. | 2 * Copyright © 2007,2008,2009 Red Hat, Inc. |
3 * Copyright © 2010 Google, Inc. | 3 * Copyright © 2010,2012 Google, Inc. |
4 * | 4 * |
5 * This is part of HarfBuzz, a text shaping library. | 5 * This is part of HarfBuzz, a text shaping library. |
6 * | 6 * |
7 * Permission is hereby granted, without written agreement and without | 7 * Permission is hereby granted, without written agreement and without |
8 * license or royalty fees, to use, copy, modify, and distribute this | 8 * license or royalty fees, to use, copy, modify, and distribute this |
9 * software and its documentation for any purpose, provided that the | 9 * software and its documentation for any purpose, provided that the |
10 * above copyright notice and the following two paragraphs appear in | 10 * above copyright notice and the following two paragraphs appear in |
11 * all copies of this software. | 11 * all copies of this software. |
12 * | 12 * |
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES | 14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN | 15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | 16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
17 * DAMAGE. | 17 * DAMAGE. |
18 * | 18 * |
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, | 19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | 20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS | 21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO | 22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
24 * | 24 * |
25 * Red Hat Author(s): Behdad Esfahbod | 25 * Red Hat Author(s): Behdad Esfahbod |
26 * Google Author(s): Behdad Esfahbod | 26 * Google Author(s): Behdad Esfahbod |
27 */ | 27 */ |
28 | 28 |
29 #ifndef HB_OT_LAYOUT_COMMON_PRIVATE_HH | 29 #ifndef HB_OT_LAYOUT_COMMON_PRIVATE_HH |
30 #define HB_OT_LAYOUT_COMMON_PRIVATE_HH | 30 #define HB_OT_LAYOUT_COMMON_PRIVATE_HH |
31 | 31 |
32 #include "hb-ot-layout-private.hh" | 32 #include "hb-ot-layout-private.hh" |
33 | |
34 #include "hb-open-type-private.hh" | 33 #include "hb-open-type-private.hh" |
| 34 #include "hb-set-private.hh" |
35 | 35 |
36 | 36 |
37 #define NO_CONTEXT ((unsigned int) 0x110000) | |
38 #define NOT_COVERED ((unsigned int) 0x110000) | 37 #define NOT_COVERED ((unsigned int) 0x110000) |
39 #define MAX_NESTING_LEVEL 8 | 38 #define MAX_NESTING_LEVEL 8 |
40 | 39 |
41 | 40 |
42 | 41 |
43 /* | 42 /* |
44 * | 43 * |
45 * OpenType Layout Common Table Formats | 44 * OpenType Layout Common Table Formats |
46 * | 45 * |
47 */ | 46 */ |
48 | 47 |
49 | 48 |
50 /* | 49 /* |
51 * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList | 50 * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList |
52 */ | 51 */ |
53 | 52 |
54 template <typename Type> | 53 template <typename Type> |
55 struct Record | 54 struct Record |
56 { | 55 { |
57 inline int cmp (hb_tag_t a) const { | 56 inline int cmp (hb_tag_t a) const { |
58 return tag.cmp (a); | 57 return tag.cmp (a); |
59 } | 58 } |
60 | 59 |
61 inline bool sanitize (hb_sanitize_context_t *c, void *base) { | 60 inline bool sanitize (hb_sanitize_context_t *c, void *base) { |
62 TRACE_SANITIZE (); | 61 TRACE_SANITIZE (); |
63 return c->check_struct (this) | 62 return TRACE_RETURN (c->check_struct (this) && offset.sanitize (c, base)); |
64 » && offset.sanitize (c, base); | |
65 } | 63 } |
66 | 64 |
67 Tag tag; /* 4-byte Tag identifier */ | 65 Tag tag; /* 4-byte Tag identifier */ |
68 OffsetTo<Type> | 66 OffsetTo<Type> |
69 offset; /* Offset from beginning of object holding | 67 offset; /* Offset from beginning of object holding |
70 * the Record */ | 68 * the Record */ |
71 public: | 69 public: |
72 DEFINE_SIZE_STATIC (6); | 70 DEFINE_SIZE_STATIC (6); |
73 }; | 71 }; |
74 | 72 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 }; | 106 }; |
109 | 107 |
110 template <typename Type> | 108 template <typename Type> |
111 struct RecordListOf : RecordArrayOf<Type> | 109 struct RecordListOf : RecordArrayOf<Type> |
112 { | 110 { |
113 inline const Type& operator [] (unsigned int i) const | 111 inline const Type& operator [] (unsigned int i) const |
114 { return this+RecordArrayOf<Type>::operator [](i).offset; } | 112 { return this+RecordArrayOf<Type>::operator [](i).offset; } |
115 | 113 |
116 inline bool sanitize (hb_sanitize_context_t *c) { | 114 inline bool sanitize (hb_sanitize_context_t *c) { |
117 TRACE_SANITIZE (); | 115 TRACE_SANITIZE (); |
118 return RecordArrayOf<Type>::sanitize (c, this); | 116 return TRACE_RETURN (RecordArrayOf<Type>::sanitize (c, this)); |
119 } | 117 } |
120 }; | 118 }; |
121 | 119 |
122 | 120 |
123 struct RangeRecord | 121 struct RangeRecord |
124 { | 122 { |
125 inline int cmp (hb_codepoint_t g) const { | 123 inline int cmp (hb_codepoint_t g) const { |
126 hb_codepoint_t a = start, b = end; | 124 hb_codepoint_t a = start, b = end; |
127 return g < a ? -1 : g <= b ? 0 : +1 ; | 125 return g < a ? -1 : g <= b ? 0 : +1 ; |
128 } | 126 } |
129 | 127 |
130 inline bool sanitize (hb_sanitize_context_t *c) { | 128 inline bool sanitize (hb_sanitize_context_t *c) { |
131 TRACE_SANITIZE (); | 129 TRACE_SANITIZE (); |
132 return c->check_struct (this); | 130 return TRACE_RETURN (c->check_struct (this)); |
| 131 } |
| 132 |
| 133 inline bool intersects (const hb_set_t *glyphs) const { |
| 134 return glyphs->intersects (start, end); |
133 } | 135 } |
134 | 136 |
135 GlyphID start; /* First GlyphID in the range */ | 137 GlyphID start; /* First GlyphID in the range */ |
136 GlyphID end; /* Last GlyphID in the range */ | 138 GlyphID end; /* Last GlyphID in the range */ |
137 USHORT value; /* Value */ | 139 USHORT value; /* Value */ |
138 public: | 140 public: |
139 DEFINE_SIZE_STATIC (6); | 141 DEFINE_SIZE_STATIC (6); |
140 }; | 142 }; |
141 DEFINE_NULL_DATA (RangeRecord, "\000\001"); | 143 DEFINE_NULL_DATA (RangeRecord, "\000\001"); |
142 | 144 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 inline bool has_required_feature (void) const { return reqFeatureIndex != 0xff
ff; } | 179 inline bool has_required_feature (void) const { return reqFeatureIndex != 0xff
ff; } |
178 inline unsigned int get_required_feature_index (void) const | 180 inline unsigned int get_required_feature_index (void) const |
179 { | 181 { |
180 if (reqFeatureIndex == 0xffff) | 182 if (reqFeatureIndex == 0xffff) |
181 return Index::NOT_FOUND_INDEX; | 183 return Index::NOT_FOUND_INDEX; |
182 return reqFeatureIndex;; | 184 return reqFeatureIndex;; |
183 } | 185 } |
184 | 186 |
185 inline bool sanitize (hb_sanitize_context_t *c) { | 187 inline bool sanitize (hb_sanitize_context_t *c) { |
186 TRACE_SANITIZE (); | 188 TRACE_SANITIZE (); |
187 return c->check_struct (this) | 189 return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c)); |
188 » && featureIndex.sanitize (c); | |
189 } | 190 } |
190 | 191 |
191 Offset lookupOrder; /* = Null (reserved for an offset to a | 192 Offset lookupOrder; /* = Null (reserved for an offset to a |
192 * reordering table) */ | 193 * reordering table) */ |
193 USHORT reqFeatureIndex;/* Index of a feature required for this | 194 USHORT reqFeatureIndex;/* Index of a feature required for this |
194 * language system--if no required features | 195 * language system--if no required features |
195 * = 0xFFFF */ | 196 * = 0xFFFF */ |
196 IndexArray featureIndex; /* Array of indices into the FeatureList */ | 197 IndexArray featureIndex; /* Array of indices into the FeatureList */ |
197 public: | 198 public: |
198 DEFINE_SIZE_ARRAY (6, featureIndex); | 199 DEFINE_SIZE_ARRAY (6, featureIndex); |
(...skipping 17 matching lines...) Expand all Loading... |
216 return this+langSys[i].offset; | 217 return this+langSys[i].offset; |
217 } | 218 } |
218 inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const | 219 inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const |
219 { return langSys.find_index (tag, index); } | 220 { return langSys.find_index (tag, index); } |
220 | 221 |
221 inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; } | 222 inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; } |
222 inline const LangSys& get_default_lang_sys (void) const { return this+defaultL
angSys; } | 223 inline const LangSys& get_default_lang_sys (void) const { return this+defaultL
angSys; } |
223 | 224 |
224 inline bool sanitize (hb_sanitize_context_t *c) { | 225 inline bool sanitize (hb_sanitize_context_t *c) { |
225 TRACE_SANITIZE (); | 226 TRACE_SANITIZE (); |
226 return defaultLangSys.sanitize (c, this) | 227 return TRACE_RETURN (defaultLangSys.sanitize (c, this) && langSys.sanitize (
c, this)); |
227 » && langSys.sanitize (c, this); | |
228 } | 228 } |
229 | 229 |
230 private: | 230 private: |
231 OffsetTo<LangSys> | 231 OffsetTo<LangSys> |
232 defaultLangSys; /* Offset to DefaultLangSys table--from | 232 defaultLangSys; /* Offset to DefaultLangSys table--from |
233 * beginning of Script table--may be Null */ | 233 * beginning of Script table--may be Null */ |
234 RecordArrayOf<LangSys> | 234 RecordArrayOf<LangSys> |
235 langSys; /* Array of LangSysRecords--listed | 235 langSys; /* Array of LangSysRecords--listed |
236 * alphabetically by LangSysTag */ | 236 * alphabetically by LangSysTag */ |
237 public: | 237 public: |
238 DEFINE_SIZE_ARRAY (4, langSys); | 238 DEFINE_SIZE_ARRAY (4, langSys); |
239 }; | 239 }; |
240 | 240 |
241 typedef RecordListOf<Script> ScriptList; | 241 typedef RecordListOf<Script> ScriptList; |
242 | 242 |
243 | 243 |
244 struct Feature | 244 struct Feature |
245 { | 245 { |
246 inline unsigned int get_lookup_count (void) const | 246 inline unsigned int get_lookup_count (void) const |
247 { return lookupIndex.len; } | 247 { return lookupIndex.len; } |
248 inline hb_tag_t get_lookup_index (unsigned int i) const | 248 inline hb_tag_t get_lookup_index (unsigned int i) const |
249 { return lookupIndex[i]; } | 249 { return lookupIndex[i]; } |
250 inline unsigned int get_lookup_indexes (unsigned int start_index, | 250 inline unsigned int get_lookup_indexes (unsigned int start_index, |
251 unsigned int *lookup_count /* IN/OUT *
/, | 251 unsigned int *lookup_count /* IN/OUT *
/, |
252 unsigned int *lookup_tags /* OUT */) c
onst | 252 unsigned int *lookup_tags /* OUT */) c
onst |
253 { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); } | 253 { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); } |
254 | 254 |
255 inline bool sanitize (hb_sanitize_context_t *c) { | 255 inline bool sanitize (hb_sanitize_context_t *c) { |
256 TRACE_SANITIZE (); | 256 TRACE_SANITIZE (); |
257 return c->check_struct (this) | 257 return TRACE_RETURN (c->check_struct (this) && lookupIndex.sanitize (c)); |
258 » && lookupIndex.sanitize (c); | |
259 } | 258 } |
260 | 259 |
261 Offset featureParams; /* Offset to Feature Parameters table (if one | 260 Offset featureParams; /* Offset to Feature Parameters table (if one |
262 * has been defined for the feature), relative | 261 * has been defined for the feature), relative |
263 * to the beginning of the Feature Table; = Null | 262 * to the beginning of the Feature Table; = Null |
264 * if not required */ | 263 * if not required */ |
265 IndexArray lookupIndex; /* Array of LookupList indices */ | 264 IndexArray lookupIndex; /* Array of LookupList indices */ |
266 public: | 265 public: |
267 DEFINE_SIZE_ARRAY (4, lookupIndex); | 266 DEFINE_SIZE_ARRAY (4, lookupIndex); |
268 }; | 267 }; |
269 | 268 |
270 typedef RecordListOf<Feature> FeatureList; | 269 typedef RecordListOf<Feature> FeatureList; |
271 | 270 |
272 | 271 |
273 struct LookupFlag : USHORT | 272 struct LookupFlag : USHORT |
274 { | 273 { |
275 enum { | 274 enum Flags { |
276 RightToLeft = 0x0001u, | 275 RightToLeft = 0x0001u, |
277 IgnoreBaseGlyphs = 0x0002u, | 276 IgnoreBaseGlyphs = 0x0002u, |
278 IgnoreLigatures = 0x0004u, | 277 IgnoreLigatures = 0x0004u, |
279 IgnoreMarks = 0x0008u, | 278 IgnoreMarks = 0x0008u, |
280 IgnoreFlags = 0x000Eu, | 279 IgnoreFlags = 0x000Eu, |
281 UseMarkFilteringSet = 0x0010u, | 280 UseMarkFilteringSet = 0x0010u, |
282 Reserved = 0x00E0u, | 281 Reserved = 0x00E0u, |
283 MarkAttachmentType = 0xFF00u | 282 MarkAttachmentType = 0xFF00u |
284 }; | 283 }; |
285 public: | 284 public: |
(...skipping 16 matching lines...) Expand all Loading... |
302 { | 301 { |
303 const USHORT &markFilteringSet = StructAfter<USHORT> (subTable); | 302 const USHORT &markFilteringSet = StructAfter<USHORT> (subTable); |
304 flag += (markFilteringSet << 16); | 303 flag += (markFilteringSet << 16); |
305 } | 304 } |
306 return flag; | 305 return flag; |
307 } | 306 } |
308 | 307 |
309 inline bool sanitize (hb_sanitize_context_t *c) { | 308 inline bool sanitize (hb_sanitize_context_t *c) { |
310 TRACE_SANITIZE (); | 309 TRACE_SANITIZE (); |
311 /* Real sanitize of the subtables is done by GSUB/GPOS/... */ | 310 /* Real sanitize of the subtables is done by GSUB/GPOS/... */ |
312 if (!(c->check_struct (this) | 311 if (!(c->check_struct (this) && subTable.sanitize (c))) return TRACE_RETURN
(false); |
313 && subTable.sanitize (c))) return false; | |
314 if (unlikely (lookupFlag & LookupFlag::UseMarkFilteringSet)) | 312 if (unlikely (lookupFlag & LookupFlag::UseMarkFilteringSet)) |
315 { | 313 { |
316 USHORT &markFilteringSet = StructAfter<USHORT> (subTable); | 314 USHORT &markFilteringSet = StructAfter<USHORT> (subTable); |
317 if (!markFilteringSet.sanitize (c)) return false; | 315 if (!markFilteringSet.sanitize (c)) return TRACE_RETURN (false); |
318 } | 316 } |
319 return true; | 317 return TRACE_RETURN (true); |
320 } | 318 } |
321 | 319 |
322 USHORT lookupType; /* Different enumerations for GSUB and G
POS */ | 320 USHORT lookupType; /* Different enumerations for GSUB and G
POS */ |
323 USHORT lookupFlag; /* Lookup qualifiers */ | 321 USHORT lookupFlag; /* Lookup qualifiers */ |
324 ArrayOf<Offset> | 322 ArrayOf<Offset> |
325 subTable; /* Array of SubTables */ | 323 subTable; /* Array of SubTables */ |
326 USHORT markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph s
ets | 324 USHORT markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph s
ets |
327 * structure. This field is only present
if bit | 325 * structure. This field is only present
if bit |
328 * UseMarkFilteringSet of lookup flags i
s set. */ | 326 * UseMarkFilteringSet of lookup flags i
s set. */ |
329 public: | 327 public: |
(...skipping 15 matching lines...) Expand all Loading... |
345 inline unsigned int get_coverage (hb_codepoint_t glyph_id) const | 343 inline unsigned int get_coverage (hb_codepoint_t glyph_id) const |
346 { | 344 { |
347 int i = glyphArray.search (glyph_id); | 345 int i = glyphArray.search (glyph_id); |
348 if (i != -1) | 346 if (i != -1) |
349 return i; | 347 return i; |
350 return NOT_COVERED; | 348 return NOT_COVERED; |
351 } | 349 } |
352 | 350 |
353 inline bool sanitize (hb_sanitize_context_t *c) { | 351 inline bool sanitize (hb_sanitize_context_t *c) { |
354 TRACE_SANITIZE (); | 352 TRACE_SANITIZE (); |
355 return glyphArray.sanitize (c); | 353 return TRACE_RETURN (glyphArray.sanitize (c)); |
356 } | 354 } |
357 | 355 |
| 356 inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) c
onst { |
| 357 return glyphs->has (glyphArray[index]); |
| 358 } |
| 359 |
| 360 struct Iter { |
| 361 inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; }; |
| 362 inline bool more (void) { return i < c->glyphArray.len; } |
| 363 inline void next (void) { i++; } |
| 364 inline uint16_t get_glyph (void) { return c->glyphArray[i]; } |
| 365 inline uint16_t get_coverage (void) { return i; } |
| 366 |
| 367 private: |
| 368 const struct CoverageFormat1 *c; |
| 369 unsigned int i; |
| 370 }; |
| 371 |
358 private: | 372 private: |
359 USHORT coverageFormat; /* Format identifier--format = 1 */ | 373 USHORT coverageFormat; /* Format identifier--format = 1 */ |
360 SortedArrayOf<GlyphID> | 374 SortedArrayOf<GlyphID> |
361 glyphArray; /* Array of GlyphIDs--in numerical order */ | 375 glyphArray; /* Array of GlyphIDs--in numerical order */ |
362 public: | 376 public: |
363 DEFINE_SIZE_ARRAY (4, glyphArray); | 377 DEFINE_SIZE_ARRAY (4, glyphArray); |
364 }; | 378 }; |
365 | 379 |
366 struct CoverageFormat2 | 380 struct CoverageFormat2 |
367 { | 381 { |
368 friend struct Coverage; | 382 friend struct Coverage; |
369 | 383 |
370 private: | 384 private: |
371 inline unsigned int get_coverage (hb_codepoint_t glyph_id) const | 385 inline unsigned int get_coverage (hb_codepoint_t glyph_id) const |
372 { | 386 { |
373 int i = rangeRecord.search (glyph_id); | 387 int i = rangeRecord.search (glyph_id); |
374 if (i != -1) { | 388 if (i != -1) { |
375 const RangeRecord &range = rangeRecord[i]; | 389 const RangeRecord &range = rangeRecord[i]; |
376 return (unsigned int) range.value + (glyph_id - range.start); | 390 return (unsigned int) range.value + (glyph_id - range.start); |
377 } | 391 } |
378 return NOT_COVERED; | 392 return NOT_COVERED; |
379 } | 393 } |
380 | 394 |
381 inline bool sanitize (hb_sanitize_context_t *c) { | 395 inline bool sanitize (hb_sanitize_context_t *c) { |
382 TRACE_SANITIZE (); | 396 TRACE_SANITIZE (); |
383 return rangeRecord.sanitize (c); | 397 return TRACE_RETURN (rangeRecord.sanitize (c)); |
384 } | 398 } |
385 | 399 |
| 400 inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) c
onst { |
| 401 unsigned int i; |
| 402 unsigned int count = rangeRecord.len; |
| 403 for (i = 0; i < count; i++) { |
| 404 const RangeRecord &range = rangeRecord[i]; |
| 405 if (range.value <= index && |
| 406 index < (unsigned int) range.value + (range.end - range.start) && |
| 407 range.intersects (glyphs)) |
| 408 return true; |
| 409 else if (index < range.value) |
| 410 return false; |
| 411 } |
| 412 return false; |
| 413 } |
| 414 |
| 415 struct Iter { |
| 416 inline void init (const CoverageFormat2 &c_) { |
| 417 c = &c_; |
| 418 coverage = 0; |
| 419 i = 0; |
| 420 j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0; |
| 421 } |
| 422 inline bool more (void) { return i < c->rangeRecord.len; } |
| 423 inline void next (void) { |
| 424 coverage++; |
| 425 if (j == c->rangeRecord[i].end) { |
| 426 i++; |
| 427 if (more ()) |
| 428 j = c->rangeRecord[i].start; |
| 429 return; |
| 430 } |
| 431 j++; |
| 432 } |
| 433 inline uint16_t get_glyph (void) { return j; } |
| 434 inline uint16_t get_coverage (void) { return coverage; } |
| 435 |
| 436 private: |
| 437 const struct CoverageFormat2 *c; |
| 438 unsigned int i, j, coverage; |
| 439 }; |
| 440 |
386 private: | 441 private: |
387 USHORT coverageFormat; /* Format identifier--format = 2 */ | 442 USHORT coverageFormat; /* Format identifier--format = 2 */ |
388 SortedArrayOf<RangeRecord> | 443 SortedArrayOf<RangeRecord> |
389 rangeRecord; /* Array of glyph ranges--ordered by | 444 rangeRecord; /* Array of glyph ranges--ordered by |
390 * Start GlyphID. rangeCount entries | 445 * Start GlyphID. rangeCount entries |
391 * long */ | 446 * long */ |
392 public: | 447 public: |
393 DEFINE_SIZE_ARRAY (4, rangeRecord); | 448 DEFINE_SIZE_ARRAY (4, rangeRecord); |
394 }; | 449 }; |
395 | 450 |
396 struct Coverage | 451 struct Coverage |
397 { | 452 { |
398 inline unsigned int operator () (hb_codepoint_t glyph_id) const { return get_c
overage (glyph_id); } | 453 inline unsigned int operator () (hb_codepoint_t glyph_id) const { return get_c
overage (glyph_id); } |
399 | 454 |
400 inline unsigned int get_coverage (hb_codepoint_t glyph_id) const | 455 inline unsigned int get_coverage (hb_codepoint_t glyph_id) const |
401 { | 456 { |
402 switch (u.format) { | 457 switch (u.format) { |
403 case 1: return u.format1.get_coverage(glyph_id); | 458 case 1: return u.format1.get_coverage(glyph_id); |
404 case 2: return u.format2.get_coverage(glyph_id); | 459 case 2: return u.format2.get_coverage(glyph_id); |
405 default:return NOT_COVERED; | 460 default:return NOT_COVERED; |
406 } | 461 } |
407 } | 462 } |
408 | 463 |
409 inline bool sanitize (hb_sanitize_context_t *c) { | 464 inline bool sanitize (hb_sanitize_context_t *c) { |
410 TRACE_SANITIZE (); | 465 TRACE_SANITIZE (); |
411 if (!u.format.sanitize (c)) return false; | 466 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
412 switch (u.format) { | 467 switch (u.format) { |
413 case 1: return u.format1.sanitize (c); | 468 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
414 case 2: return u.format2.sanitize (c); | 469 case 2: return TRACE_RETURN (u.format2.sanitize (c)); |
415 default:return true; | 470 default:return TRACE_RETURN (true); |
416 } | 471 } |
417 } | 472 } |
418 | 473 |
| 474 inline bool intersects (const hb_set_t *glyphs) const { |
| 475 /* TODO speed this up */ |
| 476 Coverage::Iter iter; |
| 477 for (iter.init (*this); iter.more (); iter.next ()) { |
| 478 if (glyphs->has (iter.get_glyph ())) |
| 479 return true; |
| 480 } |
| 481 return false; |
| 482 } |
| 483 |
| 484 inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) c
onst { |
| 485 switch (u.format) { |
| 486 case 1: return u.format1.intersects_coverage (glyphs, index); |
| 487 case 2: return u.format2.intersects_coverage (glyphs, index); |
| 488 default:return false; |
| 489 } |
| 490 } |
| 491 |
| 492 struct Iter { |
| 493 Iter (void) : format (0) {}; |
| 494 inline void init (const Coverage &c_) { |
| 495 format = c_.u.format; |
| 496 switch (format) { |
| 497 case 1: return u.format1.init (c_.u.format1); |
| 498 case 2: return u.format2.init (c_.u.format2); |
| 499 default:return; |
| 500 } |
| 501 } |
| 502 inline bool more (void) { |
| 503 switch (format) { |
| 504 case 1: return u.format1.more (); |
| 505 case 2: return u.format2.more (); |
| 506 default:return true; |
| 507 } |
| 508 } |
| 509 inline void next (void) { |
| 510 switch (format) { |
| 511 case 1: u.format1.next (); break; |
| 512 case 2: u.format2.next (); break; |
| 513 default: break; |
| 514 } |
| 515 } |
| 516 inline uint16_t get_glyph (void) { |
| 517 switch (format) { |
| 518 case 1: return u.format1.get_glyph (); |
| 519 case 2: return u.format2.get_glyph (); |
| 520 default:return true; |
| 521 } |
| 522 } |
| 523 inline uint16_t get_coverage (void) { |
| 524 switch (format) { |
| 525 case 1: return u.format1.get_coverage (); |
| 526 case 2: return u.format2.get_coverage (); |
| 527 default:return true; |
| 528 } |
| 529 } |
| 530 |
| 531 private: |
| 532 unsigned int format; |
| 533 union { |
| 534 CoverageFormat1::Iter format1; |
| 535 CoverageFormat2::Iter format2; |
| 536 } u; |
| 537 }; |
| 538 |
419 private: | 539 private: |
420 union { | 540 union { |
421 USHORT format; /* Format identifier */ | 541 USHORT format; /* Format identifier */ |
422 CoverageFormat1 format1; | 542 CoverageFormat1 format1; |
423 CoverageFormat2 format2; | 543 CoverageFormat2 format2; |
424 } u; | 544 } u; |
425 public: | 545 public: |
426 DEFINE_SIZE_UNION (2, format); | 546 DEFINE_SIZE_UNION (2, format); |
427 }; | 547 }; |
428 | 548 |
429 | 549 |
430 /* | 550 /* |
431 * Class Definition Table | 551 * Class Definition Table |
432 */ | 552 */ |
433 | 553 |
434 struct ClassDefFormat1 | 554 struct ClassDefFormat1 |
435 { | 555 { |
436 friend struct ClassDef; | 556 friend struct ClassDef; |
437 | 557 |
438 private: | 558 private: |
439 inline unsigned int get_class (hb_codepoint_t glyph_id) const | 559 inline unsigned int get_class (hb_codepoint_t glyph_id) const |
440 { | 560 { |
441 if ((unsigned int) (glyph_id - startGlyph) < classValue.len) | 561 if ((unsigned int) (glyph_id - startGlyph) < classValue.len) |
442 return classValue[glyph_id - startGlyph]; | 562 return classValue[glyph_id - startGlyph]; |
443 return 0; | 563 return 0; |
444 } | 564 } |
445 | 565 |
446 inline bool sanitize (hb_sanitize_context_t *c) { | 566 inline bool sanitize (hb_sanitize_context_t *c) { |
447 TRACE_SANITIZE (); | 567 TRACE_SANITIZE (); |
448 return c->check_struct (this) | 568 return TRACE_RETURN (c->check_struct (this) && classValue.sanitize (c)); |
449 » && classValue.sanitize (c); | 569 } |
| 570 |
| 571 inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) cons
t { |
| 572 unsigned int count = classValue.len; |
| 573 for (unsigned int i = 0; i < count; i++) |
| 574 if (classValue[i] == klass && glyphs->has (startGlyph + i)) |
| 575 return true; |
| 576 return false; |
450 } | 577 } |
451 | 578 |
452 USHORT classFormat; /* Format identifier--format = 1 */ | 579 USHORT classFormat; /* Format identifier--format = 1 */ |
453 GlyphID startGlyph; /* First GlyphID of the classValueArray
*/ | 580 GlyphID startGlyph; /* First GlyphID of the classValueArray
*/ |
454 ArrayOf<USHORT> | 581 ArrayOf<USHORT> |
455 classValue; /* Array of Class Values--one per GlyphI
D */ | 582 classValue; /* Array of Class Values--one per GlyphI
D */ |
456 public: | 583 public: |
457 DEFINE_SIZE_ARRAY (6, classValue); | 584 DEFINE_SIZE_ARRAY (6, classValue); |
458 }; | 585 }; |
459 | 586 |
460 struct ClassDefFormat2 | 587 struct ClassDefFormat2 |
461 { | 588 { |
462 friend struct ClassDef; | 589 friend struct ClassDef; |
463 | 590 |
464 private: | 591 private: |
465 inline unsigned int get_class (hb_codepoint_t glyph_id) const | 592 inline unsigned int get_class (hb_codepoint_t glyph_id) const |
466 { | 593 { |
467 int i = rangeRecord.search (glyph_id); | 594 int i = rangeRecord.search (glyph_id); |
468 if (i != -1) | 595 if (i != -1) |
469 return rangeRecord[i].value; | 596 return rangeRecord[i].value; |
470 return 0; | 597 return 0; |
471 } | 598 } |
472 | 599 |
473 inline bool sanitize (hb_sanitize_context_t *c) { | 600 inline bool sanitize (hb_sanitize_context_t *c) { |
474 TRACE_SANITIZE (); | 601 TRACE_SANITIZE (); |
475 return rangeRecord.sanitize (c); | 602 return TRACE_RETURN (rangeRecord.sanitize (c)); |
| 603 } |
| 604 |
| 605 inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) cons
t { |
| 606 unsigned int count = rangeRecord.len; |
| 607 for (unsigned int i = 0; i < count; i++) |
| 608 if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs)) |
| 609 return true; |
| 610 return false; |
476 } | 611 } |
477 | 612 |
478 USHORT classFormat; /* Format identifier--format = 2 */ | 613 USHORT classFormat; /* Format identifier--format = 2 */ |
479 SortedArrayOf<RangeRecord> | 614 SortedArrayOf<RangeRecord> |
480 rangeRecord; /* Array of glyph ranges--ordered by | 615 rangeRecord; /* Array of glyph ranges--ordered by |
481 * Start GlyphID */ | 616 * Start GlyphID */ |
482 public: | 617 public: |
483 DEFINE_SIZE_ARRAY (4, rangeRecord); | 618 DEFINE_SIZE_ARRAY (4, rangeRecord); |
484 }; | 619 }; |
485 | 620 |
486 struct ClassDef | 621 struct ClassDef |
487 { | 622 { |
488 inline unsigned int operator () (hb_codepoint_t glyph_id) const { return get_c
lass (glyph_id); } | 623 inline unsigned int operator () (hb_codepoint_t glyph_id) const { return get_c
lass (glyph_id); } |
489 | 624 |
490 inline unsigned int get_class (hb_codepoint_t glyph_id) const | 625 inline unsigned int get_class (hb_codepoint_t glyph_id) const |
491 { | 626 { |
492 switch (u.format) { | 627 switch (u.format) { |
493 case 1: return u.format1.get_class(glyph_id); | 628 case 1: return u.format1.get_class(glyph_id); |
494 case 2: return u.format2.get_class(glyph_id); | 629 case 2: return u.format2.get_class(glyph_id); |
495 default:return 0; | 630 default:return 0; |
496 } | 631 } |
497 } | 632 } |
498 | 633 |
499 inline bool sanitize (hb_sanitize_context_t *c) { | 634 inline bool sanitize (hb_sanitize_context_t *c) { |
500 TRACE_SANITIZE (); | 635 TRACE_SANITIZE (); |
501 if (!u.format.sanitize (c)) return false; | 636 if (!u.format.sanitize (c)) return TRACE_RETURN (false); |
502 switch (u.format) { | 637 switch (u.format) { |
503 case 1: return u.format1.sanitize (c); | 638 case 1: return TRACE_RETURN (u.format1.sanitize (c)); |
504 case 2: return u.format2.sanitize (c); | 639 case 2: return TRACE_RETURN (u.format2.sanitize (c)); |
505 default:return true; | 640 default:return TRACE_RETURN (true); |
506 } | 641 } |
507 } | 642 } |
508 | 643 |
| 644 inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) cons
t { |
| 645 switch (u.format) { |
| 646 case 1: return u.format1.intersects_class (glyphs, klass); |
| 647 case 2: return u.format2.intersects_class (glyphs, klass); |
| 648 default:return false; |
| 649 } |
| 650 } |
| 651 |
509 private: | 652 private: |
510 union { | 653 union { |
511 USHORT format; /* Format identifier */ | 654 USHORT format; /* Format identifier */ |
512 ClassDefFormat1 format1; | 655 ClassDefFormat1 format1; |
513 ClassDefFormat2 format2; | 656 ClassDefFormat2 format2; |
514 } u; | 657 } u; |
515 public: | 658 public: |
516 DEFINE_SIZE_UNION (2, format); | 659 DEFINE_SIZE_UNION (2, format); |
517 }; | 660 }; |
518 | 661 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 | 710 |
568 inline unsigned int get_size (void) const | 711 inline unsigned int get_size (void) const |
569 { | 712 { |
570 unsigned int f = deltaFormat; | 713 unsigned int f = deltaFormat; |
571 if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::sta
tic_size; | 714 if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::sta
tic_size; |
572 return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f))); | 715 return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f))); |
573 } | 716 } |
574 | 717 |
575 inline bool sanitize (hb_sanitize_context_t *c) { | 718 inline bool sanitize (hb_sanitize_context_t *c) { |
576 TRACE_SANITIZE (); | 719 TRACE_SANITIZE (); |
577 return c->check_struct (this) | 720 return TRACE_RETURN (c->check_struct (this) && c->check_range (this, this->g
et_size ())); |
578 » && c->check_range (this, this->get_size ()); | |
579 } | 721 } |
580 | 722 |
581 private: | 723 private: |
582 USHORT startSize; /* Smallest size to correct--in ppem */ | 724 USHORT startSize; /* Smallest size to correct--in ppem */ |
583 USHORT endSize; /* Largest size to correct--in ppem */ | 725 USHORT endSize; /* Largest size to correct--in ppem */ |
584 USHORT deltaFormat; /* Format of DeltaValue array data: 1, 2
, or 3 | 726 USHORT deltaFormat; /* Format of DeltaValue array data: 1, 2
, or 3 |
585 * 1 Signed 2-bit value, 8 values per
uint16 | 727 * 1 Signed 2-bit value, 8 values per
uint16 |
586 * 2 Signed 4-bit value, 4 values per
uint16 | 728 * 2 Signed 4-bit value, 4 values per
uint16 |
587 * 3 Signed 8-bit value, 2 values per
uint16 | 729 * 3 Signed 8-bit value, 2 values per
uint16 |
588 */ | 730 */ |
589 USHORT deltaValue[VAR]; /* Array of compressed data */ | 731 USHORT deltaValue[VAR]; /* Array of compressed data */ |
590 public: | 732 public: |
591 DEFINE_SIZE_ARRAY (6, deltaValue); | 733 DEFINE_SIZE_ARRAY (6, deltaValue); |
592 }; | 734 }; |
593 | 735 |
594 | 736 |
595 | 737 |
596 #endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */ | 738 #endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */ |
OLD | NEW |