_h_m_t_x.py revision ca4c45681ef2ea9290c6845f8bf61dff281fc5c4
1import DefaultTable
2import Numeric
3from fontTools import ttLib
4from fontTools.misc.textTools import safeEval
5
6
7class table__h_m_t_x(DefaultTable.DefaultTable):
8
9	headerTag = 'hhea'
10	advanceName = 'width'
11	sideBearingName = 'lsb'
12	numberOfMetricsName = 'numberOfHMetrics'
13
14	def decompile(self, data, ttFont):
15		numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName))
16		metrics = Numeric.fromstring(data[:4 * numberOfMetrics],
17				Numeric.Int16)
18		if ttLib.endian <> "big":
19			metrics = metrics.byteswapped()
20		metrics.shape = (numberOfMetrics, 2)
21		data = data[4 * numberOfMetrics:]
22		numberOfSideBearings = ttFont['maxp'].numGlyphs - numberOfMetrics
23		numberOfSideBearings = int(numberOfSideBearings)
24		if numberOfSideBearings:
25			assert numberOfSideBearings > 0, "bad hmtx/vmtx table"
26			lastAdvance = metrics[-1][0]
27			advances = Numeric.array([lastAdvance] * numberOfSideBearings,
28					Numeric.Int16)
29			sideBearings = Numeric.fromstring(data[:2 * numberOfSideBearings],
30					Numeric.Int16)
31			if ttLib.endian <> "big":
32				sideBearings = sideBearings.byteswapped()
33			data = data[2 * numberOfSideBearings:]
34			additionalMetrics = Numeric.array([advances, sideBearings],
35					Numeric.Int16)
36			metrics = Numeric.concatenate((metrics,
37					Numeric.transpose(additionalMetrics)))
38		if data:
39			import sys
40			sys.stderr.write("too much data for hmtx/vmtx table\n")
41		metrics = metrics.tolist()
42		self.metrics = {}
43		for i in range(len(metrics)):
44			glyphName = ttFont.getGlyphName(i)
45			self.metrics[glyphName] = metrics[i]
46
47	def compile(self, ttFont):
48		metrics = []
49		for glyphName in ttFont.getGlyphOrder():
50			metrics.append(self.metrics[glyphName])
51		lastAdvance = metrics[-1][0]
52		lastIndex = len(metrics)
53		while metrics[lastIndex-2][0] == lastAdvance:
54			lastIndex = lastIndex - 1
55			if lastIndex == 0:
56				# all advances are equal
57				break
58		additionalMetrics = metrics[lastIndex:]
59		additionalMetrics = map(lambda (advance, sb): sb, additionalMetrics)
60		metrics = metrics[:lastIndex]
61		setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics))
62
63		metrics = Numeric.array(metrics, Numeric.Int16)
64		if ttLib.endian <> "big":
65			metrics = metrics.byteswapped()
66		data = metrics.tostring()
67
68		additionalMetrics = Numeric.array(additionalMetrics, Numeric.Int16)
69		if ttLib.endian <> "big":
70			additionalMetrics = additionalMetrics.byteswapped()
71		data = data + additionalMetrics.tostring()
72		return data
73
74	def toXML(self, writer, ttFont):
75		names = self.metrics.keys()
76		names.sort()
77		for glyphName in names:
78			advance, sb = self.metrics[glyphName]
79			writer.simpletag("mtx", [
80					("name", glyphName),
81					(self.advanceName, advance),
82					(self.sideBearingName, sb),
83					])
84			writer.newline()
85
86	def fromXML(self, (name, attrs, content), ttFont):
87		if not hasattr(self, "metrics"):
88			self.metrics = {}
89		if name == "mtx":
90			self.metrics[attrs["name"]] = [safeEval(attrs[self.advanceName]),
91					safeEval(attrs[self.sideBearingName])]
92
93	def __getitem__(self, glyphName):
94		return self.metrics[glyphName]
95
96	def __setitem__(self, glyphName, (advance, sb)):
97		self.metrics[glyphName] = advance, sb
98
99