"""fontTools.ttLib -- a package for dealing with TrueType fonts.

This package offers translators to convert TrueType fonts to Python
objects and vice versa, and additionally from Python to TTX (an XML-based
text format) and vice versa.

Example interactive session:

Python 1.5.2c1 (#43, Mar  9 1999, 13:06:43)  [CW PPC w/GUSI w/MSL]
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>> from fontTools import ttLib
>> tt = ttLib.TTFont("afont.ttf")
>> tt['maxp'].numGlyphs
242
>> tt['OS/2'].achVendID
'B&H\000'
>> tt['head'].unitsPerEm
2048
>> tt.saveXML("afont.ttx")
Dumping 'LTSH' table...
Dumping 'OS/2' table...
Dumping 'VDMX' table...
Dumping 'cmap' table...
Dumping 'cvt ' table...
Dumping 'fpgm' table...
Dumping 'glyf' table...
Dumping 'hdmx' table...
Dumping 'head' table...
Dumping 'hhea' table...
Dumping 'hmtx' table...
Dumping 'loca' table...
Dumping 'maxp' table...
Dumping 'name' table...
Dumping 'post' table...
Dumping 'prep' table...
>> tt2 = ttLib.TTFont()
>> tt2.importXML("afont.ttx")
>> tt2['maxp'].numGlyphs
242
>>

"""

from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import *
from fontTools.misc.loggingTools import deprecateArgument, deprecateFunction
import os
import sys
import logging
try:
	import mmap
	class _mmap(mmap.mmap):
		# Subclass native type just so we can assign a new attribute ('name') to instances.
		pass
except ImportError:
	pass


log = logging.getLogger(__name__)

class TTLibError(Exception): pass

class TTFont(object):

	"""The main font object. It manages file input and output, and offers
	a convenient way of accessing tables.
	Tables will be only decompiled when necessary, ie. when they're actually
	accessed. This means that simple operations can be extremely fast.
	"""

	def __init__(self, file=None, res_name_or_index=None,
			sfntVersion="\000\001\000\000", flavor=None, checkChecksums=False,
			verbose=None, recalcBBoxes=True, allowVID=False, ignoreDecompileErrors=False,
			recalcTimestamp=True, fontNumber=-1, lazy=None, quiet=None):

		"""The constructor can be called with a few different arguments.
		When reading a font from disk, 'file' should be either a pathname
		pointing to a file, or a readable file object.

		It we're running on a Macintosh, 'res_name_or_index' maybe an sfnt
		resource name or an sfnt resource index number or zero. The latter
		case will cause TTLib to autodetect whether the file is a flat file
		or a suitcase. (If it's a suitcase, only the first 'sfnt' resource
		will be read!)

		The 'checkChecksums' argument is used to specify how sfnt
		checksums are treated upon reading a file from disk:
			0: don't check (default)
			1: check, print warnings if a wrong checksum is found
			2: check, raise an exception if a wrong checksum is found.

		The TTFont constructor can also be called without a 'file'
		argument: this is the way to create a new empty font.
		In this case you can optionally supply the 'sfntVersion' argument,
		and a 'flavor' which can be None, 'woff', or 'woff2'.

		If the recalcBBoxes argument is false, a number of things will *not*
		be recalculated upon save/compile:
			1) glyph bounding boxes
			2) maxp font bounding box
			3) hhea min/max values
		(1) is needed for certain kinds of CJK fonts (ask Werner Lemberg ;-).
		Additionally, upon importing an TTX file, this option cause glyphs
		to be compiled right away. This should reduce memory consumption
		greatly, and therefore should have some impact on the time needed
		to parse/compile large fonts.

		If the recalcTimestamp argument is false, the modified timestamp in the
		'head' table will *not* be recalculated upon save/compile.

		If the allowVID argument is set to true, then virtual GID's are
		supported. Asking for a glyph ID with a glyph name or GID that is not in
		the font will return a virtual GID.   This is valid for GSUB and cmap
		tables. For SING glyphlets, the cmap table is used to specify Unicode
		values for virtual GI's used in GSUB/GPOS rules. If the gid N is requested
		and does not exist in the font, or the glyphname has the form glyphN
		and does not exist in the font, then N is used as the virtual GID.
		Else, the first virtual GID is assigned as 0x1000 -1; for subsequent new
		virtual GIDs, the next is one less than the previous.

		If ignoreDecompileErrors is set to True, exceptions raised in
		individual tables during decompilation will be ignored, falling
		back to the DefaultTable implementation, which simply keeps the
		binary data.

		If lazy is set to True, many data structures are loaded lazily, upon
		access only.  If it is set to False, many data structures are loaded
		immediately.  The default is lazy=None which is somewhere in between.
		"""

		from fontTools.ttLib import sfnt

		for name in ("verbose", "quiet"):
			val = locals().get(name)
			if val is not None:
				deprecateArgument(name, "configure logging instead")
			setattr(self, name, val)

		self.lazy = lazy
		self.recalcBBoxes = recalcBBoxes
		self.recalcTimestamp = recalcTimestamp
		self.tables = {}
		self.reader = None

		# Permit the user to reference glyphs that are not int the font.
		self.last_vid = 0xFFFE # Can't make it be 0xFFFF, as the world is full unsigned short integer counters that get incremented after the last seen GID value.
		self.reverseVIDDict = {}
		self.VIDDict = {}
		self.allowVID = allowVID
		self.ignoreDecompileErrors = ignoreDecompileErrors

		if not file:
			self.sfntVersion = sfntVersion
			self.flavor = flavor
			self.flavorData = None
			return
		if not hasattr(file, "read"):
			closeStream = True
			# assume file is a string
			if res_name_or_index is not None:
				# see if it contains 'sfnt' resources in the resource or data fork
				from . import macUtils
				if res_name_or_index == 0:
					if macUtils.getSFNTResIndices(file):
						# get the first available sfnt font.
						file = macUtils.SFNTResourceReader(file, 1)
					else:
						file = open(file, "rb")
				else:
					file = macUtils.SFNTResourceReader(file, res_name_or_index)
			else:
				file = open(file, "rb")

		else:
			# assume "file" is a readable file object
			closeStream = False
		if not self.lazy:
			# Try mmap()ing it first:
			try:
				# TODO: Port to Windows version of mmap's module
				tmp = _mmap(file.fileno(), 0, flags=mmap.MAP_PRIVATE, prot=mmap.PROT_READ)
			except mmap.error:
				# Read into memory and wrap a stream around it to allow overwriting
				tmp = BytesIO(file.read())
			if hasattr(file, 'name'):
				# save reference to input file name
				tmp.name = file.name
			if closeStream:
				file.close()
			file = tmp
		self.reader = sfnt.SFNTReader(file, checkChecksums, fontNumber=fontNumber)
		self.sfntVersion = self.reader.sfntVersion
		self.flavor = self.reader.flavor
		self.flavorData = self.reader.flavorData

	def close(self):
		"""If we still have a reader object, close it."""
		if self.reader is not None:
			self.reader.close()

	def save(self, file, reorderTables=True):
		"""Save the font to disk. Similarly to the constructor,
		the 'file' argument can be either a pathname or a writable
		file object.
		"""
		from fontTools.ttLib import sfnt
		if not hasattr(file, "write"):
			if self.lazy and self.reader.file.name == file:
				raise TTLibError(
					"Can't overwrite TTFont when 'lazy' attribute is True")
			closeStream = True
			file = open(file, "wb")
		else:
			# assume "file" is a writable file object
			closeStream = False

		tags = list(self.keys())
		if "GlyphOrder" in tags:
			tags.remove("GlyphOrder")
		numTables = len(tags)
		# write to a temporary stream to allow saving to unseekable streams
		tmp = BytesIO()
		writer = sfnt.SFNTWriter(tmp, numTables, self.sfntVersion, self.flavor, self.flavorData)

		done = []
		for tag in tags:
			self._writeTable(tag, writer, done)

		writer.close()

		if (reorderTables is None or writer.reordersTables() or
				(reorderTables is False and self.reader is None)):
			# don't reorder tables and save as is
			file.write(tmp.getvalue())
			tmp.close()
		else:
			if reorderTables is False:
				# sort tables using the original font's order
				tableOrder = list(self.reader.keys())
			else:
				# use the recommended order from the OpenType specification
				tableOrder = None
			tmp.flush()
			tmp.seek(0)
			tmp2 = BytesIO()
			reorderFontTables(tmp, tmp2, tableOrder)
			file.write(tmp2.getvalue())
			tmp.close()
			tmp2.close()

		if closeStream:
			file.close()

	def saveXML(self, fileOrPath, progress=None, quiet=None,
			tables=None, skipTables=None, splitTables=False, disassembleInstructions=True,
			bitmapGlyphDataFormat='raw', newlinestr=None):
		"""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.
		The 'tables' argument must either be false (dump all tables) or a
		list of tables to dump. The 'skipTables' argument may be a list of tables
		to skip, but only when the 'tables' argument is false.
		"""
		from fontTools import version
		from fontTools.misc import xmlWriter

		# only write the MAJOR.MINOR version in the 'ttLibVersion' attribute of
		# TTX files' root element (without PATCH or .dev suffixes)
		version = ".".join(version.split('.')[:2])

		if quiet is not None:
			deprecateArgument("quiet", "configure logging instead")

		self.disassembleInstructions = disassembleInstructions
		self.bitmapGlyphDataFormat = bitmapGlyphDataFormat
		if not tables:
			tables = list(self.keys())
			if "GlyphOrder" not in tables:
				tables = ["GlyphOrder"] + tables
			if skipTables:
				for tag in skipTables:
					if tag in tables:
						tables.remove(tag)
		numTables = len(tables)
		if progress:
			progress.set(0, numTables)
			idlefunc = getattr(progress, "idle", None)
		else:
			idlefunc = None

		writer = xmlWriter.XMLWriter(fileOrPath, idlefunc=idlefunc,
				newlinestr=newlinestr)
		writer.begintag("ttFont", sfntVersion=repr(tostr(self.sfntVersion))[1:-1],
				ttLibVersion=version)
		writer.newline()

		if not splitTables:
			writer.newline()
		else:
			# 'fileOrPath' must now be a path
			path, ext = os.path.splitext(fileOrPath)
			fileNameTemplate = path + ".%s" + ext

		for i in range(numTables):
			if progress:
				progress.set(i)
			tag = tables[i]
			if splitTables:
				tablePath = fileNameTemplate % tagToIdentifier(tag)
				tableWriter = xmlWriter.XMLWriter(tablePath, idlefunc=idlefunc,
						newlinestr=newlinestr)
				tableWriter.begintag("ttFont", ttLibVersion=version)
				tableWriter.newline()
				tableWriter.newline()
				writer.simpletag(tagToXML(tag), src=os.path.basename(tablePath))
				writer.newline()
			else:
				tableWriter = writer
			self._tableToXML(tableWriter, tag, progress)
			if splitTables:
				tableWriter.endtag("ttFont")
				tableWriter.newline()
				tableWriter.close()
		if progress:
			progress.set((i + 1))
		writer.endtag("ttFont")
		writer.newline()
		# close if 'fileOrPath' is a path; leave it open if it's a file.
		# The special string "-" means standard output so leave that open too
		if not hasattr(fileOrPath, "write") and fileOrPath != "-":
			writer.close()

	def _tableToXML(self, writer, tag, progress, quiet=None):
		if quiet is not None:
			deprecateArgument("quiet", "configure logging instead")
		if tag in self:
			table = self[tag]
			report = "Dumping '%s' table..." % tag
		else:
			report = "No '%s' table found." % tag
		if progress:
			progress.setLabel(report)
		log.info(report)
		if tag not in self:
			return
		xmlTag = tagToXML(tag)
		attrs = dict()
		if hasattr(table, "ERROR"):
			attrs['ERROR'] = "decompilation error"
		from .tables.DefaultTable import DefaultTable
		if table.__class__ == DefaultTable:
			attrs['raw'] = True
		writer.begintag(xmlTag, **attrs)
		writer.newline()
		if tag in ("glyf", "CFF "):
			table.toXML(writer, self, progress)
		else:
			table.toXML(writer, self)
		writer.endtag(xmlTag)
		writer.newline()
		writer.newline()

	def importXML(self, fileOrPath, progress=None, quiet=None):
		"""Import a TTX file (an XML-based text format), so as to recreate
		a font object.
		"""
		if quiet is not None:
			deprecateArgument("quiet", "configure logging instead")

		if "maxp" in self and "post" in self:
			# Make sure the glyph order is loaded, as it otherwise gets
			# lost if the XML doesn't contain the glyph order, yet does
			# contain the table which was originally used to extract the
			# glyph names from (ie. 'post', 'cmap' or 'CFF ').
			self.getGlyphOrder()

		from fontTools.misc import xmlReader

		reader = xmlReader.XMLReader(fileOrPath, self, progress)
		reader.read()

	def isLoaded(self, tag):
		"""Return true if the table identified by 'tag' has been
		decompiled and loaded into memory."""
		return tag in self.tables

	def has_key(self, tag):
		if self.isLoaded(tag):
			return True
		elif self.reader and tag in self.reader:
			return True
		elif tag == "GlyphOrder":
			return True
		else:
			return False

	__contains__ = has_key

	def keys(self):
		keys = list(self.tables.keys())
		if self.reader:
			for key in list(self.reader.keys()):
				if key not in keys:
					keys.append(key)

		if "GlyphOrder" in keys:
			keys.remove("GlyphOrder")
		keys = sortedTagList(keys)
		return ["GlyphOrder"] + keys

	def __len__(self):
		return len(list(self.keys()))

	def __getitem__(self, tag):
		tag = Tag(tag)
		try:
			return self.tables[tag]
		except KeyError:
			if tag == "GlyphOrder":
				table = GlyphOrder(tag)
				self.tables[tag] = table
				return table
			if self.reader is not None:
				import traceback
				log.debug("Reading '%s' table from disk", tag)
				data = self.reader[tag]
				tableClass = getTableClass(tag)
				table = tableClass(tag)
				self.tables[tag] = table
				log.debug("Decompiling '%s' table", tag)
				try:
					table.decompile(data, self)
				except:
					if not self.ignoreDecompileErrors:
						raise
					# fall back to DefaultTable, retaining the binary table data
					log.exception(
						"An exception occurred during the decompilation of the '%s' table", tag)
					from .tables.DefaultTable import DefaultTable
					file = StringIO()
					traceback.print_exc(file=file)
					table = DefaultTable(tag)
					table.ERROR = file.getvalue()
					self.tables[tag] = table
					table.decompile(data, self)
				return table
			else:
				raise KeyError("'%s' table not found" % tag)

	def __setitem__(self, tag, table):
		self.tables[Tag(tag)] = table

	def __delitem__(self, tag):
		if tag not in self:
			raise KeyError("'%s' table not found" % tag)
		if tag in self.tables:
			del self.tables[tag]
		if self.reader and tag in self.reader:
			del self.reader[tag]

	def get(self, tag, default=None):
		try:
			return self[tag]
		except KeyError:
			return default

	def setGlyphOrder(self, glyphOrder):
		self.glyphOrder = glyphOrder

	def getGlyphOrder(self):
		try:
			return self.glyphOrder
		except AttributeError:
			pass
		if 'CFF ' in self:
			cff = self['CFF ']
			self.glyphOrder = cff.getGlyphOrder()
		elif 'post' in self:
			# TrueType font
			glyphOrder = self['post'].getGlyphOrder()
			if glyphOrder is None:
				#
				# No names found in the 'post' table.
				# Try to create glyph names from the unicode cmap (if available)
				# in combination with the Adobe Glyph List (AGL).
				#
				self._getGlyphNamesFromCmap()
			else:
				self.glyphOrder = glyphOrder
		else:
			self._getGlyphNamesFromCmap()
		return self.glyphOrder

	def _getGlyphNamesFromCmap(self):
		#
		# This is rather convoluted, but then again, it's an interesting problem:
		# - we need to use the unicode values found in the cmap table to
		#   build glyph names (eg. because there is only a minimal post table,
		#   or none at all).
		# - but the cmap parser also needs glyph names to work with...
		# So here's what we do:
		# - make up glyph names based on glyphID
		# - load a temporary cmap table based on those names
		# - extract the unicode values, build the "real" glyph names
		# - unload the temporary cmap table
		#
		if self.isLoaded("cmap"):
			# Bootstrapping: we're getting called by the cmap parser
			# itself. This means self.tables['cmap'] contains a partially
			# loaded cmap, making it impossible to get at a unicode
			# subtable here. We remove the partially loaded cmap and
			# restore it later.
			# This only happens if the cmap table is loaded before any
			# other table that does f.getGlyphOrder()  or f.getGlyphName().
			cmapLoading = self.tables['cmap']
			del self.tables['cmap']
		else:
			cmapLoading = None
		# Make up glyph names based on glyphID, which will be used by the
		# temporary cmap and by the real cmap in case we don't find a unicode
		# cmap.
		numGlyphs = int(self['maxp'].numGlyphs)
		glyphOrder = [None] * numGlyphs
		glyphOrder[0] = ".notdef"
		for i in range(1, numGlyphs):
			glyphOrder[i] = "glyph%.5d" % i
		# Set the glyph order, so the cmap parser has something
		# to work with (so we don't get called recursively).
		self.glyphOrder = glyphOrder

		# Make up glyph names based on the reversed cmap table. Because some
		# glyphs (eg. ligatures or alternates) may not be reachable via cmap,
		# this naming table will usually not cover all glyphs in the font.
		# If the font has no Unicode cmap table, reversecmap will be empty.
		reversecmap = self['cmap'].buildReversed()
		useCount = {}
		for i in range(numGlyphs):
			tempName = glyphOrder[i]
			if tempName in reversecmap:
				# If a font maps both U+0041 LATIN CAPITAL LETTER A and
				# U+0391 GREEK CAPITAL LETTER ALPHA to the same glyph,
				# we prefer naming the glyph as "A".
				glyphName = self._makeGlyphName(min(reversecmap[tempName]))
				numUses = useCount[glyphName] = useCount.get(glyphName, 0) + 1
				if numUses > 1:
					glyphName = "%s.alt%d" % (glyphName, numUses - 1)
				glyphOrder[i] = glyphName

		# Delete the temporary cmap table from the cache, so it can
		# be parsed again with the right names.
		del self.tables['cmap']
		self.glyphOrder = glyphOrder
		if cmapLoading:
			# restore partially loaded cmap, so it can continue loading
			# using the proper names.
			self.tables['cmap'] = cmapLoading

	@staticmethod
	def _makeGlyphName(codepoint):
		from fontTools import agl  # Adobe Glyph List
		if codepoint in agl.UV2AGL:
			return agl.UV2AGL[codepoint]
		elif codepoint <= 0xFFFF:
			return "uni%04X" % codepoint
		else:
			return "u%X" % codepoint

	def getGlyphNames(self):
		"""Get a list of glyph names, sorted alphabetically."""
		glyphNames = sorted(self.getGlyphOrder()[:])
		return glyphNames

	def getGlyphNames2(self):
		"""Get a list of glyph names, sorted alphabetically,
		but not case sensitive.
		"""
		from fontTools.misc import textTools
		return textTools.caselessSort(self.getGlyphOrder())

	def getGlyphName(self, glyphID, requireReal=False):
		try:
			return self.getGlyphOrder()[glyphID]
		except IndexError:
			if requireReal or not self.allowVID:
				# XXX The ??.W8.otf font that ships with OSX uses higher glyphIDs in
				# the cmap table than there are glyphs. I don't think it's legal...
				return "glyph%.5d" % glyphID
			else:
				# user intends virtual GID support
				try:
					glyphName = self.VIDDict[glyphID]
				except KeyError:
					glyphName  ="glyph%.5d" % glyphID
					self.last_vid = min(glyphID, self.last_vid )
					self.reverseVIDDict[glyphName] = glyphID
					self.VIDDict[glyphID] = glyphName
				return glyphName

	def getGlyphID(self, glyphName, requireReal=False):
		if not hasattr(self, "_reverseGlyphOrderDict"):
			self._buildReverseGlyphOrderDict()
		glyphOrder = self.getGlyphOrder()
		d = self._reverseGlyphOrderDict
		if glyphName not in d:
			if glyphName in glyphOrder:
				self._buildReverseGlyphOrderDict()
				return self.getGlyphID(glyphName)
			else:
				if requireReal:
					raise KeyError(glyphName)
				elif not self.allowVID:
					# Handle glyphXXX only
					if glyphName[:5] == "glyph":
						try:
							return int(glyphName[5:])
						except (NameError, ValueError):
							raise KeyError(glyphName)
				else:
					# user intends virtual GID support
					try:
						glyphID = self.reverseVIDDict[glyphName]
					except KeyError:
						# if name is in glyphXXX format, use the specified name.
						if glyphName[:5] == "glyph":
							try:
								glyphID = int(glyphName[5:])
							except (NameError, ValueError):
								glyphID = None
						if glyphID is None:
							glyphID = self.last_vid -1
							self.last_vid = glyphID
						self.reverseVIDDict[glyphName] = glyphID
						self.VIDDict[glyphID] = glyphName
					return glyphID

		glyphID = d[glyphName]
		if glyphName != glyphOrder[glyphID]:
			self._buildReverseGlyphOrderDict()
			return self.getGlyphID(glyphName)
		return glyphID

	def getReverseGlyphMap(self, rebuild=False):
		if rebuild or not hasattr(self, "_reverseGlyphOrderDict"):
			self._buildReverseGlyphOrderDict()
		return self._reverseGlyphOrderDict

	def _buildReverseGlyphOrderDict(self):
		self._reverseGlyphOrderDict = d = {}
		glyphOrder = self.getGlyphOrder()
		for glyphID in range(len(glyphOrder)):
			d[glyphOrder[glyphID]] = glyphID

	def _writeTable(self, tag, writer, done):
		"""Internal helper function for self.save(). Keeps track of
		inter-table dependencies.
		"""
		if tag in done:
			return
		tableClass = getTableClass(tag)
		for masterTable in tableClass.dependencies:
			if masterTable not in done:
				if masterTable in self:
					self._writeTable(masterTable, writer, done)
				else:
					done.append(masterTable)
		tabledata = self.getTableData(tag)
		log.debug("writing '%s' table to disk", tag)
		writer[tag] = tabledata
		done.append(tag)

	def getTableData(self, tag):
		"""Returns raw table data, whether compiled or directly read from disk.
		"""
		tag = Tag(tag)
		if self.isLoaded(tag):
			log.debug("compiling '%s' table", tag)
			return self.tables[tag].compile(self)
		elif self.reader and tag in self.reader:
			log.debug("Reading '%s' table from disk", tag)
			return self.reader[tag]
		else:
			raise KeyError(tag)

	def getGlyphSet(self, preferCFF=True):
		"""Return a generic GlyphSet, which is a dict-like object
		mapping glyph names to glyph objects. The returned glyph objects
		have a .draw() method that supports the Pen protocol, and will
		have an attribute named 'width'.

		If the font is CFF-based, the outlines will be taken from the 'CFF '
		table. Otherwise the outlines will be taken from the 'glyf' table.
		If the font contains both a 'CFF ' and a 'glyf' table, you can use
		the 'preferCFF' argument to specify which one should be taken.
		"""
		glyphs = None
		if (preferCFF and "CFF " in self) or "glyf" not in self:
			glyphs = _TTGlyphSet(self, list(self["CFF "].cff.values())[0].CharStrings, _TTGlyphCFF)

		if glyphs is None and "glyf" in self:
			glyphs = _TTGlyphSet(self, self["glyf"], _TTGlyphGlyf)

		if glyphs is None:
			raise TTLibError("Font contains no outlines")

		return glyphs


class _TTGlyphSet(object):

	"""Generic dict-like GlyphSet class that pulls metrics from hmtx and
	glyph shape from TrueType or CFF.
	"""

	def __init__(self, ttFont, glyphs, glyphType):
		self._glyphs = glyphs
		self._hmtx = ttFont['hmtx']
		self._glyphType = glyphType

	def keys(self):
		return list(self._glyphs.keys())

	def has_key(self, glyphName):
		return glyphName in self._glyphs

	__contains__ = has_key

	def __getitem__(self, glyphName):
		return self._glyphType(self, self._glyphs[glyphName], self._hmtx[glyphName])

	def get(self, glyphName, default=None):
		try:
			return self[glyphName]
		except KeyError:
			return default

class _TTGlyph(object):

	"""Wrapper for a TrueType glyph that supports the Pen protocol, meaning
	that it has a .draw() method that takes a pen object as its only
	argument. Additionally there is a 'width' attribute.
	"""

	def __init__(self, glyphset, glyph, metrics):
		self._glyphset = glyphset
		self._glyph = glyph
		self.width, self.lsb = metrics

	def draw(self, pen):
		"""Draw the glyph onto Pen. See fontTools.pens.basePen for details
		how that works.
		"""
		self._glyph.draw(pen)

class _TTGlyphCFF(_TTGlyph):
	pass

class _TTGlyphGlyf(_TTGlyph):

	def draw(self, pen):
		"""Draw the glyph onto Pen. See fontTools.pens.basePen for details
		how that works.
		"""
		glyfTable = self._glyphset._glyphs
		glyph = self._glyph
		offset = self.lsb - glyph.xMin if hasattr(glyph, "xMin") else 0
		glyph.draw(pen, glyfTable, offset)


class GlyphOrder(object):

	"""A pseudo table. The glyph order isn't in the font as a separate
	table, but it's nice to present it as such in the TTX format.
	"""

	def __init__(self, tag=None):
		pass

	def toXML(self, writer, ttFont):
		glyphOrder = ttFont.getGlyphOrder()
		writer.comment("The 'id' attribute is only for humans; "
				"it is ignored when parsed.")
		writer.newline()
		for i in range(len(glyphOrder)):
			glyphName = glyphOrder[i]
			writer.simpletag("GlyphID", id=i, name=glyphName)
			writer.newline()

	def fromXML(self, name, attrs, content, ttFont):
		if not hasattr(self, "glyphOrder"):
			self.glyphOrder = []
			ttFont.setGlyphOrder(self.glyphOrder)
		if name == "GlyphID":
			self.glyphOrder.append(attrs["name"])


def getTableModule(tag):
	"""Fetch the packer/unpacker module for a table.
	Return None when no module is found.
	"""
	from . import tables
	pyTag = tagToIdentifier(tag)
	try:
		__import__("fontTools.ttLib.tables." + pyTag)
	except ImportError as err:
		# If pyTag is found in the ImportError message,
		# means table is not implemented.  If it's not
		# there, then some other module is missing, don't
		# suppress the error.
		if str(err).find(pyTag) >= 0:
			return None
		else:
			raise err
	else:
		return getattr(tables, pyTag)


def getTableClass(tag):
	"""Fetch the packer/unpacker class for a table.
	Return None when no class is found.
	"""
	module = getTableModule(tag)
	if module is None:
		from .tables.DefaultTable import DefaultTable
		return DefaultTable
	pyTag = tagToIdentifier(tag)
	tableClass = getattr(module, "table_" + pyTag)
	return tableClass


def getClassTag(klass):
	"""Fetch the table tag for a class object."""
	name = klass.__name__
	assert name[:6] == 'table_'
	name = name[6:] # Chop 'table_'
	return identifierToTag(name)


def newTable(tag):
	"""Return a new instance of a table."""
	tableClass = getTableClass(tag)
	return tableClass(tag)


def _escapechar(c):
	"""Helper function for tagToIdentifier()"""
	import re
	if re.match("[a-z0-9]", c):
		return "_" + c
	elif re.match("[A-Z]", c):
		return c + "_"
	else:
		return hex(byteord(c))[2:]


def tagToIdentifier(tag):
	"""Convert a table tag to a valid (but UGLY) python identifier,
	as well as a filename that's guaranteed to be unique even on a
	caseless file system. Each character is mapped to two characters.
	Lowercase letters get an underscore before the letter, uppercase
	letters get an underscore after the letter. Trailing spaces are
	trimmed. Illegal characters are escaped as two hex bytes. If the
	result starts with a number (as the result of a hex escape), an
	extra underscore is prepended. Examples:
		'glyf' -> '_g_l_y_f'
		'cvt ' -> '_c_v_t'
		'OS/2' -> 'O_S_2f_2'
	"""
	import re
	tag = Tag(tag)
	if tag == "GlyphOrder":
		return tag
	assert len(tag) == 4, "tag should be 4 characters long"
	while len(tag) > 1 and tag[-1] == ' ':
		tag = tag[:-1]
	ident = ""
	for c in tag:
		ident = ident + _escapechar(c)
	if re.match("[0-9]", ident):
		ident = "_" + ident
	return ident


def identifierToTag(ident):
	"""the opposite of tagToIdentifier()"""
	if ident == "GlyphOrder":
		return ident
	if len(ident) % 2 and ident[0] == "_":
		ident = ident[1:]
	assert not (len(ident) % 2)
	tag = ""
	for i in range(0, len(ident), 2):
		if ident[i] == "_":
			tag = tag + ident[i+1]
		elif ident[i+1] == "_":
			tag = tag + ident[i]
		else:
			# assume hex
			tag = tag + chr(int(ident[i:i+2], 16))
	# append trailing spaces
	tag = tag + (4 - len(tag)) * ' '
	return Tag(tag)


def tagToXML(tag):
	"""Similarly to tagToIdentifier(), this converts a TT tag
	to a valid XML element name. Since XML element names are
	case sensitive, this is a fairly simple/readable translation.
	"""
	import re
	tag = Tag(tag)
	if tag == "OS/2":
		return "OS_2"
	elif tag == "GlyphOrder":
		return tag
	if re.match("[A-Za-z_][A-Za-z_0-9]* *$", tag):
		return tag.strip()
	else:
		return tagToIdentifier(tag)


def xmlToTag(tag):
	"""The opposite of tagToXML()"""
	if tag == "OS_2":
		return Tag("OS/2")
	if len(tag) == 8:
		return identifierToTag(tag)
	else:
		return Tag(tag + " " * (4 - len(tag)))


@deprecateFunction("use logging instead", category=DeprecationWarning)
def debugmsg(msg):
	import time
	print(msg + time.strftime("  (%H:%M:%S)", time.localtime(time.time())))


# Table order as recommended in the OpenType specification 1.4
TTFTableOrder = ["head", "hhea", "maxp", "OS/2", "hmtx", "LTSH", "VDMX",
				"hdmx", "cmap", "fpgm", "prep", "cvt ", "loca", "glyf",
				"kern", "name", "post", "gasp", "PCLT"]

OTFTableOrder = ["head", "hhea", "maxp", "OS/2", "name", "cmap", "post",
				"CFF "]

def sortedTagList(tagList, tableOrder=None):
	"""Return a sorted copy of tagList, sorted according to the OpenType
	specification, or according to a custom tableOrder. If given and not
	None, tableOrder needs to be a list of tag names.
	"""
	tagList = sorted(tagList)
	if tableOrder is None:
		if "DSIG" in tagList:
			# DSIG should be last (XXX spec reference?)
			tagList.remove("DSIG")
			tagList.append("DSIG")
		if "CFF " in tagList:
			tableOrder = OTFTableOrder
		else:
			tableOrder = TTFTableOrder
	orderedTables = []
	for tag in tableOrder:
		if tag in tagList:
			orderedTables.append(tag)
			tagList.remove(tag)
	orderedTables.extend(tagList)
	return orderedTables


def reorderFontTables(inFile, outFile, tableOrder=None, checkChecksums=False):
	"""Rewrite a font file, ordering the tables as recommended by the
	OpenType specification 1.4.
	"""
	from fontTools.ttLib.sfnt import SFNTReader, SFNTWriter
	reader = SFNTReader(inFile, checkChecksums=checkChecksums)
	writer = SFNTWriter(outFile, len(reader.tables), reader.sfntVersion, reader.flavor, reader.flavorData)
	tables = list(reader.keys())
	for tag in sortedTagList(tables, tableOrder):
		writer[tag] = reader[tag]
	writer.close()


def maxPowerOfTwo(x):
	"""Return the highest exponent of two, so that
	(2 ** exponent) <= x.  Return 0 if x is 0.
	"""
	exponent = 0
	while x:
		x = x >> 1
		exponent = exponent + 1
	return max(exponent - 1, 0)


def getSearchRange(n, itemSize=16):
	"""Calculate searchRange, entrySelector, rangeShift.
	"""
	# itemSize defaults to 16, for backward compatibility
	# with upstream fonttools.
	exponent = maxPowerOfTwo(n)
	searchRange = (2 ** exponent) * itemSize
	entrySelector = exponent
	rangeShift = max(0, n * itemSize - searchRange)
	return searchRange, entrySelector, rangeShift
