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