123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- from fontTools.misc.arrayTools import updateBounds, pointInRect, unionRect
- from fontTools.misc.bezierTools import calcCubicBounds, calcQuadraticBounds
- from fontTools.pens.basePen import BasePen
- __all__ = ["BoundsPen", "ControlBoundsPen"]
- class ControlBoundsPen(BasePen):
- """Pen to calculate the "control bounds" of a shape. This is the
- bounding box of all control points, so may be larger than the
- actual bounding box if there are curves that don't have points
- on their extremes.
- When the shape has been drawn, the bounds are available as the
- ``bounds`` attribute of the pen object. It's a 4-tuple::
- (xMin, yMin, xMax, yMax).
- If ``ignoreSinglePoints`` is True, single points are ignored.
- """
- def __init__(self, glyphSet, ignoreSinglePoints=False):
- BasePen.__init__(self, glyphSet)
- self.ignoreSinglePoints = ignoreSinglePoints
- self.init()
- def init(self):
- self.bounds = None
- self._start = None
- def _moveTo(self, pt):
- self._start = pt
- if not self.ignoreSinglePoints:
- self._addMoveTo()
- def _addMoveTo(self):
- if self._start is None:
- return
- bounds = self.bounds
- if bounds:
- self.bounds = updateBounds(bounds, self._start)
- else:
- x, y = self._start
- self.bounds = (x, y, x, y)
- self._start = None
- def _lineTo(self, pt):
- self._addMoveTo()
- self.bounds = updateBounds(self.bounds, pt)
- def _curveToOne(self, bcp1, bcp2, pt):
- self._addMoveTo()
- bounds = self.bounds
- bounds = updateBounds(bounds, bcp1)
- bounds = updateBounds(bounds, bcp2)
- bounds = updateBounds(bounds, pt)
- self.bounds = bounds
- def _qCurveToOne(self, bcp, pt):
- self._addMoveTo()
- bounds = self.bounds
- bounds = updateBounds(bounds, bcp)
- bounds = updateBounds(bounds, pt)
- self.bounds = bounds
- class BoundsPen(ControlBoundsPen):
- """Pen to calculate the bounds of a shape. It calculates the
- correct bounds even when the shape contains curves that don't
- have points on their extremes. This is somewhat slower to compute
- than the "control bounds".
- When the shape has been drawn, the bounds are available as the
- ``bounds`` attribute of the pen object. It's a 4-tuple::
- (xMin, yMin, xMax, yMax)
- """
- def _curveToOne(self, bcp1, bcp2, pt):
- self._addMoveTo()
- bounds = self.bounds
- bounds = updateBounds(bounds, pt)
- if not pointInRect(bcp1, bounds) or not pointInRect(bcp2, bounds):
- bounds = unionRect(
- bounds, calcCubicBounds(self._getCurrentPoint(), bcp1, bcp2, pt)
- )
- self.bounds = bounds
- def _qCurveToOne(self, bcp, pt):
- self._addMoveTo()
- bounds = self.bounds
- bounds = updateBounds(bounds, pt)
- if not pointInRect(bcp, bounds):
- bounds = unionRect(
- bounds, calcQuadraticBounds(self._getCurrentPoint(), bcp, pt)
- )
- self.bounds = bounds
|