[morx] Separate building from writing lookup tables
For AAT lookup format 2 (and other formats too), we need to shuffle the data before we can estimate the encoded size. After this restructuring, this data shuffling only needs to happen once.
This commit is contained in:
parent
68dc15375b
commit
bdf29b4169
@ -549,6 +549,8 @@ class ValueRecord(ValueFormat):
|
|||||||
|
|
||||||
|
|
||||||
class AATLookup(BaseConverter):
|
class AATLookup(BaseConverter):
|
||||||
|
BIN_SEARCH_HEADER_SIZE = 10
|
||||||
|
|
||||||
def read(self, reader, font, tableDict):
|
def read(self, reader, font, tableDict):
|
||||||
format = reader.readUShort()
|
format = reader.readUShort()
|
||||||
if format == 0:
|
if format == 0:
|
||||||
@ -557,11 +559,11 @@ class AATLookup(BaseConverter):
|
|||||||
elif format == 2:
|
elif format == 2:
|
||||||
mapping = self.readFormat2(reader)
|
mapping = self.readFormat2(reader)
|
||||||
elif format == 4:
|
elif format == 4:
|
||||||
mapping = self.readFormat4(reader)
|
mapping = self.readFormat4(reader)
|
||||||
elif format == 6:
|
elif format == 6:
|
||||||
mapping = self.readFormat6(reader)
|
mapping = self.readFormat6(reader)
|
||||||
elif format == 8:
|
elif format == 8:
|
||||||
mapping = self.readFormat8(reader)
|
mapping = self.readFormat8(reader)
|
||||||
else:
|
else:
|
||||||
assert False, "unsupported lookup format: %d" % format
|
assert False, "unsupported lookup format: %d" % format
|
||||||
return {font.getGlyphName(k):font.getGlyphName(v)
|
return {font.getGlyphName(k):font.getGlyphName(v)
|
||||||
@ -570,14 +572,15 @@ class AATLookup(BaseConverter):
|
|||||||
def write(self, writer, font, tableDict, value, repeatIndex=None):
|
def write(self, writer, font, tableDict, value, repeatIndex=None):
|
||||||
glyphMap = font.getReverseGlyphMap()
|
glyphMap = font.getReverseGlyphMap()
|
||||||
binSrchHeaderSize = 10
|
binSrchHeaderSize = 10
|
||||||
formatSizes = {6: binSrchHeaderSize + len(value) * 4 + 4}
|
|
||||||
if glyphMap.keys() == value.keys():
|
|
||||||
formatSizes[0] = len(value) * 2
|
|
||||||
# TODO: Also implement format 2, 4, and 8.
|
# TODO: Also implement format 2, 4, and 8.
|
||||||
bestFormat = min(formatSizes, key=formatSizes.get)
|
formats = list(sorted(filter(None, [
|
||||||
writeMethod = getattr(self, 'writeFormat%d' % bestFormat)
|
self.buildFormat0(font, value),
|
||||||
writer.writeUShort(bestFormat)
|
self.buildFormat6(font, value),
|
||||||
writeMethod(writer, font, value)
|
])))
|
||||||
|
# We use the format ID as secondary sort key to make the output
|
||||||
|
# deterministic when multiple formats have same encoded size.
|
||||||
|
_size, _format, writeMethod = formats[0]
|
||||||
|
writeMethod(writer)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def writeBinSearchHeader(writer, numUnits, unitSize):
|
def writeBinSearchHeader(writer, numUnits, unitSize):
|
||||||
@ -589,17 +592,32 @@ class AATLookup(BaseConverter):
|
|||||||
writer.writeUShort(entrySelector)
|
writer.writeUShort(entrySelector)
|
||||||
writer.writeUShort(rangeShift)
|
writer.writeUShort(rangeShift)
|
||||||
|
|
||||||
|
def buildFormat0(self, font, value):
|
||||||
|
if font.getReverseGlyphMap().keys() != value.keys():
|
||||||
|
return None
|
||||||
|
return (len(value) * 2, 0,
|
||||||
|
lambda writer: self.writeFormat0(writer, font, value))
|
||||||
|
|
||||||
def writeFormat0(self, writer, font, value):
|
def writeFormat0(self, writer, font, value):
|
||||||
|
writer.writeUShort(0)
|
||||||
for glyph in font.getGlyphOrder():
|
for glyph in font.getGlyphOrder():
|
||||||
writer.writeUShort(font.getGlyphID(value[glyph]))
|
writer.writeUShort(font.getGlyphID(value[glyph]))
|
||||||
|
|
||||||
def writeFormat6(self, writer, font, value):
|
def buildFormat6(self, font, value):
|
||||||
table = [(font.getGlyphID(key), font.getGlyphID(value))
|
entries = [(font.getGlyphID(key), font.getGlyphID(value))
|
||||||
for key, value in value.items()] + [(0xFFFF, 0xFFFF)]
|
for key, value in value.items()]
|
||||||
table.sort()
|
entries.sort()
|
||||||
|
if entries[-1][0] != 0xFFFF:
|
||||||
|
entries.append((0xFFFF, 0xFFFF))
|
||||||
|
return (self.BIN_SEARCH_HEADER_SIZE + len(entries) * 4, 6,
|
||||||
|
lambda writer:
|
||||||
|
self.writeFormat6(writer, font, value, entries))
|
||||||
|
|
||||||
|
def writeFormat6(self, writer, font, value, entries):
|
||||||
|
writer.writeUShort(6)
|
||||||
self.writeBinSearchHeader(writer,
|
self.writeBinSearchHeader(writer,
|
||||||
numUnits=len(table), unitSize=4)
|
numUnits=len(entries), unitSize=4)
|
||||||
for key, value in table:
|
for key, value in entries:
|
||||||
writer.writeUShort(key)
|
writer.writeUShort(key)
|
||||||
writer.writeUShort(value)
|
writer.writeUShort(value)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user