11ae29591efbb29492ce05378909ccf4028d7c1eeBehdad Esfahbodfrom __future__ import print_function, division, absolute_import 230e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodfrom fontTools.misc.py23 import * 37842e56b97ce677b83bdab09cda48bc2d89ac75aJustfrom fontTools import ttLib 47ed91eca1eaa96b79eae780778e89bb9ec44c1eeBehdad Esfahbodfrom fontTools.ttLib.standardGlyphOrder import standardGlyphOrder 57ed91eca1eaa96b79eae780778e89bb9ec44c1eeBehdad Esfahbodfrom fontTools.misc import sstruct 67842e56b97ce677b83bdab09cda48bc2d89ac75aJustfrom fontTools.misc.textTools import safeEval, readHex 730e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodfrom . import DefaultTable 830e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodimport sys 930e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodimport struct 1030e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodimport array 117842e56b97ce677b83bdab09cda48bc2d89ac75aJust 127842e56b97ce677b83bdab09cda48bc2d89ac75aJust 137842e56b97ce677b83bdab09cda48bc2d89ac75aJustpostFormat = """ 147842e56b97ce677b83bdab09cda48bc2d89ac75aJust > 157842e56b97ce677b83bdab09cda48bc2d89ac75aJust formatType: 16.16F 167842e56b97ce677b83bdab09cda48bc2d89ac75aJust italicAngle: 16.16F # italic angle in degrees 177842e56b97ce677b83bdab09cda48bc2d89ac75aJust underlinePosition: h 187842e56b97ce677b83bdab09cda48bc2d89ac75aJust underlineThickness: h 1904985bfdded4d445c67524b018965df1f4a4c313fcoiffie isFixedPitch: L 2004985bfdded4d445c67524b018965df1f4a4c313fcoiffie minMemType42: L # minimum memory if TrueType font is downloaded 2104985bfdded4d445c67524b018965df1f4a4c313fcoiffie maxMemType42: L # maximum memory if TrueType font is downloaded 2204985bfdded4d445c67524b018965df1f4a4c313fcoiffie minMemType1: L # minimum memory if Type1 font is downloaded 2304985bfdded4d445c67524b018965df1f4a4c313fcoiffie maxMemType1: L # maximum memory if Type1 font is downloaded 247842e56b97ce677b83bdab09cda48bc2d89ac75aJust""" 257842e56b97ce677b83bdab09cda48bc2d89ac75aJust 267842e56b97ce677b83bdab09cda48bc2d89ac75aJustpostFormatSize = sstruct.calcsize(postFormat) 277842e56b97ce677b83bdab09cda48bc2d89ac75aJust 287842e56b97ce677b83bdab09cda48bc2d89ac75aJust 297842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass table__p_o_s_t(DefaultTable.DefaultTable): 307842e56b97ce677b83bdab09cda48bc2d89ac75aJust 317842e56b97ce677b83bdab09cda48bc2d89ac75aJust def decompile(self, data, ttFont): 327842e56b97ce677b83bdab09cda48bc2d89ac75aJust sstruct.unpack(postFormat, data[:postFormatSize], self) 337842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = data[postFormatSize:] 347842e56b97ce677b83bdab09cda48bc2d89ac75aJust if self.formatType == 1.0: 357842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.decode_format_1_0(data, ttFont) 367842e56b97ce677b83bdab09cda48bc2d89ac75aJust elif self.formatType == 2.0: 377842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.decode_format_2_0(data, ttFont) 387842e56b97ce677b83bdab09cda48bc2d89ac75aJust elif self.formatType == 3.0: 397842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.decode_format_3_0(data, ttFont) 404a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten elif self.formatType == 4.0: 414a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten self.decode_format_4_0(data, ttFont) 427842e56b97ce677b83bdab09cda48bc2d89ac75aJust else: 437842e56b97ce677b83bdab09cda48bc2d89ac75aJust # supported format 44cd5aad92f23737ff93a110d5c73d624658a28da8Behdad Esfahbod raise ttLib.TTLibError("'post' table format %f not supported" % self.formatType) 457842e56b97ce677b83bdab09cda48bc2d89ac75aJust 467842e56b97ce677b83bdab09cda48bc2d89ac75aJust def compile(self, ttFont): 477842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = sstruct.pack(postFormat, self) 487842e56b97ce677b83bdab09cda48bc2d89ac75aJust if self.formatType == 1.0: 497842e56b97ce677b83bdab09cda48bc2d89ac75aJust pass # we're done 507842e56b97ce677b83bdab09cda48bc2d89ac75aJust elif self.formatType == 2.0: 517842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = data + self.encode_format_2_0(ttFont) 527842e56b97ce677b83bdab09cda48bc2d89ac75aJust elif self.formatType == 3.0: 537842e56b97ce677b83bdab09cda48bc2d89ac75aJust pass # we're done 544a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten elif self.formatType == 4.0: 554a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten data = data + self.encode_format_4_0(ttFont) 567842e56b97ce677b83bdab09cda48bc2d89ac75aJust else: 577842e56b97ce677b83bdab09cda48bc2d89ac75aJust # supported format 58cd5aad92f23737ff93a110d5c73d624658a28da8Behdad Esfahbod raise ttLib.TTLibError("'post' table format %f not supported" % self.formatType) 597842e56b97ce677b83bdab09cda48bc2d89ac75aJust return data 607842e56b97ce677b83bdab09cda48bc2d89ac75aJust 617842e56b97ce677b83bdab09cda48bc2d89ac75aJust def getGlyphOrder(self): 627842e56b97ce677b83bdab09cda48bc2d89ac75aJust """This function will get called by a ttLib.TTFont instance. 637842e56b97ce677b83bdab09cda48bc2d89ac75aJust Do not call this function yourself, use TTFont().getGlyphOrder() 647842e56b97ce677b83bdab09cda48bc2d89ac75aJust or its relatives instead! 657842e56b97ce677b83bdab09cda48bc2d89ac75aJust """ 667842e56b97ce677b83bdab09cda48bc2d89ac75aJust if not hasattr(self, "glyphOrder"): 67cd5aad92f23737ff93a110d5c73d624658a28da8Behdad Esfahbod raise ttLib.TTLibError("illegal use of getGlyphOrder()") 687842e56b97ce677b83bdab09cda48bc2d89ac75aJust glyphOrder = self.glyphOrder 697842e56b97ce677b83bdab09cda48bc2d89ac75aJust del self.glyphOrder 707842e56b97ce677b83bdab09cda48bc2d89ac75aJust return glyphOrder 717842e56b97ce677b83bdab09cda48bc2d89ac75aJust 727842e56b97ce677b83bdab09cda48bc2d89ac75aJust def decode_format_1_0(self, data, ttFont): 73c2b05ccf8ce7b8ae80e06b667152398ebd4c4872jvr self.glyphOrder = standardGlyphOrder[:ttFont["maxp"].numGlyphs] 747842e56b97ce677b83bdab09cda48bc2d89ac75aJust 757842e56b97ce677b83bdab09cda48bc2d89ac75aJust def decode_format_2_0(self, data, ttFont): 767842e56b97ce677b83bdab09cda48bc2d89ac75aJust numGlyphs, = struct.unpack(">H", data[:2]) 777842e56b97ce677b83bdab09cda48bc2d89ac75aJust numGlyphs = int(numGlyphs) 78f9104bcc2cd61bf029ac6736ef0ee98968bde472jvr if numGlyphs > ttFont['maxp'].numGlyphs: 79f9104bcc2cd61bf029ac6736ef0ee98968bde472jvr # Assume the numGlyphs field is bogus, so sync with maxp. 80f9104bcc2cd61bf029ac6736ef0ee98968bde472jvr # I've seen this in one font, and if the assumption is 81f9104bcc2cd61bf029ac6736ef0ee98968bde472jvr # wrong elsewhere, well, so be it: it's hard enough to 82f9104bcc2cd61bf029ac6736ef0ee98968bde472jvr # work around _one_ non-conforming post format... 83f9104bcc2cd61bf029ac6736ef0ee98968bde472jvr numGlyphs = ttFont['maxp'].numGlyphs 847842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = data[2:] 857842e56b97ce677b83bdab09cda48bc2d89ac75aJust indices = array.array("H") 867842e56b97ce677b83bdab09cda48bc2d89ac75aJust indices.fromstring(data[:2*numGlyphs]) 87180ace6a5ff1399ec53bc696e8bef7cce6eef39aBehdad Esfahbod if sys.byteorder != "big": 887842e56b97ce677b83bdab09cda48bc2d89ac75aJust indices.byteswap() 897842e56b97ce677b83bdab09cda48bc2d89ac75aJust data = data[2*numGlyphs:] 907842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.extraNames = extraNames = unpackPStrings(data) 917842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.glyphOrder = glyphOrder = [None] * int(ttFont['maxp'].numGlyphs) 927842e56b97ce677b83bdab09cda48bc2d89ac75aJust for glyphID in range(numGlyphs): 937842e56b97ce677b83bdab09cda48bc2d89ac75aJust index = indices[glyphID] 947842e56b97ce677b83bdab09cda48bc2d89ac75aJust if index > 257: 957842e56b97ce677b83bdab09cda48bc2d89ac75aJust name = extraNames[index-258] 967842e56b97ce677b83bdab09cda48bc2d89ac75aJust else: 977842e56b97ce677b83bdab09cda48bc2d89ac75aJust # fetch names from standard list 987842e56b97ce677b83bdab09cda48bc2d89ac75aJust name = standardGlyphOrder[index] 997842e56b97ce677b83bdab09cda48bc2d89ac75aJust glyphOrder[glyphID] = name 1007842e56b97ce677b83bdab09cda48bc2d89ac75aJust #AL990511: code added to handle the case of new glyphs without 1017842e56b97ce677b83bdab09cda48bc2d89ac75aJust # entries into the 'post' table 1027842e56b97ce677b83bdab09cda48bc2d89ac75aJust if numGlyphs < ttFont['maxp'].numGlyphs: 1037842e56b97ce677b83bdab09cda48bc2d89ac75aJust for i in range(numGlyphs, ttFont['maxp'].numGlyphs): 1047842e56b97ce677b83bdab09cda48bc2d89ac75aJust glyphOrder[i] = "glyph#%.5d" % i 1057842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.extraNames.append(glyphOrder[i]) 1067842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.build_psNameMapping(ttFont) 1077842e56b97ce677b83bdab09cda48bc2d89ac75aJust 1087842e56b97ce677b83bdab09cda48bc2d89ac75aJust def build_psNameMapping(self, ttFont): 1097842e56b97ce677b83bdab09cda48bc2d89ac75aJust mapping = {} 1107842e56b97ce677b83bdab09cda48bc2d89ac75aJust allNames = {} 1117842e56b97ce677b83bdab09cda48bc2d89ac75aJust for i in range(ttFont['maxp'].numGlyphs): 1127842e56b97ce677b83bdab09cda48bc2d89ac75aJust glyphName = psName = self.glyphOrder[i] 113bc5e1cb195c0bfa1c8e7507326d5a9ad05aecb4bBehdad Esfahbod if glyphName in allNames: 1147842e56b97ce677b83bdab09cda48bc2d89ac75aJust # make up a new glyphName that's unique 11585be2e0a9773acec3c6d14c345b1fd94ab3aa5c3Behdad Esfahbod n = allNames[glyphName] 11685be2e0a9773acec3c6d14c345b1fd94ab3aa5c3Behdad Esfahbod allNames[glyphName] = n + 1 117dc7e6f3e5563a853477ebe26166b002c158dbe8bBehdad Esfahbod glyphName = glyphName + "#" + repr(n) 1187842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.glyphOrder[i] = glyphName 1197842e56b97ce677b83bdab09cda48bc2d89ac75aJust mapping[glyphName] = psName 12085be2e0a9773acec3c6d14c345b1fd94ab3aa5c3Behdad Esfahbod else: 12185be2e0a9773acec3c6d14c345b1fd94ab3aa5c3Behdad Esfahbod allNames[glyphName] = 1 1227842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.mapping = mapping 1237842e56b97ce677b83bdab09cda48bc2d89ac75aJust 1247842e56b97ce677b83bdab09cda48bc2d89ac75aJust def decode_format_3_0(self, data, ttFont): 1257842e56b97ce677b83bdab09cda48bc2d89ac75aJust # Setting self.glyphOrder to None will cause the TTFont object 1267842e56b97ce677b83bdab09cda48bc2d89ac75aJust # try and construct glyph names from a Unicode cmap table. 1277842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.glyphOrder = None 1287842e56b97ce677b83bdab09cda48bc2d89ac75aJust 1294a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten def decode_format_4_0(self, data, ttFont): 1304a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten from fontTools import agl 1314a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten numGlyphs = ttFont['maxp'].numGlyphs 132149b9f97e39fa2ff3272a9677e49d9d3e7901140Olivier Berten indices = array.array("H") 133149b9f97e39fa2ff3272a9677e49d9d3e7901140Olivier Berten indices.fromstring(data) 134149b9f97e39fa2ff3272a9677e49d9d3e7901140Olivier Berten if sys.byteorder != "big": 135149b9f97e39fa2ff3272a9677e49d9d3e7901140Olivier Berten indices.byteswap() 1364a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten # In some older fonts, the size of the post table doesn't match 1374a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten # the number of glyphs. Sometimes it's bigger, sometimes smaller. 1384a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten self.glyphOrder = glyphOrder = [''] * int(numGlyphs) 1394a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten for i in range(min(len(indices),numGlyphs)): 1404a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten if indices[i] == 0xFFFF: 1414a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten self.glyphOrder[i] = '' 1424a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten elif indices[i] in agl.UV2AGL: 1434a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten self.glyphOrder[i] = agl.UV2AGL[indices[i]] 1444a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten else: 1454a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten self.glyphOrder[i] = "uni%04X" % indices[i] 1464a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten self.build_psNameMapping(ttFont) 1474a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten 1487842e56b97ce677b83bdab09cda48bc2d89ac75aJust def encode_format_2_0(self, ttFont): 1497842e56b97ce677b83bdab09cda48bc2d89ac75aJust numGlyphs = ttFont['maxp'].numGlyphs 1507842e56b97ce677b83bdab09cda48bc2d89ac75aJust glyphOrder = ttFont.getGlyphOrder() 1517842e56b97ce677b83bdab09cda48bc2d89ac75aJust assert len(glyphOrder) == numGlyphs 1527842e56b97ce677b83bdab09cda48bc2d89ac75aJust indices = array.array("H") 1530d762b00de43e9c73a77969afb52a68f1974c54ejvr extraDict = {} 1540d762b00de43e9c73a77969afb52a68f1974c54ejvr extraNames = self.extraNames 1550d762b00de43e9c73a77969afb52a68f1974c54ejvr for i in range(len(extraNames)): 1560d762b00de43e9c73a77969afb52a68f1974c54ejvr extraDict[extraNames[i]] = i 1577842e56b97ce677b83bdab09cda48bc2d89ac75aJust for glyphID in range(numGlyphs): 1587842e56b97ce677b83bdab09cda48bc2d89ac75aJust glyphName = glyphOrder[glyphID] 159bc5e1cb195c0bfa1c8e7507326d5a9ad05aecb4bBehdad Esfahbod if glyphName in self.mapping: 1607842e56b97ce677b83bdab09cda48bc2d89ac75aJust psName = self.mapping[glyphName] 1617842e56b97ce677b83bdab09cda48bc2d89ac75aJust else: 1627842e56b97ce677b83bdab09cda48bc2d89ac75aJust psName = glyphName 163bc5e1cb195c0bfa1c8e7507326d5a9ad05aecb4bBehdad Esfahbod if psName in extraDict: 1640d762b00de43e9c73a77969afb52a68f1974c54ejvr index = 258 + extraDict[psName] 1657842e56b97ce677b83bdab09cda48bc2d89ac75aJust elif psName in standardGlyphOrder: 1667842e56b97ce677b83bdab09cda48bc2d89ac75aJust index = standardGlyphOrder.index(psName) 1677842e56b97ce677b83bdab09cda48bc2d89ac75aJust else: 1680d762b00de43e9c73a77969afb52a68f1974c54ejvr index = 258 + len(extraNames) 1690d762b00de43e9c73a77969afb52a68f1974c54ejvr extraDict[psName] = len(extraNames) 1700d762b00de43e9c73a77969afb52a68f1974c54ejvr extraNames.append(psName) 1717842e56b97ce677b83bdab09cda48bc2d89ac75aJust indices.append(index) 172180ace6a5ff1399ec53bc696e8bef7cce6eef39aBehdad Esfahbod if sys.byteorder != "big": 1737842e56b97ce677b83bdab09cda48bc2d89ac75aJust indices.byteswap() 1740d762b00de43e9c73a77969afb52a68f1974c54ejvr return struct.pack(">H", numGlyphs) + indices.tostring() + packPStrings(extraNames) 1757842e56b97ce677b83bdab09cda48bc2d89ac75aJust 1764a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten def encode_format_4_0(self, ttFont): 1774a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten from fontTools import agl 1784a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten numGlyphs = ttFont['maxp'].numGlyphs 1794a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten glyphOrder = ttFont.getGlyphOrder() 1804a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten assert len(glyphOrder) == numGlyphs 181ec8dccb7318988591aa65bdf3a70d521837d094bOlivier Berten indices = array.array("H") 1824a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten for glyphID in glyphOrder: 1834a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten glyphID = glyphID.split('#')[0] 1844a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten if glyphID in agl.AGL2UV: 185ec8dccb7318988591aa65bdf3a70d521837d094bOlivier Berten indices.append(agl.AGL2UV[glyphID]) 1864a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten elif len(glyphID) == 7 and glyphID[:3] == 'uni': 187ec8dccb7318988591aa65bdf3a70d521837d094bOlivier Berten indices.append(int(glyphID[3:],16)) 1884a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten else: 189ec8dccb7318988591aa65bdf3a70d521837d094bOlivier Berten indices.append(0xFFFF) 190ec8dccb7318988591aa65bdf3a70d521837d094bOlivier Berten if sys.byteorder != "big": 191ec8dccb7318988591aa65bdf3a70d521837d094bOlivier Berten indices.byteswap() 192ec8dccb7318988591aa65bdf3a70d521837d094bOlivier Berten return indices.tostring() 1934a73f8b4e983b3910d888bab7d50293e363152e9Olivier Berten 1947842e56b97ce677b83bdab09cda48bc2d89ac75aJust def toXML(self, writer, ttFont): 1957842e56b97ce677b83bdab09cda48bc2d89ac75aJust formatstring, names, fixes = sstruct.getformat(postFormat) 1967842e56b97ce677b83bdab09cda48bc2d89ac75aJust for name in names: 1977842e56b97ce677b83bdab09cda48bc2d89ac75aJust value = getattr(self, name) 1987842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.simpletag(name, value=value) 1997842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.newline() 2007842e56b97ce677b83bdab09cda48bc2d89ac75aJust if hasattr(self, "mapping"): 2017842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.begintag("psNames") 2027842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.newline() 2037842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.comment("This file uses unique glyph names based on the information\n" 2047842e56b97ce677b83bdab09cda48bc2d89ac75aJust "found in the 'post' table. Since these names might not be unique,\n" 2057842e56b97ce677b83bdab09cda48bc2d89ac75aJust "we have to invent artificial names in case of clashes. In order to\n" 2067842e56b97ce677b83bdab09cda48bc2d89ac75aJust "be able to retain the original information, we need a name to\n" 2077842e56b97ce677b83bdab09cda48bc2d89ac75aJust "ps name mapping for those cases where they differ. That's what\n" 2087842e56b97ce677b83bdab09cda48bc2d89ac75aJust "you see below.\n") 2097842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.newline() 210ac1b4359467ca3deab03186a15eae1d55eb35567Behdad Esfahbod items = sorted(self.mapping.items()) 2117842e56b97ce677b83bdab09cda48bc2d89ac75aJust for name, psName in items: 2127842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.simpletag("psName", name=name, psName=psName) 2137842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.newline() 2147842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.endtag("psNames") 2157842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.newline() 2167842e56b97ce677b83bdab09cda48bc2d89ac75aJust if hasattr(self, "extraNames"): 2177842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.begintag("extraNames") 2187842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.newline() 2197842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.comment("following are the name that are not taken from the standard Mac glyph order") 2207842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.newline() 2217842e56b97ce677b83bdab09cda48bc2d89ac75aJust for name in self.extraNames: 2227842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.simpletag("psName", name=name) 2237842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.newline() 2247842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.endtag("extraNames") 2257842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.newline() 2267842e56b97ce677b83bdab09cda48bc2d89ac75aJust if hasattr(self, "data"): 2277842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.begintag("hexdata") 2287842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.newline() 2297842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.dumphex(self.data) 2307842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.endtag("hexdata") 2317842e56b97ce677b83bdab09cda48bc2d89ac75aJust writer.newline() 2327842e56b97ce677b83bdab09cda48bc2d89ac75aJust 2333a9fd301808f5a8991ca9ac44028d1ecb22d307fBehdad Esfahbod def fromXML(self, name, attrs, content, ttFont): 2347842e56b97ce677b83bdab09cda48bc2d89ac75aJust if name not in ("psNames", "extraNames", "hexdata"): 2357842e56b97ce677b83bdab09cda48bc2d89ac75aJust setattr(self, name, safeEval(attrs["value"])) 2367842e56b97ce677b83bdab09cda48bc2d89ac75aJust elif name == "psNames": 2377842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.mapping = {} 2387842e56b97ce677b83bdab09cda48bc2d89ac75aJust for element in content: 239b774f9f684c5a0f91f5fa177c9a461968789123fBehdad Esfahbod if not isinstance(element, tuple): 2407842e56b97ce677b83bdab09cda48bc2d89ac75aJust continue 2417842e56b97ce677b83bdab09cda48bc2d89ac75aJust name, attrs, content = element 2427842e56b97ce677b83bdab09cda48bc2d89ac75aJust if name == "psName": 2437842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.mapping[attrs["name"]] = attrs["psName"] 2447842e56b97ce677b83bdab09cda48bc2d89ac75aJust elif name == "extraNames": 2457842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.extraNames = [] 2467842e56b97ce677b83bdab09cda48bc2d89ac75aJust for element in content: 247b774f9f684c5a0f91f5fa177c9a461968789123fBehdad Esfahbod if not isinstance(element, tuple): 2487842e56b97ce677b83bdab09cda48bc2d89ac75aJust continue 2497842e56b97ce677b83bdab09cda48bc2d89ac75aJust name, attrs, content = element 2507842e56b97ce677b83bdab09cda48bc2d89ac75aJust if name == "psName": 2517842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.extraNames.append(attrs["name"]) 2527842e56b97ce677b83bdab09cda48bc2d89ac75aJust else: 2537842e56b97ce677b83bdab09cda48bc2d89ac75aJust self.data = readHex(content) 2547842e56b97ce677b83bdab09cda48bc2d89ac75aJust 2557842e56b97ce677b83bdab09cda48bc2d89ac75aJust 2567842e56b97ce677b83bdab09cda48bc2d89ac75aJustdef unpackPStrings(data): 2577842e56b97ce677b83bdab09cda48bc2d89ac75aJust strings = [] 258f9104bcc2cd61bf029ac6736ef0ee98968bde472jvr index = 0 259f9104bcc2cd61bf029ac6736ef0ee98968bde472jvr dataLen = len(data) 260f9104bcc2cd61bf029ac6736ef0ee98968bde472jvr while index < dataLen: 261319c5fd10e2ea84304bd299b7483e05b5b0d5480Behdad Esfahbod length = byteord(data[index]) 26243d7ac16b19f9cad251a8d74a0b93cf8d439fad7Behdad Esfahbod strings.append(tostr(data[index+1:index+1+length], encoding="latin1")) 263f9104bcc2cd61bf029ac6736ef0ee98968bde472jvr index = index + 1 + length 2647842e56b97ce677b83bdab09cda48bc2d89ac75aJust return strings 2657842e56b97ce677b83bdab09cda48bc2d89ac75aJust 266f9104bcc2cd61bf029ac6736ef0ee98968bde472jvr 2677842e56b97ce677b83bdab09cda48bc2d89ac75aJustdef packPStrings(strings): 2685f6418d9e1fa15a89dcec29cdc433ba2c99732c3Behdad Esfahbod data = b"" 2697842e56b97ce677b83bdab09cda48bc2d89ac75aJust for s in strings: 27043d7ac16b19f9cad251a8d74a0b93cf8d439fad7Behdad Esfahbod data = data + bytechr(len(s)) + tobytes(s, encoding="latin1") 2717842e56b97ce677b83bdab09cda48bc2d89ac75aJust return data 2727842e56b97ce677b83bdab09cda48bc2d89ac75aJust 273