class TTF: def __init__(self, path): with open(path, "rb") as f: self.src = f.read() self.header = Header(self.src) self.offsetData = 12 + 16 * self.header.numTables self.tables = OrderedDict() for i in range(self.header.numTables): idx = 12 + 16 * i t = Table(self.src, idx) self.tables[t.tag] = t if t.tag == "loca": print binascii.b2a_hex(t.data[-3]) # sort tables with offset # self.tables.sort(key=lambda x: x.offset) # get global properties head = self.tables["head"] self.checkSumAdjustment = struct.unpack("!L", head.data[8:12])[0] head.data = head.data[:8] + "\0\0\0\0" + head.data[12:] # byte length of loca values loca = self.tables["loca"] if (ord(head.data[-1]) & 0xFF) >> 4 == 0: loca_format = "H" loca_size = 2 else: loca_format = "L" loca_size = 4 self.numGlyphs = struct.unpack("!H", self.tables["maxp"].data[4:6])[0] print "loca_format: ", loca_format print "len(self.loca.data): ", len(loca.data) print "numGlyphs: ", self.numGlyphs glyf_offsets = struct.unpack("!" + str(self.numGlyphs + 1) + loca_format, loca.data) print "len(glyf_offsets): ", len(glyf_offsets) # check checksum for all table def checkTables(self): for k,t in self.tables.items(): tmp = t.data if k == "head": tmp = tmp[:8] + "\0\0\0\0" + tmp[12:] if t.checkSum == calcSum(tmp): print k, ": ok" else: print k, ": ng" # dump table for debug def dumpTable(self, name): if not(name in self.tables): return with open(name + "_data", "wb") as f: f.write(self.tables[k].data) def outputTTF(self): ttf_header = "" ttf_table = "" ttf_data = "" # make sure tables are sorted by offset # self.tables.sort(key=lambda x: x.offset) # compute offsets for data offset_new = 0 # offset for ttf_data = len(ttf_header + ttf_table) offset_data = 12 + (16 * self.header.numTables) # for checkSumAdj offset_csa = 0 totalSum = 0 # FIRST: generate ttf_data, and calculate offset offsets = {} for k, t in sorted(self.tables.items(), key=lambda x: x[1].offset): offsets[k] = offset_new ttf_data += t.data # insert paddings if t.length % 4 != 0: ttf_data += "\0" * (4 - (t.length % 4)) # check the data with src left = offset_data + offset_new if (self.src[left : left + t.length] == t.data and ttf_data[offset_new : offset_new + t.length] == t.data): print k, ": same" else: print k, ": different" # for checkSumAdjustment. totalSum += t.checkSum # update offset, including paddings offset_new += (t.length + 3) & 0xFFFFFFFC # SECOND: generate ttf_table for k,t in self.tables.items(): t.offset = offsets[k] + offset_data ttf_table += t.outputTTF() # THIRD: generate ttf_header ttf_header = self.header.outputTTF() # now we gotta calculate checkSumAdjustment in head table. offset_csa = offsets["head"] + 8 if ttf_data[offset_csa:offset_csa+4] == "\0\0\0\0": print "csa is \\0\\0\\0\\0, it's ok!" num_int32 = (12 + (16 * self.header.numTables)) / 4 totalSum += sum(struct.unpack("!" + str(num_int32) + "L", ttf_header + ttf_table)) csa_old = self.src[offset_data + offset_csa : offset_data + offset_csa + 4] csa = (0xB1B0AFBA - totalSum) & 0xFFFFFFFF print "old csa: ", binascii.b2a_hex(csa_old) print "new csa: ", binascii.b2a_hex(struct.pack("!L", csa)) ttf_data = ttf_data[:offset_csa] + struct.pack("!L", csa) + ttf_data[(offset_csa+4):] head = self.tables["head"] left = head.offset + offset_data if self.src[left : left + head.length] == head.data: print "head: same" else: print "head: different" # check values with self.src if ttf_header == self.src[:12]: print "header: same" else: print "header: different" if ttf_table == self.src[12:12+(16*self.header.numTables)]: print "table: same" else: print "table: different" if ttf_data == self.src[12+(16*self.header.numTables):]: print "data: same" else: print "data: different" s = (ttf_header + ttf_table + ttf_data) if s == self.src: print "all same!!!" else: print "all differ..." return s def glitch(self): pass