import DefaultTable | |
import struct, sstruct | |
#from fontTools.misc.textTools import readHex | |
from types import TupleType | |
from sbixBitmapSet import * | |
from sbixBitmap import * | |
""" | |
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 type(element) == TupleType: | |
myBitmapSet.fromXML(element, 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 |