[feaLib] Implement the ignore substitution
statement
https://github.com/behdad/fonttools/issues/503
This commit is contained in:
parent
aae350c84a
commit
ab7b86005e
@ -296,12 +296,6 @@ class LanguageSystemStatement(Statement):
|
|||||||
builder.add_language_system(self.location, self.script, self.language)
|
builder.add_language_system(self.location, self.script, self.language)
|
||||||
|
|
||||||
|
|
||||||
class IgnoreSubstitutionRule(Statement):
|
|
||||||
def __init__(self, location, prefix, glyphs, suffix):
|
|
||||||
Statement.__init__(self, location)
|
|
||||||
self.prefix, self.glyphs, self.suffix = (prefix, glyphs, suffix)
|
|
||||||
|
|
||||||
|
|
||||||
class FontRevisionStatement(Statement):
|
class FontRevisionStatement(Statement):
|
||||||
def __init__(self, location, revision):
|
def __init__(self, location, revision):
|
||||||
Statement.__init__(self, location)
|
Statement.__init__(self, location)
|
||||||
|
@ -49,6 +49,7 @@ class BuilderTest(unittest.TestCase):
|
|||||||
GPOS_1 GPOS_1_zero GPOS_2 GPOS_2b GPOS_3 GPOS_4 GPOS_5 GPOS_6 GPOS_8
|
GPOS_1 GPOS_1_zero GPOS_2 GPOS_2b GPOS_3 GPOS_4 GPOS_5 GPOS_6 GPOS_8
|
||||||
GSUB_2 GSUB_3 GSUB_6 GSUB_8
|
GSUB_2 GSUB_3 GSUB_6 GSUB_8
|
||||||
spec4h1 spec5d1 spec5d2 spec5fi1 spec5fi2 spec5fi3 spec5fi4
|
spec4h1 spec5d1 spec5d2 spec5fi1 spec5fi2 spec5fi3 spec5fi4
|
||||||
|
spec5f_ii_1
|
||||||
spec5h1 spec6b_ii spec6d2 spec6e spec6f spec6h_ii spec6h_iii_1 spec8a
|
spec5h1 spec6b_ii spec6d2 spec6e spec6f spec6h_ii spec6h_iii_1 spec8a
|
||||||
spec9b spec9c1 spec9c2 spec9c3
|
spec9b spec9c1 spec9c2 spec9c3
|
||||||
bug463 bug501 bug502 bug505
|
bug463 bug501 bug502 bug505
|
||||||
|
@ -295,7 +295,8 @@ class Parser(object):
|
|||||||
raise FeatureLibError(
|
raise FeatureLibError(
|
||||||
"No lookups can be specified for \"ignore sub\"",
|
"No lookups can be specified for \"ignore sub\"",
|
||||||
location)
|
location)
|
||||||
return ast.IgnoreSubstitutionRule(location, prefix, glyphs, suffix)
|
return ast.ChainContextSubstStatement(
|
||||||
|
location, prefix, glyphs, suffix, [])
|
||||||
raise FeatureLibError(
|
raise FeatureLibError(
|
||||||
"Expected \"substitute\"", self.next_token_location_)
|
"Expected \"substitute\"", self.next_token_location_)
|
||||||
|
|
||||||
|
@ -291,22 +291,24 @@ class ParserTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_ignore_sub(self):
|
def test_ignore_sub(self):
|
||||||
doc = self.parse("feature test {ignore sub e t' c;} test;")
|
doc = self.parse("feature test {ignore sub e t' c;} test;")
|
||||||
s = doc.statements[0].statements[0]
|
sub = doc.statements[0].statements[0]
|
||||||
self.assertEqual(type(s), ast.IgnoreSubstitutionRule)
|
self.assertIsInstance(sub, ast.ChainContextSubstStatement)
|
||||||
self.assertEqual(glyphstr(s.prefix), "e")
|
self.assertEqual(glyphstr(sub.prefix), "e")
|
||||||
self.assertEqual(glyphstr(s.glyphs), "t")
|
self.assertEqual(glyphstr(sub.glyphs), "t")
|
||||||
self.assertEqual(glyphstr(s.suffix), "c")
|
self.assertEqual(glyphstr(sub.suffix), "c")
|
||||||
|
self.assertEqual(sub.lookups, [])
|
||||||
|
|
||||||
def test_ignore_substitute(self):
|
def test_ignore_substitute(self):
|
||||||
doc = self.parse(
|
doc = self.parse(
|
||||||
"feature test {"
|
"feature test {"
|
||||||
" ignore substitute f [a e] d' [a u]' [e y];"
|
" ignore substitute f [a e] d' [a u]' [e y];"
|
||||||
"} test;")
|
"} test;")
|
||||||
s = doc.statements[0].statements[0]
|
sub = doc.statements[0].statements[0]
|
||||||
self.assertEqual(type(s), ast.IgnoreSubstitutionRule)
|
self.assertIsInstance(sub, ast.ChainContextSubstStatement)
|
||||||
self.assertEqual(glyphstr(s.prefix), "f [a e]")
|
self.assertEqual(glyphstr(sub.prefix), "f [a e]")
|
||||||
self.assertEqual(glyphstr(s.glyphs), "d [a u]")
|
self.assertEqual(glyphstr(sub.glyphs), "d [a u]")
|
||||||
self.assertEqual(glyphstr(s.suffix), "[e y]")
|
self.assertEqual(glyphstr(sub.suffix), "[e y]")
|
||||||
|
self.assertEqual(sub.lookups, [])
|
||||||
|
|
||||||
def test_language(self):
|
def test_language(self):
|
||||||
doc = self.parse("feature test {language DEU;} test;")
|
doc = self.parse("feature test {language DEU;} test;")
|
||||||
|
9
Lib/fontTools/feaLib/testdata/spec5f_ii_1.fea
vendored
Normal file
9
Lib/fontTools/feaLib/testdata/spec5f_ii_1.fea
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# OpenType Feature File specification, section 5.f.ii, example 1
|
||||||
|
# "Specifying exceptions to the Chain Sub rule"
|
||||||
|
# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
|
||||||
|
|
||||||
|
feature test {
|
||||||
|
ignore substitute f [a e] d';
|
||||||
|
ignore substitute a d' d;
|
||||||
|
substitute [a e n] d' by d.alt;
|
||||||
|
} test;
|
97
Lib/fontTools/feaLib/testdata/spec5f_ii_1.ttx
vendored
Normal file
97
Lib/fontTools/feaLib/testdata/spec5f_ii_1.ttx
vendored
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<?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=3 -->
|
||||||
|
<ChainContextSubst index="0" Format="3">
|
||||||
|
<!-- BacktrackGlyphCount=2 -->
|
||||||
|
<BacktrackCoverage index="0">
|
||||||
|
<Glyph value="a"/>
|
||||||
|
<Glyph value="e"/>
|
||||||
|
</BacktrackCoverage>
|
||||||
|
<BacktrackCoverage index="1">
|
||||||
|
<Glyph value="f"/>
|
||||||
|
</BacktrackCoverage>
|
||||||
|
<!-- InputGlyphCount=1 -->
|
||||||
|
<InputCoverage index="0">
|
||||||
|
<Glyph value="d"/>
|
||||||
|
</InputCoverage>
|
||||||
|
<!-- LookAheadGlyphCount=0 -->
|
||||||
|
<!-- SubstCount=0 -->
|
||||||
|
</ChainContextSubst>
|
||||||
|
<ChainContextSubst index="1" Format="3">
|
||||||
|
<!-- BacktrackGlyphCount=1 -->
|
||||||
|
<BacktrackCoverage index="0">
|
||||||
|
<Glyph value="a"/>
|
||||||
|
</BacktrackCoverage>
|
||||||
|
<!-- InputGlyphCount=1 -->
|
||||||
|
<InputCoverage index="0">
|
||||||
|
<Glyph value="d"/>
|
||||||
|
</InputCoverage>
|
||||||
|
<!-- LookAheadGlyphCount=1 -->
|
||||||
|
<LookAheadCoverage index="0">
|
||||||
|
<Glyph value="d"/>
|
||||||
|
</LookAheadCoverage>
|
||||||
|
<!-- SubstCount=0 -->
|
||||||
|
</ChainContextSubst>
|
||||||
|
<ChainContextSubst index="2" Format="3">
|
||||||
|
<!-- BacktrackGlyphCount=1 -->
|
||||||
|
<BacktrackCoverage index="0">
|
||||||
|
<Glyph value="a"/>
|
||||||
|
<Glyph value="e"/>
|
||||||
|
<Glyph value="n"/>
|
||||||
|
</BacktrackCoverage>
|
||||||
|
<!-- InputGlyphCount=1 -->
|
||||||
|
<InputCoverage index="0">
|
||||||
|
<Glyph value="d"/>
|
||||||
|
</InputCoverage>
|
||||||
|
<!-- LookAheadGlyphCount=0 -->
|
||||||
|
<!-- SubstCount=1 -->
|
||||||
|
<SubstLookupRecord index="0">
|
||||||
|
<SequenceIndex value="0"/>
|
||||||
|
<LookupListIndex value="1"/>
|
||||||
|
</SubstLookupRecord>
|
||||||
|
</ChainContextSubst>
|
||||||
|
</Lookup>
|
||||||
|
<Lookup index="1">
|
||||||
|
<!-- LookupType=1 -->
|
||||||
|
<LookupFlag value="0"/>
|
||||||
|
<!-- SubTableCount=1 -->
|
||||||
|
<SingleSubst index="0">
|
||||||
|
<Substitution in="d" out="d.alt"/>
|
||||||
|
</SingleSubst>
|
||||||
|
</Lookup>
|
||||||
|
</LookupList>
|
||||||
|
</GSUB>
|
||||||
|
|
||||||
|
</ttFont>
|
Loading…
x
Reference in New Issue
Block a user