1
from fontTools.pens.basePen import BasePen
2
from fontTools.misc.arrayTools import updateBounds, pointInRect, unionRect
3
from fontTools.misc.bezierTools import calcCubicBounds, calcQuadraticBounds
6
__all__ = ["BoundsPen", "ControlBoundsPen"]
9
class ControlBoundsPen(BasePen):
11
"""Pen to calculate the "control bounds" of a shape. This is the
12
bounding box of all control points, so may be larger than the
13
actual bounding box if there are curves that don't have points
16
When the shape has been drawn, the bounds are available as the
17
'bounds' attribute of the pen object. It's a 4-tuple:
18
(xMin, yMin, xMax, yMax)
21
def __init__(self, glyphSet):
22
BasePen.__init__(self, glyphSet)
25
def _moveTo(self, pt):
28
self.bounds = updateBounds(bounds, pt)
31
self.bounds = (x, y, x, y)
33
def _lineTo(self, pt):
34
self.bounds = updateBounds(self.bounds, pt)
36
def _curveToOne(self, bcp1, bcp2, pt):
38
bounds = updateBounds(bounds, bcp1)
39
bounds = updateBounds(bounds, bcp2)
40
bounds = updateBounds(bounds, pt)
43
def _qCurveToOne(self, bcp, pt):
45
bounds = updateBounds(bounds, bcp)
46
bounds = updateBounds(bounds, pt)
50
class BoundsPen(ControlBoundsPen):
52
"""Pen to calculate the bounds of a shape. It calculates the
53
correct bounds even when the shape contains curves that don't
54
have points on their extremes. This is somewhat slower to compute
55
than the "control bounds".
57
When the shape has been drawn, the bounds are available as the
58
'bounds' attribute of the pen object. It's a 4-tuple:
59
(xMin, yMin, xMax, yMax)
62
def _curveToOne(self, bcp1, bcp2, pt):
64
bounds = updateBounds(bounds, pt)
65
if not pointInRect(bcp1, bounds) or not pointInRect(bcp2, bounds):
66
bounds = unionRect(bounds, calcCubicBounds(
67
self._getCurrentPoint(), bcp1, bcp2, pt))
70
def _qCurveToOne(self, bcp, pt):
72
bounds = updateBounds(bounds, pt)
73
if not pointInRect(bcp, bounds):
74
bounds = unionRect(bounds, calcQuadraticBounds(
75
self._getCurrentPoint(), bcp, pt))
79
if __name__ == "__main__":
83
pen.qCurveTo((50, 75), (60, 50), (50, 25), (0, 0))
84
pen.curveTo((-50, 25), (-60, 50), (-50, 75), (0, 100))
87
pen = ControlBoundsPen(None)