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