1from __future__ import print_function, division, absolute_import
2from fontTools.misc.py23 import *
3from fontTools.misc import sstruct
4from . import DefaultTable
5
6hdmxHeaderFormat = """
7	>   # big endian!
8	version:	H
9	numRecords:	H
10	recordSize:	l
11"""
12
13class table__h_d_m_x(DefaultTable.DefaultTable):
14
15	def decompile(self, data, ttFont):
16		numGlyphs = ttFont['maxp'].numGlyphs
17		glyphOrder = ttFont.getGlyphOrder()
18		dummy, data = sstruct.unpack2(hdmxHeaderFormat, data, self)
19		self.hdmx = {}
20		for i in range(self.numRecords):
21			ppem = byteord(data[0])
22			maxSize = byteord(data[1])
23			widths = {}
24			for glyphID in range(numGlyphs):
25				widths[glyphOrder[glyphID]] = byteord(data[glyphID+2])
26			self.hdmx[ppem] = widths
27			data = data[self.recordSize:]
28		assert len(data) == 0, "too much hdmx data"
29
30	def compile(self, ttFont):
31		self.version = 0
32		numGlyphs = ttFont['maxp'].numGlyphs
33		glyphOrder = ttFont.getGlyphOrder()
34		self.recordSize = 4 * ((2 + numGlyphs + 3) // 4)
35		pad = (self.recordSize - 2 - numGlyphs) * b"\0"
36		self.numRecords = len(self.hdmx)
37		data = sstruct.pack(hdmxHeaderFormat, self)
38		items = sorted(self.hdmx.items())
39		for ppem, widths in items:
40			data = data + bytechr(ppem) + bytechr(max(widths.values()))
41			for glyphID in range(len(glyphOrder)):
42				width = widths[glyphOrder[glyphID]]
43				data = data + bytechr(width)
44			data = data + pad
45		return data
46
47	def toXML(self, writer, ttFont):
48		writer.begintag("hdmxData")
49		writer.newline()
50		ppems = sorted(self.hdmx.keys())
51		records = []
52		format = ""
53		for ppem in ppems:
54			widths = self.hdmx[ppem]
55			records.append(widths)
56			format = format + "%4d"
57		glyphNames = ttFont.getGlyphOrder()[:]
58		glyphNames.sort()
59		maxNameLen = max(map(len, glyphNames))
60		format = "%" + repr(maxNameLen) + 's:' + format + ' ;'
61		writer.write(format % (("ppem",) + tuple(ppems)))
62		writer.newline()
63		writer.newline()
64		for glyphName in glyphNames:
65			row = []
66			for ppem in ppems:
67				widths = self.hdmx[ppem]
68				row.append(widths[glyphName])
69			if ";" in glyphName:
70				glyphName = "\\x3b".join(glyphName.split(";"))
71			writer.write(format % ((glyphName,) + tuple(row)))
72			writer.newline()
73		writer.endtag("hdmxData")
74		writer.newline()
75
76	def fromXML(self, name, attrs, content, ttFont):
77		if name != "hdmxData":
78			return
79		content = strjoin(content)
80		lines = content.split(";")
81		topRow = lines[0].split()
82		assert topRow[0] == "ppem:", "illegal hdmx format"
83		ppems = list(map(int, topRow[1:]))
84		self.hdmx = hdmx = {}
85		for ppem in ppems:
86			hdmx[ppem] = {}
87		lines = (line.split() for line in lines[1:])
88		for line in lines:
89			if not line:
90				continue
91			assert line[0][-1] == ":", "illegal hdmx format"
92			glyphName = line[0][:-1]
93			if "\\" in glyphName:
94				from fontTools.misc.textTools import safeEval
95				glyphName = safeEval('"""' + glyphName + '"""')
96			line = list(map(int, line[1:]))
97			assert len(line) == len(ppems), "illegal hdmx format"
98			for i in range(len(ppems)):
99				hdmx[ppems[i]][glyphName] = line[i]
100
101