[indic-like] Add per-lookup per-syllable flag This allows mix-and-matching per-syllable and other lookups. In fact, removes the clear-syllables call completely. Fixes https://github.com/harfbuzz/harfbuzz/issues/3513
diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index 8ba555c..3faa1e5 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh
@@ -408,9 +408,10 @@ { matcher_t () : lookup_props (0), + mask (-1), ignore_zwnj (false), ignore_zwj (false), - mask (-1), + per_syllable (false), syllable {0}, match_func (nullptr), match_data (nullptr) {} @@ -421,7 +422,8 @@ void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; } void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; } void set_mask (hb_mask_t mask_) { mask = mask_; } - void set_syllable (uint8_t syllable_) { syllable = syllable_; } + void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; } + void set_syllable (uint8_t syllable_) { syllable = per_syllable ? syllable_ : 0; } void set_match_func (match_func_t match_func_, const void *match_data_) { match_func = match_func_; match_data = match_data_; } @@ -467,9 +469,10 @@ protected: unsigned int lookup_props; + hb_mask_t mask; bool ignore_zwnj; bool ignore_zwj; - hb_mask_t mask; + bool per_syllable; uint8_t syllable; match_func_t match_func; const void *match_data; @@ -488,6 +491,7 @@ /* Ignore ZWJ if we are matching context, or asked to. */ matcher.set_ignore_zwj (context_match || c->auto_zwj); matcher.set_mask (context_match ? -1 : c->lookup_mask); + matcher.set_per_syllable (c->per_syllable); } void set_lookup_props (unsigned int lookup_props) { @@ -634,6 +638,7 @@ bool has_glyph_classes; bool auto_zwnj; bool auto_zwj; + bool per_syllable; bool random; uint32_t random_state; @@ -662,6 +667,7 @@ has_glyph_classes (gdef.has_glyph_classes ()), auto_zwnj (true), auto_zwj (true), + per_syllable (false), random (false), random_state (1) { init_iters (); } @@ -674,6 +680,7 @@ void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; init_iters (); } void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; init_iters (); } void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; init_iters (); } + void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; init_iters (); } void set_random (bool random_) { random = random_; } void set_recurse_func (recurse_func_t func) { recurse_func = func; } void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index f509dd9..f4ea21a 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc
@@ -1931,6 +1931,7 @@ c.set_auto_zwj (lookups[table_index][i].auto_zwj); c.set_auto_zwnj (lookups[table_index][i].auto_zwnj); c.set_random (lookups[table_index][i].random); + c.set_per_syllable (lookups[table_index][i].per_syllable); apply_string<Proxy> (&c, proxy.table.get_lookup (lookup_index),
diff --git a/src/hb-ot-layout.hh b/src/hb-ot-layout.hh index ac15458..75bba0b 100644 --- a/src/hb-ot-layout.hh +++ b/src/hb-ot-layout.hh
@@ -172,17 +172,6 @@ return start; } -static inline void -_hb_clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font HB_UNUSED, - hb_buffer_t *buffer) -{ - hb_glyph_info_t *info = buffer->info; - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; i++) - info[i].syllable() = 0; -} - /* unicode_props */
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 12ceea5..f085c78 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc
@@ -117,7 +117,8 @@ hb_mask_t mask, bool auto_zwnj, bool auto_zwj, - bool random) + bool random, + bool per_syllable) { unsigned int lookup_indices[32]; unsigned int offset, len; @@ -145,6 +146,7 @@ lookup->auto_zwnj = auto_zwnj; lookup->auto_zwj = auto_zwj; lookup->random = random; + lookup->per_syllable = per_syllable; } offset += len; @@ -277,6 +279,7 @@ map->auto_zwnj = !(info->flags & F_MANUAL_ZWNJ); map->auto_zwj = !(info->flags & F_MANUAL_ZWJ); map->random = !!(info->flags & F_RANDOM); + map->per_syllable = !!(info->flags & F_PER_SYLLABLE); if ((info->flags & F_GLOBAL) && info->max_value == 1) { /* Uses the global bit */ map->shift = global_bit_shift; @@ -319,7 +322,8 @@ m.features[i].mask, m.features[i].auto_zwnj, m.features[i].auto_zwj, - m.features[i].random); + m.features[i].random, + m.features[i].per_syllable); /* Sort lookups and merge duplicates */ if (last_num_lookups < m.lookups[table_index].length)
diff --git a/src/hb-ot-map.hh b/src/hb-ot-map.hh index 5f2afae..f1cbf75 100644 --- a/src/hb-ot-map.hh +++ b/src/hb-ot-map.hh
@@ -56,6 +56,7 @@ unsigned int auto_zwnj : 1; unsigned int auto_zwj : 1; unsigned int random : 1; + unsigned int per_syllable : 1; int cmp (const hb_tag_t tag_) const { return tag_ < tag ? -1 : tag_ > tag ? 1 : 0; } @@ -66,6 +67,7 @@ unsigned short auto_zwnj : 1; unsigned short auto_zwj : 1; unsigned short random : 1; + unsigned short per_syllable : 1; hb_mask_t mask; HB_INTERNAL static int cmp (const void *pa, const void *pb) @@ -183,7 +185,8 @@ F_GLOBAL_MANUAL_JOINERS= F_GLOBAL | F_MANUAL_JOINERS, F_GLOBAL_HAS_FALLBACK = F_GLOBAL | F_HAS_FALLBACK, F_GLOBAL_SEARCH = 0x0010u, /* If feature not found in LangSys, look for it in global feature list and pick one. */ - F_RANDOM = 0x0020u /* Randomly select a glyph from an AlternateSubstFormat1 subtable. */ + F_RANDOM = 0x0020u, /* Randomly select a glyph from an AlternateSubstFormat1 subtable. */ + F_PER_SYLLABLE = 0x0040u /* Contain lookup application to within syllable. */ }; HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t); @@ -237,7 +240,8 @@ hb_mask_t mask, bool auto_zwnj = true, bool auto_zwj = true, - bool random = false); + bool random = false, + bool per_syllable = false); struct feature_info_t { hb_tag_t tag;
diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index 4a8781c..c80f7df 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc
@@ -109,17 +109,17 @@ * These features are applied in order, one at a time, after initial_reordering, * constrained to the syllable. */ - {HB_TAG('n','u','k','t'), F_GLOBAL_MANUAL_JOINERS}, - {HB_TAG('a','k','h','n'), F_GLOBAL_MANUAL_JOINERS}, - {HB_TAG('r','p','h','f'), F_MANUAL_JOINERS}, - {HB_TAG('r','k','r','f'), F_GLOBAL_MANUAL_JOINERS}, - {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS}, - {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS}, - {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS}, - {HB_TAG('h','a','l','f'), F_MANUAL_JOINERS}, - {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS}, - {HB_TAG('v','a','t','u'), F_GLOBAL_MANUAL_JOINERS}, - {HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS}, + {HB_TAG('n','u','k','t'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('a','k','h','n'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('r','p','h','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('r','k','r','f'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('h','a','l','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('v','a','t','u'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE}, /* * Other features. * These features are applied all at once, after final_reordering, constrained @@ -127,12 +127,12 @@ * Default Bengali font in Windows for example has intermixed * lookups for init,pres,abvs,blws features. */ - {HB_TAG('i','n','i','t'), F_MANUAL_JOINERS}, - {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS}, - {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS}, - {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS}, - {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS}, - {HB_TAG('h','a','l','n'), F_GLOBAL_MANUAL_JOINERS}, + {HB_TAG('i','n','i','t'), F_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('h','a','l','n'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE}, }; /* @@ -183,10 +183,10 @@ /* Do this before any lookups have been applied. */ map->add_gsub_pause (setup_syllables_indic); - map->enable_feature (HB_TAG('l','o','c','l')); + map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE); /* The Indic specs do not require ccmp, but we apply it here since if * there is a use of it, it's typically at the beginning. */ - map->enable_feature (HB_TAG('c','c','m','p')); + map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE); unsigned int i = 0; @@ -201,8 +201,6 @@ for (; i < INDIC_NUM_FEATURES; i++) map->add_feature (indic_features[i]); - - map->add_gsub_pause (_hb_clear_syllables); } static void
diff --git a/src/hb-ot-shape-complex-khmer.cc b/src/hb-ot-shape-complex-khmer.cc index 7787886..d7ec163 100644 --- a/src/hb-ot-shape-complex-khmer.cc +++ b/src/hb-ot-shape-complex-khmer.cc
@@ -45,11 +45,11 @@ * These features are applied all at once, before reordering, constrained * to the syllable. */ - {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS}, - {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS}, - {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS}, - {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS}, - {HB_TAG('c','f','a','r'), F_MANUAL_JOINERS}, + {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE}, + {HB_TAG('c','f','a','r'), F_MANUAL_JOINERS | F_PER_SYLLABLE}, /* * Other features. * These features are applied all at once after clearing syllables. @@ -107,16 +107,10 @@ * * https://github.com/harfbuzz/harfbuzz/issues/974 */ - map->enable_feature (HB_TAG('l','o','c','l')); - map->enable_feature (HB_TAG('c','c','m','p')); + map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE); + map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE); - unsigned int i = 0; - for (; i < KHMER_BASIC_FEATURES; i++) - map->add_feature (khmer_features[i]); - - map->add_gsub_pause (_hb_clear_syllables); - - for (; i < KHMER_NUM_FEATURES; i++) + for (unsigned i = 0; i < KHMER_NUM_FEATURES; i++) map->add_feature (khmer_features[i]); }
diff --git a/src/hb-ot-shape-complex-myanmar.cc b/src/hb-ot-shape-complex-myanmar.cc index e6ae75e..c7aa80a 100644 --- a/src/hb-ot-shape-complex-myanmar.cc +++ b/src/hb-ot-shape-complex-myanmar.cc
@@ -79,22 +79,20 @@ /* Do this before any lookups have been applied. */ map->add_gsub_pause (setup_syllables_myanmar); - map->enable_feature (HB_TAG('l','o','c','l')); + map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE); /* The Indic specs do not require ccmp, but we apply it here since if * there is a use of it, it's typically at the beginning. */ - map->enable_feature (HB_TAG('c','c','m','p')); + map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE); map->add_gsub_pause (reorder_myanmar); for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_basic_features); i++) { - map->enable_feature (myanmar_basic_features[i], F_MANUAL_ZWJ); + map->enable_feature (myanmar_basic_features[i], F_MANUAL_ZWJ | F_PER_SYLLABLE); map->add_gsub_pause (nullptr); } - map->add_gsub_pause (_hb_clear_syllables); - for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_other_features); i++) map->enable_feature (myanmar_other_features[i], F_MANUAL_ZWJ); }
diff --git a/src/hb-ot-shape-complex-use.cc b/src/hb-ot-shape-complex-use.cc index a3f73ad..1d13c8a 100644 --- a/src/hb-ot-shape-complex-use.cc +++ b/src/hb-ot-shape-complex-use.cc
@@ -115,25 +115,24 @@ map->add_gsub_pause (setup_syllables_use); /* "Default glyph pre-processing group" */ - map->enable_feature (HB_TAG('l','o','c','l')); - map->enable_feature (HB_TAG('c','c','m','p')); - map->enable_feature (HB_TAG('n','u','k','t')); - map->enable_feature (HB_TAG('a','k','h','n'), F_MANUAL_ZWJ); + map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE); + map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE); + map->enable_feature (HB_TAG('n','u','k','t'), F_PER_SYLLABLE); + map->enable_feature (HB_TAG('a','k','h','n'), F_MANUAL_ZWJ | F_PER_SYLLABLE); /* "Reordering group" */ map->add_gsub_pause (_hb_clear_substitution_flags); - map->add_feature (HB_TAG('r','p','h','f'), F_MANUAL_ZWJ); + map->add_feature (HB_TAG('r','p','h','f'), F_MANUAL_ZWJ | F_PER_SYLLABLE); map->add_gsub_pause (record_rphf_use); map->add_gsub_pause (_hb_clear_substitution_flags); - map->enable_feature (HB_TAG('p','r','e','f'), F_MANUAL_ZWJ); + map->enable_feature (HB_TAG('p','r','e','f'), F_MANUAL_ZWJ | F_PER_SYLLABLE); map->add_gsub_pause (record_pref_use); /* "Orthographic unit shaping group" */ for (unsigned int i = 0; i < ARRAY_LENGTH (use_basic_features); i++) - map->enable_feature (use_basic_features[i], F_MANUAL_ZWJ); + map->enable_feature (use_basic_features[i], F_MANUAL_ZWJ | F_PER_SYLLABLE); map->add_gsub_pause (reorder_use); - map->add_gsub_pause (_hb_clear_syllables); /* "Topographical features" */ for (unsigned int i = 0; i < ARRAY_LENGTH (use_topographical_features); i++)