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


[docs] 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)