[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
This commit is contained in:
parent
61486746d3
commit
044d7a06db
|
@ -408,9 +408,10 @@ struct hb_ot_apply_context_t :
|
|||
{
|
||||
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 @@ struct hb_ot_apply_context_t :
|
|||
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 @@ struct hb_ot_apply_context_t :
|
|||
|
||||
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 @@ struct hb_ot_apply_context_t :
|
|||
/* 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 @@ struct hb_ot_apply_context_t :
|
|||
bool has_glyph_classes;
|
||||
bool auto_zwnj;
|
||||
bool auto_zwj;
|
||||
bool per_syllable;
|
||||
bool random;
|
||||
|
||||
uint32_t random_state;
|
||||
|
@ -662,6 +667,7 @@ struct hb_ot_apply_context_t :
|
|||
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 @@ struct hb_ot_apply_context_t :
|
|||
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_; }
|
||||
|
|
|
@ -1931,6 +1931,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
|
|||
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),
|
||||
|
|
|
@ -172,17 +172,6 @@ _hb_next_syllable (hb_buffer_t *buffer, unsigned int start)
|
|||
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 */
|
||||
|
||||
|
|
|
@ -117,7 +117,8 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
|
|||
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 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
|
|||
lookup->auto_zwnj = auto_zwnj;
|
||||
lookup->auto_zwj = auto_zwj;
|
||||
lookup->random = random;
|
||||
lookup->per_syllable = per_syllable;
|
||||
}
|
||||
|
||||
offset += len;
|
||||
|
@ -277,6 +279,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
|||
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 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
|
|||
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)
|
||||
|
|
|
@ -56,6 +56,7 @@ struct hb_ot_map_t
|
|||
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 @@ struct hb_ot_map_t
|
|||
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 @@ enum hb_ot_map_feature_flags_t
|
|||
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 @@ struct hb_ot_map_builder_t
|
|||
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;
|
||||
|
|
|
@ -109,17 +109,17 @@ indic_features[] =
|
|||
* 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 @@ indic_features[] =
|
|||
* 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 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
|
|||
/* 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 @@ collect_features_indic (hb_ot_shape_planner_t *plan)
|
|||
|
||||
for (; i < INDIC_NUM_FEATURES; i++)
|
||||
map->add_feature (indic_features[i]);
|
||||
|
||||
map->add_gsub_pause (_hb_clear_syllables);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -45,11 +45,11 @@ khmer_features[] =
|
|||
* 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 @@ collect_features_khmer (hb_ot_shape_planner_t *plan)
|
|||
*
|
||||
* 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]);
|
||||
}
|
||||
|
||||
|
|
|
@ -79,22 +79,20 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan)
|
|||
/* 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);
|
||||
}
|
||||
|
|
|
@ -115,25 +115,24 @@ collect_features_use (hb_ot_shape_planner_t *plan)
|
|||
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++)
|
||||
|
|
Binary file not shown.
|
@ -11,3 +11,4 @@
|
|||
../fonts/b3075ca42b27dde7341c2d0ae16703c5b6640df0.ttf;;U+0B2C,U+0B55,U+0B3E;[uni0B2C=0+641|uni0B55=0+0|uni0B3E=0+253]
|
||||
../fonts/b3075ca42b27dde7341c2d0ae16703c5b6640df0.ttf;;U+0B2C,U+0B3E,U+0B55;[uni0B2C=0+641|uni0B3E=0+253|uni0B55=0+0]
|
||||
../fonts/e2b17207c4b7ad78d843e1b0c4d00b09398a1137.ttf;;U+0BAA,U+0BAA,U+0BCD;[pa-tamil=0+778|pa-tamil.001=1+778|pulli-tamil=1@-385,0+0]
|
||||
../fonts/41071178fbce4956d151f50967af458dbf555f7b.ttf;;U+0926,U+093F,U+0938,U+0902,U+092C,U+0930;[isigndeva=0+266|dadeva=0+541|sadeva=2+709|anusvaradeva=2@0,-1+0|badeva=4+537|radeva=5+436]
|
||||
|
|
Loading…
Reference in New Issue