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.
143 lines
4.2 KiB
Python
143 lines
4.2 KiB
Python
from __future__ import print_function, division
|
|
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
|