# -*- coding: utf-8 -*-
"""
glifLib.py -- Generic module for reading and writing the .glif format.

More info about the .glif format (GLyphInterchangeFormat) can be found here:

	http://unifiedfontobject.org

The main class in this module is GlyphSet. It manages a set of .glif files
in a folder. It offers two ways to read glyph data, and one way to write
glyph data. See the class doc string for details.
"""

from __future__ import absolute_import, unicode_literals
from warnings import warn
from collections import OrderedDict
import fs
import fs.base
import fs.errors
import fs.osfs
import fs.path
from fontTools.misc.py23 import basestring, unicode, tobytes, tounicode
from fontTools.misc import plistlib
from fontTools.pens.pointPen import AbstractPointPen, PointToSegmentPen
from fontTools.ufoLib.errors import GlifLibError
from fontTools.ufoLib.filenames import userNameToFileName
from fontTools.ufoLib.validators import (
	genericTypeValidator,
	colorValidator,
	guidelinesValidator,
	anchorsValidator,
	identifierValidator,
	imageValidator,
	glyphLibValidator,
)
from fontTools.misc import etree
from fontTools.ufoLib import _UFOBaseIO
from fontTools.ufoLib.utils import integerTypes, numberTypes


__all__ = [
	"GlyphSet",
	"GlifLibError",
	"readGlyphFromString", "writeGlyphToString",
	"glyphNameToFileName"
]


# ---------
# Constants
# ---------

CONTENTS_FILENAME = "contents.plist"
LAYERINFO_FILENAME = "layerinfo.plist"
supportedUFOFormatVersions = [1, 2, 3]
supportedGLIFFormatVersions = [1, 2]


# ------------
# Simple Glyph
# ------------

class Glyph(object):

	"""
	Minimal glyph object. It has no glyph attributes until either
	the draw() or the drawPoints() method has been called.
	"""

	def __init__(self, glyphName, glyphSet):
		self.glyphName = glyphName
		self.glyphSet = glyphSet

	def draw(self, pen):
		"""
		Draw this glyph onto a *FontTools* Pen.
		"""
		pointPen = PointToSegmentPen(pen)
		self.drawPoints(pointPen)

	def drawPoints(self, pointPen):
		"""
		Draw this glyph onto a PointPen.
		"""
		self.glyphSet.readGlyph(self.glyphName, self, pointPen)


# ---------
# Glyph Set
# ---------

class GlyphSet(_UFOBaseIO):

	"""
	GlyphSet manages a set of .glif files inside one directory.

	GlyphSet's constructor takes a path to an existing directory as it's
	first argument. Reading glyph data can either be done through the
	readGlyph() method, or by using GlyphSet's dictionary interface, where
	the keys are glyph names and the values are (very) simple glyph objects.

	To write a glyph to the glyph set, you use the writeGlyph() method.
	The simple glyph objects returned through the dict interface do not
	support writing, they are just a convenient way to get at the glyph data.
	"""

	glyphClass = Glyph

	def __init__(
		self,
		path,
		glyphNameToFileNameFunc=None,
		ufoFormatVersion=3,
		validateRead=True,
		validateWrite=True,
	):
		"""
		'path' should be a path (string) to an existing local directory, or
		an instance of fs.base.FS class.

		The optional 'glyphNameToFileNameFunc' argument must be a callback
		function that takes two arguments: a glyph name and a list of all
		existing filenames (if any exist). It should return a file name
		(including the .glif extension). The glyphNameToFileName function
		is called whenever a file name is created for a given glyph name.

		``validateRead`` will validate read operations. Its default is ``True``.
		``validateWrite`` will validate write operations. Its default is ``True``.
		"""
		if ufoFormatVersion not in supportedUFOFormatVersions:
			raise GlifLibError("Unsupported UFO format version: %s" % ufoFormatVersion)
		if isinstance(path, basestring):
			try:
				filesystem = fs.osfs.OSFS(path)
			except fs.errors.CreateFailed:
				raise GlifLibError("No glyphs directory '%s'" % path)
			self._shouldClose = True
		elif isinstance(path, fs.base.FS):
			filesystem = path
			try:
				filesystem.check()
			except fs.errors.FilesystemClosed:
				raise GlifLibError("the filesystem '%s' is closed" % filesystem)
			self._shouldClose = False
		else:
			raise TypeError(
				"Expected a path string or fs object, found %s"
				% type(path).__name__
			)
		try:
			path = filesystem.getsyspath("/")
		except fs.errors.NoSysPath:
			# network or in-memory FS may not map to the local one
			path = unicode(filesystem)
		# 'dirName' is kept for backward compatibility only, but it's DEPRECATED
		# as it's not guaranteed that it maps to an existing OSFS directory.
		# Client could use the FS api via the `self.fs` attribute instead.
		self.dirName = fs.path.parts(path)[-1]
		self.fs = filesystem
		# if glyphSet contains no 'contents.plist', we consider it empty
		self._havePreviousFile = filesystem.exists(CONTENTS_FILENAME)
		self.ufoFormatVersion = ufoFormatVersion
		if glyphNameToFileNameFunc is None:
			glyphNameToFileNameFunc = glyphNameToFileName
		self.glyphNameToFileName = glyphNameToFileNameFunc
		self._validateRead = validateRead
		self._validateWrite = validateWrite
		self._existingFileNames = None
		self._reverseContents = None

		self.rebuildContents()

	def rebuildContents(self, validateRead=None):
		"""
		Rebuild the contents dict by loading contents.plist.

		``validateRead`` will validate the data, by default it is set to the
		class's ``validateRead`` value, can be overridden.
		"""
		if validateRead is None:
			validateRead = self._validateRead
		contents = self._getPlist(CONTENTS_FILENAME, {})
		# validate the contents
		if validateRead:
			invalidFormat = False
			if not isinstance(contents, dict):
				invalidFormat = True
			else:
				for name, fileName in contents.items():
					if not isinstance(name, basestring):
						invalidFormat = True
					if not isinstance(fileName, basestring):
						invalidFormat = True
					elif not self.fs.exists(fileName):
						raise GlifLibError(
							"%s references a file that does not exist: %s"
							% (CONTENTS_FILENAME, fileName)
						)
			if invalidFormat:
				raise GlifLibError("%s is not properly formatted" % CONTENTS_FILENAME)
		self.contents = contents
		self._existingFileNames = None
		self._reverseContents = None

	def getReverseContents(self):
		"""
		Return a reversed dict of self.contents, mapping file names to
		glyph names. This is primarily an aid for custom glyph name to file
		name schemes that want to make sure they don't generate duplicate
		file names. The file names are converted to lowercase so we can
		reliably check for duplicates that only differ in case, which is
		important for case-insensitive file systems.
		"""
		if self._reverseContents is None:
			d = {}
			for k, v in self.contents.items():
				d[v.lower()] = k
			self._reverseContents = d
		return self._reverseContents

	def writeContents(self):
		"""
		Write the contents.plist file out to disk. Call this method when
		you're done writing glyphs.
		"""
		self._writePlist(CONTENTS_FILENAME, self.contents)

	# layer info

	def readLayerInfo(self, info, validateRead=None):
		"""
		``validateRead`` will validate the data, by default it is set to the
		class's ``validateRead`` value, can be overridden.
		"""
		if validateRead is None:
			validateRead = self._validateRead
		infoDict = self._getPlist(LAYERINFO_FILENAME, {})
		if validateRead:
			if not isinstance(infoDict, dict):
				raise GlifLibError("layerinfo.plist is not properly formatted.")
			infoDict = validateLayerInfoVersion3Data(infoDict)
		# populate the object
		for attr, value in infoDict.items():
			try:
				setattr(info, attr, value)
			except AttributeError:
				raise GlifLibError("The supplied layer info object does not support setting a necessary attribute (%s)." % attr)

	def writeLayerInfo(self, info, validateWrite=None):
		"""
		``validateWrite`` will validate the data, by default it is set to the
		class's ``validateWrite`` value, can be overridden.
		"""
		if validateWrite is None:
			validateWrite = self._validateWrite
		if self.ufoFormatVersion < 3:
			raise GlifLibError("layerinfo.plist is not allowed in UFO %d." % self.ufoFormatVersion)
		# gather data
		infoData = {}
		for attr in layerInfoVersion3ValueData.keys():
			if hasattr(info, attr):
				try:
					value = getattr(info, attr)
				except AttributeError:
					raise GlifLibError("The supplied info object does not support getting a necessary attribute (%s)." % attr)
				if value is None or (attr == 'lib' and not value):
					continue
				infoData[attr] = value
		if infoData:
			# validate
			if validateWrite:
				infoData = validateLayerInfoVersion3Data(infoData)
			# write file
			self._writePlist(LAYERINFO_FILENAME, infoData)
		elif self._havePreviousFile and self.fs.exists(LAYERINFO_FILENAME):
			# data empty, remove existing file
			self.fs.remove(LAYERINFO_FILENAME)

	def getGLIF(self, glyphName):
		"""
		Get the raw GLIF text for a given glyph name. This only works
		for GLIF files that are already on disk.

		This method is useful in situations when the raw XML needs to be
		read from a glyph set for a particular glyph before fully parsing
		it into an object structure via the readGlyph method.

		Raises KeyError if 'glyphName' is not in contents.plist, or
		GlifLibError if the file associated with can't be found.
		"""
		fileName = self.contents[glyphName]
		try:
			return self.fs.readbytes(fileName)
		except fs.errors.ResourceNotFound:
			raise GlifLibError(
				"The file '%s' associated with glyph '%s' in contents.plist "
				"does not exist on %s" % (fileName, glyphName, self.fs)
			)

	def getGLIFModificationTime(self, glyphName):
		"""
		Returns the modification time for the GLIF file with 'glyphName', as
		a floating point number giving the number of seconds since the epoch.
		Return None if the associated file does not exist or the underlying
		filesystem does not support getting modified times.
		Raises KeyError if the glyphName is not in contents.plist.
		"""
		fileName = self.contents[glyphName]
		return self.getFileModificationTime(fileName)

	# reading/writing API

	def readGlyph(self, glyphName, glyphObject=None, pointPen=None, validate=None):
		"""
		Read a .glif file for 'glyphName' from the glyph set. The
		'glyphObject' argument can be any kind of object (even None);
		the readGlyph() method will attempt to set the following
		attributes on it:
			"width"      the advance width of the glyph
			"height"     the advance height of the glyph
			"unicodes"   a list of unicode values for this glyph
			"note"       a string
			"lib"        a dictionary containing custom data
			"image"      a dictionary containing image data
			"guidelines" a list of guideline data dictionaries
			"anchors"    a list of anchor data dictionaries

		All attributes are optional, in two ways:
			1) An attribute *won't* be set if the .glif file doesn't
			   contain data for it. 'glyphObject' will have to deal
			   with default values itself.
			2) If setting the attribute fails with an AttributeError
			   (for example if the 'glyphObject' attribute is read-
			   only), readGlyph() will not propagate that exception,
			   but ignore that attribute.

		To retrieve outline information, you need to pass an object
		conforming to the PointPen protocol as the 'pointPen' argument.
		This argument may be None if you don't need the outline data.

		readGlyph() will raise KeyError if the glyph is not present in
		the glyph set.

		``validate`` will validate the data, by default it is set to the
		class's ``validateRead`` value, can be overridden.
		"""
		if validate is None:
			validate = self._validateRead
		text = self.getGLIF(glyphName)
		tree = _glifTreeFromString(text)
		if self.ufoFormatVersion < 3:
			formatVersions = (1,)
		else:
			formatVersions = (1, 2)
		_readGlyphFromTree(tree, glyphObject, pointPen, formatVersions=formatVersions, validate=validate)

	def writeGlyph(self, glyphName, glyphObject=None, drawPointsFunc=None, formatVersion=None, validate=None):
		"""
		Write a .glif file for 'glyphName' to the glyph set. The
		'glyphObject' argument can be any kind of object (even None);
		the writeGlyph() method will attempt to get the following
		attributes from it:
			"width"      the advance with of the glyph
			"height"     the advance height of the glyph
			"unicodes"   a list of unicode values for this glyph
			"note"       a string
			"lib"        a dictionary containing custom data
			"image"      a dictionary containing image data
			"guidelines" a list of guideline data dictionaries
			"anchors"    a list of anchor data dictionaries

		All attributes are optional: if 'glyphObject' doesn't
		have the attribute, it will simply be skipped.

		To write outline data to the .glif file, writeGlyph() needs
		a function (any callable object actually) that will take one
		argument: an object that conforms to the PointPen protocol.
		The function will be called by writeGlyph(); it has to call the
		proper PointPen methods to transfer the outline to the .glif file.

		The GLIF format version will be chosen based on the ufoFormatVersion
		passed during the creation of this object. If a particular format
		version is desired, it can be passed with the formatVersion argument.

		``validate`` will validate the data, by default it is set to the
		class's ``validateWrite`` value, can be overridden.
		"""
		if formatVersion is None:
			if self.ufoFormatVersion >= 3:
				formatVersion = 2
			else:
				formatVersion = 1
		if formatVersion not in supportedGLIFFormatVersions:
			raise GlifLibError("Unsupported GLIF format version: %s" % formatVersion)
		if formatVersion == 2 and self.ufoFormatVersion < 3:
			raise GlifLibError(
				"Unsupported GLIF format version (%d) for UFO format version %d."
				% (formatVersion, self.ufoFormatVersion)
			)
		if validate is None:
			validate = self._validateWrite
		fileName = self.contents.get(glyphName)
		if fileName is None:
			if self._existingFileNames is None:
				self._existingFileNames = {}
				for fileName in self.contents.values():
					self._existingFileNames[fileName] = fileName.lower()
			fileName = self.glyphNameToFileName(glyphName, self._existingFileNames)
			self.contents[glyphName] = fileName
			self._existingFileNames[fileName] = fileName.lower()
			if self._reverseContents is not None:
				self._reverseContents[fileName.lower()] = glyphName
		data = _writeGlyphToBytes(
			glyphName,
			glyphObject,
			drawPointsFunc,
			formatVersion=formatVersion,
			validate=validate,
		)
		if (
			self._havePreviousFile
			and self.fs.exists(fileName)
			and data == self.fs.readbytes(fileName)
		):
			return
		self.fs.writebytes(fileName, data)

	def deleteGlyph(self, glyphName):
		"""Permanently delete the glyph from the glyph set on disk. Will
		raise KeyError if the glyph is not present in the glyph set.
		"""
		fileName = self.contents[glyphName]
		self.fs.remove(fileName)
		if self._existingFileNames is not None:
			del self._existingFileNames[fileName]
		if self._reverseContents is not None:
			del self._reverseContents[self.contents[glyphName].lower()]
		del self.contents[glyphName]

	# dict-like support

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

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

	__contains__ = has_key

	def __len__(self):
		return len(self.contents)

	def __getitem__(self, glyphName):
		if glyphName not in self.contents:
			raise KeyError(glyphName)
		return self.glyphClass(glyphName, self)

	# quickly fetch unicode values

	def getUnicodes(self, glyphNames=None):
		"""
		Return a dictionary that maps glyph names to lists containing
		the unicode value[s] for that glyph, if any. This parses the .glif
		files partially, so it is a lot faster than parsing all files completely.
		By default this checks all glyphs, but a subset can be passed with glyphNames.
		"""
		unicodes = {}
		if glyphNames is None:
			glyphNames = self.contents.keys()
		for glyphName in glyphNames:
			text = self.getGLIF(glyphName)
			unicodes[glyphName] = _fetchUnicodes(text)
		return unicodes

	def getComponentReferences(self, glyphNames=None):
		"""
		Return a dictionary that maps glyph names to lists containing the
		base glyph name of components in the glyph. This parses the .glif
		files partially, so it is a lot faster than parsing all files completely.
		By default this checks all glyphs, but a subset can be passed with glyphNames.
		"""
		components = {}
		if glyphNames is None:
			glyphNames = self.contents.keys()
		for glyphName in glyphNames:
			text = self.getGLIF(glyphName)
			components[glyphName] = _fetchComponentBases(text)
		return components

	def getImageReferences(self, glyphNames=None):
		"""
		Return a dictionary that maps glyph names to the file name of the image
		referenced by the glyph. This parses the .glif files partially, so it is a
		lot faster than parsing all files completely.
		By default this checks all glyphs, but a subset can be passed with glyphNames.
		"""
		images = {}
		if glyphNames is None:
			glyphNames = self.contents.keys()
		for glyphName in glyphNames:
			text = self.getGLIF(glyphName)
			images[glyphName] = _fetchImageFileName(text)
		return images

	def close(self):
		if self._shouldClose:
			self.fs.close()

	def __enter__(self):
		return self

	def __exit__(self, exc_type, exc_value, exc_tb):
		self.close()


# -----------------------
# Glyph Name to File Name
# -----------------------

def glyphNameToFileName(glyphName, existingFileNames):
	"""
	Wrapper around the userNameToFileName function in filenames.py
	"""
	if existingFileNames is None:
		existingFileNames = []
	if not isinstance(glyphName, unicode):
		try:
			new = unicode(glyphName)
			glyphName = new
		except UnicodeDecodeError:
			pass
	return userNameToFileName(glyphName, existing=existingFileNames, suffix=".glif")

# -----------------------
# GLIF To and From String
# -----------------------

def readGlyphFromString(aString, glyphObject=None, pointPen=None, formatVersions=(1, 2), validate=True):
	"""
	Read .glif data from a string into a glyph object.

	The 'glyphObject' argument can be any kind of object (even None);
	the readGlyphFromString() method will attempt to set the following
	attributes on it:
		"width"      the advance with of the glyph
		"height"     the advance height of the glyph
		"unicodes"   a list of unicode values for this glyph
		"note"       a string
		"lib"        a dictionary containing custom data
		"image"      a dictionary containing image data
		"guidelines" a list of guideline data dictionaries
		"anchors"    a list of anchor data dictionaries

	All attributes are optional, in two ways:
		1) An attribute *won't* be set if the .glif file doesn't
		   contain data for it. 'glyphObject' will have to deal
		   with default values itself.
		2) If setting the attribute fails with an AttributeError
		   (for example if the 'glyphObject' attribute is read-
		   only), readGlyphFromString() will not propagate that
		   exception, but ignore that attribute.

	To retrieve outline information, you need to pass an object
	conforming to the PointPen protocol as the 'pointPen' argument.
	This argument may be None if you don't need the outline data.

	The formatVersions argument defined the GLIF format versions
	that are allowed to be read.

	``validate`` will validate the read data. It is set to ``True`` by default.
	"""
	tree = _glifTreeFromString(aString)
	_readGlyphFromTree(tree, glyphObject, pointPen, formatVersions=formatVersions, validate=validate)


def _writeGlyphToBytes(
		glyphName, glyphObject=None, drawPointsFunc=None, writer=None,
		formatVersion=2, validate=True):
	"""Return .glif data for a glyph as a UTF-8 encoded bytes string."""
	# start
	if validate and not isinstance(glyphName, basestring):
		raise GlifLibError("The glyph name is not properly formatted.")
	if validate and len(glyphName) == 0:
		raise GlifLibError("The glyph name is empty.")
	root = etree.Element("glyph", OrderedDict([("name", glyphName), ("format", repr(formatVersion))]))
	identifiers = set()
	# advance
	_writeAdvance(glyphObject, root, validate)
	# unicodes
	if getattr(glyphObject, "unicodes", None):
		_writeUnicodes(glyphObject, root, validate)
	# note
	if getattr(glyphObject, "note", None):
		_writeNote(glyphObject, root, validate)
	# image
	if formatVersion >= 2 and getattr(glyphObject, "image", None):
		_writeImage(glyphObject, root, validate)
	# guidelines
	if formatVersion >= 2 and getattr(glyphObject, "guidelines", None):
		_writeGuidelines(glyphObject, root, identifiers, validate)
	# anchors
	anchors = getattr(glyphObject, "anchors", None)
	if formatVersion >= 2 and anchors:
		_writeAnchors(glyphObject, root, identifiers, validate)
	# outline
	if drawPointsFunc is not None:
		outline = etree.SubElement(root, "outline")
		pen = GLIFPointPen(outline, identifiers=identifiers, validate=validate)
		drawPointsFunc(pen)
		if formatVersion == 1 and anchors:
			_writeAnchorsFormat1(pen, anchors, validate)
		# prevent lxml from writing self-closing tags
		if not len(outline):
			outline.text = "\n  "
	# lib
	if getattr(glyphObject, "lib", None):
		_writeLib(glyphObject, root, validate)
	# return the text
	data = etree.tostring(
		root, encoding="UTF-8", xml_declaration=True, pretty_print=True
	)
	return data


def writeGlyphToString(glyphName, glyphObject=None, drawPointsFunc=None, formatVersion=2, validate=True):
	"""
	Return .glif data for a glyph as a Unicode string (`unicode` in py2, `str`
	in py3). The XML declaration's encoding is always set to "UTF-8".
	The 'glyphObject' argument can be any kind of object (even None);
	the writeGlyphToString() method will attempt to get the following
	attributes from it:
		"width"      the advance width of the glyph
		"height"     the advance height of the glyph
		"unicodes"   a list of unicode values for this glyph
		"note"       a string
		"lib"        a dictionary containing custom data
		"image"      a dictionary containing image data
		"guidelines" a list of guideline data dictionaries
		"anchors"    a list of anchor data dictionaries

	All attributes are optional: if 'glyphObject' doesn't
	have the attribute, it will simply be skipped.

	To write outline data to the .glif file, writeGlyphToString() needs
	a function (any callable object actually) that will take one
	argument: an object that conforms to the PointPen protocol.
	The function will be called by writeGlyphToString(); it has to call the
	proper PointPen methods to transfer the outline to the .glif file.

	The GLIF format version can be specified with the formatVersion argument.

	``validate`` will validate the written data. It is set to ``True`` by default.
	"""
	data = _writeGlyphToBytes(
		glyphName,
		glyphObject=glyphObject,
		drawPointsFunc=drawPointsFunc,
		formatVersion=formatVersion,
		validate=validate,
	)
	return data.decode("utf-8")


def _writeAdvance(glyphObject, element, validate):
	width = getattr(glyphObject, "width", None)
	if width is not None:
		if validate and not isinstance(width, numberTypes):
			raise GlifLibError("width attribute must be int or float")
		if width == 0:
			width = None
	height = getattr(glyphObject, "height", None)
	if height is not None:
		if validate and not isinstance(height, numberTypes):
			raise GlifLibError("height attribute must be int or float")
		if height == 0:
			height = None
	if width is not None and height is not None:
		etree.SubElement(element, "advance", OrderedDict([("height", repr(height)), ("width", repr(width))]))
	elif width is not None:
		etree.SubElement(element, "advance", dict(width=repr(width)))
	elif height is not None:
		etree.SubElement(element, "advance", dict(height=repr(height)))

def _writeUnicodes(glyphObject, element, validate):
	unicodes = getattr(glyphObject, "unicodes", None)
	if validate and isinstance(unicodes, integerTypes):
		unicodes = [unicodes]
	seen = set()
	for code in unicodes:
		if validate and not isinstance(code, integerTypes):
			raise GlifLibError("unicode values must be int")
		if code in seen:
			continue
		seen.add(code)
		hexCode = "%04X" % code
		etree.SubElement(element, "unicode", dict(hex=hexCode))

def _writeNote(glyphObject, element, validate):
	note = getattr(glyphObject, "note", None)
	if validate and not isinstance(note, basestring):
		raise GlifLibError("note attribute must be str or unicode")
	note = note.strip()
	note = "\n" + note + "\n"
	# ensure text is unicode, if it's bytes decode as ASCII
	etree.SubElement(element, "note").text = tounicode(note)

def _writeImage(glyphObject, element, validate):
	image = getattr(glyphObject, "image", None)
	if validate and not imageValidator(image):
		raise GlifLibError("image attribute must be a dict or dict-like object with the proper structure.")
	attrs = OrderedDict([("fileName", image["fileName"])])
	for attr, default in _transformationInfo:
		value = image.get(attr, default)
		if value != default:
			attrs[attr] = repr(value)
	color = image.get("color")
	if color is not None:
		attrs["color"] = color
	etree.SubElement(element, "image", attrs)

def _writeGuidelines(glyphObject, element, identifiers, validate):
	guidelines = getattr(glyphObject, "guidelines", [])
	if validate and not guidelinesValidator(guidelines):
		raise GlifLibError("guidelines attribute does not have the proper structure.")
	for guideline in guidelines:
		attrs = OrderedDict()
		x = guideline.get("x")
		if x is not None:
			attrs["x"] = repr(x)
		y = guideline.get("y")
		if y is not None:
			attrs["y"] = repr(y)
		angle = guideline.get("angle")
		if angle is not None:
			attrs["angle"] = repr(angle)
		name = guideline.get("name")
		if name is not None:
			attrs["name"] = name
		color = guideline.get("color")
		if color is not None:
			attrs["color"] = color
		identifier = guideline.get("identifier")
		if identifier is not None:
			if validate and identifier in identifiers:
				raise GlifLibError("identifier used more than once: %s" % identifier)
			attrs["identifier"] = identifier
			identifiers.add(identifier)
		etree.SubElement(element, "guideline", attrs)

def _writeAnchorsFormat1(pen, anchors, validate):
	if validate and not anchorsValidator(anchors):
		raise GlifLibError("anchors attribute does not have the proper structure.")
	for anchor in anchors:
		attrs = {}
		x = anchor["x"]
		attrs["x"] = repr(x)
		y = anchor["y"]
		attrs["y"] = repr(y)
		name = anchor.get("name")
		if name is not None:
			attrs["name"] = name
		pen.beginPath()
		pen.addPoint((x, y), segmentType="move", name=name)
		pen.endPath()

def _writeAnchors(glyphObject, element, identifiers, validate):
	anchors = getattr(glyphObject, "anchors", [])
	if validate and not anchorsValidator(anchors):
		raise GlifLibError("anchors attribute does not have the proper structure.")
	for anchor in anchors:
		attrs = OrderedDict()
		x = anchor["x"]
		attrs["x"] = repr(x)
		y = anchor["y"]
		attrs["y"] = repr(y)
		name = anchor.get("name")
		if name is not None:
			attrs["name"] = name
		color = anchor.get("color")
		if color is not None:
			attrs["color"] = color
		identifier = anchor.get("identifier")
		if identifier is not None:
			if validate and identifier in identifiers:
				raise GlifLibError("identifier used more than once: %s" % identifier)
			attrs["identifier"] = identifier
			identifiers.add(identifier)
		etree.SubElement(element, "anchor", attrs)

def _writeLib(glyphObject, element, validate):
	lib = getattr(glyphObject, "lib", None)
	if not lib:
		# don't write empty lib
		return
	if validate:
		valid, message = glyphLibValidator(lib)
		if not valid:
			raise GlifLibError(message)
	if not isinstance(lib, dict):
		lib = dict(lib)
	# plist inside GLIF begins with 2 levels of indentation
	e = plistlib.totree(lib, indent_level=2)
	etree.SubElement(element, "lib").append(e)

# -----------------------
# layerinfo.plist Support
# -----------------------

layerInfoVersion3ValueData = {
	"color"			: dict(type=basestring, valueValidator=colorValidator),
	"lib"			: dict(type=dict, valueValidator=genericTypeValidator)
}

def validateLayerInfoVersion3ValueForAttribute(attr, value):
	"""
	This performs very basic validation of the value for attribute
	following the UFO 3 fontinfo.plist specification. The results
	of this should not be interpretted as *correct* for the font
	that they are part of. This merely indicates that the value
	is of the proper type and, where the specification defines
	a set range of possible values for an attribute, that the
	value is in the accepted range.
	"""
	if attr not in layerInfoVersion3ValueData:
		return False
	dataValidationDict = layerInfoVersion3ValueData[attr]
	valueType = dataValidationDict.get("type")
	validator = dataValidationDict.get("valueValidator")
	valueOptions = dataValidationDict.get("valueOptions")
	# have specific options for the validator
	if valueOptions is not None:
		isValidValue = validator(value, valueOptions)
	# no specific options
	else:
		if validator == genericTypeValidator:
			isValidValue = validator(value, valueType)
		else:
			isValidValue = validator(value)
	return isValidValue

def validateLayerInfoVersion3Data(infoData):
	"""
	This performs very basic validation of the value for infoData
	following the UFO 3 layerinfo.plist specification. The results
	of this should not be interpretted as *correct* for the font
	that they are part of. This merely indicates that the values
	are of the proper type and, where the specification defines
	a set range of possible values for an attribute, that the
	value is in the accepted range.
	"""
	for attr, value in infoData.items():
		if attr not in layerInfoVersion3ValueData:
			raise GlifLibError("Unknown attribute %s." % attr)
		isValidValue = validateLayerInfoVersion3ValueForAttribute(attr, value)
		if not isValidValue:
			raise GlifLibError("Invalid value for attribute %s (%s)." % (attr, repr(value)))
	return infoData

# -----------------
# GLIF Tree Support
# -----------------

def _glifTreeFromFile(aFile):
	root = etree.parse(aFile).getroot()
	if root.tag != "glyph":
		raise GlifLibError("The GLIF is not properly formatted.")
	if root.text and root.text.strip() != '':
		raise GlifLibError("Invalid GLIF structure.")
	return root


def _glifTreeFromString(aString):
	data = tobytes(aString, encoding="utf-8")
	root = etree.fromstring(data)
	if root.tag != "glyph":
		raise GlifLibError("The GLIF is not properly formatted.")
	if root.text and root.text.strip() != '':
		raise GlifLibError("Invalid GLIF structure.")
	return root

def _readGlyphFromTree(tree, glyphObject=None, pointPen=None, formatVersions=(1, 2), validate=True):
	# check the format version
	formatVersion = tree.get("format")
	if validate and formatVersion is None:
		raise GlifLibError("Unspecified format version in GLIF.")
	try:
		v = int(formatVersion)
		formatVersion = v
	except ValueError:
		pass
	if validate and formatVersion not in formatVersions:
		raise GlifLibError("Forbidden GLIF format version: %s" % formatVersion)
	if formatVersion == 1:
		_readGlyphFromTreeFormat1(tree=tree, glyphObject=glyphObject, pointPen=pointPen, validate=validate)
	elif formatVersion == 2:
		_readGlyphFromTreeFormat2(tree=tree, glyphObject=glyphObject, pointPen=pointPen, validate=validate)
	else:
		raise GlifLibError("Unsupported GLIF format version: %s" % formatVersion)


def _readGlyphFromTreeFormat1(tree, glyphObject=None, pointPen=None, validate=None):
	# get the name
	_readName(glyphObject, tree, validate)
	# populate the sub elements
	unicodes = []
	haveSeenAdvance = haveSeenOutline = haveSeenLib = haveSeenNote = False
	for element in tree:
		if element.tag == "outline":
			if validate:
				if haveSeenOutline:
					raise GlifLibError("The outline element occurs more than once.")
				if element.attrib:
					raise GlifLibError("The outline element contains unknown attributes.")
				if element.text and element.text.strip() != '':
					raise GlifLibError("Invalid outline structure.")
			haveSeenOutline = True
			buildOutlineFormat1(glyphObject, pointPen, element, validate)
		elif glyphObject is None:
			continue
		elif element.tag == "advance":
			if validate and haveSeenAdvance:
				raise GlifLibError("The advance element occurs more than once.")
			haveSeenAdvance = True
			_readAdvance(glyphObject, element)
		elif element.tag == "unicode":
			try:
				v = element.get("hex")
				v = int(v, 16)
				if v not in unicodes:
					unicodes.append(v)
			except ValueError:
				raise GlifLibError("Illegal value for hex attribute of unicode element.")
		elif element.tag == "note":
			if validate and haveSeenNote:
				raise GlifLibError("The note element occurs more than once.")
			haveSeenNote = True
			_readNote(glyphObject, element)
		elif element.tag == "lib":
			if validate and haveSeenLib:
				raise GlifLibError("The lib element occurs more than once.")
			haveSeenLib = True
			_readLib(glyphObject, element, validate)
		else:
			raise GlifLibError("Unknown element in GLIF: %s" % element)
	# set the collected unicodes
	if unicodes:
		_relaxedSetattr(glyphObject, "unicodes", unicodes)

def _readGlyphFromTreeFormat2(tree, glyphObject=None, pointPen=None, validate=None):
	# get the name
	_readName(glyphObject, tree, validate)
	# populate the sub elements
	unicodes = []
	guidelines = []
	anchors = []
	haveSeenAdvance = haveSeenImage = haveSeenOutline = haveSeenLib = haveSeenNote = False
	identifiers = set()
	for element in tree:
		if element.tag == "outline":
			if validate:
				if haveSeenOutline:
					raise GlifLibError("The outline element occurs more than once.")
				if element.attrib:
					raise GlifLibError("The outline element contains unknown attributes.")
				if element.text and element.text.strip() != '':
					raise GlifLibError("Invalid outline structure.")
			haveSeenOutline = True
			if pointPen is not None:
				buildOutlineFormat2(glyphObject, pointPen, element, identifiers, validate)
		elif glyphObject is None:
			continue
		elif element.tag == "advance":
			if validate and haveSeenAdvance:
				raise GlifLibError("The advance element occurs more than once.")
			haveSeenAdvance = True
			_readAdvance(glyphObject, element)
		elif element.tag == "unicode":
			try:
				v = element.get("hex")
				v = int(v, 16)
				if v not in unicodes:
					unicodes.append(v)
			except ValueError:
				raise GlifLibError("Illegal value for hex attribute of unicode element.")
		elif element.tag == "guideline":
			if validate and len(element):
				raise GlifLibError("Unknown children in guideline element.")
			attrib = dict(element.attrib)
			for attr in ("x", "y", "angle"):
				if attr in attrib:
					attrib[attr] = _number(attrib[attr])
			guidelines.append(attrib)
		elif element.tag == "anchor":
			if validate and len(element):
				raise GlifLibError("Unknown children in anchor element.")
			attrib = dict(element.attrib)
			for attr in ("x", "y"):
				if attr in element.attrib:
					attrib[attr] = _number(attrib[attr])
			anchors.append(attrib)
		elif element.tag == "image":
			if validate:
				if haveSeenImage:
					raise GlifLibError("The image element occurs more than once.")
				if len(element):
					raise GlifLibError("Unknown children in image element.")
			haveSeenImage = True
			_readImage(glyphObject, element, validate)
		elif element.tag == "note":
			if validate and haveSeenNote:
				raise GlifLibError("The note element occurs more than once.")
			haveSeenNote = True
			_readNote(glyphObject, element)
		elif element.tag == "lib":
			if validate and haveSeenLib:
				raise GlifLibError("The lib element occurs more than once.")
			haveSeenLib = True
			_readLib(glyphObject, element, validate)
		else:
			raise GlifLibError("Unknown element in GLIF: %s" % element)
	# set the collected unicodes
	if unicodes:
		_relaxedSetattr(glyphObject, "unicodes", unicodes)
	# set the collected guidelines
	if guidelines:
		if validate and not guidelinesValidator(guidelines, identifiers):
			raise GlifLibError("The guidelines are improperly formatted.")
		_relaxedSetattr(glyphObject, "guidelines", guidelines)
	# set the collected anchors
	if anchors:
		if validate and not anchorsValidator(anchors, identifiers):
			raise GlifLibError("The anchors are improperly formatted.")
		_relaxedSetattr(glyphObject, "anchors", anchors)

def _readName(glyphObject, root, validate):
	glyphName = root.get("name")
	if validate and not glyphName:
		raise GlifLibError("Empty glyph name in GLIF.")
	if glyphName and glyphObject is not None:
		_relaxedSetattr(glyphObject, "name", glyphName)

def _readAdvance(glyphObject, advance):
	width = _number(advance.get("width", 0))
	_relaxedSetattr(glyphObject, "width", width)
	height = _number(advance.get("height", 0))
	_relaxedSetattr(glyphObject, "height", height)

def _readNote(glyphObject, note):
	lines = note.text.split("\n")
	note = "\n".join(line.strip() for line in lines if line.strip())
	_relaxedSetattr(glyphObject, "note", note)

def _readLib(glyphObject, lib, validate):
	assert len(lib) == 1
	child = lib[0]
	plist = plistlib.fromtree(child)
	if validate:
		valid, message = glyphLibValidator(plist)
		if not valid:
			raise GlifLibError(message)
	_relaxedSetattr(glyphObject, "lib", plist)

def _readImage(glyphObject, image, validate):
	imageData = dict(image.attrib)
	for attr, default in _transformationInfo:
		value = imageData.get(attr, default)
		imageData[attr] = _number(value)
	if validate and not imageValidator(imageData):
		raise GlifLibError("The image element is not properly formatted.")
	_relaxedSetattr(glyphObject, "image", imageData)

# ----------------
# GLIF to PointPen
# ----------------

contourAttributesFormat2 = set(["identifier"])
componentAttributesFormat1 = set(["base", "xScale", "xyScale", "yxScale", "yScale", "xOffset", "yOffset"])
componentAttributesFormat2 = componentAttributesFormat1 | set(["identifier"])
pointAttributesFormat1 = set(["x", "y", "type", "smooth", "name"])
pointAttributesFormat2 = pointAttributesFormat1 | set(["identifier"])
pointSmoothOptions = set(("no", "yes"))
pointTypeOptions = set(["move", "line", "offcurve", "curve", "qcurve"])

# format 1

def buildOutlineFormat1(glyphObject, pen, outline, validate):
	anchors = []
	for element in outline:
		if element.tag == "contour":
			if len(element) == 1:
				point = element[0]
				if point.tag == "point":
					anchor = _buildAnchorFormat1(point, validate)
					if anchor is not None:
						anchors.append(anchor)
						continue
			if pen is not None:
				_buildOutlineContourFormat1(pen, element, validate)
		elif element.tag == "component":
			if pen is not None:
				_buildOutlineComponentFormat1(pen, element, validate)
		else:
			raise GlifLibError("Unknown element in outline element: %s" % element)
	if glyphObject is not None and anchors:
		if validate and not anchorsValidator(anchors):
			raise GlifLibError("GLIF 1 anchors are not properly formatted.")
		_relaxedSetattr(glyphObject, "anchors", anchors)

def _buildAnchorFormat1(point, validate):
	if point.get("type") != "move":
		return None
	name = point.get("name")
	if name is None:
		return None
	x = point.get("x")
	y = point.get("y")
	if validate and x is None:
		raise GlifLibError("Required x attribute is missing in point element.")
	if validate and y is None:
		raise GlifLibError("Required y attribute is missing in point element.")
	x = _number(x)
	y = _number(y)
	anchor = dict(x=x, y=y, name=name)
	return anchor

def _buildOutlineContourFormat1(pen, contour, validate):
	if validate and contour.attrib:
		raise GlifLibError("Unknown attributes in contour element.")
	pen.beginPath()
	if len(contour):
		massaged = _validateAndMassagePointStructures(contour, pointAttributesFormat1, openContourOffCurveLeniency=True, validate=validate)
		_buildOutlinePointsFormat1(pen, massaged)
	pen.endPath()

def _buildOutlinePointsFormat1(pen, contour):
	for point in contour:
		x = point["x"]
		y = point["y"]
		segmentType = point["segmentType"]
		smooth = point["smooth"]
		name = point["name"]
		pen.addPoint((x, y), segmentType=segmentType, smooth=smooth, name=name)

def _buildOutlineComponentFormat1(pen, component, validate):
	if validate:
		if len(component):
			raise GlifLibError("Unknown child elements of component element.")
		for attr in component.attrib.keys():
			if attr not in componentAttributesFormat1:
				raise GlifLibError("Unknown attribute in component element: %s" % attr)
	baseGlyphName = component.get("base")
	if validate and baseGlyphName is None:
		raise GlifLibError("The base attribute is not defined in the component.")
	transformation = []
	for attr, default in _transformationInfo:
		value = component.get(attr)
		if value is None:
			value = default
		else:
			value = _number(value)
		transformation.append(value)
	pen.addComponent(baseGlyphName, tuple(transformation))

# format 2

def buildOutlineFormat2(glyphObject, pen, outline, identifiers, validate):
	for element in outline:
		if element.tag == "contour":
			_buildOutlineContourFormat2(pen, element, identifiers, validate)
		elif element.tag == "component":
			_buildOutlineComponentFormat2(pen, element, identifiers, validate)
		else:
			raise GlifLibError("Unknown element in outline element: %s" % element.tag)

def _buildOutlineContourFormat2(pen, contour, identifiers, validate):
	if validate:
		for attr in contour.attrib.keys():
			if attr not in contourAttributesFormat2:
				raise GlifLibError("Unknown attribute in contour element: %s" % attr)
	identifier = contour.get("identifier")
	if identifier is not None:
		if validate:
			if identifier in identifiers:
				raise GlifLibError("The identifier %s is used more than once." % identifier)
			if not identifierValidator(identifier):
				raise GlifLibError("The contour identifier %s is not valid." % identifier)
		identifiers.add(identifier)
	try:
		pen.beginPath(identifier=identifier)
	except TypeError:
		pen.beginPath()
		warn("The beginPath method needs an identifier kwarg. The contour's identifier value has been discarded.", DeprecationWarning)
	if len(contour):
		massaged = _validateAndMassagePointStructures(contour, pointAttributesFormat2, validate=validate)
		_buildOutlinePointsFormat2(pen, massaged, identifiers, validate)
	pen.endPath()

def _buildOutlinePointsFormat2(pen, contour, identifiers, validate):
	for point in contour:
		x = point["x"]
		y = point["y"]
		segmentType = point["segmentType"]
		smooth = point["smooth"]
		name = point["name"]
		identifier = point.get("identifier")
		if identifier is not None:
			if validate:
				if identifier in identifiers:
					raise GlifLibError("The identifier %s is used more than once." % identifier)
				if not identifierValidator(identifier):
					raise GlifLibError("The identifier %s is not valid." % identifier)
			identifiers.add(identifier)
		try:
			pen.addPoint((x, y), segmentType=segmentType, smooth=smooth, name=name, identifier=identifier)
		except TypeError:
			pen.addPoint((x, y), segmentType=segmentType, smooth=smooth, name=name)
			warn("The addPoint method needs an identifier kwarg. The point's identifier value has been discarded.", DeprecationWarning)

def _buildOutlineComponentFormat2(pen, component, identifiers, validate):
	if validate:
		if len(component):
			raise GlifLibError("Unknown child elements of component element.")
		for attr in component.attrib.keys():
			if attr not in componentAttributesFormat2:
				raise GlifLibError("Unknown attribute in component element: %s" % attr)
	baseGlyphName = component.get("base")
	if validate and baseGlyphName is None:
		raise GlifLibError("The base attribute is not defined in the component.")
	transformation = []
	for attr, default in _transformationInfo:
		value = component.get(attr)
		if value is None:
			value = default
		else:
			value = _number(value)
		transformation.append(value)
	identifier = component.get("identifier")
	if identifier is not None:
		if validate:
			if identifier in identifiers:
				raise GlifLibError("The identifier %s is used more than once." % identifier)
			if validate and not identifierValidator(identifier):
				raise GlifLibError("The identifier %s is not valid." % identifier)
		identifiers.add(identifier)
	try:
		pen.addComponent(baseGlyphName, tuple(transformation), identifier=identifier)
	except TypeError:
		pen.addComponent(baseGlyphName, tuple(transformation))
		warn("The addComponent method needs an identifier kwarg. The component's identifier value has been discarded.", DeprecationWarning)

# all formats

def _validateAndMassagePointStructures(contour, pointAttributes, openContourOffCurveLeniency=False, validate=True):
	if not len(contour):
		return
	# store some data for later validation
	lastOnCurvePoint = None
	haveOffCurvePoint = False
	# validate and massage the individual point elements
	massaged = []
	for index, element in enumerate(contour):
		# not <point>
		if element.tag != "point":
			raise GlifLibError("Unknown child element (%s) of contour element." % element.tag)
		point = dict(element.attrib)
		massaged.append(point)
		if validate:
			# unknown attributes
			for attr in point.keys():
				if attr not in pointAttributes:
					raise GlifLibError("Unknown attribute in point element: %s" % attr)
			# search for unknown children
			if len(element):
				raise GlifLibError("Unknown child elements in point element.")
		# x and y are required
		for attr in ("x", "y"):
			value = element.get(attr)
			if validate and value is None:
				raise GlifLibError("Required %s attribute is missing in point element." % attr)
			point[attr] = _number(value)
		# segment type
		pointType = point.pop("type", "offcurve")
		if validate and pointType not in pointTypeOptions:
			raise GlifLibError("Unknown point type: %s" % pointType)
		if pointType == "offcurve":
			pointType = None
		point["segmentType"] = pointType
		if pointType is None:
			haveOffCurvePoint = True
		else:
			lastOnCurvePoint = index
		# move can only occur as the first point
		if validate and pointType == "move" and index != 0:
			raise GlifLibError("A move point occurs after the first point in the contour.")
		# smooth is optional
		smooth = point.get("smooth", "no")
		if validate and smooth is not None:
			if smooth not in pointSmoothOptions:
				raise GlifLibError("Unknown point smooth value: %s" % smooth)
		smooth = smooth == "yes"
		point["smooth"] = smooth
		# smooth can only be applied to curve and qcurve
		if validate and smooth and pointType is None:
			raise GlifLibError("smooth attribute set in an offcurve point.")
		# name is optional
		if "name" not in element.attrib:
			point["name"] = None
	if openContourOffCurveLeniency:
		# remove offcurves that precede a move. this is technically illegal,
		# but we let it slide because there are fonts out there in the wild like this.
		if massaged[0]["segmentType"] == "move":
			count = 0
			for point in reversed(massaged):
				if point["segmentType"] is None:
					count += 1
				else:
					break
			if count:
				massaged = massaged[:-count]
	# validate the off-curves in the segments
	if validate and haveOffCurvePoint and lastOnCurvePoint is not None:
		# we only care about how many offCurves there are before an onCurve
		# filter out the trailing offCurves
		offCurvesCount = len(massaged) - 1 - lastOnCurvePoint
		for point in massaged:
			segmentType = point["segmentType"]
			if segmentType is None:
				offCurvesCount += 1
			else:
				if offCurvesCount:
					# move and line can't be preceded by off-curves
					if segmentType == "move":
						# this will have been filtered out already
						raise GlifLibError("move can not have an offcurve.")
					elif segmentType == "line":
						raise GlifLibError("line can not have an offcurve.")
					elif segmentType == "curve":
						if offCurvesCount > 2:
							raise GlifLibError("Too many offcurves defined for curve.")
					elif segmentType == "qcurve":
						pass
					else:
						# unknown segment type. it'll be caught later.
						pass
				offCurvesCount = 0
	return massaged

# ---------------------
# Misc Helper Functions
# ---------------------

def _relaxedSetattr(object, attr, value):
	try:
		setattr(object, attr, value)
	except AttributeError:
		pass

def _number(s):
	"""
	Given a numeric string, return an integer or a float, whichever
	the string indicates. _number("1") will return the integer 1,
	_number("1.0") will return the float 1.0.

	>>> _number("1")
	1
	>>> _number("1.0")
	1.0
	>>> _number("a")  # doctest: +IGNORE_EXCEPTION_DETAIL
	Traceback (most recent call last):
	    ...
	GlifLibError: Could not convert a to an int or float.
	"""
	try:
		n = int(s)
		return n
	except ValueError:
		pass
	try:
		n = float(s)
		return n
	except ValueError:
		raise GlifLibError("Could not convert %s to an int or float." % s)

# --------------------
# Rapid Value Fetching
# --------------------

# base

class _DoneParsing(Exception): pass

class _BaseParser(object):

	def __init__(self):
		self._elementStack = []

	def parse(self, text):
		from xml.parsers.expat import ParserCreate
		parser = ParserCreate()
		parser.StartElementHandler = self.startElementHandler
		parser.EndElementHandler = self.endElementHandler
		parser.Parse(text)

	def startElementHandler(self, name, attrs):
		self._elementStack.append(name)

	def endElementHandler(self, name):
		other = self._elementStack.pop(-1)
		assert other == name


# unicodes

def _fetchUnicodes(glif):
	"""
	Get a list of unicodes listed in glif.
	"""
	parser = _FetchUnicodesParser()
	parser.parse(glif)
	return parser.unicodes

class _FetchUnicodesParser(_BaseParser):

	def __init__(self):
		self.unicodes = []
		super(_FetchUnicodesParser, self).__init__()

	def startElementHandler(self, name, attrs):
		if name == "unicode" and self._elementStack and self._elementStack[-1] == "glyph":
			value = attrs.get("hex")
			if value is not None:
				try:
					value = int(value, 16)
					if value not in self.unicodes:
						self.unicodes.append(value)
				except ValueError:
					pass
		super(_FetchUnicodesParser, self).startElementHandler(name, attrs)

# image

def _fetchImageFileName(glif):
	"""
	The image file name (if any) from glif.
	"""
	parser = _FetchImageFileNameParser()
	try:
		parser.parse(glif)
	except _DoneParsing:
		pass
	return parser.fileName

class _FetchImageFileNameParser(_BaseParser):

	def __init__(self):
		self.fileName = None
		super(_FetchImageFileNameParser, self).__init__()

	def startElementHandler(self, name, attrs):
		if name == "image" and self._elementStack and self._elementStack[-1] == "glyph":
			self.fileName = attrs.get("fileName")
			raise _DoneParsing
		super(_FetchImageFileNameParser, self).startElementHandler(name, attrs)

# component references

def _fetchComponentBases(glif):
	"""
	Get a list of component base glyphs listed in glif.
	"""
	parser = _FetchComponentBasesParser()
	try:
		parser.parse(glif)
	except _DoneParsing:
		pass
	return list(parser.bases)

class _FetchComponentBasesParser(_BaseParser):

	def __init__(self):
		self.bases = []
		super(_FetchComponentBasesParser, self).__init__()

	def startElementHandler(self, name, attrs):
		if name == "component" and self._elementStack and self._elementStack[-1] == "outline":
			base = attrs.get("base")
			if base is not None:
				self.bases.append(base)
		super(_FetchComponentBasesParser, self).startElementHandler(name, attrs)

	def endElementHandler(self, name):
		if name == "outline":
			raise _DoneParsing
		super(_FetchComponentBasesParser, self).endElementHandler(name)

# --------------
# GLIF Point Pen
# --------------

_transformationInfo = [
	# field name, default value
	("xScale",    1),
	("xyScale",   0),
	("yxScale",   0),
	("yScale",    1),
	("xOffset",   0),
	("yOffset",   0),
]

class GLIFPointPen(AbstractPointPen):

	"""
	Helper class using the PointPen protocol to write the <outline>
	part of .glif files.
	"""

	def __init__(self, element, formatVersion=2, identifiers=None, validate=True):
		if identifiers is None:
			identifiers = set()
		self.formatVersion = formatVersion
		self.identifiers = identifiers
		self.outline = element
		self.contour = None
		self.prevOffCurveCount = 0
		self.prevPointTypes = []
		self.validate = validate

	def beginPath(self, identifier=None, **kwargs):
		attrs = OrderedDict()
		if identifier is not None and self.formatVersion >= 2:
			if self.validate:
				if identifier in self.identifiers:
					raise GlifLibError("identifier used more than once: %s" % identifier)
				if not identifierValidator(identifier):
					raise GlifLibError("identifier not formatted properly: %s" % identifier)
			attrs["identifier"] = identifier
			self.identifiers.add(identifier)
		self.contour = etree.SubElement(self.outline, "contour", attrs)
		self.prevOffCurveCount = 0

	def endPath(self):
		if self.prevPointTypes and self.prevPointTypes[0] == "move":
			if self.validate and self.prevPointTypes[-1] == "offcurve":
				raise GlifLibError("open contour has loose offcurve point")
		# prevent lxml from writing self-closing tags
		if not len(self.contour):
			self.contour.text = "\n  "
		self.contour = None
		self.prevPointType = None
		self.prevOffCurveCount = 0
		self.prevPointTypes = []

	def addPoint(self, pt, segmentType=None, smooth=None, name=None, identifier=None, **kwargs):
		attrs = OrderedDict()
		# coordinates
		if pt is not None:
			if self.validate:
				for coord in pt:
					if not isinstance(coord, numberTypes):
						raise GlifLibError("coordinates must be int or float")
			attrs["x"] = repr(pt[0])
			attrs["y"] = repr(pt[1])
		# segment type
		if segmentType == "offcurve":
			segmentType = None
		if self.validate:
			if segmentType == "move" and self.prevPointTypes:
				raise GlifLibError("move occurs after a point has already been added to the contour.")
			if segmentType in ("move", "line") and self.prevPointTypes and self.prevPointTypes[-1] == "offcurve":
				raise GlifLibError("offcurve occurs before %s point." % segmentType)
			if segmentType == "curve" and self.prevOffCurveCount > 2:
				raise GlifLibError("too many offcurve points before curve point.")
		if segmentType is not None:
			attrs["type"] = segmentType
		else:
			segmentType = "offcurve"
		if segmentType == "offcurve":
			self.prevOffCurveCount += 1
		else:
			self.prevOffCurveCount = 0
		self.prevPointTypes.append(segmentType)
		# smooth
		if smooth:
			if self.validate and segmentType == "offcurve":
				raise GlifLibError("can't set smooth in an offcurve point.")
			attrs["smooth"] = "yes"
		# name
		if name is not None:
			attrs["name"] = name
		# identifier
		if identifier is not None and self.formatVersion >= 2:
			if self.validate:
				if identifier in self.identifiers:
					raise GlifLibError("identifier used more than once: %s" % identifier)
				if not identifierValidator(identifier):
					raise GlifLibError("identifier not formatted properly: %s" % identifier)
			attrs["identifier"] = identifier
			self.identifiers.add(identifier)
		etree.SubElement(self.contour, "point", attrs)

	def addComponent(self, glyphName, transformation, identifier=None, **kwargs):
		attrs = OrderedDict([("base", glyphName)])
		for (attr, default), value in zip(_transformationInfo, transformation):
			if self.validate and not isinstance(value, numberTypes):
				raise GlifLibError("transformation values must be int or float")
			if value != default:
				attrs[attr] = repr(value)
		if identifier is not None and self.formatVersion >= 2:
			if self.validate:
				if identifier in self.identifiers:
					raise GlifLibError("identifier used more than once: %s" % identifier)
				if self.validate and not identifierValidator(identifier):
					raise GlifLibError("identifier not formatted properly: %s" % identifier)
			attrs["identifier"] = identifier
			self.identifiers.add(identifier)
		etree.SubElement(self.outline, "component", attrs)

if __name__ == "__main__":
	import doctest
	doctest.testmod()
