1from __future__ import print_function, division, absolute_import 2from fontTools.misc.py23 import * 3from fontTools.misc import sstruct 4from fontTools.misc.textTools import readHex 5from fontTools.ttLib import TTLibError 6from . import DefaultTable 7 8# Apple's documentation of 'meta': 9# https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6meta.html 10 11META_HEADER_FORMAT = """ 12 > # big endian 13 version: L 14 flags: L 15 dataOffset: L 16 numDataMaps: L 17""" 18 19 20DATA_MAP_FORMAT = """ 21 > # big endian 22 tag: 4s 23 dataOffset: L 24 dataLength: L 25""" 26 27 28class table__m_e_t_a(DefaultTable.DefaultTable): 29 def __init__(self, tag=None): 30 DefaultTable.DefaultTable.__init__(self, tag) 31 self.data = {} 32 33 def decompile(self, data, ttFont): 34 headerSize = sstruct.calcsize(META_HEADER_FORMAT) 35 header = sstruct.unpack(META_HEADER_FORMAT, data[0 : headerSize]) 36 if header["version"] != 1: 37 raise TTLibError("unsupported 'meta' version %d" % 38 header["version"]) 39 dataMapSize = sstruct.calcsize(DATA_MAP_FORMAT) 40 for i in range(header["numDataMaps"]): 41 dataMapOffset = headerSize + i * dataMapSize 42 dataMap = sstruct.unpack( 43 DATA_MAP_FORMAT, 44 data[dataMapOffset : dataMapOffset + dataMapSize]) 45 tag = dataMap["tag"] 46 offset = dataMap["dataOffset"] 47 self.data[tag] = data[offset : offset + dataMap["dataLength"]] 48 if tag in ["dlng", "slng"]: 49 self.data[tag] = self.data[tag].decode("utf-8") 50 51 def compile(self, ttFont): 52 keys = sorted(self.data.keys()) 53 headerSize = sstruct.calcsize(META_HEADER_FORMAT) 54 dataOffset = headerSize + len(keys) * sstruct.calcsize(DATA_MAP_FORMAT) 55 header = sstruct.pack(META_HEADER_FORMAT, { 56 "version": 1, 57 "flags": 0, 58 "dataOffset": dataOffset, 59 "numDataMaps": len(keys) 60 }) 61 dataMaps = [] 62 dataBlocks = [] 63 for tag in keys: 64 if tag in ["dlng", "slng"]: 65 data = self.data[tag].encode("utf-8") 66 else: 67 data = self.data[tag] 68 dataMaps.append(sstruct.pack(DATA_MAP_FORMAT, { 69 "tag": tag, 70 "dataOffset": dataOffset, 71 "dataLength": len(data) 72 })) 73 dataBlocks.append(data) 74 dataOffset += len(data) 75 return bytesjoin([header] + dataMaps + dataBlocks) 76 77 def toXML(self, writer, ttFont): 78 for tag in sorted(self.data.keys()): 79 if tag in ["dlng", "slng"]: 80 writer.begintag("text", tag=tag) 81 writer.newline() 82 writer.write(self.data[tag]) 83 writer.newline() 84 writer.endtag("text") 85 writer.newline() 86 else: 87 writer.begintag("hexdata", tag=tag) 88 writer.newline() 89 writer.dumphex(self.data[tag]) 90 writer.endtag("hexdata") 91 writer.newline() 92 93 def fromXML(self, name, attrs, content, ttFont): 94 if name == "hexdata": 95 self.data[attrs["tag"]] = readHex(content) 96 elif name == "text" and attrs["tag"] in ["dlng", "slng"]: 97 self.data[attrs["tag"]] = strjoin(content).strip() 98 else: 99 raise TTLibError("can't handle '%s' element" % name) 100