_m_a_x_p.py revision fc99ad1513ca5443a29f1cc99df6016325e8dcbb
17842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport DefaultTable
27842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport sstruct
37842e56b97ce677b83bdab09cda48bc2d89ac75aJustfrom fontTools.misc.textTools import safeEval
47842e56b97ce677b83bdab09cda48bc2d89ac75aJust
57842e56b97ce677b83bdab09cda48bc2d89ac75aJustmaxpFormat_0_5 = """
67842e56b97ce677b83bdab09cda48bc2d89ac75aJust		>	# big endian
77842e56b97ce677b83bdab09cda48bc2d89ac75aJust		tableVersion:			i
87842e56b97ce677b83bdab09cda48bc2d89ac75aJust		numGlyphs:				H
97842e56b97ce677b83bdab09cda48bc2d89ac75aJust"""
107842e56b97ce677b83bdab09cda48bc2d89ac75aJust
117842e56b97ce677b83bdab09cda48bc2d89ac75aJustmaxpFormat_1_0_add = """
127842e56b97ce677b83bdab09cda48bc2d89ac75aJust		>	# big endian
137842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxPoints:				H
147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxContours:			H
157842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxCompositePoints:		H
167842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxCompositeContours:	H
177842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxZones:				H
187842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxTwilightPoints:		H
197842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxStorage:				H
207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxFunctionDefs:		H
217842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxInstructionDefs:		H
227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxStackElements:		H
237842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxSizeOfInstructions:	H
247842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxComponentElements:	H
257842e56b97ce677b83bdab09cda48bc2d89ac75aJust		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)
367842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.tableVersion == 0x00010000:
377842e56b97ce677b83bdab09cda48bc2d89ac75aJust			dummy, data = sstruct.unpack2(maxpFormat_1_0_add, data, self)
387842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
397842e56b97ce677b83bdab09cda48bc2d89ac75aJust			assert self.tableVersion == 0x00005000, "unknown 'maxp' format: %x" % self.tableVersion
407842e56b97ce677b83bdab09cda48bc2d89ac75aJust		assert len(data) == 0
417842e56b97ce677b83bdab09cda48bc2d89ac75aJust
427842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def compile(self, ttFont):
437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if ttFont.has_key('glyf'):
443e097c609540944dd9290ad58df346ca86492031Just			if ttFont.isLoaded('glyf') and ttFont.recalcBBoxes:
457842e56b97ce677b83bdab09cda48bc2d89ac75aJust				self.recalc(ttFont)
467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
477842e56b97ce677b83bdab09cda48bc2d89ac75aJust			pass # XXX CFF!!!
487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		data = sstruct.pack(maxpFormat_0_5, self)
497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.tableVersion == 0x00010000:
507842e56b97ce677b83bdab09cda48bc2d89ac75aJust			data = data + sstruct.pack(maxpFormat_1_0_add, self)
517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
527842e56b97ce677b83bdab09cda48bc2d89ac75aJust			assert self.tableVersion == 0x00005000, "unknown 'maxp' format: %f" % self.tableVersion
537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return data
547842e56b97ce677b83bdab09cda48bc2d89ac75aJust
557842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def recalc(self, ttFont):
567842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""Recalculate the font bounding box, and most other maxp values except
577842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for the TT instructions values. Also recalculate the value of bit 1
58fc99ad1513ca5443a29f1cc99df6016325e8dcbbPetr		of the flags field and the font bounding box of the 'head' table.
597842e56b97ce677b83bdab09cda48bc2d89ac75aJust		"""
607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		glyfTable = ttFont['glyf']
617842e56b97ce677b83bdab09cda48bc2d89ac75aJust		hmtxTable = ttFont['hmtx']
627842e56b97ce677b83bdab09cda48bc2d89ac75aJust		headTable = ttFont['head']
637842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.numGlyphs = len(glyfTable)
647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		xMin = 100000
657842e56b97ce677b83bdab09cda48bc2d89ac75aJust		yMin = 100000
667842e56b97ce677b83bdab09cda48bc2d89ac75aJust		xMax = -100000
677842e56b97ce677b83bdab09cda48bc2d89ac75aJust		yMax = -100000
687842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxPoints = 0
697842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxContours = 0
707842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxCompositePoints = 0
717842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxCompositeContours = 0
727842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxComponentElements = 0
737842e56b97ce677b83bdab09cda48bc2d89ac75aJust		maxComponentDepth = 0
747842e56b97ce677b83bdab09cda48bc2d89ac75aJust		allXMaxIsLsb = 1
757842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for glyphName in ttFont.getGlyphOrder():
767842e56b97ce677b83bdab09cda48bc2d89ac75aJust			g = glyfTable[glyphName]
777842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if g.numberOfContours:
787842e56b97ce677b83bdab09cda48bc2d89ac75aJust				if hmtxTable[glyphName][1] <> g.xMin:
797842e56b97ce677b83bdab09cda48bc2d89ac75aJust					allXMaxIsLsb = 0
807842e56b97ce677b83bdab09cda48bc2d89ac75aJust				xMin = min(xMin, g.xMin)
817842e56b97ce677b83bdab09cda48bc2d89ac75aJust				yMin = min(yMin, g.yMin)
827842e56b97ce677b83bdab09cda48bc2d89ac75aJust				xMax = max(xMax, g.xMax)
837842e56b97ce677b83bdab09cda48bc2d89ac75aJust				yMax = max(yMax, g.yMax)
847842e56b97ce677b83bdab09cda48bc2d89ac75aJust				if g.numberOfContours > 0:
857842e56b97ce677b83bdab09cda48bc2d89ac75aJust					nPoints, nContours = g.getMaxpValues()
867842e56b97ce677b83bdab09cda48bc2d89ac75aJust					maxPoints = max(maxPoints, nPoints)
877842e56b97ce677b83bdab09cda48bc2d89ac75aJust					maxContours = max(maxContours, nContours)
887842e56b97ce677b83bdab09cda48bc2d89ac75aJust				else:
897842e56b97ce677b83bdab09cda48bc2d89ac75aJust					nPoints, nContours, componentDepth = g.getCompositeMaxpValues(glyfTable)
907842e56b97ce677b83bdab09cda48bc2d89ac75aJust					maxCompositePoints = max(maxCompositePoints, nPoints)
917842e56b97ce677b83bdab09cda48bc2d89ac75aJust					maxCompositeContours = max(maxCompositeContours, nContours)
927842e56b97ce677b83bdab09cda48bc2d89ac75aJust					maxComponentElements = max(maxComponentElements, len(g.components))
937842e56b97ce677b83bdab09cda48bc2d89ac75aJust					maxComponentDepth = max(maxComponentDepth, componentDepth)
94fc99ad1513ca5443a29f1cc99df6016325e8dcbbPetr		headTable.xMin = xMin
95fc99ad1513ca5443a29f1cc99df6016325e8dcbbPetr		headTable.yMin = yMin
96fc99ad1513ca5443a29f1cc99df6016325e8dcbbPetr		headTable.xMax = xMax
97fc99ad1513ca5443a29f1cc99df6016325e8dcbbPetr		headTable.yMax = yMax
987842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.maxPoints = maxPoints
997842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.maxContours = maxContours
1007842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.maxCompositePoints = maxCompositePoints
1017842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.maxCompositeContours = maxCompositeContours
1027842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.maxComponentDepth = maxComponentDepth
1037842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if allXMaxIsLsb:
1047842e56b97ce677b83bdab09cda48bc2d89ac75aJust			headTable.flags = headTable.flags | 0x2
1057842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
1067842e56b97ce677b83bdab09cda48bc2d89ac75aJust			headTable.flags = headTable.flags & ~0x2
1077842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1087842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def testrepr(self):
1097842e56b97ce677b83bdab09cda48bc2d89ac75aJust		items = self.__dict__.items()
1107842e56b97ce677b83bdab09cda48bc2d89ac75aJust		items.sort()
1117842e56b97ce677b83bdab09cda48bc2d89ac75aJust		print ". . . . . . . . ."
1127842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for combo in items:
1137842e56b97ce677b83bdab09cda48bc2d89ac75aJust			print "  %s: %s" % combo
1147842e56b97ce677b83bdab09cda48bc2d89ac75aJust		print ". . . . . . . . ."
1157842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1167842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def toXML(self, writer, ttFont):
1177842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.tableVersion <> 0x00005000:
1187842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.comment("Most of this table will be recalculated by the compiler")
1197842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.newline()
1207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		formatstring, names, fixes = sstruct.getformat(maxpFormat_0_5)
1217842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if self.tableVersion == 0x00010000:
1227842e56b97ce677b83bdab09cda48bc2d89ac75aJust			formatstring, names_1_0, fixes = sstruct.getformat(maxpFormat_1_0_add)
1237842e56b97ce677b83bdab09cda48bc2d89ac75aJust			names = names + names_1_0
1247842e56b97ce677b83bdab09cda48bc2d89ac75aJust		else:
1257842e56b97ce677b83bdab09cda48bc2d89ac75aJust			assert self.tableVersion == 0x00005000, "unknown 'maxp' format: %f" % self.tableVersion
1267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for name in names:
1277842e56b97ce677b83bdab09cda48bc2d89ac75aJust			value = getattr(self, name)
1287842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if type(value) == type(0L):
1297842e56b97ce677b83bdab09cda48bc2d89ac75aJust				value=int(value)
1307842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if name == "tableVersion":
1317842e56b97ce677b83bdab09cda48bc2d89ac75aJust				value = hex(value)
1327842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.simpletag(name, value=value)
1337842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.newline()
1347842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1357842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def fromXML(self, (name, attrs, content), ttFont):
1367842e56b97ce677b83bdab09cda48bc2d89ac75aJust		setattr(self, name, safeEval(attrs["value"]))
1377842e56b97ce677b83bdab09cda48bc2d89ac75aJust
1387842e56b97ce677b83bdab09cda48bc2d89ac75aJust
139