11ae29591efbb29492ce05378909ccf4028d7c1eeBehdad Esfahbodfrom __future__ import print_function, division, absolute_import
21b8cde1b6f005d3c9c1b2aadf11a0519cc02f15eBehdad Esfahbodfrom fontTools.misc.py23 import *
31b8cde1b6f005d3c9c1b2aadf11a0519cc02f15eBehdad Esfahbodfrom fontTools.misc import sstruct
4f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbodfrom fontTools.misc.textTools import readHex
51b8cde1b6f005d3c9c1b2aadf11a0519cc02f15eBehdad Esfahbodimport struct
61b8cde1b6f005d3c9c1b2aadf11a0519cc02f15eBehdad Esfahbod
7f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod
8f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad EsfahbodsbixBitmapHeaderFormat = """
9f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod	>
10f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod	usReserved1:     H    # 00 00
11f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod	usReserved2:     H    #       00 00
12f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod	imageFormatTag:  4s   # e.g. "png "
13f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod"""
14f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod
15f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad EsfahbodsbixBitmapHeaderFormatSize = sstruct.calcsize(sbixBitmapHeaderFormat)
16f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod
17f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod
18f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbodclass Bitmap(object):
19f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod	def __init__(self, glyphName=None, referenceGlyphName=None, usReserved1=0, usReserved2=0, imageFormatTag=None, imageData=None, rawdata=None, gid=0):
20f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		self.gid = gid
21f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		self.glyphName = glyphName
22f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		self.referenceGlyphName = referenceGlyphName
23f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		self.usReserved1 = usReserved1
24f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		self.usReserved2 = usReserved2
25f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		self.rawdata = rawdata
26f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		self.imageFormatTag = imageFormatTag
27f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		self.imageData = imageData
284801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod
29f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod	def decompile(self, ttFont):
30f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		self.glyphName = ttFont.getGlyphName(self.gid)
31f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		if self.rawdata is None:
32f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			from fontTools import ttLib
33de85e4599f192055569542b90da96773d4140661Behdad Esfahbod			raise ttLib.TTLibError("No table data to decompile")
34f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		if len(self.rawdata) > 0:
35f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			if len(self.rawdata) < sbixBitmapHeaderFormatSize:
36f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod				from fontTools import ttLib
37f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod				#print "Bitmap %i header too short: Expected %x, got %x." % (self.gid, sbixBitmapHeaderFormatSize, len(self.rawdata))
38de85e4599f192055569542b90da96773d4140661Behdad Esfahbod				raise ttLib.TTLibError("Bitmap header too short.")
394801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod
40f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			sstruct.unpack(sbixBitmapHeaderFormat, self.rawdata[:sbixBitmapHeaderFormatSize], self)
414801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod
42f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			if self.imageFormatTag == "dupe":
43f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod				# bitmap is a reference to another glyph's bitmap
44f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod				gid, = struct.unpack(">H", self.rawdata[sbixBitmapHeaderFormatSize:])
45f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod				self.referenceGlyphName = ttFont.getGlyphName(gid)
46f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			else:
47f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod				self.imageData = self.rawdata[sbixBitmapHeaderFormatSize:]
48f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod				self.referenceGlyphName = None
49f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		# clean up
50f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		del self.rawdata
51f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		del self.gid
524801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod
53f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod	def compile(self, ttFont):
54f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		if self.glyphName is None:
55f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			from fontTools import ttLib
56de85e4599f192055569542b90da96773d4140661Behdad Esfahbod			raise ttLib.TTLibError("Can't compile bitmap without glyph name")
57f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			# TODO: if ttFont has no maxp, cmap etc., ignore glyph names and compile by index?
58f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			# (needed if you just want to compile the sbix table on its own)
59f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		self.gid = struct.pack(">H", ttFont.getGlyphID(self.glyphName))
60f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		if self.imageFormatTag is None:
61f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			self.rawdata = ""
62f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		else:
63f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			self.rawdata = sstruct.pack(sbixBitmapHeaderFormat, self) + self.imageData
644801a3ae39bfd79b05e3bb00245c06ab5e09d622Behdad Esfahbod
65f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod	def toXML(self, xmlWriter, ttFont):
66f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		if self.imageFormatTag == None:
67f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			# TODO: ignore empty bitmaps?
68f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			# a bitmap entry is required for each glyph,
69f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			# but empty ones can be calculated at compile time
70f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			xmlWriter.simpletag("bitmap", glyphname=self.glyphName)
71f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			xmlWriter.newline()
72f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			return
73f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		xmlWriter.begintag("bitmap", format=self.imageFormatTag, glyphname=self.glyphName)
74f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		xmlWriter.newline()
75f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		#xmlWriter.simpletag("usReserved1", value=self.usReserved1)
76f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		#xmlWriter.newline()
77f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		#xmlWriter.simpletag("usReserved2", value=self.usReserved2)
78f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		#xmlWriter.newline()
79f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		if self.imageFormatTag == "dupe":
80f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			# format == "dupe" is apparently a reference to another glyph id.
81f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			xmlWriter.simpletag("ref", glyphname=self.referenceGlyphName)
82f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		else:
83f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			xmlWriter.begintag("hexdata")
84f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			xmlWriter.newline()
85f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			xmlWriter.dumphex(self.imageData)
86f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			xmlWriter.endtag("hexdata")
87f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		xmlWriter.newline()
88f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		xmlWriter.endtag("bitmap")
89f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		xmlWriter.newline()
90f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod
91de85e4599f192055569542b90da96773d4140661Behdad Esfahbod	def fromXML(self, name, attrs, content, ttFont):
92f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		#if name in ["usReserved1", "usReserved2"]:
93f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		#	setattr(self, name, int(attrs["value"]))
94f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		#elif
95f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		if name == "ref":
96f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			# bitmap is a "dupe", i.e. a reference to another bitmap.
97f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			# in this case imageData contains the glyph id of the reference glyph
98f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			# get glyph id from glyphname
99f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			self.imageData = struct.pack(">H", ttFont.getGlyphID(attrs["glyphname"]))
100f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		elif name == "hexdata":
101f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			self.imageData = readHex(content)
102f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod		else:
103f1394f3fddcccc9ecf4669522c1a6d8152e5f173Behdad Esfahbod			from fontTools import ttLib
104de85e4599f192055569542b90da96773d4140661Behdad Esfahbod			raise ttLib.TTLibError("can't handle '%s' element" % name)
105