普通文本  |  105行  |  3.74 KB

from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
from fontTools.misc import sstruct
from fontTools.misc.textTools import readHex
import struct


sbixBitmapHeaderFormat = """
	>
	usReserved1:     H    # 00 00
	usReserved2:     H    #       00 00
	imageFormatTag:  4s   # e.g. "png "
"""

sbixBitmapHeaderFormatSize = sstruct.calcsize(sbixBitmapHeaderFormat)


class Bitmap(object):
	def __init__(self, glyphName=None, referenceGlyphName=None, usReserved1=0, usReserved2=0, imageFormatTag=None, imageData=None, rawdata=None, gid=0):
		self.gid = gid
		self.glyphName = glyphName
		self.referenceGlyphName = referenceGlyphName
		self.usReserved1 = usReserved1
		self.usReserved2 = usReserved2
		self.rawdata = rawdata
		self.imageFormatTag = imageFormatTag
		self.imageData = imageData

	def decompile(self, ttFont):
		self.glyphName = ttFont.getGlyphName(self.gid)
		if self.rawdata is None:
			from fontTools import ttLib
			raise ttLib.TTLibError("No table data to decompile")
		if len(self.rawdata) > 0:
			if len(self.rawdata) < sbixBitmapHeaderFormatSize:
				from fontTools import ttLib
				#print "Bitmap %i header too short: Expected %x, got %x." % (self.gid, sbixBitmapHeaderFormatSize, len(self.rawdata))
				raise ttLib.TTLibError("Bitmap header too short.")

			sstruct.unpack(sbixBitmapHeaderFormat, self.rawdata[:sbixBitmapHeaderFormatSize], self)

			if self.imageFormatTag == "dupe":
				# bitmap is a reference to another glyph's bitmap
				gid, = struct.unpack(">H", self.rawdata[sbixBitmapHeaderFormatSize:])
				self.referenceGlyphName = ttFont.getGlyphName(gid)
			else:
				self.imageData = self.rawdata[sbixBitmapHeaderFormatSize:]
				self.referenceGlyphName = None
		# clean up
		del self.rawdata
		del self.gid

	def compile(self, ttFont):
		if self.glyphName is None:
			from fontTools import ttLib
			raise ttLib.TTLibError("Can't compile bitmap without glyph name")
			# TODO: if ttFont has no maxp, cmap etc., ignore glyph names and compile by index?
			# (needed if you just want to compile the sbix table on its own)
		self.gid = struct.pack(">H", ttFont.getGlyphID(self.glyphName))
		if self.imageFormatTag is None:
			self.rawdata = ""
		else:
			self.rawdata = sstruct.pack(sbixBitmapHeaderFormat, self) + self.imageData

	def toXML(self, xmlWriter, ttFont):
		if self.imageFormatTag == None:
			# TODO: ignore empty bitmaps?
			# a bitmap entry is required for each glyph,
			# but empty ones can be calculated at compile time
			xmlWriter.simpletag("bitmap", glyphname=self.glyphName)
			xmlWriter.newline()
			return
		xmlWriter.begintag("bitmap", format=self.imageFormatTag, glyphname=self.glyphName)
		xmlWriter.newline()
		#xmlWriter.simpletag("usReserved1", value=self.usReserved1)
		#xmlWriter.newline()
		#xmlWriter.simpletag("usReserved2", value=self.usReserved2)
		#xmlWriter.newline()
		if self.imageFormatTag == "dupe":
			# format == "dupe" is apparently a reference to another glyph id.
			xmlWriter.simpletag("ref", glyphname=self.referenceGlyphName)
		else:
			xmlWriter.begintag("hexdata")
			xmlWriter.newline()
			xmlWriter.dumphex(self.imageData)
			xmlWriter.endtag("hexdata")
		xmlWriter.newline()
		xmlWriter.endtag("bitmap")
		xmlWriter.newline()

	def fromXML(self, name, attrs, content, ttFont):
		#if name in ["usReserved1", "usReserved2"]:
		#	setattr(self, name, int(attrs["value"]))
		#elif
		if name == "ref":
			# bitmap is a "dupe", i.e. a reference to another bitmap.
			# in this case imageData contains the glyph id of the reference glyph
			# get glyph id from glyphname
			self.imageData = struct.pack(">H", ttFont.getGlyphID(attrs["glyphname"]))
		elif name == "hexdata":
			self.imageData = readHex(content)
		else:
			from fontTools import ttLib
			raise ttLib.TTLibError("can't handle '%s' element" % name)