[feaLib] make Device Table from device tuples

This commit is contained in:
moyogo 2015-12-05 08:15:05 +00:00
parent 5644da31d2
commit c01b956ae7
5 changed files with 115 additions and 22 deletions

View File

@ -316,6 +316,25 @@ class Builder(object):
lookup.mapping[glyph] = valuerecord
def _makeOpenTypeDeviceTable(deviceTable, device):
device = tuple(sorted(device))
deviceTable.StartSize = startSize = device[0][0]
deviceTable.EndSize = endSize = device[-1][0]
deviceDict = dict(device)
deviceTable.DeltaValue = deltaValues = [
deviceDict.get(size, 0)
for size in range(startSize, endSize + 1)]
maxDelta = max(deltaValues)
minDelta = min(deltaValues)
assert minDelta > -129 and maxDelta < 128
if minDelta > -3 and maxDelta < 2:
deviceTable.DeltaFormat = 1
elif minDelta > -9 and maxDelta < 8:
deviceTable.DeltaFormat = 2
else:
deviceTable.DeltaFormat = 3
def makeOpenTypeValueRecord(v):
"""ast.ValueRecord --> (otBase.ValueRecord, int ValueFormat)"""
vr = otBase.ValueRecord()
@ -328,18 +347,18 @@ def makeOpenTypeValueRecord(v):
if v.yAdvance:
vr.YAdvance = v.yAdvance
# TODO: Implement the following. Not sure how, though.
# The commented-out lines did not work; the problem is that we need to
# construct a Device table with an array of delta values.
# if v.xPlaDevice:
# vr.XPlaDevice = otTables.XPlaDevice()
# vr.XPlaDevice.value = v.xPlaDevice
# if v.yPlaDevice:
# vr.YPlaDevice = v.yPlaDevice
# if v.xAdvDevice:
# vr.XAdvDevice = v.xAdvDevice
# if v.yAdvDevice:
# vr.YAdvDevice = v.yAdvDevice
if v.xPlaDevice:
vr.XPlaDevice = otTables.XPlaDevice()
_makeOpenTypeDeviceTable(vr.XPlaDevice, v.xPlaDevice)
if v.yPlaDevice:
vr.YPlaDevice = otTables.YPlaDevice()
_makeOpenTypeDeviceTable(vr.YPlaDevice, v.yPlaDevice)
if v.xAdvDevice:
vr.XAdvDevice = otTables.XAdvDevice()
_makeOpenTypeDeviceTable(vr.XAdvDevice, v.xAdvDevice)
if v.yAdvDevice:
vr.YAdvDevice = otTables.YAdvDevice()
_makeOpenTypeDeviceTable(vr.YAdvDevice, v.yAdvDevice)
vrMask = 0
for mask, name, _, _ in otBase.valueRecordFormat:

View File

@ -373,6 +373,17 @@ class Parser(object):
xPlaDevice, yPlaDevice, xAdvDevice, yAdvDevice = (
self.parse_device_(), self.parse_device_(),
self.parse_device_(), self.parse_device_())
allDeltas = sorted([
delta
for size, delta
in (xPlaDevice if xPlaDevice else ()) +
(yPlaDevice if yPlaDevice else ()) +
(xAdvDevice if xAdvDevice else ()) +
(yAdvDevice if yAdvDevice else ())])
if allDeltas[0] < -128 or allDeltas[-1] > 127:
raise FeatureLibError(
"Device value out of valid range (-128..127)",
self.cur_token_location_)
else:
xPlaDevice, yPlaDevice, xAdvDevice, yAdvDevice = (
None, None, None, None)

View File

@ -479,9 +479,9 @@ class ParserTest(unittest.TestCase):
" valueRecordDef <"
" 1 2 3 4"
" <device 8 88>"
" <device 11 111, 12 222>"
" <device 11 111, 12 112>"
" <device NULL>"
" <device 33 -333, 44 -444, 55 555>"
" <device 33 -113, 44 -114, 55 115>"
" > foo;"
"} liga;")
value = doc.statements[0].statements[0].value
@ -490,9 +490,9 @@ class ParserTest(unittest.TestCase):
self.assertEqual(value.xAdvance, 3)
self.assertEqual(value.yAdvance, 4)
self.assertEqual(value.xPlaDevice, ((8, 88),))
self.assertEqual(value.yPlaDevice, ((11, 111), (12, 222)))
self.assertEqual(value.yPlaDevice, ((11, 111), (12, 112)))
self.assertIsNone(value.xAdvDevice)
self.assertEqual(value.yAdvDevice, ((33, -333), (44, -444), (55, 555)))
self.assertEqual(value.yAdvDevice, ((33, -113), (44, -114), (55, 115)))
def test_valuerecord_named(self):
doc = self.parse("valueRecordDef <1 2 3 4> foo;"
@ -518,6 +518,13 @@ class ParserTest(unittest.TestCase):
self.assertEqual(liga.statements[0].value.xAdvance, 789)
self.assertEqual(smcp.statements[0].value.xAdvance, 789)
def test_valuerecord_device_value_out_of_range(self):
self.assertRaisesRegex(
FeatureLibError, r"Device value out of valid range \(-128..127\)",
self.parse,
"valueRecordDef <1 2 3 4 <device NULL> <device NULL> "
"<device NULL> <device 11 128>> foo;")
def test_languagesystem(self):
[langsys] = self.parse("languagesystem latn DEU;").statements
self.assertEqual(langsys.script, "latn")

View File

@ -6,13 +6,18 @@ feature kern {
position [one two three] <-80 0 -160 0>;
position A <
1 2 3 4
<device 11 111, 12 222> <device 13 333, 14 444>
<device 16 666> <device NULL>
<device 11 111, 12 112> <device 13 113, 14 114>
<device 16 116> <device NULL>
>;
position B <
1 2 3 4
<device 11 111, 12 222> <device 13 333, 14 444>
<device 16 666> <device NULL>
<device 11 111, 12 112> <device 13 113, 14 114>
<device 16 116> <device NULL>
>;
position C <
1 2 3 4
<device 11 -2, 14 1> <device 13 -3, 15 1>
<device 11 -8, 14 7> <device 13 8, 15 1>
>;
position four 400;
position five <-80 0 -160 0>;

View File

@ -53,7 +53,7 @@
<Lookup index="0">
<!-- LookupType=1 -->
<LookupFlag value="0"/>
<!-- SubTableCount=5 -->
<!-- SubTableCount=6 -->
<SinglePos index="0" Format="1">
<Coverage>
<Glyph value="one"/>
@ -93,7 +93,58 @@
<Glyph value="B"/>
</Coverage>
<ValueFormat value="15"/>
<Value XPlacement="1" YPlacement="2" XAdvance="3" YAdvance="4"/>
<Value XPlacement="1" YPlacement="2" XAdvance="3" YAdvance="4">
<XPlaDevice>
<StartSize value="11"/>
<EndSize value="12"/>
<DeltaFormat value="3"/>
<DeltaValue value="[111, 112]"/>
</XPlaDevice>
<YPlaDevice>
<StartSize value="13"/>
<EndSize value="14"/>
<DeltaFormat value="3"/>
<DeltaValue value="[113, 114]"/>
</YPlaDevice>
<XAdvDevice>
<StartSize value="16"/>
<EndSize value="16"/>
<DeltaFormat value="3"/>
<DeltaValue value="[116]"/>
</XAdvDevice>
</Value>
</SinglePos>
<SinglePos index="5" Format="1">
<Coverage>
<Glyph value="C"/>
</Coverage>
<ValueFormat value="15"/>
<Value XPlacement="1" YPlacement="2" XAdvance="3" YAdvance="4">
<XPlaDevice>
<StartSize value="11"/>
<EndSize value="14"/>
<DeltaFormat value="1"/>
<DeltaValue value="[-2, 0, 0, 1]"/>
</XPlaDevice>
<YPlaDevice>
<StartSize value="13"/>
<EndSize value="15"/>
<DeltaFormat value="2"/>
<DeltaValue value="[-3, 0, 1]"/>
</YPlaDevice>
<XAdvDevice>
<StartSize value="11"/>
<EndSize value="14"/>
<DeltaFormat value="2"/>
<DeltaValue value="[-8, 0, 0, 7]"/>
</XAdvDevice>
<YAdvDevice>
<StartSize value="13"/>
<EndSize value="15"/>
<DeltaFormat value="3"/>
<DeltaValue value="[8, 0, 1]"/>
</YAdvDevice>
</Value>
</SinglePos>
</Lookup>
<Lookup index="1">