[feaLib] Add unit test with spec section 5.f.ii, example 4

This is another test case for the `ignore sub` statement.
After the recent changes to feaLib, the output is now identical
to the output generated by makeotf.

https://github.com/behdad/fonttools/issues/503
This commit is contained in:
Sascha Brawer 2016-02-05 15:55:53 +01:00
parent ec9077a566
commit 4a23f8eb85
3 changed files with 334 additions and 22 deletions

View File

@ -15,27 +15,31 @@ import unittest
def makeTTFont(): def makeTTFont():
glyphs = ( glyphs = """
".notdef space slash fraction semicolon period comma ampersand " .notdef space slash fraction semicolon period comma ampersand
"quotedblleft quotedblright quoteleft quoteright " quotedblleft quotedblright quoteleft quoteright
"zero one two three four five six seven eight nine " zero one two three four five six seven eight nine
"zero.oldstyle one.oldstyle two.oldstyle three.oldstyle " zero.oldstyle one.oldstyle two.oldstyle three.oldstyle
"four.oldstyle five.oldstyle six.oldstyle seven.oldstyle " four.oldstyle five.oldstyle six.oldstyle seven.oldstyle
"eight.oldstyle nine.oldstyle onequarter onehalf threequarters " eight.oldstyle nine.oldstyle onequarter onehalf threequarters
"onesuperior twosuperior threesuperior ordfeminine ordmasculine " onesuperior twosuperior threesuperior ordfeminine ordmasculine
"A B C D E F G H I J K L M N O P Q R S T U V W X Y Z " A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
"a b c d e f g h i j k l m n o p q r s t u v w x y z " a b c d e f g h i j k l m n o p q r s t u v w x y z
"A.sc B.sc C.sc D.sc E.sc F.sc G.sc H.sc I.sc J.sc K.sc L.sc M.sc " A.sc B.sc C.sc D.sc E.sc F.sc G.sc H.sc I.sc J.sc K.sc L.sc M.sc
"N.sc O.sc P.sc Q.sc R.sc S.sc T.sc U.sc V.sc W.sc X.sc Y.sc Z.sc " N.sc O.sc P.sc Q.sc R.sc S.sc T.sc U.sc V.sc W.sc X.sc Y.sc Z.sc
"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.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 " a.alt1 a.alt2 a.alt3 a.end b.alt c.mid d.alt d.mid
"n.end s.end Eng Eng.alt1 Eng.alt2 Eng.alt3 " e.begin e.mid e.end m.begin n.end s.end z.end
"G.swash H.swash " Eng Eng.alt1 Eng.alt2 Eng.alt3
"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.swash B.swash C.swash D.swash E.swash F.swash G.swash H.swash
"a_n_d ydieresis yacute breve " I.swash J.swash K.swash L.swash M.swash N.swash O.swash P.swash
"grave acute dieresis macron circumflex cedilla umlaut ogonek caron " Q.swash R.swash S.swash T.swash U.swash V.swash W.swash X.swash
"damma hamza sukun kasratan lam_meem_jeem noon.final noon.initial " Y.swash Z.swash
).split() 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 T_h T_h.swash ydieresis yacute breve
grave acute dieresis macron circumflex cedilla umlaut ogonek caron
damma hamza sukun kasratan lam_meem_jeem noon.final noon.initial
""".split()
font = TTFont() font = TTFont()
font.setGlyphOrder(glyphs) font.setGlyphOrder(glyphs)
return font return font
@ -50,7 +54,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 spec5f_ii_2 spec5f_ii_3 spec5f_ii_1 spec5f_ii_2 spec5f_ii_3 spec5f_ii_4
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 bug506 bug509 bug512 bug463 bug501 bug502 bug505 bug506 bug509 bug512

View File

@ -0,0 +1,23 @@
# OpenType Feature File specification, section 5.f.ii, example 4
# "Specifying exceptions to the Chain Sub rule"
# http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html
@LETTER = [A-Z a-z];
feature cswh {
# --- Glyph classes used in this feature:
@BEGINNINGS = [A-N P-Z T_h m];
@BEGINNINGS_SWASH = [A.swash-N.swash P.swash-Z.swash T_h.swash m.begin];
@ENDINGS = [a e z];
@ENDINGS_SWASH = [a.end e.end z.end];
# --- Beginning-of-word swashes:
ignore substitute @LETTER @BEGINNINGS';
substitute @BEGINNINGS' by @BEGINNINGS_SWASH;
# --- End-of-word swashes:
ignore substitute @ENDINGS' @LETTER;
substitute @ENDINGS' by @ENDINGS_SWASH;
} cswh;

View File

@ -0,0 +1,285 @@
<?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="cswh"/>
<Feature>
<!-- LookupCount=1 -->
<LookupListIndex index="0" value="0"/>
</Feature>
</FeatureRecord>
</FeatureList>
<LookupList>
<!-- LookupCount=2 -->
<Lookup index="0">
<!-- LookupType=6 -->
<LookupFlag value="0"/>
<!-- SubTableCount=4 -->
<ChainContextSubst index="0" Format="3">
<!-- BacktrackGlyphCount=1 -->
<BacktrackCoverage index="0">
<Glyph value="A"/>
<Glyph value="B"/>
<Glyph value="C"/>
<Glyph value="D"/>
<Glyph value="E"/>
<Glyph value="F"/>
<Glyph value="G"/>
<Glyph value="H"/>
<Glyph value="I"/>
<Glyph value="J"/>
<Glyph value="K"/>
<Glyph value="L"/>
<Glyph value="M"/>
<Glyph value="N"/>
<Glyph value="O"/>
<Glyph value="P"/>
<Glyph value="Q"/>
<Glyph value="R"/>
<Glyph value="S"/>
<Glyph value="T"/>
<Glyph value="U"/>
<Glyph value="V"/>
<Glyph value="W"/>
<Glyph value="X"/>
<Glyph value="Y"/>
<Glyph value="Z"/>
<Glyph value="a"/>
<Glyph value="b"/>
<Glyph value="c"/>
<Glyph value="d"/>
<Glyph value="e"/>
<Glyph value="f"/>
<Glyph value="g"/>
<Glyph value="h"/>
<Glyph value="i"/>
<Glyph value="j"/>
<Glyph value="k"/>
<Glyph value="l"/>
<Glyph value="m"/>
<Glyph value="n"/>
<Glyph value="o"/>
<Glyph value="p"/>
<Glyph value="q"/>
<Glyph value="r"/>
<Glyph value="s"/>
<Glyph value="t"/>
<Glyph value="u"/>
<Glyph value="v"/>
<Glyph value="w"/>
<Glyph value="x"/>
<Glyph value="y"/>
<Glyph value="z"/>
</BacktrackCoverage>
<!-- InputGlyphCount=1 -->
<InputCoverage index="0">
<Glyph value="A"/>
<Glyph value="B"/>
<Glyph value="C"/>
<Glyph value="D"/>
<Glyph value="E"/>
<Glyph value="F"/>
<Glyph value="G"/>
<Glyph value="H"/>
<Glyph value="I"/>
<Glyph value="J"/>
<Glyph value="K"/>
<Glyph value="L"/>
<Glyph value="M"/>
<Glyph value="N"/>
<Glyph value="P"/>
<Glyph value="Q"/>
<Glyph value="R"/>
<Glyph value="S"/>
<Glyph value="T"/>
<Glyph value="U"/>
<Glyph value="V"/>
<Glyph value="W"/>
<Glyph value="X"/>
<Glyph value="Y"/>
<Glyph value="Z"/>
<Glyph value="m"/>
<Glyph value="T_h"/>
</InputCoverage>
<!-- LookAheadGlyphCount=0 -->
<!-- SubstCount=0 -->
</ChainContextSubst>
<ChainContextSubst index="1" Format="3">
<!-- BacktrackGlyphCount=0 -->
<!-- InputGlyphCount=1 -->
<InputCoverage index="0">
<Glyph value="A"/>
<Glyph value="B"/>
<Glyph value="C"/>
<Glyph value="D"/>
<Glyph value="E"/>
<Glyph value="F"/>
<Glyph value="G"/>
<Glyph value="H"/>
<Glyph value="I"/>
<Glyph value="J"/>
<Glyph value="K"/>
<Glyph value="L"/>
<Glyph value="M"/>
<Glyph value="N"/>
<Glyph value="P"/>
<Glyph value="Q"/>
<Glyph value="R"/>
<Glyph value="S"/>
<Glyph value="T"/>
<Glyph value="U"/>
<Glyph value="V"/>
<Glyph value="W"/>
<Glyph value="X"/>
<Glyph value="Y"/>
<Glyph value="Z"/>
<Glyph value="m"/>
<Glyph value="T_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="a"/>
<Glyph value="e"/>
<Glyph value="z"/>
</InputCoverage>
<!-- LookAheadGlyphCount=1 -->
<LookAheadCoverage index="0">
<Glyph value="A"/>
<Glyph value="B"/>
<Glyph value="C"/>
<Glyph value="D"/>
<Glyph value="E"/>
<Glyph value="F"/>
<Glyph value="G"/>
<Glyph value="H"/>
<Glyph value="I"/>
<Glyph value="J"/>
<Glyph value="K"/>
<Glyph value="L"/>
<Glyph value="M"/>
<Glyph value="N"/>
<Glyph value="O"/>
<Glyph value="P"/>
<Glyph value="Q"/>
<Glyph value="R"/>
<Glyph value="S"/>
<Glyph value="T"/>
<Glyph value="U"/>
<Glyph value="V"/>
<Glyph value="W"/>
<Glyph value="X"/>
<Glyph value="Y"/>
<Glyph value="Z"/>
<Glyph value="a"/>
<Glyph value="b"/>
<Glyph value="c"/>
<Glyph value="d"/>
<Glyph value="e"/>
<Glyph value="f"/>
<Glyph value="g"/>
<Glyph value="h"/>
<Glyph value="i"/>
<Glyph value="j"/>
<Glyph value="k"/>
<Glyph value="l"/>
<Glyph value="m"/>
<Glyph value="n"/>
<Glyph value="o"/>
<Glyph value="p"/>
<Glyph value="q"/>
<Glyph value="r"/>
<Glyph value="s"/>
<Glyph value="t"/>
<Glyph value="u"/>
<Glyph value="v"/>
<Glyph value="w"/>
<Glyph value="x"/>
<Glyph value="y"/>
<Glyph value="z"/>
</LookAheadCoverage>
<!-- SubstCount=0 -->
</ChainContextSubst>
<ChainContextSubst index="3" Format="3">
<!-- BacktrackGlyphCount=0 -->
<!-- InputGlyphCount=1 -->
<InputCoverage index="0">
<Glyph value="a"/>
<Glyph value="e"/>
<Glyph value="z"/>
</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="A" out="A.swash"/>
<Substitution in="B" out="B.swash"/>
<Substitution in="C" out="C.swash"/>
<Substitution in="D" out="D.swash"/>
<Substitution in="E" out="E.swash"/>
<Substitution in="F" out="F.swash"/>
<Substitution in="G" out="G.swash"/>
<Substitution in="H" out="H.swash"/>
<Substitution in="I" out="I.swash"/>
<Substitution in="J" out="J.swash"/>
<Substitution in="K" out="K.swash"/>
<Substitution in="L" out="L.swash"/>
<Substitution in="M" out="M.swash"/>
<Substitution in="N" out="N.swash"/>
<Substitution in="P" out="P.swash"/>
<Substitution in="Q" out="Q.swash"/>
<Substitution in="R" out="R.swash"/>
<Substitution in="S" out="S.swash"/>
<Substitution in="T" out="T.swash"/>
<Substitution in="T_h" out="T_h.swash"/>
<Substitution in="U" out="U.swash"/>
<Substitution in="V" out="V.swash"/>
<Substitution in="W" out="W.swash"/>
<Substitution in="X" out="X.swash"/>
<Substitution in="Y" out="Y.swash"/>
<Substitution in="Z" out="Z.swash"/>
<Substitution in="a" out="a.end"/>
<Substitution in="e" out="e.end"/>
<Substitution in="m" out="m.begin"/>
<Substitution in="z" out="z.end"/>
</SingleSubst>
</Lookup>
</LookupList>
</GSUB>
</ttFont>