_h_m_t_x.py revision 3a9fd301808f5a8991ca9ac44028d1ecb22d307f
1ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turnerimport sys
2ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turnerfrom . import DefaultTable
3ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turnerimport array
4ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turnerfrom fontTools import ttLib
5ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turnerfrom fontTools.misc.textTools import safeEval
6ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turnerimport warnings
7ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner
8ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner
9ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turnerclass table__h_m_t_x(DefaultTable.DefaultTable):
10ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner
11ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner	headerTag = 'hhea'
12ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner	advanceName = 'width'
13ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner	sideBearingName = 'lsb'
14ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner	numberOfMetricsName = 'numberOfHMetrics'
15ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner
16ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner	def decompile(self, data, ttFont):
17ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		numGlyphs = ttFont['maxp'].numGlyphs
18ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName))
19ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		if numberOfMetrics > numGlyphs:
20ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner			numberOfMetrics = numGlyphs # We warn later.
21ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		# Note: advanceWidth is unsigned, but we read/write as signed.
22ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		metrics = array.array("h", data[:4 * numberOfMetrics])
23ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		if sys.byteorder != "big":
24ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner			metrics.byteswap()
25ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		data = data[4 * numberOfMetrics:]
26ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		numberOfSideBearings = numGlyphs - numberOfMetrics
27ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		sideBearings = array.array("h", data[:2 * numberOfSideBearings])
28ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		data = data[2 * numberOfSideBearings:]
29ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner
30ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		if sys.byteorder != "big":
31ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner			sideBearings.byteswap()
32ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		if data:
33ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner			sys.stderr.write("too much data for hmtx/vmtx table\n")
34ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		self.metrics = {}
35ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		for i in range(numberOfMetrics):
36ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner			glyphName = ttFont.getGlyphName(i)
37ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner			self.metrics[glyphName] = list(metrics[i*2:i*2+2])
38ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		lastAdvance = metrics[-2]
39ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		for i in range(numberOfSideBearings):
40ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner			glyphName = ttFont.getGlyphName(i + numberOfMetrics)
41ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner			self.metrics[glyphName] = [lastAdvance, sideBearings[i]]
42ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner
43ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner	def compile(self, ttFont):
44ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		metrics = []
45ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		for glyphName in ttFont.getGlyphOrder():
46ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner			metrics.append(self.metrics[glyphName])
47ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		lastAdvance = metrics[-1][0]
48ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		lastIndex = len(metrics)
49ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner		while metrics[lastIndex-2][0] == lastAdvance:
50ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner			lastIndex -= 1
51ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner			if lastIndex <= 1:
52ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner				# all advances are equal
53ee57375c96822790cc7f837b4fdf64a9c1d69b3aDavid 'Digit' Turner				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_pair):
97		self.metrics[glyphName] = tuple(advance_sb_pair)
98
99