[subset] refactor feature tag filtering so it can be used for scripts as well.

This commit is contained in:
Garret Rieger 2022-06-30 20:03:33 +00:00
parent c69ec6f5bb
commit 1bf051ef3b
2 changed files with 49 additions and 26 deletions

View File

@ -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<hb_tag_t>* tags, /* IN/OUT */
const hb_set_t* filter)
{
hb_vector_t<hb_tag_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 <typename T>
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<hb_tag_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);

View File

@ -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;