G_M_A_P_.py revision 2b06aaa2a6bcd363c25fb0c43f6bb906906594bd
1from . import DefaultTable
2from fontTools.misc import sstruct
3from types import StringType
4from fontTools.misc.textTools import safeEval, num2binary, binary2num
5
6GMAPFormat = """
7		>	# big endian
8		tableVersionMajor:	H
9		tableVersionMinor: 	H
10		flags:	H
11		recordsCount:		H
12		recordsOffset:		H
13		fontNameLength:		H
14"""
15# psFontName is a byte string which follows the record above. This is zero padded
16# to the beginning of the records array. The recordsOffsst is 32 bit aligned.
17
18GMAPRecordFormat1 = """
19		>	# big endian
20		UV:			L
21		cid:		H
22		gid:		H
23		ggid:		H
24		name:		32s
25"""
26
27
28
29class GMAPRecord:
30	def __init__(self, uv = 0, cid = 0, gid = 0, ggid = 0, name = ""):
31		self.UV = uv
32		self.cid = cid
33		self.gid = gid
34		self.ggid = ggid
35		self.name = name
36
37	def toXML(self, writer, ttFont):
38		writer.begintag("GMAPRecord")
39		writer.newline()
40		writer.simpletag("UV", value=self.UV)
41		writer.newline()
42		writer.simpletag("cid", value=self.cid)
43		writer.newline()
44		writer.simpletag("gid", value=self.gid)
45		writer.newline()
46		writer.simpletag("glyphletGid", value=self.gid)
47		writer.newline()
48		writer.simpletag("GlyphletName", value=self.name)
49		writer.newline()
50		writer.endtag("GMAPRecord")
51		writer.newline()
52
53
54	def fromXML(self, (name, attrs, content), ttFont):
55		value = attrs["value"]
56		if name == "GlyphletName":
57			self.name = value
58		else:
59			try:
60				value = safeEval(value)
61			except OverflowError:
62				value = long(value)
63			setattr(self, name, value)
64
65
66	def compile(self, ttFont):
67		if 	self.UV == None:
68			self.UV = 0
69		nameLen =  len(self.name)
70		if nameLen < 32:
71			self.name = self.name + "\0"*(32 - nameLen)
72		data = sstruct.pack(GMAPRecordFormat1, self)
73		return data
74
75	def __repr__(self):
76		return "GMAPRecord[ UV: " + str(self.UV) + ", cid: " + str(self.cid) + ", gid: " + str(self.gid) + ", ggid: " + str(self.ggid) + ", Glyphlet Name: " + str(self.name) + " ]"
77
78
79class table_G_M_A_P_(DefaultTable.DefaultTable):
80
81	dependencies = []
82
83	def decompile(self, data, ttFont):
84		dummy, newData = sstruct.unpack2(GMAPFormat, data, self)
85		self.psFontName = newData[:self.fontNameLength]
86		assert (self.recordsOffset % 4) == 0, "GMAP error: recordsOffset is not 32 bit aligned."
87		newData = data[self.recordsOffset:]
88		self.gmapRecords = []
89		for i in range (self.recordsCount):
90			gmapRecord, newData = sstruct.unpack2(GMAPRecordFormat1, newData, GMAPRecord())
91			gmapRecord.name = gmapRecord.name.strip('\0')
92			self.gmapRecords.append(gmapRecord)
93
94
95	def compile(self, ttFont):
96		self.recordsCount = len(self.gmapRecords)
97		self.fontNameLength = len(self.psFontName)
98		self.recordsOffset = 4 *(((self.fontNameLength + 12)  + 3) /4)
99		data = sstruct.pack(GMAPFormat, self)
100		data = data + self.psFontName
101		data = data + "\0" * (self.recordsOffset - len(data))
102		for record in self.gmapRecords:
103			data = data + record.compile(ttFont)
104		return data
105
106
107	def toXML(self, writer, ttFont):
108		writer.comment("Most of this table will be recalculated by the compiler")
109		writer.newline()
110		formatstring, names, fixes = sstruct.getformat(GMAPFormat)
111		for name in names:
112			value = getattr(self, name)
113			writer.simpletag(name, value=value)
114			writer.newline()
115		writer.simpletag("PSFontName", value=self.psFontName)
116		writer.newline()
117		for gmapRecord in self.gmapRecords:
118			gmapRecord.toXML(writer, ttFont)
119
120	def fromXML(self, (name, attrs, content), ttFont):
121		if name == "GMAPRecord":
122			if not hasattr(self, "gmapRecords"):
123				self.gmapRecords = []
124			gmapRecord = GMAPRecord()
125			self.gmapRecords.append(gmapRecord)
126			for element in content:
127				if isinstance(element, StringType):
128					continue
129				gmapRecord.fromXML(element, ttFont)
130		else:
131			value = attrs["value"]
132			if name == "PSFontName":
133				self.psFontName = value
134			else:
135				try:
136					value = safeEval(value)
137				except OverflowError:
138					value = long(value)
139				setattr(self, name, value)
140