_h_m_t_x.py revision 32c10eecffb4923e0721c395e4b80fb732543f18
1081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencerfrom __future__ import print_function, division
2081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencerfrom fontTools.misc.py23 import *
3081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencerfrom fontTools.misc.textTools import safeEval
4081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencerfrom . import DefaultTable
5081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencerimport sys
6081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencerimport array
7081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencerimport warnings
8081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer
9081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer
10081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencerclass table__h_m_t_x(DefaultTable.DefaultTable):
11081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer
12081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer	headerTag = 'hhea'
13081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer	advanceName = 'width'
14081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer	sideBearingName = 'lsb'
15081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer	numberOfMetricsName = 'numberOfHMetrics'
16081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer
17081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer	def decompile(self, data, ttFont):
18081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		numGlyphs = ttFont['maxp'].numGlyphs
19081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName))
20081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		if numberOfMetrics > numGlyphs:
21081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			numberOfMetrics = numGlyphs # We warn later.
22081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		# Note: advanceWidth is unsigned, but we read/write as signed.
23081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		metrics = array.array("h", data[:4 * numberOfMetrics])
24081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		if sys.byteorder != "big":
25081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			metrics.byteswap()
26081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		data = data[4 * numberOfMetrics:]
27081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		numberOfSideBearings = numGlyphs - numberOfMetrics
28081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		sideBearings = array.array("h", data[:2 * numberOfSideBearings])
29081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		data = data[2 * numberOfSideBearings:]
30081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer
31081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		if sys.byteorder != "big":
32081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			sideBearings.byteswap()
33081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		if data:
34081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			sys.stderr.write("too much data for hmtx/vmtx table\n")
35081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		self.metrics = {}
36081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		for i in range(numberOfMetrics):
37081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			glyphName = ttFont.getGlyphName(i)
38081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			self.metrics[glyphName] = list(metrics[i*2:i*2+2])
39081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		lastAdvance = metrics[-2]
40081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		for i in range(numberOfSideBearings):
41081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			glyphName = ttFont.getGlyphName(i + numberOfMetrics)
42081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			self.metrics[glyphName] = [lastAdvance, sideBearings[i]]
43081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer
44081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer	def compile(self, ttFont):
45081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		metrics = []
46081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		for glyphName in ttFont.getGlyphOrder():
47081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			metrics.append(self.metrics[glyphName])
48081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		lastAdvance = metrics[-1][0]
49081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		lastIndex = len(metrics)
50081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		while metrics[lastIndex-2][0] == lastAdvance:
51081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			lastIndex -= 1
52081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			if lastIndex <= 1:
53081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer				# all advances are equal
54081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer				lastIndex = 1
55081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer				break
56081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		additionalMetrics = metrics[lastIndex:]
57081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		additionalMetrics = [sb for advance, sb in additionalMetrics]
58081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		metrics = metrics[:lastIndex]
59081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics))
60081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer
61081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		allMetrics = []
62081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		for item in metrics:
63081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			allMetrics.extend(item)
64081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		allMetrics = array.array("h", allMetrics)
65081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		if sys.byteorder != "big":
66081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			allMetrics.byteswap()
67081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		data = allMetrics.tostring()
68081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer
69081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		additionalMetrics = array.array("h", additionalMetrics)
70081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		if sys.byteorder != "big":
71081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			additionalMetrics.byteswap()
72081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		data = data + additionalMetrics.tostring()
73081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		return data
74081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer
75081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer	def toXML(self, writer, ttFont):
76081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		names = sorted(self.metrics.keys())
77081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		for glyphName in names:
78081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			advance, sb = self.metrics[glyphName]
79081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			writer.simpletag("mtx", [
80081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer					("name", glyphName),
81081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer					(self.advanceName, advance),
82081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer					(self.sideBearingName, sb),
83081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer					])
84081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			writer.newline()
85081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer
86081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer	def fromXML(self, name, attrs, content, ttFont):
87081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		if not hasattr(self, "metrics"):
88081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			self.metrics = {}
89081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		if name == "mtx":
90081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer			self.metrics[attrs["name"]] = [safeEval(attrs[self.advanceName]),
91081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer					safeEval(attrs[self.sideBearingName])]
92081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer
93081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer	def __getitem__(self, glyphName):
94081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		return self.metrics[glyphName]
95081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer
96081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer	def __setitem__(self, glyphName, advance_sb_pair):
97081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer		self.metrics[glyphName] = tuple(advance_sb_pair)
98081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer
99081a1941b595f6294e4ce678fd61ef56a2ceb51eMichael J. Spencer