From 1bf051ef3bafe2d6c24983863dc3bf2f04505b3c Mon Sep 17 00:00:00 2001 From: Garret Rieger Date: Thu, 30 Jun 2022 20:03:33 +0000 Subject: [PATCH] [subset] refactor feature tag filtering so it can be used for scripts as well. --- src/hb-subset-plan.cc | 72 +++++++++++++++++++++++++++---------------- src/hb-subset-plan.hh | 3 ++ 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 4e3bb1d47..560355b3a 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -91,6 +91,38 @@ _remap_indexes (const hb_set_t *indexes, typedef void (*layout_collect_func_t) (hb_face_t *face, hb_tag_t table_tag, const hb_tag_t *scripts, const hb_tag_t *languages, const hb_tag_t *features, hb_set_t *lookup_indexes /* OUT */); +/** + * Removes all tags from 'tags' that are not in filter. Additionally eliminates any duplicates. + * Returns true if anything was removed (not including duplicates). + */ +static bool _filter_tag_list(hb_vector_t* tags, /* IN/OUT */ + const hb_set_t* filter) +{ + hb_vector_t out; + out.alloc (tags->get_size()); + + bool removed = false; + hb_set_t visited; + + for (hb_tag_t tag : *tags) + { + if (!tag) continue; + if (visited.has (tag)) continue; + + if (!filter->has (tag)) + { + removed = true; + continue; + } + + visited.add (tag); + out.push (tag); + } + + hb_swap (out, *tags); + return removed; +} + template static void _collect_layout_indices (hb_face_t *face, const T& table, @@ -98,35 +130,18 @@ static void _collect_layout_indices (hb_face_t *face, layout_collect_func_t layout_collect_func, hb_set_t *indices /* OUT */) { + unsigned num_features = table.get_feature_count () + 1; hb_vector_t features; - if (!features.alloc (table.get_feature_count () + 1)) + // TODO(garretrieger): propagate error to plan + if (!features.resize (num_features)) return; + table.get_feature_tags (0, &num_features, features.arrayZ); + features.resize (num_features); + bool retain_all_features = !_filter_tag_list (&features, layout_features_to_retain); + + // TODO(garretrieger): propagate error to plan + if (features.in_error () || !features) return; - hb_set_t visited_features; - bool retain_all_features = true; - for (unsigned i = 0; i < table.get_feature_count (); i++) - { - hb_tag_t tag = table.get_feature_tag (i); - if (!tag) continue; - if (!layout_features_to_retain->has (tag)) - { - retain_all_features = false; - continue; - } - - if (visited_features.has (tag)) - continue; - - features.push (tag); - visited_features.add (tag); - } - - if (!features) - return; - - // The collect function needs a null element to signal end of the array. - features.push (0); - if (retain_all_features) { // Looking for all features, trigger the faster collection method. @@ -139,6 +154,8 @@ static void _collect_layout_indices (hb_face_t *face, return; } + // The collect function needs a null element to signal end of the array. + features.push (0); layout_collect_func (face, T::tableTag, nullptr, @@ -549,6 +566,8 @@ hb_subset_plan_create_or_fail (hb_face_t *face, _nameid_closure (face, plan->name_ids); plan->name_languages = hb_set_copy (input->sets.name_languages); plan->layout_features = hb_set_copy (input->sets.layout_features); + plan->layout_scripts = hb_set_create (); + hb_set_invert (plan->layout_scripts); plan->glyphs_requested = hb_set_copy (input->sets.glyphs); plan->drop_tables = hb_set_copy (input->sets.drop_tables); plan->no_subset_tables = hb_set_copy (input->sets.no_subset_tables); @@ -636,6 +655,7 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan) hb_set_destroy (plan->name_ids); hb_set_destroy (plan->name_languages); hb_set_destroy (plan->layout_features); + hb_set_destroy (plan->layout_scripts); hb_set_destroy (plan->glyphs_requested); hb_set_destroy (plan->drop_tables); hb_set_destroy (plan->no_subset_tables); diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh index 2aaf19c61..830c8b9c2 100644 --- a/src/hb-subset-plan.hh +++ b/src/hb-subset-plan.hh @@ -55,6 +55,9 @@ struct hb_subset_plan_t //layout features which will be preserved hb_set_t *layout_features; + // layout scripts which will be preserved. + hb_set_t *layout_scripts; + //glyph ids requested to retain hb_set_t *glyphs_requested;