blob: 19f25b50e350ef8a6a6430bc30ece899f223c1ce [file] [log] [blame]
Behdad Esfahbod1ae29592014-01-14 15:07:50 +08001from __future__ import print_function, division, absolute_import
Behdad Esfahbod30e691e2013-11-27 17:27:45 -05002from fontTools.misc.py23 import *
3from fontTools.misc.textTools import safeEval
Behdad Esfahbod2b06aaa2013-11-27 02:34:11 -05004from . import DefaultTable
Behdad Esfahbod7ed91ec2013-11-27 15:16:28 -05005import operator
jvraa2723c2003-08-22 20:02:25 +00006import struct
jvraa2723c2003-08-22 20:02:25 +00007
8
9class 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):
jvrbc6e55b2006-10-21 13:29:47 +000017 self.getGlyphName = ttFont.getGlyphName # for use in get/set item functions, for access by GID
jvraa2723c2003-08-22 20:02:25 +000018 self.majorVersion, self.minorVersion, self.defaultVertOriginY, self.numVertOriginYMetrics = struct.unpack(">HHhH", data[:8])
jvrbc6e55b2006-10-21 13:29:47 +000019 assert (self.majorVersion <= 1), "Major version of VORG table is higher than I know how to handle"
jvraa2723c2003-08-22 20:02:25 +000020 data = data[8:]
jvrbc6e55b2006-10-21 13:29:47 +000021 vids = []
22 gids = []
23 pos = 0
jvraa2723c2003-08-22 20:02:25 +000024 for i in range(self.numVertOriginYMetrics):
jvrbc6e55b2006-10-21 13:29:47 +000025 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 Esfahbode5ca7962013-11-27 04:38:16 -050033 names = map(operator.getitem, [glyphOrder]*self.numVertOriginYMetrics, gids)
jvrbc6e55b2006-10-21 13:29:47 +000034 except IndexError:
35 getGlyphName = self.getGlyphName
36 names = map(getGlyphName, gids )
37
Behdad Esfahbode5ca7962013-11-27 04:38:16 -050038 list(map(operator.setitem, [vOrig]*self.numVertOriginYMetrics, names, vids))
jvrbc6e55b2006-10-21 13:29:47 +000039
jvraa2723c2003-08-22 20:02:25 +000040
41 def compile(self, ttFont):
Behdad Esfahbodc2297cd2013-11-27 06:26:55 -050042 vorgs = list(self.VOriginRecords.values())
43 names = list(self.VOriginRecords.keys())
jvrbc6e55b2006-10-21 13:29:47 +000044 nameMap = ttFont.getReverseGlyphMap()
45 lenRecords = len(vorgs)
46 try:
47 gids = map(operator.getitem, [nameMap]*lenRecords, names)
48 except KeyError:
Behdad Esfahboddc873722013-12-04 21:28:50 -050049 nameMap = ttFont.getReverseGlyphMap(rebuild=True)
jvrbc6e55b2006-10-21 13:29:47 +000050 gids = map(operator.getitem, [nameMap]*lenRecords, names)
Behdad Esfahbode5ca7962013-11-27 04:38:16 -050051 vOriginTable = list(zip(gids, vorgs))
jvrbc6e55b2006-10-21 13:29:47 +000052 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 Esfahbod18316aa2013-11-27 21:17:35 -050057 data = bytesjoin(dataList)
jvraa2723c2003-08-22 20:02:25 +000058 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 Esfahbod3a9fd302013-11-27 03:19:32 -050082 def fromXML(self, name, attrs, content, ttFont):
jvrcd75d572008-03-09 08:58:36 +000083 if not hasattr(self, "VOriginRecords"):
84 self.VOriginRecords = {}
jvrbc6e55b2006-10-21 13:29:47 +000085 self.getGlyphName = ttFont.getGlyphName # for use in get/set item functions, for access by GID
jvraa2723c2003-08-22 20:02:25 +000086 if name == "VOriginRecord":
jvraa2723c2003-08-22 20:02:25 +000087 vOriginRec = VOriginRecord()
88 for element in content:
Behdad Esfahbodfaaca762013-11-27 23:37:57 -050089 if isinstance(element, basestring):
jvraa2723c2003-08-22 20:02:25 +000090 continue
Behdad Esfahbod3a9fd302013-11-27 03:19:32 -050091 name, attrs, content = element
92 vOriginRec.fromXML(name, attrs, content, ttFont)
jvraa2723c2003-08-22 20:02:25 +000093 self.VOriginRecords[vOriginRec.glyphName] = vOriginRec.vOrigin
Behdad Esfahbodbc5e1cb2013-11-27 02:33:03 -050094 elif "value" in attrs:
Behdad Esfahbod7cc6d272013-11-27 04:00:15 -050095 setattr(self, name, safeEval(attrs["value"]))
jvraa2723c2003-08-22 20:02:25 +000096
jvrbc6e55b2006-10-21 13:29:47 +000097
98 def __getitem__(self, glyphSelector):
Behdad Esfahbodb774f9f2013-11-27 05:17:37 -050099 if isinstance(glyphSelector, int):
jvrbc6e55b2006-10-21 13:29:47 +0000100 # its a gid, convert to glyph name
101 glyphSelector = self.getGlyphName(glyphSelector)
102
Behdad Esfahbodbc5e1cb2013-11-27 02:33:03 -0500103 if glyphSelector not in self.VOriginRecords:
jvraa2723c2003-08-22 20:02:25 +0000104 return self.defaultVertOriginY
105
jvrbc6e55b2006-10-21 13:29:47 +0000106 return self.VOriginRecords[glyphSelector]
jvraa2723c2003-08-22 20:02:25 +0000107
jvrbc6e55b2006-10-21 13:29:47 +0000108 def __setitem__(self, glyphSelector, value):
Behdad Esfahbodb774f9f2013-11-27 05:17:37 -0500109 if isinstance(glyphSelector, int):
jvrbc6e55b2006-10-21 13:29:47 +0000110 # its a gid, convert to glyph name
111 glyphSelector = self.getGlyphName(glyphSelector)
112
jvraa2723c2003-08-22 20:02:25 +0000113 if value != self.defaultVertOriginY:
jvrbc6e55b2006-10-21 13:29:47 +0000114 self.VOriginRecords[glyphSelector] = value
Behdad Esfahbodbc5e1cb2013-11-27 02:33:03 -0500115 elif glyphSelector in self.VOriginRecords:
jvrbc6e55b2006-10-21 13:29:47 +0000116 del self.VOriginRecords[glyphSelector]
jvraa2723c2003-08-22 20:02:25 +0000117
Behdad Esfahbod487b15f2014-05-14 13:51:10 -0600118 def __delitem__(self, glyphSelector):
119 del self.VOriginRecords[glyphSelector]
120
Behdad Esfahbode388db52013-11-28 14:26:58 -0500121class VOriginRecord(object):
jvraa2723c2003-08-22 20:02:25 +0000122
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 Esfahbod3a9fd302013-11-27 03:19:32 -0500137 def fromXML(self, name, attrs, content, ttFont):
jvraa2723c2003-08-22 20:02:25 +0000138 value = attrs["value"]
139 if name == "glyphName":
140 setattr(self, name, value)
141 else:
Behdad Esfahbod7cc6d272013-11-27 04:00:15 -0500142 setattr(self, name, safeEval(value))