| from __future__ import print_function, division, absolute_import |
| from fontTools.misc.py23 import * |
| from fontTools.misc import sstruct |
| from fontTools.misc.textTools import 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, basestring): |
| 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)) |