1from fontTools.misc import sstruct 2from fontTools.misc.textTools import safeEval 3from . import DefaultTable 4 5maxpFormat_0_5 = """ 6 > # big endian 7 tableVersion: i 8 numGlyphs: H 9""" 10 11maxpFormat_1_0_add = """ 12 > # big endian 13 maxPoints: H 14 maxContours: H 15 maxCompositePoints: H 16 maxCompositeContours: H 17 maxZones: H 18 maxTwilightPoints: H 19 maxStorage: H 20 maxFunctionDefs: H 21 maxInstructionDefs: H 22 maxStackElements: H 23 maxSizeOfInstructions: H 24 maxComponentElements: H 25 maxComponentDepth: H 26""" 27 28 29class table__m_a_x_p(DefaultTable.DefaultTable): 30 31 dependencies = ['glyf'] 32 33 def decompile(self, data, ttFont): 34 dummy, data = sstruct.unpack2(maxpFormat_0_5, data, self) 35 self.numGlyphs = int(self.numGlyphs) 36 if self.tableVersion != 0x00005000: 37 dummy, data = sstruct.unpack2(maxpFormat_1_0_add, data, self) 38 assert len(data) == 0 39 40 def compile(self, ttFont): 41 if 'glyf' in ttFont: 42 if ttFont.isLoaded('glyf') and ttFont.recalcBBoxes: 43 self.recalc(ttFont) 44 else: 45 pass # CFF 46 self.numGlyphs = len(ttFont.getGlyphOrder()) 47 if self.tableVersion != 0x00005000: 48 self.tableVersion = 0x00010000 49 data = sstruct.pack(maxpFormat_0_5, self) 50 if self.tableVersion == 0x00010000: 51 data = data + sstruct.pack(maxpFormat_1_0_add, self) 52 return data 53 54 def recalc(self, ttFont): 55 """Recalculate the font bounding box, and most other maxp values except 56 for the TT instructions values. Also recalculate the value of bit 1 57 of the flags field and the font bounding box of the 'head' table. 58 """ 59 glyfTable = ttFont['glyf'] 60 hmtxTable = ttFont['hmtx'] 61 headTable = ttFont['head'] 62 self.numGlyphs = len(glyfTable) 63 INFINITY = 100000 64 xMin = +INFINITY 65 yMin = +INFINITY 66 xMax = -INFINITY 67 yMax = -INFINITY 68 maxPoints = 0 69 maxContours = 0 70 maxCompositePoints = 0 71 maxCompositeContours = 0 72 maxComponentElements = 0 73 maxComponentDepth = 0 74 allXMinIsLsb = 1 75 for glyphName in ttFont.getGlyphOrder(): 76 g = glyfTable[glyphName] 77 if g.numberOfContours: 78 if hmtxTable[glyphName][1] != g.xMin: 79 allXMinIsLsb = 0 80 xMin = min(xMin, g.xMin) 81 yMin = min(yMin, g.yMin) 82 xMax = max(xMax, g.xMax) 83 yMax = max(yMax, g.yMax) 84 if g.numberOfContours > 0: 85 nPoints, nContours = g.getMaxpValues() 86 maxPoints = max(maxPoints, nPoints) 87 maxContours = max(maxContours, nContours) 88 else: 89 nPoints, nContours, componentDepth = g.getCompositeMaxpValues(glyfTable) 90 maxCompositePoints = max(maxCompositePoints, nPoints) 91 maxCompositeContours = max(maxCompositeContours, nContours) 92 maxComponentElements = max(maxComponentElements, len(g.components)) 93 maxComponentDepth = max(maxComponentDepth, componentDepth) 94 if xMin == +INFINITY: 95 headTable.xMin = 0 96 headTable.yMin = 0 97 headTable.xMax = 0 98 headTable.yMax = 0 99 else: 100 headTable.xMin = xMin 101 headTable.yMin = yMin 102 headTable.xMax = xMax 103 headTable.yMax = yMax 104 self.maxPoints = maxPoints 105 self.maxContours = maxContours 106 self.maxCompositePoints = maxCompositePoints 107 self.maxCompositeContours = maxCompositeContours 108 self.maxComponentElements = maxComponentElements 109 self.maxComponentDepth = maxComponentDepth 110 if allXMinIsLsb: 111 headTable.flags = headTable.flags | 0x2 112 else: 113 headTable.flags = headTable.flags & ~0x2 114 115 def testrepr(self): 116 items = sorted(self.__dict__.items()) 117 print(". . . . . . . . .") 118 for combo in items: 119 print(" %s: %s" % combo) 120 print(". . . . . . . . .") 121 122 def toXML(self, writer, ttFont): 123 if self.tableVersion != 0x00005000: 124 writer.comment("Most of this table will be recalculated by the compiler") 125 writer.newline() 126 formatstring, names, fixes = sstruct.getformat(maxpFormat_0_5) 127 if self.tableVersion != 0x00005000: 128 formatstring, names_1_0, fixes = sstruct.getformat(maxpFormat_1_0_add) 129 names = names + names_1_0 130 for name in names: 131 value = getattr(self, name) 132 if name == "tableVersion": 133 value = hex(value) 134 writer.simpletag(name, value=value) 135 writer.newline() 136 137 def fromXML(self, name, attrs, content, ttFont): 138 setattr(self, name, safeEval(attrs["value"])) 139