Add support for standard EBLC/EBDT embedded bitmaps
diff --git a/Doc/documentation.html b/Doc/documentation.html
index ccb9a7d..748f5f7 100644
--- a/Doc/documentation.html
+++ b/Doc/documentation.html
@@ -42,7 +42,7 @@
 The following tables are currently supported:
 <BLOCKQUOTE><TT>
 <!-- begin table list -->
-BASE, CFF, DSIG, GDEF, GMAP, GPKG, GPOS, GSUB, JSTF, LTSH, META, OS/2, SING, TSI0, TSI1, TSI2, TSI3, TSI5, TSIB, TSID, TSIJ, TSIP, TSIS, TSIV, VORG, cmap, cvt, fpgm, gasp, glyf, hdmx, head, hhea, hmtx, kern, loca, maxp, name, post, prep, vhea and vmtx
+BASE, CFF, DSIG, EBDT, EBLC, GDEF, GMAP, GPKG, GPOS, GSUB, JSTF, LTSH, META, OS/2, SING, TSI0, TSI1, TSI2, TSI3, TSI5, TSIB, TSID, TSIJ, TSIP, TSIS, TSIV, VORG, cmap, cvt, fpgm, gasp, glyf, hdmx, head, hhea, hmtx, kern, loca, maxp, name, post, prep, vhea and vmtx
 <!-- end table list -->
 </TT></BLOCKQUOTE>
 Other tables are dumped as hexadecimal data.
diff --git a/Lib/fontTools/ttLib/__init__.py b/Lib/fontTools/ttLib/__init__.py
index 1b8117f..128bcea 100644
--- a/Lib/fontTools/ttLib/__init__.py
+++ b/Lib/fontTools/ttLib/__init__.py
@@ -211,7 +211,8 @@
 			file.close()
 	
 	def saveXML(self, fileOrPath, progress=None, 
-			tables=None, skipTables=None, splitTables=0, disassembleInstructions=1):
+			tables=None, skipTables=None, splitTables=0, disassembleInstructions=1,
+			bitmapGlyphDataFormat='raw'):
 		"""Export the font as TTX (an XML-based text file), or as a series of text
 		files when splitTables is true. In the latter case, the 'fileOrPath'
 		argument should be a path to a directory.
@@ -223,6 +224,7 @@
 		import xmlWriter
 		
 		self.disassembleInstructions = disassembleInstructions
+		self.bitmapGlyphDataFormat = bitmapGlyphDataFormat
 		if not tables:
 			tables = self.keys()
 			if "GlyphOrder" not in tables:
diff --git a/Lib/fontTools/ttLib/tables/BitmapGlyphMetrics.py b/Lib/fontTools/ttLib/tables/BitmapGlyphMetrics.py
new file mode 100644
index 0000000..9cf4667
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/BitmapGlyphMetrics.py
@@ -0,0 +1,57 @@
+# Since bitmap glyph metrics are shared between EBLC and EBDT
+# this class gets its own python file.
+import sstruct
+from types import TupleType
+from fontTools.misc.textTools import safeEval
+
+
+bigGlyphMetricsFormat = """
+  > # big endian
+  height:       B
+  width:        B
+  horiBearingX: b
+  horiBearingY: b
+  horiAdvance:  B
+  vertBearingX: b
+  vertBearingY: b
+  vertAdvance:  B
+"""
+
+smallGlyphMetricsFormat = """
+  > # big endian
+  height:   B
+  width:    B
+  BearingX: b
+  BearingY: b
+  Advance:  B
+"""
+
+class BitmapGlyphMetrics:
+
+	def toXML(self, writer, ttFont):
+		writer.begintag(self.__class__.__name__)
+		writer.newline()
+		for metricName in sstruct.getformat(self.__class__.binaryFormat)[1]:
+			writer.simpletag(metricName, value=getattr(self, metricName))
+			writer.newline()
+		writer.endtag(self.__class__.__name__)
+		writer.newline()
+
+	def fromXML(self, (name, attrs, content), ttFont):
+		metricNames = set(sstruct.getformat(self.__class__.binaryFormat)[1])
+		for element in content:
+			if type(element) != TupleType:
+				continue
+			name, attrs, content = element
+			# Make sure this is a metric that is needed by GlyphMetrics.
+			if name in metricNames:
+				vars(self)[name] = safeEval(attrs['value'])
+			else:
+				print "Warning: unknown name '%s' being ignored in %s." % name, self.__class__.__name__
+
+
+class BigGlyphMetrics(BitmapGlyphMetrics):
+	binaryFormat = bigGlyphMetricsFormat
+	
+class SmallGlyphMetrics(BitmapGlyphMetrics):
+	binaryFormat = smallGlyphMetricsFormat
diff --git a/Lib/fontTools/ttLib/tables/E_B_D_T_.py b/Lib/fontTools/ttLib/tables/E_B_D_T_.py
new file mode 100644
index 0000000..5e62693
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/E_B_D_T_.py
@@ -0,0 +1,749 @@
+
+import DefaultTable
+import os
+import string
+import struct
+import sstruct
+import itertools
+from types import TupleType
+from fontTools.misc.textTools import safeEval, readHex, hexStr, deHexStr
+from BitmapGlyphMetrics import BigGlyphMetrics, bigGlyphMetricsFormat, SmallGlyphMetrics, smallGlyphMetricsFormat
+
+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 = itertools.izip(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 itertools.izip(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 string.join(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 itertools.izip(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 type(element) != TupleType:
+					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(element, ttFont)
+					assert glyphName not in bitmapGlyphDict, "Duplicate glyphs with the same name '%s' in the same strike." % glyphName
+					bitmapGlyphDict[glyphName] = curGlyph
+				else:
+					print "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] == None, "Duplicate strike EBDT indices."
+			self.strikeData[strikeIndex] = bitmapGlyphDict
+
+class EbdtComponent:
+
+	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 type(element) != TupleType:
+				continue
+			name, attrs, content = element
+			if name in componentNames:
+				vars(self)[name] = safeEval(attrs['value'])
+			else:
+				print "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 = ord(curByte)
+		numBitsCut = min(8, numBits)
+		for i in xrange(numBitsCut):
+			if value & 0x1:
+				binaryList.append('1')
+			else:
+				binaryList.append('0')
+			value = value >> 1
+		numBits -= numBitsCut
+	return string.join(binaryList, "")
+
+def _binary2data(binary):
+	byteList = []
+	for bitLoc in xrange(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(chr(curByte))
+	return string.join(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 string.join(map(_reverseBytes, data), "")
+	byte = ord(data)
+	result = 0
+	for i in xrange(8):
+		result = result << 1
+		result |= byte & 1
+		byte = byte >> 1
+	return chr(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 xrange(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 type(element) != TupleType:
+			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 xrange(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 = string.join(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 type(element) != TupleType:
+			continue
+		name, attr, content = element
+		if name == 'row':
+			mapParams = itertools.izip(attr['value'], itertools.repeat('1'))
+			rowData = string.join(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):
+	folder = 'bitmaps/'
+	filename = glyphName + bitmapObject.fileExtension
+	if not os.path.isdir(folder):
+		os.makedirs(folder)
+	folder += 'strike%d/' % strikeIndex
+	if not os.path.isdir(folder):
+		os.makedirs(folder)
+
+	fullPath = 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:
+
+	# 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
+
+	def __getattr__(self, attr):
+		# Allow lazy decompile.
+		if attr[:2] == '__':
+			raise AttributeError, attr
+		if self.data == None:
+			raise AttributeError, attr
+		self.decompile()
+		self.data = None
+		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 type(element) != TupleType:
+				continue
+			name, attr, content = element
+			# Chop off 'imagedata' from the tag to get just the option.
+			option = name[:-len('imagedata')]
+			if option in self.__class__.xmlDataFunctions:
+				self.readData(element, 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:
+
+		def writeMetrics(self, writer, ttFont):
+			self.metrics.toXML(writer, ttFont)
+
+		def readMetrics(self, (name, attrs, content), ttFont):
+			for element in content:
+				if type(element) != TupleType:
+					continue
+				name, attrs, content = element
+				if name == curMetricsName:
+					self.metrics = metricsClass()
+					self.metrics.fromXML(element, ttFont)
+				elif name == oppositeMetricsName:
+					print "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:
+
+	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 == 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 xrange(*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 = ord(curByte) >> cutPoint
+			firstHalf = ((1<<numBitsCut)-1) & firstHalf
+			newByte = firstHalf
+			if firstByteLoc < secondByteLoc and secondByteLoc < len(self.imageData):
+				curByte = _reverseBytes(self.imageData[secondByteLoc])
+				secondHalf = ord(curByte) << numBitsCut
+				newByte = (firstHalf | secondHalf) & ((1<<numBits)-1)
+			dataList.append(chr(newByte))
+
+		# The way the data is kept is opposite the algorithm used.
+		data = string.join(dataList, "")
+		if not reverseBytes:
+			data = _reverseBytes(data)
+		return data
+
+	def setRows(self, dataRows, bitDepth=1, metrics=None, reverseBytes=False):
+		if metrics == None:
+			metrics = self.metrics
+		if not reverseBytes:
+			dataRows = 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 itertools.izip(xrange(*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 = ord(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(string.join(map(chr, ordDataList), ""))
+
+class ByteAlignedBitmapMixin:
+
+	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 == 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 == None:
+			metrics = self.metrics
+		if reverseBytes:
+			dataRows = map(_reverseBytes, dataRows)
+		self.imageData = string.join(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 type(element) != TupleType:
+				continue
+			name, attr, content = element
+			if name == 'components':
+				self.componentArray = []
+				for compElement in content:
+					if type(compElement) != TupleType:
+						continue
+					name, attr, content = compElement
+					if name == 'ebdtComponent':
+						curComponent = EbdtComponent()
+						curComponent.fromXML(compElement, ttFont)
+						self.componentArray.append(curComponent)
+					else:
+						print "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 xrange(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('\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 string.join(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 xrange(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 string.join(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,
+	}
diff --git a/Lib/fontTools/ttLib/tables/E_B_L_C_.py b/Lib/fontTools/ttLib/tables/E_B_L_C_.py
new file mode 100644
index 0000000..bb6e415
--- /dev/null
+++ b/Lib/fontTools/ttLib/tables/E_B_L_C_.py
@@ -0,0 +1,614 @@
+
+import DefaultTable
+import string
+import struct
+import sstruct
+import itertools
+from types import TupleType
+from collections import deque
+from fontTools.misc.textTools import safeEval
+from BitmapGlyphMetrics import BigGlyphMetrics, bigGlyphMetricsFormat, SmallGlyphMetrics, smallGlyphMetricsFormat
+
+eblcHeaderFormat = """
+	> # big endian
+	version:  16.16F
+	numSizes: I
+"""
+# The table format string is split to handle sbitLineMetrics simply.
+bitmapSizeTableFormatPart1 = """
+	> # big endian
+	indexSubTableArrayOffset: I
+	indexTablesSize:          I
+	numberOfIndexSubTables:   I
+	colorRef:                 I
+"""
+# The compound type for hori and vert.
+sbitLineMetricsFormat = """
+	> # big endian
+	ascender:              b
+	descender:             b
+	widthMax:              B
+	caretSlopeNumerator:   b
+	caretSlopeDenominator: b
+	caretOffset:           b
+	minOriginSB:           b
+	minAdvanceSB:          b
+	maxBeforeBL:           b
+	minAfterBL:            b
+	pad1:                  b
+	pad2:                  b
+"""
+# hori and vert go between the two parts.
+bitmapSizeTableFormatPart2 = """
+	> # big endian
+	startGlyphIndex: H
+	endGlyphIndex:   H
+	ppemX:           B
+	ppemY:           B
+	bitDepth:        B
+	flags:           b
+"""
+
+indexSubTableArrayFormat = ">HHL"
+indexSubTableArraySize = struct.calcsize(indexSubTableArrayFormat)
+
+indexSubHeaderFormat = ">HHL"
+indexSubHeaderSize = struct.calcsize(indexSubHeaderFormat)
+
+codeOffsetPairFormat = ">HH"
+codeOffsetPairSize = struct.calcsize(codeOffsetPairFormat)
+
+class table_E_B_L_C_(DefaultTable.DefaultTable):
+
+	dependencies = ['EBDT']
+
+	# 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 getIndexFormatClass(self, indexFormat):
+		return eblc_sub_table_classes[indexFormat]
+
+	def decompile(self, data, ttFont):
+
+		# Save the original data because offsets are from the start of the table.
+		origData = data
+
+		dummy, data = sstruct.unpack2(eblcHeaderFormat, data, self)
+
+		self.strikes = []
+		for curStrikeIndex in xrange(self.numSizes):
+			curStrike = Strike()
+			self.strikes.append(curStrike)
+			curTable = curStrike.bitmapSizeTable
+			dummy, data = sstruct.unpack2(bitmapSizeTableFormatPart1, data, curTable)
+			for metric in ('hori', 'vert'):
+				metricObj = SbitLineMetrics()
+				vars(curTable)[metric] = metricObj
+				dummy, data = sstruct.unpack2(sbitLineMetricsFormat, data, metricObj)
+			dummy, data = sstruct.unpack2(bitmapSizeTableFormatPart2, data, curTable)
+
+		for curStrike in self.strikes:
+			curTable = curStrike.bitmapSizeTable
+			for subtableIndex in xrange(curTable.numberOfIndexSubTables):
+				lowerBound = curTable.indexSubTableArrayOffset + subtableIndex * indexSubTableArraySize
+				upperBound = lowerBound + indexSubTableArraySize
+				data = origData[lowerBound:upperBound]
+
+				tup = struct.unpack(indexSubTableArrayFormat, data)
+				(firstGlyphIndex, lastGlyphIndex, additionalOffsetToIndexSubtable) = tup
+				offsetToIndexSubTable = curTable.indexSubTableArrayOffset + additionalOffsetToIndexSubtable
+				data = origData[offsetToIndexSubTable:]
+
+				tup = struct.unpack(indexSubHeaderFormat, data[:indexSubHeaderSize])
+				(indexFormat, imageFormat, imageDataOffset) = tup
+
+				indexFormatClass = self.getIndexFormatClass(indexFormat)
+				indexSubTable = indexFormatClass(data[indexSubHeaderSize:], ttFont)
+				indexSubTable.firstGlyphIndex = firstGlyphIndex
+				indexSubTable.lastGlyphIndex = lastGlyphIndex
+				indexSubTable.additionalOffsetToIndexSubtable = additionalOffsetToIndexSubtable
+				indexSubTable.indexFormat = indexFormat
+				indexSubTable.imageFormat = imageFormat
+				indexSubTable.imageDataOffset = imageDataOffset
+				curStrike.indexSubTables.append(indexSubTable)
+
+	def compile(self, ttFont):
+
+		dataList = []
+		self.numSizes = len(self.strikes)
+		dataList.append(sstruct.pack(eblcHeaderFormat, self))
+
+		# Data size of the header + bitmapSizeTable needs to be calculated
+		# in order to form offsets. This value will hold the size of the data
+		# in dataList after all the data is consolidated in dataList.
+		dataSize = len(dataList[0])
+
+		# The table will be structured in the following order:
+		# (0) header
+		# (1) Each bitmapSizeTable [1 ... self.numSizes]
+		# (2) Alternate between indexSubTableArray and indexSubTable
+		#     for each bitmapSizeTable present.
+		#
+		# The issue is maintaining the proper offsets when table information
+		# gets moved around. All offsets and size information must be recalculated
+		# when building the table to allow editing within ttLib and also allow easy
+		# import/export to and from XML. All of this offset information is lost
+		# when exporting to XML so everything must be calculated fresh so importing
+		# from XML will work cleanly. Only byte offset and size information is
+		# calculated fresh. Count information like numberOfIndexSubTables is
+		# checked through assertions. If the information in this table was not
+		# touched or was changed properly then these types of values should match.
+		#
+		# The table will be rebuilt the following way:
+		# (0) Precompute the size of all the bitmapSizeTables. This is needed to
+		#     compute the offsets properly.
+		# (1) For each bitmapSizeTable compute the indexSubTable and
+		#    	indexSubTableArray pair. The indexSubTable must be computed first
+		#     so that the offset information in indexSubTableArray can be
+		#     calculated. Update the data size after each pairing.
+		# (2) Build each bitmapSizeTable.
+		# (3) Consolidate all the data into the main dataList in the correct order.
+
+		for curStrike in self.strikes:
+			dataSize += sstruct.calcsize(bitmapSizeTableFormatPart1)
+			dataSize += len(('hori', 'vert')) * sstruct.calcsize(sbitLineMetricsFormat)
+			dataSize += sstruct.calcsize(bitmapSizeTableFormatPart2)
+
+		indexSubTablePairDataList = []
+		for curStrike in self.strikes:
+			curTable = curStrike.bitmapSizeTable
+			curTable.numberOfIndexSubTables = len(curStrike.indexSubTables)
+			curTable.indexSubTableArrayOffset = dataSize
+
+			# Precompute the size of the indexSubTableArray. This information
+			# is important for correctly calculating the new value for
+			# additionalOffsetToIndexSubtable.
+			sizeOfSubTableArray = curTable.numberOfIndexSubTables * indexSubTableArraySize
+			lowerBound = dataSize
+			dataSize += sizeOfSubTableArray
+			upperBound = dataSize
+
+			indexSubTableDataList = []
+			for indexSubTable in curStrike.indexSubTables:
+				indexSubTable.additionalOffsetToIndexSubtable = dataSize - curTable.indexSubTableArrayOffset
+				glyphIds = map(ttFont.getGlyphID, indexSubTable.names)
+				indexSubTable.firstGlyphIndex = min(glyphIds)
+				indexSubTable.lastGlyphIndex = max(glyphIds)
+				data = indexSubTable.compile(ttFont)
+				indexSubTableDataList.append(data)
+				dataSize += len(data)
+			curTable.startGlyphIndex = min(ist.firstGlyphIndex for ist in curStrike.indexSubTables)
+			curTable.endGlyphIndex = max(ist.lastGlyphIndex for ist in curStrike.indexSubTables)
+
+			for i in curStrike.indexSubTables:
+				data = struct.pack(indexSubHeaderFormat, i.firstGlyphIndex, i.lastGlyphIndex, i.additionalOffsetToIndexSubtable)
+				indexSubTablePairDataList.append(data)
+			indexSubTablePairDataList.extend(indexSubTableDataList)
+			curTable.indexTablesSize = dataSize - curTable.indexSubTableArrayOffset
+
+		for curStrike in self.strikes:
+			curTable = curStrike.bitmapSizeTable
+			data = sstruct.pack(bitmapSizeTableFormatPart1, curTable)
+			dataList.append(data)
+			for metric in ('hori', 'vert'):
+				metricObj = vars(curTable)[metric]
+				data = sstruct.pack(sbitLineMetricsFormat, metricObj)
+				dataList.append(data)
+			data = sstruct.pack(bitmapSizeTableFormatPart2, curTable)
+			dataList.append(data)
+		dataList.extend(indexSubTablePairDataList)
+
+		return string.join(dataList, "")
+
+	def toXML(self, writer, ttFont):
+		writer.simpletag('header', [('version', self.version)])
+		writer.newline()
+		for curIndex, curStrike in enumerate(self.strikes):
+			curStrike.toXML(curIndex, writer, ttFont)
+
+	def fromXML(self, (name, attrs, content), ttFont):
+		if name == 'header':
+			self.version = safeEval(attrs['version'])
+		elif name == 'strike':
+			if not hasattr(self, 'strikes'):
+				self.strikes = []
+			strikeIndex = safeEval(attrs['index'])
+			curStrike = Strike()
+			curStrike.fromXML((name, attrs, content), ttFont, self)
+
+			# Grow the strike array to the appropriate size. The XML format
+			# allows for the strike index value to be out of order.
+			if strikeIndex >= len(self.strikes):
+				self.strikes += [None] * (strikeIndex + 1 - len(self.strikes))
+			assert self.strikes[strikeIndex] == None, "Duplicate strike EBLC indices."
+			self.strikes[strikeIndex] = curStrike
+
+class Strike:
+
+	def __init__(self):
+		self.bitmapSizeTable = BitmapSizeTable()
+		self.indexSubTables = []
+
+	def toXML(self, strikeIndex, writer, ttFont):
+		writer.begintag('strike', [('index', strikeIndex)])
+		writer.newline()
+		self.bitmapSizeTable.toXML(writer, ttFont)
+		writer.comment('GlyphIds are written but not read. The firstGlyphIndex and\nlastGlyphIndex values will be recalculated by the compiler.')
+		writer.newline()
+		for indexSubTable in self.indexSubTables:
+			indexSubTable.toXML(writer, ttFont)
+		writer.endtag('strike')
+		writer.newline()
+
+	def fromXML(self, (name, attrs, content), ttFont, locator):
+		for element in content:
+			if type(element) != TupleType:
+				continue
+			name, attrs, content = element
+			if name == 'bitmapSizeTable':
+				self.bitmapSizeTable.fromXML(element, ttFont)
+			elif name.startswith(_indexSubTableSubclassPrefix):
+				indexFormat = safeEval(name[len(_indexSubTableSubclassPrefix):])
+				indexFormatClass = locator.getIndexFormatClass(indexFormat)
+				indexSubTable = indexFormatClass(None, None)
+				indexSubTable.indexFormat = indexFormat
+				indexSubTable.fromXML(element, ttFont)
+				self.indexSubTables.append(indexSubTable)
+
+
+class BitmapSizeTable:
+
+	# Returns all the simple metric names that bitmap size table
+	# cares about in terms of XML creation.
+	def _getXMLMetricNames(self):
+		dataNames = sstruct.getformat(bitmapSizeTableFormatPart1)[1]
+		dataNames = dataNames + sstruct.getformat(bitmapSizeTableFormatPart2)[1]
+		# Skip the first 3 data names because they are byte offsets and counts.
+		return dataNames[3:]
+
+	def toXML(self, writer, ttFont):
+		writer.begintag('bitmapSizeTable')
+		writer.newline()
+		for metric in ('hori', 'vert'):
+			getattr(self, metric).toXML(metric, writer, ttFont)
+		for metricName in self._getXMLMetricNames():
+			writer.simpletag(metricName, value=getattr(self, metricName))
+			writer.newline()
+		writer.endtag('bitmapSizeTable')
+		writer.newline()
+
+	def fromXML(self, (name, attrs, content), ttFont):
+		# Create a lookup for all the simple names that make sense to
+		# bitmap size table. Only read the information from these names.
+		dataNames = set(self._getXMLMetricNames())
+		for element in content:
+			if type(element) != TupleType:
+				continue
+			name, attrs, content = element
+			if name == 'sbitLineMetrics':
+				direction = attrs['direction']
+				assert direction in ('hori', 'vert'), "SbitLineMetrics direction specified invalid."
+				metricObj = SbitLineMetrics()
+				metricObj.fromXML(element, ttFont)
+				vars(self)[direction] = metricObj
+			elif name in dataNames:
+				vars(self)[name] = safeEval(attrs['value'])
+			else:
+				print "Warning: unknown name '%s' being ignored in BitmapSizeTable." % name
+
+
+class SbitLineMetrics:
+
+	def toXML(self, name, writer, ttFont):
+		writer.begintag('sbitLineMetrics', [('direction', name)])
+		writer.newline()
+		for metricName in sstruct.getformat(sbitLineMetricsFormat)[1]:
+			writer.simpletag(metricName, value=getattr(self, metricName))
+			writer.newline()
+		writer.endtag('sbitLineMetrics')
+		writer.newline()
+
+	def fromXML(self, (name, attrs, content), ttFont):
+		metricNames = set(sstruct.getformat(sbitLineMetricsFormat)[1])
+		for element in content:
+			if type(element) != TupleType:
+				continue
+			name, attrs, content = element
+			if name in metricNames:
+				vars(self)[name] = safeEval(attrs['value'])
+
+# Important information about the naming scheme. Used for identifying subtables.
+_indexSubTableSubclassPrefix = 'eblc_index_sub_table_'
+
+class EblcIndexSubTable:
+
+	def __init__(self, data, ttFont):
+		self.data = data
+		self.ttFont = ttFont
+
+	def __getattr__(self, attr):
+		# Allow lazy decompile.
+		if attr[:2] == '__':
+			raise AttributeError, attr
+		if self.data == None:
+			raise AttributeError, attr
+		self.decompile()
+		self.data = None
+		self.ttFont = None
+		return getattr(self, attr)
+
+	# This method just takes care of the indexSubHeader. Implementing subclasses
+	# should call it to compile the indexSubHeader and then continue compiling
+	# the remainder of their unique format.
+	def compile(self, ttFont):
+		return struct.pack(indexSubHeaderFormat, self.indexFormat, self.imageFormat, self.imageDataOffset)
+
+	# Creates the XML for bitmap glyphs. Each index sub table basically makes
+	# the same XML except for specific metric information that is written
+	# out via a method call that a subclass implements optionally.
+	def toXML(self, writer, ttFont):
+		writer.begintag(self.__class__.__name__, [
+				('imageFormat', self.imageFormat),
+				('firstGlyphIndex', self.firstGlyphIndex),
+				('lastGlyphIndex', self.lastGlyphIndex),
+				])
+		writer.newline()
+		self.writeMetrics(writer, ttFont)
+		# Write out the names as thats all thats needed to rebuild etc.
+		# For font debugging of consecutive formats the ids are also written.
+		# The ids are not read when moving from the XML format.
+		glyphIds = map(ttFont.getGlyphID, self.names)
+		for glyphName, glyphId in itertools.izip(self.names, glyphIds):
+			writer.simpletag('glyphLoc', name=glyphName, id=glyphId)
+			writer.newline()
+		writer.endtag(self.__class__.__name__)
+		writer.newline()
+
+	def fromXML(self, (name, attrs, content), ttFont):
+		# Read all the attributes. Even though the glyph indices are
+		# recalculated, they are still read in case there needs to
+		# be an immediate export of the data.
+		self.imageFormat = safeEval(attrs['imageFormat'])
+		self.firstGlyphIndex = safeEval(attrs['firstGlyphIndex'])
+		self.lastGlyphIndex = safeEval(attrs['lastGlyphIndex'])
+
+		self.readMetrics((name, attrs, content), ttFont)
+
+		self.names = []
+		for element in content:
+			if type(element) != TupleType:
+				continue
+			name, attrs, content = element
+			if name == 'glyphLoc':
+				self.names.append(attrs['name'])
+
+	# A helper method that writes the metrics for the index sub table. It also
+	# is responsible for writing the image size for fixed size data since fixed
+	# size is not recalculated on compile. Default behavior is to do nothing.
+	def writeMetrics(self, writer, ttFont):
+		pass
+
+	# A helper method that is the inverse of writeMetrics.
+	def readMetrics(self, (name, attrs, content), ttFont):
+		pass
+
+	# This method is for fixed glyph data sizes. There are formats where
+	# the glyph data is fixed but are actually composite glyphs. To handle
+	# this the font spec in indexSubTable makes the data the size of the
+	# fixed size by padding the component arrays. This function abstracts
+	# out this padding process. Input is data unpadded. Output is data
+	# padded only in fixed formats. Default behavior is to return the data.
+	def padBitmapData(self, data):
+		return data
+
+	# Remove any of the glyph locations and names that are flagged as skipped.
+	# This only occurs in formats {1,3}.
+	def removeSkipGlyphs(self):
+		# Determines if a name, location pair is a valid data location.
+		# Skip glyphs are marked when the size is equal to zero.
+		def isValidLocation((name, (startByte, endByte))):
+			return startByte < endByte
+		# Remove all skip glyphs.
+		dataPairs = filter(isValidLocation, zip(self.names, self.locations))
+		self.names, self.locations = map(list, zip(*dataPairs))
+
+# A closure for creating a custom mixin. This is done because formats 1 and 3
+# are very similar. The only difference between them is the size per offset
+# value. Code put in here should handle both cases generally.
+def _createOffsetArrayIndexSubTableMixin(formatStringForDataType):
+
+	# Prep the data size for the offset array data format.
+	dataFormat = '>'+formatStringForDataType
+	offsetDataSize = struct.calcsize(dataFormat)
+
+	class OffsetArrayIndexSubTableMixin:
+
+		def decompile(self):
+
+			numGlyphs = self.lastGlyphIndex - self.firstGlyphIndex + 1
+			indexingOffsets = [glyphIndex * offsetDataSize for glyphIndex in xrange(numGlyphs+2)]
+			indexingLocations = zip(indexingOffsets, indexingOffsets[1:])
+			offsetArray = [struct.unpack(dataFormat, self.data[slice(*loc)])[0] for loc in indexingLocations]
+
+			glyphIds = range(self.firstGlyphIndex, self.lastGlyphIndex+1)
+			modifiedOffsets = [offset + self.imageDataOffset for offset in offsetArray]
+			self.locations = zip(modifiedOffsets, modifiedOffsets[1:])
+
+			self.names = map(self.ttFont.getGlyphName, glyphIds)
+			self.removeSkipGlyphs()
+
+		def compile(self, ttFont):
+			# First make sure that all the data lines up properly. Formats 1 and 3
+			# must have all its data lined up consecutively. If not this will fail.
+			for curLoc, nxtLoc in itertools.izip(self.locations, self.locations[1:]):
+				assert curLoc[1] == nxtLoc[0], "Data must be consecutive in indexSubTable offset formats"
+
+			glyphIds = map(ttFont.getGlyphID, self.names)
+			# Make sure that all ids are sorted strictly increasing.
+			assert all(glyphIds[i] < glyphIds[i+1] for i in xrange(len(glyphIds)-1))
+
+			# Run a simple algorithm to add skip glyphs to the data locations at
+			# the places where an id is not present.
+			idQueue = deque(glyphIds)
+			locQueue = deque(self.locations)
+			allGlyphIds = range(self.firstGlyphIndex, self.lastGlyphIndex+1)
+			allLocations = []
+			for curId in allGlyphIds:
+				if curId != idQueue[0]:
+					allLocations.append((locQueue[0][0], locQueue[0][0]))
+				else:
+					idQueue.popleft()
+					allLocations.append(locQueue.popleft())
+
+			# Now that all the locations are collected, pack them appropriately into
+			# offsets. This is the form where offset[i] is the location and
+			# offset[i+1]-offset[i] is the size of the data location.
+			offsets = list(allLocations[0]) + [loc[1] for loc in allLocations[1:]]
+			# Image data offset must be less than or equal to the minimum of locations.
+			# This offset may change the value for round tripping but is safer and
+			# allows imageDataOffset to not be required to be in the XML version.
+			self.imageDataOffset = min(offsets)
+			offsetArray = [offset - self.imageDataOffset for offset in offsets]
+
+			dataList = [EblcIndexSubTable.compile(self, ttFont)]
+			dataList += [struct.pack(dataFormat, offsetValue) for offsetValue in offsetArray]
+			# Take care of any padding issues. Only occurs in format 3.
+			if offsetDataSize * len(dataList) % 4 != 0:
+				dataList.append(struct.pack(dataFormat, 0))
+			return string.join(dataList, "")
+
+	return OffsetArrayIndexSubTableMixin
+
+# A Mixin for functionality shared between the different kinds
+# of fixed sized data handling. Both kinds have big metrics so
+# that kind of special processing is also handled in this mixin.
+class FixedSizeIndexSubTableMixin:
+
+	def writeMetrics(self, writer, ttFont):
+		writer.simpletag('imageSize', value=self.imageSize)
+		writer.newline()
+		self.metrics.toXML(writer, ttFont)
+
+	def readMetrics(self, (name, attrs, content), ttFont):
+		for element in content:
+			if type(element) != TupleType:
+				continue
+			name, attrs, content = element
+			if name == 'imageSize':
+				self.imageSize = safeEval(attrs['value'])
+			elif name == BigGlyphMetrics.__name__:
+				self.metrics = BigGlyphMetrics()
+				self.metrics.fromXML(element, ttFont)
+			elif name == SmallGlyphMetrics.__name__:
+				print "Warning: SmallGlyphMetrics being ignored in format %d." % self.indexFormat
+
+	def padBitmapData(self, data):
+		# Make sure that the data isn't bigger than the fixed size.
+		assert len(data) <= self.imageSize, "Data in indexSubTable format %d must be less than the fixed size." % self.indexFormat
+		# Pad the data so that it matches the fixed size.
+		pad = (self.imageSize - len(data)) * '\0'
+		return data + pad
+
+class eblc_index_sub_table_1(_createOffsetArrayIndexSubTableMixin('L'), EblcIndexSubTable):
+	pass
+
+class eblc_index_sub_table_2(FixedSizeIndexSubTableMixin, EblcIndexSubTable):
+
+	def decompile(self):
+		(self.imageSize,) = struct.unpack(">L", self.data[:4])
+		self.metrics = BigGlyphMetrics()
+		sstruct.unpack2(bigGlyphMetricsFormat, self.data[4:], self.metrics)
+		glyphIds = range(self.firstGlyphIndex, self.lastGlyphIndex+1)
+		offsets = [self.imageSize * i + self.imageDataOffset for i in xrange(len(glyphIds)+1)]
+		self.locations = zip(offsets, offsets[1:])
+		self.names = map(self.ttFont.getGlyphName, glyphIds)
+
+	def compile(self, ttFont):
+		glyphIds = map(ttFont.getGlyphID, self.names)
+		# Make sure all the ids are consecutive. This is required by Format 2.
+		assert glyphIds == range(self.firstGlyphIndex, self.lastGlyphIndex+1), "Format 2 ids must be consecutive."
+		self.imageDataOffset = min(zip(*self.locations)[0])
+
+		dataList = [EblcIndexSubTable.compile(self, ttFont)]
+		dataList.append(struct.pack(">L", self.imageSize))
+		dataList.append(sstruct.pack(bigGlyphMetricsFormat, self.metrics))
+		return string.join(dataList, "")
+
+class eblc_index_sub_table_3(_createOffsetArrayIndexSubTableMixin('H'), EblcIndexSubTable):
+	pass
+
+class eblc_index_sub_table_4(EblcIndexSubTable):
+
+	def decompile(self):
+
+		(numGlyphs,) = struct.unpack(">L", self.data[:4])
+		data = self.data[4:]
+		indexingOffsets = [glyphIndex * codeOffsetPairSize for glyphIndex in xrange(numGlyphs+2)]
+		indexingLocations = zip(indexingOffsets, indexingOffsets[1:])
+		glyphArray = [struct.unpack(codeOffsetPairFormat, data[slice(*loc)]) for loc in indexingLocations]
+		glyphIds, offsets = map(list, zip(*glyphArray))
+		# There are one too many glyph ids. Get rid of the last one.
+		glyphIds.pop()
+
+		offsets = [offset + self.imageDataOffset for offset in offsets]
+		self.locations = zip(offsets, offsets[1:])
+		self.names = map(self.ttFont.getGlyphName, glyphIds)
+
+	def compile(self, ttFont):
+		# First make sure that all the data lines up properly. Format 4
+		# must have all its data lined up consecutively. If not this will fail.
+		for curLoc, nxtLoc in itertools.izip(self.locations, self.locations[1:]):
+			assert curLoc[1] == nxtLoc[0], "Data must be consecutive in indexSubTable format 4"
+
+		offsets = list(self.locations[0]) + [loc[1] for loc in self.locations[1:]]
+		# Image data offset must be less than or equal to the minimum of locations.
+		# Resetting this offset may change the value for round tripping but is safer
+		# and allows imageDataOffset to not be required to be in the XML version.
+		self.imageDataOffset = min(offsets)
+		offsets = [offset - self.imageDataOffset for offset in offsets]
+		glyphIds = map(ttFont.getGlyphID, self.names)
+		# Create an iterator over the ids plus a padding value.
+		idsPlusPad = list(itertools.chain(glyphIds, [0]))
+
+		dataList = [EblcIndexSubTable.compile(self, ttFont)]
+		dataList.append(struct.pack(">L", len(glyphIds)))
+		tmp = [struct.pack(codeOffsetPairFormat, *cop) for cop in itertools.izip(idsPlusPad, offsets)]
+		dataList += tmp
+		data = string.join(dataList, "")
+		return data
+
+class eblc_index_sub_table_5(FixedSizeIndexSubTableMixin, EblcIndexSubTable):
+
+	def decompile(self):
+		self.origDataLen = 0
+		(self.imageSize,) = struct.unpack(">L", self.data[:4])
+		data = self.data[4:]
+		self.metrics, data = sstruct.unpack2(bigGlyphMetricsFormat, data, BigGlyphMetrics())
+		(numGlyphs,) = struct.unpack(">L", data[:4])
+		data = data[4:]
+		glyphIds = [struct.unpack(">H", data[2*i:2*(i+1)])[0] for i in xrange(numGlyphs)]
+
+		offsets = [self.imageSize * i + self.imageDataOffset for i in xrange(len(glyphIds)+1)]
+		self.locations = zip(offsets, offsets[1:])
+		self.names = map(self.ttFont.getGlyphName, glyphIds)
+
+	def compile(self, ttFont):
+		self.imageDataOffset = min(zip(*self.locations)[0])
+		dataList = [EblcIndexSubTable.compile(self, ttFont)]
+		dataList.append(struct.pack(">L", self.imageSize))
+		dataList.append(sstruct.pack(bigGlyphMetricsFormat, self.metrics))
+		glyphIds = map(ttFont.getGlyphID, self.names)
+		dataList.append(struct.pack(">L", len(glyphIds)))
+		dataList += [struct.pack(">H", curId) for curId in glyphIds]
+		if len(glyphIds) % 2 == 1:
+			dataList.append(struct.pack(">H", 0))
+		return string.join(dataList, "")
+
+# Dictionary of indexFormat to the class representing that format.
+eblc_sub_table_classes = {
+		1: eblc_index_sub_table_1,
+		2: eblc_index_sub_table_2,
+		3: eblc_index_sub_table_3,
+		4: eblc_index_sub_table_4,
+		5: eblc_index_sub_table_5,
+	}
diff --git a/Lib/fontTools/ttLib/tables/__init__.py b/Lib/fontTools/ttLib/tables/__init__.py
index 84cbf04..76f363e 100644
--- a/Lib/fontTools/ttLib/tables/__init__.py
+++ b/Lib/fontTools/ttLib/tables/__init__.py
@@ -6,6 +6,8 @@
 	import B_A_S_E_
 	import C_F_F_
 	import D_S_I_G_
+	import E_B_D_T_
+	import E_B_L_C_
 	import G_D_E_F_
 	import G_M_A_P_
 	import G_P_K_G_