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