Index: third_party/harfbuzz-ng/src/hb-ot-map.cc |
diff --git a/third_party/harfbuzz-ng/src/hb-ot-map.cc b/third_party/harfbuzz-ng/src/hb-ot-map.cc |
index 559193c1bae6072928c9ae9faee71470d1ba354d..4985eb22b20814e891301dad35095b1c7eddac6b 100644 |
--- a/third_party/harfbuzz-ng/src/hb-ot-map.cc |
+++ b/third_party/harfbuzz-ng/src/hb-ot-map.cc |
@@ -99,6 +99,7 @@ void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value, |
{ |
feature_info_t *info = feature_infos.push(); |
if (unlikely (!info)) return; |
+ if (unlikely (!tag)) return; |
info->tag = tag; |
info->seq = feature_infos.len; |
info->max_value = value; |
@@ -131,9 +132,25 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) |
{ |
m.global_mask = 1; |
- for (unsigned int table_index = 0; table_index < 2; table_index++) { |
+ unsigned int required_feature_index[2]; |
+ hb_tag_t required_feature_tag[2]; |
+ /* We default to applying required feature in stage 0. If the required |
+ * feature has a tag that is known to the shaper, we apply required feature |
+ * in the stage for that tag. |
+ */ |
+ unsigned int required_feature_stage[2] = {0, 0}; |
+ |
+ for (unsigned int table_index = 0; table_index < 2; table_index++) |
+ { |
m.chosen_script[table_index] = chosen_script[table_index]; |
m.found_script[table_index] = found_script[table_index]; |
+ |
+ hb_ot_layout_language_get_required_feature (face, |
+ table_tags[table_index], |
+ script_index[table_index], |
+ language_index[table_index], |
+ &required_feature_index[table_index], |
+ &required_feature_tag[table_index]); |
} |
if (!feature_infos.len) |
@@ -141,7 +158,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) |
/* Sort features and merge duplicates */ |
{ |
- feature_infos.sort (); |
+ feature_infos.qsort (); |
unsigned int j = 0; |
for (unsigned int i = 1; i < feature_infos.len; i++) |
if (feature_infos[i].tag != feature_infos[j].tag) |
@@ -166,7 +183,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) |
/* Allocate bits now */ |
unsigned int next_bit = 1; |
- for (unsigned int i = 0; i < feature_infos.len; i++) { |
+ for (unsigned int i = 0; i < feature_infos.len; i++) |
+ { |
const feature_info_t *info = &feature_infos[i]; |
unsigned int bits_needed; |
@@ -184,12 +202,20 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) |
hb_bool_t found = false; |
unsigned int feature_index[2]; |
for (unsigned int table_index = 0; table_index < 2; table_index++) |
+ { |
+ if (required_feature_tag[table_index] == info->tag) |
+ { |
+ required_feature_stage[table_index] = info->stage[table_index]; |
+ found = true; |
+ continue; |
+ } |
found |= hb_ot_layout_language_find_feature (face, |
table_tags[table_index], |
script_index[table_index], |
language_index[table_index], |
info->tag, |
&feature_index[table_index]); |
+ } |
if (!found && !(info->flags & F_HAS_FALLBACK)) |
continue; |
@@ -224,23 +250,21 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) |
add_gsub_pause (NULL); |
add_gpos_pause (NULL); |
- for (unsigned int table_index = 0; table_index < 2; table_index++) { |
- hb_tag_t table_tag = table_tags[table_index]; |
- |
+ for (unsigned int table_index = 0; table_index < 2; table_index++) |
+ { |
/* Collect lookup indices for features */ |
- unsigned int required_feature_index; |
- if (hb_ot_layout_language_get_required_feature_index (face, |
- table_tag, |
- script_index[table_index], |
- language_index[table_index], |
- &required_feature_index)) |
- m.add_lookups (face, table_index, required_feature_index, 1, true); |
- |
unsigned int stage_index = 0; |
unsigned int last_num_lookups = 0; |
for (unsigned stage = 0; stage < current_stage[table_index]; stage++) |
{ |
+ if (required_feature_index[table_index] != HB_OT_LAYOUT_NO_FEATURE_INDEX && |
+ required_feature_stage[table_index] == stage) |
+ m.add_lookups (face, table_index, |
+ required_feature_index[table_index], |
+ 1 /* mask */, |
+ true /* auto_zwj */); |
+ |
for (unsigned i = 0; i < m.features.len; i++) |
if (m.features[i].stage[table_index] == stage) |
m.add_lookups (face, table_index, |
@@ -251,7 +275,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) |
/* Sort lookups and merge duplicates */ |
if (last_num_lookups < m.lookups[table_index].len) |
{ |
- m.lookups[table_index].sort (last_num_lookups, m.lookups[table_index].len); |
+ m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].len); |
unsigned int j = last_num_lookups; |
for (unsigned int i = j + 1; i < m.lookups[table_index].len; i++) |