[featureVars] Process lookups for features other than rvrn last

Fixes https://github.com/fonttools/fonttools/issues/3097
This commit is contained in:
Behdad Esfahbod 2023-05-01 11:36:39 -06:00
parent f026853cb2
commit 5b96fff9ce
2 changed files with 56 additions and 31 deletions

View File

@ -14,7 +14,9 @@ from collections import OrderedDict
from .errors import VarLibError, VarLibValidationError from .errors import VarLibError, VarLibValidationError
def addFeatureVariations(font, conditionalSubstitutions, featureTag="rvrn"): def addFeatureVariations(
font, conditionalSubstitutions, featureTag="rvrn", processLast=None
):
"""Add conditional substitutions to a Variable Font. """Add conditional substitutions to a Variable Font.
The `conditionalSubstitutions` argument is a list of (Region, Substitutions) The `conditionalSubstitutions` argument is a list of (Region, Substitutions)
@ -45,6 +47,9 @@ def addFeatureVariations(font, conditionalSubstitutions, featureTag="rvrn"):
# >>> f.save(dstPath) # >>> f.save(dstPath)
""" """
if processLast is None:
processLast = featureTag != "rvrn"
_checkSubstitutionGlyphsExist( _checkSubstitutionGlyphsExist(
glyphNames=set(font.getGlyphOrder()), glyphNames=set(font.getGlyphOrder()),
substitutions=conditionalSubstitutions, substitutions=conditionalSubstitutions,
@ -60,7 +65,9 @@ def addFeatureVariations(font, conditionalSubstitutions, featureTag="rvrn"):
font["GSUB"] = buildGSUB() font["GSUB"] = buildGSUB()
# setup lookups # setup lookups
lookupMap = buildSubstitutionLookups(font["GSUB"].table, allSubstitutions) lookupMap = buildSubstitutionLookups(
font["GSUB"].table, allSubstitutions, processLast
)
# addFeatureVariationsRaw takes a list of # addFeatureVariationsRaw takes a list of
# ( {condition}, [ lookup indices ] ) # ( {condition}, [ lookup indices ] )
@ -71,7 +78,9 @@ def addFeatureVariations(font, conditionalSubstitutions, featureTag="rvrn"):
(conditionSet, [lookupMap[s] for s in substitutions]) (conditionSet, [lookupMap[s] for s in substitutions])
) )
addFeatureVariationsRaw(font, font["GSUB"].table, conditionsAndLookups, featureTag) addFeatureVariationsRaw(
font, font["GSUB"].table, conditionsAndLookups, featureTag, processLast
)
def _checkSubstitutionGlyphsExist(glyphNames, substitutions): def _checkSubstitutionGlyphsExist(glyphNames, substitutions):
@ -316,10 +325,15 @@ def cleanupBox(box):
# #
def addFeatureVariationsRaw(font, table, conditionalSubstitutions, featureTag="rvrn"): def addFeatureVariationsRaw(
font, table, conditionalSubstitutions, featureTag="rvrn", processLast=None
):
"""Low level implementation of addFeatureVariations that directly """Low level implementation of addFeatureVariations that directly
models the possibilities of the FeatureVariations table.""" models the possibilities of the FeatureVariations table."""
if processLast is None:
processLast = featureTag != "rvrn"
# #
# if there is no <featureTag> feature: # if there is no <featureTag> feature:
# make empty <featureTag> feature # make empty <featureTag> feature
@ -378,9 +392,15 @@ def addFeatureVariationsRaw(font, table, conditionalSubstitutions, featureTag="r
existingLookupIndices = table.FeatureList.FeatureRecord[ existingLookupIndices = table.FeatureList.FeatureRecord[
varFeatureIndex varFeatureIndex
].Feature.LookupListIndex ].Feature.LookupListIndex
combinedLookupIndices = (
existingLookupIndices + lookupIndices
if processLast
else lookupIndices + existingLookupIndices
)
records.append( records.append(
buildFeatureTableSubstitutionRecord( buildFeatureTableSubstitutionRecord(
varFeatureIndex, lookupIndices + existingLookupIndices varFeatureIndex, combinedLookupIndices
) )
) )
featureVariationRecords.append( featureVariationRecords.append(
@ -463,27 +483,32 @@ def visit(visitor, obj, attr, value):
setattr(obj, attr, visitor.shift + value) setattr(obj, attr, visitor.shift + value)
def buildSubstitutionLookups(gsub, allSubstitutions): def buildSubstitutionLookups(gsub, allSubstitutions, processLast=False):
"""Build the lookups for the glyph substitutions, return a dict mapping """Build the lookups for the glyph substitutions, return a dict mapping
the substitution to lookup indices.""" the substitution to lookup indices."""
# Insert lookups at the beginning of the lookup vector # Insert lookups at the beginning of the lookup vector
# https://github.com/googlefonts/fontmake/issues/950 # https://github.com/googlefonts/fontmake/issues/950
firstIndex = len(gsub.LookupList.Lookup) if processLast else 0
lookupMap = {} lookupMap = {}
for i, substitutionMap in enumerate(allSubstitutions): for i, substitutionMap in enumerate(allSubstitutions):
lookupMap[substitutionMap] = i lookupMap[substitutionMap] = firstIndex + i
# Shift all lookup indices in gsub by len(allSubstitutions) if not processLast:
shift = len(allSubstitutions) # Shift all lookup indices in gsub by len(allSubstitutions)
visitor = ShifterVisitor(shift) shift = len(allSubstitutions)
visitor.visit(gsub.FeatureList.FeatureRecord) visitor = ShifterVisitor(shift)
visitor.visit(gsub.LookupList.Lookup) visitor.visit(gsub.FeatureList.FeatureRecord)
visitor.visit(gsub.LookupList.Lookup)
for i, subst in enumerate(allSubstitutions): for i, subst in enumerate(allSubstitutions):
substMap = dict(subst) substMap = dict(subst)
lookup = buildLookup([buildSingleSubstSubtable(substMap)]) lookup = buildLookup([buildSingleSubstSubtable(substMap)])
gsub.LookupList.Lookup.insert(i, lookup) if processLast:
gsub.LookupList.Lookup.append(lookup)
else:
gsub.LookupList.Lookup.insert(i, lookup)
assert gsub.LookupList.Lookup[lookupMap[subst]] is lookup assert gsub.LookupList.Lookup[lookupMap[subst]] is lookup
gsub.LookupList.LookupCount = len(gsub.LookupList.Lookup) gsub.LookupList.LookupCount = len(gsub.LookupList.Lookup)
return lookupMap return lookupMap

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.38"> <ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.39">
<fvar> <fvar>
@ -54,14 +54,14 @@
<FeatureTag value="rclt"/> <FeatureTag value="rclt"/>
<Feature> <Feature>
<!-- LookupCount=1 --> <!-- LookupCount=1 -->
<LookupListIndex index="0" value="3"/> <LookupListIndex index="0" value="0"/>
</Feature> </Feature>
</FeatureRecord> </FeatureRecord>
<FeatureRecord index="1"> <FeatureRecord index="1">
<FeatureTag value="rclt"/> <FeatureTag value="rclt"/>
<Feature> <Feature>
<!-- LookupCount=1 --> <!-- LookupCount=1 -->
<LookupListIndex index="0" value="4"/> <LookupListIndex index="0" value="1"/>
</Feature> </Feature>
</FeatureRecord> </FeatureRecord>
</FeatureList> </FeatureList>
@ -72,7 +72,7 @@
<LookupFlag value="0"/> <LookupFlag value="0"/>
<!-- SubTableCount=1 --> <!-- SubTableCount=1 -->
<SingleSubst index="0"> <SingleSubst index="0">
<Substitution in="uni0024" out="uni0024.nostroke"/> <Substitution in="uni0041" out="uni0061"/>
</SingleSubst> </SingleSubst>
</Lookup> </Lookup>
<Lookup index="1"> <Lookup index="1">
@ -88,7 +88,7 @@
<LookupFlag value="0"/> <LookupFlag value="0"/>
<!-- SubTableCount=1 --> <!-- SubTableCount=1 -->
<SingleSubst index="0"> <SingleSubst index="0">
<Substitution in="uni0061" out="uni0041"/> <Substitution in="uni0024" out="uni0024.nostroke"/>
</SingleSubst> </SingleSubst>
</Lookup> </Lookup>
<Lookup index="3"> <Lookup index="3">
@ -104,7 +104,7 @@
<LookupFlag value="0"/> <LookupFlag value="0"/>
<!-- SubTableCount=1 --> <!-- SubTableCount=1 -->
<SingleSubst index="0"> <SingleSubst index="0">
<Substitution in="uni0041" out="uni0061"/> <Substitution in="uni0061" out="uni0041"/>
</SingleSubst> </SingleSubst>
</Lookup> </Lookup>
</LookupList> </LookupList>
@ -133,7 +133,7 @@
<Feature> <Feature>
<!-- LookupCount=3 --> <!-- LookupCount=3 -->
<LookupListIndex index="0" value="0"/> <LookupListIndex index="0" value="0"/>
<LookupListIndex index="1" value="1"/> <LookupListIndex index="1" value="2"/>
<LookupListIndex index="2" value="3"/> <LookupListIndex index="2" value="3"/>
</Feature> </Feature>
</SubstitutionRecord> </SubstitutionRecord>
@ -141,9 +141,9 @@
<FeatureIndex value="1"/> <FeatureIndex value="1"/>
<Feature> <Feature>
<!-- LookupCount=3 --> <!-- LookupCount=3 -->
<LookupListIndex index="0" value="0"/> <LookupListIndex index="0" value="1"/>
<LookupListIndex index="1" value="1"/> <LookupListIndex index="1" value="2"/>
<LookupListIndex index="2" value="4"/> <LookupListIndex index="2" value="3"/>
</Feature> </Feature>
</SubstitutionRecord> </SubstitutionRecord>
</FeatureTableSubstitution> </FeatureTableSubstitution>
@ -169,15 +169,15 @@
<FeatureIndex value="0"/> <FeatureIndex value="0"/>
<Feature> <Feature>
<!-- LookupCount=2 --> <!-- LookupCount=2 -->
<LookupListIndex index="0" value="2"/> <LookupListIndex index="0" value="0"/>
<LookupListIndex index="1" value="3"/> <LookupListIndex index="1" value="4"/>
</Feature> </Feature>
</SubstitutionRecord> </SubstitutionRecord>
<SubstitutionRecord index="1"> <SubstitutionRecord index="1">
<FeatureIndex value="1"/> <FeatureIndex value="1"/>
<Feature> <Feature>
<!-- LookupCount=2 --> <!-- LookupCount=2 -->
<LookupListIndex index="0" value="2"/> <LookupListIndex index="0" value="1"/>
<LookupListIndex index="1" value="4"/> <LookupListIndex index="1" value="4"/>
</Feature> </Feature>
</SubstitutionRecord> </SubstitutionRecord>
@ -199,7 +199,7 @@
<FeatureIndex value="0"/> <FeatureIndex value="0"/>
<Feature> <Feature>
<!-- LookupCount=2 --> <!-- LookupCount=2 -->
<LookupListIndex index="0" value="1"/> <LookupListIndex index="0" value="0"/>
<LookupListIndex index="1" value="3"/> <LookupListIndex index="1" value="3"/>
</Feature> </Feature>
</SubstitutionRecord> </SubstitutionRecord>
@ -208,7 +208,7 @@
<Feature> <Feature>
<!-- LookupCount=2 --> <!-- LookupCount=2 -->
<LookupListIndex index="0" value="1"/> <LookupListIndex index="0" value="1"/>
<LookupListIndex index="1" value="4"/> <LookupListIndex index="1" value="3"/>
</Feature> </Feature>
</SubstitutionRecord> </SubstitutionRecord>
</FeatureTableSubstitution> </FeatureTableSubstitution>
@ -230,15 +230,15 @@
<Feature> <Feature>
<!-- LookupCount=2 --> <!-- LookupCount=2 -->
<LookupListIndex index="0" value="0"/> <LookupListIndex index="0" value="0"/>
<LookupListIndex index="1" value="3"/> <LookupListIndex index="1" value="2"/>
</Feature> </Feature>
</SubstitutionRecord> </SubstitutionRecord>
<SubstitutionRecord index="1"> <SubstitutionRecord index="1">
<FeatureIndex value="1"/> <FeatureIndex value="1"/>
<Feature> <Feature>
<!-- LookupCount=2 --> <!-- LookupCount=2 -->
<LookupListIndex index="0" value="0"/> <LookupListIndex index="0" value="1"/>
<LookupListIndex index="1" value="4"/> <LookupListIndex index="1" value="2"/>
</Feature> </Feature>
</SubstitutionRecord> </SubstitutionRecord>
</FeatureTableSubstitution> </FeatureTableSubstitution>