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