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