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