154 lines
4.8 KiB
Python
Raw Normal View History

from __future__ import print_function, division, absolute_import
2013-12-06 19:41:49 -05:00
from fontTools.misc.py23 import *
from fontTools.misc import sstruct
2014-09-24 12:33:57 +02:00
from fontTools.misc.textTools import readHex, num2binary, binary2num
2013-12-06 19:41:49 -05:00
from . import DefaultTable
2014-09-19 18:19:28 +02:00
from .sbixGlyph import *
2014-09-19 16:21:23 +02:00
from .sbixStrike import *
2013-12-06 19:41:49 -05:00
import struct
2013-12-06 19:40:00 -05:00
"""
sbix Table organization:
UInt16 version
UInt16 flags
2014-09-22 16:58:55 +02:00
UInt32 numStrikes number of strikes (bitmap set for a specific size)
UInt32 strikeOffset[numStrikes] offsetEntries
2013-12-06 19:40:00 -05:00
(Variable) storage for bitmap sets
2014-09-23 18:29:42 +02:00
strikeOffset:
2013-12-06 19:40:00 -05:00
UInt32 strikeOffset Offset from begining of table to data for the individual strike
2013-12-06 19:40:00 -05:00
2014-09-23 18:29:42 +02:00
strike:
2013-12-06 19:40:00 -05:00
2014-09-22 17:20:04 +02:00
UInt16 ppem
UInt16 resolution
UInt32 glyphDataOffset[numGlyphs+1]
2014-09-23 18:29:42 +02:00
(Variable) storage for glyph data
2013-12-06 19:40:00 -05:00
2014-09-23 18:29:42 +02:00
glyphDataOffset:
2013-12-06 19:40:00 -05:00
UInt32 glyphDataOffset offset from start of bitmap set to individual bitmap
2013-12-06 19:40:00 -05:00
2014-09-23 18:29:42 +02:00
glyph:
2013-12-06 19:40:00 -05:00
SInt16 originOffsetX 00 00
SInt16 originOffsetY 00 00
2014-09-24 11:54:32 +02:00
FourCharCode graphicType data type, e.g. "png "
2014-09-23 18:29:42 +02:00
(Variable) glyph data
2013-12-06 19:40:00 -05:00
"""
sbixHeaderFormat = """
>
version: H # Version number (set to 1)
flags: H # The only two bits used in the flags field are bits 0
# and 1. For historical reasons, bit 0 must always be 1.
# Bit 1 is a sbixDrawOutlines flag and is interpreted as
# follows:
# 0: Draw only 'sbix' bitmaps
# 1: Draw both 'sbix' bitmaps and outlines, in that
# order
2014-09-22 16:58:55 +02:00
numStrikes: L # Number of bitmap strikes to follow
2013-12-06 19:40:00 -05:00
"""
sbixHeaderFormatSize = sstruct.calcsize(sbixHeaderFormat)
sbixStrikeOffsetFormat = """
>
strikeOffset: L # Offset from begining of table to data for the
# individual strike
2013-12-06 19:40:00 -05:00
"""
sbixStrikeOffsetFormatSize = sstruct.calcsize(sbixStrikeOffsetFormat)
2013-12-06 19:40:00 -05:00
class table__s_b_i_x(DefaultTable.DefaultTable):
def __init__(self, tag):
self.tableTag = tag
self.version = 1
self.flags = 1
2014-09-22 16:58:55 +02:00
self.numStrikes = 0
self.strikes = {}
self.strikeOffsets = []
2013-12-06 19:40:00 -05:00
def decompile(self, data, ttFont):
# read table header
sstruct.unpack(sbixHeaderFormat, data[ : sbixHeaderFormatSize], self)
# collect offsets to individual strikes in self.strikeOffsets
2014-09-22 16:58:55 +02:00
for i in range(self.numStrikes):
2014-09-24 12:07:35 +02:00
current_offset = sbixHeaderFormatSize + i * sbixStrikeOffsetFormatSize
offset_entry = sbixStrikeOffset()
sstruct.unpack(sbixStrikeOffsetFormat, \
2014-09-24 12:07:35 +02:00
data[current_offset : current_offset+sbixStrikeOffsetFormatSize], \
offset_entry)
self.strikeOffsets.append(offset_entry.strikeOffset)
2013-12-06 19:40:00 -05:00
2014-09-22 17:07:01 +02:00
# decompile Strikes
2014-09-22 16:58:55 +02:00
for i in range(self.numStrikes-1, -1, -1):
2014-09-24 12:07:35 +02:00
current_strike = Strike(rawdata=data[self.strikeOffsets[i]:])
data = data[:self.strikeOffsets[i]]
2014-09-24 12:07:35 +02:00
current_strike.decompile(ttFont)
2014-09-22 17:07:01 +02:00
#print " Strike length: %xh" % len(bitmapSetData)
2014-09-24 12:07:35 +02:00
#print "Number of Glyph entries:", len(current_strike.glyphs)
if current_strike.ppem in self.strikes:
2013-12-06 19:40:00 -05:00
from fontTools import ttLib
2014-09-22 17:20:04 +02:00
raise ttLib.TTLibError("Pixel 'ppem' must be unique for each Strike")
2014-09-24 12:07:35 +02:00
self.strikes[current_strike.ppem] = current_strike
2013-12-06 19:40:00 -05:00
2014-09-23 18:29:42 +02:00
# after the glyph data records have been extracted, we don't need the offsets anymore
del self.strikeOffsets
2014-09-23 18:47:13 +02:00
del self.numStrikes
2013-12-06 19:40:00 -05:00
def compile(self, ttFont):
sbixData = ""
self.numStrikes = len(self.strikes)
2013-12-06 19:40:00 -05:00
sbixHeader = sstruct.pack(sbixHeaderFormat, self)
2014-09-23 18:29:42 +02:00
# calculate offset to start of first strike
setOffset = sbixHeaderFormatSize + sbixStrikeOffsetFormatSize * self.numStrikes
2013-12-06 19:40:00 -05:00
for si in sorted(self.strikes.keys()):
2014-09-24 12:07:35 +02:00
current_strike = self.strikes[si]
current_strike.compile(ttFont)
2014-09-23 18:29:42 +02:00
# append offset to this strike to table header
2014-09-24 12:07:35 +02:00
current_strike.strikeOffset = setOffset
sbixHeader += sstruct.pack(sbixStrikeOffsetFormat, current_strike)
setOffset += len(current_strike.data)
sbixData += current_strike.data
2013-12-06 19:40:00 -05:00
return sbixHeader + sbixData
def toXML(self, xmlWriter, ttFont):
xmlWriter.simpletag("version", value=self.version)
2013-12-06 19:40:00 -05:00
xmlWriter.newline()
2014-09-24 12:33:57 +02:00
xmlWriter.simpletag("flags", value=num2binary(self.flags, 16))
2013-12-06 19:40:00 -05:00
xmlWriter.newline()
for i in sorted(self.strikes.keys()):
self.strikes[i].toXML(xmlWriter, ttFont)
2013-12-06 19:40:00 -05:00
def fromXML(self, name, attrs, content, ttFont):
2014-09-24 12:33:57 +02:00
if name =="version":
2013-12-06 19:40:00 -05:00
setattr(self, name, int(attrs["value"]))
2014-09-24 12:33:57 +02:00
elif name == "flags":
setattr(self, name, binary2num(attrs["value"]))
2014-09-22 17:07:01 +02:00
elif name == "strike":
2014-09-24 12:07:35 +02:00
current_strike = Strike()
2013-12-06 19:40:00 -05:00
for element in content:
if isinstance(element, tuple):
name, attrs, content = element
2014-09-24 12:07:35 +02:00
current_strike.fromXML(name, attrs, content, ttFont)
self.strikes[current_strike.ppem] = current_strike
2013-12-06 19:40:00 -05:00
else:
from fontTools import ttLib
raise ttLib.TTLibError("can't handle '%s' element" % name)
2013-12-06 19:40:00 -05:00
# Helper classes
2014-09-24 12:07:35 +02:00
class sbixStrikeOffset(object):
2013-12-06 19:40:00 -05:00
pass