1from fontTools.misc import sstruct 2from fontTools.misc.textTools import bytesjoin, safeEval, readHex 3from . import DefaultTable 4import sys 5import array 6 7GPKGFormat = """ 8 > # big endian 9 version: H 10 flags: H 11 numGMAPs: H 12 numGlyplets: H 13""" 14# psFontName is a byte string which follows the record above. This is zero padded 15# to the beginning of the records array. The recordsOffsst is 32 bit aligned. 16 17 18class table_G_P_K_G_(DefaultTable.DefaultTable): 19 def decompile(self, data, ttFont): 20 dummy, newData = sstruct.unpack2(GPKGFormat, data, self) 21 22 GMAPoffsets = array.array("I") 23 endPos = (self.numGMAPs + 1) * 4 24 GMAPoffsets.frombytes(newData[:endPos]) 25 if sys.byteorder != "big": 26 GMAPoffsets.byteswap() 27 self.GMAPs = [] 28 for i in range(self.numGMAPs): 29 start = GMAPoffsets[i] 30 end = GMAPoffsets[i + 1] 31 self.GMAPs.append(data[start:end]) 32 pos = endPos 33 endPos = pos + (self.numGlyplets + 1) * 4 34 glyphletOffsets = array.array("I") 35 glyphletOffsets.frombytes(newData[pos:endPos]) 36 if sys.byteorder != "big": 37 glyphletOffsets.byteswap() 38 self.glyphlets = [] 39 for i in range(self.numGlyplets): 40 start = glyphletOffsets[i] 41 end = glyphletOffsets[i + 1] 42 self.glyphlets.append(data[start:end]) 43 44 def compile(self, ttFont): 45 self.numGMAPs = len(self.GMAPs) 46 self.numGlyplets = len(self.glyphlets) 47 GMAPoffsets = [0] * (self.numGMAPs + 1) 48 glyphletOffsets = [0] * (self.numGlyplets + 1) 49 50 dataList = [sstruct.pack(GPKGFormat, self)] 51 52 pos = len(dataList[0]) + (self.numGMAPs + 1) * 4 + (self.numGlyplets + 1) * 4 53 GMAPoffsets[0] = pos 54 for i in range(1, self.numGMAPs + 1): 55 pos += len(self.GMAPs[i - 1]) 56 GMAPoffsets[i] = pos 57 gmapArray = array.array("I", GMAPoffsets) 58 if sys.byteorder != "big": 59 gmapArray.byteswap() 60 dataList.append(gmapArray.tobytes()) 61 62 glyphletOffsets[0] = pos 63 for i in range(1, self.numGlyplets + 1): 64 pos += len(self.glyphlets[i - 1]) 65 glyphletOffsets[i] = pos 66 glyphletArray = array.array("I", glyphletOffsets) 67 if sys.byteorder != "big": 68 glyphletArray.byteswap() 69 dataList.append(glyphletArray.tobytes()) 70 dataList += self.GMAPs 71 dataList += self.glyphlets 72 data = bytesjoin(dataList) 73 return data 74 75 def toXML(self, writer, ttFont): 76 writer.comment("Most of this table will be recalculated by the compiler") 77 writer.newline() 78 formatstring, names, fixes = sstruct.getformat(GPKGFormat) 79 for name in names: 80 value = getattr(self, name) 81 writer.simpletag(name, value=value) 82 writer.newline() 83 84 writer.begintag("GMAPs") 85 writer.newline() 86 for gmapData in self.GMAPs: 87 writer.begintag("hexdata") 88 writer.newline() 89 writer.dumphex(gmapData) 90 writer.endtag("hexdata") 91 writer.newline() 92 writer.endtag("GMAPs") 93 writer.newline() 94 95 writer.begintag("glyphlets") 96 writer.newline() 97 for glyphletData in self.glyphlets: 98 writer.begintag("hexdata") 99 writer.newline() 100 writer.dumphex(glyphletData) 101 writer.endtag("hexdata") 102 writer.newline() 103 writer.endtag("glyphlets") 104 writer.newline() 105 106 def fromXML(self, name, attrs, content, ttFont): 107 if name == "GMAPs": 108 if not hasattr(self, "GMAPs"): 109 self.GMAPs = [] 110 for element in content: 111 if isinstance(element, str): 112 continue 113 itemName, itemAttrs, itemContent = element 114 if itemName == "hexdata": 115 self.GMAPs.append(readHex(itemContent)) 116 elif name == "glyphlets": 117 if not hasattr(self, "glyphlets"): 118 self.glyphlets = [] 119 for element in content: 120 if isinstance(element, str): 121 continue 122 itemName, itemAttrs, itemContent = element 123 if itemName == "hexdata": 124 self.glyphlets.append(readHex(itemContent)) 125 else: 126 setattr(self, name, safeEval(attrs["value"])) 127