| from __future__ import print_function, division, absolute_import |
| from fontTools.misc.py23 import * |
| from fontTools.misc import sstruct |
| from fontTools.misc.textTools import readHex |
| import struct |
| |
| |
| sbixBitmapHeaderFormat = """ |
| > |
| usReserved1: H # 00 00 |
| usReserved2: H # 00 00 |
| imageFormatTag: 4s # e.g. "png " |
| """ |
| |
| sbixBitmapHeaderFormatSize = sstruct.calcsize(sbixBitmapHeaderFormat) |
| |
| |
| class Bitmap(object): |
| def __init__(self, glyphName=None, referenceGlyphName=None, usReserved1=0, usReserved2=0, imageFormatTag=None, imageData=None, rawdata=None, gid=0): |
| self.gid = gid |
| self.glyphName = glyphName |
| self.referenceGlyphName = referenceGlyphName |
| self.usReserved1 = usReserved1 |
| self.usReserved2 = usReserved2 |
| self.rawdata = rawdata |
| self.imageFormatTag = imageFormatTag |
| self.imageData = imageData |
| |
| def decompile(self, ttFont): |
| self.glyphName = ttFont.getGlyphName(self.gid) |
| if self.rawdata is None: |
| from fontTools import ttLib |
| raise ttLib.TTLibError("No table data to decompile") |
| if len(self.rawdata) > 0: |
| if len(self.rawdata) < sbixBitmapHeaderFormatSize: |
| from fontTools import ttLib |
| #print "Bitmap %i header too short: Expected %x, got %x." % (self.gid, sbixBitmapHeaderFormatSize, len(self.rawdata)) |
| raise ttLib.TTLibError("Bitmap header too short.") |
| |
| sstruct.unpack(sbixBitmapHeaderFormat, self.rawdata[:sbixBitmapHeaderFormatSize], self) |
| |
| if self.imageFormatTag == "dupe": |
| # bitmap is a reference to another glyph's bitmap |
| gid, = struct.unpack(">H", self.rawdata[sbixBitmapHeaderFormatSize:]) |
| self.referenceGlyphName = ttFont.getGlyphName(gid) |
| else: |
| self.imageData = self.rawdata[sbixBitmapHeaderFormatSize:] |
| self.referenceGlyphName = None |
| # clean up |
| del self.rawdata |
| del self.gid |
| |
| def compile(self, ttFont): |
| if self.glyphName is None: |
| from fontTools import ttLib |
| raise ttLib.TTLibError("Can't compile bitmap without glyph name") |
| # TODO: if ttFont has no maxp, cmap etc., ignore glyph names and compile by index? |
| # (needed if you just want to compile the sbix table on its own) |
| self.gid = struct.pack(">H", ttFont.getGlyphID(self.glyphName)) |
| if self.imageFormatTag is None: |
| self.rawdata = "" |
| else: |
| self.rawdata = sstruct.pack(sbixBitmapHeaderFormat, self) + self.imageData |
| |
| def toXML(self, xmlWriter, ttFont): |
| if self.imageFormatTag == None: |
| # TODO: ignore empty bitmaps? |
| # a bitmap entry is required for each glyph, |
| # but empty ones can be calculated at compile time |
| xmlWriter.simpletag("bitmap", glyphname=self.glyphName) |
| xmlWriter.newline() |
| return |
| xmlWriter.begintag("bitmap", format=self.imageFormatTag, glyphname=self.glyphName) |
| xmlWriter.newline() |
| #xmlWriter.simpletag("usReserved1", value=self.usReserved1) |
| #xmlWriter.newline() |
| #xmlWriter.simpletag("usReserved2", value=self.usReserved2) |
| #xmlWriter.newline() |
| if self.imageFormatTag == "dupe": |
| # format == "dupe" is apparently a reference to another glyph id. |
| xmlWriter.simpletag("ref", glyphname=self.referenceGlyphName) |
| else: |
| xmlWriter.begintag("hexdata") |
| xmlWriter.newline() |
| xmlWriter.dumphex(self.imageData) |
| xmlWriter.endtag("hexdata") |
| xmlWriter.newline() |
| xmlWriter.endtag("bitmap") |
| xmlWriter.newline() |
| |
| def fromXML(self, name, attrs, content, ttFont): |
| #if name in ["usReserved1", "usReserved2"]: |
| # setattr(self, name, int(attrs["value"])) |
| #elif |
| if name == "ref": |
| # bitmap is a "dupe", i.e. a reference to another bitmap. |
| # in this case imageData contains the glyph id of the reference glyph |
| # get glyph id from glyphname |
| self.imageData = struct.pack(">H", ttFont.getGlyphID(attrs["glyphname"])) |
| elif name == "hexdata": |
| self.imageData = readHex(content) |
| else: |
| from fontTools import ttLib |
| raise ttLib.TTLibError("can't handle '%s' element" % name) |