[feaLib] Emit chains to LigatureSubst even without backtrack or lookahead
https://github.com/behdad/fonttools/issues/506
This commit is contained in:
parent
ea4a4e34b3
commit
dba1d6666b
@ -326,17 +326,19 @@ class LigatureCaretByPosStatement(Statement):
|
||||
|
||||
|
||||
class LigatureSubstStatement(Statement):
|
||||
def __init__(self, location, prefix, glyphs, suffix, replacement):
|
||||
def __init__(self, location, prefix, glyphs, suffix, replacement,
|
||||
forceChain):
|
||||
Statement.__init__(self, location)
|
||||
self.prefix, self.glyphs, self.suffix = (prefix, glyphs, suffix)
|
||||
self.replacement = replacement
|
||||
self.replacement, self.forceChain = replacement, forceChain
|
||||
|
||||
def build(self, builder):
|
||||
prefix = [p.glyphSet() for p in self.prefix]
|
||||
glyphs = [g.glyphSet() for g in self.glyphs]
|
||||
suffix = [s.glyphSet() for s in self.suffix]
|
||||
builder.add_ligature_subst(
|
||||
self.location, prefix, glyphs, suffix, self.replacement)
|
||||
self.location, prefix, glyphs, suffix, self.replacement,
|
||||
self.forceChain)
|
||||
|
||||
|
||||
class LookupFlagStatement(Statement):
|
||||
|
@ -512,8 +512,8 @@ class Builder(object):
|
||||
self.aalt_features_.append((location, featureName))
|
||||
|
||||
def add_ligature_subst(self, location,
|
||||
prefix, glyphs, suffix, replacement):
|
||||
if prefix or suffix:
|
||||
prefix, glyphs, suffix, replacement, forceChain):
|
||||
if prefix or suffix or forceChain:
|
||||
chain = self.get_lookup_(location, ChainContextSubstBuilder)
|
||||
lookup = self.get_chained_lookup_(location, LigatureSubstBuilder)
|
||||
chain.substitutions.append((prefix, glyphs, suffix, [lookup]))
|
||||
|
@ -52,7 +52,7 @@ class BuilderTest(unittest.TestCase):
|
||||
spec5f_ii_1
|
||||
spec5h1 spec6b_ii spec6d2 spec6e spec6f spec6h_ii spec6h_iii_1 spec8a
|
||||
spec9b spec9c1 spec9c2 spec9c3
|
||||
bug463 bug501 bug502 bug505
|
||||
bug463 bug501 bug502 bug505 bug506
|
||||
""".split()
|
||||
|
||||
def __init__(self, methodName):
|
||||
|
@ -241,12 +241,13 @@ class Parser(object):
|
||||
|
||||
def parse_glyph_pattern_(self, vertical):
|
||||
prefix, glyphs, lookups, values, suffix = ([], [], [], [], [])
|
||||
hasMarks = False
|
||||
while self.next_token_ not in {"by", "from", ";"}:
|
||||
gc = self.parse_glyphclass_(accept_glyphname=True)
|
||||
marked = False
|
||||
if self.next_token_ == "'":
|
||||
self.expect_symbol_("'")
|
||||
marked = True
|
||||
hasMarks = marked = True
|
||||
if marked:
|
||||
glyphs.append(gc)
|
||||
elif glyphs:
|
||||
@ -277,18 +278,18 @@ class Parser(object):
|
||||
|
||||
if not glyphs and not suffix: # eg., "sub f f i by"
|
||||
assert lookups == []
|
||||
return ([], prefix, [None] * len(prefix), values, [])
|
||||
return ([], prefix, [None] * len(prefix), values, [], hasMarks)
|
||||
else:
|
||||
assert not any(values[:len(prefix)]), values
|
||||
values = values[len(prefix):][:len(glyphs)]
|
||||
return (prefix, glyphs, lookups, values, suffix)
|
||||
return (prefix, glyphs, lookups, values, suffix, hasMarks)
|
||||
|
||||
def parse_ignore_(self):
|
||||
assert self.is_cur_keyword_("ignore")
|
||||
location = self.cur_token_location_
|
||||
self.advance_lexer_()
|
||||
if self.cur_token_ in ["substitute", "sub"]:
|
||||
prefix, glyphs, lookups, values, suffix = \
|
||||
prefix, glyphs, lookups, values, suffix, hasMarks = \
|
||||
self.parse_glyph_pattern_(vertical=False)
|
||||
self.expect_symbol_(";")
|
||||
if any(lookups):
|
||||
@ -423,7 +424,7 @@ class Parser(object):
|
||||
return self.parse_position_mark_(enumerated, vertical)
|
||||
|
||||
location = self.cur_token_location_
|
||||
prefix, glyphs, lookups, values, suffix = \
|
||||
prefix, glyphs, lookups, values, suffix, hasMarks = \
|
||||
self.parse_glyph_pattern_(vertical)
|
||||
self.expect_symbol_(";")
|
||||
|
||||
@ -518,7 +519,7 @@ class Parser(object):
|
||||
assert self.cur_token_ in {"substitute", "sub", "reversesub", "rsub"}
|
||||
location = self.cur_token_location_
|
||||
reverse = self.cur_token_ in {"reversesub", "rsub"}
|
||||
old_prefix, old, lookups, values, old_suffix = \
|
||||
old_prefix, old, lookups, values, old_suffix, hasMarks = \
|
||||
self.parse_glyph_pattern_(vertical=False)
|
||||
if any(values):
|
||||
raise FeatureLibError(
|
||||
@ -597,7 +598,7 @@ class Parser(object):
|
||||
num_lookups == 0):
|
||||
return ast.LigatureSubstStatement(
|
||||
location, old_prefix, old, old_suffix,
|
||||
list(new[0].glyphSet())[0])
|
||||
list(new[0].glyphSet())[0], forceChain=hasMarks)
|
||||
|
||||
# GSUB lookup type 8: Reverse chaining substitution.
|
||||
if reverse:
|
||||
|
4
Lib/fontTools/feaLib/testdata/bug506.fea
vendored
Normal file
4
Lib/fontTools/feaLib/testdata/bug506.fea
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
# https://github.com/behdad/fonttools/issues/506
|
||||
feature test {
|
||||
sub f' i' by f_i;
|
||||
} test;
|
66
Lib/fontTools/feaLib/testdata/bug506.ttx
vendored
Normal file
66
Lib/fontTools/feaLib/testdata/bug506.ttx
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
<?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=2 -->
|
||||
<Lookup index="0">
|
||||
<!-- LookupType=6 -->
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
<ChainContextSubst index="0" Format="3">
|
||||
<!-- BacktrackGlyphCount=0 -->
|
||||
<!-- InputGlyphCount=2 -->
|
||||
<InputCoverage index="0">
|
||||
<Glyph value="f"/>
|
||||
</InputCoverage>
|
||||
<InputCoverage index="1">
|
||||
<Glyph value="i"/>
|
||||
</InputCoverage>
|
||||
<!-- LookAheadGlyphCount=0 -->
|
||||
<!-- SubstCount=1 -->
|
||||
<SubstLookupRecord index="0">
|
||||
<SequenceIndex value="0"/>
|
||||
<LookupListIndex value="1"/>
|
||||
</SubstLookupRecord>
|
||||
</ChainContextSubst>
|
||||
</Lookup>
|
||||
<Lookup index="1">
|
||||
<!-- LookupType=4 -->
|
||||
<LookupFlag value="0"/>
|
||||
<!-- SubTableCount=1 -->
|
||||
<LigatureSubst index="0">
|
||||
<LigatureSet glyph="f">
|
||||
<Ligature components="i" glyph="f_i"/>
|
||||
</LigatureSet>
|
||||
</LigatureSubst>
|
||||
</Lookup>
|
||||
</LookupList>
|
||||
</GSUB>
|
||||
|
||||
</ttFont>
|
Loading…
x
Reference in New Issue
Block a user