• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from __future__ import print_function, division, absolute_import
2from fontTools.misc.py23 import *
3from fontTools.misc.arrayTools import updateBounds, pointInRect, unionRect
4from fontTools.misc.bezierTools import calcCubicBounds, calcQuadraticBounds
5from fontTools.pens.basePen import BasePen
6
7
8__all__ = ["BoundsPen", "ControlBoundsPen"]
9
10
11class ControlBoundsPen(BasePen):
12
13	"""Pen to calculate the "control bounds" of a shape. This is the
14	bounding box of all control points, so may be larger than the
15	actual bounding box if there are curves that don't have points
16	on their extremes.
17
18	When the shape has been drawn, the bounds are available as the
19	'bounds' attribute of the pen object. It's a 4-tuple:
20		(xMin, yMin, xMax, yMax).
21
22	If 'ignoreSinglePoints' is True, single points are ignored.
23	"""
24
25	def __init__(self, glyphSet, ignoreSinglePoints=False):
26		BasePen.__init__(self, glyphSet)
27		self.ignoreSinglePoints = ignoreSinglePoints
28		self.init()
29
30	def init(self):
31	    self.bounds = None
32	    self._start = None
33
34	def _moveTo(self, pt):
35		self._start = pt
36		if not self.ignoreSinglePoints:
37			self._addMoveTo()
38
39	def _addMoveTo(self):
40		if self._start is None:
41			return
42		bounds = self.bounds
43		if bounds:
44			self.bounds = updateBounds(bounds, self._start)
45		else:
46			x, y = self._start
47			self.bounds = (x, y, x, y)
48		self._start = None
49
50	def _lineTo(self, pt):
51		self._addMoveTo()
52		self.bounds = updateBounds(self.bounds, pt)
53
54	def _curveToOne(self, bcp1, bcp2, pt):
55		self._addMoveTo()
56		bounds = self.bounds
57		bounds = updateBounds(bounds, bcp1)
58		bounds = updateBounds(bounds, bcp2)
59		bounds = updateBounds(bounds, pt)
60		self.bounds = bounds
61
62	def _qCurveToOne(self, bcp, pt):
63		self._addMoveTo()
64		bounds = self.bounds
65		bounds = updateBounds(bounds, bcp)
66		bounds = updateBounds(bounds, pt)
67		self.bounds = bounds
68
69
70class BoundsPen(ControlBoundsPen):
71
72	"""Pen to calculate the bounds of a shape. It calculates the
73	correct bounds even when the shape contains curves that don't
74	have points on their extremes. This is somewhat slower to compute
75	than the "control bounds".
76
77	When the shape has been drawn, the bounds are available as the
78	'bounds' attribute of the pen object. It's a 4-tuple:
79		(xMin, yMin, xMax, yMax)
80	"""
81
82	def _curveToOne(self, bcp1, bcp2, pt):
83		self._addMoveTo()
84		bounds = self.bounds
85		bounds = updateBounds(bounds, pt)
86		if not pointInRect(bcp1, bounds) or not pointInRect(bcp2, bounds):
87			bounds = unionRect(bounds, calcCubicBounds(
88					self._getCurrentPoint(), bcp1, bcp2, pt))
89		self.bounds = bounds
90
91	def _qCurveToOne(self, bcp, pt):
92		self._addMoveTo()
93		bounds = self.bounds
94		bounds = updateBounds(bounds, pt)
95		if not pointInRect(bcp, bounds):
96			bounds = unionRect(bounds, calcQuadraticBounds(
97					self._getCurrentPoint(), bcp, pt))
98		self.bounds = bounds
99