try:
    from itertools import zip_longest as zip_longest
except ImportError:
    from itertools import izip_longest as zip_longest
import collections
import os
from copy import deepcopy
from fontParts.base.errors import FontPartsError
from fontParts.base.base import (
    BaseObject,
    TransformationMixin,
    InterpolationMixin,
    SelectionMixin,
    dynamicProperty,
    interpolate,
    FuzzyNumber
)
from fontParts.base import normalizers
from fontParts.base.compatibility import GlyphCompatibilityReporter
from fontParts.base.color import Color
from fontParts.base.deprecated import DeprecatedGlyph, RemovedGlyph


class BaseGlyph(BaseObject,
                TransformationMixin,
                InterpolationMixin,
                SelectionMixin,
                DeprecatedGlyph,
                RemovedGlyph
                ):

    """
    A glyph object. This object will almost always
    be created by retrieving it from a font object.
    """

    copyAttributes = (
        "name",
        "unicodes",
        "width",
        "height",
        "note",
        "markColor",
        "lib"
    )

    def _reprContents(self):
        contents = [
            "'%s'" % self.name,
        ]
        if self.layer is not None:
            contents.append("('%s')" % self.layer.name)
        return contents

    def copy(self):
        """
        Copy this glyph's data into a new glyph object.
        This new glyph object will not belong to a font.

            >>> copiedGlyph = glyph.copy()

        This will copy:

        - name
        - unicodes
        - width
        - height
        - note
        - markColor
        - lib
        - contours
        - components
        - anchors
        - guidelines
        - image
        """
        return super(BaseGlyph, self).copy()

    def copyData(self, source):
        super(BaseGlyph, self).copyData(source)
        for contour in source.contours:
            self.appendContour(contour)
        for component in source.components:
            self.appendComponent(component=component)
        for anchor in source.anchors:
            self.appendAnchor(anchor=anchor)
        for guideline in source.guidelines:
            self.appendGuideline(guideline=guideline)
        sourceImage = source.image
        if sourceImage.data is not None:
            selfImage = self.addImage(data=sourceImage.data)
            selfImage.transformation = sourceImage.transformation
            selfImage.color = sourceImage.color

    # -------
    # Parents
    # -------

    # Layer

    _layer = None

    layer = dynamicProperty(
        "layer",
        """
        The glyph's parent layer.

            >>> layer = glyph.layer
        """
    )

    def _get_layer(self):
        if self._layer is None:
            return None
        return self._layer

    def _set_layer(self, layer):
        self._layer = layer

    # Font

    font = dynamicProperty(
        "font",
        """
        The glyph's parent font.

            >>> font = glyph.font
        """
    )

    def _get_font(self):
        if self._layer is None:
            return None
        return self.layer.font

    # --------------
    # Identification
    # --------------

    # Name

    name = dynamicProperty(
        "base_name",
        """
        The glyph's name. This will be a :ref:`type-string`.

            >>> glyph.name
            "A"
            >>> glyph.name = "A.alt"
        """
    )

    def _get_base_name(self):
        value = self._get_name()
        if value is not None:
            value = normalizers.normalizeGlyphName(value)
        return value

    def _set_base_name(self, value):
        if value == self.name:
            return
        value = normalizers.normalizeGlyphName(value)
        layer = self.layer
        if layer is not None and value in layer:
            raise ValueError("A glyph with the name '%s' already exists."
                             % value)
        self._set_name(value)

    def _get_name(self):
        """
        Get the name of the glyph.
        This must return a unicode string.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def _set_name(self, value):
        """
        Set the name of the glyph.
        This will be a unicode string.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    # Unicodes

    unicodes = dynamicProperty(
        "base_unicodes",
        """
        The glyph's unicode values in order from most to least important.

            >>> glyph.unicodes
            (65,)
            >>> glyph.unicodes = [65, 66]
            >>> glyph.unicodes = []

        The values in the returned tuple will be :ref:`type-int`.
        When setting you may use a list of :ref:`type-int` or
        :ref:`type-hex` values.
        """
    )

    def _get_base_unicodes(self):
        value = self._get_unicodes()
        value = normalizers.normalizeGlyphUnicodes(value)
        return value

    def _set_base_unicodes(self, value):
        value = list(value)
        value = normalizers.normalizeGlyphUnicodes(value)
        self._set_unicodes(value)

    def _get_unicodes(self):
        """
        Get the unicodes assigned to the glyph.
        This must return a tuple of zero or more integers.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def _set_unicodes(self, value):
        """
        Assign the unicodes to the glyph.
        This will be a list of zero or more integers.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    unicode = dynamicProperty(
        "base_unicode",
        """
        The glyph's primary unicode value.

            >>> glyph.unicode
            65
            >>> glyph.unicode = None

        This is equivalent to ``glyph.unicodes[0]``. Setting a
        ``glyph.unicode`` value will reset ``glyph.unicodes`` to a tuple
        containing that value or an empty tuple if ``value`` is ``None``.

            >>> glyph.unicodes
            (65, 67)
            >>> glyph.unicode = 65
            >>> glyph.unicodes
            (65,)
            >>> glyph.unicode = None
            >>> glyph.unicodes
            ()

        The returned value will be an :ref:`type-int` or ``None``.
        When setting you may send :ref:`type-int` or :ref:`type-hex`
        values or ``None``.
        """
    )

    def _get_base_unicode(self):
        value = self._get_unicode()
        if value is not None:
            value = normalizers.normalizeGlyphUnicode(value)
        return value

    def _set_base_unicode(self, value):
        if value is not None:
            value = normalizers.normalizeGlyphUnicode(value)
            self._set_unicode(value)
        else:
            self._set_unicodes(())

    def _get_unicode(self):
        """
        Get the primary unicode assigned to the glyph.
        This must return an integer or None.

        Subclasses may override this method.
        """
        values = self.unicodes
        if values:
            return values[0]
        return None

    def _set_unicode(self, value):
        """
        Assign the primary unicode to the glyph.
        This will be an integer or None.

        Subclasses may override this method.
        """
        if value is None:
            self.unicodes = []
        else:
            self.unicodes = [value]

    def autoUnicodes(self):
        """
        Use heuristics to set the Unicode values in the glyph.

            >>> glyph.autoUnicodes()

        Environments will define their own heuristics for
        automatically determining values.
        """
        self._autoUnicodes()

    def _autoUnicodes(self):
        """
        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    # -------
    # Metrics
    # -------

    # horizontal

    width = dynamicProperty(
        "base_width",
        """
        The glyph's width.

            >>> glyph.width
            500
            >>> glyph.width = 200

        The value will be a :ref:`type-int-float`.
        """
    )

    def _get_base_width(self):
        value = self._get_width()
        value = normalizers.normalizeGlyphWidth(value)
        return value

    def _set_base_width(self, value):
        value = normalizers.normalizeGlyphWidth(value)
        self._set_width(value)

    def _get_width(self):
        """
        This must return an int or float.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def _set_width(self, value):
        """
        value will be an int or float.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    leftMargin = dynamicProperty(
        "base_leftMargin",
        """
        The glyph's left margin.

            >>> glyph.leftMargin
            35
            >>> glyph.leftMargin = 45

        The value will be a :ref:`type-int-float`
        or `None` if the glyph has no outlines.
        """
    )

    def _get_base_leftMargin(self):
        value = self._get_leftMargin()
        value = normalizers.normalizeGlyphLeftMargin(value)
        return value

    def _set_base_leftMargin(self, value):
        value = normalizers.normalizeGlyphLeftMargin(value)
        self._set_leftMargin(value)

    def _get_leftMargin(self):
        """
        This must return an int or float.
        If the glyph has no outlines, this must return `None`.

        Subclasses may override this method.
        """
        bounds = self.bounds
        if bounds is None:
            return None
        xMin, yMin, xMax, yMax = bounds
        return xMin

    def _set_leftMargin(self, value):
        """
        value will be an int or float.

        Subclasses may override this method.
        """
        diff = value - self.leftMargin
        self.moveBy((diff, 0))
        self.width += diff

    rightMargin = dynamicProperty(
        "base_rightMargin",
        """
        The glyph's right margin.

            >>> glyph.rightMargin
            35
            >>> glyph.rightMargin = 45

        The value will be a :ref:`type-int-float`
        or `None` if the glyph has no outlines.
        """
    )

    def _get_base_rightMargin(self):
        value = self._get_rightMargin()
        value = normalizers.normalizeGlyphRightMargin(value)
        return value

    def _set_base_rightMargin(self, value):
        value = normalizers.normalizeGlyphRightMargin(value)
        self._set_rightMargin(value)

    def _get_rightMargin(self):
        """
        This must return an int or float.
        If the glyph has no outlines, this must return `None`.

        Subclasses may override this method.
        """
        bounds = self.bounds
        if bounds is None:
            return None
        xMin, yMin, xMax, yMax = bounds
        return self.width - xMax

    def _set_rightMargin(self, value):
        """
        value will be an int or float.

        Subclasses may override this method.
        """
        bounds = self.bounds
        if bounds is None:
            self.width = value
        else:
            xMin, yMin, xMax, yMax = bounds
            self.width = xMax + value

    # vertical

    height = dynamicProperty(
        "base_height",
        """
        The glyph's height.

            >>> glyph.height
            500
            >>> glyph.height = 200

        The value will be a :ref:`type-int-float`.
        """
    )

    def _get_base_height(self):
        value = self._get_height()
        value = normalizers.normalizeGlyphHeight(value)
        return value

    def _set_base_height(self, value):
        value = normalizers.normalizeGlyphHeight(value)
        self._set_height(value)

    def _get_height(self):
        """
        This must return an int or float.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def _set_height(self, value):
        """
        value will be an int or float.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    bottomMargin = dynamicProperty(
        "base_bottomMargin",
        """
        The glyph's bottom margin.

            >>> glyph.bottomMargin
            35
            >>> glyph.bottomMargin = 45

        The value will be a :ref:`type-int-float`
        or `None` if the glyph has no outlines.
        """
    )

    def _get_base_bottomMargin(self):
        value = self._get_bottomMargin()
        value = normalizers.normalizeGlyphBottomMargin(value)
        return value

    def _set_base_bottomMargin(self, value):
        value = normalizers.normalizeGlyphBottomMargin(value)
        self._set_bottomMargin(value)

    def _get_bottomMargin(self):
        """
        This must return an int or float.
        If the glyph has no outlines, this must return `None`.

        Subclasses may override this method.
        """
        bounds = self.bounds
        if bounds is None:
            return None
        xMin, yMin, xMax, yMax = bounds
        return yMin

    def _set_bottomMargin(self, value):
        """
        value will be an int or float.

        Subclasses may override this method.
        """
        diff = value - self.bottomMargin
        self.moveBy((0, diff))
        self.height += diff

    topMargin = dynamicProperty(
        "base_topMargin",
        """
        The glyph's top margin.

            >>> glyph.topMargin
            35
            >>> glyph.topMargin = 45

        The value will be a :ref:`type-int-float`
        or `None` if the glyph has no outlines.
        """
    )

    def _get_base_topMargin(self):
        value = self._get_topMargin()
        value = normalizers.normalizeGlyphTopMargin(value)
        return value

    def _set_base_topMargin(self, value):
        value = normalizers.normalizeGlyphTopMargin(value)
        self._set_topMargin(value)

    def _get_topMargin(self):
        """
        This must return an int or float.
        If the glyph has no outlines, this must return `None`.

        Subclasses may override this method.
        """
        bounds = self.bounds
        if bounds is None:
            return None
        xMin, yMin, xMax, yMax = bounds
        return self.height - yMax

    def _set_topMargin(self, value):
        """
        value will be an int or float.

        Subclasses may override this method.
        """
        bounds = self.bounds
        if bounds is None:
            self.height = value
        else:
            xMin, yMin, xMax, yMax = bounds
            self.height = yMax + value

    # ----
    # Pens
    # ----

    def getPen(self):
        """
        Return a :ref:`type-pen` object for adding outline data
        to the glyph.

            >>> pen = glyph.getPen()
        """
        self.raiseNotImplementedError()

    def getPointPen(self):
        """
        Return a :ref:`type-pointpen` object for adding outline data
        to the glyph.

            >>> pointPen = glyph.getPointPen()
        """
        self.raiseNotImplementedError()

    def draw(self, pen, contours=True, components=True):
        """
        Draw the glyph's outline data (contours and components) to
        the given :ref:`type-pen`.

            >>> glyph.draw(pen)

        If ``contours`` is set to ``False``, the glyph's
        contours will not be drawn.

            >>> glyph.draw(pen, contours=False)

        If ``components`` is set to ``False``, the glyph's
        components will not be drawn.

            >>> glyph.draw(pen, components=False)
        """
        if contours:
            for contour in self:
                contour.draw(pen)
        if components:
            for component in self.components:
                component.draw(pen)

    def drawPoints(self, pen, contours=True, components=True):
        """
        Draw the glyph's outline data (contours and components) to
        the given :ref:`type-pointpen`.

            >>> glyph.drawPoints(pointPen)

        If ``contours`` is set to ``False``, the glyph's
        contours will not be drawn.

            >>> glyph.drawPoints(pointPen, contours=False)

        If ``components`` is set to ``False``, the glyph's
        components will not be drawn.

            >>> glyph.drawPoints(pointPen, components=False)
        """
        if contours:
            for contour in self:
                contour.drawPoints(pen)
        if components:
            for component in self.components:
                component.drawPoints(pen)

    # -----------------------------------------
    # Contour, Component and Anchor Interaction
    # -----------------------------------------

    def clear(self, contours=True, components=True, anchors=True,
              guidelines=True, image=True):
        """
        Clear the glyph.

            >>> glyph.clear()

        This clears:

        - contours
        - components
        - anchors
        - guidelines
        - image

        It's possible to turn off the clearing of portions of
        the glyph with the listed arguments.

            >>> glyph.clear(guidelines=False)
        """
        self._clear(contours=contours, components=components,
                    anchors=anchors, guidelines=guidelines, image=image)

    def _clear(self, contours=True, components=True, anchors=True,
               guidelines=True, image=True):
        """
        Subclasses may override this method.
        """
        if contours:
            self.clearContours()
        if components:
            self.clearComponents()
        if anchors:
            self.clearAnchors()
        if guidelines:
            self.clearGuidelines()
        if image:
            self.clearImage()

    def appendGlyph(self, other, offset=None):
        """
        Append the data from ``other`` to new objects in this glyph.

            >>> glyph.appendGlyph(otherGlyph)

        This will append:

        - contours
        - components
        - anchors
        - guidelines

        ``offset`` indicates the x and y shift values that should
        be applied to the appended data. It must be a :ref:`type-coordinate`
        value or ``None``. If ``None`` is given, the offset will be ``(0, 0)``.

            >>> glyph.appendGlyph(otherGlyph, (100, 0))
        """
        if offset is None:
            offset = (0, 0)
        offset = normalizers.normalizeTransformationOffset(offset)
        self._appendGlyph(other, offset)

    def _appendGlyph(self, other, offset=None):
        """
        Subclasses may override this method.
        """
        other = other.copy()
        if offset != (0, 0):
            other.moveBy(offset)
        for contour in other.contours:
            self.appendContour(contour)
        for component in other.components:
            self.appendComponent(component=component)
        for anchor in other.anchors:
            self.appendAnchor(anchor=anchor)
        for guideline in other.guidelines:
            self.appendGuideline(guideline=guideline)

    # Contours

    def _setGlyphInContour(self, contour):
        if contour.glyph is None:
            contour.glyph = self

    contours = dynamicProperty(
        "contours",
        """
        An :ref:`type-immutable-list` of all contours in the glyph.

            >>> contours = glyph.contours

        The list will contain :class:`BaseContour` objects.
        """
    )

    def _get_contours(self):
        """
        Subclasses may override this method.
        """
        return tuple([self[i] for i in range(len(self))])

    def __len__(self):
        """
        The number of contours in the glyph.

            >>> len(glyph)
            2
        """
        return self._lenContours()

    def _lenContours(self, **kwargs):
        """
        This must return an integer.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def __iter__(self):
        """
        Iterate through all contours in the glyph.

            >>> for contour in glyph:
            ...     contour.reverse()
        """
        return self._iterContours()

    def _iterContours(self, **kwargs):
        """
        This must return an iterator that returns wrapped contours.

        Subclasses may override this method.
        """
        count = len(self)
        index = 0
        while count:
            yield self[index]
            count -= 1
            index += 1

    def __getitem__(self, index):
        """
        Get the contour located at ``index`` from the glyph.

            >>> contour = glyph[0]

        The returned value will be a :class:`BaseContour` object.
        """
        index = normalizers.normalizeIndex(index)
        if index >= len(self):
            raise ValueError("No contour located at index %d." % index)
        contour = self._getContour(index)
        self._setGlyphInContour(contour)
        return contour

    def _getContour(self, index, **kwargs):
        """
        This must return a wrapped contour.

        index will be a valid index.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def _getContourIndex(self, contour):
        for i, other in enumerate(self.contours):
            if contour == other:
                return i
        raise FontPartsError("The contour could not be found.")

    def appendContour(self, contour, offset=None):
        """
        Append a contour containing the same data as ``contour``
        to this glyph.

            >>> contour = glyph.appendContour(contour)

        This will return a :class:`BaseContour` object representing
        the new contour in the glyph. ``offset`` indicates the x and
        y shift values that should be applied to the appended data.
        It must be a :ref:`type-coordinate` value or ``None``. If
        ``None`` is given, the offset will be ``(0, 0)``.

            >>> contour = glyph.appendContour(contour, (100, 0))
        """
        contour = normalizers.normalizeContour(contour)
        if offset is None:
            offset = (0, 0)
        offset = normalizers.normalizeTransformationOffset(offset)
        return self._appendContour(contour, offset)

    def _appendContour(self, contour, offset=None, **kwargs):
        """
        contour will be an object with a drawPoints method.

        offset will be a valid offset (x, y).

        This must return the new contour.

        Subclasses may override this method.
        """
        pointPen = self.getPointPen()
        if offset != (0, 0):
            copy = contour.copy()
            copy.moveBy(offset)
            copy.drawPoints(pointPen)
        else:
            contour.drawPoints(pointPen)
        return self[-1]

    def removeContour(self, contour):
        """
        Remove ``contour`` from the glyph.

            >>> glyph.removeContour(contour)

        ``contour`` may be a :ref:`BaseContour` or an :ref:`type-int`
        representing a contour index.
        """
        if isinstance(contour, int):
            index = contour
        else:
            index = self._getContourIndex(contour)
        index = normalizers.normalizeIndex(index)
        if index >= len(self):
            raise ValueError("No contour located at index %d." % index)
        self._removeContour(index)

    def _removeContour(self, index, **kwargs):
        """
        index will be a valid index.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def clearContours(self):
        """
        Clear all contours in the glyph.

            >>> glyph.clearContours()
        """
        self._clearContours()

    def _clearContours(self):
        """
        Subclasses may override this method.
        """
        for _ in range(len(self)):
            self.removeContour(-1)

    def removeOverlap(self):
        """
        Perform a remove overlap operation on the contours.

            >>> glyph.removeOverlap()

        The behavior of this may vary across environments.
        """
        self._removeOverlap()

    def _removeOverlap(self):
        """
        Subclasses must implement this method.
        """
        self.raiseNotImplementedError()

    # Components

    def _setGlyphInComponent(self, component):
        if component.glyph is None:
            component.glyph = self

    components = dynamicProperty(
        "components",
        """
        An :ref:`type-immutable-list` of all components in the glyph.

            >>> components = glyph.components

        The list will contain :class:`BaseComponent` objects.
        """
    )

    def _get_components(self):
        """
        Subclasses may override this method.
        """
        return tuple([self._getitem__components(i) for
                     i in range(self._len__components())])

    def _len__components(self):
        return self._lenComponents()

    def _lenComponents(self, **kwargs):
        """
        This must return an integer indicating
        the number of components in the glyph.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def _getitem__components(self, index):
        index = normalizers.normalizeIndex(index)
        if index >= self._len__components():
            raise ValueError("No component located at index %d." % index)
        component = self._getComponent(index)
        self._setGlyphInComponent(component)
        return component

    def _getComponent(self, index, **kwargs):
        """
        This must return a wrapped component.

        index will be a valid index.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def _getComponentIndex(self, component):
        for i, other in enumerate(self.components):
            if component == other:
                return i
        raise FontPartsError("The component could not be found.")

    def appendComponent(self, baseGlyph=None, offset=None, scale=None, component=None):
        """
        Append a component to this glyph.

            >>> component = glyph.appendComponent("A")

        This will return a :class:`BaseComponent` object representing
        the new component in the glyph. ``offset`` indicates the x and
        y shift values that should be applied to the appended component.
        It must be a :ref:`type-coordinate` value or ``None``. If
        ``None`` is given, the offset will be ``(0, 0)``.

            >>> component = glyph.appendComponent("A", offset=(10, 20))

        ``scale`` indicates the x and y scale values that should be
        applied to the appended component. It must be a
        :ref:`type-scale` value or ``None``. If ``None`` is given,
        the scale will be ``(1.0, 1.0)``.

            >>> component = glyph.appendComponent("A", scale=(1.0, 2.0))

        ``component`` may be a :class:`BaseComponent` object from which
        attribute values will be copied. If ``baseGlyph``, ``offset``
        or ``scale`` are specified as arguments, those values will be used
        instead of the values in the given component object.
        """
        identifier = None
        sxy = 0
        syx = 0
        if component is not None:
            component = normalizers.normalizeComponent(component)
            if baseGlyph is None:
                baseGlyph = component.baseGlyph
            sx, sxy, syx, sy, ox, oy = component.transformation
            if offset is None:
                offset = (ox, oy)
            if scale is None:
                scale = (sx, sy)
            if baseGlyph is None:
                baseGlyph = component.baseGlyph
            if component.identifier is not None:
                existing = set([c.identifier for c in self.components if c.identifier is not None])
                if component.identifier not in existing:
                    identifier = component.identifier
        baseGlyph = normalizers.normalizeGlyphName(baseGlyph)
        if self.name == baseGlyph:
            raise FontPartsError(("A glyph cannot contain a component referencing itself."))
        if offset is None:
            offset = (0, 0)
        if scale is None:
            scale = (1, 1)
        offset = normalizers.normalizeTransformationOffset(offset)
        scale = normalizers.normalizeTransformationScale(scale)
        ox, oy = offset
        sx, sy = scale
        transformation = (sx, sxy, syx, sy, ox, oy)
        identifier = normalizers.normalizeIdentifier(identifier)
        return self._appendComponent(baseGlyph, transformation=transformation, identifier=identifier)

    def _appendComponent(self, baseGlyph, transformation=None, identifier=None, **kwargs):
        """
        baseGlyph will be a valid glyph name.
        The baseGlyph may or may not be in the layer.

        offset will be a valid offset (x, y).
        scale will be a valid scale (x, y).
        identifier will be a valid, nonconflicting identifier.

        This must return the new component.

        Subclasses may override this method.
        """
        pointPen = self.getPointPen()
        pointPen.addComponent(baseGlyph, transformation=transformation, identifier=identifier)
        return self.components[-1]

    def removeComponent(self, component):
        """
        Remove ``component`` from the glyph.

            >>> glyph.removeComponent(component)

        ``component`` may be a :ref:`BaseComponent` or an
        :ref:`type-int` representing a component index.
        """
        if isinstance(component, int):
            index = component
        else:
            index = self._getComponentIndex(component)
        index = normalizers.normalizeIndex(index)
        if index >= self._len__components():
            raise ValueError("No component located at index %d." % index)
        self._removeComponent(index)

    def _removeComponent(self, index, **kwargs):
        """
        index will be a valid index.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def clearComponents(self):
        """
        Clear all components in the glyph.

            >>> glyph.clearComponents()
        """
        self._clearComponents()

    def _clearComponents(self):
        """
        Subclasses may override this method.
        """
        for _ in range(self._len__components()):
            self.removeComponent(-1)

    def decompose(self):
        """
        Decompose all components in the glyph to contours.

            >>> glyph.decompose()
        """
        self._decompose()

    def _decompose(self):
        """
        Subclasses may override this method.
        """
        for component in self.components:
            component.decompose()

    # Anchors

    def _setGlyphInAnchor(self, anchor):
        if anchor.glyph is None:
            anchor.glyph = self

    anchors = dynamicProperty(
        "anchors",
        """
        An :ref:`type-immutable-list` of all anchors in the glyph.

            >>> anchors = glyph.anchors

        The list will contain :class:`BaseAnchor` objects.
        """
    )

    def _get_anchors(self):
        """
        Subclasses may override this method.
        """
        return tuple([self._getitem__anchors(i) for
                     i in range(self._len__anchors())])

    def _len__anchors(self):
        return self._lenAnchors()

    def _lenAnchors(self, **kwargs):
        """
        This must return an integer indicating
        the number of anchors in the glyph.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def _getitem__anchors(self, index):
        index = normalizers.normalizeIndex(index)
        if index >= self._len__anchors():
            raise ValueError("No anchor located at index %d." % index)
        anchor = self._getAnchor(index)
        self._setGlyphInAnchor(anchor)
        return anchor

    def _getAnchor(self, index, **kwargs):
        """
        This must return a wrapped anchor.

        index will be a valid index.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def _getAnchorIndex(self, anchor):
        for i, other in enumerate(self.anchors):
            if anchor == other:
                return i
        raise FontPartsError("The anchor could not be found.")

    def appendAnchor(self, name=None, position=None, color=None, anchor=None):
        """
        Append an anchor to this glyph.

            >>> anchor = glyph.appendAnchor("top", (10, 20))

        This will return a :class:`BaseAnchor` object representing
        the new anchor in the glyph. ``name`` indicated the name to
        be assigned to the anchor. It must be a :ref:`type-string`
        or ``None``. ``position`` indicates the x and y location
        to be applied to the anchor. It must be a
        :ref:`type-coordinate` value. ``color`` indicates the color
        to be applied to the anchor. It must be a :ref:`type-color`
        or ``None``.

            >>> anchor = glyph.appendAnchor("top", (10, 20), color=(1, 0, 0, 1))

        ``anchor`` may be a :class:`BaseAnchor` object from which
        attribute values will be copied. If ``name``, ``position``
        or ``color`` are specified as arguments, those values will
        be used instead of the values in the given anchor object.
        """
        identifier = None
        if anchor is not None:
            anchor = normalizers.normalizeAnchor(anchor)
            if name is None:
                name = anchor.name
            if position is None:
                position = anchor.position
            if color is None:
                color = anchor.color
            if anchor.identifier is not None:
                existing = set([a.identifier for a in self.anchors if a.identifier is not None])
                if anchor.identifier not in existing:
                    identifier = anchor.identifier
        name = normalizers.normalizeAnchorName(name)
        position = normalizers.normalizeCoordinateTuple(position)
        if color is not None:
            color = normalizers.normalizeColor(color)
        identifier = normalizers.normalizeIdentifier(identifier)
        return self._appendAnchor(name, position=position, color=color, identifier=identifier)

    def _appendAnchor(self, name, position=None, color=None, identifier=None, **kwargs):
        """
        name will be a valid anchor name.
        position will be a valid position (x, y).
        color will be None or a valid color.
        identifier will be a valid, nonconflicting identifier.

        This must return the new anchor.

        Subclasses may override this method.
        """
        self.raiseNotImplementedError()

    def removeAnchor(self, anchor):
        """
        Remove ``anchor`` from the glyph.

            >>> glyph.removeAnchor(anchor)

        ``anchor`` may be an :ref:`BaseAnchor` or an
        :ref:`type-int` representing an anchor index.
        """
        if isinstance(anchor, int):
            index = anchor
        else:
            index = self._getAnchorIndex(anchor)
        index = normalizers.normalizeIndex(index)
        if index >= self._len__anchors():
            raise ValueError("No anchor located at index %d." % index)
        self._removeAnchor(index)

    def _removeAnchor(self, index, **kwargs):
        """
        index will be a valid index.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def clearAnchors(self):
        """
        Clear all anchors in the glyph.

            >>> glyph.clearAnchors()
        """
        self._clearAnchors()

    def _clearAnchors(self):
        """
        Subclasses may override this method.
        """
        for _ in range(self._len__anchors()):
            self.removeAnchor(-1)

    # ----------
    # Guidelines
    # ----------

    def _setGlyphInGuideline(self, guideline):
        if guideline.glyph is None:
            guideline.glyph = self

    guidelines = dynamicProperty(
        "guidelines",
        """
        An :ref:`type-immutable-list` of all guidelines in the glyph.

            >>> guidelines = glyph.guidelines

        The list will contain :class:`BaseGuideline` objects.
        """
    )

    def _get_guidelines(self):
        """
        Subclasses may override this method.
        """
        return tuple([self._getitem__guidelines(i) for
                     i in range(self._len__guidelines())])

    def _len__guidelines(self):
        return self._lenGuidelines()

    def _lenGuidelines(self, **kwargs):
        """
        This must return an integer indicating
        the number of guidelines in the glyph.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def _getitem__guidelines(self, index):
        index = normalizers.normalizeIndex(index)
        if index >= self._len__guidelines():
            raise ValueError("No guideline located at index %d." % index)
        guideline = self._getGuideline(index)
        self._setGlyphInGuideline(guideline)
        return guideline

    def _getGuideline(self, index, **kwargs):
        """
        This must return a wrapped guideline.

        index will be a valid index.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def _getGuidelineIndex(self, guideline):
        for i, other in enumerate(self.guidelines):
            if guideline == other:
                return i
        raise FontPartsError("The guideline could not be found.")

    def appendGuideline(self, position=None, angle=None, name=None, color=None, guideline=None):
        """
        Append a guideline to this glyph.

            >>> guideline = glyph.appendGuideline((100, 0), 90)

        This will return a :class:`BaseGuideline` object representing
        the new guideline in the glyph. ``position`` indicates the
        x and y location to be used as the center point of the anchor.
        It must be a :ref:`type-coordinate` value. ``angle`` indicates
        the angle of the guideline, in degrees. This must be a
        :ref:`type-int-float` between 0 and 360. ``name`` indicates
        an name to be assigned to the guideline. It must be a
        :ref:`type-string` or ``None``.

            >>> guideline = glyph.appendGuideline((100, 0), 90, name="left")

        ``color`` indicates the color to be applied to the guideline.
        It must be a :ref:`type-color` or ``None``.

            >>> guideline = glyph.appendGuideline((100, 0), 90, color=(1, 0, 0, 1))

        ``guideline`` may be a :class:`BaseGuideline` object from which
        attribute values will be copied. If ``position``, ``angle``, ``name``
        or ``color`` are specified as arguments, those values will be used
        instead of the values in the given guideline object.
        """
        identifier = None
        if guideline is not None:
            guideline = normalizers.normalizeGuideline(guideline)
            if position is None:
                position = guideline.position
            if angle is None:
                angle = guideline.angle
            if name is None:
                name = guideline.name
            if color is None:
                color = guideline.color
            if guideline.identifier is not None:
                existing = set([g.identifier for g in self.guidelines if g.identifier is not None])
                if guideline.identifier not in existing:
                    identifier = guideline.identifier
        position = normalizers.normalizeCoordinateTuple(position)
        angle = normalizers.normalizeRotationAngle(angle)
        if name is not None:
            name = normalizers.normalizeGuidelineName(name)
        if color is not None:
            color = normalizers.normalizeColor(color)
        identifier = normalizers.normalizeIdentifier(identifier)
        guideline = self._appendGuideline(position, angle, name=name, color=color, identifier=identifier)
        guideline.glyph = self
        return guideline

    def _appendGuideline(self, position, angle, name=None, color=None, identifier=None, **kwargs):
        """
        position will be a valid position (x, y).
        angle will be a valid angle.
        name will be a valid guideline name or None.
        color will be a valid color or None .
        identifier will be a valid, nonconflicting identifier.

        This must return the new guideline.

        Subclasses may override this method.
        """
        self.raiseNotImplementedError()

    def removeGuideline(self, guideline):
        """
        Remove ``guideline`` from the glyph.

            >>> glyph.removeGuideline(guideline)

        ``guideline`` may be a :ref:`BaseGuideline` or an
        :ref:`type-int` representing an guideline index.
        """
        if isinstance(guideline, int):
            index = guideline
        else:
            index = self._getGuidelineIndex(guideline)
        index = normalizers.normalizeIndex(index)
        if index >= self._len__guidelines():
            raise ValueError("No guideline located at index %d." % index)
        self._removeGuideline(index)

    def _removeGuideline(self, index, **kwargs):
        """
        index will be a valid index.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def clearGuidelines(self):
        """
        Clear all guidelines in the glyph.

            >>> glyph.clearGuidelines()
        """
        self._clearGuidelines()

    def _clearGuidelines(self):
        """
        Subclasses may override this method.
        """
        for _ in range(self._len__guidelines()):
            self.removeGuideline(-1)

    # ------------------
    # Data Normalization
    # ------------------

    def round(self):
        """
        Round coordinates to the nearest integer.

            >>> glyph.round()

        This applies to the following:

        - width
        - height
        - contours
        - components
        - anchors
        - guidelines
        - image
        """
        self._round()

    def _round(self):
        """
        Subclasses may override this method.
        """
        for contour in self.contours:
            contour.round()
        for component in self.components:
            component.round()
        for anchor in self.anchors:
            anchor.round()
        for guideline in self.guidelines:
            guideline.round()
        if self.image.data is not None:
            image.round()
        self.width = normalizers.normalizeVisualRounding(self.width)
        self.height = normalizers.normalizeVisualRounding(self.height)

    def correctDirection(self, trueType=False):
        """
        Correct the winding direction of the contours following
        the PostScript recommendations.

            >>> glyph.correctDirection()

        If ``trueType`` is ``True`` the TrueType recommendations
        will be followed.
        """
        self._correctDirection(trueType=trueType)

    def _correctDirection(self, trueType=False, **kwargs):
        """
        Subclasses may override this method.
        """
        self.raiseNotImplementedError()

    def autoContourOrder(self):
        """
        Automatically order the contours based on heuristics.

            >>> glyph.autoContourOrder()

        The results of this may vary across environments.
        """
        self._autoContourOrder()

    def _autoContourOrder(self, **kwargs):
        """
        Sorting is based on (in this order):
        - the (negative) point count
        - the (negative) segment count
        - x value of the center of the contour rounded to a threshold
        - y value of the center of the contour rounded to a threshold
          (such threshold is calculated as the smallest contour width
          or height in the glyph divided by two)
        - the (negative) surface of the bounding box of the contour: width * height
        the latter is a safety net for for instances like a very thin 'O' where the
        x centers could be close enough to rely on the y for the sort which could
        very well be the same for both contours. We use the _negative_ of the surface
        to ensure that larger contours appear first, which seems more natural.
        """
        tempContourList = []
        contourList = []
        xThreshold = None
        yThreshold = None

        for contour in self:
            bounds = contour.bounds
            if bounds is None:
                continue
            xMin, yMin, xMax, yMax = bounds
            width = xMax - xMin
            height = yMax - yMin
            xC = 0.5 * (xMin + xMax)
            yC = 0.5 * (yMin + yMax)
            xTh = abs(width * 0.5)
            yTh = abs(height * 0.5)
            if xThreshold is None or xThreshold > xTh:
                xThreshold = xTh
            if yThreshold is None or yThreshold > yTh:
                yThreshold = yTh
            tempContourList.append((-len(contour.points), -len(contour.segments), xC, yC, -(width * height), contour))

        for points, segments, x, y, surface, contour in tempContourList:
            contourList.append((points, segments, FuzzyNumber(x, xThreshold), FuzzyNumber(y, yThreshold), surface, contour))
        contourList.sort()

        self.clearContours()
        for points, segments, xO, yO, surface, contour in contourList:
            self.appendContour(contour)

    # --------------
    # Transformation
    # --------------

    def _transformBy(self, matrix, **kwargs):
        """
        Subclasses may override this method.
        """
        for contour in self.contours:
            contour.transformBy(matrix)
        for component in self.components:
            component.transformBy(matrix)
        for anchor in self.anchors:
            anchor.transformBy(matrix)
        for guideline in self.guidelines:
            guideline.transformBy(matrix)

    def scaleBy(self, value, origin=None, width=False, height=False):
        """
        %s
        **width** indicates if the glyph's width should be scaled.
        **height** indicates if the glyph's height should be scaled.

        The origin must not be specified when scaling the width or height.
        """
        value = normalizers.normalizeTransformationScale(value)
        if origin is None:
            origin = (0, 0)
        origin = normalizers.normalizeCoordinateTuple(origin)
        if origin != (0, 0) and (width or height):
            raise FontPartsError(("The origin must not be set when "
                                  "scaling the width or height."))
        super(BaseGlyph, self).scaleBy(value, origin=origin)
        sX, sY = value
        if width:
            self._scaleWidthBy(sX)
        if height:
            self._scaleHeightBy(sY)

    scaleBy.__doc__ %= TransformationMixin.scaleBy.__doc__

    def _scaleWidthBy(self, value):
        """
        Subclasses may override this method.
        """
        self.width *= value

    def _scaleHeightBy(self, value):
        """
        Subclasses may override this method.
        """
        self.height *= value

    # --------------------
    # Interpolation & Math
    # --------------------

    def toMathGlyph(self, scaleComponentTransform=True, strict=False):
        """
        Returns the glyph as an object that follows the
        `MathGlyph protocol <https://github.com/typesupply/fontMath>`_.

            >>> mg = glyph.toMathGlyph()

        **scaleComponentTransform** Enables the MathGlyph
          `scaleComponentTransform` option.
        **strict**  Enables the MathGlyph `strict` option.
        """
        return self._toMathGlyph(scaleComponentTransform=scaleComponentTransform, strict=strict)

    def _toMathGlyph(self, scaleComponentTransform=True, strict=False):
        """
        Subclasses may override this method.
        """
        import fontMath
        mathGlyph = fontMath.MathGlyph(
            None,
            scaleComponentTransform=scaleComponentTransform,
            strict=strict
        )
        pen = mathGlyph.getPointPen()
        self.drawPoints(pen)
        for anchor in self.anchors:
            d = dict(
                x=anchor.x,
                y=anchor.y,
                name=anchor.name,
                identifier=anchor.identifier,
                color=anchor.color
            )
            mathGlyph.anchors.append(d)
        for guideline in self.guidelines:
            d = dict(
                x=guideline.x,
                y=guideline.y,
                angle=guideline.angle,
                name=guideline.name,
                identifier=guideline.identifier,
                color=guideline.color
            )
            mathGlyph.guidelines.append(d)
        mathGlyph.lib = deepcopy(self.lib)
        mathGlyph.name = self.name
        mathGlyph.unicodes = self.unicodes
        mathGlyph.width = self.width
        mathGlyph.height = self.height
        mathGlyph.note = self.note
        return mathGlyph

    def fromMathGlyph(self, mathGlyph, filterRedundantPoints=True):
        """
        Replaces the contents of this glyph with the contents of ``mathGlyph``.

            >>> glyph.fromMathGlyph(mg)

        ``mathGlyph`` must be an object following the
        `MathGlyph protocol <https://github.com/typesupply/fontMath>`_.

        **filterRedundantPoints** enables the MathGlyph `drawPoints`
          `filterRedundantPoints` option.
        """
        return self._fromMathGlyph(mathGlyph, toThisGlyph=True, filterRedundantPoints=filterRedundantPoints)

    def _fromMathGlyph(self, mathGlyph, toThisGlyph=False, filterRedundantPoints=True):
        # make the destination
        if toThisGlyph:
            copied = self
            copied.clear()
        else:
            copyClass = self.copyClass
            if copyClass is None:
                copyClass = self.__class__
            copied = copyClass()
        # populate
        pen = copied.getPointPen()
        mathGlyph.drawPoints(pen, filterRedundantPoints=filterRedundantPoints)
        for anchor in mathGlyph.anchors:
            a = copied.appendAnchor(
                name=anchor.get("name"),
                position=(anchor["x"], anchor["y"]),
                color=anchor.get("color")
            )
            identifier = anchor.get("identifier")
            if identifier is not None:
                a._setIdentifier(identifier)
        for guideline in mathGlyph.guidelines:
            guideColor = guideline.get("color")
            if guideColor is None:
                colorData = None
            else:
                r, g, b, a = guideColor
                colorData = (r, g, b, a)
            g = copied.appendGuideline(
                position=(guideline["x"], guideline["y"]),
                angle=guideline["angle"],
                name=guideline.get("name"),
                color=colorData,
            )
            identifier = guideline.get("identifier")
            if identifier is not None:
                g._setIdentifier(identifier)
        copied.lib.update(mathGlyph.lib)
        if not toThisGlyph:
            copied.name = mathGlyph.name
            copied.unicodes = mathGlyph.unicodes
        copied.width = mathGlyph.width
        copied.height = mathGlyph.height
        copied.note = mathGlyph.note
        return copied

    def __mul__(self, factor):
        """
        Subclasses may override this method.
        """
        mathGlyph = self._toMathGlyph()
        result = mathGlyph * factor
        copied = self._fromMathGlyph(result)
        return copied

    __rmul__ = __mul__

    def __truediv__(self, factor):
        """
        Subclasses may override this method.
        """
        mathGlyph = self._toMathGlyph()
        result = mathGlyph / factor
        copied = self._fromMathGlyph(result)
        return copied

    # py2 support
    __div__ = __truediv__

    def __add__(self, other):
        """
        Subclasses may override this method.
        """
        selfMathGlyph = self._toMathGlyph()
        otherMathGlyph = other._toMathGlyph()
        result = selfMathGlyph + otherMathGlyph
        copied = self._fromMathGlyph(result)
        return copied

    def __sub__(self, other):
        """
        Subclasses may override this method.
        """
        selfMathGlyph = self._toMathGlyph()
        otherMathGlyph = other._toMathGlyph()
        result = selfMathGlyph - otherMathGlyph
        copied = self._fromMathGlyph(result)
        return copied

    def interpolate(self, factor, minGlyph, maxGlyph,
                    round=True, suppressError=True):
        """
        Interpolate the contents of this glyph at location ``factor``
        in a linear interpolation between ``minGlyph`` and ``maxGlyph``.

            >>> glyph.interpolate(0.5, otherGlyph1, otherGlyph2)

        ``factor`` may be a :ref:`type-int-float` or a tuple containing
        two :ref:`type-int-float` values representing x and y factors.

            >>> glyph.interpolate((0.5, 1.0), otherGlyph1, otherGlyph2)

        ``minGlyph`` must be a :class:`BaseGlyph` and will be located at 0.0
        in the interpolation range. ``maxGlyph`` must be a :class:`BaseGlyph`
        and will be located at 1.0 in the interpolation range. If ``round``
        is ``True``, the contents of the glyph will be rounded to integers
        after the interpolation is performed.

            >>> glyph.interpolate(0.5, otherGlyph1, otherGlyph2, round=True)

        This method assumes that ``minGlyph`` and ``maxGlyph`` are completely
        compatible with each other for interpolation. If not, any errors
        encountered will raise a :class:`FontPartsError`. If ``suppressError``
        is ``True``, no exception will be raised and errors will be silently
        ignored.
        """
        factor = normalizers.normalizeInterpolationFactor(factor)
        if not isinstance(minGlyph, BaseGlyph):
            raise TypeError(("Interpolation to an instance of %r can not be "
                             "performed from an instance of %r.")
                            % (self.__class__.__name__,
                               minGlyph.__class__.__name__))
        if not isinstance(maxGlyph, BaseGlyph):
            raise TypeError(("Interpolation to an instance of %r can not be "
                             "performed from an instance of %r.")
                            % (self.__class__.__name__,
                               maxGlyph.__class__.__name__))
        round = normalizers.normalizeBoolean(round)
        suppressError = normalizers.normalizeBoolean(suppressError)
        self._interpolate(factor, minGlyph, maxGlyph,
                          round=round, suppressError=suppressError)

    def _interpolate(self, factor, minGlyph, maxGlyph,
                     round=True, suppressError=True):
        """
        Subclasses may override this method.
        """
        from fontMath.mathFunctions import setRoundIntegerFunction

        setRoundIntegerFunction(normalizers.normalizeVisualRounding)

        minGlyph = minGlyph._toMathGlyph()
        maxGlyph = maxGlyph._toMathGlyph()
        try:
            result = interpolate(minGlyph, maxGlyph, factor)
        except IndexError:
            result = None
        if result is None and not suppressError:
            raise FontPartsError(("Glyphs '%s' and '%s' could not be "
                                  "interpolated.")
                                 % (minGlyph.name, maxGlyph.name))
        if result is not None:
            if round:
                result = result.round()
            self._fromMathGlyph(result, toThisGlyph=True)

    compatibilityReporterClass = GlyphCompatibilityReporter

    @staticmethod
    def _checkPairs(object1, object2, reporter, reporterObject):
        compatibility = object1.isCompatible(object2)[1]
        if compatibility.fatal or compatibility.warning:
            if compatibility.fatal:
                reporter.fatal = True
            if compatibility.warning:
                reporter.warning = True
            reporterObject.append(compatibility)

    def isCompatible(self, other):
        """
        Evaluate the interpolation compatibility of this glyph
        and ``other``.

            >>> compatible, report = self.isCompatible(otherGlyph)
            >>> compatible
            False

        This will return a :ref:`type-bool` indicating if this glyph is
        compatible with ``other`` and a :class:`GlyphCompatibilityReporter`
        containing a detailed report about compatibility errors.
        """
        return super(BaseGlyph, self).isCompatible(other, BaseGlyph)

    def _isCompatible(self, other, reporter):
        """
        This is the environment implementation of
        :meth:`BaseGlyph.isCompatible`.

        Subclasses may override this method.
        """
        glyph1 = self
        glyph2 = other
        # contour count
        if len(self.contours) != len(glyph2.contours):
            reporter.fatal = True
            reporter.contourCountDifference = True
        # contour pairs
        for i in range(min(len(glyph1), len(glyph2))):
            contour1 = glyph1[i]
            contour2 = glyph2[i]
            self._checkPairs(contour1, contour2, reporter, reporter.contours)
        # component count
        if len(glyph1.components) != len(glyph2.components):
            reporter.fatal = True
            reporter.componentCountDifference = True
        # component check
        component_diff = []
        selfComponents = [component.baseGlyph for component in glyph1.components]
        otherComponents = [component.baseGlyph for component in glyph2.components]
        for index, (left, right) in enumerate(
            zip_longest(selfComponents, otherComponents)
        ):
            if left != right:
                component_diff.append((index, left, right))

        if component_diff:
            reporter.warning = True
            reporter.componentDifferences = component_diff
            if not reporter.componentCountDifference and set(selfComponents) == set(
                otherComponents
            ):
                reporter.componentOrderDifference = True

            selfComponents_counted_set = collections.Counter(selfComponents)
            otherComponents_counted_set = collections.Counter(otherComponents)
            missing_from_glyph1 = (
                otherComponents_counted_set - selfComponents_counted_set
            )
            if missing_from_glyph1:
                reporter.fatal = True
                reporter.componentsMissingFromGlyph1 = sorted(
                    missing_from_glyph1.elements()
                )
            missing_from_glyph2 = (
                selfComponents_counted_set - otherComponents_counted_set
            )
            if missing_from_glyph2:
                reporter.fatal = True
                reporter.componentsMissingFromGlyph2 = sorted(
                    missing_from_glyph2.elements()
                )
        # guideline count
        if len(self.guidelines) != len(glyph2.guidelines):
            reporter.warning = True
            reporter.guidelineCountDifference = True
        # guideline check
        selfGuidelines = []
        otherGuidelines = []
        for source, names in ((self, selfGuidelines),
                              (other, otherGuidelines)):
            for i, guideline in enumerate(source.guidelines):
                names.append((guideline.name, i))
        guidelines1 = set(selfGuidelines)
        guidelines2 = set(otherGuidelines)
        if len(guidelines1.difference(guidelines2)) != 0:
            reporter.warning = True
            reporter.guidelinesMissingFromGlyph2 = list(
                guidelines1.difference(guidelines2))
        if len(guidelines2.difference(guidelines1)) != 0:
            reporter.warning = True
            reporter.guidelinesMissingFromGlyph1 = list(
                guidelines2.difference(guidelines1))
        # anchor count
        if len(self.anchors) != len(glyph2.anchors):
            reporter.warning = True
            reporter.anchorCountDifference = True
        # anchor check
        anchor_diff = []
        selfAnchors = [anchor.name for anchor in glyph1.anchors]
        otherAnchors = [anchor.name for anchor in glyph2.anchors]
        for index, (left, right) in enumerate(zip_longest(selfAnchors, otherAnchors)):
            if left != right:
                anchor_diff.append((index, left, right))

        if anchor_diff:
            reporter.warning = True
            reporter.anchorDifferences = anchor_diff
            if not reporter.anchorCountDifference and set(selfAnchors) == set(
                otherAnchors
            ):
                reporter.anchorOrderDifference = True

            selfAnchors_counted_set = collections.Counter(selfAnchors)
            otherAnchors_counted_set = collections.Counter(otherAnchors)
            missing_from_glyph1 = otherAnchors_counted_set - selfAnchors_counted_set
            if missing_from_glyph1:
                reporter.anchorsMissingFromGlyph1 = sorted(
                    missing_from_glyph1.elements()
                )
            missing_from_glyph2 = selfAnchors_counted_set - otherAnchors_counted_set
            if missing_from_glyph2:
                reporter.anchorsMissingFromGlyph2 = sorted(
                    missing_from_glyph2.elements()
                )

    # ------------
    # Data Queries
    # ------------

    def pointInside(self, point):
        """
        Determine if ``point`` is in the black or white of the glyph.

            >>> glyph.pointInside((40, 65))
            True

        ``point`` must be a :ref:`type-coordinate`.
        """
        point = normalizers.normalizeCoordinateTuple(point)
        return self._pointInside(point)

    def _pointInside(self, point):
        """
        Subclasses may override this method.
        """
        from fontTools.pens.pointInsidePen import PointInsidePen
        pen = PointInsidePen(glyphSet=None, testPoint=point, evenOdd=False)
        self.draw(pen)
        return pen.getResult()

    bounds = dynamicProperty(
        "bounds",
        """
        The bounds of the glyph in the form
        ``(x minimum, y minimum, x maximum, y maximum)`` or,
        in the case of empty glyphs ``None``.

            >>> glyph.bounds
            (10, 30, 765, 643)
        """
    )

    def _get_base_bounds(self):
        value = self._get_bounds()
        if value is not None:
            value = normalizers.normalizeBoundingBox(value)
        return value

    def _get_bounds(self):
        """
        Subclasses may override this method.
        """
        from fontTools.pens.boundsPen import BoundsPen
        pen = BoundsPen(self.layer)
        self.draw(pen)
        return pen.bounds

    area = dynamicProperty(
        "area",
        """
        The area of the glyph as a :ref:`type-int-float` or,
        in the case of empty glyphs ``None``.

            >>> glyph.area
            583
        """
    )

    def _get_base_area(self):
        value = self._get_area()
        if value is not None:
            value = normalizers.normalizeArea(value)
        return value

    def _get_area(self):
        """
        Subclasses may override this method.
        """
        from fontTools.pens.areaPen import AreaPen
        pen = AreaPen(self.layer)
        self.draw(pen)
        return abs(pen.value)

    # -----------------
    # Layer Interaction
    # -----------------

    layers = dynamicProperty(
        "layers",
        """
        Immutable tuple of the glyph's layers.

            >>> glyphLayers = glyph.layers

        This will return a tuple of all :ref:`type-glyph-layer` in the glyph.
        """
    )

    def _get_layers(self, **kwargs):
        font = self.font
        if font is None:
            return tuple()
        glyphs = []
        for layer in font.layers:
            if self.name in layer:
                glyphs.append(layer[self.name])
        return tuple(glyphs)

    # get

    def getLayer(self, name):
        """
        Get the :ref:`type-glyph-layer` with ``name`` in this glyph.

            >>> glyphLayer = glyph.getLayer("foreground")
        """
        name = normalizers.normalizeLayerName(name)
        return self._getLayer(name)

    def _getLayer(self, name, **kwargs):
        """
        name will be a string, but there may not be a
        layer with a name matching the string. If not,
        a ``ValueError`` must be raised.

        Subclasses may override this method.
        """
        for glyph in self.layers:
            if glyph.layer.name == name:
                return glyph
        raise ValueError("No layer named '%s' in glyph '%s'."
                         % (name, self.name))

    # new

    def newLayer(self, name):
        """
        Make a new layer with ``name`` in this glyph.

            >>> glyphLayer = glyph.newLayer("background")

        This will return the new :ref:`type-glyph-layer`.
        If the layer already exists in this glyph, it
        will be cleared.
        """
        layerName = name
        glyphName = self.name
        layerName = normalizers.normalizeLayerName(layerName)
        for glyph in self.layers:
            if glyph.layer.name == layerName:
                layer = glyph.layer
                layer.removeGlyph(glyphName)
                break
        glyph = self._newLayer(name=layerName)
        layer = self.font.getLayer(layerName)
        # layer._setLayerInGlyph(glyph)
        return glyph

    def _newLayer(self, name, **kwargs):
        """
        name will be a string representing a valid layer
        name. The name will have been tested to make sure
        that no layer in the glyph already has the name.

        This must returned the new glyph.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    # remove

    def removeLayer(self, layer):
        """
        Remove ``layer`` from this glyph.

            >>> glyph.removeLayer("background")

        Layer can be a :ref:`type-glyph-layer` or a :ref:`type-string`
        representing a layer name.
        """
        if isinstance(layer, BaseGlyph):
            layer = layer.layer.name
        layerName = layer
        layerName = normalizers.normalizeLayerName(layerName)
        if self._getLayer(layerName).layer.name == layerName:
            self._removeLayer(layerName)

    def _removeLayer(self, name, **kwargs):
        """
        name will be a valid layer name. It will
        represent an existing layer in the font.

        Subclasses may override this method.
        """
        self.raiseNotImplementedError()

    # -----
    # Image
    # -----

    image = dynamicProperty(
        "base_image",
        "The :class:`BaseImage` for the glyph."
    )

    def _get_base_image(self):
        image = self._get_image()
        if image.glyph is None:
            image.glyph = self
        return image

    def _get_image(self):
        """
        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def addImage(self, path=None, data=None, scale=None,
                 position=None, color=None):
        """
        Set the image in the glyph. This will return the
        assigned :class:`BaseImage`. The image data can be
        defined via ``path`` to an image file:

            >>> image = glyph.addImage(path="/path/to/my/image.png")

        The image data can be defined with raw image data
        via ``data``.

            >>> image = glyph.addImage(data=someImageData)

        If ``path`` and ``data`` are both provided, a
        :class:`FontPartsError` will be raised. The supported
        image formats will vary across environments. Refer
        to :class:`BaseImage` for complete details.

        ``scale`` indicates the x and y scale values that should be
        applied to the image. It must be a :ref:`type-scale` value
        or ``None``.

            >>> image = glyph.addImage(path="/p/t/image.png", scale=(0.5, 1.0))

        ``position`` indicates the x and y location of the lower left
        point of the image.

            >>> image = glyph.addImage(path="/p/t/image.png", position=(10, 20))

        ``color`` indicates the color to be applied to the image. It must
        be a :ref:`type-color` or ``None``.

            >>> image = glyph.addImage(path="/p/t/image.png", color=(1, 0, 0, 0.5))
        """
        if path is not None and data is not None:
            raise FontPartsError("Only path or data may be defined, not both.")
        if scale is None:
            scale = (1, 1)
        if position is None:
            position = (0, 0)
        scale = normalizers.normalizeTransformationScale(scale)
        position = normalizers.normalizeTransformationOffset(position)
        if color is not None:
            color = normalizers.normalizeColor(color)
        sx, sy = scale
        ox, oy = position
        transformation = (sx, 0, 0, sy, ox, oy)
        if path is not None:
            if not os.path.exists(path):
                raise IOError("No image located at '%s'." % path)
            f = open(path, "rb")
            data = f.read()
            f.close()
        self._addImage(data=data, transformation=transformation, color=color)
        return self.image

    def _addImage(self, data, transformation=None, color=None):
        """
        data will be raw, unnormalized image data.
        Each environment may have different possible
        formats, so this is unspecified.

        transformation will be a valid transformation matrix.

        color will be a color tuple or None.

        This must return an Image object. Assigning it
        to the glyph will be handled by the base class.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def clearImage(self):
        """
        Remove the image from the glyph.

            >>> glyph.clearImage()
        """
        if self.image is not None:
            self._clearImage()

    def _clearImage(self, **kwargs):
        """
        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    # ----------
    # Mark color
    # ----------

    markColor = dynamicProperty(
        "base_markColor",
        """
        The glyph's mark color.

            >>> glyph.markColor
            (1, 0, 0, 0.5)
            >>> glyph.markColor = None

        The value may be a :ref:`type-color` or ``None``.
        """
    )

    def _get_base_markColor(self):
        value = self._get_markColor()
        if value is not None:
            value = normalizers.normalizeColor(value)
            value = Color(value)
        return value

    def _set_base_markColor(self, value):
        if value is not None:
            value = normalizers.normalizeColor(value)
        self._set_markColor(value)

    def _get_markColor(self):
        """
        Return the mark color value as a color tuple or None.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def _set_markColor(self, value):
        """
        value will be a color tuple or None.

        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    # ----
    # Note
    # ----

    note = dynamicProperty(
        "base_note",
        """
        The glyph's note.

            >>> glyph.note
            "P.B. said this looks 'awesome.'"
            >>> glyph.note = "P.B. said this looks 'AWESOME.'"

        The value may be a :ref:`type-string` or ``None``.
        """
    )

    def _get_base_note(self):
        value = self._get_note()
        if value is not None:
            value = normalizers.normalizeGlyphNote(value)
        return value

    def _set_base_note(self, value):
        if value is not None:
            value = normalizers.normalizeGlyphNote(value)
        self._set_note(value)

    def _get_note(self):
        """
        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def _set_note(self, value):
        """
        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    # ---
    # Lib
    # ---

    lib = dynamicProperty(
        "base_lib",
        """
        The :class:`BaseLib` for the glyph.

            >>> lib = glyph.lib
        """
    )

    def _get_base_lib(self):
        lib = self._get_lib()
        lib.glyph = self
        return lib

    def _get_lib(self):
        """
        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    # --------
    # Temp Lib
    # --------

    tempLib = dynamicProperty(
        "base_tempLib",
        """
        The :class:`BaseLib` for the glyph.

            >>> tempLib = glyph.tempLib
        """
    )

    def _get_base_tempLib(self):
        lib = self._get_tempLib()
        lib.glyph = self
        return lib

    def _get_tempLib(self):
        """
        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    # ---
    # API
    # ---

    def isEmpty(self):
        """
        This will return :ref:`type-bool` indicating if there are contours and/or
        components in the glyph.

            >>> glyph.isEmpty()

        Note: This method only checks for the presence of contours and components.
        Other attributes (guidelines, anchors, a lib, etc.) will not affect what
        this method returns.
        """
        if self.contours:
            return False
        if self.components:
            return False
        return True

    def loadFromGLIF(self, glifData):
        """
        Reads ``glifData``, in
        `GLIF format <http://unifiedfontobject.org/versions/ufo3/glyphs/glif/>`_,
        into this glyph.

            >>> glyph.readGlyphFromString(xmlData)
        """
        self._loadFromGLIF(glifData)

    def _loadFromGLIF(self, glifData):
        """
        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    def dumpToGLIF(self, glyphFormatVersion=2):
        """
        This will return the glyph's contents as a string in
        `GLIF format <http://unifiedfontobject.org/versions/ufo3/glyphs/glif/>`_.

            >>> xml = glyph.writeGlyphToString()

        ``glyphFormatVersion`` must be a :ref:`type-int` that defines
        the preferred GLIF format version.
        """
        glyphFormatVersion = normalizers.normalizeGlyphFormatVersion(
            glyphFormatVersion)
        return self._dumpToGLIF(glyphFormatVersion)

    def _dumpToGLIF(self, glyphFormatVersion):
        """
        Subclasses must override this method.
        """
        self.raiseNotImplementedError()

    # ---------
    # Selection
    # ---------

    # contours

    selectedContours = dynamicProperty(
        "base_selectedContours",
        """
        An :ref:`type-immutable-list` of contours selected in the glyph.

            >>> contours = glyph.selectedContours:
            >>> glyph.selectedContours = otherContours

        It is possible to use a list of :ref:`type-int` representing
        contour indexes when setting the selected contours.

            >>> glyph.selectedContours = [0, 2]
        """
    )

    def _get_base_selectedContours(self):
        selected = tuple([normalizers.normalizeContour(contour) for
                         contour in self._get_selectedContours()])
        return selected

    def _get_selectedContours(self):
        """
        Subclasses may override this method.
        """
        return self._getSelectedSubObjects(self.contours)

    def _set_base_selectedContours(self, value):
        normalized = []
        for i in value:
            if isinstance(i, int):
                i = normalizers.normalizeIndex(i)
            else:
                i = normalizers.normalizeContour(i)
            normalized.append(i)
        self._set_selectedContours(normalized)

    def _set_selectedContours(self, value):
        """
        Subclasses may override this method.
        """
        return self._setSelectedSubObjects(self.contours, value)

    # components

    selectedComponents = dynamicProperty(
        "base_selectedComponents",
        """
        An :ref:`type-immutable-list` of components selected in the glyph.

            >>> components = glyph.selectedComponents:
            >>> glyph.selectedComponents = otherComponents

        It is possible to use a list of :ref:`type-int` representing
        component indexes when setting the selected components.

            >>> glyph.selectedComponents = [0, 2]
        """
    )

    def _get_base_selectedComponents(self):
        selected = tuple([normalizers.normalizeComponent(component) for
                         component in self._get_selectedComponents()])
        return selected

    def _get_selectedComponents(self):
        """
        Subclasses may override this method.
        """
        return self._getSelectedSubObjects(self.components)

    def _set_base_selectedComponents(self, value):
        normalized = []
        for i in value:
            if isinstance(i, int):
                i = normalizers.normalizeIndex(i)
            else:
                i = normalizers.normalizeComponent(i)
            normalized.append(i)
        self._set_selectedComponents(normalized)

    def _set_selectedComponents(self, value):
        """
        Subclasses may override this method.
        """
        return self._setSelectedSubObjects(self.components, value)

    # anchors

    selectedAnchors = dynamicProperty(
        "base_selectedAnchors",
        """
        An :ref:`type-immutable-list` of anchors selected in the glyph.

            >>> anchors = glyph.selectedAnchors:
            >>> glyph.selectedAnchors = otherAnchors

        It is possible to use a list of :ref:`type-int` representing
        anchor indexes when setting the selected anchors.

            >>> glyph.selectedAnchors = [0, 2]
        """
    )

    def _get_base_selectedAnchors(self):
        selected = tuple([normalizers.normalizeAnchor(anchor) for
                         anchor in self._get_selectedAnchors()])
        return selected

    def _get_selectedAnchors(self):
        """
        Subclasses may override this method.
        """
        return self._getSelectedSubObjects(self.anchors)

    def _set_base_selectedAnchors(self, value):
        normalized = []
        for i in value:
            if isinstance(i, int):
                i = normalizers.normalizeIndex(i)
            else:
                i = normalizers.normalizeAnchor(i)
            normalized.append(i)
        self._set_selectedAnchors(normalized)

    def _set_selectedAnchors(self, value):
        """
        Subclasses may override this method.
        """
        return self._setSelectedSubObjects(self.anchors, value)

    # guidelines

    selectedGuidelines = dynamicProperty(
        "base_selectedGuidelines",
        """
        An :ref:`type-immutable-list` of guidelines selected in the glyph.

            >>> guidelines = glyph.selectedGuidelines:
            >>> glyph.selectedGuidelines = otherGuidelines

        It is possible to use a list of :ref:`type-int` representing
        guidelines indexes when setting the selected guidelines.

            >>> glyph.selectedGuidelines = [0, 2]
        """
    )

    def _get_base_selectedGuidelines(self):
        selected = tuple([normalizers.normalizeGuideline(guideline) for
                         guideline in self._get_selectedGuidelines()])
        return selected

    def _get_selectedGuidelines(self):
        """
        Subclasses may override this method.
        """
        return self._getSelectedSubObjects(self.guidelines)

    def _set_base_selectedGuidelines(self, value):
        normalized = []
        for i in value:
            if isinstance(i, int):
                i = normalizers.normalizeIndex(i)
            else:
                i = normalizers.normalizeGuideline(i)
            normalized.append(i)
        self._set_selectedGuidelines(normalized)

    def _set_selectedGuidelines(self, value):
        """
        Subclasses may override this method.
        """
        return self._setSelectedSubObjects(self.guidelines, value)
