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