[otlLib] Implement otlLib.getSinglePosSubtable()
https://github.com/behdad/fonttools/issues/468
This commit is contained in:
parent
6ea91c9e7a
commit
ce7cc432f2
@ -134,9 +134,8 @@ def buildSinglePos(mapping, glyphMap):
|
||||
# a SinglePos format 1 subtable; that is the most compact form.
|
||||
for key, glyphs in coverages.items():
|
||||
if len(glyphs) > 1:
|
||||
valueFormat, value = key[0], values[key]
|
||||
result.append(_buildSinglePosFormat1(
|
||||
valueFormat, glyphs, value, glyphMap))
|
||||
format1Mapping = {g: values[key] for g in glyphs}
|
||||
result.append(buildSinglePosSubtable(format1Mapping, glyphMap))
|
||||
handled.add(key)
|
||||
|
||||
# In the remaining ValueRecords, look for those whose valueFormat
|
||||
@ -146,8 +145,7 @@ def buildSinglePos(mapping, glyphMap):
|
||||
f2 = [k for k in keys if k not in handled]
|
||||
if len(f2) > 1:
|
||||
format2Mapping = {coverages[k][0]: values[k] for k in f2}
|
||||
result.append(_buildSinglePosFormat2(
|
||||
valueFormat, format2Mapping, glyphMap))
|
||||
result.append(buildSinglePosSubtable(format2Mapping, glyphMap))
|
||||
handled.update(f2)
|
||||
|
||||
# The remaining ValueRecords are singletons in the sense that
|
||||
@ -155,9 +153,9 @@ def buildSinglePos(mapping, glyphMap):
|
||||
# is unique as well. We encode these in format 1 again.
|
||||
for key, glyphs in coverages.items():
|
||||
if key not in handled:
|
||||
valueFormat, value = key[0], values[key]
|
||||
result.append(_buildSinglePosFormat1(
|
||||
valueFormat, glyphs, value, glyphMap))
|
||||
assert len(glyphs) == 1, glyphs
|
||||
st = buildSinglePosSubtable({glyphs[0]: values[key]}, glyphMap)
|
||||
result.append(st)
|
||||
|
||||
# When the OpenType layout engine traverses the subtables, it will
|
||||
# stop after the first matching subtable. Therefore, we sort the
|
||||
@ -171,20 +169,22 @@ def buildSinglePos(mapping, glyphMap):
|
||||
return result
|
||||
|
||||
|
||||
def _buildSinglePosFormat1(valueFormat, glyphs, value, glyphMap):
|
||||
t = ot.SinglePos()
|
||||
t.Format, t.ValueFormat, t.Value = 1, valueFormat, value
|
||||
t.Coverage = buildCoverage(glyphs, glyphMap)
|
||||
return t
|
||||
|
||||
|
||||
def _buildSinglePosFormat2(valueFormat, mapping, glyphMap):
|
||||
t = ot.SinglePos()
|
||||
t.Format, t.ValueFormat = 2, valueFormat
|
||||
t.Coverage = buildCoverage(mapping.keys(), glyphMap)
|
||||
t.Value = [mapping[g] for g in t.Coverage.glyphs]
|
||||
t.ValueCount = len(t.Value)
|
||||
return t
|
||||
def buildSinglePosSubtable(values, glyphMap):
|
||||
"""{glyphName: otBase.ValueRecord} --> otTables.SinglePos"""
|
||||
self = ot.SinglePos()
|
||||
self.Coverage = buildCoverage(values.keys(), glyphMap)
|
||||
valueRecords = [values[g] for g in self.Coverage.glyphs]
|
||||
self.ValueFormat = 0
|
||||
for v in valueRecords:
|
||||
self.ValueFormat |= v.getFormat()
|
||||
if all(v == valueRecords[0] for v in valueRecords):
|
||||
self.Format = 1
|
||||
self.Value = valueRecords[0]
|
||||
else:
|
||||
self.Format = 2
|
||||
self.Value = valueRecords
|
||||
self.ValueCount = len(self.Value)
|
||||
return self
|
||||
|
||||
|
||||
def _getSinglePosTableKey(subtable, glyphMap):
|
||||
|
@ -125,7 +125,6 @@ class BuilderTest(unittest.TestCase):
|
||||
'</Device>')
|
||||
|
||||
def test_buildSinglePos(self):
|
||||
self.maxDiff = None
|
||||
subtables = builder.buildSinglePos({
|
||||
"one": builder.buildValue({"XPlacement": 500}),
|
||||
"two": builder.buildValue({"XPlacement": 500}),
|
||||
@ -134,7 +133,7 @@ class BuilderTest(unittest.TestCase):
|
||||
"five": builder.buildValue({"XPlacement": 500}),
|
||||
"six": builder.buildValue({"YPlacement": -6}),
|
||||
}, self.GLYPHMAP)
|
||||
self.assertEqual(''.join([getXML(t.toXML) for t in subtables[:3]]),
|
||||
self.assertEqual(''.join([getXML(t.toXML) for t in subtables]),
|
||||
'<SinglePos Format="1">'
|
||||
' <Coverage>'
|
||||
' <Glyph value="one"/>'
|
||||
@ -162,6 +161,39 @@ class BuilderTest(unittest.TestCase):
|
||||
' <Value YPlacement="-6"/>'
|
||||
'</SinglePos>')
|
||||
|
||||
def test_buildSinglePosSubtable_format1(self):
|
||||
subtable = builder.buildSinglePosSubtable({
|
||||
"one": builder.buildValue({"XPlacement": 777}),
|
||||
"two": builder.buildValue({"XPlacement": 777}),
|
||||
}, self.GLYPHMAP)
|
||||
self.assertEqual(getXML(subtable.toXML),
|
||||
'<SinglePos Format="1">'
|
||||
' <Coverage>'
|
||||
' <Glyph value="one"/>'
|
||||
' <Glyph value="two"/>'
|
||||
' </Coverage>'
|
||||
' <ValueFormat value="1"/>'
|
||||
' <Value XPlacement="777"/>'
|
||||
'</SinglePos>')
|
||||
|
||||
def test_buildSinglePosSubtable_format2(self):
|
||||
subtable = builder.buildSinglePosSubtable({
|
||||
"one": builder.buildValue({"XPlacement": 777}),
|
||||
"two": builder.buildValue({"YPlacement": -888}),
|
||||
}, self.GLYPHMAP)
|
||||
self.maxDiff = None
|
||||
self.assertEqual(getXML(subtable.toXML),
|
||||
'<SinglePos Format="2">'
|
||||
' <Coverage>'
|
||||
' <Glyph value="one"/>'
|
||||
' <Glyph value="two"/>'
|
||||
' </Coverage>'
|
||||
' <ValueFormat value="3"/>'
|
||||
' <!-- ValueCount=2 -->'
|
||||
' <Value index="0" XPlacement="777"/>'
|
||||
' <Value index="1" YPlacement="-888"/>'
|
||||
'</SinglePos>')
|
||||
|
||||
def test_buildValue(self):
|
||||
value = builder.buildValue({"XPlacement": 7, "YPlacement": 23})
|
||||
func = lambda writer, font: value.toXML(writer, font, valueName="Val")
|
||||
|
Loading…
x
Reference in New Issue
Block a user