1from __future__ import print_function, division, absolute_import 2from fontTools.misc.py23 import * 3from fontTools.misc.textTools import safeEval 4from . import DefaultTable 5import operator 6import struct 7 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): 17 self.getGlyphName = ttFont.getGlyphName # for use in get/set item functions, for access by GID 18 self.majorVersion, self.minorVersion, self.defaultVertOriginY, self.numVertOriginYMetrics = struct.unpack(">HHhH", data[:8]) 19 assert (self.majorVersion <= 1), "Major version of VORG table is higher than I know how to handle" 20 data = data[8:] 21 vids = [] 22 gids = [] 23 pos = 0 24 for i in range(self.numVertOriginYMetrics): 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: 33 names = map(operator.getitem, [glyphOrder]*self.numVertOriginYMetrics, gids) 34 except IndexError: 35 getGlyphName = self.getGlyphName 36 names = map(getGlyphName, gids ) 37 38 list(map(operator.setitem, [vOrig]*self.numVertOriginYMetrics, names, vids)) 39 40 41 def compile(self, ttFont): 42 vorgs = list(self.VOriginRecords.values()) 43 names = list(self.VOriginRecords.keys()) 44 nameMap = ttFont.getReverseGlyphMap() 45 lenRecords = len(vorgs) 46 try: 47 gids = map(operator.getitem, [nameMap]*lenRecords, names) 48 except KeyError: 49 nameMap = ttFont.getReverseGlyphMap(rebuild=True) 50 gids = map(operator.getitem, [nameMap]*lenRecords, names) 51 vOriginTable = list(zip(gids, vorgs)) 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) 57 data = bytesjoin(dataList) 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 82 def fromXML(self, name, attrs, content, ttFont): 83 if not hasattr(self, "VOriginRecords"): 84 self.VOriginRecords = {} 85 self.getGlyphName = ttFont.getGlyphName # for use in get/set item functions, for access by GID 86 if name == "VOriginRecord": 87 vOriginRec = VOriginRecord() 88 for element in content: 89 if isinstance(element, basestring): 90 continue 91 name, attrs, content = element 92 vOriginRec.fromXML(name, attrs, content, ttFont) 93 self.VOriginRecords[vOriginRec.glyphName] = vOriginRec.vOrigin 94 elif "value" in attrs: 95 setattr(self, name, safeEval(attrs["value"])) 96 97 98 def __getitem__(self, glyphSelector): 99 if isinstance(glyphSelector, int): 100 # its a gid, convert to glyph name 101 glyphSelector = self.getGlyphName(glyphSelector) 102 103 if glyphSelector not in self.VOriginRecords: 104 return self.defaultVertOriginY 105 106 return self.VOriginRecords[glyphSelector] 107 108 def __setitem__(self, glyphSelector, value): 109 if isinstance(glyphSelector, int): 110 # its a gid, convert to glyph name 111 glyphSelector = self.getGlyphName(glyphSelector) 112 113 if value != self.defaultVertOriginY: 114 self.VOriginRecords[glyphSelector] = value 115 elif glyphSelector in self.VOriginRecords: 116 del self.VOriginRecords[glyphSelector] 117 118 def __delitem__(self, glyphSelector): 119 del self.VOriginRecords[glyphSelector] 120 121class VOriginRecord(object): 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 137 def fromXML(self, name, attrs, content, ttFont): 138 value = attrs["value"] 139 if name == "glyphName": 140 setattr(self, name, value) 141 else: 142 setattr(self, name, safeEval(value)) 143