# Source code for fontTools.ttLib.tables._h_d_m_x

    from fontTools.misc import sstruct
    from fontTools.misc.textTools import bytechr, byteord, strjoin
    from . import DefaultTable
    import array
    from collections.abc import Mapping

    hdmxHeaderFormat = """
    	>   # big endian!
    	version:	H
    	numRecords:	H
    	recordSize:	l
    """

    class _GlyphnamedList(Mapping):

    	def __init__(self, reverseGlyphOrder, data):
    		self._array = data
    		self._map = dict(reverseGlyphOrder)

    	def __getitem__(self, k):
    		return self._array[self._map[k]]

    	def __len__(self):
    		return len(self._map)

    	def __iter__(self):
    		return iter(self._map)

    	def keys(self):
    		return self._map.keys()

    class table__h_d_m_x(DefaultTable.DefaultTable):

    	def decompile(self, data, ttFont):
    		numGlyphs = ttFont['maxp'].numGlyphs
    		glyphOrder = ttFont.getGlyphOrder()
    		dummy, data = sstruct.unpack2(hdmxHeaderFormat, data, self)
    		self.hdmx = {}
    		for i in range(self.numRecords):
    			ppem = byteord(data[0])
    			maxSize = byteord(data[1])
    			widths = _GlyphnamedList(ttFont.getReverseGlyphMap(), array.array("B", data[2:2+numGlyphs]))
    			self.hdmx[ppem] = widths
    			data = data[self.recordSize:]
    		assert len(data) == 0, "too much hdmx data"

    	def compile(self, ttFont):
    		self.version = 0
    		numGlyphs = ttFont['maxp'].numGlyphs
    		glyphOrder = ttFont.getGlyphOrder()
    		self.recordSize = 4 * ((2 + numGlyphs + 3) // 4)
    		pad = (self.recordSize - 2 - numGlyphs) * b"\0"
    		self.numRecords = len(self.hdmx)
    		data = sstruct.pack(hdmxHeaderFormat, self)
    		items = sorted(self.hdmx.items())
    		for ppem, widths in items:
    			data = data + bytechr(ppem) + bytechr(max(widths.values()))
    			for glyphID in range(len(glyphOrder)):
    				width = widths[glyphOrder[glyphID]]
    				data = data + bytechr(width)
    			data = data + pad
    		return data

    	def toXML(self, writer, ttFont):
    		writer.begintag("hdmxData")
    		writer.newline()
    		ppems = sorted(self.hdmx.keys())
    		records = []
    		format = ""
    		for ppem in ppems:
    			widths = self.hdmx[ppem]
    			records.append(widths)
    			format = format + "%4d"
    		glyphNames = ttFont.getGlyphOrder()[:]
    		glyphNames.sort()
    		maxNameLen = max(map(len, glyphNames))
    		format = "%" + repr(maxNameLen) + 's:' + format + ' ;'
    		writer.write(format % (("ppem",) + tuple(ppems)))
    		writer.newline()
    		writer.newline()
    		for glyphName in glyphNames:
    			row = []
    			for ppem in ppems:
    				widths = self.hdmx[ppem]
    				row.append(widths[glyphName])
    			if ";" in glyphName:
    				glyphName = "\\x3b".join(glyphName.split(";"))
    			writer.write(format % ((glyphName,) + tuple(row)))
    			writer.newline()
    		writer.endtag("hdmxData")
    		writer.newline()

    	def fromXML(self, name, attrs, content, ttFont):
    		if name != "hdmxData":
    			return
    		content = strjoin(content)
    		lines = content.split(";")
    		topRow = lines[0].split()
    		assert topRow[0] == "ppem:", "illegal hdmx format"
    		ppems = list(map(int, topRow[1:]))
    		self.hdmx = hdmx = {}
    		for ppem in ppems:
    			hdmx[ppem] = {}
    		lines = (line.split() for line in lines[1:])
    		for line in lines:
    			if not line:
    				continue
    			assert line[0][-1] == ":", "illegal hdmx format"
    			glyphName = line[0][:-1]
    			if "\\" in glyphName:
    				from fontTools.misc.textTools import safeEval
    				glyphName = safeEval('"""' + glyphName + '"""')
    			line = list(map(int, line[1:]))
    			assert len(line) == len(ppems), "illegal hdmx format"
    			for i in range(len(ppems)):
    				hdmx[ppems[i]][glyphName] = line[i]