Skip to content

Commit

Permalink
Support building feature variations using the "condition" statement.
Browse files Browse the repository at this point in the history
  • Loading branch information
simoncozens committed May 24, 2021
1 parent 91cee05 commit 7a69fb1
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 3 deletions.
2 changes: 2 additions & 0 deletions Lib/fontTools/feaLib/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -2084,6 +2084,8 @@ def build(self, builder):
for key, value in builder.features_.items():
items = builder.feature_variations_.setdefault(key,{}).setdefault(self.conditionset,[])
items.extend(value)
if key not in features:
features[key] = [] # Ensure we make a feature record
builder.features_ = features
builder.end_feature()

Expand Down
44 changes: 42 additions & 2 deletions Lib/fontTools/feaLib/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from fontTools.otlLib.error import OpenTypeLibError
from fontTools.varLib.varStore import OnlineVarStoreBuilder
from fontTools.varLib.builder import buildVarDevTable
from fontTools.varLib.featureVars import addFeatureVariationsRaw
from fontTools.varLib.models import normalizeValue
from collections import defaultdict
import itertools
Expand Down Expand Up @@ -211,6 +212,8 @@ def build(self, tables=None, debug=False):
if tag not in tables:
continue
table = self.makeTable(tag)
if self.feature_variations_:
self.makeFeatureVariations(table, tag)
if (
table.ScriptList.ScriptCount > 0
or table.FeatureList.FeatureCount > 0
Expand Down Expand Up @@ -874,7 +877,8 @@ def makeTable(self, tag):
)

size_feature = tag == "GPOS" and feature_tag == "size"
if len(lookup_indices) == 0 and not size_feature:
force_feature = self.any_feature_variations(feature_tag, tag)
if len(lookup_indices) == 0 and not size_feature and not force_feature:
continue

for ix in lookup_indices:
Expand Down Expand Up @@ -940,6 +944,42 @@ def makeTable(self, tag):
table.LookupList.LookupCount = len(table.LookupList.Lookup)
return table

def makeFeatureVariations(self, table, table_tag):
feature_vars = {}
has_any_variations = False
# Sort out which lookups to build, gather their indices
for (
script_,
language,
feature_tag,
), variations in self.feature_variations_.items():
feature_vars[feature_tag] = []
for conditionset, builders in variations.items():
raw_conditionset = self.conditionsets_[conditionset]
indices = []
for b in builders:
if b.table != table_tag:
continue
assert b.lookup_index is not None
indices.append(b.lookup_index)
has_any_variations = True
feature_vars[feature_tag].append((raw_conditionset, indices))

if has_any_variations:
for feature_tag, conditions_and_lookups in feature_vars.items():
addFeatureVariationsRaw(
self.font, table, conditions_and_lookups, feature_tag
)

def any_feature_variations(self, feature_tag, table_tag):
for (_, _, feature), variations in self.feature_variations_.items():
if feature != feature_tag:
continue
for conditionset, builders in variations.items():
if any(b.table == table_tag for b in builders):
return True
return False

def get_lookup_name_(self, lookup):
rev = {v: k for k, v in self.named_lookups_.items()}
if lookup in rev:
Expand Down Expand Up @@ -1480,7 +1520,7 @@ def add_conditionset(self, key, value):
# Normalize
axisMap = {
axis.axisTag: (axis.minValue, axis.defaultValue, axis.maxValue)
for axis in self.font["fvar"].axes
for axis in self.axes
}

value = {
Expand Down
2 changes: 1 addition & 1 deletion Tests/feaLib/builder_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class BuilderTest(unittest.TestCase):
SingleSubstSubtable aalt_chain_contextual_subst AlternateChained
MultipleLookupsPerGlyph MultipleLookupsPerGlyph2 GSUB_6_formats
GSUB_5_formats delete_glyph STAT_test STAT_test_elidedFallbackNameID
variable_scalar_valuerecord variable_scalar_anchor
variable_scalar_valuerecord variable_scalar_anchor variable_conditionset
""".split()

VARFONT_AXES = [
Expand Down
13 changes: 13 additions & 0 deletions Tests/feaLib/data/variable_conditionset.fea
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
languagesystem DFLT dflt;

lookup symbols_heavy {
sub a by b;
} symbols_heavy;

conditionset heavy {
wght 700 900;
} heavy;

variation rvrn heavy {
lookup symbols_heavy;
} rvrn;
63 changes: 63 additions & 0 deletions Tests/feaLib/data/variable_conditionset.ttx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<ttFont>

<GSUB>
<Version value="0x00010001"/>
<ScriptList>
<!-- ScriptCount=1 -->
<ScriptRecord index="0">
<ScriptTag value="DFLT"/>
<Script>
<DefaultLangSys>
<ReqFeatureIndex value="65535"/>
<!-- FeatureCount=1 -->
<FeatureIndex index="0" value="0"/>
</DefaultLangSys>
<!-- LangSysCount=0 -->
</Script>
</ScriptRecord>
</ScriptList>
<FeatureList>
<!-- FeatureCount=1 -->
<FeatureRecord index="0">
<FeatureTag value="rvrn"/>
<Feature>
<!-- LookupCount=0 -->
</Feature>
</FeatureRecord>
</FeatureList>
<LookupList>
<!-- LookupCount=1 -->
<Lookup index="0">
<LookupType value="1"/>
<LookupFlag value="0"/>
<!-- SubTableCount=1 -->
<SingleSubst index="0">
<Substitution in="a" out="b"/>
</SingleSubst>
</Lookup>
</LookupList>
<FeatureVariations>
<Version value="0x00010000"/>
<FeatureVariationRecord index="0">
<ConditionSet>
<ConditionTable index="0" Format="1">
<AxisIndex value="0"/>
<FilterRangeMinValue value="0.625"/>
<FilterRangeMaxValue value="0.875"/>
</ConditionTable>
</ConditionSet>
<FeatureTableSubstitution>
<Version value="0x00010000"/>
<SubstitutionRecord index="0">
<FeatureIndex value="0"/>
<Feature>
<LookupListIndex index="0" value="0"/>
</Feature>
</SubstitutionRecord>
</FeatureTableSubstitution>
</FeatureVariationRecord>
</FeatureVariations>
</GSUB>

</ttFont>

0 comments on commit 7a69fb1

Please sign in to comment.