from fontTools.misc.py23 import bytesjoin, strjoin from fontTools.misc import sstruct from fontTools.misc.textTools import readHex from fontTools.ttLib import TTLibError from . import DefaultTable # Apple's documentation of 'meta': # https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6meta.html META_HEADER_FORMAT = """ > # big endian version: L flags: L dataOffset: L numDataMaps: L """ DATA_MAP_FORMAT = """ > # big endian tag: 4s dataOffset: L dataLength: L """ class table__m_e_t_a(DefaultTable.DefaultTable): def __init__(self, tag=None): DefaultTable.DefaultTable.__init__(self, tag) self.data = {} def decompile(self, data, ttFont): headerSize = sstruct.calcsize(META_HEADER_FORMAT) header = sstruct.unpack(META_HEADER_FORMAT, data[0 : headerSize]) if header["version"] != 1: raise TTLibError("unsupported 'meta' version %d" % header["version"]) dataMapSize = sstruct.calcsize(DATA_MAP_FORMAT) for i in range(header["numDataMaps"]): dataMapOffset = headerSize + i * dataMapSize dataMap = sstruct.unpack( DATA_MAP_FORMAT, data[dataMapOffset : dataMapOffset + dataMapSize]) tag = dataMap["tag"] offset = dataMap["dataOffset"] self.data[tag] = data[offset : offset + dataMap["dataLength"]] if tag in ["dlng", "slng"]: self.data[tag] = self.data[tag].decode("utf-8") def compile(self, ttFont): keys = sorted(self.data.keys()) headerSize = sstruct.calcsize(META_HEADER_FORMAT) dataOffset = headerSize + len(keys) * sstruct.calcsize(DATA_MAP_FORMAT) header = sstruct.pack(META_HEADER_FORMAT, { "version": 1, "flags": 0, "dataOffset": dataOffset, "numDataMaps": len(keys) }) dataMaps = [] dataBlocks = [] for tag in keys: if tag in ["dlng", "slng"]: data = self.data[tag].encode("utf-8") else: data = self.data[tag] dataMaps.append(sstruct.pack(DATA_MAP_FORMAT, { "tag": tag, "dataOffset": dataOffset, "dataLength": len(data) })) dataBlocks.append(data) dataOffset += len(data) return bytesjoin([header] + dataMaps + dataBlocks) def toXML(self, writer, ttFont): for tag in sorted(self.data.keys()): if tag in ["dlng", "slng"]: writer.begintag("text", tag=tag) writer.newline() writer.write(self.data[tag]) writer.newline() writer.endtag("text") writer.newline() else: writer.begintag("hexdata", tag=tag) writer.newline() data = self.data[tag] if min(data) >= 0x20 and max(data) <= 0x7E: writer.comment("ascii: " + data.decode("ascii")) writer.newline() writer.dumphex(data) writer.endtag("hexdata") writer.newline() def fromXML(self, name, attrs, content, ttFont): if name == "hexdata": self.data[attrs["tag"]] = readHex(content) elif name == "text" and attrs["tag"] in ["dlng", "slng"]: self.data[attrs["tag"]] = strjoin(content).strip() else: raise TTLibError("can't handle '%s' element" % name)