| 28 | |
| 29 | |
| 30 | class Glyph(object): |
| 31 | def __init__(self, glyphName=None, referenceGlyphName=None, originOffsetX=0, originOffsetY=0, graphicType=None, meshData=None, rawdata=None, gid=0): |
| 32 | self.gid = gid |
| 33 | self.glyphName = glyphName |
| 34 | self.referenceGlyphName = referenceGlyphName |
| 35 | self.originOffsetX = originOffsetX |
| 36 | self.originOffsetY = originOffsetY |
| 37 | self.rawdata = rawdata |
| 38 | self.graphicType = graphicType |
| 39 | self.meshData = meshData |
| 40 | |
| 41 | # fix self.graphicType if it is null terminated or too short |
| 42 | if self.graphicType is not None: |
| 43 | if self.graphicType[-1] == "\0": |
| 44 | self.graphicType = self.graphicType[:-1] |
| 45 | if len(self.graphicType) > 4: |
| 46 | from fontTools import ttLib |
| 47 | raise ttLib.TTLibError("Glyph.graphicType must not be longer than 4 characters.") |
| 48 | elif len(self.graphicType) < 4: |
| 49 | # pad with spaces |
| 50 | self.graphicType += " "[:(4 - len(self.graphicType))] |
| 51 | |
| 52 | def decompile(self, ttFont): |
| 53 | #print("DECOMPILING", self.rawdata) |
| 54 | self.glyphName = ttFont.getGlyphName(self.gid) |
| 55 | if self.rawdata is None: |
| 56 | from fontTools import ttLib |
| 57 | raise ttLib.TTLibError("No table data to decompile") |
| 58 | if len(self.rawdata) > 0: |
| 59 | if len(self.rawdata) < meshGlyphHeaderFormatSize: |
| 60 | from fontTools import ttLib |
| 61 | #print "Glyph %i header too short: Expected %x, got %x." % (self.gid, meshGlyphHeaderFormatSize, len(self.rawdata)) |
| 62 | raise ttLib.TTLibError("Glyph header too short.") |
| 63 | |
| 64 | sstruct.unpack(meshGlyphHeaderFormat, self.rawdata[:meshGlyphHeaderFormatSize], self) |
| 65 | |
| 66 | if self.graphicType == "dupe": |
| 67 | # this glyph is a reference to another glyph's image data |
| 68 | gid, = struct.unpack(">H", self.rawdata[meshGlyphHeaderFormatSize:]) |
| 69 | self.referenceGlyphName = ttFont.getGlyphName(gid) |
| 70 | else: |
| 71 | self.meshData = self.rawdata[meshGlyphHeaderFormatSize:] |
| 72 | self.referenceGlyphName = None |
| 73 | # clean up |
| 74 | del self.rawdata |
| 75 | del self.gid |
| 76 | |
| 77 | def compile(self, ttFont): |
| 78 | if self.glyphName is None: |
| 79 | from fontTools import ttLib |
| 80 | raise ttLib.TTLibError("Can't compile Glyph without glyph name") |
| 81 | # TODO: if ttFont has no maxp, cmap etc., ignore glyph names and compile by index? |
| 82 | # (needed if you just want to compile the mesh table on its own) |
| 83 | self.gid = struct.pack(">H", ttFont.getGlyphID(self.glyphName)) |
| 84 | if self.graphicType is None: |
| 85 | self.rawdata = b"" |
| 86 | else: |
| 87 | self.rawdata = sstruct.pack(meshGlyphHeaderFormat, self) + self.meshData |