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