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