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