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()


[docs] class table__h_d_m_x(DefaultTable.DefaultTable):
[docs] 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"
[docs] 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
[docs] 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()
[docs] 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]