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