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