from __future__ import print_function, division, absolute_import from fontTools.misc.py23 import * from fontTools.misc import sstruct from fontTools.misc.textTools import safeEval, num2binary, binary2num from . import DefaultTable from .sbixGlyph import * from .sbixStrike import * 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 numStrikes: L # Number of bitmap strikes to follow """ sbixHeaderFormatSize = sstruct.calcsize(sbixHeaderFormat) sbixStrikeOffsetFormat = """ > strikeOffset: L # Offset from begining of table to data for the # individual strike """ sbixStrikeOffsetFormatSize = sstruct.calcsize(sbixStrikeOffsetFormat) class table__s_b_i_x(DefaultTable.DefaultTable): def __init__(self, tag=None): DefaultTable.DefaultTable.__init__(self, tag) self.version = 1 self.flags = 1 self.numStrikes = 0 self.strikes = {} self.strikeOffsets = [] def decompile(self, data, ttFont): # read table header sstruct.unpack(sbixHeaderFormat, data[ : sbixHeaderFormatSize], self) # collect offsets to individual strikes in self.strikeOffsets for i in range(self.numStrikes): current_offset = sbixHeaderFormatSize + i * sbixStrikeOffsetFormatSize offset_entry = sbixStrikeOffset() sstruct.unpack(sbixStrikeOffsetFormat, \ data[current_offset:current_offset+sbixStrikeOffsetFormatSize], \ offset_entry) self.strikeOffsets.append(offset_entry.strikeOffset) # decompile Strikes for i in range(self.numStrikes-1, -1, -1): current_strike = Strike(rawdata=data[self.strikeOffsets[i]:]) data = data[:self.strikeOffsets[i]] current_strike.decompile(ttFont) #print " Strike length: %xh" % len(bitmapSetData) #print "Number of Glyph entries:", len(current_strike.glyphs) if current_strike.ppem in self.strikes: from fontTools import ttLib raise ttLib.TTLibError("Pixel 'ppem' must be unique for each Strike") self.strikes[current_strike.ppem] = current_strike # after the glyph data records have been extracted, we don't need the offsets anymore del self.strikeOffsets del self.numStrikes def compile(self, ttFont): sbixData = b"" self.numStrikes = len(self.strikes) sbixHeader = sstruct.pack(sbixHeaderFormat, self) # calculate offset to start of first strike setOffset = sbixHeaderFormatSize + sbixStrikeOffsetFormatSize * self.numStrikes for si in sorted(self.strikes.keys()): current_strike = self.strikes[si] current_strike.compile(ttFont) # append offset to this strike to table header current_strike.strikeOffset = setOffset sbixHeader += sstruct.pack(sbixStrikeOffsetFormat, current_strike) setOffset += len(current_strike.data) sbixData += current_strike.data return sbixHeader + sbixData def toXML(self, xmlWriter, ttFont): xmlWriter.simpletag("version", value=self.version) xmlWriter.newline() xmlWriter.simpletag("flags", value=num2binary(self.flags, 16)) xmlWriter.newline() for i in sorted(self.strikes.keys()): self.strikes[i].toXML(xmlWriter, ttFont) def fromXML(self, name, attrs, content, ttFont): if name =="version": setattr(self, name, safeEval(attrs["value"])) elif name == "flags": setattr(self, name, binary2num(attrs["value"])) elif name == "strike": current_strike = Strike() for element in content: if isinstance(element, tuple): name, attrs, content = element current_strike.fromXML(name, attrs, content, ttFont) self.strikes[current_strike.ppem] = current_strike else: from fontTools import ttLib raise ttLib.TTLibError("can't handle '%s' element" % name) # Helper classes class sbixStrikeOffset(object): pass