_m_a_x_p.py revision 898295619d8df4e4422c566cd9499c48d1d6b647
17842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport DefaultTable
27842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport sstruct
37842e56b97ce677b83bdab09cda48bc2d89ac75aJustfrom fontTools.misc.textTools import safeEval
47842e56b97ce677b83bdab09cda48bc2d89ac75aJust
57842e56b97ce677b83bdab09cda48bc2d89ac75aJustmaxpFormat_0_5 = """
67842e56b97ce677b83bdab09cda48bc2d89ac75aJust		>	# big endian
7898295619d8df4e4422c566cd9499c48d1d6b647jvr		tableVersion:           i
8898295619d8df4e4422c566cd9499c48d1d6b647jvr		numGlyphs:              H
97842e56b97ce677b83bdab09cda48bc2d89ac75aJust"""
107842e56b97ce677b83bdab09cda48bc2d89ac75aJust
117842e56b97ce677b83bdab09cda48bc2d89ac75aJustmaxpFormat_1_0_add = """
127842e56b97ce677b83bdab09cda48bc2d89ac75aJust		>	# big endian
13898295619d8df4e4422c566cd9499c48d1d6b647jvr		maxPoints:              H
14898295619d8df4e4422c566cd9499c48d1d6b647jvr		maxContours:            H
15898295619d8df4e4422c566cd9499c48d1d6b647jvr		maxCompositePoints:     H
16898295619d8df4e4422c566cd9499c48d1d6b647jvr		maxCompositeContours:   H
17898295619d8df4e4422c566cd9499c48d1d6b647jvr		maxZones:               H
18898295619d8df4e4422c566cd9499c48d1d6b647jvr		maxTwilightPoints:      H
19898295619d8df4e4422c566cd9499c48d1d6b647jvr		maxStorage:             H
20898295619d8df4e4422c566cd9499c48d1d6b647jvr		maxFunctionDefs:        H
21898295619d8df4e4422c566cd9499c48d1d6b647jvr		maxInstructionDefs:     H
22898295619d8df4e4422c566cd9499c48d1d6b647jvr		maxStackElements:       H
23898295619d8df4e4422c566cd9499c48d1d6b647jvr		maxSizeOfInstructions:  H
24898295619d8df4e4422c566cd9499c48d1d6b647jvr		maxComponentElements:   H
25898295619d8df4e4422c566cd9499c48d1d6b647jvr		maxComponentDepth:      H
267842e56b97ce677b83bdab09cda48bc2d89ac75aJust"""
277842e56b97ce677b83bdab09cda48bc2d89ac75aJust
287842e56b97ce677b83bdab09cda48bc2d89ac75aJust
297842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass table__m_a_x_p(DefaultTable.DefaultTable):
307842e56b97ce677b83bdab09cda48bc2d89ac75aJust
317842e56b97ce677b83bdab09cda48bc2d89ac75aJust	dependencies = ['glyf']
327842e56b97ce677b83bdab09cda48bc2d89ac75aJust
337842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def decompile(self, data, ttFont):
347842e56b97ce677b83bdab09cda48bc2d89ac75aJust		dummy, data = sstruct.unpack2(maxpFormat_0_5, data, self)
357842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.numGlyphs = int(self.numGlyphs)
36bc90c7a05b2e5114db9b0c0a6448e68d80ccf622jvr		if self.tableVersion != 0x00005000:
377842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dummy, data = sstruct.unpack2(maxpFormat_1_0_add, data, self)
387842e56b97ce677b83bdab09cda48bc2d89ac75aJust		assert len(data) == 0
397842e56b97ce677b83bdab09cda48bc2d89ac75aJust
407842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def compile(self, ttFont):
417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if ttFont.has_key('glyf'):
423e097c609540944dd9290ad58df346ca86492031Just			if ttFont.isLoaded('glyf') and ttFont.recalcBBoxes:
437842e56b97ce677b83bdab09cda48bc2d89ac75aJust				self.recalc(ttFont)
447842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
45bc90c7a05b2e5114db9b0c0a6448e68d80ccf622jvr			pass  # CFF
46bc90c7a05b2e5114db9b0c0a6448e68d80ccf622jvr		if self.tableVersion != 0x00005000:
47bc90c7a05b2e5114db9b0c0a6448e68d80ccf622jvr			self.tableVersion = 0x00010000
487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		data = sstruct.pack(maxpFormat_0_5, self)
497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.tableVersion == 0x00010000:
507842e56b97ce677b83bdab09cda48bc2d89ac75aJust			data = data + sstruct.pack(maxpFormat_1_0_add, self)
517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return data
527842e56b97ce677b83bdab09cda48bc2d89ac75aJust
537842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def recalc(self, ttFont):
547842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""Recalculate the font bounding box, and most other maxp values except
557842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for the TT instructions values. Also recalculate the value of bit 1
56fc99ad1513ca5443a29f1cc99df6016325e8dcbbPetr		of the flags field and the font bounding box of the 'head' table.
577842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""
587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		glyfTable = ttFont['glyf']
597842e56b97ce677b83bdab09cda48bc2d89ac75aJust		hmtxTable = ttFont['hmtx']
607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		headTable = ttFont['head']
617842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.numGlyphs = len(glyfTable)
627842e56b97ce677b83bdab09cda48bc2d89ac75aJust		xMin = 100000
637842e56b97ce677b83bdab09cda48bc2d89ac75aJust		yMin = 100000
647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		xMax = -100000
657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		yMax = -100000
667842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxPoints = 0
677842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxContours = 0
687842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxCompositePoints = 0
697842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxCompositeContours = 0
707842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxComponentElements = 0
717842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxComponentDepth = 0
727842e56b97ce677b83bdab09cda48bc2d89ac75aJust		allXMaxIsLsb = 1
737842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for glyphName in ttFont.getGlyphOrder():
747842e56b97ce677b83bdab09cda48bc2d89ac75aJust			g = glyfTable[glyphName]
757842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if g.numberOfContours:
767842e56b97ce677b83bdab09cda48bc2d89ac75aJust				if hmtxTable[glyphName][1] <> g.xMin:
777842e56b97ce677b83bdab09cda48bc2d89ac75aJust					allXMaxIsLsb = 0
787842e56b97ce677b83bdab09cda48bc2d89ac75aJust				xMin = min(xMin, g.xMin)
797842e56b97ce677b83bdab09cda48bc2d89ac75aJust				yMin = min(yMin, g.yMin)
807842e56b97ce677b83bdab09cda48bc2d89ac75aJust				xMax = max(xMax, g.xMax)
817842e56b97ce677b83bdab09cda48bc2d89ac75aJust				yMax = max(yMax, g.yMax)
827842e56b97ce677b83bdab09cda48bc2d89ac75aJust				if g.numberOfContours > 0:
837842e56b97ce677b83bdab09cda48bc2d89ac75aJust					nPoints, nContours = g.getMaxpValues()
847842e56b97ce677b83bdab09cda48bc2d89ac75aJust					maxPoints = max(maxPoints, nPoints)
857842e56b97ce677b83bdab09cda48bc2d89ac75aJust					maxContours = max(maxContours, nContours)
867842e56b97ce677b83bdab09cda48bc2d89ac75aJust				else:
877842e56b97ce677b83bdab09cda48bc2d89ac75aJust					nPoints, nContours, componentDepth = g.getCompositeMaxpValues(glyfTable)
887842e56b97ce677b83bdab09cda48bc2d89ac75aJust					maxCompositePoints = max(maxCompositePoints, nPoints)
897842e56b97ce677b83bdab09cda48bc2d89ac75aJust					maxCompositeContours = max(maxCompositeContours, nContours)
907842e56b97ce677b83bdab09cda48bc2d89ac75aJust					maxComponentElements = max(maxComponentElements, len(g.components))
917842e56b97ce677b83bdab09cda48bc2d89ac75aJust					maxComponentDepth = max(maxComponentDepth, componentDepth)
92fc99ad1513ca5443a29f1cc99df6016325e8dcbbPetr		headTable.xMin = xMin
93fc99ad1513ca5443a29f1cc99df6016325e8dcbbPetr		headTable.yMin = yMin
94fc99ad1513ca5443a29f1cc99df6016325e8dcbbPetr		headTable.xMax = xMax
95fc99ad1513ca5443a29f1cc99df6016325e8dcbbPetr		headTable.yMax = yMax
967842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.maxPoints = maxPoints
977842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.maxContours = maxContours
987842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.maxCompositePoints = maxCompositePoints
997842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.maxCompositeContours = maxCompositeContours
1007842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.maxComponentDepth = maxComponentDepth
1017842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if allXMaxIsLsb:
1027842e56b97ce677b83bdab09cda48bc2d89ac75aJust			headTable.flags = headTable.flags | 0x2
1037842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
1047842e56b97ce677b83bdab09cda48bc2d89ac75aJust			headTable.flags = headTable.flags & ~0x2
1057842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1067842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def testrepr(self):
1077842e56b97ce677b83bdab09cda48bc2d89ac75aJust		items = self.__dict__.items()
1087842e56b97ce677b83bdab09cda48bc2d89ac75aJust		items.sort()
1097842e56b97ce677b83bdab09cda48bc2d89ac75aJust		print ". . . . . . . . ."
1107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for combo in items:
1117842e56b97ce677b83bdab09cda48bc2d89ac75aJust			print "  %s: %s" % combo
1127842e56b97ce677b83bdab09cda48bc2d89ac75aJust		print ". . . . . . . . ."
1137842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1147842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def toXML(self, writer, ttFont):
115bc90c7a05b2e5114db9b0c0a6448e68d80ccf622jvr		if self.tableVersion != 0x00005000:
1167842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.comment("Most of this table will be recalculated by the compiler")
1177842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.newline()
1187842e56b97ce677b83bdab09cda48bc2d89ac75aJust		formatstring, names, fixes = sstruct.getformat(maxpFormat_0_5)
119bc90c7a05b2e5114db9b0c0a6448e68d80ccf622jvr		if self.tableVersion != 0x00005000:
1207842e56b97ce677b83bdab09cda48bc2d89ac75aJust			formatstring, names_1_0, fixes = sstruct.getformat(maxpFormat_1_0_add)
1217842e56b97ce677b83bdab09cda48bc2d89ac75aJust			names = names + names_1_0
1227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for name in names:
1237842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value = getattr(self, name)
1247842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if type(value) == type(0L):
1257842e56b97ce677b83bdab09cda48bc2d89ac75aJust				value=int(value)
1267842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if name == "tableVersion":
1277842e56b97ce677b83bdab09cda48bc2d89ac75aJust				value = hex(value)
1287842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.simpletag(name, value=value)
1297842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.newline()
1307842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1317842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def fromXML(self, (name, attrs, content), ttFont):
1327842e56b97ce677b83bdab09cda48bc2d89ac75aJust		setattr(self, name, safeEval(attrs["value"]))
1337842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1347842e56b97ce677b83bdab09cda48bc2d89ac75aJust
135