from __future__ import print_function, division, absolute_import from fontTools.misc.py23 import * from fontTools.misc import sstruct from fontTools.misc.textTools import readHex from . import DefaultTable from .sbixBitmap import * from .sbixBitmapSet import * import struct """ sbix Table organization: USHORT version? USHORT version? USHORT count number of bitmap sets offsetEntry offsetEntry[count] offsetEntries (Variable) storage for bitmap sets offsetEntry: ULONG offset offset from table start to bitmap set bitmap set: USHORT size height and width in pixels USHORT resolution ? offsetRecord offsetRecord[] (Variable) storage for bitmaps offsetRecord: ULONG bitmapOffset offset from start of bitmap set to individual bitmap bitmap: ULONG reserved 00 00 00 00 char[4] format data type, e.g. "png " (Variable) bitmap data """ sbixHeaderFormat = """ > usVal1: H # 00 01 usVal2: H # 00 01 numSets: L # 00 00 00 02 # number of bitmap sets """ sbixHeaderFormatSize = sstruct.calcsize(sbixHeaderFormat) sbixBitmapSetOffsetFormat = """ > offset: L # 00 00 00 10 # offset from table start to each bitmap set """ sbixBitmapSetOffsetFormatSize = sstruct.calcsize(sbixBitmapSetOffsetFormat) class table__s_b_i_x(DefaultTable.DefaultTable): def __init__(self, tag): self.tableTag = tag self.usVal1 = 1 self.usVal2 = 1 self.numSets = 0 self.bitmapSets = {} self.bitmapSetOffsets = [] def decompile(self, data, ttFont): # read table header sstruct.unpack(sbixHeaderFormat, data[ : sbixHeaderFormatSize], self) # collect offsets to individual bitmap sets in self.bitmapSetOffsets for i in range(self.numSets): myOffset = sbixHeaderFormatSize + i * sbixBitmapSetOffsetFormatSize offsetEntry = sbixBitmapSetOffset() sstruct.unpack(sbixBitmapSetOffsetFormat, \ data[myOffset : myOffset+sbixBitmapSetOffsetFormatSize], \ offsetEntry) self.bitmapSetOffsets.append(offsetEntry.offset) # decompile BitmapSets for i in range(self.numSets-1, -1, -1): myBitmapSet = BitmapSet(rawdata=data[self.bitmapSetOffsets[i]:]) data = data[:self.bitmapSetOffsets[i]] myBitmapSet.decompile(ttFont) #print " BitmapSet length: %xh" % len(bitmapSetData) #print "Number of Bitmaps:", myBitmapSet.numBitmaps if myBitmapSet.size in self.bitmapSets: from fontTools import ttLib raise ttLib.TTLibError("Pixel 'size' must be unique for each BitmapSet") self.bitmapSets[myBitmapSet.size] = myBitmapSet # after the bitmaps have been extracted, we don't need the offsets anymore del self.bitmapSetOffsets def compile(self, ttFont): sbixData = "" self.numSets = len(self.bitmapSets) sbixHeader = sstruct.pack(sbixHeaderFormat, self) # calculate offset to start of first bitmap set setOffset = sbixHeaderFormatSize + sbixBitmapSetOffsetFormatSize * self.numSets for si in sorted(self.bitmapSets.keys()): myBitmapSet = self.bitmapSets[si] myBitmapSet.compile(ttFont) # append offset to this bitmap set to table header myBitmapSet.offset = setOffset sbixHeader += sstruct.pack(sbixBitmapSetOffsetFormat, myBitmapSet) setOffset += sbixBitmapSetHeaderFormatSize + len(myBitmapSet.data) sbixData += myBitmapSet.data return sbixHeader + sbixData def toXML(self, xmlWriter, ttFont): xmlWriter.simpletag("usVal1", value=self.usVal1) xmlWriter.newline() xmlWriter.simpletag("usVal2", value=self.usVal2) xmlWriter.newline() for i in sorted(self.bitmapSets.keys()): self.bitmapSets[i].toXML(xmlWriter, ttFont) def fromXML(self, name, attrs, content, ttFont): if name in ["usVal1", "usVal2"]: setattr(self, name, int(attrs["value"])) elif name == "bitmapSet": myBitmapSet = BitmapSet() for element in content: if isinstance(element, tuple): name, attrs, content = element myBitmapSet.fromXML(name, attrs, content, ttFont) self.bitmapSets[myBitmapSet.size] = myBitmapSet else: from fontTools import ttLib raise ttLib.TTLibError("can't handle '%s' element" % name) # Helper classes class sbixBitmapSetOffset(object): pass