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