diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index d73ddc1d9..2e867e3de 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -295,7 +295,7 @@ struct Sequence for (unsigned int i = 0; i < count; i++) { _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i); - c->output_glyph (substitute.array[i], klass); + c->output_glyph_for_component (substitute.array[i], klass); } c->buffer->skip_glyph (); diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index c8926c0fb..4521eecf5 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -567,13 +567,25 @@ struct hb_apply_context_t inline void _set_glyph_props (hb_codepoint_t glyph_index, unsigned int class_guess = 0, - bool ligature = false) const + bool ligature = false, + bool component = false) const { unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) & HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE; add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED; if (ligature) + { add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED; + /* In the only place that the MULTIPLIED bit is used, Uniscribe + * seems to only care about the "last" transformation between + * Ligature and Multiple substitions. Ie. if you ligate, expand, + * and ligate again, it forgives the multiplication and acts as + * if only ligation happened. As such, clear MULTIPLIED bit. + */ + add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED; + } + if (component) + add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED; if (likely (has_glyph_classes)) _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index)); else if (class_guess) @@ -596,10 +608,10 @@ struct hb_apply_context_t _set_glyph_props (glyph_index, class_guess, true); buffer->replace_glyph (glyph_index); } - inline void output_glyph (hb_codepoint_t glyph_index, - unsigned int class_guess) const + inline void output_glyph_for_component (hb_codepoint_t glyph_index, + unsigned int class_guess) const { - _set_glyph_props (glyph_index, class_guess); + _set_glyph_props (glyph_index, class_guess, false, true); buffer->output_glyph (glyph_index); } }; diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index 4f03e1b0e..3ded92fec 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -50,9 +50,11 @@ typedef enum /* The following are used internally; not derived from GDEF. */ HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED = 0x10u, HB_OT_LAYOUT_GLYPH_PROPS_LIGATED = 0x20u, + HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED = 0x40u, HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED | - HB_OT_LAYOUT_GLYPH_PROPS_LIGATED + HB_OT_LAYOUT_GLYPH_PROPS_LIGATED | + HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED } hb_ot_layout_glyph_class_mask_t; @@ -381,6 +383,18 @@ _hb_glyph_info_ligated (const hb_glyph_info_t *info) return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED); } +static inline bool +_hb_glyph_info_multiplied (const hb_glyph_info_t *info) +{ + return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED); +} + +static inline bool +_hb_glyph_info_ligated_and_didnt_multiply (const hb_glyph_info_t *info) +{ + return _hb_glyph_info_ligated (info) && !_hb_glyph_info_multiplied (info); +} + /* Allocation / deallocation. */ static inline void diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 77a79a579..4b122201c 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -1446,7 +1446,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, if (start + 1 < end && info[start].indic_position() == POS_RA_TO_BECOME_REPH && ((info[start].indic_category() == OT_Repha) ^ - _hb_glyph_info_ligated (&info[start]))) + _hb_glyph_info_ligated_and_didnt_multiply (&info[start]))) { unsigned int new_reph_pos; reph_position_t reph_pos = indic_plan->config->reph_pos; @@ -1599,7 +1599,7 @@ final_reordering_syllable (const hb_ot_shape_plan_t *plan, * If pref len is longer than one, then only reorder if it ligated. If * pref len is one, only reorder if it didn't ligate with other things. */ if (_hb_glyph_info_substituted (&info[i]) && - ((pref_len == 1) ^ _hb_glyph_info_ligated (&info[i]))) + ((pref_len == 1) ^ _hb_glyph_info_ligated_and_didnt_multiply (&info[i]))) { /* * 2. Try to find a target position the same way as for pre-base matra. diff --git a/test/shaping/Makefile.am b/test/shaping/Makefile.am index db3ebbcca..cefd4803c 100644 --- a/test/shaping/Makefile.am +++ b/test/shaping/Makefile.am @@ -34,7 +34,10 @@ CLEANFILES += \ hb_test_tools.py[co] \ $(NULL) -TESTS = tests/context-matching.tests +TESTS = \ + tests/context-matching.tests \ + tests/indic-pref-blocking.tests \ + $(NULL) TEST_EXTENSIONS = \ .tests \ diff --git a/test/shaping/fonts/sha1sum/226bc2deab3846f1a682085f70c67d0421014144.ttf b/test/shaping/fonts/sha1sum/226bc2deab3846f1a682085f70c67d0421014144.ttf new file mode 100644 index 000000000..70c0c0a83 Binary files /dev/null and b/test/shaping/fonts/sha1sum/226bc2deab3846f1a682085f70c67d0421014144.ttf differ diff --git a/test/shaping/tests/MANIFEST b/test/shaping/tests/MANIFEST index 8a6157a5b..ac10e0756 100644 --- a/test/shaping/tests/MANIFEST +++ b/test/shaping/tests/MANIFEST @@ -1 +1,2 @@ context-matching.tests +indic-pref-blocking.tests