from fontTools.misc import sstruct from fontTools.misc.textTools import tobytes, tostr, safeEval from . import DefaultTable GMAPFormat = """ > # big endian tableVersionMajor: H tableVersionMinor: H flags: H recordsCount: H recordsOffset: H fontNameLength: H """ # psFontName is a byte string which follows the record above. This is zero padded # to the beginning of the records array. The recordsOffsst is 32 bit aligned. GMAPRecordFormat1 = """ > # big endian UV: L cid: H gid: H ggid: H name: 32s """ class GMAPRecord(object): def __init__(self, uv=0, cid=0, gid=0, ggid=0, name=""): self.UV = uv self.cid = cid self.gid = gid self.ggid = ggid self.name = name def toXML(self, writer, ttFont): writer.begintag("GMAPRecord") writer.newline() writer.simpletag("UV", value=self.UV) writer.newline() writer.simpletag("cid", value=self.cid) writer.newline() writer.simpletag("gid", value=self.gid) writer.newline() writer.simpletag("glyphletGid", value=self.gid) writer.newline() writer.simpletag("GlyphletName", value=self.name) writer.newline() writer.endtag("GMAPRecord") writer.newline() def fromXML(self, name, attrs, content, ttFont): value = attrs["value"] if name == "GlyphletName": self.name = value else: setattr(self, name, safeEval(value)) def compile(self, ttFont): if self.UV is None: self.UV = 0 nameLen = len(self.name) if nameLen < 32: self.name = self.name + "\0"*(32 - nameLen) data = sstruct.pack(GMAPRecordFormat1, self) return data def __repr__(self): return "GMAPRecord[ UV: " + str(self.UV) + ", cid: " + str(self.cid) + ", gid: " + str(self.gid) + ", ggid: " + str(self.ggid) + ", Glyphlet Name: " + str(self.name) + " ]" class table_G_M_A_P_(DefaultTable.DefaultTable): dependencies = [] def decompile(self, data, ttFont): dummy, newData = sstruct.unpack2(GMAPFormat, data, self) self.psFontName = tostr(newData[:self.fontNameLength]) assert (self.recordsOffset % 4) == 0, "GMAP error: recordsOffset is not 32 bit aligned." newData = data[self.recordsOffset:] self.gmapRecords = [] for i in range (self.recordsCount): gmapRecord, newData = sstruct.unpack2(GMAPRecordFormat1, newData, GMAPRecord()) gmapRecord.name = gmapRecord.name.strip('\0') self.gmapRecords.append(gmapRecord) def compile(self, ttFont): self.recordsCount = len(self.gmapRecords) self.fontNameLength = len(self.psFontName) self.recordsOffset = 4 * (((self.fontNameLength + 12) + 3) // 4) data = sstruct.pack(GMAPFormat, self) data = data + tobytes(self.psFontName) data = data + b"\0" * (self.recordsOffset - len(data)) for record in self.gmapRecords: data = data + record.compile(ttFont) return data def toXML(self, writer, ttFont): writer.comment("Most of this table will be recalculated by the compiler") writer.newline() formatstring, names, fixes = sstruct.getformat(GMAPFormat) for name in names: value = getattr(self, name) writer.simpletag(name, value=value) writer.newline() writer.simpletag("PSFontName", value=self.psFontName) writer.newline() for gmapRecord in self.gmapRecords: gmapRecord.toXML(writer, ttFont) def fromXML(self, name, attrs, content, ttFont): if name == "GMAPRecord": if not hasattr(self, "gmapRecords"): self.gmapRecords = [] gmapRecord = GMAPRecord() self.gmapRecords.append(gmapRecord) for element in content: if isinstance(element, str): continue name, attrs, content = element gmapRecord.fromXML(name, attrs, content, ttFont) else: value = attrs["value"] if name == "PSFontName": self.psFontName = value else: setattr(self, name, safeEval(value))