[subset] Support GSUB/GPOS.FeatureVariations
We should add a test using the font at: https://github.com/behdad/harfbuzz/issues/521 Test with: $ fonttools subset avar_rvrn.ttf --text=r
This commit is contained in:
parent
b2e9882b30
commit
fe01d87b94
@ -1183,8 +1183,7 @@ def subset_lookups(self, lookup_indices):
|
|||||||
|
|
||||||
@_add_method(otTables.Lookup)
|
@_add_method(otTables.Lookup)
|
||||||
def collect_lookups(self):
|
def collect_lookups(self):
|
||||||
return _uniq_sort(sum((st.collect_lookups() for st in self.SubTable
|
return sum((st.collect_lookups() for st in self.SubTable if st), [])
|
||||||
if st), []))
|
|
||||||
|
|
||||||
@_add_method(otTables.Lookup)
|
@_add_method(otTables.Lookup)
|
||||||
def may_have_non_1to1(self):
|
def may_have_non_1to1(self):
|
||||||
@ -1220,6 +1219,7 @@ def neuter_lookups(self, lookup_indices):
|
|||||||
|
|
||||||
@_add_method(otTables.LookupList)
|
@_add_method(otTables.LookupList)
|
||||||
def closure_lookups(self, lookup_indices):
|
def closure_lookups(self, lookup_indices):
|
||||||
|
"""Returns sorted index of all lookups reachable from lookup_indices."""
|
||||||
lookup_indices = _uniq_sort(lookup_indices)
|
lookup_indices = _uniq_sort(lookup_indices)
|
||||||
recurse = lookup_indices
|
recurse = lookup_indices
|
||||||
while True:
|
while True:
|
||||||
@ -1235,6 +1235,7 @@ def closure_lookups(self, lookup_indices):
|
|||||||
|
|
||||||
@_add_method(otTables.Feature)
|
@_add_method(otTables.Feature)
|
||||||
def subset_lookups(self, lookup_indices):
|
def subset_lookups(self, lookup_indices):
|
||||||
|
""""Returns True if feature is non-empty afterwards."""
|
||||||
self.LookupListIndex = [l for l in self.LookupListIndex
|
self.LookupListIndex = [l for l in self.LookupListIndex
|
||||||
if l in lookup_indices]
|
if l in lookup_indices]
|
||||||
# Now map them.
|
# Now map them.
|
||||||
@ -1243,10 +1244,6 @@ def subset_lookups(self, lookup_indices):
|
|||||||
self.LookupCount = len(self.LookupListIndex)
|
self.LookupCount = len(self.LookupListIndex)
|
||||||
return self.LookupCount or self.FeatureParams
|
return self.LookupCount or self.FeatureParams
|
||||||
|
|
||||||
@_add_method(otTables.Feature)
|
|
||||||
def collect_lookups(self):
|
|
||||||
return self.LookupListIndex[:]
|
|
||||||
|
|
||||||
@_add_method(otTables.FeatureList)
|
@_add_method(otTables.FeatureList)
|
||||||
def subset_lookups(self, lookup_indices):
|
def subset_lookups(self, lookup_indices):
|
||||||
"""Returns the indices of nonempty features."""
|
"""Returns the indices of nonempty features."""
|
||||||
@ -1254,17 +1251,15 @@ def subset_lookups(self, lookup_indices):
|
|||||||
# HarfBuzz chooses shaper for Khmer based on presence of this
|
# HarfBuzz chooses shaper for Khmer based on presence of this
|
||||||
# feature. See thread at:
|
# feature. See thread at:
|
||||||
# http://lists.freedesktop.org/archives/harfbuzz/2012-November/002660.html
|
# http://lists.freedesktop.org/archives/harfbuzz/2012-November/002660.html
|
||||||
feature_indices = [i for i,f in enumerate(self.FeatureRecord)
|
return [i for i,f in enumerate(self.FeatureRecord)
|
||||||
if (f.Feature.subset_lookups(lookup_indices) or
|
if (f.Feature.subset_lookups(lookup_indices) or
|
||||||
f.FeatureTag == 'pref')]
|
f.FeatureTag == 'pref')]
|
||||||
self.subset_features(feature_indices)
|
|
||||||
return feature_indices
|
|
||||||
|
|
||||||
@_add_method(otTables.FeatureList)
|
@_add_method(otTables.FeatureList)
|
||||||
def collect_lookups(self, feature_indices):
|
def collect_lookups(self, feature_indices):
|
||||||
return _uniq_sort(sum((self.FeatureRecord[i].Feature.collect_lookups()
|
return sum((self.FeatureRecord[i].Feature.LookupListIndex
|
||||||
for i in feature_indices
|
for i in feature_indices
|
||||||
if i < self.FeatureCount), []))
|
if i < self.FeatureCount), [])
|
||||||
|
|
||||||
@_add_method(otTables.FeatureList)
|
@_add_method(otTables.FeatureList)
|
||||||
def subset_features(self, feature_indices):
|
def subset_features(self, feature_indices):
|
||||||
@ -1273,6 +1268,41 @@ def subset_features(self, feature_indices):
|
|||||||
self.FeatureCount = len(self.FeatureRecord)
|
self.FeatureCount = len(self.FeatureRecord)
|
||||||
return bool(self.FeatureCount)
|
return bool(self.FeatureCount)
|
||||||
|
|
||||||
|
@_add_method(otTables.FeatureTableSubstitution)
|
||||||
|
def subset_lookups(self, lookup_indices):
|
||||||
|
"""Returns the indices of nonempty features."""
|
||||||
|
return [r.FeatureIndex for r in self.SubstitutionRecord
|
||||||
|
if r.Feature.subset_lookups(lookup_indices)]
|
||||||
|
|
||||||
|
@_add_method(otTables.FeatureVariations)
|
||||||
|
def subset_lookups(self, lookup_indices):
|
||||||
|
"""Returns the indices of nonempty features."""
|
||||||
|
return sum((f.FeatureTableSubstitution.subset_lookups(lookup_indices)
|
||||||
|
for f in self.FeatureVariationRecord), [])
|
||||||
|
|
||||||
|
@_add_method(otTables.FeatureVariations)
|
||||||
|
def collect_lookups(self, feature_indices):
|
||||||
|
return sum((r.Feature.LookupListIndex
|
||||||
|
for vr in self.FeatureVariationRecord
|
||||||
|
for r in vr.FeatureTableSubstitution.SubstitutionRecord
|
||||||
|
if r.FeatureIndex in feature_indices), [])
|
||||||
|
|
||||||
|
@_add_method(otTables.FeatureTableSubstitution)
|
||||||
|
def subset_features(self, feature_indices):
|
||||||
|
self.ensureDecompiled()
|
||||||
|
self.SubstitutionRecord = [r for r in self.SubstitutionRecord
|
||||||
|
if r.FeatureIndex in feature_indices]
|
||||||
|
self.SubstitutionCount = len(self.SubstitutionRecord)
|
||||||
|
return bool(self.SubstitutionCount)
|
||||||
|
|
||||||
|
@_add_method(otTables.FeatureVariations)
|
||||||
|
def subset_features(self, feature_indices):
|
||||||
|
self.ensureDecompiled()
|
||||||
|
self.FeaturVariationRecord = [r for r in self.FeatureVariationRecord
|
||||||
|
if r.FeatureTableSubstitution.subset_features(feature_indices)]
|
||||||
|
self.FeatureVariationCount = len(self.FeatureVariationRecord)
|
||||||
|
return bool(self.FeatureVariationCount)
|
||||||
|
|
||||||
@_add_method(otTables.DefaultLangSys,
|
@_add_method(otTables.DefaultLangSys,
|
||||||
otTables.LangSys)
|
otTables.LangSys)
|
||||||
def subset_features(self, feature_indices):
|
def subset_features(self, feature_indices):
|
||||||
@ -1353,6 +1383,9 @@ def closure_glyphs(self, s):
|
|||||||
lookup_indices = self.table.FeatureList.collect_lookups(feature_indices)
|
lookup_indices = self.table.FeatureList.collect_lookups(feature_indices)
|
||||||
else:
|
else:
|
||||||
lookup_indices = []
|
lookup_indices = []
|
||||||
|
if getattr(self.table, 'FeatureVariations', None):
|
||||||
|
lookup_indices += self.table.FeatureVariations.collect_lookups(feature_indices)
|
||||||
|
lookup_indices = _uniq_sort(lookup_indices)
|
||||||
if self.table.LookupList:
|
if self.table.LookupList:
|
||||||
while True:
|
while True:
|
||||||
orig_glyphs = frozenset(s.glyphs)
|
orig_glyphs = frozenset(s.glyphs)
|
||||||
@ -1396,6 +1429,13 @@ def subset_lookups(self, lookup_indices):
|
|||||||
feature_indices = self.table.FeatureList.subset_lookups(lookup_indices)
|
feature_indices = self.table.FeatureList.subset_lookups(lookup_indices)
|
||||||
else:
|
else:
|
||||||
feature_indices = []
|
feature_indices = []
|
||||||
|
if getattr(self.table, 'FeatureVariations', None):
|
||||||
|
feature_indices += self.table.FeatureVariations.subset_lookups(lookup_indices)
|
||||||
|
feature_indices = _uniq_sort(feature_indices)
|
||||||
|
if self.table.FeatureList:
|
||||||
|
self.table.FeatureList.subset_features(feature_indices)
|
||||||
|
if getattr(self.table, 'FeatureVariations', None):
|
||||||
|
self.table.FeatureVariations.subset_features(feature_indices)
|
||||||
if self.table.ScriptList:
|
if self.table.ScriptList:
|
||||||
self.table.ScriptList.subset_features(feature_indices, self.retain_empty_scripts())
|
self.table.ScriptList.subset_features(feature_indices, self.retain_empty_scripts())
|
||||||
|
|
||||||
@ -1418,6 +1458,9 @@ def prune_lookups(self, remap=True):
|
|||||||
lookup_indices = self.table.FeatureList.collect_lookups(feature_indices)
|
lookup_indices = self.table.FeatureList.collect_lookups(feature_indices)
|
||||||
else:
|
else:
|
||||||
lookup_indices = []
|
lookup_indices = []
|
||||||
|
if getattr(self.table, 'FeatureVariations', None):
|
||||||
|
lookup_indices += self.table.FeatureVariations.collect_lookups(feature_indices)
|
||||||
|
lookup_indices = _uniq_sort(lookup_indices)
|
||||||
if self.table.LookupList:
|
if self.table.LookupList:
|
||||||
lookup_indices = self.table.LookupList.closure_lookups(lookup_indices)
|
lookup_indices = self.table.LookupList.closure_lookups(lookup_indices)
|
||||||
else:
|
else:
|
||||||
@ -1428,13 +1471,15 @@ def prune_lookups(self, remap=True):
|
|||||||
self.neuter_lookups(lookup_indices)
|
self.neuter_lookups(lookup_indices)
|
||||||
|
|
||||||
@_add_method(ttLib.getTableClass('GSUB'),
|
@_add_method(ttLib.getTableClass('GSUB'),
|
||||||
ttLib.getTableClass('GPOS'))
|
ttLib.getTableClass('GPOS'))
|
||||||
def subset_feature_tags(self, feature_tags):
|
def subset_feature_tags(self, feature_tags):
|
||||||
if self.table.FeatureList:
|
if self.table.FeatureList:
|
||||||
feature_indices = \
|
feature_indices = \
|
||||||
[i for i,f in enumerate(self.table.FeatureList.FeatureRecord)
|
[i for i,f in enumerate(self.table.FeatureList.FeatureRecord)
|
||||||
if f.FeatureTag in feature_tags]
|
if f.FeatureTag in feature_tags]
|
||||||
self.table.FeatureList.subset_features(feature_indices)
|
self.table.FeatureList.subset_features(feature_indices)
|
||||||
|
if getattr(self.table, 'FeatureVariations', None):
|
||||||
|
self.table.FeatureVariations.subset_features(feature_indices)
|
||||||
else:
|
else:
|
||||||
feature_indices = []
|
feature_indices = []
|
||||||
if self.table.ScriptList:
|
if self.table.ScriptList:
|
||||||
@ -1450,6 +1495,8 @@ def prune_features(self):
|
|||||||
feature_indices = []
|
feature_indices = []
|
||||||
if self.table.FeatureList:
|
if self.table.FeatureList:
|
||||||
self.table.FeatureList.subset_features(feature_indices)
|
self.table.FeatureList.subset_features(feature_indices)
|
||||||
|
if getattr(self.table, 'FeatureVariations', None):
|
||||||
|
self.table.FeatureVariations.subset_features(feature_indices)
|
||||||
if self.table.ScriptList:
|
if self.table.ScriptList:
|
||||||
self.table.ScriptList.subset_features(feature_indices, self.retain_empty_scripts())
|
self.table.ScriptList.subset_features(feature_indices, self.retain_empty_scripts())
|
||||||
|
|
||||||
@ -1512,6 +1559,7 @@ def prune_post_subset(self, options):
|
|||||||
if not table.LookupList:
|
if not table.LookupList:
|
||||||
table.FeatureList = None
|
table.FeatureList = None
|
||||||
|
|
||||||
|
|
||||||
if table.FeatureList:
|
if table.FeatureList:
|
||||||
self.remove_redundant_langsys()
|
self.remove_redundant_langsys()
|
||||||
# Remove unreferenced features
|
# Remove unreferenced features
|
||||||
@ -1529,6 +1577,13 @@ def prune_post_subset(self, options):
|
|||||||
#if table.ScriptList and not table.ScriptList.ScriptRecord:
|
#if table.ScriptList and not table.ScriptList.ScriptRecord:
|
||||||
# table.ScriptList = None
|
# table.ScriptList = None
|
||||||
|
|
||||||
|
if not table.FeatureList and hasattr(table, 'FeatureVariations'):
|
||||||
|
table.FeatureVariations = None
|
||||||
|
|
||||||
|
if hasattr(table, 'FeatureVariations') and not table.FeatureVariations:
|
||||||
|
if table.Version == 0x00010001:
|
||||||
|
table.Version = 0x00010000
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@_add_method(ttLib.getTableClass('GDEF'))
|
@_add_method(ttLib.getTableClass('GDEF'))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user