_h_m_t_x.py revision 4c2f1b6a2c2e4d85d4987606795097d592b1586a
1import sys
2import DefaultTable
3import array
4from fontTools import ttLib
5from fontTools.misc.textTools import safeEval
6import warnings
7
8
9class table__h_m_t_x(DefaultTable.DefaultTable):
10
11	headerTag = 'hhea'
12	advanceName = 'width'
13	sideBearingName = 'lsb'
14	numberOfMetricsName = 'numberOfHMetrics'
15
16	def decompile(self, data, ttFont):
17		numGlyphs = ttFont['maxp'].numGlyphs
18		numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName))
19		if numberOfMetrics > numGlyphs:
20			numberOfMetrics = numGlyphs # We warn later.
21		# Note: advanceWidth is unsigned, but we read/write as signed.
22		metrics = array.array("h", data[:4 * numberOfMetrics])
23		if sys.byteorder <> "big":
24			metrics.byteswap()
25		data = data[4 * numberOfMetrics:]
26		numberOfSideBearings = numGlyphs - numberOfMetrics
27		sideBearings = array.array("h", data[:2 * numberOfSideBearings])
28		data = data[2 * numberOfSideBearings:]
29
30		if sys.byteorder <> "big":
31			sideBearings.byteswap()
32		if data:
33			sys.stderr.write("too much data for hmtx/vmtx table\n")
34		self.metrics = {}
35		for i in range(numberOfMetrics):
36			glyphName = ttFont.getGlyphName(i)
37			self.metrics[glyphName] = list(metrics[i*2:i*2+2])
38		lastAdvance = metrics[-2]
39		for i in range(numberOfSideBearings):
40			glyphName = ttFont.getGlyphName(i + numberOfMetrics)
41			self.metrics[glyphName] = [lastAdvance, sideBearings[i]]
42
43	def compile(self, ttFont):
44		metrics = []
45		for glyphName in ttFont.getGlyphOrder():
46			metrics.append(self.metrics[glyphName])
47		lastAdvance = metrics[-1][0]
48		lastIndex = len(metrics)
49		while metrics[lastIndex-2][0] == lastAdvance:
50			lastIndex -= 1
51			if lastIndex <= 1:
52				# all advances are equal
53				lastIndex = 1
54				break
55		additionalMetrics = metrics[lastIndex:]
56		additionalMetrics = [sb for advance, sb in additionalMetrics]
57		metrics = metrics[:lastIndex]
58		setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics))
59
60		allMetrics = []
61		for item in metrics:
62			allMetrics.extend(item)
63		allMetrics = array.array("h", allMetrics)
64		if sys.byteorder <> "big":
65			allMetrics.byteswap()
66		data = allMetrics.tostring()
67
68		additionalMetrics = array.array("h", additionalMetrics)
69		if sys.byteorder <> "big":
70			additionalMetrics.byteswap()
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