from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
from fontTools.misc import sstruct
from fontTools.misc.textTools import safeEval, readHex, hexStr, deHexStr
from .BitmapGlyphMetrics import BigGlyphMetrics, bigGlyphMetricsFormat, SmallGlyphMetrics, smallGlyphMetricsFormat
from . import DefaultTable
import itertools
import os
import struct
import logging


log = logging.getLogger(__name__)

ebdtTableVersionFormat = """
	> # big endian
	version: 16.16F
"""

ebdtComponentFormat = """
	> # big endian
	glyphCode: H
	xOffset:   b
	yOffset:   b
"""

class table_E_B_D_T_(DefaultTable.DefaultTable):

	# Keep a reference to the name of the data locator table.
	locatorName = 'EBLC'

	# This method can be overridden in subclasses to support new formats
	# without changing the other implementation. Also can be used as a
	# convenience method for coverting a font file to an alternative format.
	def getImageFormatClass(self, imageFormat):
		return ebdt_bitmap_classes[imageFormat]

	def decompile(self, data, ttFont):
		# Get the version but don't advance the slice.
		# Most of the lookup for this table is done relative
		# to the begining so slice by the offsets provided
		# in the EBLC table.
		sstruct.unpack2(ebdtTableVersionFormat, data, self)

		# Keep a dict of glyphs that have been seen so they aren't remade.
		# This dict maps intervals of data to the BitmapGlyph.
		glyphDict = {}

		# Pull out the EBLC table and loop through glyphs.
		# A strike is a concept that spans both tables.
		# The actual bitmap data is stored in the EBDT.
		locator = ttFont[self.__class__.locatorName]
		self.strikeData = []
		for curStrike in locator.strikes:
			bitmapGlyphDict = {}
			self.strikeData.append(bitmapGlyphDict)
			for indexSubTable in curStrike.indexSubTables:
				dataIter = zip(indexSubTable.names, indexSubTable.locations)
				for curName, curLoc in dataIter:
					# Don't create duplicate data entries for the same glyphs.
					# Instead just use the structures that already exist if they exist.
					if curLoc in glyphDict:
						curGlyph = glyphDict[curLoc]
					else:
						curGlyphData = data[slice(*curLoc)]
						imageFormatClass = self.getImageFormatClass(indexSubTable.imageFormat)
						curGlyph = imageFormatClass(curGlyphData, ttFont)
						glyphDict[curLoc] = curGlyph
					bitmapGlyphDict[curName] = curGlyph

	def compile(self, ttFont):

		dataList = []
		dataList.append(sstruct.pack(ebdtTableVersionFormat, self))
		dataSize = len(dataList[0])

		# Keep a dict of glyphs that have been seen so they aren't remade.
		# This dict maps the id of the BitmapGlyph to the interval
		# in the data.
		glyphDict = {}

		# Go through the bitmap glyph data. Just in case the data for a glyph
		# changed the size metrics should be recalculated. There are a variety
		# of formats and they get stored in the EBLC table. That is why
		# recalculation is defered to the EblcIndexSubTable class and just
		# pass what is known about bitmap glyphs from this particular table.
		locator = ttFont[self.__class__.locatorName]
		for curStrike, curGlyphDict in zip(locator.strikes, self.strikeData):
			for curIndexSubTable in curStrike.indexSubTables:
				dataLocations = []
				for curName in curIndexSubTable.names:
					# Handle the data placement based on seeing the glyph or not.
					# Just save a reference to the location if the glyph has already
					# been saved in compile. This code assumes that glyphs will only
					# be referenced multiple times from indexFormat5. By luck the
					# code may still work when referencing poorly ordered fonts with
					# duplicate references. If there is a font that is unlucky the
					# respective compile methods for the indexSubTables will fail
					# their assertions. All fonts seem to follow this assumption.
					# More complicated packing may be needed if a counter-font exists.
					glyph = curGlyphDict[curName]
					objectId = id(glyph)
					if objectId not in glyphDict:
						data = glyph.compile(ttFont)
						data = curIndexSubTable.padBitmapData(data)
						startByte = dataSize
						dataSize += len(data)
						endByte = dataSize
						dataList.append(data)
						dataLoc = (startByte, endByte)
						glyphDict[objectId] = dataLoc
					else:
						dataLoc = glyphDict[objectId]
					dataLocations.append(dataLoc)
				# Just use the new data locations in the indexSubTable.
				# The respective compile implementations will take care
				# of any of the problems in the convertion that may arise.
				curIndexSubTable.locations = dataLocations

		return bytesjoin(dataList)

	def toXML(self, writer, ttFont):
		# When exporting to XML if one of the data export formats
		# requires metrics then those metrics may be in the locator.
		# In this case populate the bitmaps with "export metrics".
		if ttFont.bitmapGlyphDataFormat in ('row', 'bitwise'):
			locator = ttFont[self.__class__.locatorName]
			for curStrike, curGlyphDict in zip(locator.strikes, self.strikeData):
				for curIndexSubTable in curStrike.indexSubTables:
					for curName in curIndexSubTable.names:
						glyph = curGlyphDict[curName]
						# I'm not sure which metrics have priority here.
						# For now if both metrics exist go with glyph metrics.
						if hasattr(glyph, 'metrics'):
							glyph.exportMetrics = glyph.metrics
						else:
							glyph.exportMetrics = curIndexSubTable.metrics
						glyph.exportBitDepth = curStrike.bitmapSizeTable.bitDepth

		writer.simpletag("header", [('version', self.version)])
		writer.newline()
		locator = ttFont[self.__class__.locatorName]
		for strikeIndex, bitmapGlyphDict in enumerate(self.strikeData):
			writer.begintag('strikedata', [('index', strikeIndex)])
			writer.newline()
			for curName, curBitmap in bitmapGlyphDict.items():
				curBitmap.toXML(strikeIndex, curName, writer, ttFont)
			writer.endtag('strikedata')
			writer.newline()

	def fromXML(self, name, attrs, content, ttFont):
		if name == 'header':
			self.version = safeEval(attrs['version'])
		elif name == 'strikedata':
			if not hasattr(self, 'strikeData'):
				self.strikeData = []
			strikeIndex = safeEval(attrs['index'])

			bitmapGlyphDict = {}
			for element in content:
				if not isinstance(element, tuple):
					continue
				name, attrs, content = element
				if name[4:].startswith(_bitmapGlyphSubclassPrefix[4:]):
					imageFormat = safeEval(name[len(_bitmapGlyphSubclassPrefix):])
					glyphName = attrs['name']
					imageFormatClass = self.getImageFormatClass(imageFormat)
					curGlyph = imageFormatClass(None, None)
					curGlyph.fromXML(name, attrs, content, ttFont)
					assert glyphName not in bitmapGlyphDict, "Duplicate glyphs with the same name '%s' in the same strike." % glyphName
					bitmapGlyphDict[glyphName] = curGlyph
				else:
					log.warning("%s being ignored by %s", name, self.__class__.__name__)

			# Grow the strike data array to the appropriate size. The XML
			# format allows the strike index value to be out of order.
			if strikeIndex >= len(self.strikeData):
				self.strikeData += [None] * (strikeIndex + 1 - len(self.strikeData))
			assert self.strikeData[strikeIndex] is None, "Duplicate strike EBDT indices."
			self.strikeData[strikeIndex] = bitmapGlyphDict

class EbdtComponent(object):

	def toXML(self, writer, ttFont):
		writer.begintag('ebdtComponent', [('name', self.name)])
		writer.newline()
		for componentName in sstruct.getformat(ebdtComponentFormat)[1][1:]:
			writer.simpletag(componentName, value=getattr(self, componentName))
			writer.newline()
		writer.endtag('ebdtComponent')
		writer.newline()

	def fromXML(self, name, attrs, content, ttFont):
		self.name = attrs['name']
		componentNames = set(sstruct.getformat(ebdtComponentFormat)[1][1:])
		for element in content:
			if not isinstance(element, tuple):
				continue
			name, attrs, content = element
			if name in componentNames:
				vars(self)[name] = safeEval(attrs['value'])
			else:
				log.warning("unknown name '%s' being ignored by EbdtComponent.", name)

# Helper functions for dealing with binary.

def _data2binary(data, numBits):
	binaryList = []
	for curByte in data:
		value = byteord(curByte)
		numBitsCut = min(8, numBits)
		for i in range(numBitsCut):
			if value & 0x1:
				binaryList.append('1')
			else:
				binaryList.append('0')
			value = value >> 1
		numBits -= numBitsCut
	return strjoin(binaryList)

def _binary2data(binary):
	byteList = []
	for bitLoc in range(0, len(binary), 8):
		byteString = binary[bitLoc:bitLoc+8]
		curByte = 0
		for curBit in reversed(byteString):
			curByte = curByte << 1
			if curBit == '1':
				curByte |= 1
		byteList.append(bytechr(curByte))
	return bytesjoin(byteList)

def _memoize(f):
	class memodict(dict):
		def __missing__(self, key):
			ret = f(key)
			if len(key) == 1:
				self[key] = ret
			return ret
	return memodict().__getitem__

# 00100111 -> 11100100 per byte, not to be confused with little/big endian.
# Bitmap data per byte is in the order that binary is written on the page
# with the least significant bit as far right as possible. This is the
# opposite of what makes sense algorithmically and hence this function.
@_memoize
def _reverseBytes(data):
	if len(data) != 1:
		return bytesjoin(map(_reverseBytes, data))
	byte = byteord(data)
	result = 0
	for i in range(8):
		result = result << 1
		result |= byte & 1
		byte = byte >> 1
	return bytechr(result)

# This section of code is for reading and writing image data to/from XML.

def _writeRawImageData(strikeIndex, glyphName, bitmapObject, writer, ttFont):
	writer.begintag('rawimagedata')
	writer.newline()
	writer.dumphex(bitmapObject.imageData)
	writer.endtag('rawimagedata')
	writer.newline()

def _readRawImageData(bitmapObject, name, attrs, content, ttFont):
	bitmapObject.imageData = readHex(content)

def _writeRowImageData(strikeIndex, glyphName, bitmapObject, writer, ttFont):
	metrics = bitmapObject.exportMetrics
	del bitmapObject.exportMetrics
	bitDepth = bitmapObject.exportBitDepth
	del bitmapObject.exportBitDepth

	writer.begintag('rowimagedata', bitDepth=bitDepth, width=metrics.width, height=metrics.height)
	writer.newline()
	for curRow in range(metrics.height):
		rowData = bitmapObject.getRow(curRow, bitDepth=bitDepth, metrics=metrics)
		writer.simpletag('row', value=hexStr(rowData))
		writer.newline()
	writer.endtag('rowimagedata')
	writer.newline()

def _readRowImageData(bitmapObject, name, attrs, content, ttFont):
	bitDepth = safeEval(attrs['bitDepth'])
	metrics = SmallGlyphMetrics()
	metrics.width = safeEval(attrs['width'])
	metrics.height = safeEval(attrs['height'])

	dataRows = []
	for element in content:
		if not isinstance(element, tuple):
			continue
		name, attr, content = element
		# Chop off 'imagedata' from the tag to get just the option.
		if name == 'row':
			dataRows.append(deHexStr(attr['value']))
	bitmapObject.setRows(dataRows, bitDepth=bitDepth, metrics=metrics)

def _writeBitwiseImageData(strikeIndex, glyphName, bitmapObject, writer, ttFont):
	metrics = bitmapObject.exportMetrics
	del bitmapObject.exportMetrics
	bitDepth = bitmapObject.exportBitDepth
	del bitmapObject.exportBitDepth

	# A dict for mapping binary to more readable/artistic ASCII characters.
	binaryConv = {'0':'.', '1':'@'}

	writer.begintag('bitwiseimagedata', bitDepth=bitDepth, width=metrics.width, height=metrics.height)
	writer.newline()
	for curRow in range(metrics.height):
		rowData = bitmapObject.getRow(curRow, bitDepth=1, metrics=metrics, reverseBytes=True)
		rowData = _data2binary(rowData, metrics.width)
		# Make the output a readable ASCII art form.
		rowData = strjoin(map(binaryConv.get, rowData))
		writer.simpletag('row', value=rowData)
		writer.newline()
	writer.endtag('bitwiseimagedata')
	writer.newline()

def _readBitwiseImageData(bitmapObject, name, attrs, content, ttFont):
	bitDepth = safeEval(attrs['bitDepth'])
	metrics = SmallGlyphMetrics()
	metrics.width = safeEval(attrs['width'])
	metrics.height = safeEval(attrs['height'])

	# A dict for mapping from ASCII to binary. All characters are considered
	# a '1' except space, period and '0' which maps to '0'.
	binaryConv = {' ':'0', '.':'0', '0':'0'}

	dataRows = []
	for element in content:
		if not isinstance(element, tuple):
			continue
		name, attr, content = element
		if name == 'row':
			mapParams = zip(attr['value'], itertools.repeat('1'))
			rowData = strjoin(itertools.starmap(binaryConv.get, mapParams))
			dataRows.append(_binary2data(rowData))

	bitmapObject.setRows(dataRows, bitDepth=bitDepth, metrics=metrics, reverseBytes=True)

def _writeExtFileImageData(strikeIndex, glyphName, bitmapObject, writer, ttFont):
	try:
		folder = os.path.dirname(writer.file.name)
	except AttributeError:
		# fall back to current directory if output file's directory isn't found
		folder = '.'
	folder = os.path.join(folder, 'bitmaps')
	filename = glyphName + bitmapObject.fileExtension
	if not os.path.isdir(folder):
		os.makedirs(folder)
	folder = os.path.join(folder, 'strike%d' % strikeIndex)
	if not os.path.isdir(folder):
		os.makedirs(folder)

	fullPath = os.path.join(folder, filename)
	writer.simpletag('extfileimagedata', value=fullPath)
	writer.newline()

	with open(fullPath, "wb") as file:
		file.write(bitmapObject.imageData)

def _readExtFileImageData(bitmapObject, name, attrs, content, ttFont):
	fullPath = attrs['value']
	with open(fullPath, "rb") as file:
		bitmapObject.imageData = file.read()

# End of XML writing code.

# Important information about the naming scheme. Used for identifying formats
# in XML.
_bitmapGlyphSubclassPrefix = 'ebdt_bitmap_format_'

class BitmapGlyph(object):

	# For the external file format. This can be changed in subclasses. This way
	# when the extfile option is turned on files have the form: glyphName.ext
	# The default is just a flat binary file with no meaning.
	fileExtension = '.bin'

	# Keep track of reading and writing of various forms.
	xmlDataFunctions = {
		'raw':		(_writeRawImageData, _readRawImageData),
		'row':		(_writeRowImageData, _readRowImageData),
		'bitwise':	(_writeBitwiseImageData, _readBitwiseImageData),
		'extfile':	(_writeExtFileImageData, _readExtFileImageData),
		}

	def __init__(self, data, ttFont):
		self.data = data
		self.ttFont = ttFont
		# TODO Currently non-lazy decompilation is untested here...
		#if not ttFont.lazy:
		#	self.decompile()
		#	del self.data

	def __getattr__(self, attr):
		# Allow lazy decompile.
		if attr[:2] == '__':
			raise AttributeError(attr)
		if not hasattr(self, "data"):
			raise AttributeError(attr)
		self.decompile()
		del self.data
		return getattr(self, attr)

	# Not a fan of this but it is needed for safer safety checking.
	def getFormat(self):
		return safeEval(self.__class__.__name__[len(_bitmapGlyphSubclassPrefix):])

	def toXML(self, strikeIndex, glyphName, writer, ttFont):
		writer.begintag(self.__class__.__name__, [('name', glyphName)])
		writer.newline()

		self.writeMetrics(writer, ttFont)
		# Use the internal write method to write using the correct output format.
		self.writeData(strikeIndex, glyphName, writer, ttFont)

		writer.endtag(self.__class__.__name__)
		writer.newline()

	def fromXML(self, name, attrs, content, ttFont):
		self.readMetrics(name, attrs, content, ttFont)
		for element in content:
			if not isinstance(element, tuple):
				continue
			name, attr, content = element
			if not name.endswith('imagedata'):
				continue
			# Chop off 'imagedata' from the tag to get just the option.
			option = name[:-len('imagedata')]
			assert option in self.__class__.xmlDataFunctions
			self.readData(name, attr, content, ttFont)

	# Some of the glyphs have the metrics. This allows for metrics to be
	# added if the glyph format has them. Default behavior is to do nothing.
	def writeMetrics(self, writer, ttFont):
		pass

	# The opposite of write metrics.
	def readMetrics(self, name, attrs, content, ttFont):
		pass

	def writeData(self, strikeIndex, glyphName, writer, ttFont):
		try:
			writeFunc, readFunc = self.__class__.xmlDataFunctions[ttFont.bitmapGlyphDataFormat]
		except KeyError:
			writeFunc = _writeRawImageData
		writeFunc(strikeIndex, glyphName, self, writer, ttFont)

	def readData(self, name, attrs, content, ttFont):
		# Chop off 'imagedata' from the tag to get just the option.
		option = name[:-len('imagedata')]
		writeFunc, readFunc = self.__class__.xmlDataFunctions[option]
		readFunc(self, name, attrs, content, ttFont)


# A closure for creating a mixin for the two types of metrics handling.
# Most of the code is very similar so its easier to deal with here.
# Everything works just by passing the class that the mixin is for.
def _createBitmapPlusMetricsMixin(metricsClass):
	# Both metrics names are listed here to make meaningful error messages.
	metricStrings = [BigGlyphMetrics.__name__, SmallGlyphMetrics.__name__]
	curMetricsName = metricsClass.__name__
	# Find which metrics this is for and determine the opposite name.
	metricsId = metricStrings.index(curMetricsName)
	oppositeMetricsName = metricStrings[1-metricsId]

	class BitmapPlusMetricsMixin(object):

		def writeMetrics(self, writer, ttFont):
			self.metrics.toXML(writer, ttFont)

		def readMetrics(self, name, attrs, content, ttFont):
			for element in content:
				if not isinstance(element, tuple):
					continue
				name, attrs, content = element
				if name == curMetricsName:
					self.metrics = metricsClass()
					self.metrics.fromXML(name, attrs, content, ttFont)
				elif name == oppositeMetricsName:
					log.warning("Warning: %s being ignored in format %d.", oppositeMetricsName, self.getFormat())

	return BitmapPlusMetricsMixin

# Since there are only two types of mixin's just create them here.
BitmapPlusBigMetricsMixin = _createBitmapPlusMetricsMixin(BigGlyphMetrics)
BitmapPlusSmallMetricsMixin = _createBitmapPlusMetricsMixin(SmallGlyphMetrics)

# Data that is bit aligned can be tricky to deal with. These classes implement
# helper functionality for dealing with the data and getting a particular row
# of bitwise data. Also helps implement fancy data export/import in XML.
class BitAlignedBitmapMixin(object):

	def _getBitRange(self, row, bitDepth, metrics):
		rowBits = (bitDepth * metrics.width)
		bitOffset = row * rowBits
		return (bitOffset, bitOffset+rowBits)

	def getRow(self, row, bitDepth=1, metrics=None, reverseBytes=False):
		if metrics is None:
			metrics = self.metrics
		assert 0 <= row and row < metrics.height, "Illegal row access in bitmap"

		# Loop through each byte. This can cover two bytes in the original data or
		# a single byte if things happen to be aligned. The very last entry might
		# not be aligned so take care to trim the binary data to size and pad with
		# zeros in the row data. Bit aligned data is somewhat tricky.
		#
		# Example of data cut. Data cut represented in x's.
		# '|' represents byte boundary.
		# data = ...0XX|XXXXXX00|000... => XXXXXXXX
		#		or
		# data = ...0XX|XXXX0000|000... => XXXXXX00
		#   or
		# data = ...000|XXXXXXXX|000... => XXXXXXXX
		#   or
		# data = ...000|00XXXX00|000... => XXXX0000
		#
		dataList = []
		bitRange = self._getBitRange(row, bitDepth, metrics)
		stepRange = bitRange + (8,)
		for curBit in range(*stepRange):
			endBit = min(curBit+8, bitRange[1])
			numBits = endBit - curBit
			cutPoint = curBit % 8
			firstByteLoc = curBit // 8
			secondByteLoc = endBit // 8
			if firstByteLoc < secondByteLoc:
				numBitsCut = 8 - cutPoint
			else:
				numBitsCut = endBit - curBit
			curByte = _reverseBytes(self.imageData[firstByteLoc])
			firstHalf = byteord(curByte) >> cutPoint
			firstHalf = ((1<<numBitsCut)-1) & firstHalf
			newByte = firstHalf
			if firstByteLoc < secondByteLoc and secondByteLoc < len(self.imageData):
				curByte = _reverseBytes(self.imageData[secondByteLoc])
				secondHalf = byteord(curByte) << numBitsCut
				newByte = (firstHalf | secondHalf) & ((1<<numBits)-1)
			dataList.append(bytechr(newByte))

		# The way the data is kept is opposite the algorithm used.
		data = bytesjoin(dataList)
		if not reverseBytes:
			data = _reverseBytes(data)
		return data

	def setRows(self, dataRows, bitDepth=1, metrics=None, reverseBytes=False):
		if metrics is None:
			metrics = self.metrics
		if not reverseBytes:
			dataRows = list(map(_reverseBytes, dataRows))

		# Keep track of a list of ordinal values as they are easier to modify
		# than a list of strings. Map to actual strings later.
		numBytes = (self._getBitRange(len(dataRows), bitDepth, metrics)[0] + 7) // 8
		ordDataList = [0] * numBytes
		for row, data in enumerate(dataRows):
			bitRange = self._getBitRange(row, bitDepth, metrics)
			stepRange = bitRange + (8,)
			for curBit, curByte in zip(range(*stepRange), data):
				endBit = min(curBit+8, bitRange[1])
				cutPoint = curBit % 8
				firstByteLoc = curBit // 8
				secondByteLoc = endBit // 8
				if firstByteLoc < secondByteLoc:
					numBitsCut = 8 - cutPoint
				else:
					numBitsCut = endBit - curBit
				curByte = byteord(curByte)
				firstByte = curByte & ((1<<numBitsCut)-1)
				ordDataList[firstByteLoc] |= (firstByte << cutPoint)
				if firstByteLoc < secondByteLoc and secondByteLoc < numBytes:
					secondByte = (curByte >> numBitsCut) & ((1<<8-numBitsCut)-1)
					ordDataList[secondByteLoc] |= secondByte

		# Save the image data with the bits going the correct way.
		self.imageData = _reverseBytes(bytesjoin(map(bytechr, ordDataList)))

class ByteAlignedBitmapMixin(object):

	def _getByteRange(self, row, bitDepth, metrics):
		rowBytes = (bitDepth * metrics.width + 7) // 8
		byteOffset = row * rowBytes
		return (byteOffset, byteOffset+rowBytes)

	def getRow(self, row, bitDepth=1, metrics=None, reverseBytes=False):
		if metrics is None:
			metrics = self.metrics
		assert 0 <= row and row < metrics.height, "Illegal row access in bitmap"
		byteRange = self._getByteRange(row, bitDepth, metrics)
		data = self.imageData[slice(*byteRange)]
		if reverseBytes:
			data = _reverseBytes(data)
		return data

	def setRows(self, dataRows, bitDepth=1, metrics=None, reverseBytes=False):
		if metrics is None:
			metrics = self.metrics
		if reverseBytes:
			dataRows = map(_reverseBytes, dataRows)
		self.imageData = bytesjoin(dataRows)

class ebdt_bitmap_format_1(ByteAlignedBitmapMixin, BitmapPlusSmallMetricsMixin, BitmapGlyph):

	def decompile(self):
		self.metrics = SmallGlyphMetrics()
		dummy, data = sstruct.unpack2(smallGlyphMetricsFormat, self.data, self.metrics)
		self.imageData = data

	def compile(self, ttFont):
		data = sstruct.pack(smallGlyphMetricsFormat, self.metrics)
		return data + self.imageData


class ebdt_bitmap_format_2(BitAlignedBitmapMixin, BitmapPlusSmallMetricsMixin, BitmapGlyph):

	def decompile(self):
		self.metrics = SmallGlyphMetrics()
		dummy, data = sstruct.unpack2(smallGlyphMetricsFormat, self.data, self.metrics)
		self.imageData = data

	def compile(self, ttFont):
		data = sstruct.pack(smallGlyphMetricsFormat, self.metrics)
		return data + self.imageData


class ebdt_bitmap_format_5(BitAlignedBitmapMixin, BitmapGlyph):

	def decompile(self):
		self.imageData = self.data

	def compile(self, ttFont):
		return self.imageData

class ebdt_bitmap_format_6(ByteAlignedBitmapMixin, BitmapPlusBigMetricsMixin, BitmapGlyph):

	def decompile(self):
		self.metrics = BigGlyphMetrics()
		dummy, data = sstruct.unpack2(bigGlyphMetricsFormat, self.data, self.metrics)
		self.imageData = data

	def compile(self, ttFont):
		data = sstruct.pack(bigGlyphMetricsFormat, self.metrics)
		return data + self.imageData


class ebdt_bitmap_format_7(BitAlignedBitmapMixin, BitmapPlusBigMetricsMixin, BitmapGlyph):

	def decompile(self):
		self.metrics = BigGlyphMetrics()
		dummy, data = sstruct.unpack2(bigGlyphMetricsFormat, self.data, self.metrics)
		self.imageData = data

	def compile(self, ttFont):
		data = sstruct.pack(bigGlyphMetricsFormat, self.metrics)
		return data + self.imageData


class ComponentBitmapGlyph(BitmapGlyph):

	def toXML(self, strikeIndex, glyphName, writer, ttFont):
		writer.begintag(self.__class__.__name__, [('name', glyphName)])
		writer.newline()

		self.writeMetrics(writer, ttFont)

		writer.begintag('components')
		writer.newline()
		for curComponent in self.componentArray:
			curComponent.toXML(writer, ttFont)
		writer.endtag('components')
		writer.newline()

		writer.endtag(self.__class__.__name__)
		writer.newline()

	def fromXML(self, name, attrs, content, ttFont):
		self.readMetrics(name, attrs, content, ttFont)
		for element in content:
			if not isinstance(element, tuple):
				continue
			name, attr, content = element
			if name == 'components':
				self.componentArray = []
				for compElement in content:
					if not isinstance(compElement, tuple):
						continue
					name, attrs, content = compElement
					if name == 'ebdtComponent':
						curComponent = EbdtComponent()
						curComponent.fromXML(name, attrs, content, ttFont)
						self.componentArray.append(curComponent)
					else:
						log.warning("'%s' being ignored in component array.", name)


class ebdt_bitmap_format_8(BitmapPlusSmallMetricsMixin, ComponentBitmapGlyph):

	def decompile(self):
		self.metrics = SmallGlyphMetrics()
		dummy, data = sstruct.unpack2(smallGlyphMetricsFormat, self.data, self.metrics)
		data = data[1:]

		(numComponents,) = struct.unpack(">H", data[:2])
		data = data[2:]
		self.componentArray = []
		for i in range(numComponents):
			curComponent = EbdtComponent()
			dummy, data = sstruct.unpack2(ebdtComponentFormat, data, curComponent)
			curComponent.name = self.ttFont.getGlyphName(curComponent.glyphCode)
			self.componentArray.append(curComponent)

	def compile(self, ttFont):
		dataList = []
		dataList.append(sstruct.pack(smallGlyphMetricsFormat, self.metrics))
		dataList.append(b'\0')
		dataList.append(struct.pack(">H", len(self.componentArray)))
		for curComponent in self.componentArray:
			curComponent.glyphCode = ttFont.getGlyphID(curComponent.name)
			dataList.append(sstruct.pack(ebdtComponentFormat, curComponent))
		return bytesjoin(dataList)


class ebdt_bitmap_format_9(BitmapPlusBigMetricsMixin, ComponentBitmapGlyph):

	def decompile(self):
		self.metrics = BigGlyphMetrics()
		dummy, data = sstruct.unpack2(bigGlyphMetricsFormat, self.data, self.metrics)
		(numComponents,) = struct.unpack(">H", data[:2])
		data = data[2:]
		self.componentArray = []
		for i in range(numComponents):
			curComponent = EbdtComponent()
			dummy, data = sstruct.unpack2(ebdtComponentFormat, data, curComponent)
			curComponent.name = self.ttFont.getGlyphName(curComponent.glyphCode)
			self.componentArray.append(curComponent)

	def compile(self, ttFont):
		dataList = []
		dataList.append(sstruct.pack(bigGlyphMetricsFormat, self.metrics))
		dataList.append(struct.pack(">H", len(self.componentArray)))
		for curComponent in self.componentArray:
			curComponent.glyphCode = ttFont.getGlyphID(curComponent.name)
			dataList.append(sstruct.pack(ebdtComponentFormat, curComponent))
		return bytesjoin(dataList)


# Dictionary of bitmap formats to the class representing that format
# currently only the ones listed in this map are the ones supported.
ebdt_bitmap_classes = {
		1: ebdt_bitmap_format_1,
		2: ebdt_bitmap_format_2,
		5: ebdt_bitmap_format_5,
		6: ebdt_bitmap_format_6,
		7: ebdt_bitmap_format_7,
		8: ebdt_bitmap_format_8,
		9: ebdt_bitmap_format_9,
	}
