_h_m_t_x.py revision ca4c45681ef2ea9290c6845f8bf61dff281fc5c4
17842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport DefaultTable
27842e56b97ce677b83bdab09cda48bc2d89ac75aJustimport Numeric
37842e56b97ce677b83bdab09cda48bc2d89ac75aJustfrom fontTools import ttLib
47842e56b97ce677b83bdab09cda48bc2d89ac75aJustfrom fontTools.misc.textTools import safeEval
57842e56b97ce677b83bdab09cda48bc2d89ac75aJust
67842e56b97ce677b83bdab09cda48bc2d89ac75aJust
77842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass table__h_m_t_x(DefaultTable.DefaultTable):
87842e56b97ce677b83bdab09cda48bc2d89ac75aJust
97842e56b97ce677b83bdab09cda48bc2d89ac75aJust	headerTag = 'hhea'
107842e56b97ce677b83bdab09cda48bc2d89ac75aJust	advanceName = 'width'
117842e56b97ce677b83bdab09cda48bc2d89ac75aJust	sideBearingName = 'lsb'
127842e56b97ce677b83bdab09cda48bc2d89ac75aJust	numberOfMetricsName = 'numberOfHMetrics'
137842e56b97ce677b83bdab09cda48bc2d89ac75aJust
147842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def decompile(self, data, ttFont):
157842e56b97ce677b83bdab09cda48bc2d89ac75aJust		numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName))
167842e56b97ce677b83bdab09cda48bc2d89ac75aJust		metrics = Numeric.fromstring(data[:4 * numberOfMetrics],
177842e56b97ce677b83bdab09cda48bc2d89ac75aJust				Numeric.Int16)
187842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if ttLib.endian <> "big":
197842e56b97ce677b83bdab09cda48bc2d89ac75aJust			metrics = metrics.byteswapped()
207842e56b97ce677b83bdab09cda48bc2d89ac75aJust		metrics.shape = (numberOfMetrics, 2)
217842e56b97ce677b83bdab09cda48bc2d89ac75aJust		data = data[4 * numberOfMetrics:]
227842e56b97ce677b83bdab09cda48bc2d89ac75aJust		numberOfSideBearings = ttFont['maxp'].numGlyphs - numberOfMetrics
237842e56b97ce677b83bdab09cda48bc2d89ac75aJust		numberOfSideBearings = int(numberOfSideBearings)
247842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if numberOfSideBearings:
257842e56b97ce677b83bdab09cda48bc2d89ac75aJust			assert numberOfSideBearings > 0, "bad hmtx/vmtx table"
267842e56b97ce677b83bdab09cda48bc2d89ac75aJust			lastAdvance = metrics[-1][0]
277842e56b97ce677b83bdab09cda48bc2d89ac75aJust			advances = Numeric.array([lastAdvance] * numberOfSideBearings,
287842e56b97ce677b83bdab09cda48bc2d89ac75aJust					Numeric.Int16)
297842e56b97ce677b83bdab09cda48bc2d89ac75aJust			sideBearings = Numeric.fromstring(data[:2 * numberOfSideBearings],
307842e56b97ce677b83bdab09cda48bc2d89ac75aJust					Numeric.Int16)
317842e56b97ce677b83bdab09cda48bc2d89ac75aJust			if ttLib.endian <> "big":
327842e56b97ce677b83bdab09cda48bc2d89ac75aJust				sideBearings = sideBearings.byteswapped()
337842e56b97ce677b83bdab09cda48bc2d89ac75aJust			data = data[2 * numberOfSideBearings:]
347842e56b97ce677b83bdab09cda48bc2d89ac75aJust			additionalMetrics = Numeric.array([advances, sideBearings],
357842e56b97ce677b83bdab09cda48bc2d89ac75aJust					Numeric.Int16)
367842e56b97ce677b83bdab09cda48bc2d89ac75aJust			metrics = Numeric.concatenate((metrics,
377842e56b97ce677b83bdab09cda48bc2d89ac75aJust					Numeric.transpose(additionalMetrics)))
387842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if data:
39731e4377e13b91d906d78f6e1e8c7ca2097c71e8Just			import sys
40731e4377e13b91d906d78f6e1e8c7ca2097c71e8Just			sys.stderr.write("too much data for hmtx/vmtx table\n")
417842e56b97ce677b83bdab09cda48bc2d89ac75aJust		metrics = metrics.tolist()
427842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.metrics = {}
437842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for i in range(len(metrics)):
447842e56b97ce677b83bdab09cda48bc2d89ac75aJust			glyphName = ttFont.getGlyphName(i)
457842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.metrics[glyphName] = metrics[i]
467842e56b97ce677b83bdab09cda48bc2d89ac75aJust
477842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def compile(self, ttFont):
487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		metrics = []
497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for glyphName in ttFont.getGlyphOrder():
507842e56b97ce677b83bdab09cda48bc2d89ac75aJust			metrics.append(self.metrics[glyphName])
517842e56b97ce677b83bdab09cda48bc2d89ac75aJust		lastAdvance = metrics[-1][0]
527842e56b97ce677b83bdab09cda48bc2d89ac75aJust		lastIndex = len(metrics)
537842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while metrics[lastIndex-2][0] == lastAdvance:
547842e56b97ce677b83bdab09cda48bc2d89ac75aJust			lastIndex = lastIndex - 1
55ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr			if lastIndex == 0:
56ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr				# all advances are equal
57ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr				break
587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		additionalMetrics = metrics[lastIndex:]
597842e56b97ce677b83bdab09cda48bc2d89ac75aJust		additionalMetrics = map(lambda (advance, sb): sb, additionalMetrics)
607842e56b97ce677b83bdab09cda48bc2d89ac75aJust		metrics = metrics[:lastIndex]
617842e56b97ce677b83bdab09cda48bc2d89ac75aJust		setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics))
627842e56b97ce677b83bdab09cda48bc2d89ac75aJust
637842e56b97ce677b83bdab09cda48bc2d89ac75aJust		metrics = Numeric.array(metrics, Numeric.Int16)
647842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if ttLib.endian <> "big":
657842e56b97ce677b83bdab09cda48bc2d89ac75aJust			metrics = metrics.byteswapped()
667842e56b97ce677b83bdab09cda48bc2d89ac75aJust		data = metrics.tostring()
677842e56b97ce677b83bdab09cda48bc2d89ac75aJust
687842e56b97ce677b83bdab09cda48bc2d89ac75aJust		additionalMetrics = Numeric.array(additionalMetrics, Numeric.Int16)
697842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if ttLib.endian <> "big":
707842e56b97ce677b83bdab09cda48bc2d89ac75aJust			additionalMetrics = additionalMetrics.byteswapped()
717842e56b97ce677b83bdab09cda48bc2d89ac75aJust		data = data + additionalMetrics.tostring()
727842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return data
737842e56b97ce677b83bdab09cda48bc2d89ac75aJust
747842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def toXML(self, writer, ttFont):
757842e56b97ce677b83bdab09cda48bc2d89ac75aJust		names = self.metrics.keys()
767842e56b97ce677b83bdab09cda48bc2d89ac75aJust		names.sort()
777842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for glyphName in names:
787842e56b97ce677b83bdab09cda48bc2d89ac75aJust			advance, sb = self.metrics[glyphName]
797842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.simpletag("mtx", [
807842e56b97ce677b83bdab09cda48bc2d89ac75aJust					("name", glyphName),
817842e56b97ce677b83bdab09cda48bc2d89ac75aJust					(self.advanceName, advance),
827842e56b97ce677b83bdab09cda48bc2d89ac75aJust					(self.sideBearingName, sb),
837842e56b97ce677b83bdab09cda48bc2d89ac75aJust					])
847842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.newline()
857842e56b97ce677b83bdab09cda48bc2d89ac75aJust
867842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def fromXML(self, (name, attrs, content), ttFont):
877842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if not hasattr(self, "metrics"):
887842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.metrics = {}
897842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if name == "mtx":
907842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.metrics[attrs["name"]] = [safeEval(attrs[self.advanceName]),
917842e56b97ce677b83bdab09cda48bc2d89ac75aJust					safeEval(attrs[self.sideBearingName])]
927842e56b97ce677b83bdab09cda48bc2d89ac75aJust
937842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __getitem__(self, glyphName):
947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.metrics[glyphName]
957842e56b97ce677b83bdab09cda48bc2d89ac75aJust
967842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __setitem__(self, glyphName, (advance, sb)):
977842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.metrics[glyphName] = advance, sb
987842e56b97ce677b83bdab09cda48bc2d89ac75aJust
99