1from fontTools.misc.py23 import bytesjoin 2from fontTools.misc import sstruct 3from fontTools.misc.textTools import safeEval, readHex 4from . import DefaultTable 5import sys 6import array 7 8GPKGFormat = """ 9 > # big endian 10 version: H 11 flags: H 12 numGMAPs: H 13 numGlyplets: 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 18 19class table_G_P_K_G_(DefaultTable.DefaultTable): 20 21 def decompile(self, data, ttFont): 22 dummy, newData = sstruct.unpack2(GPKGFormat, data, self) 23 24 GMAPoffsets = array.array("I") 25 endPos = (self.numGMAPs+1) * 4 26 GMAPoffsets.frombytes(newData[:endPos]) 27 if sys.byteorder != "big": GMAPoffsets.byteswap() 28 self.GMAPs = [] 29 for i in range(self.numGMAPs): 30 start = GMAPoffsets[i] 31 end = GMAPoffsets[i+1] 32 self.GMAPs.append(data[start:end]) 33 pos = endPos 34 endPos = pos + (self.numGlyplets + 1)*4 35 glyphletOffsets = array.array("I") 36 glyphletOffsets.frombytes(newData[pos:endPos]) 37 if sys.byteorder != "big": 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": gmapArray.byteswap() 59 dataList.append(gmapArray.tobytes()) 60 61 glyphletOffsets[0] = pos 62 for i in range(1, self.numGlyplets +1): 63 pos += len(self.glyphlets[i-1]) 64 glyphletOffsets[i] = pos 65 glyphletArray = array.array("I", glyphletOffsets) 66 if sys.byteorder != "big": glyphletArray.byteswap() 67 dataList.append(glyphletArray.tobytes()) 68 dataList += self.GMAPs 69 dataList += self.glyphlets 70 data = bytesjoin(dataList) 71 return data 72 73 def toXML(self, writer, ttFont): 74 writer.comment("Most of this table will be recalculated by the compiler") 75 writer.newline() 76 formatstring, names, fixes = sstruct.getformat(GPKGFormat) 77 for name in names: 78 value = getattr(self, name) 79 writer.simpletag(name, value=value) 80 writer.newline() 81 82 writer.begintag("GMAPs") 83 writer.newline() 84 for gmapData in self.GMAPs: 85 writer.begintag("hexdata") 86 writer.newline() 87 writer.dumphex(gmapData) 88 writer.endtag("hexdata") 89 writer.newline() 90 writer.endtag("GMAPs") 91 writer.newline() 92 93 writer.begintag("glyphlets") 94 writer.newline() 95 for glyphletData in self.glyphlets: 96 writer.begintag("hexdata") 97 writer.newline() 98 writer.dumphex(glyphletData) 99 writer.endtag("hexdata") 100 writer.newline() 101 writer.endtag("glyphlets") 102 writer.newline() 103 104 def fromXML(self, name, attrs, content, ttFont): 105 if name == "GMAPs": 106 if not hasattr(self, "GMAPs"): 107 self.GMAPs = [] 108 for element in content: 109 if isinstance(element, str): 110 continue 111 itemName, itemAttrs, itemContent = element 112 if itemName == "hexdata": 113 self.GMAPs.append(readHex(itemContent)) 114 elif name == "glyphlets": 115 if not hasattr(self, "glyphlets"): 116 self.glyphlets = [] 117 for element in content: 118 if isinstance(element, str): 119 continue 120 itemName, itemAttrs, itemContent = element 121 if itemName == "hexdata": 122 self.glyphlets.append(readHex(itemContent)) 123 else: 124 setattr(self, name, safeEval(attrs["value"])) 125