[feaLib] Merge SingleSubst chain targets
This makes the output of feaLib more compact, using a similar technique as seems to be used by makeotf. After this change, feaLib generates output that more similar to makeotf: * For the test cases in `bug512.fea` and `bug463.fea`, feaLib now generates the exact same output as makeotf v2.0.90. * For the test cases in `GSUB_6.fea`, it is hard to say because makeotf crashes on the test file; our test contains language constructs that are valid according to the spec, but didn't yet get implemented by makeotf. When commenting out those constructs, feaLib generates the exact same output as makeotf v2.0.90. * For the test cases in `feature_aalt.fea`, the output of feaLib is now structually the same as the output of makeotf v2.0.90. However, two lookups are in different order. feaLib's ordering reflects the order of statements in the compiled input source; no idea why makeotf would want to reverse the ordering. Since this ordering difference only affects the _targets_ of chain substitutions, there is no semantic difference. Resolves https://github.com/behdad/fonttools/issues/512.
This commit is contained in:
parent
1ddfe24338
commit
ec9077a566
@ -555,11 +555,7 @@ class Builder(object):
|
||||
alts.add(to_glyph)
|
||||
return
|
||||
if prefix or suffix or forceChain:
|
||||
chain = self.get_lookup_(location, ChainContextSubstBuilder)
|
||||
sub = self.get_chained_lookup_(location, SingleSubstBuilder)
|
||||
sub.mapping.update(mapping)
|
||||
chain.substitutions.append(
|
||||
(prefix, [mapping.keys()], suffix, [sub]))
|
||||
self.add_single_subst_chained_(location, prefix, suffix, mapping)
|
||||
return
|
||||
lookup = self.get_lookup_(location, SingleSubstBuilder)
|
||||
for (from_glyph, to_glyph) in mapping.items():
|
||||
@ -570,6 +566,24 @@ class Builder(object):
|
||||
location)
|
||||
lookup.mapping[from_glyph] = to_glyph
|
||||
|
||||
def find_chainable_SingleSubst_(self, chain, glyphs):
|
||||
"""Helper for add_single_subst_chained_()"""
|
||||
for _, _, _, substitutions in chain.substitutions:
|
||||
for sub in substitutions:
|
||||
if (isinstance(sub, SingleSubstBuilder) and
|
||||
not any(g in glyphs for g in sub.mapping.keys())):
|
||||
return sub
|
||||
return None
|
||||
|
||||
def add_single_subst_chained_(self, location, prefix, suffix, mapping):
|
||||
# https://github.com/behdad/fonttools/issues/512
|
||||
chain = self.get_lookup_(location, ChainContextSubstBuilder)
|
||||
sub = self.find_chainable_SingleSubst_(chain, set(mapping.keys()))
|
||||
if sub is None:
|
||||
sub = self.get_chained_lookup_(location, SingleSubstBuilder)
|
||||
sub.mapping.update(mapping)
|
||||
chain.substitutions.append((prefix, [mapping.keys()], suffix, [sub]))
|
||||
|
||||
def add_cursive_pos(self, location, glyphclass, entryAnchor, exitAnchor):
|
||||
lookup = self.get_lookup_(location, CursivePosBuilder)
|
||||
lookup.add_attachment(
|
||||
|
@ -30,6 +30,7 @@ def makeTTFont():
|
||||
"A.alt1 A.alt2 A.alt3 B.alt1 B.alt2 B.alt3 C.alt1 C.alt2 C.alt3 "
|
||||
"a.alt1 a.alt2 a.alt3 b.alt c.mid d.alt d.mid e.begin e.mid "
|
||||
"n.end s.end Eng Eng.alt1 Eng.alt2 Eng.alt3 "
|
||||
"G.swash H.swash "
|
||||
"f_l c_h c_k c_s c_t f_f f_f_i f_f_l f_i o_f_f_i s_t f_i.begin "
|
||||
"a_n_d ydieresis yacute breve "
|
||||
"grave acute dieresis macron circumflex cedilla umlaut ogonek caron "
|
||||
@ -52,7 +53,7 @@ class BuilderTest(unittest.TestCase):
|
||||
spec5f_ii_1 spec5f_ii_2 spec5f_ii_3
|
||||
spec5h1 spec6b_ii spec6d2 spec6e spec6f spec6h_ii spec6h_iii_1 spec8a
|
||||
spec9b spec9c1 spec9c2 spec9c3
|
||||
bug463 bug501 bug502 bug505 bug506 bug509
|
||||
bug463 bug501 bug502 bug505 bug506 bug509 bug512
|
||||
""".split()
|
||||
|
||||
def __init__(self, methodName):
|
||||
|
41
Lib/fontTools/feaLib/testdata/GSUB_6.ttx
vendored
41
Lib/fontTools/feaLib/testdata/GSUB_6.ttx
vendored
@ -24,15 +24,15 @@
|
||||
<Feature>
|
||||
<!-- LookupCount=5 -->
|
||||
<LookupListIndex index="0" value="0"/>
|
||||
<LookupListIndex index="1" value="3"/>
|
||||
<LookupListIndex index="2" value="5"/>
|
||||
<LookupListIndex index="3" value="7"/>
|
||||
<LookupListIndex index="4" value="9"/>
|
||||
<LookupListIndex index="1" value="2"/>
|
||||
<LookupListIndex index="2" value="4"/>
|
||||
<LookupListIndex index="3" value="6"/>
|
||||
<LookupListIndex index="4" value="8"/>
|
||||
</Feature>
|
||||
</FeatureRecord>
|
||||
</FeatureList>
|
||||
<LookupList>
|
||||
<!-- LookupCount=10 -->
|
||||
<!-- LookupCount=9 -->
|
||||
<Lookup index="0">
|
||||
<!-- LookupType=6 -->
|
||||
<LookupFlag value="0"/>
|
||||
@ -76,7 +76,7 @@
|
||||
<!-- SubstCount=1 -->
|
||||
<SubstLookupRecord index="0">
|
||||
<SequenceIndex value="0"/>
|
||||
<LookupListIndex value="2"/>
|
||||
<LookupListIndex value="1"/>
|
||||
</SubstLookupRecord>
|
||||
</ChainContextSubst>
|
||||
</Lookup>
|
||||
@ -86,19 +86,12 @@
|
||||
<!-- SubTableCount=1 -->
|
||||
<SingleSubst index="0">
|
||||
<Substitution in="A" out="A.sc"/>
|
||||
</SingleSubst>
|
||||
</Lookup>
|
||||
<Lookup index="2">
|
||||
<!-- LookupType=1 -->
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
<SingleSubst index="0">
|
||||
<Substitution in="B" out="B.sc"/>
|
||||
<Substitution in="C" out="C.sc"/>
|
||||
<Substitution in="D" out="D.sc"/>
|
||||
</SingleSubst>
|
||||
</Lookup>
|
||||
<Lookup index="3">
|
||||
<Lookup index="2">
|
||||
<!-- LookupType=6 -->
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
@ -142,11 +135,11 @@
|
||||
<!-- SubstCount=1 -->
|
||||
<SubstLookupRecord index="0">
|
||||
<SequenceIndex value="0"/>
|
||||
<LookupListIndex value="4"/>
|
||||
<LookupListIndex value="3"/>
|
||||
</SubstLookupRecord>
|
||||
</ChainContextSubst>
|
||||
</Lookup>
|
||||
<Lookup index="4">
|
||||
<Lookup index="3">
|
||||
<!-- LookupType=2 -->
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
@ -154,7 +147,7 @@
|
||||
<Substitution in="c_t" out="c,t"/>
|
||||
</MultipleSubst>
|
||||
</Lookup>
|
||||
<Lookup index="5">
|
||||
<Lookup index="4">
|
||||
<!-- LookupType=6 -->
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
@ -173,11 +166,11 @@
|
||||
<!-- SubstCount=1 -->
|
||||
<SubstLookupRecord index="0">
|
||||
<SequenceIndex value="0"/>
|
||||
<LookupListIndex value="6"/>
|
||||
<LookupListIndex value="5"/>
|
||||
</SubstLookupRecord>
|
||||
</ChainContextSubst>
|
||||
</Lookup>
|
||||
<Lookup index="6">
|
||||
<Lookup index="5">
|
||||
<!-- LookupType=3 -->
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
@ -188,7 +181,7 @@
|
||||
</AlternateSet>
|
||||
</AlternateSubst>
|
||||
</Lookup>
|
||||
<Lookup index="7">
|
||||
<Lookup index="6">
|
||||
<!-- LookupType=6 -->
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
@ -213,11 +206,11 @@
|
||||
<!-- SubstCount=1 -->
|
||||
<SubstLookupRecord index="0">
|
||||
<SequenceIndex value="0"/>
|
||||
<LookupListIndex value="8"/>
|
||||
<LookupListIndex value="7"/>
|
||||
</SubstLookupRecord>
|
||||
</ChainContextSubst>
|
||||
</Lookup>
|
||||
<Lookup index="8">
|
||||
<Lookup index="7">
|
||||
<!-- LookupType=4 -->
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
@ -232,7 +225,7 @@
|
||||
</LigatureSet>
|
||||
</LigatureSubst>
|
||||
</Lookup>
|
||||
<Lookup index="9">
|
||||
<Lookup index="8">
|
||||
<!-- LookupType=6 -->
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
@ -264,7 +257,7 @@
|
||||
<!-- SubstCount=1 -->
|
||||
<SubstLookupRecord index="0">
|
||||
<SequenceIndex value="0"/>
|
||||
<LookupListIndex value="3"/>
|
||||
<LookupListIndex value="2"/>
|
||||
</SubstLookupRecord>
|
||||
</ChainContextSubst>
|
||||
</Lookup>
|
||||
|
13
Lib/fontTools/feaLib/testdata/bug463.ttx
vendored
13
Lib/fontTools/feaLib/testdata/bug463.ttx
vendored
@ -28,7 +28,7 @@
|
||||
</FeatureRecord>
|
||||
</FeatureList>
|
||||
<LookupList>
|
||||
<!-- LookupCount=3 -->
|
||||
<!-- LookupCount=2 -->
|
||||
<Lookup index="0">
|
||||
<!-- LookupType=6 -->
|
||||
<LookupFlag value="0"/>
|
||||
@ -82,7 +82,7 @@
|
||||
<!-- SubstCount=1 -->
|
||||
<SubstLookupRecord index="0">
|
||||
<SequenceIndex value="0"/>
|
||||
<LookupListIndex value="2"/>
|
||||
<LookupListIndex value="1"/>
|
||||
</SubstLookupRecord>
|
||||
</ChainContextSubst>
|
||||
</Lookup>
|
||||
@ -92,15 +92,8 @@
|
||||
<!-- SubTableCount=1 -->
|
||||
<SingleSubst index="0">
|
||||
<Substitution in="A" out="ordfeminine"/>
|
||||
<Substitution in="a" out="ordfeminine"/>
|
||||
</SingleSubst>
|
||||
</Lookup>
|
||||
<Lookup index="2">
|
||||
<!-- LookupType=1 -->
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
<SingleSubst index="0">
|
||||
<Substitution in="O" out="ordmasculine"/>
|
||||
<Substitution in="a" out="ordfeminine"/>
|
||||
<Substitution in="o" out="ordmasculine"/>
|
||||
</SingleSubst>
|
||||
</Lookup>
|
||||
|
6
Lib/fontTools/feaLib/testdata/bug512.fea
vendored
Normal file
6
Lib/fontTools/feaLib/testdata/bug512.fea
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
feature test {
|
||||
sub G' by G.swash;
|
||||
sub H' by H.swash;
|
||||
sub G' by g;
|
||||
sub H' by H.swash;
|
||||
} test;
|
110
Lib/fontTools/feaLib/testdata/bug512.ttx
vendored
Normal file
110
Lib/fontTools/feaLib/testdata/bug512.ttx
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ttFont sfntVersion="true" ttLibVersion="3.0">
|
||||
|
||||
<GSUB>
|
||||
<Version value="1.0"/>
|
||||
<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="test"/>
|
||||
<Feature>
|
||||
<!-- LookupCount=1 -->
|
||||
<LookupListIndex index="0" value="0"/>
|
||||
</Feature>
|
||||
</FeatureRecord>
|
||||
</FeatureList>
|
||||
<LookupList>
|
||||
<!-- LookupCount=3 -->
|
||||
<Lookup index="0">
|
||||
<!-- LookupType=6 -->
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=4 -->
|
||||
<ChainContextSubst index="0" Format="3">
|
||||
<!-- BacktrackGlyphCount=0 -->
|
||||
<!-- InputGlyphCount=1 -->
|
||||
<InputCoverage index="0">
|
||||
<Glyph value="G"/>
|
||||
</InputCoverage>
|
||||
<!-- LookAheadGlyphCount=0 -->
|
||||
<!-- SubstCount=1 -->
|
||||
<SubstLookupRecord index="0">
|
||||
<SequenceIndex value="0"/>
|
||||
<LookupListIndex value="1"/>
|
||||
</SubstLookupRecord>
|
||||
</ChainContextSubst>
|
||||
<ChainContextSubst index="1" Format="3">
|
||||
<!-- BacktrackGlyphCount=0 -->
|
||||
<!-- InputGlyphCount=1 -->
|
||||
<InputCoverage index="0">
|
||||
<Glyph value="H"/>
|
||||
</InputCoverage>
|
||||
<!-- LookAheadGlyphCount=0 -->
|
||||
<!-- SubstCount=1 -->
|
||||
<SubstLookupRecord index="0">
|
||||
<SequenceIndex value="0"/>
|
||||
<LookupListIndex value="1"/>
|
||||
</SubstLookupRecord>
|
||||
</ChainContextSubst>
|
||||
<ChainContextSubst index="2" Format="3">
|
||||
<!-- BacktrackGlyphCount=0 -->
|
||||
<!-- InputGlyphCount=1 -->
|
||||
<InputCoverage index="0">
|
||||
<Glyph value="G"/>
|
||||
</InputCoverage>
|
||||
<!-- LookAheadGlyphCount=0 -->
|
||||
<!-- SubstCount=1 -->
|
||||
<SubstLookupRecord index="0">
|
||||
<SequenceIndex value="0"/>
|
||||
<LookupListIndex value="2"/>
|
||||
</SubstLookupRecord>
|
||||
</ChainContextSubst>
|
||||
<ChainContextSubst index="3" Format="3">
|
||||
<!-- BacktrackGlyphCount=0 -->
|
||||
<!-- InputGlyphCount=1 -->
|
||||
<InputCoverage index="0">
|
||||
<Glyph value="H"/>
|
||||
</InputCoverage>
|
||||
<!-- LookAheadGlyphCount=0 -->
|
||||
<!-- SubstCount=1 -->
|
||||
<SubstLookupRecord index="0">
|
||||
<SequenceIndex value="0"/>
|
||||
<LookupListIndex value="2"/>
|
||||
</SubstLookupRecord>
|
||||
</ChainContextSubst>
|
||||
</Lookup>
|
||||
<Lookup index="1">
|
||||
<!-- LookupType=1 -->
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
<SingleSubst index="0">
|
||||
<Substitution in="G" out="G.swash"/>
|
||||
<Substitution in="H" out="H.swash"/>
|
||||
</SingleSubst>
|
||||
</Lookup>
|
||||
<Lookup index="2">
|
||||
<!-- LookupType=1 -->
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
<SingleSubst index="0">
|
||||
<Substitution in="G" out="g"/>
|
||||
<Substitution in="H" out="H.swash"/>
|
||||
</SingleSubst>
|
||||
</Lookup>
|
||||
</LookupList>
|
||||
</GSUB>
|
||||
|
||||
</ttFont>
|
19
Lib/fontTools/feaLib/testdata/feature_aalt.ttx
vendored
19
Lib/fontTools/feaLib/testdata/feature_aalt.ttx
vendored
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ttFont>
|
||||
<ttFont sfntVersion="true" ttLibVersion="3.0">
|
||||
|
||||
<GSUB>
|
||||
<Version value="1.0"/>
|
||||
@ -41,7 +41,7 @@
|
||||
<FeatureTag value="liga"/>
|
||||
<Feature>
|
||||
<!-- LookupCount=1 -->
|
||||
<LookupListIndex index="0" value="6"/>
|
||||
<LookupListIndex index="0" value="5"/>
|
||||
</Feature>
|
||||
</FeatureRecord>
|
||||
<FeatureRecord index="3">
|
||||
@ -60,7 +60,7 @@
|
||||
</FeatureRecord>
|
||||
</FeatureList>
|
||||
<LookupList>
|
||||
<!-- LookupCount=7 -->
|
||||
<!-- LookupCount=6 -->
|
||||
<Lookup index="0">
|
||||
<!-- LookupType=1 -->
|
||||
<LookupFlag value="0"/>
|
||||
@ -152,7 +152,7 @@
|
||||
<!-- SubstCount=1 -->
|
||||
<SubstLookupRecord index="0">
|
||||
<SequenceIndex value="0"/>
|
||||
<LookupListIndex value="5"/>
|
||||
<LookupListIndex value="4"/>
|
||||
</SubstLookupRecord>
|
||||
</ChainContextSubst>
|
||||
</Lookup>
|
||||
@ -162,19 +162,12 @@
|
||||
<!-- SubTableCount=1 -->
|
||||
<SingleSubst index="0">
|
||||
<Substitution in="A" out="ordfeminine"/>
|
||||
<Substitution in="a" out="ordfeminine"/>
|
||||
</SingleSubst>
|
||||
</Lookup>
|
||||
<Lookup index="5">
|
||||
<!-- LookupType=1 -->
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
<SingleSubst index="0">
|
||||
<Substitution in="O" out="ordmasculine"/>
|
||||
<Substitution in="a" out="ordfeminine"/>
|
||||
<Substitution in="o" out="ordmasculine"/>
|
||||
</SingleSubst>
|
||||
</Lookup>
|
||||
<Lookup index="6">
|
||||
<Lookup index="5">
|
||||
<!-- LookupType=4 -->
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
|
Loading…
x
Reference in New Issue
Block a user