G_M_A_P_.py revision 2b06aaa2a6bcd363c25fb0c43f6bb906906594bd
1from . import DefaultTable 2from fontTools.misc import sstruct 3from types import StringType 4from fontTools.misc.textTools import safeEval, num2binary, binary2num 5 6GMAPFormat = """ 7 > # big endian 8 tableVersionMajor: H 9 tableVersionMinor: H 10 flags: H 11 recordsCount: H 12 recordsOffset: H 13 fontNameLength: H 14""" 15# psFontName is a byte string which follows the record above. This is zero padded 16# to the beginning of the records array. The recordsOffsst is 32 bit aligned. 17 18GMAPRecordFormat1 = """ 19 > # big endian 20 UV: L 21 cid: H 22 gid: H 23 ggid: H 24 name: 32s 25""" 26 27 28 29class GMAPRecord: 30 def __init__(self, uv = 0, cid = 0, gid = 0, ggid = 0, name = ""): 31 self.UV = uv 32 self.cid = cid 33 self.gid = gid 34 self.ggid = ggid 35 self.name = name 36 37 def toXML(self, writer, ttFont): 38 writer.begintag("GMAPRecord") 39 writer.newline() 40 writer.simpletag("UV", value=self.UV) 41 writer.newline() 42 writer.simpletag("cid", value=self.cid) 43 writer.newline() 44 writer.simpletag("gid", value=self.gid) 45 writer.newline() 46 writer.simpletag("glyphletGid", value=self.gid) 47 writer.newline() 48 writer.simpletag("GlyphletName", value=self.name) 49 writer.newline() 50 writer.endtag("GMAPRecord") 51 writer.newline() 52 53 54 def fromXML(self, (name, attrs, content), ttFont): 55 value = attrs["value"] 56 if name == "GlyphletName": 57 self.name = value 58 else: 59 try: 60 value = safeEval(value) 61 except OverflowError: 62 value = long(value) 63 setattr(self, name, value) 64 65 66 def compile(self, ttFont): 67 if self.UV == None: 68 self.UV = 0 69 nameLen = len(self.name) 70 if nameLen < 32: 71 self.name = self.name + "\0"*(32 - nameLen) 72 data = sstruct.pack(GMAPRecordFormat1, self) 73 return data 74 75 def __repr__(self): 76 return "GMAPRecord[ UV: " + str(self.UV) + ", cid: " + str(self.cid) + ", gid: " + str(self.gid) + ", ggid: " + str(self.ggid) + ", Glyphlet Name: " + str(self.name) + " ]" 77 78 79class table_G_M_A_P_(DefaultTable.DefaultTable): 80 81 dependencies = [] 82 83 def decompile(self, data, ttFont): 84 dummy, newData = sstruct.unpack2(GMAPFormat, data, self) 85 self.psFontName = newData[:self.fontNameLength] 86 assert (self.recordsOffset % 4) == 0, "GMAP error: recordsOffset is not 32 bit aligned." 87 newData = data[self.recordsOffset:] 88 self.gmapRecords = [] 89 for i in range (self.recordsCount): 90 gmapRecord, newData = sstruct.unpack2(GMAPRecordFormat1, newData, GMAPRecord()) 91 gmapRecord.name = gmapRecord.name.strip('\0') 92 self.gmapRecords.append(gmapRecord) 93 94 95 def compile(self, ttFont): 96 self.recordsCount = len(self.gmapRecords) 97 self.fontNameLength = len(self.psFontName) 98 self.recordsOffset = 4 *(((self.fontNameLength + 12) + 3) /4) 99 data = sstruct.pack(GMAPFormat, self) 100 data = data + self.psFontName 101 data = data + "\0" * (self.recordsOffset - len(data)) 102 for record in self.gmapRecords: 103 data = data + record.compile(ttFont) 104 return data 105 106 107 def toXML(self, writer, ttFont): 108 writer.comment("Most of this table will be recalculated by the compiler") 109 writer.newline() 110 formatstring, names, fixes = sstruct.getformat(GMAPFormat) 111 for name in names: 112 value = getattr(self, name) 113 writer.simpletag(name, value=value) 114 writer.newline() 115 writer.simpletag("PSFontName", value=self.psFontName) 116 writer.newline() 117 for gmapRecord in self.gmapRecords: 118 gmapRecord.toXML(writer, ttFont) 119 120 def fromXML(self, (name, attrs, content), ttFont): 121 if name == "GMAPRecord": 122 if not hasattr(self, "gmapRecords"): 123 self.gmapRecords = [] 124 gmapRecord = GMAPRecord() 125 self.gmapRecords.append(gmapRecord) 126 for element in content: 127 if isinstance(element, StringType): 128 continue 129 gmapRecord.fromXML(element, ttFont) 130 else: 131 value = attrs["value"] 132 if name == "PSFontName": 133 self.psFontName = value 134 else: 135 try: 136 value = safeEval(value) 137 except OverflowError: 138 value = long(value) 139 setattr(self, name, value) 140