[feaLib] Implement the ignore substitution statement

https://github.com/behdad/fonttools/issues/503
This commit is contained in:
Sascha Brawer 2016-02-04 11:33:54 +01:00
parent aae350c84a
commit ab7b86005e
6 changed files with 121 additions and 17 deletions

View File

@ -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)

View File

@ -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

View File

@ -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_)

View File

@ -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;")

View 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;

View 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>