11ae29591efbb29492ce05378909ccf4028d7c1eeBehdad Esfahbodfrom __future__ import print_function, division, absolute_import 21b8cde1b6f005d3c9c1b2aadf11a0519cc02f15eBehdad Esfahbodfrom fontTools.misc.py23 import * 31b8cde1b6f005d3c9c1b2aadf11a0519cc02f15eBehdad Esfahbodfrom fontTools.misc import sstruct 41b8cde1b6f005d3c9c1b2aadf11a0519cc02f15eBehdad Esfahbodfrom fontTools.misc.textTools import readHex 51b8cde1b6f005d3c9c1b2aadf11a0519cc02f15eBehdad Esfahbodfrom . import DefaultTable 61b8cde1b6f005d3c9c1b2aadf11a0519cc02f15eBehdad Esfahbodfrom .sbixBitmap import * 71b8cde1b6f005d3c9c1b2aadf11a0519cc02f15eBehdad Esfahbodfrom .sbixBitmapSet import * 81b8cde1b6f005d3c9c1b2aadf11a0519cc02f15eBehdad Esfahbodimport struct 94801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 104801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod""" 114801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbodsbix Table organization: 124801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 134801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad EsfahbodUSHORT version? 144801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad EsfahbodUSHORT version? 154801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad EsfahbodUSHORT count number of bitmap sets 164801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad EsfahbodoffsetEntry offsetEntry[count] offsetEntries 174801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod(Variable) storage for bitmap sets 184801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 194801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 204801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad EsfahbodoffsetEntry: 214801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 224801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad EsfahbodULONG offset offset from table start to bitmap set 234801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 244801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 254801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbodbitmap set: 264801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 274801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad EsfahbodUSHORT size height and width in pixels 284801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad EsfahbodUSHORT resolution ? 294801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad EsfahbodoffsetRecord offsetRecord[] 304801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod(Variable) storage for bitmaps 314801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 324801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 334801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad EsfahbodoffsetRecord: 344801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 354801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad EsfahbodULONG bitmapOffset offset from start of bitmap set to individual bitmap 364801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 374801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 384801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbodbitmap: 394801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 404801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad EsfahbodULONG reserved 00 00 00 00 414801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbodchar[4] format data type, e.g. "png " 424801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod(Variable) bitmap data 434801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod""" 444801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 454801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad EsfahbodsbixHeaderFormat = """ 464801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod > 474801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod usVal1: H # 00 01 484801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod usVal2: H # 00 01 494801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod numSets: L # 00 00 00 02 # number of bitmap sets 504801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod""" 514801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad EsfahbodsbixHeaderFormatSize = sstruct.calcsize(sbixHeaderFormat) 524801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 534801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 544801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad EsfahbodsbixBitmapSetOffsetFormat = """ 554801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod > 564801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod offset: L # 00 00 00 10 # offset from table start to each bitmap set 574801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod""" 584801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad EsfahbodsbixBitmapSetOffsetFormatSize = sstruct.calcsize(sbixBitmapSetOffsetFormat) 594801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 604801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 614801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbodclass table__s_b_i_x(DefaultTable.DefaultTable): 624801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod def __init__(self, tag): 634801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod self.tableTag = tag 644801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod self.usVal1 = 1 654801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod self.usVal2 = 1 664801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod self.numSets = 0 674801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod self.bitmapSets = {} 684801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod self.bitmapSetOffsets = [] 694801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 704801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod def decompile(self, data, ttFont): 714801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod # read table header 724801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod sstruct.unpack(sbixHeaderFormat, data[ : sbixHeaderFormatSize], self) 734801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod # collect offsets to individual bitmap sets in self.bitmapSetOffsets 744801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod for i in range(self.numSets): 754801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod myOffset = sbixHeaderFormatSize + i * sbixBitmapSetOffsetFormatSize 764801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod offsetEntry = sbixBitmapSetOffset() 774801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod sstruct.unpack(sbixBitmapSetOffsetFormat, \ 784801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod data[myOffset : myOffset+sbixBitmapSetOffsetFormatSize], \ 794801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod offsetEntry) 804801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod self.bitmapSetOffsets.append(offsetEntry.offset) 814801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 824801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod # decompile BitmapSets 834801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod for i in range(self.numSets-1, -1, -1): 844801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod myBitmapSet = BitmapSet(rawdata=data[self.bitmapSetOffsets[i]:]) 854801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod data = data[:self.bitmapSetOffsets[i]] 864801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod myBitmapSet.decompile(ttFont) 874801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod #print " BitmapSet length: %xh" % len(bitmapSetData) 884801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod #print "Number of Bitmaps:", myBitmapSet.numBitmaps 894801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod if myBitmapSet.size in self.bitmapSets: 904801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod from fontTools import ttLib 91de85e4599f192055569542b90da96773d4140661Behdad Esfahbod raise ttLib.TTLibError("Pixel 'size' must be unique for each BitmapSet") 924801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod self.bitmapSets[myBitmapSet.size] = myBitmapSet 934801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 944801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod # after the bitmaps have been extracted, we don't need the offsets anymore 954801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod del self.bitmapSetOffsets 964801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 974801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod def compile(self, ttFont): 984801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod sbixData = "" 994801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod self.numSets = len(self.bitmapSets) 1004801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod sbixHeader = sstruct.pack(sbixHeaderFormat, self) 1014801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 1024801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod # calculate offset to start of first bitmap set 1034801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod setOffset = sbixHeaderFormatSize + sbixBitmapSetOffsetFormatSize * self.numSets 1044801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 1054801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod for si in sorted(self.bitmapSets.keys()): 1064801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod myBitmapSet = self.bitmapSets[si] 1074801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod myBitmapSet.compile(ttFont) 1084801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod # append offset to this bitmap set to table header 1094801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod myBitmapSet.offset = setOffset 1104801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod sbixHeader += sstruct.pack(sbixBitmapSetOffsetFormat, myBitmapSet) 1114801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod setOffset += sbixBitmapSetHeaderFormatSize + len(myBitmapSet.data) 1124801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod sbixData += myBitmapSet.data 1134801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 1144801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod return sbixHeader + sbixData 1154801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 1164801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod def toXML(self, xmlWriter, ttFont): 1174801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod xmlWriter.simpletag("usVal1", value=self.usVal1) 1184801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod xmlWriter.newline() 1194801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod xmlWriter.simpletag("usVal2", value=self.usVal2) 1204801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod xmlWriter.newline() 1214801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod for i in sorted(self.bitmapSets.keys()): 1224801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod self.bitmapSets[i].toXML(xmlWriter, ttFont) 1234801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 124de85e4599f192055569542b90da96773d4140661Behdad Esfahbod def fromXML(self, name, attrs, content, ttFont): 1254801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod if name in ["usVal1", "usVal2"]: 1264801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod setattr(self, name, int(attrs["value"])) 1274801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod elif name == "bitmapSet": 1284801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod myBitmapSet = BitmapSet() 1294801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod for element in content: 130de85e4599f192055569542b90da96773d4140661Behdad Esfahbod if isinstance(element, tuple): 131de85e4599f192055569542b90da96773d4140661Behdad Esfahbod name, attrs, content = element 132de85e4599f192055569542b90da96773d4140661Behdad Esfahbod myBitmapSet.fromXML(name, attrs, content, ttFont) 1334801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod self.bitmapSets[myBitmapSet.size] = myBitmapSet 1344801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod else: 1354801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod from fontTools import ttLib 136de85e4599f192055569542b90da96773d4140661Behdad Esfahbod raise ttLib.TTLibError("can't handle '%s' element" % name) 1374801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 1384801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 1394801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod# Helper classes 1404801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod 1414801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbodclass sbixBitmapSetOffset(object): 1424801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod pass 143