[feaLib] distinguish missing value and explicit '<NULL>' for PairPos2 format A
Fixes #1459
This commit is contained in:
parent
af0e78e2eb
commit
091b05296d
@ -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):
|
||||||
|
@ -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,
|
||||||
|
@ -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;"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user