This seems to work now. At some point we should go back and clean up and merge datastructures between the four different color font formats.
105 lines
3.7 KiB
Python
105 lines
3.7 KiB
Python
from __future__ import print_function, division
|
|
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)
|