diff options
Diffstat (limited to 'Tests/feaLib')
-rw-r--r-- | Tests/feaLib/STAT2.fea | 4 | ||||
-rw-r--r-- | Tests/feaLib/builder_test.py | 213 | ||||
-rw-r--r-- | Tests/feaLib/data/GPOS_2.ttx | 1 | ||||
-rw-r--r-- | Tests/feaLib/data/GPOS_2b.ttx | 5 | ||||
-rw-r--r-- | Tests/feaLib/data/GPOS_4.fea | 10 | ||||
-rw-r--r-- | Tests/feaLib/data/GPOS_5.fea | 29 | ||||
-rw-r--r-- | Tests/feaLib/data/GPOS_6.fea | 7 | ||||
-rw-r--r-- | Tests/feaLib/data/PairPosSubtable.ttx | 5 | ||||
-rw-r--r-- | Tests/feaLib/data/STAT_bad.fea | 96 | ||||
-rw-r--r-- | Tests/feaLib/data/STAT_test.fea | 109 | ||||
-rw-r--r-- | Tests/feaLib/data/STAT_test.ttx | 228 | ||||
-rw-r--r-- | Tests/feaLib/data/STAT_test_elidedFallbackNameID.fea | 84 | ||||
-rw-r--r-- | Tests/feaLib/data/STAT_test_elidedFallbackNameID.ttx | 225 | ||||
-rw-r--r-- | Tests/feaLib/data/bug453.fea | 6 | ||||
-rw-r--r-- | Tests/feaLib/data/bug633.ttx | 1 | ||||
-rw-r--r-- | Tests/feaLib/data/size2.ttx | 4 | ||||
-rw-r--r-- | Tests/feaLib/data/spec6b_ii.ttx | 1 | ||||
-rw-r--r-- | Tests/feaLib/data/spec6d2.fea | 10 | ||||
-rw-r--r-- | Tests/feaLib/data/spec6e.fea | 9 | ||||
-rw-r--r-- | Tests/feaLib/data/spec6f.fea | 3 | ||||
-rw-r--r-- | Tests/feaLib/data/spec6h_ii.fea | 6 | ||||
-rw-r--r-- | Tests/feaLib/lexer_test.py | 9 | ||||
-rw-r--r-- | Tests/feaLib/parser_test.py | 70 |
23 files changed, 1100 insertions, 35 deletions
diff --git a/Tests/feaLib/STAT2.fea b/Tests/feaLib/STAT2.fea new file mode 100644 index 00000000..2595a9a4 --- /dev/null +++ b/Tests/feaLib/STAT2.fea @@ -0,0 +1,4 @@ +table STAT { + ElidedFallbackName { name "Roman"; }; + DesignAxis zonk 0 { name "Zonkey"; };' +} STAT; diff --git a/Tests/feaLib/builder_test.py b/Tests/feaLib/builder_test.py index 279e8ca8..0a55239c 100644 --- a/Tests/feaLib/builder_test.py +++ b/Tests/feaLib/builder_test.py @@ -1,4 +1,3 @@ -from fontTools.misc.py23 import * from fontTools.misc.loggingTools import CapturingLogHandler from fontTools.feaLib.builder import Builder, addOpenTypeFeatures, \ addOpenTypeFeaturesFromString @@ -8,7 +7,9 @@ from fontTools.feaLib.parser import Parser from fontTools.feaLib import ast from fontTools.feaLib.lexer import Lexer import difflib +from io import StringIO import os +import re import shutil import sys import tempfile @@ -73,7 +74,7 @@ class BuilderTest(unittest.TestCase): LigatureSubtable AlternateSubtable MultipleSubstSubtable SingleSubstSubtable aalt_chain_contextual_subst AlternateChained MultipleLookupsPerGlyph MultipleLookupsPerGlyph2 GSUB_6_formats - GSUB_5_formats delete_glyph + GSUB_5_formats delete_glyph STAT_test STAT_test_elidedFallbackNameID """.split() def __init__(self, methodName): @@ -118,7 +119,7 @@ class BuilderTest(unittest.TestCase): def expect_ttx(self, font, expected_ttx, replace=None): path = self.temp_path(suffix=".ttx") font.saveXML(path, tables=['head', 'name', 'BASE', 'GDEF', 'GSUB', - 'GPOS', 'OS/2', 'hhea', 'vhea']) + 'GPOS', 'OS/2', 'STAT', 'hhea', 'vhea']) actual = self.read_ttx(path) expected = self.read_ttx(expected_ttx) if replace: @@ -141,10 +142,15 @@ class BuilderTest(unittest.TestCase): feapath = self.getpath("%s.fea" % name) addOpenTypeFeatures(font, feapath) self.expect_ttx(font, self.getpath("%s.ttx" % name)) - # Make sure we can produce binary OpenType tables, not just XML. + # Check that: + # 1) tables do compile (only G* tables as long as we have a mock font) + # 2) dumping after save-reload yields the same TTX dump as before for tag in ('GDEF', 'GSUB', 'GPOS'): if tag in font: - font[tag].compile(font) + data = font[tag].compile(font) + font[tag].decompile(data, font) + self.expect_ttx(font, self.getpath("%s.ttx" % name)) + # Optionally check a debug dump. debugttx = self.getpath("%s-debug.ttx" % name) if os.path.exists(debugttx): addOpenTypeFeatures(font, feapath, debug=True) @@ -463,6 +469,201 @@ class BuilderTest(unittest.TestCase): "} test;" ) + def test_STAT_elidedfallbackname_already_defined(self): + self.assertRaisesRegex( + FeatureLibError, + 'ElidedFallbackName is already set.', + self.build, + 'table name {' + ' nameid 256 "Roman"; ' + '} name;' + 'table STAT {' + ' ElidedFallbackName { name "Roman"; };' + ' ElidedFallbackNameID 256;' + '} STAT;') + + def test_STAT_elidedfallbackname_set_twice(self): + self.assertRaisesRegex( + FeatureLibError, + 'ElidedFallbackName is already set.', + self.build, + 'table name {' + ' nameid 256 "Roman"; ' + '} name;' + 'table STAT {' + ' ElidedFallbackName { name "Roman"; };' + ' ElidedFallbackName { name "Italic"; };' + '} STAT;') + + def test_STAT_elidedfallbacknameID_already_defined(self): + self.assertRaisesRegex( + FeatureLibError, + 'ElidedFallbackNameID is already set.', + self.build, + 'table name {' + ' nameid 256 "Roman"; ' + '} name;' + 'table STAT {' + ' ElidedFallbackNameID 256;' + ' ElidedFallbackName { name "Roman"; };' + '} STAT;') + + def test_STAT_elidedfallbacknameID_not_in_name_table(self): + self.assertRaisesRegex( + FeatureLibError, + 'ElidedFallbackNameID 256 points to a nameID that does not ' + 'exist in the "name" table', + self.build, + 'table name {' + ' nameid 257 "Roman"; ' + '} name;' + 'table STAT {' + ' ElidedFallbackNameID 256;' + ' DesignAxis opsz 1 { name "Optical Size"; };' + '} STAT;') + + def test_STAT_design_axis_name(self): + self.assertRaisesRegex( + FeatureLibError, + 'Expected "name"', + self.build, + 'table name {' + ' nameid 256 "Roman"; ' + '} name;' + 'table STAT {' + ' ElidedFallbackName { name "Roman"; };' + ' DesignAxis opsz 0 { badtag "Optical Size"; };' + '} STAT;') + + def test_STAT_duplicate_design_axis_name(self): + self.assertRaisesRegex( + FeatureLibError, + 'DesignAxis already defined for tag "opsz".', + self.build, + 'table name {' + ' nameid 256 "Roman"; ' + '} name;' + 'table STAT {' + ' ElidedFallbackName { name "Roman"; };' + ' DesignAxis opsz 0 { name "Optical Size"; };' + ' DesignAxis opsz 1 { name "Optical Size"; };' + '} STAT;') + + def test_STAT_design_axis_duplicate_order(self): + self.assertRaisesRegex( + FeatureLibError, + "DesignAxis already defined for axis number 0.", + self.build, + 'table name {' + ' nameid 256 "Roman"; ' + '} name;' + 'table STAT {' + ' ElidedFallbackName { name "Roman"; };' + ' DesignAxis opsz 0 { name "Optical Size"; };' + ' DesignAxis wdth 0 { name "Width"; };' + ' AxisValue {' + ' location opsz 8;' + ' location wdth 400;' + ' name "Caption";' + ' };' + '} STAT;') + + def test_STAT_undefined_tag(self): + self.assertRaisesRegex( + FeatureLibError, + 'DesignAxis not defined for wdth.', + self.build, + 'table name {' + ' nameid 256 "Roman"; ' + '} name;' + 'table STAT {' + ' ElidedFallbackName { name "Roman"; };' + ' DesignAxis opsz 0 { name "Optical Size"; };' + ' AxisValue { ' + ' location wdth 125; ' + ' name "Wide"; ' + ' };' + '} STAT;') + + def test_STAT_axis_value_format4(self): + self.assertRaisesRegex( + FeatureLibError, + 'Axis tag wdth already defined.', + self.build, + 'table name {' + ' nameid 256 "Roman"; ' + '} name;' + 'table STAT {' + ' ElidedFallbackName { name "Roman"; };' + ' DesignAxis opsz 0 { name "Optical Size"; };' + ' DesignAxis wdth 1 { name "Width"; };' + ' DesignAxis wght 2 { name "Weight"; };' + ' AxisValue { ' + ' location opsz 8; ' + ' location wdth 125; ' + ' location wdth 125; ' + ' location wght 500; ' + ' name "Caption Medium Wide"; ' + ' };' + '} STAT;') + + def test_STAT_duplicate_axis_value_record(self): + # Test for Duplicate AxisValueRecords even when the definition order + # is different. + self.assertRaisesRegex( + FeatureLibError, + 'An AxisValueRecord with these values is already defined.', + self.build, + 'table name {' + ' nameid 256 "Roman"; ' + '} name;' + 'table STAT {' + ' ElidedFallbackName { name "Roman"; };' + ' DesignAxis opsz 0 { name "Optical Size"; };' + ' DesignAxis wdth 1 { name "Width"; };' + ' AxisValue {' + ' location opsz 8;' + ' location wdth 400;' + ' name "Caption";' + ' };' + ' AxisValue {' + ' location wdth 400;' + ' location opsz 8;' + ' name "Caption";' + ' };' + '} STAT;') + + def test_STAT_axis_value_missing_location(self): + self.assertRaisesRegex( + FeatureLibError, + 'Expected "Axis location"', + self.build, + 'table name {' + ' nameid 256 "Roman"; ' + '} name;' + 'table STAT {' + ' ElidedFallbackName { name "Roman"; ' + '};' + ' DesignAxis opsz 0 { name "Optical Size"; };' + ' AxisValue { ' + ' name "Wide"; ' + ' };' + '} STAT;') + + def test_STAT_invalid_location_tag(self): + self.assertRaisesRegex( + FeatureLibError, + 'Tags cannot be longer than 4 characters', + self.build, + 'table name {' + ' nameid 256 "Roman"; ' + '} name;' + 'table STAT {' + ' ElidedFallbackName { name "Roman"; ' + ' name 3 1 0x0411 "ローマン"; }; ' + ' DesignAxis width 0 { name "Width"; };' + '} STAT;') + def test_extensions(self): class ast_BaseClass(ast.MarkClass): def asFea(self, indent=""): @@ -574,7 +775,7 @@ class BuilderTest(unittest.TestCase): self.assertRaises(NotImplementedError, self.build, "", tables={"FOO"}) def test_build_pre_parsed_ast_featurefile(self): - f = UnicodeIO("feature liga {sub f i by f_i;} liga;") + f = StringIO("feature liga {sub f i by f_i;} liga;") tree = Parser(f).parse() font = makeTTFont() addOpenTypeFeatures(font, tree) diff --git a/Tests/feaLib/data/GPOS_2.ttx b/Tests/feaLib/data/GPOS_2.ttx index 84dc8195..c9a6c146 100644 --- a/Tests/feaLib/data/GPOS_2.ttx +++ b/Tests/feaLib/data/GPOS_2.ttx @@ -76,6 +76,7 @@ <!-- Class2Count=2 --> <Class1Record index="0"> <Class2Record index="0"> + <Value1 XAdvance="0"/> </Class2Record> <Class2Record index="1"> <Value1 XAdvance="-26"/> diff --git a/Tests/feaLib/data/GPOS_2b.ttx b/Tests/feaLib/data/GPOS_2b.ttx index 40f458f2..8a892c1e 100644 --- a/Tests/feaLib/data/GPOS_2b.ttx +++ b/Tests/feaLib/data/GPOS_2b.ttx @@ -50,6 +50,7 @@ <!-- Class2Count=2 --> <Class1Record index="0"> <Class2Record index="0"> + <Value1 XAdvance="0"/> </Class2Record> <Class2Record index="1"> <Value1 XAdvance="1"/> @@ -79,6 +80,7 @@ <!-- Class2Count=3 --> <Class1Record index="0"> <Class2Record index="0"> + <Value1 XAdvance="0"/> </Class2Record> <Class2Record index="1"> <Value1 XAdvance="4"/> @@ -89,8 +91,10 @@ </Class1Record> <Class1Record index="1"> <Class2Record index="0"> + <Value1 XAdvance="0"/> </Class2Record> <Class2Record index="1"> + <Value1 XAdvance="0"/> </Class2Record> <Class2Record index="2"> <Value1 XAdvance="2"/> @@ -114,6 +118,7 @@ <!-- Class2Count=2 --> <Class1Record index="0"> <Class2Record index="0"> + <Value1 XPlacement="0" YPlacement="0" XAdvance="0" YAdvance="0"/> </Class2Record> <Class2Record index="1"> <Value1 XPlacement="5" YPlacement="5" XAdvance="5" YAdvance="5"/> diff --git a/Tests/feaLib/data/GPOS_4.fea b/Tests/feaLib/data/GPOS_4.fea index cfd2d757..7c90ab63 100644 --- a/Tests/feaLib/data/GPOS_4.fea +++ b/Tests/feaLib/data/GPOS_4.fea @@ -6,7 +6,11 @@ markClass [cedilla] <anchor 222 22> @BOTTOM_MARKS; markClass [ogonek] <anchor 333 33> @SIDE_MARKS; feature test { - pos base a <anchor 11 1> mark @TOP_MARKS <anchor 12 -1> mark @BOTTOM_MARKS; - pos base [b c] <anchor 22 -2> mark @BOTTOM_MARKS; - pos base d <anchor 33 3> mark @SIDE_MARKS; + pos base a + <anchor 11 1> mark @TOP_MARKS + <anchor 12 -1> mark @BOTTOM_MARKS; + pos base [b c] + <anchor 22 -2> mark @BOTTOM_MARKS; + pos base d + <anchor 33 3> mark @SIDE_MARKS; } test; diff --git a/Tests/feaLib/data/GPOS_5.fea b/Tests/feaLib/data/GPOS_5.fea index b116539a..a8f8536e 100644 --- a/Tests/feaLib/data/GPOS_5.fea +++ b/Tests/feaLib/data/GPOS_5.fea @@ -5,14 +5,29 @@ markClass [ogonek] <anchor 800 -10> @OGONEK; feature test { - pos ligature [c_t s_t] <anchor 500 800> mark @TOP_MARKS <anchor 500 -200> mark @BOTTOM_MARKS - ligComponent <anchor 1500 800> mark @TOP_MARKS <anchor 1500 -200> mark @BOTTOM_MARKS <anchor 1550 0> mark @OGONEK; + pos ligature [c_t s_t] + <anchor 500 800> mark @TOP_MARKS + <anchor 500 -200> mark @BOTTOM_MARKS + ligComponent + <anchor 1500 800> mark @TOP_MARKS + <anchor 1500 -200> mark @BOTTOM_MARKS + <anchor 1550 0> mark @OGONEK; - pos ligature f_l <anchor 300 800> mark @TOP_MARKS <anchor 300 -200> mark @BOTTOM_MARKS - ligComponent <anchor 600 800> mark @TOP_MARKS <anchor 600 -200> mark @BOTTOM_MARKS; + pos ligature f_l + <anchor 300 800> mark @TOP_MARKS + <anchor 300 -200> mark @BOTTOM_MARKS + ligComponent + <anchor 600 800> mark @TOP_MARKS + <anchor 600 -200> mark @BOTTOM_MARKS; - pos ligature [f_f_l] <anchor 300 800> mark @TOP_MARKS <anchor 300 -200> mark @BOTTOM_MARKS - ligComponent <anchor 600 800> mark @TOP_MARKS <anchor 600 -200> mark @BOTTOM_MARKS - ligComponent <anchor 900 800> mark @TOP_MARKS <anchor 900 -200> mark @BOTTOM_MARKS; + pos ligature [f_f_l] + <anchor 300 800> mark @TOP_MARKS + <anchor 300 -200> mark @BOTTOM_MARKS + ligComponent + <anchor 600 800> mark @TOP_MARKS + <anchor 600 -200> mark @BOTTOM_MARKS + ligComponent + <anchor 900 800> mark @TOP_MARKS + <anchor 900 -200> mark @BOTTOM_MARKS; } test; diff --git a/Tests/feaLib/data/GPOS_6.fea b/Tests/feaLib/data/GPOS_6.fea index 37b29365..e54ff6e3 100644 --- a/Tests/feaLib/data/GPOS_6.fea +++ b/Tests/feaLib/data/GPOS_6.fea @@ -5,6 +5,9 @@ markClass macron <anchor 2 2 contourpoint 22> @TOP_MARKS; markClass [cedilla] <anchor 3 3 contourpoint 33> @BOTTOM_MARKS; feature test { - pos mark [acute grave macron ogonek] <anchor 500 200> mark @TOP_MARKS <anchor 500 -80> mark @BOTTOM_MARKS; - pos mark [dieresis caron] <anchor 500 200> mark @TOP_MARKS; + pos mark [acute grave macron ogonek] + <anchor 500 200> mark @TOP_MARKS + <anchor 500 -80> mark @BOTTOM_MARKS; + pos mark [dieresis caron] + <anchor 500 200> mark @TOP_MARKS; } test; diff --git a/Tests/feaLib/data/PairPosSubtable.ttx b/Tests/feaLib/data/PairPosSubtable.ttx index 4b76f991..2d78f64f 100644 --- a/Tests/feaLib/data/PairPosSubtable.ttx +++ b/Tests/feaLib/data/PairPosSubtable.ttx @@ -76,6 +76,7 @@ <!-- Class2Count=2 --> <Class1Record index="0"> <Class2Record index="0"> + <Value1 XAdvance="0"/> </Class2Record> <Class2Record index="1"> <Value1 XAdvance="-12"/> @@ -105,8 +106,10 @@ <!-- Class2Count=3 --> <Class1Record index="0"> <Class2Record index="0"> + <Value1 XAdvance="0"/> </Class2Record> <Class2Record index="1"> + <Value1 XAdvance="0"/> </Class2Record> <Class2Record index="2"> <Value1 XAdvance="-20"/> @@ -114,11 +117,13 @@ </Class1Record> <Class1Record index="1"> <Class2Record index="0"> + <Value1 XAdvance="0"/> </Class2Record> <Class2Record index="1"> <Value1 XAdvance="-10"/> </Class2Record> <Class2Record index="2"> + <Value1 XAdvance="0"/> </Class2Record> </Class1Record> </PairPos> diff --git a/Tests/feaLib/data/STAT_bad.fea b/Tests/feaLib/data/STAT_bad.fea new file mode 100644 index 00000000..8ec887f0 --- /dev/null +++ b/Tests/feaLib/data/STAT_bad.fea @@ -0,0 +1,96 @@ +# bad fea file: Testing DesignAxis tag with incorrect label +table name { + nameid 25 "TestFont"; +} name; + + +table STAT { + + ElidedFallbackName { name "Roman"; }; + + DesignAxis opsz 0 { badtag "Optical Size"; }; #'badtag' instead of 'name' is incorrect + DesignAxis wdth 1 { name "Width"; }; + DesignAxis wght 2 { name "Weight"; }; + DesignAxis ital 3 { name "Italic"; }; + + AxisValue { + location opsz 8 5 9; + location wdth 300 350 450; + name "Caption"; + }; + + AxisValue { + location opsz 11 9 12; + name "Text"; + flag OlderSiblingFontAttribute ElidableAxisValueName ; + }; + + AxisValue { + location opsz 16.7 12 24; + name "Subhead"; + }; + + AxisValue { + location opsz 72 24 72; + name "Display"; + }; + + AxisValue { + location wdth 80 80 89; + name "Condensed"; + }; + + AxisValue { + location wdth 90 90 96; + name "Semicondensed"; + }; + + AxisValue { + location wdth 100 97 101; + name "Normal"; + flag ElidableAxisValueName; + }; + + AxisValue { + location wdth 125 102 125; + name "Extended"; + }; + + AxisValue { + location wght 300 300 349; + name "Light"; + }; + + AxisValue { + location wght 400 350 449; + name "Regular"; + flag ElidableAxisValueName; + }; + + AxisValue { + location wght 500 450 549; + name "Medium"; + }; + + AxisValue { + location wght 600 550 649; + name "Semibold"; + }; + + AxisValue { + location wght 700 650 749; + name "Bold"; + }; + + AxisValue { + location wght 900 750 900; + name "Black"; + }; + + AxisValue { + location ital 0; + name "Roman"; + flag ElidableAxisValueName; + }; + +} STAT; diff --git a/Tests/feaLib/data/STAT_test.fea b/Tests/feaLib/data/STAT_test.fea new file mode 100644 index 00000000..01036376 --- /dev/null +++ b/Tests/feaLib/data/STAT_test.fea @@ -0,0 +1,109 @@ +table name { + nameid 25 "TestFont"; +} name; + + +table STAT { + + ElidedFallbackName { + name "Roman"; + name 3 1 1041 "ローマン"; + }; + + DesignAxis opsz 0 { + name "Optical Size"; + }; + + DesignAxis wdth 1 { + name "Width"; + }; + + DesignAxis wght 2 { + name "Weight"; + }; + + DesignAxis ital 3 { + name "Italic"; + }; # here comment + + AxisValue { + location opsz 8; # comment here + location wdth 400; # another comment + name "Caption"; # more comments + }; + + AxisValue { + location opsz 11 9 12; + name "Text"; + flag OlderSiblingFontAttribute ElidableAxisValueName; + }; + + AxisValue { + location opsz 16.7 12 24; + name "Subhead"; + }; + + AxisValue { + location opsz 72 24 72; + name "Display"; + }; + + AxisValue { + location wdth 80 80 89; + name "Condensed"; + }; + + AxisValue { + location wdth 90 90 96; + name "Semicondensed"; + }; + + AxisValue { + location wdth 100 97 101; + name "Normal"; + flag ElidableAxisValueName; + }; + + AxisValue { + location wdth 125 102 125; + name "Extended"; + }; + + AxisValue { + location wght 300 300 349; + name "Light"; + }; + + AxisValue { + location wght 400 350 449; + name "Regular"; + flag ElidableAxisValueName; + }; + + AxisValue { + location wght 500 450 549; + name "Medium"; + }; + + AxisValue { + location wght 600 550 649; + name "Semibold"; + }; + + AxisValue { + location wght 700 650 749; + name "Bold"; + }; + + AxisValue { + location wght 900 750 900; + name "Black"; + }; + + AxisValue { + location ital 0; + name "Roman"; + flag ElidableAxisValueName; # flag comment + }; + +} STAT; diff --git a/Tests/feaLib/data/STAT_test.ttx b/Tests/feaLib/data/STAT_test.ttx new file mode 100644 index 00000000..d1b2b697 --- /dev/null +++ b/Tests/feaLib/data/STAT_test.ttx @@ -0,0 +1,228 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.20"> + + <name> + <namerecord nameID="25" platformID="3" platEncID="1" langID="0x409"> + TestFont + </namerecord> + <namerecord nameID="256" platformID="3" platEncID="1" langID="0x409"> + Roman + </namerecord> + <namerecord nameID="256" platformID="3" platEncID="1" langID="0x411"> + ローマン + </namerecord> + <namerecord nameID="257" platformID="3" platEncID="1" langID="0x409"> + Optical Size + </namerecord> + <namerecord nameID="258" platformID="3" platEncID="1" langID="0x409"> + Text + </namerecord> + <namerecord nameID="259" platformID="3" platEncID="1" langID="0x409"> + Subhead + </namerecord> + <namerecord nameID="260" platformID="3" platEncID="1" langID="0x409"> + Display + </namerecord> + <namerecord nameID="261" platformID="3" platEncID="1" langID="0x409"> + Width + </namerecord> + <namerecord nameID="262" platformID="3" platEncID="1" langID="0x409"> + Condensed + </namerecord> + <namerecord nameID="263" platformID="3" platEncID="1" langID="0x409"> + Semicondensed + </namerecord> + <namerecord nameID="264" platformID="3" platEncID="1" langID="0x409"> + Normal + </namerecord> + <namerecord nameID="265" platformID="3" platEncID="1" langID="0x409"> + Extended + </namerecord> + <namerecord nameID="266" platformID="3" platEncID="1" langID="0x409"> + Weight + </namerecord> + <namerecord nameID="267" platformID="3" platEncID="1" langID="0x409"> + Light + </namerecord> + <namerecord nameID="268" platformID="3" platEncID="1" langID="0x409"> + Regular + </namerecord> + <namerecord nameID="269" platformID="3" platEncID="1" langID="0x409"> + Medium + </namerecord> + <namerecord nameID="270" platformID="3" platEncID="1" langID="0x409"> + Semibold + </namerecord> + <namerecord nameID="271" platformID="3" platEncID="1" langID="0x409"> + Bold + </namerecord> + <namerecord nameID="272" platformID="3" platEncID="1" langID="0x409"> + Black + </namerecord> + <namerecord nameID="273" platformID="3" platEncID="1" langID="0x409"> + Italic + </namerecord> + <namerecord nameID="274" platformID="3" platEncID="1" langID="0x409"> + Roman + </namerecord> + <namerecord nameID="275" platformID="3" platEncID="1" langID="0x409"> + Caption + </namerecord> + </name> + + <STAT> + <Version value="0x00010002"/> + <DesignAxisRecordSize value="8"/> + <!-- DesignAxisCount=4 --> + <DesignAxisRecord> + <Axis index="0"> + <AxisTag value="opsz"/> + <AxisNameID value="257"/> <!-- Optical Size --> + <AxisOrdering value="0"/> + </Axis> + <Axis index="1"> + <AxisTag value="wdth"/> + <AxisNameID value="261"/> <!-- Width --> + <AxisOrdering value="1"/> + </Axis> + <Axis index="2"> + <AxisTag value="wght"/> + <AxisNameID value="266"/> <!-- Weight --> + <AxisOrdering value="2"/> + </Axis> + <Axis index="3"> + <AxisTag value="ital"/> + <AxisNameID value="273"/> <!-- Italic --> + <AxisOrdering value="3"/> + </Axis> + </DesignAxisRecord> + <!-- AxisValueCount=15 --> + <AxisValueArray> + <AxisValue index="0" Format="4"> + <!-- AxisCount=2 --> + <Flags value="0"/> + <ValueNameID value="275"/> <!-- Caption --> + <AxisValueRecord index="0"> + <AxisIndex value="0"/> + <Value value="8.0"/> + </AxisValueRecord> + <AxisValueRecord index="1"> + <AxisIndex value="1"/> + <Value value="400.0"/> + </AxisValueRecord> + </AxisValue> + <AxisValue index="1" Format="2"> + <AxisIndex value="0"/> + <Flags value="3"/> <!-- OlderSiblingFontAttribute ElidableAxisValueName --> + <ValueNameID value="258"/> <!-- Text --> + <NominalValue value="11.0"/> + <RangeMinValue value="9.0"/> + <RangeMaxValue value="12.0"/> + </AxisValue> + <AxisValue index="2" Format="2"> + <AxisIndex value="0"/> + <Flags value="0"/> + <ValueNameID value="259"/> <!-- Subhead --> + <NominalValue value="16.7"/> + <RangeMinValue value="12.0"/> + <RangeMaxValue value="24.0"/> + </AxisValue> + <AxisValue index="3" Format="2"> + <AxisIndex value="0"/> + <Flags value="0"/> + <ValueNameID value="260"/> <!-- Display --> + <NominalValue value="72.0"/> + <RangeMinValue value="24.0"/> + <RangeMaxValue value="72.0"/> + </AxisValue> + <AxisValue index="4" Format="2"> + <AxisIndex value="1"/> + <Flags value="0"/> + <ValueNameID value="262"/> <!-- Condensed --> + <NominalValue value="80.0"/> + <RangeMinValue value="80.0"/> + <RangeMaxValue value="89.0"/> + </AxisValue> + <AxisValue index="5" Format="2"> + <AxisIndex value="1"/> + <Flags value="0"/> + <ValueNameID value="263"/> <!-- Semicondensed --> + <NominalValue value="90.0"/> + <RangeMinValue value="90.0"/> + <RangeMaxValue value="96.0"/> + </AxisValue> + <AxisValue index="6" Format="2"> + <AxisIndex value="1"/> + <Flags value="2"/> <!-- ElidableAxisValueName --> + <ValueNameID value="264"/> <!-- Normal --> + <NominalValue value="100.0"/> + <RangeMinValue value="97.0"/> + <RangeMaxValue value="101.0"/> + </AxisValue> + <AxisValue index="7" Format="2"> + <AxisIndex value="1"/> + <Flags value="0"/> + <ValueNameID value="265"/> <!-- Extended --> + <NominalValue value="125.0"/> + <RangeMinValue value="102.0"/> + <RangeMaxValue value="125.0"/> + </AxisValue> + <AxisValue index="8" Format="2"> + <AxisIndex value="2"/> + <Flags value="0"/> + <ValueNameID value="267"/> <!-- Light --> + <NominalValue value="300.0"/> + <RangeMinValue value="300.0"/> + <RangeMaxValue value="349.0"/> + </AxisValue> + <AxisValue index="9" Format="2"> + <AxisIndex value="2"/> + <Flags value="2"/> <!-- ElidableAxisValueName --> + <ValueNameID value="268"/> <!-- Regular --> + <NominalValue value="400.0"/> + <RangeMinValue value="350.0"/> + <RangeMaxValue value="449.0"/> + </AxisValue> + <AxisValue index="10" Format="2"> + <AxisIndex value="2"/> + <Flags value="0"/> + <ValueNameID value="269"/> <!-- Medium --> + <NominalValue value="500.0"/> + <RangeMinValue value="450.0"/> + <RangeMaxValue value="549.0"/> + </AxisValue> + <AxisValue index="11" Format="2"> + <AxisIndex value="2"/> + <Flags value="0"/> + <ValueNameID value="270"/> <!-- Semibold --> + <NominalValue value="600.0"/> + <RangeMinValue value="550.0"/> + <RangeMaxValue value="649.0"/> + </AxisValue> + <AxisValue index="12" Format="2"> + <AxisIndex value="2"/> + <Flags value="0"/> + <ValueNameID value="271"/> <!-- Bold --> + <NominalValue value="700.0"/> + <RangeMinValue value="650.0"/> + <RangeMaxValue value="749.0"/> + </AxisValue> + <AxisValue index="13" Format="2"> + <AxisIndex value="2"/> + <Flags value="0"/> + <ValueNameID value="272"/> <!-- Black --> + <NominalValue value="900.0"/> + <RangeMinValue value="750.0"/> + <RangeMaxValue value="900.0"/> + </AxisValue> + <AxisValue index="14" Format="1"> + <AxisIndex value="3"/> + <Flags value="2"/> <!-- ElidableAxisValueName --> + <ValueNameID value="274"/> <!-- Roman --> + <Value value="0.0"/> + </AxisValue> + </AxisValueArray> + <ElidedFallbackNameID value="256"/> <!-- Roman --> + </STAT> + +</ttFont> diff --git a/Tests/feaLib/data/STAT_test_elidedFallbackNameID.fea b/Tests/feaLib/data/STAT_test_elidedFallbackNameID.fea new file mode 100644 index 00000000..5a141803 --- /dev/null +++ b/Tests/feaLib/data/STAT_test_elidedFallbackNameID.fea @@ -0,0 +1,84 @@ +table name { + nameid 25 "TestFont"; + nameid 256 "Roman"; +} name; +table STAT { + ElidedFallbackNameID 256; + DesignAxis opsz 0 { + name "Optical Size"; + }; + DesignAxis wdth 1 { + name "Width"; + }; + DesignAxis wght 2 { + name "Weight"; + }; + DesignAxis ital 3 { + name "Italic"; + }; # here comment + AxisValue { + location opsz 8; # comment here + location wdth 400; # another comment + name "Caption"; # more comments + }; + AxisValue { + location opsz 11 9 12; + name "Text"; + flag OlderSiblingFontAttribute ElidableAxisValueName; + }; + AxisValue { + location opsz 16.7 12 24; + name "Subhead"; + }; + AxisValue { + location opsz 72 24 72; + name "Display"; + }; + AxisValue { + location wdth 80 80 89; + name "Condensed"; + }; + AxisValue { + location wdth 90 90 96; + name "Semicondensed"; + }; + AxisValue { + location wdth 100 97 101; + name "Normal"; + flag ElidableAxisValueName; + }; + AxisValue { + location wdth 125 102 125; + name "Extended"; + }; + AxisValue { + location wght 300 300 349; + name "Light"; + }; + AxisValue { + location wght 400 350 449; + name "Regular"; + flag ElidableAxisValueName; + }; + AxisValue { + location wght 500 450 549; + name "Medium"; + }; + AxisValue { + location wght 600 550 649; + name "Semibold"; + }; + AxisValue { + location wght 700 650 749; + name "Bold"; + }; + AxisValue { + location wght 900 750 900; + name "Black"; + }; + AxisValue { + location ital 0; + name "Roman"; + flag ElidableAxisValueName; # flag comment + }; +} STAT;
\ No newline at end of file diff --git a/Tests/feaLib/data/STAT_test_elidedFallbackNameID.ttx b/Tests/feaLib/data/STAT_test_elidedFallbackNameID.ttx new file mode 100644 index 00000000..32802e0f --- /dev/null +++ b/Tests/feaLib/data/STAT_test_elidedFallbackNameID.ttx @@ -0,0 +1,225 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.20"> + + <name> + <namerecord nameID="25" platformID="3" platEncID="1" langID="0x409"> + TestFont + </namerecord> + <namerecord nameID="256" platformID="3" platEncID="1" langID="0x409"> + Roman + </namerecord> + <namerecord nameID="257" platformID="3" platEncID="1" langID="0x409"> + Optical Size + </namerecord> + <namerecord nameID="258" platformID="3" platEncID="1" langID="0x409"> + Text + </namerecord> + <namerecord nameID="259" platformID="3" platEncID="1" langID="0x409"> + Subhead + </namerecord> + <namerecord nameID="260" platformID="3" platEncID="1" langID="0x409"> + Display + </namerecord> + <namerecord nameID="261" platformID="3" platEncID="1" langID="0x409"> + Width + </namerecord> + <namerecord nameID="262" platformID="3" platEncID="1" langID="0x409"> + Condensed + </namerecord> + <namerecord nameID="263" platformID="3" platEncID="1" langID="0x409"> + Semicondensed + </namerecord> + <namerecord nameID="264" platformID="3" platEncID="1" langID="0x409"> + Normal + </namerecord> + <namerecord nameID="265" platformID="3" platEncID="1" langID="0x409"> + Extended + </namerecord> + <namerecord nameID="266" platformID="3" platEncID="1" langID="0x409"> + Weight + </namerecord> + <namerecord nameID="267" platformID="3" platEncID="1" langID="0x409"> + Light + </namerecord> + <namerecord nameID="268" platformID="3" platEncID="1" langID="0x409"> + Regular + </namerecord> + <namerecord nameID="269" platformID="3" platEncID="1" langID="0x409"> + Medium + </namerecord> + <namerecord nameID="270" platformID="3" platEncID="1" langID="0x409"> + Semibold + </namerecord> + <namerecord nameID="271" platformID="3" platEncID="1" langID="0x409"> + Bold + </namerecord> + <namerecord nameID="272" platformID="3" platEncID="1" langID="0x409"> + Black + </namerecord> + <namerecord nameID="273" platformID="3" platEncID="1" langID="0x409"> + Italic + </namerecord> + <namerecord nameID="274" platformID="3" platEncID="1" langID="0x409"> + Roman + </namerecord> + <namerecord nameID="275" platformID="3" platEncID="1" langID="0x409"> + Caption + </namerecord> + </name> + + <STAT> + <Version value="0x00010002"/> + <DesignAxisRecordSize value="8"/> + <!-- DesignAxisCount=4 --> + <DesignAxisRecord> + <Axis index="0"> + <AxisTag value="opsz"/> + <AxisNameID value="257"/> <!-- Optical Size --> + <AxisOrdering value="0"/> + </Axis> + <Axis index="1"> + <AxisTag value="wdth"/> + <AxisNameID value="261"/> <!-- Width --> + <AxisOrdering value="1"/> + </Axis> + <Axis index="2"> + <AxisTag value="wght"/> + <AxisNameID value="266"/> <!-- Weight --> + <AxisOrdering value="2"/> + </Axis> + <Axis index="3"> + <AxisTag value="ital"/> + <AxisNameID value="273"/> <!-- Italic --> + <AxisOrdering value="3"/> + </Axis> + </DesignAxisRecord> + <!-- AxisValueCount=15 --> + <AxisValueArray> + <AxisValue index="0" Format="4"> + <!-- AxisCount=2 --> + <Flags value="0"/> + <ValueNameID value="275"/> <!-- Caption --> + <AxisValueRecord index="0"> + <AxisIndex value="0"/> + <Value value="8.0"/> + </AxisValueRecord> + <AxisValueRecord index="1"> + <AxisIndex value="1"/> + <Value value="400.0"/> + </AxisValueRecord> + </AxisValue> + <AxisValue index="1" Format="2"> + <AxisIndex value="0"/> + <Flags value="3"/> <!-- OlderSiblingFontAttribute ElidableAxisValueName --> + <ValueNameID value="258"/> <!-- Text --> + <NominalValue value="11.0"/> + <RangeMinValue value="9.0"/> + <RangeMaxValue value="12.0"/> + </AxisValue> + <AxisValue index="2" Format="2"> + <AxisIndex value="0"/> + <Flags value="0"/> + <ValueNameID value="259"/> <!-- Subhead --> + <NominalValue value="16.7"/> + <RangeMinValue value="12.0"/> + <RangeMaxValue value="24.0"/> + </AxisValue> + <AxisValue index="3" Format="2"> + <AxisIndex value="0"/> + <Flags value="0"/> + <ValueNameID value="260"/> <!-- Display --> + <NominalValue value="72.0"/> + <RangeMinValue value="24.0"/> + <RangeMaxValue value="72.0"/> + </AxisValue> + <AxisValue index="4" Format="2"> + <AxisIndex value="1"/> + <Flags value="0"/> + <ValueNameID value="262"/> <!-- Condensed --> + <NominalValue value="80.0"/> + <RangeMinValue value="80.0"/> + <RangeMaxValue value="89.0"/> + </AxisValue> + <AxisValue index="5" Format="2"> + <AxisIndex value="1"/> + <Flags value="0"/> + <ValueNameID value="263"/> <!-- Semicondensed --> + <NominalValue value="90.0"/> + <RangeMinValue value="90.0"/> + <RangeMaxValue value="96.0"/> + </AxisValue> + <AxisValue index="6" Format="2"> + <AxisIndex value="1"/> + <Flags value="2"/> <!-- ElidableAxisValueName --> + <ValueNameID value="264"/> <!-- Normal --> + <NominalValue value="100.0"/> + <RangeMinValue value="97.0"/> + <RangeMaxValue value="101.0"/> + </AxisValue> + <AxisValue index="7" Format="2"> + <AxisIndex value="1"/> + <Flags value="0"/> + <ValueNameID value="265"/> <!-- Extended --> + <NominalValue value="125.0"/> + <RangeMinValue value="102.0"/> + <RangeMaxValue value="125.0"/> + </AxisValue> + <AxisValue index="8" Format="2"> + <AxisIndex value="2"/> + <Flags value="0"/> + <ValueNameID value="267"/> <!-- Light --> + <NominalValue value="300.0"/> + <RangeMinValue value="300.0"/> + <RangeMaxValue value="349.0"/> + </AxisValue> + <AxisValue index="9" Format="2"> + <AxisIndex value="2"/> + <Flags value="2"/> <!-- ElidableAxisValueName --> + <ValueNameID value="268"/> <!-- Regular --> + <NominalValue value="400.0"/> + <RangeMinValue value="350.0"/> + <RangeMaxValue value="449.0"/> + </AxisValue> + <AxisValue index="10" Format="2"> + <AxisIndex value="2"/> + <Flags value="0"/> + <ValueNameID value="269"/> <!-- Medium --> + <NominalValue value="500.0"/> + <RangeMinValue value="450.0"/> + <RangeMaxValue value="549.0"/> + </AxisValue> + <AxisValue index="11" Format="2"> + <AxisIndex value="2"/> + <Flags value="0"/> + <ValueNameID value="270"/> <!-- Semibold --> + <NominalValue value="600.0"/> + <RangeMinValue value="550.0"/> + <RangeMaxValue value="649.0"/> + </AxisValue> + <AxisValue index="12" Format="2"> + <AxisIndex value="2"/> + <Flags value="0"/> + <ValueNameID value="271"/> <!-- Bold --> + <NominalValue value="700.0"/> + <RangeMinValue value="650.0"/> + <RangeMaxValue value="749.0"/> + </AxisValue> + <AxisValue index="13" Format="2"> + <AxisIndex value="2"/> + <Flags value="0"/> + <ValueNameID value="272"/> <!-- Black --> + <NominalValue value="900.0"/> + <RangeMinValue value="750.0"/> + <RangeMaxValue value="900.0"/> + </AxisValue> + <AxisValue index="14" Format="1"> + <AxisIndex value="3"/> + <Flags value="2"/> <!-- ElidableAxisValueName --> + <ValueNameID value="274"/> <!-- Roman --> + <Value value="0.0"/> + </AxisValue> + </AxisValueArray> + <ElidedFallbackNameID value="256"/> <!-- Roman --> + </STAT> + +</ttFont> diff --git a/Tests/feaLib/data/bug453.fea b/Tests/feaLib/data/bug453.fea index 486632ee..ed0e6f94 100644 --- a/Tests/feaLib/data/bug453.fea +++ b/Tests/feaLib/data/bug453.fea @@ -2,10 +2,12 @@ feature mark { lookup mark1 { markClass [acute] <anchor 150 -10> @TOP_MARKS; - pos base [e] <anchor 250 450> mark @TOP_MARKS; + pos base [e] + <anchor 250 450> mark @TOP_MARKS; } mark1; lookup mark2 { markClass [acute] <anchor 150 -20> @TOP_MARKS_2; - pos base [e] <anchor 250 450> mark @TOP_MARKS_2; + pos base [e] + <anchor 250 450> mark @TOP_MARKS_2; } mark2; } mark; diff --git a/Tests/feaLib/data/bug633.ttx b/Tests/feaLib/data/bug633.ttx index b119ebbe..075c1777 100644 --- a/Tests/feaLib/data/bug633.ttx +++ b/Tests/feaLib/data/bug633.ttx @@ -52,6 +52,7 @@ <!-- Class2Count=3 --> <Class1Record index="0"> <Class2Record index="0"> + <Value1 XAdvance="0"/> </Class2Record> <Class2Record index="1"> <Value1 XAdvance="0"/> diff --git a/Tests/feaLib/data/size2.ttx b/Tests/feaLib/data/size2.ttx index a822af36..1a12ddfc 100644 --- a/Tests/feaLib/data/size2.ttx +++ b/Tests/feaLib/data/size2.ttx @@ -26,8 +26,8 @@ <DesignSize value="10.0"/> <SubfamilyID value="0"/> <SubfamilyNameID value="0"/> - <RangeStart value="0"/> - <RangeEnd value="0"/> + <RangeStart value="0.0"/> + <RangeEnd value="0.0"/> </FeatureParamsSize> <!-- LookupCount=0 --> </Feature> diff --git a/Tests/feaLib/data/spec6b_ii.ttx b/Tests/feaLib/data/spec6b_ii.ttx index a7131ded..c7b8de81 100644 --- a/Tests/feaLib/data/spec6b_ii.ttx +++ b/Tests/feaLib/data/spec6b_ii.ttx @@ -91,6 +91,7 @@ <!-- Class2Count=2 --> <Class1Record index="0"> <Class2Record index="0"> + <Value1 XAdvance="0"/> </Class2Record> <Class2Record index="1"> <Value1 XAdvance="-100"/> diff --git a/Tests/feaLib/data/spec6d2.fea b/Tests/feaLib/data/spec6d2.fea index ead224fe..5c2620d2 100644 --- a/Tests/feaLib/data/spec6d2.fea +++ b/Tests/feaLib/data/spec6d2.fea @@ -9,7 +9,11 @@ markClass [dieresis umlaut] <anchor 300 -10> @TOP_MARKS; markClass [cedilla] <anchor 300 600> @BOTTOM_MARKS; feature test { - pos base [e o] <anchor 250 450> mark @TOP_MARKS <anchor 250 -12> mark @BOTTOM_MARKS; -#test-fea2fea: pos base [a u] <anchor 265 450> mark @TOP_MARKS <anchor 250 -10> mark @BOTTOM_MARKS; - position base [a u] <anchor 265 450> mark @TOP_MARKS <anchor 250-10> mark @BOTTOM_MARKS; + pos base [e o] + <anchor 250 450> mark @TOP_MARKS + <anchor 250 -12> mark @BOTTOM_MARKS; +#test-fea2fea: pos base [a u] + position base [a u] + <anchor 265 450> mark @TOP_MARKS + <anchor 250 -10> mark @BOTTOM_MARKS; } test; diff --git a/Tests/feaLib/data/spec6e.fea b/Tests/feaLib/data/spec6e.fea index ed956c8f..64612232 100644 --- a/Tests/feaLib/data/spec6e.fea +++ b/Tests/feaLib/data/spec6e.fea @@ -4,7 +4,10 @@ markClass sukun <anchor 261 488> @TOP_MARKS; markClass kasratan <anchor 346 -98> @BOTTOM_MARKS; feature test { - pos ligature lam_meem_jeem <anchor 625 1800> mark @TOP_MARKS # mark above lam - ligComponent <anchor 376 -368> mark @BOTTOM_MARKS # mark below meem - ligComponent <anchor NULL>; # jeem has no marks + pos ligature lam_meem_jeem + <anchor 625 1800> mark @TOP_MARKS # mark above lam + ligComponent + <anchor 376 -368> mark @BOTTOM_MARKS # mark below meem + ligComponent + <anchor NULL>; # jeem has no marks } test; diff --git a/Tests/feaLib/data/spec6f.fea b/Tests/feaLib/data/spec6f.fea index 8d32008c..277bdb46 100644 --- a/Tests/feaLib/data/spec6f.fea +++ b/Tests/feaLib/data/spec6f.fea @@ -2,5 +2,6 @@ languagesystem DFLT dflt; feature test { markClass damma <anchor 189 -103> @MARK_CLASS_1; - pos mark hamza <anchor 221 301> mark @MARK_CLASS_1; + pos mark hamza + <anchor 221 301> mark @MARK_CLASS_1; } test; diff --git a/Tests/feaLib/data/spec6h_ii.fea b/Tests/feaLib/data/spec6h_ii.fea index 36a1f032..690d2a35 100644 --- a/Tests/feaLib/data/spec6h_ii.fea +++ b/Tests/feaLib/data/spec6h_ii.fea @@ -12,8 +12,10 @@ lookup CNTXT_PAIR_POS { } CNTXT_PAIR_POS; lookup CNTXT_MARK_TO_BASE { - pos base o <anchor 250 450> mark @ALL_MARKS; - pos base c <anchor 250 450> mark @ALL_MARKS; + pos base o + <anchor 250 450> mark @ALL_MARKS; + pos base c + <anchor 250 450> mark @ALL_MARKS; } CNTXT_MARK_TO_BASE; feature test { diff --git a/Tests/feaLib/lexer_test.py b/Tests/feaLib/lexer_test.py index 238552ec..24dc5dba 100644 --- a/Tests/feaLib/lexer_test.py +++ b/Tests/feaLib/lexer_test.py @@ -1,6 +1,7 @@ -from fontTools.misc.py23 import * +from fontTools.misc.py23 import tobytes from fontTools.feaLib.error import FeatureLibError, IncludedFeaNotFound from fontTools.feaLib.lexer import IncludingLexer, Lexer +from io import StringIO import os import shutil import tempfile @@ -184,7 +185,7 @@ class IncludingLexerTest(unittest.TestCase): lambda: list(lexer)) def test_featurefilepath_None(self): - lexer = IncludingLexer(UnicodeIO("# foobar")) + lexer = IncludingLexer(StringIO("# foobar")) self.assertIsNone(lexer.featurefilepath) files = set(loc.file for _, _, loc in lexer) self.assertIn("<features>", files) @@ -196,7 +197,7 @@ class IncludingLexerTest(unittest.TestCase): pos A B -40; } kern; """, encoding="utf-8")) - including = UnicodeIO("include(%s);" % included.name) + including = StringIO("include(%s);" % included.name) try: lexer = IncludingLexer(including) files = set(loc.file for _, _, loc in lexer) @@ -224,7 +225,7 @@ class IncludingLexerTest(unittest.TestCase): # itself have a path, because it was initialized from # an in-memory stream, so it will use the current working # directory to resolve relative include statements - lexer = IncludingLexer(UnicodeIO("include(included.fea);")) + lexer = IncludingLexer(StringIO("include(included.fea);")) files = set(os.path.realpath(loc.file) for _, _, loc in lexer) expected = os.path.realpath(included.name) self.assertIn(expected, files) diff --git a/Tests/feaLib/parser_test.py b/Tests/feaLib/parser_test.py index db505950..de2bc3ca 100644 --- a/Tests/feaLib/parser_test.py +++ b/Tests/feaLib/parser_test.py @@ -1280,6 +1280,76 @@ class ParserTest(unittest.TestCase): '"dflt" is not a valid script tag; use "DFLT" instead', self.parse, "feature test {script dflt;} test;") + def test_stat_design_axis(self): # STAT DesignAxis + doc = self.parse('table STAT { DesignAxis opsz 0 ' + '{name "Optical Size";}; } STAT;') + da = doc.statements[0].statements[0] + self.assertIsInstance(da, ast.STATDesignAxisStatement) + self.assertEqual(da.tag, 'opsz') + self.assertEqual(da.axisOrder, 0) + self.assertEqual(da.names[0].string, 'Optical Size') + + def test_stat_axis_value_format1(self): # STAT AxisValue + doc = self.parse('table STAT { DesignAxis opsz 0 ' + '{name "Optical Size";}; ' + 'AxisValue {location opsz 8; name "Caption";}; } ' + 'STAT;') + avr = doc.statements[0].statements[1] + self.assertIsInstance(avr, ast.STATAxisValueStatement) + self.assertEqual(avr.locations[0].tag, 'opsz') + self.assertEqual(avr.locations[0].values[0], 8) + self.assertEqual(avr.names[0].string, 'Caption') + + def test_stat_axis_value_format2(self): # STAT AxisValue + doc = self.parse('table STAT { DesignAxis opsz 0 ' + '{name "Optical Size";}; ' + 'AxisValue {location opsz 8 6 10; name "Caption";}; } ' + 'STAT;') + avr = doc.statements[0].statements[1] + self.assertIsInstance(avr, ast.STATAxisValueStatement) + self.assertEqual(avr.locations[0].tag, 'opsz') + self.assertEqual(avr.locations[0].values, [8, 6, 10]) + self.assertEqual(avr.names[0].string, 'Caption') + + def test_stat_axis_value_format2_bad_range(self): # STAT AxisValue + self.assertRaisesRegex( + FeatureLibError, + 'Default value 5 is outside of specified range 6-10.', + self.parse, 'table STAT { DesignAxis opsz 0 ' + '{name "Optical Size";}; ' + 'AxisValue {location opsz 5 6 10; name "Caption";}; } ' + 'STAT;') + + def test_stat_axis_value_format4(self): # STAT AxisValue + self.assertRaisesRegex( + FeatureLibError, + 'Only one value is allowed in a Format 4 Axis Value Record, but 3 were found.', + self.parse, 'table STAT { ' + 'DesignAxis opsz 0 {name "Optical Size";}; ' + 'DesignAxis wdth 0 {name "Width";}; ' + 'AxisValue {' + 'location opsz 8 6 10; ' + 'location wdth 400; ' + 'name "Caption";}; } ' + 'STAT;') + + def test_stat_elidedfallbackname(self): # STAT ElidedFallbackName + doc = self.parse('table STAT { ElidedFallbackName {name "Roman"; ' + 'name 3 1 0x0411 "ローマン"; }; ' + '} STAT;') + nameRecord = doc.statements[0].statements[0] + self.assertIsInstance(nameRecord, ast.ElidedFallbackName) + self.assertEqual(nameRecord.names[0].string, 'Roman') + self.assertEqual(nameRecord.names[1].string, 'ローマン') + + def test_stat_elidedfallbacknameid(self): # STAT ElidedFallbackNameID + doc = self.parse('table name { nameid 278 "Roman"; } name; ' + 'table STAT { ElidedFallbackNameID 278; ' + '} STAT;') + nameRecord = doc.statements[0].statements[0] + self.assertIsInstance(nameRecord, ast.NameRecord) + self.assertEqual(nameRecord.string, 'Roman') + def test_sub_single_format_a(self): # GSUB LookupType 1 doc = self.parse("feature smcp {substitute a by a.sc;} smcp;") sub = doc.statements[0].statements[0] |