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