Behdad Esfahbod | 1ae2959 | 2014-01-14 15:07:50 +0800 | [diff] [blame] | 1 | from __future__ import print_function, division, absolute_import |
Behdad Esfahbod | 30e691e | 2013-11-27 17:27:45 -0500 | [diff] [blame] | 2 | from fontTools.misc.py23 import * |
| 3 | from fontTools.misc.textTools import safeEval |
Behdad Esfahbod | 2b06aaa | 2013-11-27 02:34:11 -0500 | [diff] [blame] | 4 | from . import DefaultTable |
Behdad Esfahbod | 7ed91ec | 2013-11-27 15:16:28 -0500 | [diff] [blame] | 5 | import operator |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 6 | import struct |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 7 | |
| 8 | |
| 9 | class table_V_O_R_G_(DefaultTable.DefaultTable): |
| 10 | |
| 11 | """ This table is structured so that you can treat it like a dictionary keyed by glyph name. |
| 12 | ttFont['VORG'][<glyphName>] will return the vertical origin for any glyph |
| 13 | ttFont['VORG'][<glyphName>] = <value> will set the vertical origin for any glyph. |
| 14 | """ |
| 15 | |
| 16 | def decompile(self, data, ttFont): |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 17 | self.getGlyphName = ttFont.getGlyphName # for use in get/set item functions, for access by GID |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 18 | self.majorVersion, self.minorVersion, self.defaultVertOriginY, self.numVertOriginYMetrics = struct.unpack(">HHhH", data[:8]) |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 19 | assert (self.majorVersion <= 1), "Major version of VORG table is higher than I know how to handle" |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 20 | data = data[8:] |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 21 | vids = [] |
| 22 | gids = [] |
| 23 | pos = 0 |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 24 | for i in range(self.numVertOriginYMetrics): |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 25 | gid, vOrigin = struct.unpack(">Hh", data[pos:pos+4]) |
| 26 | pos += 4 |
| 27 | gids.append(gid) |
| 28 | vids.append(vOrigin) |
| 29 | |
| 30 | self.VOriginRecords = vOrig = {} |
| 31 | glyphOrder = ttFont.getGlyphOrder() |
| 32 | try: |
Behdad Esfahbod | e5ca796 | 2013-11-27 04:38:16 -0500 | [diff] [blame] | 33 | names = map(operator.getitem, [glyphOrder]*self.numVertOriginYMetrics, gids) |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 34 | except IndexError: |
| 35 | getGlyphName = self.getGlyphName |
| 36 | names = map(getGlyphName, gids ) |
| 37 | |
Behdad Esfahbod | e5ca796 | 2013-11-27 04:38:16 -0500 | [diff] [blame] | 38 | list(map(operator.setitem, [vOrig]*self.numVertOriginYMetrics, names, vids)) |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 39 | |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 40 | |
| 41 | def compile(self, ttFont): |
Behdad Esfahbod | c2297cd | 2013-11-27 06:26:55 -0500 | [diff] [blame] | 42 | vorgs = list(self.VOriginRecords.values()) |
| 43 | names = list(self.VOriginRecords.keys()) |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 44 | nameMap = ttFont.getReverseGlyphMap() |
| 45 | lenRecords = len(vorgs) |
| 46 | try: |
| 47 | gids = map(operator.getitem, [nameMap]*lenRecords, names) |
| 48 | except KeyError: |
Behdad Esfahbod | dc87372 | 2013-12-04 21:28:50 -0500 | [diff] [blame] | 49 | nameMap = ttFont.getReverseGlyphMap(rebuild=True) |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 50 | gids = map(operator.getitem, [nameMap]*lenRecords, names) |
Behdad Esfahbod | e5ca796 | 2013-11-27 04:38:16 -0500 | [diff] [blame] | 51 | vOriginTable = list(zip(gids, vorgs)) |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 52 | self.numVertOriginYMetrics = lenRecords |
| 53 | vOriginTable.sort() # must be in ascending GID order |
| 54 | dataList = [ struct.pack(">Hh", rec[0], rec[1]) for rec in vOriginTable] |
| 55 | header = struct.pack(">HHhH", self.majorVersion, self.minorVersion, self.defaultVertOriginY, self.numVertOriginYMetrics) |
| 56 | dataList.insert(0, header) |
Behdad Esfahbod | 18316aa | 2013-11-27 21:17:35 -0500 | [diff] [blame] | 57 | data = bytesjoin(dataList) |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 58 | return data |
| 59 | |
| 60 | def toXML(self, writer, ttFont): |
| 61 | writer.simpletag("majorVersion", value=self.majorVersion) |
| 62 | writer.newline() |
| 63 | writer.simpletag("minorVersion", value=self.minorVersion) |
| 64 | writer.newline() |
| 65 | writer.simpletag("defaultVertOriginY", value=self.defaultVertOriginY) |
| 66 | writer.newline() |
| 67 | writer.simpletag("numVertOriginYMetrics", value=self.numVertOriginYMetrics) |
| 68 | writer.newline() |
| 69 | vOriginTable = [] |
| 70 | glyphNames = self.VOriginRecords.keys() |
| 71 | for glyphName in glyphNames: |
| 72 | try: |
| 73 | gid = ttFont.getGlyphID(glyphName) |
| 74 | except: |
| 75 | assert 0, "VORG table contains a glyph name not in ttFont.getGlyphNames(): " + str(glyphName) |
| 76 | vOriginTable.append([gid, glyphName, self.VOriginRecords[glyphName]]) |
| 77 | vOriginTable.sort() |
| 78 | for entry in vOriginTable: |
| 79 | vOriginRec = VOriginRecord(entry[1], entry[2]) |
| 80 | vOriginRec.toXML(writer, ttFont) |
| 81 | |
Behdad Esfahbod | 3a9fd30 | 2013-11-27 03:19:32 -0500 | [diff] [blame] | 82 | def fromXML(self, name, attrs, content, ttFont): |
jvr | cd75d57 | 2008-03-09 08:58:36 +0000 | [diff] [blame] | 83 | if not hasattr(self, "VOriginRecords"): |
| 84 | self.VOriginRecords = {} |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 85 | self.getGlyphName = ttFont.getGlyphName # for use in get/set item functions, for access by GID |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 86 | if name == "VOriginRecord": |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 87 | vOriginRec = VOriginRecord() |
| 88 | for element in content: |
Behdad Esfahbod | faaca76 | 2013-11-27 23:37:57 -0500 | [diff] [blame] | 89 | if isinstance(element, basestring): |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 90 | continue |
Behdad Esfahbod | 3a9fd30 | 2013-11-27 03:19:32 -0500 | [diff] [blame] | 91 | name, attrs, content = element |
| 92 | vOriginRec.fromXML(name, attrs, content, ttFont) |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 93 | self.VOriginRecords[vOriginRec.glyphName] = vOriginRec.vOrigin |
Behdad Esfahbod | bc5e1cb | 2013-11-27 02:33:03 -0500 | [diff] [blame] | 94 | elif "value" in attrs: |
Behdad Esfahbod | 7cc6d27 | 2013-11-27 04:00:15 -0500 | [diff] [blame] | 95 | setattr(self, name, safeEval(attrs["value"])) |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 96 | |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 97 | |
| 98 | def __getitem__(self, glyphSelector): |
Behdad Esfahbod | b774f9f | 2013-11-27 05:17:37 -0500 | [diff] [blame] | 99 | if isinstance(glyphSelector, int): |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 100 | # its a gid, convert to glyph name |
| 101 | glyphSelector = self.getGlyphName(glyphSelector) |
| 102 | |
Behdad Esfahbod | bc5e1cb | 2013-11-27 02:33:03 -0500 | [diff] [blame] | 103 | if glyphSelector not in self.VOriginRecords: |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 104 | return self.defaultVertOriginY |
| 105 | |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 106 | return self.VOriginRecords[glyphSelector] |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 107 | |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 108 | def __setitem__(self, glyphSelector, value): |
Behdad Esfahbod | b774f9f | 2013-11-27 05:17:37 -0500 | [diff] [blame] | 109 | if isinstance(glyphSelector, int): |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 110 | # its a gid, convert to glyph name |
| 111 | glyphSelector = self.getGlyphName(glyphSelector) |
| 112 | |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 113 | if value != self.defaultVertOriginY: |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 114 | self.VOriginRecords[glyphSelector] = value |
Behdad Esfahbod | bc5e1cb | 2013-11-27 02:33:03 -0500 | [diff] [blame] | 115 | elif glyphSelector in self.VOriginRecords: |
jvr | bc6e55b | 2006-10-21 13:29:47 +0000 | [diff] [blame] | 116 | del self.VOriginRecords[glyphSelector] |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 117 | |
Behdad Esfahbod | 487b15f | 2014-05-14 13:51:10 -0600 | [diff] [blame^] | 118 | def __delitem__(self, glyphSelector): |
| 119 | del self.VOriginRecords[glyphSelector] |
| 120 | |
Behdad Esfahbod | e388db5 | 2013-11-28 14:26:58 -0500 | [diff] [blame] | 121 | class VOriginRecord(object): |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 122 | |
| 123 | def __init__(self, name = None, vOrigin = None): |
| 124 | self.glyphName = name |
| 125 | self.vOrigin = vOrigin |
| 126 | |
| 127 | def toXML(self, writer, ttFont): |
| 128 | writer.begintag("VOriginRecord") |
| 129 | writer.newline() |
| 130 | writer.simpletag("glyphName", value=self.glyphName) |
| 131 | writer.newline() |
| 132 | writer.simpletag("vOrigin", value=self.vOrigin) |
| 133 | writer.newline() |
| 134 | writer.endtag("VOriginRecord") |
| 135 | writer.newline() |
| 136 | |
Behdad Esfahbod | 3a9fd30 | 2013-11-27 03:19:32 -0500 | [diff] [blame] | 137 | def fromXML(self, name, attrs, content, ttFont): |
jvr | aa2723c | 2003-08-22 20:02:25 +0000 | [diff] [blame] | 138 | value = attrs["value"] |
| 139 | if name == "glyphName": |
| 140 | setattr(self, name, value) |
| 141 | else: |
Behdad Esfahbod | 7cc6d27 | 2013-11-27 04:00:15 -0500 | [diff] [blame] | 142 | setattr(self, name, safeEval(value)) |