Behdad Esfahbod | 1ae2959 | 2014-01-14 15:07:50 +0800 | [diff] [blame^] | 1 | from __future__ import print_function, division, absolute_import |
Behdad Esfahbod | 7ed91ec | 2013-11-27 15:16:28 -0500 | [diff] [blame] | 2 | from fontTools.misc.py23 import * |
Behdad Esfahbod | 30e691e | 2013-11-27 17:27:45 -0500 | [diff] [blame] | 3 | from fontTools.misc import sstruct |
| 4 | from . import DefaultTable |
Just | 7842e56 | 1999-12-16 21:34:53 +0000 | [diff] [blame] | 5 | |
| 6 | hdmxHeaderFormat = """ |
Just | fd5a932 | 1999-12-23 12:32:30 +0000 | [diff] [blame] | 7 | > # big endian! |
Just | 7842e56 | 1999-12-16 21:34:53 +0000 | [diff] [blame] | 8 | version: H |
| 9 | numRecords: H |
| 10 | recordSize: l |
| 11 | """ |
| 12 | |
| 13 | class 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): |
Behdad Esfahbod | 319c5fd | 2013-11-27 18:13:48 -0500 | [diff] [blame] | 21 | ppem = byteord(data[0]) |
| 22 | maxSize = byteord(data[1]) |
Just | 7842e56 | 1999-12-16 21:34:53 +0000 | [diff] [blame] | 23 | widths = {} |
| 24 | for glyphID in range(numGlyphs): |
Behdad Esfahbod | 319c5fd | 2013-11-27 18:13:48 -0500 | [diff] [blame] | 25 | widths[glyphOrder[glyphID]] = byteord(data[glyphID+2]) |
Just | 7842e56 | 1999-12-16 21:34:53 +0000 | [diff] [blame] | 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() |
Behdad Esfahbod | 32c10ee | 2013-11-27 17:46:17 -0500 | [diff] [blame] | 34 | self.recordSize = 4 * ((2 + numGlyphs + 3) // 4) |
Behdad Esfahbod | 18316aa | 2013-11-27 21:17:35 -0500 | [diff] [blame] | 35 | pad = (self.recordSize - 2 - numGlyphs) * b"\0" |
Just | 7842e56 | 1999-12-16 21:34:53 +0000 | [diff] [blame] | 36 | self.numRecords = len(self.hdmx) |
| 37 | data = sstruct.pack(hdmxHeaderFormat, self) |
Behdad Esfahbod | ac1b435 | 2013-11-27 04:15:34 -0500 | [diff] [blame] | 38 | items = sorted(self.hdmx.items()) |
Just | 7842e56 | 1999-12-16 21:34:53 +0000 | [diff] [blame] | 39 | for ppem, widths in items: |
Behdad Esfahbod | b7a2d79 | 2013-11-27 15:19:40 -0500 | [diff] [blame] | 40 | data = data + bytechr(ppem) + bytechr(max(widths.values())) |
Just | 7842e56 | 1999-12-16 21:34:53 +0000 | [diff] [blame] | 41 | for glyphID in range(len(glyphOrder)): |
| 42 | width = widths[glyphOrder[glyphID]] |
Behdad Esfahbod | b7a2d79 | 2013-11-27 15:19:40 -0500 | [diff] [blame] | 43 | data = data + bytechr(width) |
Just | 7842e56 | 1999-12-16 21:34:53 +0000 | [diff] [blame] | 44 | data = data + pad |
| 45 | return data |
| 46 | |
| 47 | def toXML(self, writer, ttFont): |
| 48 | writer.begintag("hdmxData") |
| 49 | writer.newline() |
Behdad Esfahbod | ac1b435 | 2013-11-27 04:15:34 -0500 | [diff] [blame] | 50 | ppems = sorted(self.hdmx.keys()) |
Just | 7842e56 | 1999-12-16 21:34:53 +0000 | [diff] [blame] | 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)) |
Behdad Esfahbod | dc7e6f3 | 2013-11-27 02:44:56 -0500 | [diff] [blame] | 60 | format = "%" + repr(maxNameLen) + 's:' + format + ' ;' |
Just | 7842e56 | 1999-12-16 21:34:53 +0000 | [diff] [blame] | 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]) |
jvr | 1872557 | 2002-05-24 17:42:04 +0000 | [diff] [blame] | 69 | if ";" in glyphName: |
| 70 | glyphName = "\\x3b".join(glyphName.split(";")) |
Just | 7842e56 | 1999-12-16 21:34:53 +0000 | [diff] [blame] | 71 | writer.write(format % ((glyphName,) + tuple(row))) |
| 72 | writer.newline() |
| 73 | writer.endtag("hdmxData") |
| 74 | writer.newline() |
| 75 | |
Behdad Esfahbod | 3a9fd30 | 2013-11-27 03:19:32 -0500 | [diff] [blame] | 76 | def fromXML(self, name, attrs, content, ttFont): |
Behdad Esfahbod | 180ace6 | 2013-11-27 02:40:30 -0500 | [diff] [blame] | 77 | if name != "hdmxData": |
Just | 7842e56 | 1999-12-16 21:34:53 +0000 | [diff] [blame] | 78 | return |
Behdad Esfahbod | 18316aa | 2013-11-27 21:17:35 -0500 | [diff] [blame] | 79 | content = strjoin(content) |
Behdad Esfahbod | 14fb031 | 2013-11-27 05:47:34 -0500 | [diff] [blame] | 80 | lines = content.split(";") |
| 81 | topRow = lines[0].split() |
Just | 7842e56 | 1999-12-16 21:34:53 +0000 | [diff] [blame] | 82 | assert topRow[0] == "ppem:", "illegal hdmx format" |
Behdad Esfahbod | e5ca796 | 2013-11-27 04:38:16 -0500 | [diff] [blame] | 83 | ppems = list(map(int, topRow[1:])) |
Just | 7842e56 | 1999-12-16 21:34:53 +0000 | [diff] [blame] | 84 | self.hdmx = hdmx = {} |
| 85 | for ppem in ppems: |
| 86 | hdmx[ppem] = {} |
Behdad Esfahbod | 14fb031 | 2013-11-27 05:47:34 -0500 | [diff] [blame] | 87 | lines = (line.split() for line in lines[1:]) |
Just | 7842e56 | 1999-12-16 21:34:53 +0000 | [diff] [blame] | 88 | for line in lines: |
| 89 | if not line: |
| 90 | continue |
| 91 | assert line[0][-1] == ":", "illegal hdmx format" |
| 92 | glyphName = line[0][:-1] |
jvr | 1872557 | 2002-05-24 17:42:04 +0000 | [diff] [blame] | 93 | if "\\" in glyphName: |
| 94 | from fontTools.misc.textTools import safeEval |
| 95 | glyphName = safeEval('"""' + glyphName + '"""') |
Behdad Esfahbod | e5ca796 | 2013-11-27 04:38:16 -0500 | [diff] [blame] | 96 | line = list(map(int, line[1:])) |
Just | 7842e56 | 1999-12-16 21:34:53 +0000 | [diff] [blame] | 97 | assert len(line) == len(ppems), "illegal hdmx format" |
| 98 | for i in range(len(ppems)): |
| 99 | hdmx[ppems[i]][glyphName] = line[i] |
| 100 | |