OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 1998-2004 David Turner and Werner Lemberg | 2 * Copyright © 1998-2004 David Turner and Werner Lemberg |
3 * Copyright © 2006 Behdad Esfahbod | 3 * Copyright © 2006 Behdad Esfahbod |
4 * Copyright © 2007,2008,2009 Red Hat, Inc. | 4 * Copyright © 2007,2008,2009 Red Hat, Inc. |
5 * Copyright © 2012 Google, Inc. | 5 * Copyright © 2012,2013 Google, Inc. |
6 * | 6 * |
7 * This is part of HarfBuzz, a text shaping library. | 7 * This is part of HarfBuzz, a text shaping library. |
8 * | 8 * |
9 * Permission is hereby granted, without written agreement and without | 9 * Permission is hereby granted, without written agreement and without |
10 * license or royalty fees, to use, copy, modify, and distribute this | 10 * license or royalty fees, to use, copy, modify, and distribute this |
11 * software and its documentation for any purpose, provided that the | 11 * software and its documentation for any purpose, provided that the |
12 * above copyright notice and the following two paragraphs appear in | 12 * above copyright notice and the following two paragraphs appear in |
13 * all copies of this software. | 13 * all copies of this software. |
14 * | 14 * |
15 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | 15 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
(...skipping 10 matching lines...) Expand all Loading... |
26 * | 26 * |
27 * Red Hat Author(s): Behdad Esfahbod | 27 * Red Hat Author(s): Behdad Esfahbod |
28 * Google Author(s): Behdad Esfahbod | 28 * Google Author(s): Behdad Esfahbod |
29 */ | 29 */ |
30 | 30 |
31 #include "hb-ot-layout-private.hh" | 31 #include "hb-ot-layout-private.hh" |
32 | 32 |
33 #include "hb-ot-layout-gdef-table.hh" | 33 #include "hb-ot-layout-gdef-table.hh" |
34 #include "hb-ot-layout-gsub-table.hh" | 34 #include "hb-ot-layout-gsub-table.hh" |
35 #include "hb-ot-layout-gpos-table.hh" | 35 #include "hb-ot-layout-gpos-table.hh" |
| 36 #include "hb-ot-layout-jstf-table.hh" |
| 37 |
| 38 #include "hb-ot-map-private.hh" |
36 | 39 |
37 #include <stdlib.h> | 40 #include <stdlib.h> |
38 #include <string.h> | 41 #include <string.h> |
39 | 42 |
40 | 43 |
41 HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) | 44 HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) |
42 | 45 |
43 hb_ot_layout_t * | 46 hb_ot_layout_t * |
44 _hb_ot_layout_create (hb_face_t *face) | 47 _hb_ot_layout_create (hb_face_t *face) |
45 { | 48 { |
46 hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t)
); | 49 hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t)
); |
47 if (unlikely (!layout)) | 50 if (unlikely (!layout)) |
48 return NULL; | 51 return NULL; |
49 | 52 |
50 layout->gdef_blob = OT::Sanitizer<OT::GDEF>::sanitize (face->reference_table (
HB_OT_TAG_GDEF)); | 53 layout->gdef_blob = OT::Sanitizer<OT::GDEF>::sanitize (face->reference_table (
HB_OT_TAG_GDEF)); |
51 layout->gdef = OT::Sanitizer<OT::GDEF>::lock_instance (layout->gdef_blob); | 54 layout->gdef = OT::Sanitizer<OT::GDEF>::lock_instance (layout->gdef_blob); |
52 | 55 |
53 layout->gsub_blob = OT::Sanitizer<OT::GSUB>::sanitize (face->reference_table (
HB_OT_TAG_GSUB)); | 56 layout->gsub_blob = OT::Sanitizer<OT::GSUB>::sanitize (face->reference_table (
HB_OT_TAG_GSUB)); |
54 layout->gsub = OT::Sanitizer<OT::GSUB>::lock_instance (layout->gsub_blob); | 57 layout->gsub = OT::Sanitizer<OT::GSUB>::lock_instance (layout->gsub_blob); |
55 | 58 |
56 layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (
HB_OT_TAG_GPOS)); | 59 layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (
HB_OT_TAG_GPOS)); |
57 layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob); | 60 layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob); |
58 | 61 |
59 layout->gsub_lookup_count = layout->gsub->get_lookup_count (); | 62 layout->gsub_lookup_count = layout->gsub->get_lookup_count (); |
60 layout->gpos_lookup_count = layout->gpos->get_lookup_count (); | 63 layout->gpos_lookup_count = layout->gpos->get_lookup_count (); |
61 | 64 |
62 layout->gsub_digests = (hb_set_digest_t *) calloc (layout->gsub->get_lookup_co
unt (), sizeof (hb_set_digest_t)); | 65 layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gs
ub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t)); |
63 layout->gpos_digests = (hb_set_digest_t *) calloc (layout->gpos->get_lookup_co
unt (), sizeof (hb_set_digest_t)); | 66 layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gp
os->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t)); |
64 | 67 |
65 if (unlikely ((layout->gsub_lookup_count && !layout->gsub_digests) || | 68 if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) || |
66 » » (layout->gpos_lookup_count && !layout->gpos_digests))) | 69 » » (layout->gpos_lookup_count && !layout->gpos_accels))) |
67 { | 70 { |
68 _hb_ot_layout_destroy (layout); | 71 _hb_ot_layout_destroy (layout); |
69 return NULL; | 72 return NULL; |
70 } | 73 } |
71 | 74 |
72 for (unsigned int i = 0; i < layout->gsub_lookup_count; i++) | 75 for (unsigned int i = 0; i < layout->gsub_lookup_count; i++) |
73 { | 76 layout->gsub_accels[i].init (layout->gsub->get_lookup (i)); |
74 layout->gsub_digests[i].init (); | |
75 layout->gsub->get_lookup (i).add_coverage (&layout->gsub_digests[i]); | |
76 } | |
77 for (unsigned int i = 0; i < layout->gpos_lookup_count; i++) | 77 for (unsigned int i = 0; i < layout->gpos_lookup_count; i++) |
78 { | 78 layout->gpos_accels[i].init (layout->gpos->get_lookup (i)); |
79 layout->gpos_digests[i].init (); | |
80 layout->gpos->get_lookup (i).add_coverage (&layout->gpos_digests[i]); | |
81 } | |
82 | 79 |
83 return layout; | 80 return layout; |
84 } | 81 } |
85 | 82 |
86 void | 83 void |
87 _hb_ot_layout_destroy (hb_ot_layout_t *layout) | 84 _hb_ot_layout_destroy (hb_ot_layout_t *layout) |
88 { | 85 { |
| 86 for (unsigned int i = 0; i < layout->gsub_lookup_count; i++) |
| 87 layout->gsub_accels[i].fini (layout->gsub->get_lookup (i)); |
| 88 for (unsigned int i = 0; i < layout->gpos_lookup_count; i++) |
| 89 layout->gpos_accels[i].fini (layout->gpos->get_lookup (i)); |
| 90 |
| 91 free (layout->gsub_accels); |
| 92 free (layout->gpos_accels); |
| 93 |
89 hb_blob_destroy (layout->gdef_blob); | 94 hb_blob_destroy (layout->gdef_blob); |
90 hb_blob_destroy (layout->gsub_blob); | 95 hb_blob_destroy (layout->gsub_blob); |
91 hb_blob_destroy (layout->gpos_blob); | 96 hb_blob_destroy (layout->gpos_blob); |
92 | 97 |
93 free (layout->gsub_digests); | |
94 free (layout->gpos_digests); | |
95 | |
96 free (layout); | 98 free (layout); |
97 } | 99 } |
98 | 100 |
99 static inline const OT::GDEF& | 101 static inline const OT::GDEF& |
100 _get_gdef (hb_face_t *face) | 102 _get_gdef (hb_face_t *face) |
101 { | 103 { |
102 if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GDEF
); | 104 if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GDEF
); |
103 return *hb_ot_layout_from_face (face)->gdef; | 105 return *hb_ot_layout_from_face (face)->gdef; |
104 } | 106 } |
105 static inline const OT::GSUB& | 107 static inline const OT::GSUB& |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 unsigned int start_offset, | 407 unsigned int start_offset, |
406 unsigned int *lookup_count /* IN/OUT */, | 408 unsigned int *lookup_count /* IN/OUT */, |
407 unsigned int *lookup_indexes /* OUT */) | 409 unsigned int *lookup_indexes /* OUT */) |
408 { | 410 { |
409 const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); | 411 const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
410 const OT::Feature &f = g.get_feature (feature_index); | 412 const OT::Feature &f = g.get_feature (feature_index); |
411 | 413 |
412 return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); | 414 return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); |
413 } | 415 } |
414 | 416 |
| 417 unsigned int |
| 418 hb_ot_layout_table_get_lookup_count (hb_face_t *face, |
| 419 hb_tag_t table_tag) |
| 420 { |
| 421 switch (table_tag) |
| 422 { |
| 423 case HB_OT_TAG_GSUB: |
| 424 { |
| 425 return hb_ot_layout_from_face (face)->gsub_lookup_count; |
| 426 } |
| 427 case HB_OT_TAG_GPOS: |
| 428 { |
| 429 return hb_ot_layout_from_face (face)->gpos_lookup_count; |
| 430 } |
| 431 } |
| 432 return 0; |
| 433 } |
| 434 |
415 static void | 435 static void |
416 _hb_ot_layout_collect_lookups_lookups (hb_face_t *face, | 436 _hb_ot_layout_collect_lookups_lookups (hb_face_t *face, |
417 hb_tag_t table_tag, | 437 hb_tag_t table_tag, |
418 unsigned int feature_index, | 438 unsigned int feature_index, |
419 hb_set_t *lookup_indexes /* OUT */) | 439 hb_set_t *lookup_indexes /* OUT */) |
420 { | 440 { |
421 unsigned int lookup_indices[32]; | 441 unsigned int lookup_indices[32]; |
422 unsigned int offset, len; | 442 unsigned int offset, len; |
423 | 443 |
424 offset = 0; | 444 offset = 0; |
(...skipping 13 matching lines...) Expand all Loading... |
438 } | 458 } |
439 | 459 |
440 static void | 460 static void |
441 _hb_ot_layout_collect_lookups_features (hb_face_t *face, | 461 _hb_ot_layout_collect_lookups_features (hb_face_t *face, |
442 hb_tag_t table_tag, | 462 hb_tag_t table_tag, |
443 unsigned int script_index, | 463 unsigned int script_index, |
444 unsigned int language_index, | 464 unsigned int language_index, |
445 const hb_tag_t *features, | 465 const hb_tag_t *features, |
446 hb_set_t *lookup_indexes /* OUT */
) | 466 hb_set_t *lookup_indexes /* OUT */
) |
447 { | 467 { |
448 unsigned int required_feature_index; | |
449 if (hb_ot_layout_language_get_required_feature_index (face, | |
450 table_tag, | |
451 script_index, | |
452 language_index, | |
453 &required_feature_index)
) | |
454 _hb_ot_layout_collect_lookups_lookups (face, | |
455 table_tag, | |
456 required_feature_index, | |
457 lookup_indexes); | |
458 | |
459 if (!features) | 468 if (!features) |
460 { | 469 { |
| 470 unsigned int required_feature_index; |
| 471 if (hb_ot_layout_language_get_required_feature_index (face, |
| 472 table_tag, |
| 473 script_index, |
| 474 language_index, |
| 475 &required_feature_inde
x)) |
| 476 _hb_ot_layout_collect_lookups_lookups (face, |
| 477 table_tag, |
| 478 required_feature_index, |
| 479 lookup_indexes); |
| 480 |
461 /* All features */ | 481 /* All features */ |
462 unsigned int feature_indices[32]; | 482 unsigned int feature_indices[32]; |
463 unsigned int offset, len; | 483 unsigned int offset, len; |
464 | 484 |
465 offset = 0; | 485 offset = 0; |
466 do { | 486 do { |
467 len = ARRAY_LENGTH (feature_indices); | 487 len = ARRAY_LENGTH (feature_indices); |
468 hb_ot_layout_language_get_feature_indexes (face, | 488 hb_ot_layout_language_get_feature_indexes (face, |
469 table_tag, | 489 table_tag, |
470 script_index, | 490 script_index, |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 glyphs_before, | 626 glyphs_before, |
607 glyphs_input, | 627 glyphs_input, |
608 glyphs_after, | 628 glyphs_after, |
609 glyphs_output); | 629 glyphs_output); |
610 | 630 |
611 switch (table_tag) | 631 switch (table_tag) |
612 { | 632 { |
613 case HB_OT_TAG_GSUB: | 633 case HB_OT_TAG_GSUB: |
614 { | 634 { |
615 const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup
(lookup_index); | 635 const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup
(lookup_index); |
616 l.collect_glyphs_lookup (&c); | 636 l.collect_glyphs (&c); |
617 return; | 637 return; |
618 } | 638 } |
619 case HB_OT_TAG_GPOS: | 639 case HB_OT_TAG_GPOS: |
620 { | 640 { |
621 const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (
lookup_index); | 641 const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (
lookup_index); |
622 l.collect_glyphs_lookup (&c); | 642 l.collect_glyphs (&c); |
623 return; | 643 return; |
624 } | 644 } |
625 } | 645 } |
626 } | 646 } |
627 | 647 |
628 | 648 |
629 /* | 649 /* |
630 * OT::GSUB | 650 * OT::GSUB |
631 */ | 651 */ |
632 | 652 |
(...skipping 19 matching lines...) Expand all Loading... |
652 unsigned int lookup_index, | 672 unsigned int lookup_index, |
653 const hb_codepoint_t *glyphs, | 673 const hb_codepoint_t *glyphs, |
654 unsigned int glyphs_length, | 674 unsigned int glyphs_length, |
655 hb_bool_t zero_context) | 675 hb_bool_t zero_context) |
656 { | 676 { |
657 if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count
)) return false; | 677 if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count
)) return false; |
658 OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context); | 678 OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context); |
659 | 679 |
660 const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lo
okup_index); | 680 const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lo
okup_index); |
661 | 681 |
662 return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_digests[lookup_
index]); | 682 return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_i
ndex].digest); |
663 } | 683 } |
664 | 684 |
665 void | 685 void |
666 hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer) | 686 hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer) |
667 { | 687 { |
668 OT::GSUB::substitute_start (font, buffer); | 688 OT::GSUB::substitute_start (font, buffer); |
669 } | 689 } |
670 | 690 |
671 hb_bool_t | |
672 hb_ot_layout_substitute_lookup (hb_font_t *font, | |
673 hb_buffer_t *buffer, | |
674 unsigned int lookup_index, | |
675 hb_mask_t mask, | |
676 hb_bool_t auto_zwj) | |
677 { | |
678 if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gsub_lookup
_count)) return false; | |
679 | |
680 OT::hb_apply_context_t c (0, font, buffer, mask, auto_zwj); | |
681 | |
682 const OT::SubstLookup& l = hb_ot_layout_from_face (font->face)->gsub->get_look
up (lookup_index); | |
683 | |
684 return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gsub_digests[
lookup_index]); | |
685 } | |
686 | |
687 void | 691 void |
688 hb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer) | 692 hb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer) |
689 { | 693 { |
690 OT::GSUB::substitute_finish (font, buffer); | 694 OT::GSUB::substitute_finish (font, buffer); |
691 } | 695 } |
692 | 696 |
693 void | 697 void |
694 hb_ot_layout_lookup_substitute_closure (hb_face_t *face, | 698 hb_ot_layout_lookup_substitute_closure (hb_face_t *face, |
695 unsigned int lookup_index, | 699 unsigned int lookup_index, |
696 hb_set_t *glyphs) | 700 hb_set_t *glyphs) |
(...skipping 14 matching lines...) Expand all Loading... |
711 { | 715 { |
712 return &_get_gpos (face) != &OT::Null(OT::GPOS); | 716 return &_get_gpos (face) != &OT::Null(OT::GPOS); |
713 } | 717 } |
714 | 718 |
715 void | 719 void |
716 hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer) | 720 hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer) |
717 { | 721 { |
718 OT::GPOS::position_start (font, buffer); | 722 OT::GPOS::position_start (font, buffer); |
719 } | 723 } |
720 | 724 |
721 hb_bool_t | |
722 hb_ot_layout_position_lookup (hb_font_t *font, | |
723 hb_buffer_t *buffer, | |
724 unsigned int lookup_index, | |
725 hb_mask_t mask, | |
726 hb_bool_t auto_zwj) | |
727 { | |
728 if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gpos_lookup
_count)) return false; | |
729 | |
730 OT::hb_apply_context_t c (1, font, buffer, mask, auto_zwj); | |
731 | |
732 const OT::PosLookup& l = hb_ot_layout_from_face (font->face)->gpos->get_lookup
(lookup_index); | |
733 | |
734 return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gpos_digests[
lookup_index]); | |
735 } | |
736 | |
737 void | 725 void |
738 hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer) | 726 hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer) |
739 { | 727 { |
740 OT::GPOS::position_finish (font, buffer); | 728 OT::GPOS::position_finish (font, buffer); |
741 } | 729 } |
742 | 730 |
743 hb_bool_t | 731 hb_bool_t |
744 hb_ot_layout_get_size_params (hb_face_t *face, | 732 hb_ot_layout_get_size_params (hb_face_t *face, |
745 unsigned int *design_size, /* OUT. May be N
ULL */ | 733 unsigned int *design_size, /* OUT. May be N
ULL */ |
746 unsigned int *subfamily_id, /* OUT. May be N
ULL */ | 734 unsigned int *subfamily_id, /* OUT. May be N
ULL */ |
(...skipping 30 matching lines...) Expand all Loading... |
777 #define PARAM(a, A) if (a) *a = 0 | 765 #define PARAM(a, A) if (a) *a = 0 |
778 PARAM (design_size, designSize); | 766 PARAM (design_size, designSize); |
779 PARAM (subfamily_id, subfamilyID); | 767 PARAM (subfamily_id, subfamilyID); |
780 PARAM (subfamily_name_id, subfamilyNameID); | 768 PARAM (subfamily_name_id, subfamilyNameID); |
781 PARAM (range_start, rangeStart); | 769 PARAM (range_start, rangeStart); |
782 PARAM (range_end, rangeEnd); | 770 PARAM (range_end, rangeEnd); |
783 #undef PARAM | 771 #undef PARAM |
784 | 772 |
785 return false; | 773 return false; |
786 } | 774 } |
| 775 |
| 776 |
| 777 /* |
| 778 * Parts of different types are implemented here such that they have direct |
| 779 * access to GSUB/GPOS lookups. |
| 780 */ |
| 781 |
| 782 |
| 783 struct GSUBProxy |
| 784 { |
| 785 static const unsigned int table_index = 0; |
| 786 static const bool inplace = false; |
| 787 typedef OT::SubstLookup Lookup; |
| 788 |
| 789 GSUBProxy (hb_face_t *face) : |
| 790 table (*hb_ot_layout_from_face (face)->gsub), |
| 791 accels (hb_ot_layout_from_face (face)->gsub_accels) {} |
| 792 |
| 793 const OT::GSUB &table; |
| 794 const hb_ot_layout_lookup_accelerator_t *accels; |
| 795 }; |
| 796 |
| 797 struct GPOSProxy |
| 798 { |
| 799 static const unsigned int table_index = 1; |
| 800 static const bool inplace = true; |
| 801 typedef OT::PosLookup Lookup; |
| 802 |
| 803 GPOSProxy (hb_face_t *face) : |
| 804 table (*hb_ot_layout_from_face (face)->gpos), |
| 805 accels (hb_ot_layout_from_face (face)->gpos_accels) {} |
| 806 |
| 807 const OT::GPOS &table; |
| 808 const hb_ot_layout_lookup_accelerator_t *accels; |
| 809 }; |
| 810 |
| 811 |
| 812 template <typename Lookup> |
| 813 static inline bool apply_once (OT::hb_apply_context_t *c, |
| 814 const Lookup &lookup) |
| 815 { |
| 816 if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props)) |
| 817 return false; |
| 818 return lookup.dispatch (c); |
| 819 } |
| 820 |
| 821 template <typename Proxy> |
| 822 static inline bool |
| 823 apply_string (OT::hb_apply_context_t *c, |
| 824 const typename Proxy::Lookup &lookup, |
| 825 const hb_ot_layout_lookup_accelerator_t &accel) |
| 826 { |
| 827 bool ret = false; |
| 828 hb_buffer_t *buffer = c->buffer; |
| 829 |
| 830 if (unlikely (!buffer->len || !c->lookup_mask)) |
| 831 return false; |
| 832 |
| 833 c->set_lookup (lookup); |
| 834 |
| 835 if (likely (!lookup.is_reverse ())) |
| 836 { |
| 837 /* in/out forward substitution/positioning */ |
| 838 if (Proxy::table_index == 0) |
| 839 buffer->clear_output (); |
| 840 buffer->idx = 0; |
| 841 |
| 842 while (buffer->idx < buffer->len) |
| 843 { |
| 844 if (accel.digest.may_have (buffer->cur().codepoint) && |
| 845 (buffer->cur().mask & c->lookup_mask) && |
| 846 apply_once (c, lookup)) |
| 847 ret = true; |
| 848 else |
| 849 buffer->next_glyph (); |
| 850 } |
| 851 if (ret) |
| 852 { |
| 853 if (!Proxy::inplace) |
| 854 buffer->swap_buffers (); |
| 855 else |
| 856 assert (!buffer->has_separate_output ()); |
| 857 } |
| 858 } |
| 859 else |
| 860 { |
| 861 /* in-place backward substitution/positioning */ |
| 862 if (Proxy::table_index == 0) |
| 863 buffer->remove_output (); |
| 864 buffer->idx = buffer->len - 1; |
| 865 do |
| 866 { |
| 867 if (accel.digest.may_have (buffer->cur().codepoint) && |
| 868 (buffer->cur().mask & c->lookup_mask) && |
| 869 apply_once (c, lookup)) |
| 870 ret = true; |
| 871 /* The reverse lookup doesn't "advance" cursor (for good reason). */ |
| 872 buffer->idx--; |
| 873 |
| 874 } |
| 875 while ((int) buffer->idx >= 0); |
| 876 } |
| 877 |
| 878 return ret; |
| 879 } |
| 880 |
| 881 template <typename Proxy> |
| 882 inline void hb_ot_map_t::apply (const Proxy &proxy, |
| 883 const hb_ot_shape_plan_t *plan, |
| 884 hb_font_t *font, |
| 885 hb_buffer_t *buffer) const |
| 886 { |
| 887 const unsigned int table_index = proxy.table_index; |
| 888 unsigned int i = 0; |
| 889 OT::hb_apply_context_t c (table_index, font, buffer); |
| 890 c.set_recurse_func (Proxy::Lookup::apply_recurse_func); |
| 891 |
| 892 for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stag
e_index++) { |
| 893 const stage_map_t *stage = &stages[table_index][stage_index]; |
| 894 for (; i < stage->last_lookup; i++) |
| 895 { |
| 896 unsigned int lookup_index = lookups[table_index][i].index; |
| 897 c.set_lookup_mask (lookups[table_index][i].mask); |
| 898 c.set_auto_zwj (lookups[table_index][i].auto_zwj); |
| 899 apply_string<Proxy> (&c, |
| 900 proxy.table.get_lookup (lookup_index), |
| 901 proxy.accels[lookup_index]); |
| 902 } |
| 903 |
| 904 if (stage->pause_func) |
| 905 { |
| 906 buffer->clear_output (); |
| 907 stage->pause_func (plan, font, buffer); |
| 908 } |
| 909 } |
| 910 } |
| 911 |
| 912 void hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, h
b_buffer_t *buffer) const |
| 913 { |
| 914 GSUBProxy proxy (font->face); |
| 915 apply (proxy, plan, font, buffer); |
| 916 } |
| 917 |
| 918 void hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_
buffer_t *buffer) const |
| 919 { |
| 920 GPOSProxy proxy (font->face); |
| 921 apply (proxy, plan, font, buffer); |
| 922 } |
| 923 |
| 924 HB_INTERNAL void |
| 925 hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c, |
| 926 const OT::SubstLookup &lookup, |
| 927 const hb_ot_layout_lookup_accelerator_t &accel) |
| 928 { |
| 929 apply_string<GSUBProxy> (c, lookup, accel); |
| 930 } |
OLD | NEW |