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 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 |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 enum may_skip_t { | 342 enum may_skip_t { |
343 SKIP_NO, | 343 SKIP_NO, |
344 SKIP_YES, | 344 SKIP_YES, |
345 SKIP_MAYBE | 345 SKIP_MAYBE |
346 }; | 346 }; |
347 | 347 |
348 inline may_skip_t | 348 inline may_skip_t |
349 may_skip (const hb_apply_context_t *c, | 349 may_skip (const hb_apply_context_t *c, |
350 const hb_glyph_info_t &info) const | 350 const hb_glyph_info_t &info) const |
351 { | 351 { |
352 unsigned int property; | 352 if (!c->check_glyph_property (&info, lookup_props)) |
353 | |
354 property = _hb_glyph_info_get_glyph_props (&info); | |
355 | |
356 if (!c->match_properties (info.codepoint, property, lookup_props)) | |
357 return SKIP_YES; | 353 return SKIP_YES; |
358 | 354 |
359 if (unlikely (_hb_glyph_info_is_default_ignorable (&info) && | 355 if (unlikely (_hb_glyph_info_is_default_ignorable (&info) && |
360 (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) && | 356 (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) && |
361 (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) && | 357 (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) && |
362 !_hb_glyph_info_ligated (&info))) | 358 !_hb_glyph_info_ligated (&info))) |
363 return SKIP_MAYBE; | 359 return SKIP_MAYBE; |
364 | 360 |
365 return SKIP_NO; | 361 return SKIP_NO; |
366 } | 362 } |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 inline void reject (void) { num_items++; } | 476 inline void reject (void) { num_items++; } |
481 inline bool prev (void) | 477 inline bool prev (void) |
482 { | 478 { |
483 assert (num_items > 0); | 479 assert (num_items > 0); |
484 while (!has_no_chance ()) | 480 while (!has_no_chance ()) |
485 { | 481 { |
486 idx--; | 482 idx--; |
487 const hb_glyph_info_t &info = c->buffer->out_info[idx]; | 483 const hb_glyph_info_t &info = c->buffer->out_info[idx]; |
488 | 484 |
489 matcher_t::may_skip_t skip = matcher.may_skip (c, info); | 485 matcher_t::may_skip_t skip = matcher.may_skip (c, info); |
490 | |
491 if (unlikely (skip == matcher_t::SKIP_YES)) | 486 if (unlikely (skip == matcher_t::SKIP_YES)) |
492 continue; | 487 continue; |
493 | 488 |
494 matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data
); | 489 matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data
); |
495 if (match == matcher_t::MATCH_YES || | 490 if (match == matcher_t::MATCH_YES || |
496 (match == matcher_t::MATCH_MAYBE && | 491 (match == matcher_t::MATCH_MAYBE && |
497 skip == matcher_t::SKIP_NO)) | 492 skip == matcher_t::SKIP_NO)) |
498 { | 493 { |
499 num_items--; | 494 num_items--; |
500 match_glyph_data++; | 495 match_glyph_data++; |
(...skipping 30 matching lines...) Expand all Loading... |
531 * "ignore marks of attachment type different than | 526 * "ignore marks of attachment type different than |
532 * the attachment type specified." | 527 * the attachment type specified." |
533 */ | 528 */ |
534 if (lookup_props & LookupFlag::MarkAttachmentType) | 529 if (lookup_props & LookupFlag::MarkAttachmentType) |
535 return (lookup_props & LookupFlag::MarkAttachmentType) == (glyph_props & L
ookupFlag::MarkAttachmentType); | 530 return (lookup_props & LookupFlag::MarkAttachmentType) == (glyph_props & L
ookupFlag::MarkAttachmentType); |
536 | 531 |
537 return true; | 532 return true; |
538 } | 533 } |
539 | 534 |
540 inline bool | 535 inline bool |
541 match_properties (hb_codepoint_t glyph, | 536 check_glyph_property (const hb_glyph_info_t *info, |
542 » » unsigned int glyph_props, | 537 » » » unsigned int lookup_props) const |
543 » » unsigned int lookup_props) const | |
544 { | 538 { |
| 539 hb_codepoint_t glyph = info->codepoint; |
| 540 unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info); |
| 541 |
545 /* Not covered, if, for example, glyph class is ligature and | 542 /* Not covered, if, for example, glyph class is ligature and |
546 * lookup_props includes LookupFlags::IgnoreLigatures | 543 * lookup_props includes LookupFlags::IgnoreLigatures |
547 */ | 544 */ |
548 if (glyph_props & lookup_props & LookupFlag::IgnoreFlags) | 545 if (glyph_props & lookup_props & LookupFlag::IgnoreFlags) |
549 return false; | 546 return false; |
550 | 547 |
551 if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) | 548 if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) |
552 return match_properties_mark (glyph, glyph_props, lookup_props); | 549 return match_properties_mark (glyph, glyph_props, lookup_props); |
553 | 550 |
554 return true; | 551 return true; |
555 } | 552 } |
556 | 553 |
557 inline bool | |
558 check_glyph_property (hb_glyph_info_t *info, | |
559 unsigned int lookup_props) const | |
560 { | |
561 unsigned int property; | |
562 | |
563 property = _hb_glyph_info_get_glyph_props (info); | |
564 | |
565 return match_properties (info->codepoint, property, lookup_props); | |
566 } | |
567 | |
568 inline void _set_glyph_props (hb_codepoint_t glyph_index, | 554 inline void _set_glyph_props (hb_codepoint_t glyph_index, |
569 unsigned int class_guess = 0, | 555 unsigned int class_guess = 0, |
570 » » » bool ligature = false) const | 556 » » » bool ligature = false, |
| 557 » » » bool component = false) const |
571 { | 558 { |
572 unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) & | 559 unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) & |
573 HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE; | 560 HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE; |
574 add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED; | 561 add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED; |
575 if (ligature) | 562 if (ligature) |
| 563 { |
576 add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED; | 564 add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED; |
| 565 /* In the only place that the MULTIPLIED bit is used, Uniscribe |
| 566 * seems to only care about the "last" transformation between |
| 567 * Ligature and Multiple substitions. Ie. if you ligate, expand, |
| 568 * and ligate again, it forgives the multiplication and acts as |
| 569 * if only ligation happened. As such, clear MULTIPLIED bit. |
| 570 */ |
| 571 add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED; |
| 572 } |
| 573 if (component) |
| 574 add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED; |
577 if (likely (has_glyph_classes)) | 575 if (likely (has_glyph_classes)) |
578 _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_pr
ops (glyph_index)); | 576 _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_pr
ops (glyph_index)); |
579 else if (class_guess) | 577 else if (class_guess) |
580 _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess); | 578 _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess); |
581 } | 579 } |
582 | 580 |
583 inline void replace_glyph (hb_codepoint_t glyph_index) const | 581 inline void replace_glyph (hb_codepoint_t glyph_index) const |
584 { | 582 { |
585 _set_glyph_props (glyph_index); | 583 _set_glyph_props (glyph_index); |
586 buffer->replace_glyph (glyph_index); | 584 buffer->replace_glyph (glyph_index); |
587 } | 585 } |
588 inline void replace_glyph_inplace (hb_codepoint_t glyph_index) const | 586 inline void replace_glyph_inplace (hb_codepoint_t glyph_index) const |
589 { | 587 { |
590 _set_glyph_props (glyph_index); | 588 _set_glyph_props (glyph_index); |
591 buffer->cur().codepoint = glyph_index; | 589 buffer->cur().codepoint = glyph_index; |
592 } | 590 } |
593 inline void replace_glyph_with_ligature (hb_codepoint_t glyph_index, | 591 inline void replace_glyph_with_ligature (hb_codepoint_t glyph_index, |
594 unsigned int class_guess) const | 592 unsigned int class_guess) const |
595 { | 593 { |
596 _set_glyph_props (glyph_index, class_guess, true); | 594 _set_glyph_props (glyph_index, class_guess, true); |
597 buffer->replace_glyph (glyph_index); | 595 buffer->replace_glyph (glyph_index); |
598 } | 596 } |
599 inline void output_glyph (hb_codepoint_t glyph_index, | 597 inline void output_glyph_for_component (hb_codepoint_t glyph_index, |
600 » » » unsigned int class_guess) const | 598 » » » » » unsigned int class_guess) const |
601 { | 599 { |
602 _set_glyph_props (glyph_index, class_guess); | 600 _set_glyph_props (glyph_index, class_guess, false, true); |
603 buffer->output_glyph (glyph_index); | 601 buffer->output_glyph (glyph_index); |
604 } | 602 } |
605 }; | 603 }; |
606 | 604 |
607 | 605 |
608 | 606 |
609 typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const
void *data); | 607 typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const
void *data); |
610 typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const USHORT &value, co
nst void *data); | 608 typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const USHORT &value, co
nst void *data); |
611 typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, cons
t void *data); | 609 typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, cons
t void *data); |
612 | 610 |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
875 /* Re-adjust components for any marks following. */ | 873 /* Re-adjust components for any marks following. */ |
876 for (unsigned int i = buffer->idx; i < buffer->len; i++) { | 874 for (unsigned int i = buffer->idx; i < buffer->len; i++) { |
877 if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) { | 875 if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) { |
878 unsigned int new_lig_comp = components_so_far - last_num_components + | 876 unsigned int new_lig_comp = components_so_far - last_num_components + |
879 MIN (MAX (_hb_glyph_info_get_lig_comp (&buff
er->info[i]), 1u), last_num_components); | 877 MIN (MAX (_hb_glyph_info_get_lig_comp (&buff
er->info[i]), 1u), last_num_components); |
880 _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig
_comp); | 878 _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig
_comp); |
881 } else | 879 } else |
882 break; | 880 break; |
883 } | 881 } |
884 } | 882 } |
| 883 TRACE_RETURN (true); |
885 } | 884 } |
886 | 885 |
887 static inline bool match_backtrack (hb_apply_context_t *c, | 886 static inline bool match_backtrack (hb_apply_context_t *c, |
888 unsigned int count, | 887 unsigned int count, |
889 const USHORT backtrack[], | 888 const USHORT backtrack[], |
890 match_func_t match_func, | 889 match_func_t match_func, |
891 const void *match_data) | 890 const void *match_data) |
892 { | 891 { |
893 TRACE_APPLY (NULL); | 892 TRACE_APPLY (NULL); |
894 | 893 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 continue; | 986 continue; |
988 | 987 |
989 unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len (); | 988 unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len (); |
990 int delta = new_len - orig_len; | 989 int delta = new_len - orig_len; |
991 | 990 |
992 if (!delta) | 991 if (!delta) |
993 continue; | 992 continue; |
994 | 993 |
995 /* Recursed lookup changed buffer len. Adjust. */ | 994 /* Recursed lookup changed buffer len. Adjust. */ |
996 | 995 |
997 /* end can't go back past the current match position. */ | 996 /* end can't go back past the current match position. |
| 997 * Note: this is only true because we do NOT allow MultipleSubst |
| 998 * with zero sequence len. */ |
998 end = MAX ((int) match_positions[idx] + 1, int (end) + delta); | 999 end = MAX ((int) match_positions[idx] + 1, int (end) + delta); |
999 | 1000 |
1000 unsigned int next = idx + 1; /* next now is the position after the recursed
lookup. */ | 1001 unsigned int next = idx + 1; /* next now is the position after the recursed
lookup. */ |
1001 | 1002 |
1002 if (delta > 0) | 1003 if (delta > 0) |
1003 { | 1004 { |
1004 if (unlikely (delta + count > MAX_CONTEXT_LENGTH)) | 1005 if (unlikely (delta + count > MAX_CONTEXT_LENGTH)) |
1005 break; | 1006 break; |
1006 } | 1007 } |
1007 else | 1008 else |
(...skipping 1238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2246 unsigned int *script_count /* IN/OUT */, | 2247 unsigned int *script_count /* IN/OUT */, |
2247 hb_tag_t *script_tags /* OUT */) cons
t | 2248 hb_tag_t *script_tags /* OUT */) cons
t |
2248 { return (this+scriptList).get_tags (start_offset, script_count, script_tags);
} | 2249 { return (this+scriptList).get_tags (start_offset, script_count, script_tags);
} |
2249 inline const Script& get_script (unsigned int i) const | 2250 inline const Script& get_script (unsigned int i) const |
2250 { return (this+scriptList)[i]; } | 2251 { return (this+scriptList)[i]; } |
2251 inline bool find_script_index (hb_tag_t tag, unsigned int *index) const | 2252 inline bool find_script_index (hb_tag_t tag, unsigned int *index) const |
2252 { return (this+scriptList).find_index (tag, index); } | 2253 { return (this+scriptList).find_index (tag, index); } |
2253 | 2254 |
2254 inline unsigned int get_feature_count (void) const | 2255 inline unsigned int get_feature_count (void) const |
2255 { return (this+featureList).len; } | 2256 { return (this+featureList).len; } |
2256 inline const Tag& get_feature_tag (unsigned int i) const | 2257 inline hb_tag_t get_feature_tag (unsigned int i) const |
2257 { return (this+featureList).get_tag (i); } | 2258 { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_ta
g (i); } |
2258 inline unsigned int get_feature_tags (unsigned int start_offset, | 2259 inline unsigned int get_feature_tags (unsigned int start_offset, |
2259 unsigned int *feature_count /* IN/OUT */
, | 2260 unsigned int *feature_count /* IN/OUT */
, |
2260 hb_tag_t *feature_tags /* OUT */) co
nst | 2261 hb_tag_t *feature_tags /* OUT */) co
nst |
2261 { return (this+featureList).get_tags (start_offset, feature_count, feature_tag
s); } | 2262 { return (this+featureList).get_tags (start_offset, feature_count, feature_tag
s); } |
2262 inline const Feature& get_feature (unsigned int i) const | 2263 inline const Feature& get_feature (unsigned int i) const |
2263 { return (this+featureList)[i]; } | 2264 { return (this+featureList)[i]; } |
2264 inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const | 2265 inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const |
2265 { return (this+featureList).find_index (tag, index); } | 2266 { return (this+featureList).find_index (tag, index); } |
2266 | 2267 |
2267 inline unsigned int get_lookup_count (void) const | 2268 inline unsigned int get_lookup_count (void) const |
2268 { return (this+lookupList).len; } | 2269 { return (this+lookupList).len; } |
2269 inline const Lookup& get_lookup (unsigned int i) const | 2270 inline const Lookup& get_lookup (unsigned int i) const |
2270 { return (this+lookupList)[i]; } | 2271 { return (this+lookupList)[i]; } |
2271 | 2272 |
2272 inline bool sanitize (hb_sanitize_context_t *c) { | 2273 inline bool sanitize (hb_sanitize_context_t *c) { |
2273 TRACE_SANITIZE (this); | 2274 TRACE_SANITIZE (this); |
2274 return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) && | 2275 return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) && |
2275 scriptList.sanitize (c, this) && | 2276 scriptList.sanitize (c, this) && |
2276 featureList.sanitize (c, this) && | 2277 featureList.sanitize (c, this) && |
2277 lookupList.sanitize (c, this)); | 2278 lookupList.sanitize (c, this)); |
2278 } | 2279 } |
2279 | 2280 |
2280 protected: | 2281 protected: |
2281 FixedVersion version; /* Version of the GSUB/GPOS table--initially set | 2282 FixedVersion version; /* Version of the GSUB/GPOS table--initially set |
2282 » » » » * to 0x00010000 */ | 2283 » » » » * to 0x00010000u */ |
2283 OffsetTo<ScriptList> | 2284 OffsetTo<ScriptList> |
2284 scriptList; /* ScriptList table */ | 2285 scriptList; /* ScriptList table */ |
2285 OffsetTo<FeatureList> | 2286 OffsetTo<FeatureList> |
2286 featureList; /* FeatureList table */ | 2287 featureList; /* FeatureList table */ |
2287 OffsetTo<LookupList> | 2288 OffsetTo<LookupList> |
2288 lookupList; /* LookupList table */ | 2289 lookupList; /* LookupList table */ |
2289 public: | 2290 public: |
2290 DEFINE_SIZE_STATIC (10); | 2291 DEFINE_SIZE_STATIC (10); |
2291 }; | 2292 }; |
2292 | 2293 |
2293 | 2294 |
2294 } /* namespace OT */ | 2295 } /* namespace OT */ |
2295 | 2296 |
2296 | 2297 |
2297 #endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */ | 2298 #endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */ |
OLD | NEW |