[ttc] Implement table sharing in save()
This commit is contained in:
parent
fb77bd0b0c
commit
370368d8c2
@ -215,6 +215,12 @@ class SFNTWriter(object):
|
||||
self.file.write(b'\0' * (self.nextTableOffset - self.file.tell()))
|
||||
self.tables = OrderedDict()
|
||||
|
||||
def setEntry(self, tag, entry):
|
||||
if tag in self.tables:
|
||||
raise TTLibError("cannot rewrite '%s' table" % tag)
|
||||
|
||||
self.tables[tag] = entry
|
||||
|
||||
def __setitem__(self, tag, data):
|
||||
"""Write raw table data to disk."""
|
||||
if tag in self.tables:
|
||||
@ -243,7 +249,10 @@ class SFNTWriter(object):
|
||||
self.file.write(b'\0' * (self.nextTableOffset - self.file.tell()))
|
||||
assert self.nextTableOffset == self.file.tell()
|
||||
|
||||
self.tables[tag] = entry
|
||||
self.setEntry(tag, entry)
|
||||
|
||||
def __getitem__(self, tag):
|
||||
return self.tables[tag]
|
||||
|
||||
def close(self):
|
||||
"""All tables must have been written to disk. Now write the
|
||||
|
@ -37,7 +37,7 @@ class TTCollection(object):
|
||||
font = TTFont(file, fontNumber=i, _tableCache=tableCache, **kwargs)
|
||||
fonts.append(font)
|
||||
|
||||
def save(self, file):
|
||||
def save(self, file, shareTables=True):
|
||||
"""Save the font to disk. Similarly to the constructor,
|
||||
the 'file' argument can be either a pathname or a writable
|
||||
file object.
|
||||
@ -51,12 +51,13 @@ class TTCollection(object):
|
||||
final = file
|
||||
file = BytesIO()
|
||||
|
||||
offsets_offset = writeTTCHeader(file, len(self.fonts))
|
||||
tableCache = {} if shareTables else None
|
||||
|
||||
offsets_offset = writeTTCHeader(file, len(self.fonts))
|
||||
offsets = []
|
||||
for font in self.fonts:
|
||||
offsets.append(file.tell())
|
||||
font._save(file)
|
||||
font._save(file, tableCache=tableCache)
|
||||
file.seek(0,2)
|
||||
|
||||
file.seek(offsets_offset)
|
||||
|
@ -134,7 +134,7 @@ class TTFont(object):
|
||||
if closeStream:
|
||||
file.close()
|
||||
file = tmp
|
||||
self.tableCache = _tableCache
|
||||
self._tableCache = _tableCache
|
||||
self.reader = SFNTReader(file, checkChecksums, fontNumber=fontNumber)
|
||||
self.sfntVersion = self.reader.sfntVersion
|
||||
self.flavor = self.reader.flavor
|
||||
@ -186,7 +186,7 @@ class TTFont(object):
|
||||
if closeStream:
|
||||
file.close()
|
||||
|
||||
def _save(self, file):
|
||||
def _save(self, file, tableCache=None):
|
||||
"""Internal function, to be shared by save() and TTCollection.save()"""
|
||||
|
||||
if self.recalcTimestamp and 'head' in self:
|
||||
@ -201,7 +201,7 @@ class TTFont(object):
|
||||
|
||||
done = []
|
||||
for tag in tags:
|
||||
self._writeTable(tag, writer, done)
|
||||
self._writeTable(tag, writer, done, tableCache)
|
||||
|
||||
writer.close()
|
||||
|
||||
@ -380,8 +380,8 @@ class TTFont(object):
|
||||
import traceback
|
||||
log.debug("Reading '%s' table from disk", tag)
|
||||
data = self.reader[tag]
|
||||
if self.tableCache is not None:
|
||||
table = self.tableCache.get((Tag(tag), data))
|
||||
if self._tableCache is not None:
|
||||
table = self._tableCache.get((Tag(tag), data))
|
||||
if table is not None:
|
||||
return table
|
||||
tableClass = getTableClass(tag)
|
||||
@ -403,8 +403,8 @@ class TTFont(object):
|
||||
table.ERROR = file.getvalue()
|
||||
self.tables[tag] = table
|
||||
table.decompile(data, self)
|
||||
if self.tableCache is not None:
|
||||
self.tableCache[(Tag(tag), data)] = table
|
||||
if self._tableCache is not None:
|
||||
self._tableCache[(Tag(tag), data)] = table
|
||||
return table
|
||||
else:
|
||||
raise KeyError("'%s' table not found" % tag)
|
||||
@ -612,7 +612,7 @@ class TTFont(object):
|
||||
for glyphID in range(len(glyphOrder)):
|
||||
d[glyphOrder[glyphID]] = glyphID
|
||||
|
||||
def _writeTable(self, tag, writer, done):
|
||||
def _writeTable(self, tag, writer, done, tableCache=None):
|
||||
"""Internal helper function for self.save(). Keeps track of
|
||||
inter-table dependencies.
|
||||
"""
|
||||
@ -622,13 +622,21 @@ class TTFont(object):
|
||||
for masterTable in tableClass.dependencies:
|
||||
if masterTable not in done:
|
||||
if masterTable in self:
|
||||
self._writeTable(masterTable, writer, done)
|
||||
self._writeTable(masterTable, writer, done, tableCache)
|
||||
else:
|
||||
done.append(masterTable)
|
||||
done.append(tag)
|
||||
tabledata = self.getTableData(tag)
|
||||
if tableCache is not None:
|
||||
entry = tableCache.get((Tag(tag), tabledata))
|
||||
if entry is not None:
|
||||
log.debug("reusing '%s' table", tag)
|
||||
writer.setEntry(tag, entry)
|
||||
return
|
||||
log.debug("writing '%s' table to disk", tag)
|
||||
writer[tag] = tabledata
|
||||
done.append(tag)
|
||||
if tableCache is not None:
|
||||
tableCache[(Tag(tag), tabledata)] = writer[tag]
|
||||
|
||||
def getTableData(self, tag):
|
||||
"""Returns raw table data, whether compiled or directly read from disk.
|
||||
|
Loading…
x
Reference in New Issue
Block a user