[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)
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):
def __init__(self, location, revision):
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
GSUB_2 GSUB_3 GSUB_6 GSUB_8
spec4h1 spec5d1 spec5d2 spec5fi1 spec5fi2 spec5fi3 spec5fi4
spec5f_ii_1
spec5h1 spec6b_ii spec6d2 spec6e spec6f spec6h_ii spec6h_iii_1 spec8a
spec9b spec9c1 spec9c2 spec9c3
bug463 bug501 bug502 bug505

View File

@ -295,7 +295,8 @@ class Parser(object):
raise FeatureLibError(
"No lookups can be specified for \"ignore sub\"",
location)
return ast.IgnoreSubstitutionRule(location, prefix, glyphs, suffix)
return ast.ChainContextSubstStatement(
location, prefix, glyphs, suffix, [])
raise FeatureLibError(
"Expected \"substitute\"", self.next_token_location_)

View File

@ -291,22 +291,24 @@ class ParserTest(unittest.TestCase):
def test_ignore_sub(self):
doc = self.parse("feature test {ignore sub e t' c;} test;")
s = doc.statements[0].statements[0]
self.assertEqual(type(s), ast.IgnoreSubstitutionRule)
self.assertEqual(glyphstr(s.prefix), "e")
self.assertEqual(glyphstr(s.glyphs), "t")
self.assertEqual(glyphstr(s.suffix), "c")
sub = doc.statements[0].statements[0]
self.assertIsInstance(sub, ast.ChainContextSubstStatement)
self.assertEqual(glyphstr(sub.prefix), "e")
self.assertEqual(glyphstr(sub.glyphs), "t")
self.assertEqual(glyphstr(sub.suffix), "c")
self.assertEqual(sub.lookups, [])
def test_ignore_substitute(self):
doc = self.parse(
"feature test {"
" ignore substitute f [a e] d' [a u]' [e y];"
"} test;")
s = doc.statements[0].statements[0]
self.assertEqual(type(s), ast.IgnoreSubstitutionRule)
self.assertEqual(glyphstr(s.prefix), "f [a e]")
self.assertEqual(glyphstr(s.glyphs), "d [a u]")
self.assertEqual(glyphstr(s.suffix), "[e y]")
sub = doc.statements[0].statements[0]
self.assertIsInstance(sub, ast.ChainContextSubstStatement)
self.assertEqual(glyphstr(sub.prefix), "f [a e]")
self.assertEqual(glyphstr(sub.glyphs), "d [a u]")
self.assertEqual(glyphstr(sub.suffix), "[e y]")
self.assertEqual(sub.lookups, [])
def test_language(self):
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>