From 7aace3d3fc064433de7ff5fdc44e126ff8e371ed Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 23 Sep 2024 07:47:24 -0600 Subject: [PATCH] Ignore CGJ and Mongolian Variation Selectors during GPOS Fixes https://github.com/harfbuzz/harfbuzz/issues/4869 --- src/hb-ot-layout-gsubgpos.hh | 9 +++++++-- src/hb-ot-layout.hh | 8 +++----- .../cee442574141a0304e780b27dd872519f7d229db.ttf | Bin 0 -> 6076 bytes .../data/in-house/tests/arabic-mark-order.tests | 2 +- .../data/in-house/tests/default-ignorables.tests | 3 ++- .../data/in-house/tests/hebrew-diacritics.tests | 4 ++-- 6 files changed, 15 insertions(+), 11 deletions(-) create mode 100644 test/shape/data/in-house/fonts/cee442574141a0304e780b27dd872519f7d229db.ttf diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index 0dc3bce87..0676fbee7 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -406,6 +406,7 @@ struct hb_ot_apply_context_t : void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; } void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; } + void set_ignore_hidden (bool ignore_hidden_) { ignore_hidden = ignore_hidden_; } void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; } void set_mask (hb_mask_t mask_) { mask = mask_; } void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; } @@ -451,9 +452,10 @@ struct hb_ot_apply_context_t : if (!c->check_glyph_property (&info, lookup_props)) return SKIP_YES; - if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) && + if (unlikely (_hb_glyph_info_is_default_ignorable (&info) && (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) && - (ignore_zwj || !_hb_glyph_info_is_zwj (&info)))) + (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) && + (ignore_hidden || !_hb_glyph_info_is_hidden (&info)))) return SKIP_MAYBE; return SKIP_NO; @@ -464,6 +466,7 @@ struct hb_ot_apply_context_t : hb_mask_t mask = -1; bool ignore_zwnj = false; bool ignore_zwj = false; + bool ignore_hidden = false; bool per_syllable = false; uint8_t syllable = 0; match_func_t match_func = nullptr; @@ -486,6 +489,8 @@ struct hb_ot_apply_context_t : matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj)); /* Ignore ZWJ if we are matching context, or asked to. */ matcher.set_ignore_zwj (context_match || c->auto_zwj); + /* Ignore hidden glyphs (like CGJ) during GPOS. */ + matcher.set_ignore_hidden (c->table_index == 1); matcher.set_mask (context_match ? -1 : c->lookup_mask); /* Per syllable matching is only for GSUB. */ matcher.set_per_syllable (c->table_index == 0 && c->per_syllable); diff --git a/src/hb-ot-layout.hh b/src/hb-ot-layout.hh index 591f7a281..3a8d36ac4 100644 --- a/src/hb-ot-layout.hh +++ b/src/hb-ot-layout.hh @@ -178,7 +178,7 @@ _hb_next_syllable (hb_buffer_t *buffer, unsigned int start) * * Is it Default_Ignorable(); we have a modified Default_Ignorable(). * * Whether it's one of the four Mongolian Free Variation Selectors, * CGJ, or other characters that are hidden but should not be ignored - * like most other Default_Ignorable()s do during matching. + * like most other Default_Ignorable()s do during GSUB matching. * * Whether it's a grapheme continuation. * * The high-byte has different meanings, switched by the Gen-Cat: @@ -317,11 +317,9 @@ _hb_glyph_info_clear_default_ignorable (hb_glyph_info_t *info) info->unicode_props() &= ~ UPROPS_MASK_IGNORABLE; } static inline bool -_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info) +_hb_glyph_info_is_hidden (const hb_glyph_info_t *info) { - return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN)) - == UPROPS_MASK_IGNORABLE) && - !_hb_glyph_info_substituted (info); + return info->unicode_props() & UPROPS_MASK_HIDDEN; } static inline void _hb_glyph_info_unhide (hb_glyph_info_t *info) diff --git a/test/shape/data/in-house/fonts/cee442574141a0304e780b27dd872519f7d229db.ttf b/test/shape/data/in-house/fonts/cee442574141a0304e780b27dd872519f7d229db.ttf new file mode 100644 index 0000000000000000000000000000000000000000..5842bf764c09f4591faa1bf5569baa9a7f616d55 GIT binary patch literal 6076 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 bK~=f*ugO79pg2C)ohAq0Dg1?e5QY8+