| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc. | 2 * Copyright © 2007,2008,2009,2010 Red Hat, Inc. |
| 3 * Copyright © 2010,2012,2013 Google, Inc. | 3 * Copyright © 2010,2012,2013 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 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 | 34 |
| 35 namespace OT { | 35 namespace OT { |
| 36 | 36 |
| 37 | 37 |
| 38 struct SingleSubstFormat1 | 38 struct SingleSubstFormat1 |
| 39 { | 39 { |
| 40 inline void closure (hb_closure_context_t *c) const | 40 inline void closure (hb_closure_context_t *c) const |
| 41 { | 41 { |
| 42 TRACE_CLOSURE (this); | 42 TRACE_CLOSURE (this); |
| 43 Coverage::Iter iter; | 43 Coverage::Iter iter; |
| 44 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 44 for (iter.init (this+coverage); iter.more (); iter.next ()) |
| 45 { |
| 46 /* TODO Switch to range-based API to work around malicious fonts. |
| 47 * https://github.com/behdad/harfbuzz/issues/363 */ |
| 45 hb_codepoint_t glyph_id = iter.get_glyph (); | 48 hb_codepoint_t glyph_id = iter.get_glyph (); |
| 46 if (c->glyphs->has (glyph_id)) | 49 if (c->glyphs->has (glyph_id)) |
| 47 c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu); | 50 c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu); |
| 48 } | 51 } |
| 49 } | 52 } |
| 50 | 53 |
| 51 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const | 54 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const |
| 52 { | 55 { |
| 53 TRACE_COLLECT_GLYPHS (this); | 56 TRACE_COLLECT_GLYPHS (this); |
| 54 Coverage::Iter iter; | 57 Coverage::Iter iter; |
| 55 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 58 for (iter.init (this+coverage); iter.more (); iter.next ()) |
| 59 { |
| 60 /* TODO Switch to range-based API to work around malicious fonts. |
| 61 * https://github.com/behdad/harfbuzz/issues/363 */ |
| 56 hb_codepoint_t glyph_id = iter.get_glyph (); | 62 hb_codepoint_t glyph_id = iter.get_glyph (); |
| 57 c->input->add (glyph_id); | 63 c->input->add (glyph_id); |
| 58 c->output->add ((glyph_id + deltaGlyphID) & 0xFFFFu); | 64 c->output->add ((glyph_id + deltaGlyphID) & 0xFFFFu); |
| 59 } | 65 } |
| 60 } | 66 } |
| 61 | 67 |
| 62 inline const Coverage &get_coverage (void) const | 68 inline const Coverage &get_coverage (void) const |
| 63 { | 69 { |
| 64 return this+coverage; | 70 return this+coverage; |
| 65 } | 71 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 public: | 119 public: |
| 114 DEFINE_SIZE_STATIC (6); | 120 DEFINE_SIZE_STATIC (6); |
| 115 }; | 121 }; |
| 116 | 122 |
| 117 struct SingleSubstFormat2 | 123 struct SingleSubstFormat2 |
| 118 { | 124 { |
| 119 inline void closure (hb_closure_context_t *c) const | 125 inline void closure (hb_closure_context_t *c) const |
| 120 { | 126 { |
| 121 TRACE_CLOSURE (this); | 127 TRACE_CLOSURE (this); |
| 122 Coverage::Iter iter; | 128 Coverage::Iter iter; |
| 123 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 129 unsigned int count = substitute.len; |
| 130 for (iter.init (this+coverage); iter.more (); iter.next ()) |
| 131 { |
| 132 if (unlikely (iter.get_coverage () >= count)) |
| 133 break; /* Work around malicious fonts. https://github.com/behdad/harfbuz
z/issues/363 */ |
| 124 if (c->glyphs->has (iter.get_glyph ())) | 134 if (c->glyphs->has (iter.get_glyph ())) |
| 125 c->glyphs->add (substitute[iter.get_coverage ()]); | 135 c->glyphs->add (substitute[iter.get_coverage ()]); |
| 126 } | 136 } |
| 127 } | 137 } |
| 128 | 138 |
| 129 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const | 139 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const |
| 130 { | 140 { |
| 131 TRACE_COLLECT_GLYPHS (this); | 141 TRACE_COLLECT_GLYPHS (this); |
| 132 Coverage::Iter iter; | 142 Coverage::Iter iter; |
| 133 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 143 unsigned int count = substitute.len; |
| 144 for (iter.init (this+coverage); iter.more (); iter.next ()) |
| 145 { |
| 146 if (unlikely (iter.get_coverage () >= count)) |
| 147 break; /* Work around malicious fonts. https://github.com/behdad/harfbuz
z/issues/363 */ |
| 134 c->input->add (iter.get_glyph ()); | 148 c->input->add (iter.get_glyph ()); |
| 135 c->output->add (substitute[iter.get_coverage ()]); | 149 c->output->add (substitute[iter.get_coverage ()]); |
| 136 } | 150 } |
| 137 } | 151 } |
| 138 | 152 |
| 139 inline const Coverage &get_coverage (void) const | 153 inline const Coverage &get_coverage (void) const |
| 140 { | 154 { |
| 141 return this+coverage; | 155 return this+coverage; |
| 142 } | 156 } |
| 143 | 157 |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 public: | 328 public: |
| 315 DEFINE_SIZE_ARRAY (2, substitute); | 329 DEFINE_SIZE_ARRAY (2, substitute); |
| 316 }; | 330 }; |
| 317 | 331 |
| 318 struct MultipleSubstFormat1 | 332 struct MultipleSubstFormat1 |
| 319 { | 333 { |
| 320 inline void closure (hb_closure_context_t *c) const | 334 inline void closure (hb_closure_context_t *c) const |
| 321 { | 335 { |
| 322 TRACE_CLOSURE (this); | 336 TRACE_CLOSURE (this); |
| 323 Coverage::Iter iter; | 337 Coverage::Iter iter; |
| 324 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 338 unsigned int count = sequence.len; |
| 339 for (iter.init (this+coverage); iter.more (); iter.next ()) |
| 340 { |
| 341 if (unlikely (iter.get_coverage () >= count)) |
| 342 break; /* Work around malicious fonts. https://github.com/behdad/harfbuz
z/issues/363 */ |
| 325 if (c->glyphs->has (iter.get_glyph ())) | 343 if (c->glyphs->has (iter.get_glyph ())) |
| 326 (this+sequence[iter.get_coverage ()]).closure (c); | 344 (this+sequence[iter.get_coverage ()]).closure (c); |
| 327 } | 345 } |
| 328 } | 346 } |
| 329 | 347 |
| 330 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const | 348 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const |
| 331 { | 349 { |
| 332 TRACE_COLLECT_GLYPHS (this); | 350 TRACE_COLLECT_GLYPHS (this); |
| 333 (this+coverage).add_coverage (c->input); | 351 (this+coverage).add_coverage (c->input); |
| 334 unsigned int count = sequence.len; | 352 unsigned int count = sequence.len; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 | 450 |
| 433 typedef ArrayOf<GlyphID> AlternateSet; /* Array of alternate GlyphIDs--in | 451 typedef ArrayOf<GlyphID> AlternateSet; /* Array of alternate GlyphIDs--in |
| 434 * arbitrary order */ | 452 * arbitrary order */ |
| 435 | 453 |
| 436 struct AlternateSubstFormat1 | 454 struct AlternateSubstFormat1 |
| 437 { | 455 { |
| 438 inline void closure (hb_closure_context_t *c) const | 456 inline void closure (hb_closure_context_t *c) const |
| 439 { | 457 { |
| 440 TRACE_CLOSURE (this); | 458 TRACE_CLOSURE (this); |
| 441 Coverage::Iter iter; | 459 Coverage::Iter iter; |
| 442 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 460 unsigned int count = alternateSet.len; |
| 461 for (iter.init (this+coverage); iter.more (); iter.next ()) |
| 462 { |
| 463 if (unlikely (iter.get_coverage () >= count)) |
| 464 break; /* Work around malicious fonts. https://github.com/behdad/harfbuz
z/issues/363 */ |
| 443 if (c->glyphs->has (iter.get_glyph ())) { | 465 if (c->glyphs->has (iter.get_glyph ())) { |
| 444 const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; | 466 const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; |
| 445 unsigned int count = alt_set.len; | 467 unsigned int count = alt_set.len; |
| 446 for (unsigned int i = 0; i < count; i++) | 468 for (unsigned int i = 0; i < count; i++) |
| 447 c->glyphs->add (alt_set[i]); | 469 c->glyphs->add (alt_set[i]); |
| 448 } | 470 } |
| 449 } | 471 } |
| 450 } | 472 } |
| 451 | 473 |
| 452 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const | 474 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const |
| 453 { | 475 { |
| 454 TRACE_COLLECT_GLYPHS (this); | 476 TRACE_COLLECT_GLYPHS (this); |
| 455 Coverage::Iter iter; | 477 Coverage::Iter iter; |
| 456 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 478 unsigned int count = alternateSet.len; |
| 479 for (iter.init (this+coverage); iter.more (); iter.next ()) |
| 480 { |
| 481 if (unlikely (iter.get_coverage () >= count)) |
| 482 break; /* Work around malicious fonts. https://github.com/behdad/harfbuz
z/issues/363 */ |
| 457 c->input->add (iter.get_glyph ()); | 483 c->input->add (iter.get_glyph ()); |
| 458 const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; | 484 const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()]; |
| 459 unsigned int count = alt_set.len; | 485 unsigned int count = alt_set.len; |
| 460 for (unsigned int i = 0; i < count; i++) | 486 for (unsigned int i = 0; i < count; i++) |
| 461 c->output->add (alt_set[i]); | 487 c->output->add (alt_set[i]); |
| 462 } | 488 } |
| 463 } | 489 } |
| 464 | 490 |
| 465 inline const Coverage &get_coverage (void) const | 491 inline const Coverage &get_coverage (void) const |
| 466 { | 492 { |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 public: | 781 public: |
| 756 DEFINE_SIZE_ARRAY (2, ligature); | 782 DEFINE_SIZE_ARRAY (2, ligature); |
| 757 }; | 783 }; |
| 758 | 784 |
| 759 struct LigatureSubstFormat1 | 785 struct LigatureSubstFormat1 |
| 760 { | 786 { |
| 761 inline void closure (hb_closure_context_t *c) const | 787 inline void closure (hb_closure_context_t *c) const |
| 762 { | 788 { |
| 763 TRACE_CLOSURE (this); | 789 TRACE_CLOSURE (this); |
| 764 Coverage::Iter iter; | 790 Coverage::Iter iter; |
| 765 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 791 unsigned int count = ligatureSet.len; |
| 792 for (iter.init (this+coverage); iter.more (); iter.next ()) |
| 793 { |
| 794 if (unlikely (iter.get_coverage () >= count)) |
| 795 break; /* Work around malicious fonts. https://github.com/behdad/harfbuz
z/issues/363 */ |
| 766 if (c->glyphs->has (iter.get_glyph ())) | 796 if (c->glyphs->has (iter.get_glyph ())) |
| 767 (this+ligatureSet[iter.get_coverage ()]).closure (c); | 797 (this+ligatureSet[iter.get_coverage ()]).closure (c); |
| 768 } | 798 } |
| 769 } | 799 } |
| 770 | 800 |
| 771 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const | 801 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const |
| 772 { | 802 { |
| 773 TRACE_COLLECT_GLYPHS (this); | 803 TRACE_COLLECT_GLYPHS (this); |
| 774 Coverage::Iter iter; | 804 Coverage::Iter iter; |
| 775 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 805 unsigned int count = ligatureSet.len; |
| 806 for (iter.init (this+coverage); iter.more (); iter.next ()) |
| 807 { |
| 808 if (unlikely (iter.get_coverage () >= count)) |
| 809 break; /* Work around malicious fonts. https://github.com/behdad/harfbuz
z/issues/363 */ |
| 776 c->input->add (iter.get_glyph ()); | 810 c->input->add (iter.get_glyph ()); |
| 777 (this+ligatureSet[iter.get_coverage ()]).collect_glyphs (c); | 811 (this+ligatureSet[iter.get_coverage ()]).collect_glyphs (c); |
| 778 } | 812 } |
| 779 } | 813 } |
| 780 | 814 |
| 781 inline const Coverage &get_coverage (void) const | 815 inline const Coverage &get_coverage (void) const |
| 782 { | 816 { |
| 783 return this+coverage; | 817 return this+coverage; |
| 784 } | 818 } |
| 785 | 819 |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 if (!(this+backtrack[i]).intersects (c->glyphs)) | 950 if (!(this+backtrack[i]).intersects (c->glyphs)) |
| 917 return; | 951 return; |
| 918 | 952 |
| 919 count = lookahead.len; | 953 count = lookahead.len; |
| 920 for (unsigned int i = 0; i < count; i++) | 954 for (unsigned int i = 0; i < count; i++) |
| 921 if (!(this+lookahead[i]).intersects (c->glyphs)) | 955 if (!(this+lookahead[i]).intersects (c->glyphs)) |
| 922 return; | 956 return; |
| 923 | 957 |
| 924 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahe
ad); | 958 const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahe
ad); |
| 925 Coverage::Iter iter; | 959 Coverage::Iter iter; |
| 926 for (iter.init (this+coverage); iter.more (); iter.next ()) { | 960 count = substitute.len; |
| 961 for (iter.init (this+coverage); iter.more (); iter.next ()) |
| 962 { |
| 963 if (unlikely (iter.get_coverage () >= count)) |
| 964 break; /* Work around malicious fonts. https://github.com/behdad/harfbuz
z/issues/363 */ |
| 927 if (c->glyphs->has (iter.get_glyph ())) | 965 if (c->glyphs->has (iter.get_glyph ())) |
| 928 c->glyphs->add (substitute[iter.get_coverage ()]); | 966 c->glyphs->add (substitute[iter.get_coverage ()]); |
| 929 } | 967 } |
| 930 } | 968 } |
| 931 | 969 |
| 932 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const | 970 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const |
| 933 { | 971 { |
| 934 TRACE_COLLECT_GLYPHS (this); | 972 TRACE_COLLECT_GLYPHS (this); |
| 935 | 973 |
| 936 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverag
e> > (backtrack); | 974 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverag
e> > (backtrack); |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1266 | 1304 |
| 1267 static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer); | 1305 static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer); |
| 1268 | 1306 |
| 1269 inline bool sanitize (hb_sanitize_context_t *c) const | 1307 inline bool sanitize (hb_sanitize_context_t *c) const |
| 1270 { | 1308 { |
| 1271 TRACE_SANITIZE (this); | 1309 TRACE_SANITIZE (this); |
| 1272 if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false); | 1310 if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false); |
| 1273 const OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (l
ookupList); | 1311 const OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (l
ookupList); |
| 1274 return_trace (list.sanitize (c, this)); | 1312 return_trace (list.sanitize (c, this)); |
| 1275 } | 1313 } |
| 1276 public: | |
| 1277 DEFINE_SIZE_STATIC (10); | |
| 1278 }; | 1314 }; |
| 1279 | 1315 |
| 1280 | 1316 |
| 1281 void | 1317 void |
| 1282 GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer) | 1318 GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer) |
| 1283 { | 1319 { |
| 1284 _hb_buffer_assert_gsubgpos_vars (buffer); | 1320 _hb_buffer_assert_gsubgpos_vars (buffer); |
| 1285 | 1321 |
| 1286 const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef; | 1322 const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef; |
| 1287 unsigned int count = buffer->len; | 1323 unsigned int count = buffer->len; |
| 1288 hb_glyph_info_t *info = buffer->info; | |
| 1289 for (unsigned int i = 0; i < count; i++) | 1324 for (unsigned int i = 0; i < count; i++) |
| 1290 { | 1325 { |
| 1291 unsigned int props = gdef.get_glyph_props (info[i].codepoint); | 1326 _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buff
er->info[i].codepoint)); |
| 1292 if (!props) | 1327 _hb_glyph_info_clear_lig_props (&buffer->info[i]); |
| 1293 { | |
| 1294 /* Never mark default-ignorables as marks. | |
| 1295 * They won't get in the way of lookups anyway, | |
| 1296 * but having them as mark will cause them to be skipped | |
| 1297 * over if the lookup-flag says so, but at least for the | |
| 1298 * Mongolian variation selectors, looks like Uniscribe | |
| 1299 * marks them as non-mark. Some Mongolian fonts without | |
| 1300 * GDEF rely on this. Another notable character that | |
| 1301 * this applies to is COMBINING GRAPHEME JOINER. */ | |
| 1302 props = (_hb_glyph_info_get_general_category (&info[i]) != | |
| 1303 » HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK || | |
| 1304 » _hb_glyph_info_is_default_ignorable (&info[i])) ? | |
| 1305 » HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : | |
| 1306 » HB_OT_LAYOUT_GLYPH_PROPS_MARK; | |
| 1307 } | |
| 1308 _hb_glyph_info_set_glyph_props (&info[i], props); | |
| 1309 _hb_glyph_info_clear_lig_props (&info[i]); | |
| 1310 buffer->info[i].syllable() = 0; | 1328 buffer->info[i].syllable() = 0; |
| 1311 } | 1329 } |
| 1312 } | 1330 } |
| 1313 | 1331 |
| 1314 | 1332 |
| 1315 /* Out-of-class implementation for methods recursing */ | 1333 /* Out-of-class implementation for methods recursing */ |
| 1316 | 1334 |
| 1317 /*static*/ inline bool ExtensionSubst::is_reverse (void) const | 1335 /*static*/ inline bool ExtensionSubst::is_reverse (void) const |
| 1318 { | 1336 { |
| 1319 unsigned int type = get_type (); | 1337 unsigned int type = get_type (); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1342 c->set_lookup_index (saved_lookup_index); | 1360 c->set_lookup_index (saved_lookup_index); |
| 1343 c->set_lookup_props (saved_lookup_props); | 1361 c->set_lookup_props (saved_lookup_props); |
| 1344 return ret; | 1362 return ret; |
| 1345 } | 1363 } |
| 1346 | 1364 |
| 1347 | 1365 |
| 1348 } /* namespace OT */ | 1366 } /* namespace OT */ |
| 1349 | 1367 |
| 1350 | 1368 |
| 1351 #endif /* HB_OT_LAYOUT_GSUB_TABLE_HH */ | 1369 #endif /* HB_OT_LAYOUT_GSUB_TABLE_HH */ |
| OLD | NEW |