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