1 from __future__ import print_function, division, absolute_import 2 from fontTools.misc.py23 import * 3 from fontTools.misc import sstruct 4 from fontTools.misc.textTools import safeEval 5 from . import DefaultTable 6 7 SINGFormat = """ 8 > # big endian 9 tableVersionMajor: H 10 tableVersionMinor: H 11 glyphletVersion: H 12 permissions: h 13 mainGID: H 14 unitsPerEm: H 15 vertAdvance: h 16 vertOrigin: h 17 uniqueName: 28s 18 METAMD5: 16s 19 nameLength: 1s 20 """ 21 # baseGlyphName is a byte string which follows the record above. 22 23 24 25 class table_S_I_N_G_(DefaultTable.DefaultTable): 26 27 dependencies = [] 28 29 def decompile(self, data, ttFont): 30 dummy, rest = sstruct.unpack2(SINGFormat, data, self) 31 self.uniqueName = self.decompileUniqueName(self.uniqueName) 32 self.nameLength = byteord(self.nameLength) 33 assert len(rest) == self.nameLength 34 self.baseGlyphName = tostr(rest) 35 36 rawMETAMD5 = self.METAMD5 37 self.METAMD5 = "[" + hex(byteord(self.METAMD5[0])) 38 for char in rawMETAMD5[1:]: 39 self.METAMD5 = self.METAMD5 + ", " + hex(byteord(char)) 40 self.METAMD5 = self.METAMD5 + "]" 41 42 def decompileUniqueName(self, data): 43 name = "" 44 for char in data: 45 val = byteord(char) 46 if val == 0: 47 break 48 if (val > 31) or (val < 128): 49 name += chr(val) 50 else: 51 octString = oct(val) 52 if len(octString) > 3: 53 octString = octString[1:] # chop off that leading zero. 54 elif len(octString) < 3: 55 octString.zfill(3) 56 name += "\\" + octString 57 return name 58 59 60 def compile(self, ttFont): 61 d = self.__dict__.copy() 62 d["nameLength"] = bytechr(len(self.baseGlyphName)) 63 d["uniqueName"] = self.compilecompileUniqueName(self.uniqueName, 28) 64 METAMD5List = eval(self.METAMD5) 65 d["METAMD5"] = b"" 66 for val in METAMD5List: 67 d["METAMD5"] += bytechr(val) 68 assert (len(d["METAMD5"]) == 16), "Failed to pack 16 byte MD5 hash in SING table" 69 data = sstruct.pack(SINGFormat, d) 70 data = data + tobytes(self.baseGlyphName) 71 return data 72 73 def compilecompileUniqueName(self, name, length): 74 nameLen = len(name) 75 if length <= nameLen: 76 name = name[:length-1] + "\000" 77 else: 78 name += (nameLen - length) * "\000" 79 return name 80 81 82 def toXML(self, writer, ttFont): 83 writer.comment("Most of this table will be recalculated by the compiler") 84 writer.newline() 85 formatstring, names, fixes = sstruct.getformat(SINGFormat) 86 for name in names: 87 value = getattr(self, name) 88 writer.simpletag(name, value=value) 89 writer.newline() 90 writer.simpletag("baseGlyphName", value=self.baseGlyphName) 91 writer.newline() 92 93 def fromXML(self, name, attrs, content, ttFont): 94 value = attrs["value"] 95 if name in ["uniqueName", "METAMD5", "baseGlyphName"]: 96 setattr(self, name, value) 97 else: 98 setattr(self, name, safeEval(value)) 99