[feaLib] distinguish missing value and explicit '<NULL>' for PairPos2 format A

Fixes #1459
This commit is contained in:
Cosimo Lupo 2019-01-19 11:46:05 +00:00
parent af0e78e2eb
commit 091b05296d
No known key found for this signature in database
GPG Key ID: 59D54DB0C9976482
3 changed files with 41 additions and 4 deletions

View File

@ -1115,6 +1115,9 @@ class ValueRecord(Expression):
hash(self.xAdvDevice) ^ hash(self.yAdvDevice)) hash(self.xAdvDevice) ^ hash(self.yAdvDevice))
def makeString(self, vertical=None): def makeString(self, vertical=None):
if not self:
return "<NULL>"
x, y = self.xPlacement, self.yPlacement x, y = self.xPlacement, self.yPlacement
xAdvance, yAdvance = self.xAdvance, self.yAdvance xAdvance, yAdvance = self.xAdvance, self.yAdvance
xPlaDevice, yPlaDevice = self.xPlaDevice, self.yPlaDevice xPlaDevice, yPlaDevice = self.xPlaDevice, self.yPlaDevice
@ -1140,6 +1143,23 @@ class ValueRecord(Expression):
deviceToString(xPlaDevice), deviceToString(yPlaDevice), deviceToString(xPlaDevice), deviceToString(yPlaDevice),
deviceToString(xAdvDevice), deviceToString(yAdvDevice)) deviceToString(xAdvDevice), deviceToString(yAdvDevice))
def __bool__(self):
return any(
getattr(self, v) is not None
for v in [
"xPlacement",
"yPlacement",
"xAdvance",
"yAdvance",
"xPlaDevice",
"yPlaDevice",
"xAdvDevice",
"yAdvDevice",
]
)
__nonzero__ = __bool__
class ValueRecordDefinition(Statement): class ValueRecordDefinition(Statement):
def __init__(self, name, value, location=None): def __init__(self, name, value, location=None):

View File

@ -1153,7 +1153,7 @@ class Parser(object):
name = self.expect_name_() name = self.expect_name_()
if name == "NULL": if name == "NULL":
self.expect_symbol_(">") self.expect_symbol_(">")
return None return self.ast.ValueRecord()
vrd = self.valuerecords_.resolve(name) vrd = self.valuerecords_.resolve(name)
if vrd is None: if vrd is None:
raise FeatureLibError("Unknown valueRecordDef \"%s\"" % name, raise FeatureLibError("Unknown valueRecordDef \"%s\"" % name,

View File

@ -800,7 +800,22 @@ class ParserTest(unittest.TestCase):
self.assertEqual(pos.valuerecord2.makeString(vertical=False), self.assertEqual(pos.valuerecord2.makeString(vertical=False),
"<1 2 3 4>") "<1 2 3 4>")
def test_gpos_type_2_format_a_with_null(self): def test_gpos_type_2_format_a_with_null_first(self):
doc = self.parse("feature kern {"
" pos [T V] <NULL> [a b c] <1 2 3 4>;"
"} kern;")
pos = doc.statements[0].statements[0]
self.assertEqual(type(pos), ast.PairPosStatement)
self.assertFalse(pos.enumerated)
self.assertEqual(glyphstr([pos.glyphs1]), "[T V]")
self.assertFalse(pos.valuerecord1)
self.assertEqual(pos.valuerecord1.makeString(), "<NULL>")
self.assertEqual(glyphstr([pos.glyphs2]), "[a b c]")
self.assertEqual(pos.valuerecord2.makeString(vertical=False),
"<1 2 3 4>")
self.assertEqual(pos.asFea(), "pos [T V] <NULL> [a b c] <1 2 3 4>;")
def test_gpos_type_2_format_a_with_null_second(self):
doc = self.parse("feature kern {" doc = self.parse("feature kern {"
" pos [T V] <1 2 3 4> [a b c] <NULL>;" " pos [T V] <1 2 3 4> [a b c] <NULL>;"
"} kern;") "} kern;")
@ -811,7 +826,8 @@ class ParserTest(unittest.TestCase):
self.assertEqual(pos.valuerecord1.makeString(vertical=False), self.assertEqual(pos.valuerecord1.makeString(vertical=False),
"<1 2 3 4>") "<1 2 3 4>")
self.assertEqual(glyphstr([pos.glyphs2]), "[a b c]") self.assertEqual(glyphstr([pos.glyphs2]), "[a b c]")
self.assertIsNone(pos.valuerecord2) self.assertFalse(pos.valuerecord2)
self.assertEqual(pos.asFea(), "pos [T V] [a b c] <1 2 3 4>;")
def test_gpos_type_2_format_b(self): def test_gpos_type_2_format_b(self):
doc = self.parse("feature kern {" doc = self.parse("feature kern {"
@ -1523,7 +1539,8 @@ class ParserTest(unittest.TestCase):
def test_valuerecord_format_d(self): def test_valuerecord_format_d(self):
doc = self.parse("feature test {valueRecordDef <NULL> foo;} test;") doc = self.parse("feature test {valueRecordDef <NULL> foo;} test;")
value = doc.statements[0].statements[0].value value = doc.statements[0].statements[0].value
self.assertIsNone(value) self.assertFalse(value)
self.assertEqual(value.makeString(), "<NULL>")
def test_valuerecord_named(self): def test_valuerecord_named(self):
doc = self.parse("valueRecordDef <1 2 3 4> foo;" doc = self.parse("valueRecordDef <1 2 3 4> foo;"