Source code for fontParts.base.point

from fontTools.misc import transform
from fontParts.base.base import (
    BaseObject,
    TransformationMixin,
    PointPositionMixin,
    SelectionMixin,
    IdentifierMixin,
    dynamicProperty,
    reference
)
from fontParts.base import normalizers
from fontParts.base.deprecated import DeprecatedPoint, RemovedPoint


class BasePoint(
                BaseObject,
                TransformationMixin,
                PointPositionMixin,
                SelectionMixin,
                IdentifierMixin,
                DeprecatedPoint,
                RemovedPoint
                ):

    """
    A point object. This object is almost always
    created with :meth:`BaseContour.appendPoint`,
    the pen returned by :meth:`BaseGlyph.getPen`
    or the point pen returned by :meth:`BaseGLyph.getPointPen`.
    An orphan point can be created like this::

        >>> point = RPoint()
    """

    copyAttributes = (
        "type",
        "smooth",
        "x",
        "y",
        "name"
    )

    def _reprContents(self):
        contents = [
            "%s" % self.type,
            ("({x}, {y})".format(x=self.x, y=self.y)),
        ]
        if self.name is not None:
            contents.append("name='%s'" % self.name)
        if self.smooth:
            contents.append("smooth=%r" % self.smooth)
        return contents

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

    # Contour

    _contour = None

    contour = dynamicProperty("contour",
                              "The point's parent :class:`BaseContour`.")

    def _get_contour(self):
        if self._contour is None:
            return None
        return self._contour()

    def _set_contour(self, contour):
        if self._contour is not None:
            raise AssertionError("contour for point already set")
        if contour is not None:
            contour = reference(contour)
        self._contour = contour

    # Glyph

    glyph = dynamicProperty("glyph", "The point's parent :class:`BaseGlyph`.")

    def _get_glyph(self):
        if self._contour is None:
            return None
        return self.contour.glyph

    # Layer

    layer = dynamicProperty("layer", "The point's parent :class:`BaseLayer`.")

    def _get_layer(self):
        if self._contour is None:
            return None
        return self.glyph.layer

    # Font

    font = dynamicProperty("font", "The point's parent :class:`BaseFont`.")

    def _get_font(self):
        if self._contour is None:
            return None
        return self.glyph.font

    # ----------
    # Attributes
    # ----------

    # type

    type = dynamicProperty(
        "base_type",
        """
        The point type defined with a :ref:`type-string`.
        The possible types are:

        +----------+---------------------------------+
        | move     | An on-curve move to.            |
        +----------+---------------------------------+
        | line     | An on-curve line to.            |
        +----------+---------------------------------+
        | curve    | An on-curve cubic curve to.     |
        +----------+---------------------------------+
        | qcurve   | An on-curve quadratic curve to. |
        +----------+---------------------------------+
        | offcurve | An off-curve.                   |
        +----------+---------------------------------+
        """)

    def _get_base_type(self):
        value = self._get_type()
        value = normalizers.normalizePointType(value)
        return value

    def _set_base_type(self, value):
        value = normalizers.normalizePointType(value)
        self._set_type(value)

[docs] def _get_type(self): """ This is the environment implementation of :attr:`BasePoint.type`. This must return a :ref:`type-string` defining the point type. Subclasses must override this method. """ self.raiseNotImplementedError()
[docs] def _set_type(self, value): """ This is the environment implementation of :attr:`BasePoint.type`. **value** will be a :ref:`type-string` defining the point type. It will have been normalized with :func:`normalizers.normalizePointType`. Subclasses must override this method. """ self.raiseNotImplementedError()
# smooth smooth = dynamicProperty( "base_smooth", """ A ``bool`` indicating if the point is smooth or not. :: >>> point.smooth False >>> point.smooth = True """ ) def _get_base_smooth(self): value = self._get_smooth() value = normalizers.normalizeBoolean(value) return value def _set_base_smooth(self, value): value = normalizers.normalizeBoolean(value) self._set_smooth(value)
[docs] def _get_smooth(self): """ This is the environment implementation of :attr:`BasePoint.smooth`. This must return a ``bool`` indicating the smooth state. Subclasses must override this method. """ self.raiseNotImplementedError()
[docs] def _set_smooth(self, value): """ This is the environment implementation of :attr:`BasePoint.smooth`. **value** will be a ``bool`` indicating the smooth state. It will have been normalized with :func:`normalizers.normalizeBoolean`. Subclasses must override this method. """ self.raiseNotImplementedError()
# x x = dynamicProperty( "base_x", """ The x coordinate of the point. It must be an :ref:`type-int-float`. :: >>> point.x 100 >>> point.x = 101 """ ) def _get_base_x(self): value = self._get_x() value = normalizers.normalizeX(value) return value def _set_base_x(self, value): value = normalizers.normalizeX(value) self._set_x(value)
[docs] def _get_x(self): """ This is the environment implementation of :attr:`BasePoint.x`. This must return an :ref:`type-int-float`. Subclasses must override this method. """ self.raiseNotImplementedError()
[docs] def _set_x(self, value): """ This is the environment implementation of :attr:`BasePoint.x`. **value** will be an :ref:`type-int-float`. Subclasses must override this method. """ self.raiseNotImplementedError()
# y y = dynamicProperty( "base_y", """ The y coordinate of the point. It must be an :ref:`type-int-float`. :: >>> point.y 100 >>> point.y = 101 """ ) def _get_base_y(self): value = self._get_y() value = normalizers.normalizeY(value) return value def _set_base_y(self, value): value = normalizers.normalizeY(value) self._set_y(value)
[docs] def _get_y(self): """ This is the environment implementation of :attr:`BasePoint.y`. This must return an :ref:`type-int-float`. Subclasses must override this method. """ self.raiseNotImplementedError()
[docs] def _set_y(self, value): """ This is the environment implementation of :attr:`BasePoint.y`. **value** will be an :ref:`type-int-float`. Subclasses must override this method. """ self.raiseNotImplementedError()
# -------------- # Identification # -------------- # index index = dynamicProperty( "base_index", """ The index of the point within the ordered list of the parent glyph's point. This attribute is read only. :: >>> point.index 0 """ ) def _get_base_index(self): value = self._get_index() value = normalizers.normalizeIndex(value) return value
[docs] def _get_index(self): """ Get the point's index. This must return an ``int``. Subclasses may override this method. """ contour = self.contour if contour is None: return None return contour.points.index(self)
# name name = dynamicProperty( "base_name", """ The name of the point. This will be a :ref:`type-string` or ``None``. >>> point.name 'my point' >>> point.name = None """ ) def _get_base_name(self): value = self._get_name() if value is not None: value = normalizers.normalizePointName(value) return value def _set_base_name(self, value): if value is not None: value = normalizers.normalizePointName(value) self._set_name(value)
[docs] def _get_name(self): """ This is the environment implementation of :attr:`BasePoint.name`. This must return a :ref:`type-string` or ``None``. The returned value will be normalized with :func:`normalizers.normalizePointName`. Subclasses must override this method. """ self.raiseNotImplementedError()
[docs] def _set_name(self, value): """ This is the environment implementation of :attr:`BasePoint.name`. **value** will be a :ref:`type-string` or ``None``. It will have been normalized with :func:`normalizers.normalizePointName`. Subclasses must override this method. """ self.raiseNotImplementedError()
# -------------- # Transformation # --------------
[docs] def _transformBy(self, matrix, **kwargs): """ This is the environment implementation of :meth:`BasePoint.transformBy`. **matrix** will be a :ref:`type-transformation`. that has been normalized with :func:`normalizers.normalizeTransformationMatrix`. Subclasses may override this method. """ t = transform.Transform(*matrix) x, y = t.transformPoint((self.x, self.y)) self.x = x self.y = y
# ------------- # Normalization # -------------
[docs] def round(self): """ Round the point's coordinate. >>> point.round() This applies to the following: * x * y """ self._round()
[docs] def _round(self, **kwargs): """ This is the environment implementation of :meth:`BasePoint.round`. Subclasses may override this method. """ self.x = normalizers.normalizeVisualRounding(self.x) self.y = normalizers.normalizeVisualRounding(self.y)