_h_m_t_x.py revision ca4c45681ef2ea9290c6845f8bf61dff281fc5c4
140f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Samsimport DefaultTable
240f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Samsimport Numeric
340f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Samsfrom fontTools import ttLib
440f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Samsfrom fontTools.misc.textTools import safeEval
540f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams
640f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams
740f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Samsclass table__h_m_t_x(DefaultTable.DefaultTable):
840f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams
940f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams	headerTag = 'hhea'
1040f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams	advanceName = 'width'
1140f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams	sideBearingName = 'lsb'
1240f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams	numberOfMetricsName = 'numberOfHMetrics'
1340f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams
1440f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams	def decompile(self, data, ttFont):
1540f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName))
1640f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		metrics = Numeric.fromstring(data[:4 * numberOfMetrics],
1740f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams				Numeric.Int16)
1840f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		if ttLib.endian <> "big":
1940f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			metrics = metrics.byteswapped()
2040f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		metrics.shape = (numberOfMetrics, 2)
2102d56d90e01e20db8424de94a14fe59dc94f19c0Jason Sams		data = data[4 * numberOfMetrics:]
2202d56d90e01e20db8424de94a14fe59dc94f19c0Jason Sams		numberOfSideBearings = ttFont['maxp'].numGlyphs - numberOfMetrics
2302d56d90e01e20db8424de94a14fe59dc94f19c0Jason Sams		numberOfSideBearings = int(numberOfSideBearings)
2402d56d90e01e20db8424de94a14fe59dc94f19c0Jason Sams		if numberOfSideBearings:
2502d56d90e01e20db8424de94a14fe59dc94f19c0Jason Sams			assert numberOfSideBearings > 0, "bad hmtx/vmtx table"
2640f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			lastAdvance = metrics[-1][0]
2740f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			advances = Numeric.array([lastAdvance] * numberOfSideBearings,
2840f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams					Numeric.Int16)
2940f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			sideBearings = Numeric.fromstring(data[:2 * numberOfSideBearings],
3040f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams					Numeric.Int16)
31460a04971c494fec39ffcb38e873bb8fdd82d113Tim Murray			if ttLib.endian <> "big":
3240f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams				sideBearings = sideBearings.byteswapped()
3340f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			data = data[2 * numberOfSideBearings:]
3440f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			additionalMetrics = Numeric.array([advances, sideBearings],
3540f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams					Numeric.Int16)
3640f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			metrics = Numeric.concatenate((metrics,
3740f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams					Numeric.transpose(additionalMetrics)))
3840f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		if data:
3940f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			import sys
4040f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			sys.stderr.write("too much data for hmtx/vmtx table\n")
41c11e25c4e653124def1fb18e203b894f42106cbeTim Murray		metrics = metrics.tolist()
4240f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		self.metrics = {}
4340f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		for i in range(len(metrics)):
4440f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			glyphName = ttFont.getGlyphName(i)
4540f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			self.metrics[glyphName] = metrics[i]
4640f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams
47460a04971c494fec39ffcb38e873bb8fdd82d113Tim Murray	def compile(self, ttFont):
4840f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		metrics = []
4940f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		for glyphName in ttFont.getGlyphOrder():
501e645d29250731c6e34040940c59f1033213ad3eJason Sams			metrics.append(self.metrics[glyphName])
5140f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		lastAdvance = metrics[-1][0]
5240f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		lastIndex = len(metrics)
5340f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		while metrics[lastIndex-2][0] == lastAdvance:
5440f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			lastIndex = lastIndex - 1
5540f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			if lastIndex == 0:
56c11e25c4e653124def1fb18e203b894f42106cbeTim Murray				# all advances are equal
57c11e25c4e653124def1fb18e203b894f42106cbeTim Murray				break
58c11e25c4e653124def1fb18e203b894f42106cbeTim Murray		additionalMetrics = metrics[lastIndex:]
59c11e25c4e653124def1fb18e203b894f42106cbeTim Murray		additionalMetrics = map(lambda (advance, sb): sb, additionalMetrics)
60c11e25c4e653124def1fb18e203b894f42106cbeTim Murray		metrics = metrics[:lastIndex]
61c11e25c4e653124def1fb18e203b894f42106cbeTim Murray		setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics))
62c11e25c4e653124def1fb18e203b894f42106cbeTim Murray
6340f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		metrics = Numeric.array(metrics, Numeric.Int16)
6440f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		if ttLib.endian <> "big":
6540f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			metrics = metrics.byteswapped()
6640f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		data = metrics.tostring()
6740f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams
6840f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		additionalMetrics = Numeric.array(additionalMetrics, Numeric.Int16)
6940f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		if ttLib.endian <> "big":
7040f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			additionalMetrics = additionalMetrics.byteswapped()
7140f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		data = data + additionalMetrics.tostring()
7240f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		return data
7340f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams
7440f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams	def toXML(self, writer, ttFont):
7540f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		names = self.metrics.keys()
7640f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		names.sort()
7740f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		for glyphName in names:
7840f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			advance, sb = self.metrics[glyphName]
7940f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			writer.simpletag("mtx", [
8040f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams					("name", glyphName),
8140f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams					(self.advanceName, advance),
8240f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams					(self.sideBearingName, sb),
8340f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams					])
8440f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			writer.newline()
8540f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams
8640f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams	def fromXML(self, (name, attrs, content), ttFont):
876f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray		if not hasattr(self, "metrics"):
8840f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			self.metrics = {}
8940f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams		if name == "mtx":
9040f1fa6ed699b885e3270faf88085ed78f54a2f4Jason Sams			self.metrics[attrs["name"]] = [safeEval(attrs[self.advanceName]),
916f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray					safeEval(attrs[self.sideBearingName])]
926f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray
936f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray	def __getitem__(self, glyphName):
946f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray		return self.metrics[glyphName]
956f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray
966f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray	def __setitem__(self, glyphName, (advance, sb)):
976f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray		self.metrics[glyphName] = advance, sb
986f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray
996f842ac8aa37dd855fbffdc09f5491bd85ab3c9aTim Murray