_h_m_t_x.py revision 30e691edd056ba22fa8970280e986747817bec3d
130e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodfrom __future__ import print_function
230e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodfrom fontTools.misc.py23 import *
330e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodfrom fontTools.misc.textTools import safeEval
42b06aaa2a6bcd363c25fb0c43f6bb906906594bdBehdad Esfahbodfrom . import DefaultTable
530e691edd056ba22fa8970280e986747817bec3dBehdad Esfahbodimport sys
6035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbodimport array
7d3d7250fc3147b6333e365e5be4ff29aa92ee506pabsimport warnings
87842e56b97ce677b83bdab09cda48bc2d89ac75aJust
97842e56b97ce677b83bdab09cda48bc2d89ac75aJust
107842e56b97ce677b83bdab09cda48bc2d89ac75aJustclass table__h_m_t_x(DefaultTable.DefaultTable):
117842e56b97ce677b83bdab09cda48bc2d89ac75aJust
127842e56b97ce677b83bdab09cda48bc2d89ac75aJust	headerTag = 'hhea'
137842e56b97ce677b83bdab09cda48bc2d89ac75aJust	advanceName = 'width'
147842e56b97ce677b83bdab09cda48bc2d89ac75aJust	sideBearingName = 'lsb'
157842e56b97ce677b83bdab09cda48bc2d89ac75aJust	numberOfMetricsName = 'numberOfHMetrics'
167842e56b97ce677b83bdab09cda48bc2d89ac75aJust
177842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def decompile(self, data, ttFont):
18035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod		numGlyphs = ttFont['maxp'].numGlyphs
197842e56b97ce677b83bdab09cda48bc2d89ac75aJust		numberOfMetrics = int(getattr(ttFont[self.headerTag], self.numberOfMetricsName))
20035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod		if numberOfMetrics > numGlyphs:
21035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod			numberOfMetrics = numGlyphs # We warn later.
22035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod		# Note: advanceWidth is unsigned, but we read/write as signed.
23035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod		metrics = array.array("h", data[:4 * numberOfMetrics])
24180ace6a5ff1399ec53bc696e8bef7cce6eef39aBehdad Esfahbod		if sys.byteorder != "big":
25035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod			metrics.byteswap()
267842e56b97ce677b83bdab09cda48bc2d89ac75aJust		data = data[4 * numberOfMetrics:]
27035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod		numberOfSideBearings = numGlyphs - numberOfMetrics
28035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod		sideBearings = array.array("h", data[:2 * numberOfSideBearings])
29035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod		data = data[2 * numberOfSideBearings:]
30035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod
31180ace6a5ff1399ec53bc696e8bef7cce6eef39aBehdad Esfahbod		if sys.byteorder != "big":
32035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod			sideBearings.byteswap()
337842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if data:
34731e4377e13b91d906d78f6e1e8c7ca2097c71e8Just			sys.stderr.write("too much data for hmtx/vmtx table\n")
357842e56b97ce677b83bdab09cda48bc2d89ac75aJust		self.metrics = {}
36035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod		for i in range(numberOfMetrics):
377842e56b97ce677b83bdab09cda48bc2d89ac75aJust			glyphName = ttFont.getGlyphName(i)
38035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod			self.metrics[glyphName] = list(metrics[i*2:i*2+2])
39035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod		lastAdvance = metrics[-2]
40035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod		for i in range(numberOfSideBearings):
41035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod			glyphName = ttFont.getGlyphName(i + numberOfMetrics)
42035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod			self.metrics[glyphName] = [lastAdvance, sideBearings[i]]
437842e56b97ce677b83bdab09cda48bc2d89ac75aJust
447842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def compile(self, ttFont):
457842e56b97ce677b83bdab09cda48bc2d89ac75aJust		metrics = []
467842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for glyphName in ttFont.getGlyphOrder():
477842e56b97ce677b83bdab09cda48bc2d89ac75aJust			metrics.append(self.metrics[glyphName])
487842e56b97ce677b83bdab09cda48bc2d89ac75aJust		lastAdvance = metrics[-1][0]
497842e56b97ce677b83bdab09cda48bc2d89ac75aJust		lastIndex = len(metrics)
507842e56b97ce677b83bdab09cda48bc2d89ac75aJust		while metrics[lastIndex-2][0] == lastAdvance:
51035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod			lastIndex -= 1
521288f8ad41b183ccdc3a8657b751ce53e03953a7jvr			if lastIndex <= 1:
53ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr				# all advances are equal
541288f8ad41b183ccdc3a8657b751ce53e03953a7jvr				lastIndex = 1
55ca4c45681ef2ea9290c6845f8bf61dff281fc5c4jvr				break
567842e56b97ce677b83bdab09cda48bc2d89ac75aJust		additionalMetrics = metrics[lastIndex:]
57035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod		additionalMetrics = [sb for advance, sb in additionalMetrics]
587842e56b97ce677b83bdab09cda48bc2d89ac75aJust		metrics = metrics[:lastIndex]
597842e56b97ce677b83bdab09cda48bc2d89ac75aJust		setattr(ttFont[self.headerTag], self.numberOfMetricsName, len(metrics))
607842e56b97ce677b83bdab09cda48bc2d89ac75aJust
614c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod		allMetrics = []
624c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod		for item in metrics:
634c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod			allMetrics.extend(item)
644c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod		allMetrics = array.array("h", allMetrics)
65180ace6a5ff1399ec53bc696e8bef7cce6eef39aBehdad Esfahbod		if sys.byteorder != "big":
664c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod			allMetrics.byteswap()
674c2f1b6a2c2e4d85d4987606795097d592b1586aBehdad Esfahbod		data = allMetrics.tostring()
687842e56b97ce677b83bdab09cda48bc2d89ac75aJust
69035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod		additionalMetrics = array.array("h", additionalMetrics)
70180ace6a5ff1399ec53bc696e8bef7cce6eef39aBehdad Esfahbod		if sys.byteorder != "big":
71035bc7da2318f0dcacecba2e1e24c0a4bf3cf80cBehdad Esfahbod			additionalMetrics.byteswap()
727842e56b97ce677b83bdab09cda48bc2d89ac75aJust		data = data + additionalMetrics.tostring()
737842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return data
747842e56b97ce677b83bdab09cda48bc2d89ac75aJust
757842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def toXML(self, writer, ttFont):
76ac1b4359467ca3deab03186a15eae1d55eb35567Behdad Esfahbod		names = sorted(self.metrics.keys())
777842e56b97ce677b83bdab09cda48bc2d89ac75aJust		for glyphName in names:
787842e56b97ce677b83bdab09cda48bc2d89ac75aJust			advance, sb = self.metrics[glyphName]
797842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.simpletag("mtx", [
807842e56b97ce677b83bdab09cda48bc2d89ac75aJust					("name", glyphName),
817842e56b97ce677b83bdab09cda48bc2d89ac75aJust					(self.advanceName, advance),
827842e56b97ce677b83bdab09cda48bc2d89ac75aJust					(self.sideBearingName, sb),
837842e56b97ce677b83bdab09cda48bc2d89ac75aJust					])
847842e56b97ce677b83bdab09cda48bc2d89ac75aJust			writer.newline()
857842e56b97ce677b83bdab09cda48bc2d89ac75aJust
863a9fd301808f5a8991ca9ac44028d1ecb22d307fBehdad Esfahbod	def fromXML(self, name, attrs, content, ttFont):
877842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if not hasattr(self, "metrics"):
887842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.metrics = {}
897842e56b97ce677b83bdab09cda48bc2d89ac75aJust		if name == "mtx":
907842e56b97ce677b83bdab09cda48bc2d89ac75aJust			self.metrics[attrs["name"]] = [safeEval(attrs[self.advanceName]),
917842e56b97ce677b83bdab09cda48bc2d89ac75aJust					safeEval(attrs[self.sideBearingName])]
927842e56b97ce677b83bdab09cda48bc2d89ac75aJust
937842e56b97ce677b83bdab09cda48bc2d89ac75aJust	def __getitem__(self, glyphName):
947842e56b97ce677b83bdab09cda48bc2d89ac75aJust		return self.metrics[glyphName]
957842e56b97ce677b83bdab09cda48bc2d89ac75aJust
963a9fd301808f5a8991ca9ac44028d1ecb22d307fBehdad Esfahbod	def __setitem__(self, glyphName, advance_sb_pair):
973a9fd301808f5a8991ca9ac44028d1ecb22d307fBehdad Esfahbod		self.metrics[glyphName] = tuple(advance_sb_pair)
987842e56b97ce677b83bdab09cda48bc2d89ac75aJust
99