• 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 (
69            "GMAPRecord[ UV: "
70            + str(self.UV)
71            + ", cid: "
72            + str(self.cid)
73            + ", gid: "
74            + str(self.gid)
75            + ", ggid: "
76            + str(self.ggid)
77            + ", Glyphlet Name: "
78            + str(self.name)
79            + " ]"
80        )
81
82
83class table_G_M_A_P_(DefaultTable.DefaultTable):
84    dependencies = []
85
86    def decompile(self, data, ttFont):
87        dummy, newData = sstruct.unpack2(GMAPFormat, data, self)
88        self.psFontName = tostr(newData[: self.fontNameLength])
89        assert (
90            self.recordsOffset % 4
91        ) == 0, "GMAP error: recordsOffset is not 32 bit aligned."
92        newData = data[self.recordsOffset :]
93        self.gmapRecords = []
94        for i in range(self.recordsCount):
95            gmapRecord, newData = sstruct.unpack2(
96                GMAPRecordFormat1, newData, GMAPRecord()
97            )
98            gmapRecord.name = gmapRecord.name.strip("\0")
99            self.gmapRecords.append(gmapRecord)
100
101    def compile(self, ttFont):
102        self.recordsCount = len(self.gmapRecords)
103        self.fontNameLength = len(self.psFontName)
104        self.recordsOffset = 4 * (((self.fontNameLength + 12) + 3) // 4)
105        data = sstruct.pack(GMAPFormat, self)
106        data = data + tobytes(self.psFontName)
107        data = data + b"\0" * (self.recordsOffset - len(data))
108        for record in self.gmapRecords:
109            data = data + record.compile(ttFont)
110        return data
111
112    def toXML(self, writer, ttFont):
113        writer.comment("Most of this table will be recalculated by the compiler")
114        writer.newline()
115        formatstring, names, fixes = sstruct.getformat(GMAPFormat)
116        for name in names:
117            value = getattr(self, name)
118            writer.simpletag(name, value=value)
119            writer.newline()
120        writer.simpletag("PSFontName", value=self.psFontName)
121        writer.newline()
122        for gmapRecord in self.gmapRecords:
123            gmapRecord.toXML(writer, ttFont)
124
125    def fromXML(self, name, attrs, content, ttFont):
126        if name == "GMAPRecord":
127            if not hasattr(self, "gmapRecords"):
128                self.gmapRecords = []
129            gmapRecord = GMAPRecord()
130            self.gmapRecords.append(gmapRecord)
131            for element in content:
132                if isinstance(element, str):
133                    continue
134                name, attrs, content = element
135                gmapRecord.fromXML(name, attrs, content, ttFont)
136        else:
137            value = attrs["value"]
138            if name == "PSFontName":
139                self.psFontName = value
140            else:
141                setattr(self, name, safeEval(value))
142