From dc35a0fbcb960f57df6c09a548651028c19e9790 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 30 Jul 2023 16:32:11 -0600 Subject: [PATCH] [ot-map] Speed up feature finding New API: - hb_ot_layout_collect_feature_map() --- docs/harfbuzz-sections.txt | 1 + src/hb-ot-layout.cc | 39 +++++++++++++++++++++++++++++++++++++- src/hb-ot-layout.h | 7 +++++++ src/hb-ot-map.cc | 22 ++++++++++++++------- 4 files changed, 61 insertions(+), 8 deletions(-) diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index fd07b81fe..46d0a16d9 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -619,6 +619,7 @@ hb_ot_tags_from_script_and_language hb_ot_tags_to_script_and_language hb_ot_layout_collect_lookups hb_ot_layout_collect_features +hb_ot_layout_collect_features_map hb_ot_layout_feature_get_characters hb_ot_layout_feature_get_lookups hb_ot_layout_feature_get_name_ids diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 020b8a6c8..e6bd74b33 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1241,7 +1241,7 @@ script_collect_features (hb_collect_features_context_t *c, * terminated by %HB_TAG_NONE * @features: (nullable) (array zero-terminated=1): The array of features to collect, * terminated by %HB_TAG_NONE - * @feature_indexes: (out): The array of feature indexes found for the query + * @feature_indexes: (out): The set of feature indexes found for the query * * Fetches a list of all feature indexes in the specified face's GSUB table * or GPOS table, underneath the specified scripts, languages, and features. @@ -1282,6 +1282,43 @@ hb_ot_layout_collect_features (hb_face_t *face, } } +/** + * hb_ot_layout_collect_features_map: + * @face: #hb_face_t to work upon + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS + * @script_index: The index of the requested script tag + * @language_index: The index of the requested language tag + * @feature_map: (out): The map of feature tag to feature index. + * + * Fetches the mapping from feature tags to feature indexes for + * the specified script and language. + * + * XSince: REPLACEME + **/ +void +hb_ot_layout_collect_features_map (hb_face_t *face, + hb_tag_t table_tag, + unsigned script_index, + unsigned language_index, + hb_map_t *feature_map /* OUT */) +{ + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index); + + unsigned int count = l.get_feature_indexes (0, nullptr, nullptr); + + for (unsigned int i = 0; i < count; i++) + { + unsigned feature_index = 0; + unsigned feature_count = 1; + l.get_feature_indexes (i, &feature_count, &feature_index); + if (!feature_count) + break; + hb_tag_t feature_tag = g.get_feature_tag (feature_index); + feature_map->set (feature_tag, feature_index); + } +} + /** * hb_ot_layout_collect_lookups: diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index b0fae3707..386b98d58 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -324,6 +324,13 @@ hb_ot_layout_collect_features (hb_face_t *face, const hb_tag_t *features, hb_set_t *feature_indexes /* OUT */); +HB_EXTERN void +hb_ot_layout_collect_features_map (hb_face_t *face, + hb_tag_t table_tag, + unsigned script_index, + unsigned language_index, + hb_map_t *feature_map /* OUT */); + HB_EXTERN void hb_ot_layout_collect_lookups (hb_face_t *face, hb_tag_t table_tag, diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index bacd56ef3..fac73eb34 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -239,6 +239,13 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, feature_infos.shrink (j + 1); } + hb_map_t feature_indices[2]; + for (unsigned int table_index = 0; table_index < 2; table_index++) + hb_ot_layout_collect_features_map (face, + table_tags[table_index], + script_index[table_index], + language_index[table_index], + &feature_indices[table_index]); /* Allocate bits now */ static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), ""); @@ -261,7 +268,6 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, if (!info->max_value || next_bit + bits_needed >= global_bit_shift) continue; /* Feature disabled, or not enough bits. */ - bool found = false; unsigned int feature_index[2]; for (unsigned int table_index = 0; table_index < 2; table_index++) @@ -269,12 +275,14 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, if (required_feature_tag[table_index] == info->tag) required_feature_stage[table_index] = info->stage[table_index]; - found |= (bool) 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]); + hb_codepoint_t *index; + if (feature_indices[table_index].has (info->tag, &index)) + { + feature_index[table_index] = *index; + found = true; + } + else + feature_index[table_index] = HB_OT_LAYOUT_NO_FEATURE_INDEX; } if (!found && (info->flags & F_GLOBAL_SEARCH)) {