Home | History | Annotate | Download | only in tables
      1 from __future__ import print_function, division, absolute_import
      2 from fontTools.misc.py23 import *
      3 from fontTools.misc import sstruct
      4 from fontTools.misc.textTools import readHex
      5 from . import DefaultTable
      6 from .sbixBitmap import *
      7 from .sbixBitmapSet import *
      8 import struct
      9 
     10 """
     11 sbix Table organization:
     12 
     13 USHORT        version?
     14 USHORT        version?
     15 USHORT        count                    number of bitmap sets
     16 offsetEntry   offsetEntry[count]       offsetEntries
     17 (Variable)    storage for bitmap sets
     18 
     19 
     20 offsetEntry:
     21 
     22 ULONG         offset                   offset from table start to bitmap set
     23 
     24 
     25 bitmap set:
     26 
     27 USHORT        size                     height and width in pixels
     28 USHORT        resolution               ?
     29 offsetRecord  offsetRecord[]
     30 (Variable)    storage for bitmaps
     31 
     32 
     33 offsetRecord:
     34 
     35 ULONG         bitmapOffset             offset from start of bitmap set to individual bitmap
     36 
     37 
     38 bitmap:
     39 
     40 ULONG         reserved                 00 00 00 00
     41 char[4]       format                   data type, e.g. "png "
     42 (Variable)    bitmap data
     43 """
     44 
     45 sbixHeaderFormat = """
     46 	>
     47 	usVal1:          H    # 00 01
     48 	usVal2:          H    #       00 01
     49 	numSets:         L    # 00 00 00 02 # number of bitmap sets
     50 """
     51 sbixHeaderFormatSize = sstruct.calcsize(sbixHeaderFormat)
     52 
     53 
     54 sbixBitmapSetOffsetFormat = """
     55 	>
     56 	offset:          L    # 00 00 00 10 # offset from table start to each bitmap set
     57 """
     58 sbixBitmapSetOffsetFormatSize = sstruct.calcsize(sbixBitmapSetOffsetFormat)
     59 
     60 
     61 class table__s_b_i_x(DefaultTable.DefaultTable):
     62 	def __init__(self, tag):
     63 		self.tableTag = tag
     64 		self.usVal1 = 1
     65 		self.usVal2 = 1
     66 		self.numSets = 0
     67 		self.bitmapSets = {}
     68 		self.bitmapSetOffsets = []
     69 
     70 	def decompile(self, data, ttFont):
     71 		# read table header
     72 		sstruct.unpack(sbixHeaderFormat, data[ : sbixHeaderFormatSize], self)
     73 		# collect offsets to individual bitmap sets in self.bitmapSetOffsets
     74 		for i in range(self.numSets):
     75 			myOffset = sbixHeaderFormatSize + i * sbixBitmapSetOffsetFormatSize
     76 			offsetEntry = sbixBitmapSetOffset()
     77 			sstruct.unpack(sbixBitmapSetOffsetFormat, \
     78 				data[myOffset : myOffset+sbixBitmapSetOffsetFormatSize], \
     79 				offsetEntry)
     80 			self.bitmapSetOffsets.append(offsetEntry.offset)
     81 
     82 		# decompile BitmapSets
     83 		for i in range(self.numSets-1, -1, -1):
     84 			myBitmapSet = BitmapSet(rawdata=data[self.bitmapSetOffsets[i]:])
     85 			data = data[:self.bitmapSetOffsets[i]]
     86 			myBitmapSet.decompile(ttFont)
     87 			#print "  BitmapSet length: %xh" % len(bitmapSetData)
     88 			#print "Number of Bitmaps:", myBitmapSet.numBitmaps
     89 			if myBitmapSet.size in self.bitmapSets:
     90 				from fontTools import ttLib
     91 				raise ttLib.TTLibError("Pixel 'size' must be unique for each BitmapSet")
     92 			self.bitmapSets[myBitmapSet.size] = myBitmapSet
     93 
     94 		# after the bitmaps have been extracted, we don't need the offsets anymore
     95 		del self.bitmapSetOffsets
     96 
     97 	def compile(self, ttFont):
     98 		sbixData = ""
     99 		self.numSets = len(self.bitmapSets)
    100 		sbixHeader = sstruct.pack(sbixHeaderFormat, self)
    101 
    102 		# calculate offset to start of first bitmap set
    103 		setOffset = sbixHeaderFormatSize + sbixBitmapSetOffsetFormatSize * self.numSets
    104 
    105 		for si in sorted(self.bitmapSets.keys()):
    106 			myBitmapSet = self.bitmapSets[si]
    107 			myBitmapSet.compile(ttFont)
    108 			# append offset to this bitmap set to table header
    109 			myBitmapSet.offset = setOffset
    110 			sbixHeader += sstruct.pack(sbixBitmapSetOffsetFormat, myBitmapSet)
    111 			setOffset += sbixBitmapSetHeaderFormatSize + len(myBitmapSet.data)
    112 			sbixData += myBitmapSet.data
    113 
    114 		return sbixHeader + sbixData
    115 
    116 	def toXML(self, xmlWriter, ttFont):
    117 		xmlWriter.simpletag("usVal1", value=self.usVal1)
    118 		xmlWriter.newline()
    119 		xmlWriter.simpletag("usVal2", value=self.usVal2)
    120 		xmlWriter.newline()
    121 		for i in sorted(self.bitmapSets.keys()):
    122 			self.bitmapSets[i].toXML(xmlWriter, ttFont)
    123 
    124 	def fromXML(self, name, attrs, content, ttFont):
    125 		if name in ["usVal1", "usVal2"]:
    126 			setattr(self, name, int(attrs["value"]))
    127 		elif name == "bitmapSet":
    128 			myBitmapSet = BitmapSet()
    129 			for element in content:
    130 				if isinstance(element, tuple):
    131 					name, attrs, content = element
    132 					myBitmapSet.fromXML(name, attrs, content, ttFont)
    133 			self.bitmapSets[myBitmapSet.size] = myBitmapSet
    134 		else:
    135 			from fontTools import ttLib
    136 			raise ttLib.TTLibError("can't handle '%s' element" % name)
    137 
    138 
    139 # Helper classes
    140 
    141 class sbixBitmapSetOffset(object):
    142 	pass
    143