def keys(self): """ Return a list of all tables in the font. If a table order has been set manually or as the result of opening an existing WOFF file, the set table order will be in the list first. Tables not defined in an existing order will be sorted following the suggested ordering in the OTF/OFF specification. The first table listed in all cases is the GlyphOrder pseudo table. """ tags = set(self.tables.keys()) if self.reader is not None: tags = tags | set(self.reader.keys()) tags = list(tags) if "GlyphOrder" in tags: tags.remove("GlyphOrder") return ["GlyphOrder"] + sortedTagList(tags, self._tableOrder)
def save(self, file, compressionLevel=9, recompressTables=False, reorderTables=True, recalculateHeadChecksum=True): """ Save a WOFF into file a file object specifified by the file argument.. Optionally, file can be a path and a new file will be created at that location. compressionLevel is the compression level to be used with zlib. This must be an int between 1 and 9. The default is 9, the highest compression, but slowest compression time. Set recompressTables to True if you want any already compressed tables to be decompressed and then recompressed using the level specified by compressionLevel. If you want the tables in the WOFF reordered following the suggested optimal table orderings described in the OTF/OFF sepecification, set reorderTables to True. Tables cannot be reordered if a DSIG table is in the font. If you change any of the SFNT data or reorder the tables, the head table checkSumAdjustment must be recalculated. If you are not changing any of the SFNT data, you can set recalculateHeadChecksum to False to prevent the recalculation. This must be set to False if the font contains a DSIG table. """ # if DSIG is to be written, the table order # must be completely specified. otherwise the # DSIG may not be valid after decoding the WOFF. tags = self.keys() if "GlyphOrder" in tags: tags.remove("GlyphOrder") if "DSIG" in tags: if self._tableOrder is None or (set(self._tableOrder) != set(tags)): raise WOFFLibError( "A complete table order must be supplied when saving a font with a 'DSIG' table." ) elif reorderTables: raise WOFFLibError( "Tables can not be reordered when a 'DSIG' table is in the font. Set reorderTables to False." ) elif recalculateHeadChecksum: raise WOFFLibError( "The 'head' table checkSumAdjustment can not be recalculated when a 'DSIG' table is in the font." ) # sort the tags if necessary if reorderTables: tags = sortedTagList(tags) # open a file if necessary closeStream = False if not hasattr(file, "write"): closeStream = True file = open(file, "wb") # write the table data if "GlyphOrder" in tags: tags.remove("GlyphOrder") numTables = len(tags) writer = WOFFWriter(file, numTables, flavor=self.flavor, majorVersion=self.majorVersion, minorVersion=self.minorVersion, compressionLevel=compressionLevel, recalculateHeadChecksum=recalculateHeadChecksum, verbose=self.verbose) for tag in tags: origData = None origLength = None origChecksum = None compLength = None # table is loaded if self.isLoaded(tag): origData = self.getTableData(tag) # table is in reader elif self.reader is not None: if recompressTables: origData = self.getTableData(tag) else: if self.verbose: debugmsg("Reading '%s' table from disk" % tag) origData, origLength, origChecksum, compLength = self.reader.getCompressedTableData( tag) # add to writer writer.setTable(tag, origData, origLength=origLength, origChecksum=origChecksum, compLength=compLength) # write the metadata metadata = None metaOrigLength = None metaLength = None if hasattr(self, "metadata"): declaration = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" tree = ElementTree.ElementTree(self.metadata) f = StringIO() tree.write(f, encoding="utf-8") metadata = f.getvalue() # make sure the metadata starts with the declaration if not metadata.startswith(declaration): metadata = declaration + metadata del f elif self.reader is not None: if recompressTables: metadata = self.reader.metadata else: metadata, metaOrigLength, metaLength = self.reader.getCompressedMetadata( ) if metadata: writer.setMetadata(metadata, metaOrigLength=metaOrigLength, metaLength=metaLength) # write the private data privData = self.privateData if privData: writer.setPrivateData(privData) # close the writer writer.close() # close the file if closeStream: file.close()
def save(self, file, compressionLevel=9, recompressTables=False, reorderTables=True, recalculateHeadChecksum=True): """ Save a WOFF into file a file object specifified by the file argument.. Optionally, file can be a path and a new file will be created at that location. compressionLevel is the compression level to be used with zlib. This must be an int between 1 and 9. The default is 9, the highest compression, but slowest compression time. Set recompressTables to True if you want any already compressed tables to be decompressed and then recompressed using the level specified by compressionLevel. If you want the tables in the WOFF reordered following the suggested optimal table orderings described in the OTF/OFF sepecification, set reorderTables to True. Tables cannot be reordered if a DSIG table is in the font. If you change any of the SFNT data or reorder the tables, the head table checkSumAdjustment must be recalculated. If you are not changing any of the SFNT data, you can set recalculateHeadChecksum to False to prevent the recalculation. This must be set to False if the font contains a DSIG table. """ # if DSIG is to be written, the table order # must be completely specified. otherwise the # DSIG may not be valid after decoding the WOFF. tags = self.keys() if "GlyphOrder" in tags: tags.remove("GlyphOrder") if "DSIG" in tags: if self._tableOrder is None or (set(self._tableOrder) != set(tags)): raise WOFFLibError("A complete table order must be supplied when saving a font with a 'DSIG' table.") elif reorderTables: raise WOFFLibError("Tables can not be reordered when a 'DSIG' table is in the font. Set reorderTables to False.") elif recalculateHeadChecksum: raise WOFFLibError("The 'head' table checkSumAdjustment can not be recalculated when a 'DSIG' table is in the font.") # sort the tags if necessary if reorderTables: tags = sortedTagList(tags) # open a file if necessary closeStream = False if not hasattr(file, "write"): closeStream = True file = open(file, "wb") # write the table data if "GlyphOrder" in tags: tags.remove("GlyphOrder") numTables = len(tags) writer = WOFFWriter(file, numTables, flavor=self.flavor, majorVersion=self.majorVersion, minorVersion=self.minorVersion, compressionLevel=compressionLevel, recalculateHeadChecksum=recalculateHeadChecksum, verbose=self.verbose) for tag in tags: origData = None origLength = None origChecksum = None compLength = None # table is loaded if self.isLoaded(tag): origData = self.getTableData(tag) # table is in reader elif self.reader is not None: if recompressTables: origData = self.getTableData(tag) else: if self.verbose: debugmsg("Reading '%s' table from disk" % tag) origData, origLength, origChecksum, compLength = self.reader.getCompressedTableData(tag) # add to writer writer.setTable(tag, origData, origLength=origLength, origChecksum=origChecksum, compLength=compLength) # write the metadata metadata = None metaOrigLength = None metaLength = None if hasattr(self, "metadata"): declaration = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" tree = ElementTree.ElementTree(self.metadata) f = StringIO() tree.write(f, encoding="utf-8") metadata = f.getvalue() # make sure the metadata starts with the declaration if not metadata.startswith(declaration): metadata = declaration + metadata del f elif self.reader is not None: if recompressTables: metadata = self.reader.metadata else: metadata, metaOrigLength, metaLength = self.reader.getCompressedMetadata() if metadata: writer.setMetadata(metadata, metaOrigLength=metaOrigLength, metaLength=metaLength) # write the private data privData = self.privateData if privData: writer.setPrivateData(privData) # close the writer writer.close() # close the file if closeStream: file.close()