[subset] Don't assume FeatureList is sorted

Though the spec said FeatureRecords are sorted alphabetically by feature
tag, there're font files with unsorted FeatureList. And harfbuzz is not
able to subset these files correctly because we use binary search in
finding featureRecords when collecting lookups. Also
find_duplicate_features needs to be updated to handle this.
pull/3281/head
Qunxin Liu 3 years ago committed by Behdad Esfahbod
parent 49c9392412
commit 364b6b3989
  1. 28
      src/hb-ot-layout-gsubgpos.hh
  2. 21
      src/hb-ot-layout.cc
  3. 1
      test/subset/data/Makefile.am
  4. 1
      test/subset/data/Makefile.sources
  5. BIN
      test/subset/data/expected/layout.unsorted_featurelist/NotoIKEAHebrewLatin-Regular.default.392,3a7,3b2,3c7.ttf
  6. BIN
      test/subset/data/expected/layout.unsorted_featurelist/NotoIKEAHebrewLatin-Regular.default.retain-all-codepoint.ttf
  7. BIN
      test/subset/data/expected/layout.unsorted_featurelist/NotoIKEAHebrewLatin-Regular.layout-test.392,3a7,3b2,3c7.ttf
  8. BIN
      test/subset/data/expected/layout.unsorted_featurelist/NotoIKEAHebrewLatin-Regular.layout-test.retain-all-codepoint.ttf
  9. BIN
      test/subset/data/expected/layout.unsorted_featurelist/NotoIKEAHebrewLatin-Regular.retain-gids.392,3a7,3b2,3c7.ttf
  10. BIN
      test/subset/data/expected/layout.unsorted_featurelist/NotoIKEAHebrewLatin-Regular.retain-gids.retain-all-codepoint.ttf
  11. BIN
      test/subset/data/fonts/NotoIKEAHebrewLatin-Regular.ttf
  12. 11
      test/subset/data/tests/layout.unsorted_featurelist.tests
  13. 1
      test/subset/meson.build

@ -3658,24 +3658,33 @@ struct GSUBGPOS
const hb_set_t *feature_indices,
hb_map_t *duplicate_feature_map /* OUT */) const
{
hb_set_t unique_features;
hb_tag_t prev_t = get_feature_tag (feature_indices->get_min ());
if (feature_indices->is_empty ()) return;
hb_hashmap_t<hb_tag_t, hb_set_t *, (unsigned)-1, nullptr> unique_features;
//find out duplicate features after subset
for (unsigned i : feature_indices->iter ())
{
hb_tag_t t = get_feature_tag (i);
if (t != prev_t)
if (!unique_features.has (t))
{
prev_t = t;
unique_features.clear ();
unique_features.add (i);
hb_set_t* indices = hb_set_create ();
if (unlikely (indices == hb_set_get_empty () ||
!unique_features.set (t, indices)))
{
hb_set_destroy (indices);
for (auto _ : unique_features.iter ())
hb_set_destroy (_.second);
return;
}
if (unique_features.get (t))
unique_features.get (t)->add (i);
duplicate_feature_map->set (i, i);
continue;
}
bool found = false;
for (unsigned other_f_index : unique_features.iter ())
hb_set_t* same_tag_features = unique_features.get (t);
for (unsigned other_f_index : same_tag_features->iter ())
{
const Feature& f = get_feature (i);
const Feature& other_f = get_feature (other_f_index);
@ -3707,10 +3716,13 @@ struct GSUBGPOS
if (found == false)
{
unique_features.add (i);
same_tag_features->add (i);
duplicate_feature_map->set (i, i);
}
}
for (auto _ : unique_features.iter ())
hb_set_destroy (_.second);
}
void prune_features (const hb_map_t *lookup_indices, /* IN */

@ -1013,24 +1013,15 @@ struct hb_collect_features_context_t
}
has_feature_filter = true;
hb_set_t features_set;
for (; *features; features++)
features_set.add (*features);
for (unsigned i = 0; i < g.get_feature_count (); i++)
{
hb_tag_t tag = *features;
unsigned index;
g.find_feature_index (tag, &index);
if (index == OT::Index::NOT_FOUND_INDEX) continue;
feature_indices_filter.add(index);
for (int i = (int) index - 1; i >= 0; i--)
{
if (g.get_feature_tag (i) != tag) break;
feature_indices_filter.add(i);
}
for (unsigned i = index + 1; i < g.get_feature_count (); i++)
{
if (g.get_feature_tag (i) != tag) break;
hb_tag_t tag = g.get_feature_tag (i);
if (features_set.has (tag))
feature_indices_filter.add(i);
}
}
}

@ -36,6 +36,7 @@ EXTRA_DIST += \
expected/layout.notonastaliqurdu \
expected/layout.tinos \
expected/layout.duplicate_features \
expected/layout.unsorted_featurelist \
expected/cmap \
expected/cmap14 \
expected/sbix \

@ -34,6 +34,7 @@ TESTS = \
tests/layout.tests \
tests/layout.tinos.tests \
tests/layout.duplicate_features.tests \
tests/layout.unsorted_featurelist.tests \
tests/sbix.tests \
tests/variable.tests \
tests/glyph_names.tests \

@ -0,0 +1,11 @@
FONTS:
NotoIKEAHebrewLatin-Regular.ttf
PROFILES:
layout-test.txt
default.txt
retain-gids.txt
SUBSETS:
U+392,U+3a7,U+3b2,U+3c7
*

@ -28,6 +28,7 @@ tests = [
'layout.notonastaliqurdu',
'layout.tinos',
'layout.duplicate_features',
'layout.unsorted_featurelist',
'cmap',
'cmap14',
'sbix',

Loading…
Cancel
Save