"""_g_l_y_f.py -- Converter classes for the 'glyf' table."""

from __future__ import print_function, division, absolute_import
from collections import namedtuple
from fontTools.misc.py23 import *
from fontTools.misc import sstruct
from fontTools import ttLib
from fontTools import version
from fontTools.misc.textTools import safeEval, pad
from fontTools.misc.arrayTools import calcBounds, calcIntBounds, pointInRect
from fontTools.misc.bezierTools import calcQuadraticBounds
from fontTools.misc.fixedTools import (
	fixedToFloat as fi2fl,
	floatToFixed as fl2fi,
	otRound,
)
from numbers import Number
from . import DefaultTable
from . import ttProgram
import sys
import struct
import array
import logging
import os
from fontTools.misc import xmlWriter
from fontTools.misc.filenames import userNameToFileName

log = logging.getLogger(__name__)

# We compute the version the same as is computed in ttlib/__init__
# so that we can write 'ttLibVersion' attribute of the glyf TTX files
# when glyf is written to separate files.
version = ".".join(version.split('.')[:2])

#
# The Apple and MS rasterizers behave differently for
# scaled composite components: one does scale first and then translate
# and the other does it vice versa. MS defined some flags to indicate
# the difference, but it seems nobody actually _sets_ those flags.
#
# Funny thing: Apple seems to _only_ do their thing in the
# WE_HAVE_A_SCALE (eg. Chicago) case, and not when it's WE_HAVE_AN_X_AND_Y_SCALE
# (eg. Charcoal)...
#
SCALE_COMPONENT_OFFSET_DEFAULT = 0   # 0 == MS, 1 == Apple


class table__g_l_y_f(DefaultTable.DefaultTable):

	# this attribute controls the amount of padding applied to glyph data upon compile.
	# Glyph lenghts are aligned to multiples of the specified value. 
	# Allowed values are (0, 1, 2, 4). '0' means no padding; '1' (default) also means
	# no padding, except for when padding would allow to use short loca offsets.
	padding = 1

	def decompile(self, data, ttFont):
		loca = ttFont['loca']
		last = int(loca[0])
		noname = 0
		self.glyphs = {}
		self.glyphOrder = glyphOrder = ttFont.getGlyphOrder()
		for i in range(0, len(loca)-1):
			try:
				glyphName = glyphOrder[i]
			except IndexError:
				noname = noname + 1
				glyphName = 'ttxautoglyph%s' % i
			next = int(loca[i+1])
			glyphdata = data[last:next]
			if len(glyphdata) != (next - last):
				raise ttLib.TTLibError("not enough 'glyf' table data")
			glyph = Glyph(glyphdata)
			self.glyphs[glyphName] = glyph
			last = next
		if len(data) - next >= 4:
			log.warning(
				"too much 'glyf' table data: expected %d, received %d bytes",
				next, len(data))
		if noname:
			log.warning('%s glyphs have no name', noname)
		if ttFont.lazy is False: # Be lazy for None and True
			for glyph in self.glyphs.values():
				glyph.expand(self)

	def compile(self, ttFont):
		if not hasattr(self, "glyphOrder"):
			self.glyphOrder = ttFont.getGlyphOrder()
		padding = self.padding
		assert padding in (0, 1, 2, 4)
		locations = []
		currentLocation = 0
		dataList = []
		recalcBBoxes = ttFont.recalcBBoxes
		for glyphName in self.glyphOrder:
			glyph = self.glyphs[glyphName]
			glyphData = glyph.compile(self, recalcBBoxes)
			if padding > 1:
				glyphData = pad(glyphData, size=padding)
			locations.append(currentLocation)
			currentLocation = currentLocation + len(glyphData)
			dataList.append(glyphData)
		locations.append(currentLocation)

		if padding == 1 and currentLocation < 0x20000:
			# See if we can pad any odd-lengthed glyphs to allow loca
			# table to use the short offsets.
			indices = [i for i,glyphData in enumerate(dataList) if len(glyphData) % 2 == 1]
			if indices and currentLocation + len(indices) < 0x20000:
				# It fits.  Do it.
				for i in indices:
					dataList[i] += b'\0'
				currentLocation = 0
				for i,glyphData in enumerate(dataList):
					locations[i] = currentLocation
					currentLocation += len(glyphData)
				locations[len(dataList)] = currentLocation

		data = bytesjoin(dataList)
		if 'loca' in ttFont:
			ttFont['loca'].set(locations)
		if 'maxp' in ttFont:
			ttFont['maxp'].numGlyphs = len(self.glyphs)
		return data

	def toXML(self, writer, ttFont, splitGlyphs=False):
		notice = (
			"The xMin, yMin, xMax and yMax values\n"
			"will be recalculated by the compiler.")
		glyphNames = ttFont.getGlyphNames()
		if not splitGlyphs:
			writer.newline()
			writer.comment(notice)
			writer.newline()
			writer.newline()
		numGlyphs = len(glyphNames)
		if splitGlyphs:
			path, ext = os.path.splitext(writer.file.name)
			existingGlyphFiles = set()
		for glyphName in glyphNames:
			glyph = self[glyphName]
			if glyph.numberOfContours:
				if splitGlyphs:
					glyphPath = userNameToFileName(
						tounicode(glyphName, 'utf-8'),
						existingGlyphFiles,
						prefix=path + ".",
						suffix=ext)
					existingGlyphFiles.add(glyphPath.lower())
					glyphWriter = xmlWriter.XMLWriter(
						glyphPath, idlefunc=writer.idlefunc,
						newlinestr=writer.newlinestr)
					glyphWriter.begintag("ttFont", ttLibVersion=version)
					glyphWriter.newline()
					glyphWriter.begintag("glyf")
					glyphWriter.newline()
					glyphWriter.comment(notice)
					glyphWriter.newline()
					writer.simpletag("TTGlyph", src=os.path.basename(glyphPath))
				else:
					glyphWriter = writer
				glyphWriter.begintag('TTGlyph', [
							("name", glyphName),
							("xMin", glyph.xMin),
							("yMin", glyph.yMin),
							("xMax", glyph.xMax),
							("yMax", glyph.yMax),
							])
				glyphWriter.newline()
				glyph.toXML(glyphWriter, ttFont)
				glyphWriter.endtag('TTGlyph')
				glyphWriter.newline()
				if splitGlyphs:
					glyphWriter.endtag("glyf")
					glyphWriter.newline()
					glyphWriter.endtag("ttFont")
					glyphWriter.newline()
					glyphWriter.close()
			else:
				writer.simpletag('TTGlyph', name=glyphName)
				writer.comment("contains no outline data")
				if not splitGlyphs:
					writer.newline()
			writer.newline()

	def fromXML(self, name, attrs, content, ttFont):
		if name != "TTGlyph":
			return
		if not hasattr(self, "glyphs"):
			self.glyphs = {}
		if not hasattr(self, "glyphOrder"):
			self.glyphOrder = ttFont.getGlyphOrder()
		glyphName = attrs["name"]
		log.debug("unpacking glyph '%s'", glyphName)
		glyph = Glyph()
		for attr in ['xMin', 'yMin', 'xMax', 'yMax']:
			setattr(glyph, attr, safeEval(attrs.get(attr, '0')))
		self.glyphs[glyphName] = glyph
		for element in content:
			if not isinstance(element, tuple):
				continue
			name, attrs, content = element
			glyph.fromXML(name, attrs, content, ttFont)
		if not ttFont.recalcBBoxes:
			glyph.compact(self, 0)

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

	def getGlyphName(self, glyphID):
		return self.glyphOrder[glyphID]

	def getGlyphID(self, glyphName):
		# XXX optimize with reverse dict!!!
		return self.glyphOrder.index(glyphName)

	def removeHinting(self):
		for glyph in self.glyphs.values():
			glyph.removeHinting()

	def keys(self):
		return self.glyphs.keys()

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

	__contains__ = has_key

	def __getitem__(self, glyphName):
		glyph = self.glyphs[glyphName]
		glyph.expand(self)
		return glyph

	def __setitem__(self, glyphName, glyph):
		self.glyphs[glyphName] = glyph
		if glyphName not in self.glyphOrder:
			self.glyphOrder.append(glyphName)

	def __delitem__(self, glyphName):
		del self.glyphs[glyphName]
		self.glyphOrder.remove(glyphName)

	def __len__(self):
		assert len(self.glyphOrder) == len(self.glyphs)
		return len(self.glyphs)


glyphHeaderFormat = """
		>	# big endian
		numberOfContours:	h
		xMin:				h
		yMin:				h
		xMax:				h
		yMax:				h
"""

# flags
flagOnCurve = 0x01
flagXShort = 0x02
flagYShort = 0x04
flagRepeat = 0x08
flagXsame =  0x10
flagYsame = 0x20
flagOverlapSimple = 0x40
flagReserved = 0x80

# These flags are kept for XML output after decompiling the coordinates
keepFlags = flagOnCurve + flagOverlapSimple

_flagSignBytes = {
	0: 2,
	flagXsame: 0,
	flagXShort|flagXsame: +1,
	flagXShort: -1,
	flagYsame: 0,
	flagYShort|flagYsame: +1,
	flagYShort: -1,
}

def flagBest(x, y, onCurve):
	"""For a given x,y delta pair, returns the flag that packs this pair
	most efficiently, as well as the number of byte cost of such flag."""

	flag = flagOnCurve if onCurve else 0
	cost = 0
	# do x
	if x == 0:
		flag = flag | flagXsame
	elif -255 <= x <= 255:
		flag = flag | flagXShort
		if x > 0:
			flag = flag | flagXsame
		cost += 1
	else:
		cost += 2
	# do y
	if y == 0:
		flag = flag | flagYsame
	elif -255 <= y <= 255:
		flag = flag | flagYShort
		if y > 0:
			flag = flag | flagYsame
		cost += 1
	else:
		cost += 2
	return flag, cost

def flagFits(newFlag, oldFlag, mask):
	newBytes = _flagSignBytes[newFlag & mask]
	oldBytes = _flagSignBytes[oldFlag & mask]
	return newBytes == oldBytes or abs(newBytes) > abs(oldBytes)

def flagSupports(newFlag, oldFlag):
	return ((oldFlag & flagOnCurve) == (newFlag & flagOnCurve) and
		flagFits(newFlag, oldFlag, flagXsame|flagXShort) and
		flagFits(newFlag, oldFlag, flagYsame|flagYShort))

def flagEncodeCoord(flag, mask, coord, coordBytes):
	byteCount = _flagSignBytes[flag & mask]
	if byteCount == 1:
		coordBytes.append(coord)
	elif byteCount == -1:
		coordBytes.append(-coord)
	elif byteCount == 2:
		coordBytes.append((coord >> 8) & 0xFF)
		coordBytes.append(coord & 0xFF)

def flagEncodeCoords(flag, x, y, xBytes, yBytes):
	flagEncodeCoord(flag, flagXsame|flagXShort, x, xBytes)
	flagEncodeCoord(flag, flagYsame|flagYShort, y, yBytes)


ARG_1_AND_2_ARE_WORDS		= 0x0001  # if set args are words otherwise they are bytes
ARGS_ARE_XY_VALUES		= 0x0002  # if set args are xy values, otherwise they are points
ROUND_XY_TO_GRID		= 0x0004  # for the xy values if above is true
WE_HAVE_A_SCALE			= 0x0008  # Sx = Sy, otherwise scale == 1.0
NON_OVERLAPPING			= 0x0010  # set to same value for all components (obsolete!)
MORE_COMPONENTS			= 0x0020  # indicates at least one more glyph after this one
WE_HAVE_AN_X_AND_Y_SCALE	= 0x0040  # Sx, Sy
WE_HAVE_A_TWO_BY_TWO		= 0x0080  # t00, t01, t10, t11
WE_HAVE_INSTRUCTIONS		= 0x0100  # instructions follow
USE_MY_METRICS			= 0x0200  # apply these metrics to parent glyph
OVERLAP_COMPOUND		= 0x0400  # used by Apple in GX fonts
SCALED_COMPONENT_OFFSET		= 0x0800  # composite designed to have the component offset scaled (designed for Apple)
UNSCALED_COMPONENT_OFFSET	= 0x1000  # composite designed not to have the component offset scaled (designed for MS)


CompositeMaxpValues = namedtuple('CompositeMaxpValues', ['nPoints', 'nContours', 'maxComponentDepth'])


class Glyph(object):

	def __init__(self, data=""):
		if not data:
			# empty char
			self.numberOfContours = 0
			return
		self.data = data

	def compact(self, glyfTable, recalcBBoxes=True):
		data = self.compile(glyfTable, recalcBBoxes)
		self.__dict__.clear()
		self.data = data

	def expand(self, glyfTable):
		if not hasattr(self, "data"):
			# already unpacked
			return
		if not self.data:
			# empty char
			del self.data
			self.numberOfContours = 0
			return
		dummy, data = sstruct.unpack2(glyphHeaderFormat, self.data, self)
		del self.data
		# Some fonts (eg. Neirizi.ttf) have a 0 for numberOfContours in
		# some glyphs; decompileCoordinates assumes that there's at least
		# one, so short-circuit here.
		if self.numberOfContours == 0:
			return
		if self.isComposite():
			self.decompileComponents(data, glyfTable)
		else:
			self.decompileCoordinates(data)

	def compile(self, glyfTable, recalcBBoxes=True):
		if hasattr(self, "data"):
			if recalcBBoxes:
				# must unpack glyph in order to recalculate bounding box
				self.expand(glyfTable)
			else:
				return self.data
		if self.numberOfContours == 0:
			return ""
		if recalcBBoxes:
			self.recalcBounds(glyfTable)
		data = sstruct.pack(glyphHeaderFormat, self)
		if self.isComposite():
			data = data + self.compileComponents(glyfTable)
		else:
			data = data + self.compileCoordinates()
		return data

	def toXML(self, writer, ttFont):
		if self.isComposite():
			for compo in self.components:
				compo.toXML(writer, ttFont)
			haveInstructions = hasattr(self, "program")
		else:
			last = 0
			for i in range(self.numberOfContours):
				writer.begintag("contour")
				writer.newline()
				for j in range(last, self.endPtsOfContours[i] + 1):
					attrs = [
							("x", self.coordinates[j][0]),
							("y", self.coordinates[j][1]),
							("on", self.flags[j] & flagOnCurve),
						]
					if self.flags[j] & flagOverlapSimple:
						# Apple's rasterizer uses flagOverlapSimple in the first contour/first pt to flag glyphs that contain overlapping contours
						attrs.append(("overlap", 1))
					writer.simpletag("pt", attrs)
					writer.newline()
				last = self.endPtsOfContours[i] + 1
				writer.endtag("contour")
				writer.newline()
			haveInstructions = self.numberOfContours > 0
		if haveInstructions:
			if self.program:
				writer.begintag("instructions")
				writer.newline()
				self.program.toXML(writer, ttFont)
				writer.endtag("instructions")
			else:
				writer.simpletag("instructions")
			writer.newline()

	def fromXML(self, name, attrs, content, ttFont):
		if name == "contour":
			if self.numberOfContours < 0:
				raise ttLib.TTLibError("can't mix composites and contours in glyph")
			self.numberOfContours = self.numberOfContours + 1
			coordinates = GlyphCoordinates()
			flags = []
			for element in content:
				if not isinstance(element, tuple):
					continue
				name, attrs, content = element
				if name != "pt":
					continue  # ignore anything but "pt"
				coordinates.append((safeEval(attrs["x"]), safeEval(attrs["y"])))
				flag = not not safeEval(attrs["on"])
				if "overlap" in attrs and bool(safeEval(attrs["overlap"])):
					flag |= flagOverlapSimple
				flags.append(flag)
			flags = array.array("B", flags)
			if not hasattr(self, "coordinates"):
				self.coordinates = coordinates
				self.flags = flags
				self.endPtsOfContours = [len(coordinates)-1]
			else:
				self.coordinates.extend (coordinates)
				self.flags.extend(flags)
				self.endPtsOfContours.append(len(self.coordinates)-1)
		elif name == "component":
			if self.numberOfContours > 0:
				raise ttLib.TTLibError("can't mix composites and contours in glyph")
			self.numberOfContours = -1
			if not hasattr(self, "components"):
				self.components = []
			component = GlyphComponent()
			self.components.append(component)
			component.fromXML(name, attrs, content, ttFont)
		elif name == "instructions":
			self.program = ttProgram.Program()
			for element in content:
				if not isinstance(element, tuple):
					continue
				name, attrs, content = element
				self.program.fromXML(name, attrs, content, ttFont)

	def getCompositeMaxpValues(self, glyfTable, maxComponentDepth=1):
		assert self.isComposite()
		nContours = 0
		nPoints = 0
		for compo in self.components:
			baseGlyph = glyfTable[compo.glyphName]
			if baseGlyph.numberOfContours == 0:
				continue
			elif baseGlyph.numberOfContours > 0:
				nP, nC = baseGlyph.getMaxpValues()
			else:
				nP, nC, maxComponentDepth = baseGlyph.getCompositeMaxpValues(
						glyfTable, maxComponentDepth + 1)
			nPoints = nPoints + nP
			nContours = nContours + nC
		return CompositeMaxpValues(nPoints, nContours, maxComponentDepth)

	def getMaxpValues(self):
		assert self.numberOfContours > 0
		return len(self.coordinates), len(self.endPtsOfContours)

	def decompileComponents(self, data, glyfTable):
		self.components = []
		more = 1
		haveInstructions = 0
		while more:
			component = GlyphComponent()
			more, haveInstr, data = component.decompile(data, glyfTable)
			haveInstructions = haveInstructions | haveInstr
			self.components.append(component)
		if haveInstructions:
			numInstructions, = struct.unpack(">h", data[:2])
			data = data[2:]
			self.program = ttProgram.Program()
			self.program.fromBytecode(data[:numInstructions])
			data = data[numInstructions:]
			if len(data) >= 4:
				log.warning(
					"too much glyph data at the end of composite glyph: %d excess bytes",
					len(data))

	def decompileCoordinates(self, data):
		endPtsOfContours = array.array("h")
		endPtsOfContours.fromstring(data[:2*self.numberOfContours])
		if sys.byteorder != "big": endPtsOfContours.byteswap()
		self.endPtsOfContours = endPtsOfContours.tolist()

		data = data[2*self.numberOfContours:]

		instructionLength, = struct.unpack(">h", data[:2])
		data = data[2:]
		self.program = ttProgram.Program()
		self.program.fromBytecode(data[:instructionLength])
		data = data[instructionLength:]
		nCoordinates = self.endPtsOfContours[-1] + 1
		flags, xCoordinates, yCoordinates = \
				self.decompileCoordinatesRaw(nCoordinates, data)

		# fill in repetitions and apply signs
		self.coordinates = coordinates = GlyphCoordinates.zeros(nCoordinates)
		xIndex = 0
		yIndex = 0
		for i in range(nCoordinates):
			flag = flags[i]
			# x coordinate
			if flag & flagXShort:
				if flag & flagXsame:
					x = xCoordinates[xIndex]
				else:
					x = -xCoordinates[xIndex]
				xIndex = xIndex + 1
			elif flag & flagXsame:
				x = 0
			else:
				x = xCoordinates[xIndex]
				xIndex = xIndex + 1
			# y coordinate
			if flag & flagYShort:
				if flag & flagYsame:
					y = yCoordinates[yIndex]
				else:
					y = -yCoordinates[yIndex]
				yIndex = yIndex + 1
			elif flag & flagYsame:
				y = 0
			else:
				y = yCoordinates[yIndex]
				yIndex = yIndex + 1
			coordinates[i] = (x, y)
		assert xIndex == len(xCoordinates)
		assert yIndex == len(yCoordinates)
		coordinates.relativeToAbsolute()
		# discard all flags except "keepFlags"
		self.flags = array.array("B", (f & keepFlags for f in flags))

	def decompileCoordinatesRaw(self, nCoordinates, data):
		# unpack flags and prepare unpacking of coordinates
		flags = array.array("B", [0] * nCoordinates)
		# Warning: deep Python trickery going on. We use the struct module to unpack
		# the coordinates. We build a format string based on the flags, so we can
		# unpack the coordinates in one struct.unpack() call.
		xFormat = ">" # big endian
		yFormat = ">" # big endian
		i = j = 0
		while True:
			flag = byteord(data[i])
			i = i + 1
			repeat = 1
			if flag & flagRepeat:
				repeat = byteord(data[i]) + 1
				i = i + 1
			for k in range(repeat):
				if flag & flagXShort:
					xFormat = xFormat + 'B'
				elif not (flag & flagXsame):
					xFormat = xFormat + 'h'
				if flag & flagYShort:
					yFormat = yFormat + 'B'
				elif not (flag & flagYsame):
					yFormat = yFormat + 'h'
				flags[j] = flag
				j = j + 1
			if j >= nCoordinates:
				break
		assert j == nCoordinates, "bad glyph flags"
		data = data[i:]
		# unpack raw coordinates, krrrrrr-tching!
		xDataLen = struct.calcsize(xFormat)
		yDataLen = struct.calcsize(yFormat)
		if len(data) - (xDataLen + yDataLen) >= 4:
			log.warning(
				"too much glyph data: %d excess bytes", len(data) - (xDataLen + yDataLen))
		xCoordinates = struct.unpack(xFormat, data[:xDataLen])
		yCoordinates = struct.unpack(yFormat, data[xDataLen:xDataLen+yDataLen])
		return flags, xCoordinates, yCoordinates

	def compileComponents(self, glyfTable):
		data = b""
		lastcomponent = len(self.components) - 1
		more = 1
		haveInstructions = 0
		for i in range(len(self.components)):
			if i == lastcomponent:
				haveInstructions = hasattr(self, "program")
				more = 0
			compo = self.components[i]
			data = data + compo.compile(more, haveInstructions, glyfTable)
		if haveInstructions:
			instructions = self.program.getBytecode()
			data = data + struct.pack(">h", len(instructions)) + instructions
		return data

	def compileCoordinates(self):
		assert len(self.coordinates) == len(self.flags)
		data = []
		endPtsOfContours = array.array("h", self.endPtsOfContours)
		if sys.byteorder != "big": endPtsOfContours.byteswap()
		data.append(endPtsOfContours.tostring())
		instructions = self.program.getBytecode()
		data.append(struct.pack(">h", len(instructions)))
		data.append(instructions)

		deltas = self.coordinates.copy()
		if deltas.isFloat():
			# Warn?
			deltas.toInt()
		deltas.absoluteToRelative()

		# TODO(behdad): Add a configuration option for this?
		deltas = self.compileDeltasGreedy(self.flags, deltas)
		#deltas = self.compileDeltasOptimal(self.flags, deltas)

		data.extend(deltas)
		return bytesjoin(data)

	def compileDeltasGreedy(self, flags, deltas):
		# Implements greedy algorithm for packing coordinate deltas:
		# uses shortest representation one coordinate at a time.
		compressedflags = []
		xPoints = []
		yPoints = []
		lastflag = None
		repeat = 0
		for flag,(x,y) in zip(flags, deltas):
			# Oh, the horrors of TrueType
			# do x
			if x == 0:
				flag = flag | flagXsame
			elif -255 <= x <= 255:
				flag = flag | flagXShort
				if x > 0:
					flag = flag | flagXsame
				else:
					x = -x
				xPoints.append(bytechr(x))
			else:
				xPoints.append(struct.pack(">h", x))
			# do y
			if y == 0:
				flag = flag | flagYsame
			elif -255 <= y <= 255:
				flag = flag | flagYShort
				if y > 0:
					flag = flag | flagYsame
				else:
					y = -y
				yPoints.append(bytechr(y))
			else:
				yPoints.append(struct.pack(">h", y))
			# handle repeating flags
			if flag == lastflag and repeat != 255:
				repeat = repeat + 1
				if repeat == 1:
					compressedflags.append(flag)
				else:
					compressedflags[-2] = flag | flagRepeat
					compressedflags[-1] = repeat
			else:
				repeat = 0
				compressedflags.append(flag)
			lastflag = flag
		compressedFlags = array.array("B", compressedflags).tostring()
		compressedXs = bytesjoin(xPoints)
		compressedYs = bytesjoin(yPoints)
		return (compressedFlags, compressedXs, compressedYs)

	def compileDeltasOptimal(self, flags, deltas):
		# Implements optimal, dynaic-programming, algorithm for packing coordinate
		# deltas.  The savings are negligible :(.
		candidates = []
		bestTuple = None
		bestCost = 0
		repeat = 0
		for flag,(x,y) in zip(flags, deltas):
			# Oh, the horrors of TrueType
			flag, coordBytes = flagBest(x, y, flag)
			bestCost += 1 + coordBytes
			newCandidates = [(bestCost, bestTuple, flag, coordBytes),
							(bestCost+1, bestTuple, (flag|flagRepeat), coordBytes)]
			for lastCost,lastTuple,lastFlag,coordBytes in candidates:
				if lastCost + coordBytes <= bestCost + 1 and (lastFlag & flagRepeat) and (lastFlag < 0xff00) and flagSupports(lastFlag, flag):
					if (lastFlag & 0xFF) == (flag|flagRepeat) and lastCost == bestCost + 1:
						continue
					newCandidates.append((lastCost + coordBytes, lastTuple, lastFlag+256, coordBytes))
			candidates = newCandidates
			bestTuple = min(candidates, key=lambda t:t[0])
			bestCost = bestTuple[0]

		flags = []
		while bestTuple:
			cost, bestTuple, flag, coordBytes = bestTuple
			flags.append(flag)
		flags.reverse()

		compressedFlags = array.array("B")
		compressedXs = array.array("B")
		compressedYs = array.array("B")
		coords = iter(deltas)
		ff = []
		for flag in flags:
			repeatCount, flag = flag >> 8, flag & 0xFF
			compressedFlags.append(flag)
			if flag & flagRepeat:
				assert(repeatCount > 0)
				compressedFlags.append(repeatCount)
			else:
				assert(repeatCount == 0)
			for i in range(1 + repeatCount):
				x,y = next(coords)
				flagEncodeCoords(flag, x, y, compressedXs, compressedYs)
				ff.append(flag)
		try:
			next(coords)
			raise Exception("internal error")
		except StopIteration:
			pass
		compressedFlags = compressedFlags.tostring()
		compressedXs = compressedXs.tostring()
		compressedYs = compressedYs.tostring()

		return (compressedFlags, compressedXs, compressedYs)

	def recalcBounds(self, glyfTable):
		coords, endPts, flags = self.getCoordinates(glyfTable)
		if len(coords) > 0:
			if 0:
				# This branch calculates exact glyph outline bounds
				# analytically, handling cases without on-curve
				# extremas, etc.  However, the glyf table header
				# simply says that the bounds should be min/max x/y
				# "for coordinate data", so I suppose that means no
				# fancy thing here, just get extremas of all coord
				# points (on and off).  As such, this branch is
				# disabled.

				# Collect on-curve points
				onCurveCoords = [coords[j] for j in range(len(coords))
								if flags[j] & flagOnCurve]
				# Add implicit on-curve points
				start = 0
				for end in endPts:
					last = end
					for j in range(start, end + 1):
						if not ((flags[j] | flags[last]) & flagOnCurve):
							x = (coords[last][0] + coords[j][0]) / 2
							y = (coords[last][1] + coords[j][1]) / 2
							onCurveCoords.append((x,y))
						last = j
					start = end + 1
				# Add bounds for curves without an explicit extrema
				start = 0
				for end in endPts:
					last = end
					for j in range(start, end + 1):
						if not (flags[j] & flagOnCurve):
							next = j + 1 if j < end else start
							bbox = calcBounds([coords[last], coords[next]])
							if not pointInRect(coords[j], bbox):
								# Ouch!
								log.warning("Outline has curve with implicit extrema.")
								# Ouch!  Find analytical curve bounds.
								pthis = coords[j]
								plast = coords[last]
								if not (flags[last] & flagOnCurve):
									plast = ((pthis[0]+plast[0])/2, (pthis[1]+plast[1])/2)
								pnext = coords[next]
								if not (flags[next] & flagOnCurve):
									pnext = ((pthis[0]+pnext[0])/2, (pthis[1]+pnext[1])/2)
								bbox = calcQuadraticBounds(plast, pthis, pnext)
								onCurveCoords.append((bbox[0],bbox[1]))
								onCurveCoords.append((bbox[2],bbox[3]))
						last = j
					start = end + 1

				self.xMin, self.yMin, self.xMax, self.yMax = calcIntBounds(onCurveCoords)
			else:
				self.xMin, self.yMin, self.xMax, self.yMax = calcIntBounds(coords)
		else:
			self.xMin, self.yMin, self.xMax, self.yMax = (0, 0, 0, 0)

	def isComposite(self):
		"""Can be called on compact or expanded glyph."""
		if hasattr(self, "data") and self.data:
			return struct.unpack(">h", self.data[:2])[0] == -1
		else:
			return self.numberOfContours == -1

	def __getitem__(self, componentIndex):
		if not self.isComposite():
			raise ttLib.TTLibError("can't use glyph as sequence")
		return self.components[componentIndex]

	def getCoordinates(self, glyfTable):
		if self.numberOfContours > 0:
			return self.coordinates, self.endPtsOfContours, self.flags
		elif self.isComposite():
			# it's a composite
			allCoords = GlyphCoordinates()
			allFlags = array.array("B")
			allEndPts = []
			for compo in self.components:
				g = glyfTable[compo.glyphName]
				coordinates, endPts, flags = g.getCoordinates(glyfTable)
				if hasattr(compo, "firstPt"):
					# move according to two reference points
					x1,y1 = allCoords[compo.firstPt]
					x2,y2 = coordinates[compo.secondPt]
					move = x1-x2, y1-y2
				else:
					move = compo.x, compo.y

				coordinates = GlyphCoordinates(coordinates)
				if not hasattr(compo, "transform"):
					coordinates.translate(move)
				else:
					apple_way = compo.flags & SCALED_COMPONENT_OFFSET
					ms_way = compo.flags & UNSCALED_COMPONENT_OFFSET
					assert not (apple_way and ms_way)
					if not (apple_way or ms_way):
						scale_component_offset = SCALE_COMPONENT_OFFSET_DEFAULT  # see top of this file
					else:
						scale_component_offset = apple_way
					if scale_component_offset:
						# the Apple way: first move, then scale (ie. scale the component offset)
						coordinates.translate(move)
						coordinates.transform(compo.transform)
					else:
						# the MS way: first scale, then move
						coordinates.transform(compo.transform)
						coordinates.translate(move)
				offset = len(allCoords)
				allEndPts.extend(e + offset for e in endPts)
				allCoords.extend(coordinates)
				allFlags.extend(flags)
			return allCoords, allEndPts, allFlags
		else:
			return GlyphCoordinates(), [], array.array("B")

	def getComponentNames(self, glyfTable):
		if not hasattr(self, "data"):
			if self.isComposite():
				return [c.glyphName for c in self.components]
			else:
				return []

		# Extract components without expanding glyph

		if not self.data or struct.unpack(">h", self.data[:2])[0] >= 0:
			return []  # Not composite

		data = self.data
		i = 10
		components = []
		more = 1
		while more:
			flags, glyphID = struct.unpack(">HH", data[i:i+4])
			i += 4
			flags = int(flags)
			components.append(glyfTable.getGlyphName(int(glyphID)))

			if flags & ARG_1_AND_2_ARE_WORDS: i += 4
			else: i += 2
			if flags & WE_HAVE_A_SCALE: i += 2
			elif flags & WE_HAVE_AN_X_AND_Y_SCALE: i += 4
			elif flags & WE_HAVE_A_TWO_BY_TWO: i += 8
			more = flags & MORE_COMPONENTS

		return components

	def trim(self, remove_hinting=False):
		""" Remove padding and, if requested, hinting, from a glyph.
			This works on both expanded and compacted glyphs, without
			expanding it."""
		if not hasattr(self, "data"):
			if remove_hinting:
				self.program = ttProgram.Program()
				self.program.fromBytecode([])
			# No padding to trim.
			return
		if not self.data:
			return
		numContours = struct.unpack(">h", self.data[:2])[0]
		data = array.array("B", self.data)
		i = 10
		if numContours >= 0:
			i += 2 * numContours # endPtsOfContours
			nCoordinates = ((data[i-2] << 8) | data[i-1]) + 1
			instructionLen = (data[i] << 8) | data[i+1]
			if remove_hinting:
				# Zero instruction length
				data[i] = data [i+1] = 0
				i += 2
				if instructionLen:
					# Splice it out
					data = data[:i] + data[i+instructionLen:]
				instructionLen = 0
			else:
				i += 2 + instructionLen

			coordBytes = 0
			j = 0
			while True:
				flag = data[i]
				i = i + 1
				repeat = 1
				if flag & flagRepeat:
					repeat = data[i] + 1
					i = i + 1
				xBytes = yBytes = 0
				if flag & flagXShort:
					xBytes = 1
				elif not (flag & flagXsame):
					xBytes = 2
				if flag & flagYShort:
					yBytes = 1
				elif not (flag & flagYsame):
					yBytes = 2
				coordBytes += (xBytes + yBytes) * repeat
				j += repeat
				if j >= nCoordinates:
					break
			assert j == nCoordinates, "bad glyph flags"
			i += coordBytes
			# Remove padding
			data = data[:i]
		else:
			more = 1
			we_have_instructions = False
			while more:
				flags =(data[i] << 8) | data[i+1]
				if remove_hinting:
					flags &= ~WE_HAVE_INSTRUCTIONS
				if flags & WE_HAVE_INSTRUCTIONS:
					we_have_instructions = True
				data[i+0] = flags >> 8
				data[i+1] = flags & 0xFF
				i += 4
				flags = int(flags)

				if flags & ARG_1_AND_2_ARE_WORDS: i += 4
				else: i += 2
				if flags & WE_HAVE_A_SCALE: i += 2
				elif flags & WE_HAVE_AN_X_AND_Y_SCALE: i += 4
				elif flags & WE_HAVE_A_TWO_BY_TWO: i += 8
				more = flags & MORE_COMPONENTS
			if we_have_instructions:
				instructionLen = (data[i] << 8) | data[i+1]
				i += 2 + instructionLen
			# Remove padding
			data = data[:i]

		self.data = data.tostring()

	def removeHinting(self):
		self.trim (remove_hinting=True)

	def draw(self, pen, glyfTable, offset=0):

		if self.isComposite():
			for component in self.components:
				glyphName, transform = component.getComponentInfo()
				pen.addComponent(glyphName, transform)
			return

		coordinates, endPts, flags = self.getCoordinates(glyfTable)
		if offset:
			coordinates = coordinates.copy()
			coordinates.translate((offset, 0))
		start = 0
		for end in endPts:
			end = end + 1
			contour = coordinates[start:end]
			cFlags = flags[start:end]
			start = end
			if 1 not in cFlags:
				# There is not a single on-curve point on the curve,
				# use pen.qCurveTo's special case by specifying None
				# as the on-curve point.
				contour.append(None)
				pen.qCurveTo(*contour)
			else:
				# Shuffle the points so that contour the is guaranteed
				# to *end* in an on-curve point, which we'll use for
				# the moveTo.
				firstOnCurve = cFlags.index(1) + 1
				contour = contour[firstOnCurve:] + contour[:firstOnCurve]
				cFlags = cFlags[firstOnCurve:] + cFlags[:firstOnCurve]
				pen.moveTo(contour[-1])
				while contour:
					nextOnCurve = cFlags.index(1) + 1
					if nextOnCurve == 1:
						pen.lineTo(contour[0])
					else:
						pen.qCurveTo(*contour[:nextOnCurve])
					contour = contour[nextOnCurve:]
					cFlags = cFlags[nextOnCurve:]
			pen.closePath()

	def drawPoints(self, pen, glyfTable, offset=0):
		"""Draw the glyph using the supplied pointPen. Opposed to Glyph.draw(),
		this will not change the point indices.
		"""

		if self.isComposite():
			for component in self.components:
				glyphName, transform = component.getComponentInfo()
				pen.addComponent(glyphName, transform)
			return

		coordinates, endPts, flags = self.getCoordinates(glyfTable)
		if offset:
			coordinates = coordinates.copy()
			coordinates.translate((offset, 0))
		start = 0
		for end in endPts:
			end = end + 1
			contour = coordinates[start:end]
			cFlags = flags[start:end]
			start = end
			pen.beginPath()
			# Start with the appropriate segment type based on the final segment
			segmentType = "line" if cFlags[-1] == 1 else "qcurve"
			for i, pt in enumerate(contour):
				if cFlags[i] == 1:
					pen.addPoint(pt, segmentType=segmentType)
					segmentType = "line"
				else:
					pen.addPoint(pt)
					segmentType = "qcurve"
			pen.endPath()

	def __eq__(self, other):
		if type(self) != type(other):
			return NotImplemented
		return self.__dict__ == other.__dict__

	def __ne__(self, other):
		result = self.__eq__(other)
		return result if result is NotImplemented else not result

class GlyphComponent(object):

	def __init__(self):
		pass

	def getComponentInfo(self):
		"""Return the base glyph name and a transform."""
		# XXX Ignoring self.firstPt & self.lastpt for now: I need to implement
		# something equivalent in fontTools.objects.glyph (I'd rather not
		# convert it to an absolute offset, since it is valuable information).
		# This method will now raise "AttributeError: x" on glyphs that use
		# this TT feature.
		if hasattr(self, "transform"):
			[[xx, xy], [yx, yy]] = self.transform
			trans = (xx, xy, yx, yy, self.x, self.y)
		else:
			trans = (1, 0, 0, 1, self.x, self.y)
		return self.glyphName, trans

	def decompile(self, data, glyfTable):
		flags, glyphID = struct.unpack(">HH", data[:4])
		self.flags = int(flags)
		glyphID = int(glyphID)
		self.glyphName = glyfTable.getGlyphName(int(glyphID))
		data = data[4:]

		if self.flags & ARG_1_AND_2_ARE_WORDS:
			if self.flags & ARGS_ARE_XY_VALUES:
				self.x, self.y = struct.unpack(">hh", data[:4])
			else:
				x, y = struct.unpack(">HH", data[:4])
				self.firstPt, self.secondPt = int(x), int(y)
			data = data[4:]
		else:
			if self.flags & ARGS_ARE_XY_VALUES:
				self.x, self.y = struct.unpack(">bb", data[:2])
			else:
				x, y = struct.unpack(">BB", data[:2])
				self.firstPt, self.secondPt = int(x), int(y)
			data = data[2:]

		if self.flags & WE_HAVE_A_SCALE:
			scale, = struct.unpack(">h", data[:2])
			self.transform = [[fi2fl(scale,14), 0], [0, fi2fl(scale,14)]]  # fixed 2.14
			data = data[2:]
		elif self.flags & WE_HAVE_AN_X_AND_Y_SCALE:
			xscale, yscale = struct.unpack(">hh", data[:4])
			self.transform = [[fi2fl(xscale,14), 0], [0, fi2fl(yscale,14)]]  # fixed 2.14
			data = data[4:]
		elif self.flags & WE_HAVE_A_TWO_BY_TWO:
			(xscale, scale01,
					scale10, yscale) = struct.unpack(">hhhh", data[:8])
			self.transform = [[fi2fl(xscale,14), fi2fl(scale01,14)],
							[fi2fl(scale10,14), fi2fl(yscale,14)]] # fixed 2.14
			data = data[8:]
		more = self.flags & MORE_COMPONENTS
		haveInstructions = self.flags & WE_HAVE_INSTRUCTIONS
		self.flags = self.flags & (ROUND_XY_TO_GRID | USE_MY_METRICS |
				SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET |
				NON_OVERLAPPING | OVERLAP_COMPOUND)
		return more, haveInstructions, data

	def compile(self, more, haveInstructions, glyfTable):
		data = b""

		# reset all flags we will calculate ourselves
		flags = self.flags & (ROUND_XY_TO_GRID | USE_MY_METRICS |
				SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET |
				NON_OVERLAPPING | OVERLAP_COMPOUND)
		if more:
			flags = flags | MORE_COMPONENTS
		if haveInstructions:
			flags = flags | WE_HAVE_INSTRUCTIONS

		if hasattr(self, "firstPt"):
			if (0 <= self.firstPt <= 255) and (0 <= self.secondPt <= 255):
				data = data + struct.pack(">BB", self.firstPt, self.secondPt)
			else:
				data = data + struct.pack(">HH", self.firstPt, self.secondPt)
				flags = flags | ARG_1_AND_2_ARE_WORDS
		else:
			x = otRound(self.x)
			y = otRound(self.y)
			flags = flags | ARGS_ARE_XY_VALUES
			if (-128 <= x <= 127) and (-128 <= y <= 127):
				data = data + struct.pack(">bb", x, y)
			else:
				data = data + struct.pack(">hh", x, y)
				flags = flags | ARG_1_AND_2_ARE_WORDS

		if hasattr(self, "transform"):
			transform = [[fl2fi(x,14) for x in row] for row in self.transform]
			if transform[0][1] or transform[1][0]:
				flags = flags | WE_HAVE_A_TWO_BY_TWO
				data = data + struct.pack(">hhhh",
						transform[0][0], transform[0][1],
						transform[1][0], transform[1][1])
			elif transform[0][0] != transform[1][1]:
				flags = flags | WE_HAVE_AN_X_AND_Y_SCALE
				data = data + struct.pack(">hh",
						transform[0][0], transform[1][1])
			else:
				flags = flags | WE_HAVE_A_SCALE
				data = data + struct.pack(">h",
						transform[0][0])

		glyphID = glyfTable.getGlyphID(self.glyphName)
		return struct.pack(">HH", flags, glyphID) + data

	def toXML(self, writer, ttFont):
		attrs = [("glyphName", self.glyphName)]
		if not hasattr(self, "firstPt"):
			attrs = attrs + [("x", self.x), ("y", self.y)]
		else:
			attrs = attrs + [("firstPt", self.firstPt), ("secondPt", self.secondPt)]

		if hasattr(self, "transform"):
			transform = self.transform
			if transform[0][1] or transform[1][0]:
				attrs = attrs + [
						("scalex", transform[0][0]), ("scale01", transform[0][1]),
						("scale10", transform[1][0]), ("scaley", transform[1][1]),
						]
			elif transform[0][0] != transform[1][1]:
				attrs = attrs + [
						("scalex", transform[0][0]), ("scaley", transform[1][1]),
						]
			else:
				attrs = attrs + [("scale", transform[0][0])]
		attrs = attrs + [("flags", hex(self.flags))]
		writer.simpletag("component", attrs)
		writer.newline()

	def fromXML(self, name, attrs, content, ttFont):
		self.glyphName = attrs["glyphName"]
		if "firstPt" in attrs:
			self.firstPt = safeEval(attrs["firstPt"])
			self.secondPt = safeEval(attrs["secondPt"])
		else:
			self.x = safeEval(attrs["x"])
			self.y = safeEval(attrs["y"])
		if "scale01" in attrs:
			scalex = safeEval(attrs["scalex"])
			scale01 = safeEval(attrs["scale01"])
			scale10 = safeEval(attrs["scale10"])
			scaley = safeEval(attrs["scaley"])
			self.transform = [[scalex, scale01], [scale10, scaley]]
		elif "scalex" in attrs:
			scalex = safeEval(attrs["scalex"])
			scaley = safeEval(attrs["scaley"])
			self.transform = [[scalex, 0], [0, scaley]]
		elif "scale" in attrs:
			scale = safeEval(attrs["scale"])
			self.transform = [[scale, 0], [0, scale]]
		self.flags = safeEval(attrs["flags"])

	def __eq__(self, other):
		if type(self) != type(other):
			return NotImplemented
		return self.__dict__ == other.__dict__

	def __ne__(self, other):
		result = self.__eq__(other)
		return result if result is NotImplemented else not result

class GlyphCoordinates(object):

	def __init__(self, iterable=[], typecode="h"):
		self._a = array.array(typecode)
		self.extend(iterable)

	@property
	def array(self):
		return self._a

	def isFloat(self):
		return self._a.typecode == 'd'

	def _ensureFloat(self):
		if self.isFloat():
			return
		# The conversion to list() is to work around Jython bug
		self._a = array.array("d", list(self._a))

	def _checkFloat(self, p):
		if self.isFloat():
			return p
		if any(v > 0x7FFF or v < -0x8000 for v in p):
			self._ensureFloat()
			return p
		if any(isinstance(v, float) for v in p):
			p = [int(v) if int(v) == v else v for v in p]
			if any(isinstance(v, float) for v in p):
				self._ensureFloat()
		return p

	@staticmethod
	def zeros(count):
		return GlyphCoordinates([(0,0)] * count)

	def copy(self):
		c = GlyphCoordinates(typecode=self._a.typecode)
		c._a.extend(self._a)
		return c

	def __len__(self):
		return len(self._a) // 2

	def __getitem__(self, k):
		if isinstance(k, slice):
			indices = range(*k.indices(len(self)))
			return [self[i] for i in indices]
		return self._a[2*k],self._a[2*k+1]

	def __setitem__(self, k, v):
		if isinstance(k, slice):
			indices = range(*k.indices(len(self)))
			# XXX This only works if len(v) == len(indices)
			for j,i in enumerate(indices):
				self[i] = v[j]
			return
		v = self._checkFloat(v)
		self._a[2*k],self._a[2*k+1] = v

	def __delitem__(self, i):
		i = (2*i) % len(self._a)
		del self._a[i]
		del self._a[i]

	def __repr__(self):
		return 'GlyphCoordinates(['+','.join(str(c) for c in self)+'])'

	def append(self, p):
		p = self._checkFloat(p)
		self._a.extend(tuple(p))

	def extend(self, iterable):
		for p in iterable:
			p = self._checkFloat(p)
			self._a.extend(p)

	def toInt(self):
		if not self.isFloat():
			return
		a = array.array("h")
		for n in self._a:
			a.append(otRound(n))
		self._a = a

	def relativeToAbsolute(self):
		a = self._a
		x,y = 0,0
		for i in range(len(a) // 2):
			x = a[2*i  ] + x
			y = a[2*i+1] + y
			self[i] = (x, y)

	def absoluteToRelative(self):
		a = self._a
		x,y = 0,0
		for i in range(len(a) // 2):
			dx = a[2*i  ] - x
			dy = a[2*i+1] - y
			x = a[2*i  ]
			y = a[2*i+1]
			self[i] = (dx, dy)

	def translate(self, p):
		"""
		>>> GlyphCoordinates([(1,2)]).translate((.5,0))
		"""
		(x,y) = self._checkFloat(p)
		a = self._a
		for i in range(len(a) // 2):
			self[i] = (a[2*i] + x, a[2*i+1] + y)

	def scale(self, p):
		"""
		>>> GlyphCoordinates([(1,2)]).scale((.5,0))
		"""
		(x,y) = self._checkFloat(p)
		a = self._a
		for i in range(len(a) // 2):
			self[i] = (a[2*i] * x, a[2*i+1] * y)

	def transform(self, t):
		"""
		>>> GlyphCoordinates([(1,2)]).transform(((.5,0),(.2,.5)))
		"""
		a = self._a
		for i in range(len(a) // 2):
			x = a[2*i  ]
			y = a[2*i+1]
			px = x * t[0][0] + y * t[1][0]
			py = x * t[0][1] + y * t[1][1]
			self[i] = (px, py)

	def __eq__(self, other):
		"""
		>>> g = GlyphCoordinates([(1,2)])
		>>> g2 = GlyphCoordinates([(1.0,2)])
		>>> g3 = GlyphCoordinates([(1.5,2)])
		>>> g == g2
		True
		>>> g == g3
		False
		>>> g2 == g3
		False
		"""
		if type(self) != type(other):
			return NotImplemented
		return self._a == other._a

	def __ne__(self, other):
		"""
		>>> g = GlyphCoordinates([(1,2)])
		>>> g2 = GlyphCoordinates([(1.0,2)])
		>>> g3 = GlyphCoordinates([(1.5,2)])
		>>> g != g2
		False
		>>> g != g3
		True
		>>> g2 != g3
		True
		"""
		result = self.__eq__(other)
		return result if result is NotImplemented else not result

	# Math operations

	def __pos__(self):
		"""
		>>> g = GlyphCoordinates([(1,2)])
		>>> g
		GlyphCoordinates([(1, 2)])
		>>> g2 = +g
		>>> g2
		GlyphCoordinates([(1, 2)])
		>>> g2.translate((1,0))
		>>> g2
		GlyphCoordinates([(2, 2)])
		>>> g
		GlyphCoordinates([(1, 2)])
		"""
		return self.copy()
	def __neg__(self):
		"""
		>>> g = GlyphCoordinates([(1,2)])
		>>> g
		GlyphCoordinates([(1, 2)])
		>>> g2 = -g
		>>> g2
		GlyphCoordinates([(-1, -2)])
		>>> g
		GlyphCoordinates([(1, 2)])
		"""
		r = self.copy()
		a = r._a
		for i in range(len(a)):
			a[i] = -a[i]
		return r
	def __round__(self):
		"""
		Note: This is Python 3 only.  Python 2 does not call __round__.
		As such, we cannot test this method either. :(
		"""
		r = self.copy()
		r.toInt()
		return r

	def __add__(self, other): return self.copy().__iadd__(other)
	def __sub__(self, other): return self.copy().__isub__(other)
	def __mul__(self, other): return self.copy().__imul__(other)
	def __truediv__(self, other): return self.copy().__itruediv__(other)

	__radd__ = __add__
	__rmul__ = __mul__
	def __rsub__(self, other): return other + (-self)

	def __iadd__(self, other):
		"""
		>>> g = GlyphCoordinates([(1,2)])
		>>> g += (.5,0)
		>>> g
		GlyphCoordinates([(1.5, 2.0)])
		>>> g2 = GlyphCoordinates([(3,4)])
		>>> g += g2
		>>> g
		GlyphCoordinates([(4.5, 6.0)])
		"""
		if isinstance(other, tuple):
			assert len(other) ==  2
			self.translate(other)
			return self
		if isinstance(other, GlyphCoordinates):
			if other.isFloat(): self._ensureFloat()
			other = other._a
			a = self._a
			assert len(a) == len(other)
			for i in range(len(a) // 2):
				self[i] = (a[2*i] + other[2*i], a[2*i+1] + other[2*i+1])
			return self
		return NotImplemented

	def __isub__(self, other):
		"""
		>>> g = GlyphCoordinates([(1,2)])
		>>> g -= (.5,0)
		>>> g
		GlyphCoordinates([(0.5, 2.0)])
		>>> g2 = GlyphCoordinates([(3,4)])
		>>> g -= g2
		>>> g
		GlyphCoordinates([(-2.5, -2.0)])
		"""
		if isinstance(other, tuple):
			assert len(other) ==  2
			self.translate((-other[0],-other[1]))
			return self
		if isinstance(other, GlyphCoordinates):
			if other.isFloat(): self._ensureFloat()
			other = other._a
			a = self._a
			assert len(a) == len(other)
			for i in range(len(a) // 2):
				self[i] = (a[2*i] - other[2*i], a[2*i+1] - other[2*i+1])
			return self
		return NotImplemented

	def __imul__(self, other):
		"""
		>>> g = GlyphCoordinates([(1,2)])
		>>> g *= (2,.5)
		>>> g *= 2
		>>> g
		GlyphCoordinates([(4.0, 2.0)])
		>>> g = GlyphCoordinates([(1,2)])
		>>> g *= 2
		>>> g
		GlyphCoordinates([(2, 4)])
		"""
		if isinstance(other, Number):
			other = (other, other)
		if isinstance(other, tuple):
			if other == (1,1):
				return self
			assert len(other) ==  2
			self.scale(other)
			return self
		return NotImplemented

	def __itruediv__(self, other):
		"""
		>>> g = GlyphCoordinates([(1,3)])
		>>> g /= (.5,1.5)
		>>> g /= 2
		>>> g
		GlyphCoordinates([(1.0, 1.0)])
		"""
		if isinstance(other, Number):
			other = (other, other)
		if isinstance(other, tuple):
			if other == (1,1):
				return self
			assert len(other) ==  2
			self.scale((1./other[0],1./other[1]))
			return self
		return NotImplemented

	def __bool__(self):
		"""
		>>> g = GlyphCoordinates([])
		>>> bool(g)
		False
		>>> g = GlyphCoordinates([(0,0), (0.,0)])
		>>> bool(g)
		True
		>>> g = GlyphCoordinates([(0,0), (1,0)])
		>>> bool(g)
		True
		>>> g = GlyphCoordinates([(0,.5), (0,0)])
		>>> bool(g)
		True
		"""
		return bool(self._a)

	__nonzero__ = __bool__


def reprflag(flag):
	bin = ""
	if isinstance(flag, str):
		flag = byteord(flag)
	while flag:
		if flag & 0x01:
			bin = "1" + bin
		else:
			bin = "0" + bin
		flag = flag >> 1
	bin = (14 - len(bin)) * "0" + bin
	return bin


if __name__ == "__main__":
	import doctest, sys
	sys.exit(doctest.testmod().failed)
