[feaLib] Parse ValueRecord format C

However, not sure how to build the otTables object graph for emitting
GPOS tables with device values; the current code thus silently strips
off any device values. Left a TODO comment for implementing this.
This commit is contained in:
Sascha Brawer 2015-12-04 15:49:04 +01:00
parent b99f1c9af4
commit 46c76dbf1f
5 changed files with 55 additions and 16 deletions

View File

@ -197,12 +197,13 @@ class SubstitutionRule(Statement):
class ValueRecord(Statement): class ValueRecord(Statement):
def __init__(self, location, xPlacement, yPlacement, xAdvance, yAdvance): def __init__(self, location, xPlacement, yPlacement, xAdvance, yAdvance,
xPlaDevice, yPlaDevice, xAdvDevice, yAdvDevice):
Statement.__init__(self, location) Statement.__init__(self, location)
self.xPlacement, self.yPlacement = (xPlacement, yPlacement) self.xPlacement, self.yPlacement = (xPlacement, yPlacement)
self.xAdvance, self.yAdvance = (xAdvance, yAdvance) self.xAdvance, self.yAdvance = (xAdvance, yAdvance)
self.xPlaDevice, self.yPlaDevice = (0, 0) self.xPlaDevice, self.yPlaDevice = (xPlaDevice, yPlaDevice)
self.xAdvDevice, self.yAdvDevice = (0, 0) self.xAdvDevice, self.yAdvDevice = (xAdvDevice, yAdvDevice)
def __eq__(self, other): def __eq__(self, other):
return (self.xPlacement == other.xPlacement and return (self.xPlacement == other.xPlacement and

View File

@ -327,14 +327,20 @@ def makeOpenTypeValueRecord(v):
vr.XAdvance = v.xAdvance vr.XAdvance = v.xAdvance
if v.yAdvance: if v.yAdvance:
vr.YAdvance = v.yAdvance vr.YAdvance = v.yAdvance
if v.xPlaDevice:
vr.XPlaDevice = v.xPlaDevice # TODO: Implement the following. Not sure how, though.
if v.yPlaDevice: # The commented-out lines did not work; the problem is that we need to
vr.YPlaDevice = v.yPlaDevice # construct a Device table with an array of delta values.
if v.xAdvDevice: # if v.xPlaDevice:
vr.XAdvDevice = v.xAdvDevice # vr.XPlaDevice = otTables.XPlaDevice()
if v.yAdvDevice: # vr.XPlaDevice.value = v.xPlaDevice
vr.YAdvDevice = v.yAdvDevice # if v.yPlaDevice:
# vr.YPlaDevice = v.yPlaDevice
# if v.xAdvDevice:
# vr.XAdvDevice = v.xAdvDevice
# if v.yAdvDevice:
# vr.YAdvDevice = v.yAdvDevice
vrMask = 0 vrMask = 0
for mask, name, _, _ in otBase.valueRecordFormat: for mask, name, _, _ in otBase.valueRecordFormat:
if getattr(vr, name, 0) != 0: if getattr(vr, name, 0) != 0:

View File

@ -332,9 +332,9 @@ class Parser(object):
if self.next_token_type_ is Lexer.NUMBER: if self.next_token_type_ is Lexer.NUMBER:
number, location = self.expect_number_(), self.cur_token_location_ number, location = self.expect_number_(), self.cur_token_location_
if vertical: if vertical:
val = ast.ValueRecord(location, 0, 0, 0, number) val = ast.ValueRecord(location, 0, 0, 0, number, 0, 0, 0, 0)
else: else:
val = ast.ValueRecord(location, 0, 0, number, 0) val = ast.ValueRecord(location, 0, 0, number, 0, 0, 0, 0, 0)
return val return val
self.expect_symbol_("<") self.expect_symbol_("<")
location = self.cur_token_location_ location = self.cur_token_location_
@ -351,9 +351,16 @@ class Parser(object):
xPlacement, yPlacement, xAdvance, yAdvance = ( xPlacement, yPlacement, xAdvance, yAdvance = (
self.expect_number_(), self.expect_number_(), self.expect_number_(), self.expect_number_(),
self.expect_number_(), self.expect_number_()) self.expect_number_(), self.expect_number_())
if self.next_token_type_ is Lexer.NUMBER:
xPlaDevice, yPlaDevice, xAdvDevice, yAdvDevice = (
self.expect_number_(), self.expect_number_(),
self.expect_number_(), self.expect_number_())
else:
xPlaDevice, yPlaDevice, xAdvDevice, yAdvDevice = (0, 0, 0, 0)
self.expect_symbol_(">") self.expect_symbol_(">")
return ast.ValueRecord( return ast.ValueRecord(
location, xPlacement, yPlacement, xAdvance, yAdvance) location, xPlacement, yPlacement, xAdvance, yAdvance,
xPlaDevice, yPlaDevice, xAdvDevice, yAdvDevice)
def parse_valuerecord_definition_(self, vertical): def parse_valuerecord_definition_(self, vertical):
assert self.is_cur_keyword_("valueRecordDef") assert self.is_cur_keyword_("valueRecordDef")

View File

@ -444,6 +444,10 @@ class ParserTest(unittest.TestCase):
self.assertEqual(value.yPlacement, 0) self.assertEqual(value.yPlacement, 0)
self.assertEqual(value.xAdvance, 123) self.assertEqual(value.xAdvance, 123)
self.assertEqual(value.yAdvance, 0) self.assertEqual(value.yAdvance, 0)
self.assertEqual(value.xPlaDevice, 0)
self.assertEqual(value.yPlaDevice, 0)
self.assertEqual(value.xAdvDevice, 0)
self.assertEqual(value.yAdvDevice, 0)
def test_valuerecord_format_a_vertical(self): def test_valuerecord_format_a_vertical(self):
doc = self.parse("feature vkrn {valueRecordDef 123 foo;} vkrn;") doc = self.parse("feature vkrn {valueRecordDef 123 foo;} vkrn;")
@ -452,6 +456,10 @@ class ParserTest(unittest.TestCase):
self.assertEqual(value.yPlacement, 0) self.assertEqual(value.yPlacement, 0)
self.assertEqual(value.xAdvance, 0) self.assertEqual(value.xAdvance, 0)
self.assertEqual(value.yAdvance, 123) self.assertEqual(value.yAdvance, 123)
self.assertEqual(value.xPlaDevice, 0)
self.assertEqual(value.yPlaDevice, 0)
self.assertEqual(value.xAdvDevice, 0)
self.assertEqual(value.yAdvDevice, 0)
def test_valuerecord_format_b(self): def test_valuerecord_format_b(self):
doc = self.parse("feature liga {valueRecordDef <1 2 3 4> foo;} liga;") doc = self.parse("feature liga {valueRecordDef <1 2 3 4> foo;} liga;")
@ -460,6 +468,23 @@ class ParserTest(unittest.TestCase):
self.assertEqual(value.yPlacement, 2) self.assertEqual(value.yPlacement, 2)
self.assertEqual(value.xAdvance, 3) self.assertEqual(value.xAdvance, 3)
self.assertEqual(value.yAdvance, 4) self.assertEqual(value.yAdvance, 4)
self.assertEqual(value.xPlaDevice, 0)
self.assertEqual(value.yPlaDevice, 0)
self.assertEqual(value.xAdvDevice, 0)
self.assertEqual(value.yAdvDevice, 0)
def test_valuerecord_format_c(self):
doc = self.parse(
"feature liga {valueRecordDef <1 2 3 4 5 6 7 8> foo;} liga;")
value = doc.statements[0].statements[0].value
self.assertEqual(value.xPlacement, 1)
self.assertEqual(value.yPlacement, 2)
self.assertEqual(value.xAdvance, 3)
self.assertEqual(value.yAdvance, 4)
self.assertEqual(value.xPlaDevice, 5)
self.assertEqual(value.yPlaDevice, 6)
self.assertEqual(value.xAdvDevice, 7)
self.assertEqual(value.yAdvDevice, 8)
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;"

View File

@ -4,8 +4,8 @@ languagesystem DFLT dflt;
feature kern { feature kern {
position [one two three] <-80 0 -160 0>; position [one two three] <-80 0 -160 0>;
position A <1 2 3 4>; position A <1 2 3 4 5 6 7 8>;
position B <1 2 3 4>; position B <1 2 3 4 5 6 7 8>;
position four 400; position four 400;
position five <-80 0 -160 0>; position five <-80 0 -160 0>;
position six -200; position six -200;