old_contents: from __future__ import print_function, division, absolute_import
  from fontTools.misc.py23 import *
  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)
  	"""
  
  	def __init__(self, glyphSet):
  		BasePen.__init__(self, glyphSet)
  		self.bounds = None
  
  	def _moveTo(self, pt):
  		bounds = self.bounds
  		if bounds:
  			self.bounds = updateBounds(bounds, pt)
  		else:
  			x, y = pt
  			self.bounds = (x, y, x, y)
  
  	def _lineTo(self, pt):
  		self.bounds = updateBounds(self.bounds, pt)
  
  	def _curveToOne(self, bcp1, bcp2, pt):
  		bounds = self.bounds
  		bounds = updateBounds(bounds, bcp1)
  		bounds = updateBounds(bounds, bcp2)
  		bounds = updateBounds(bounds, pt)
  		self.bounds = bounds
  
  	def _qCurveToOne(self, bcp, pt):
  		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):
  		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):
  		bounds = self.bounds
  		bounds = updateBounds(bounds, pt)
  		if not pointInRect(bcp, bounds):
  			bounds = unionRect(bounds, calcQuadraticBounds(
  					self._getCurrentPoint(), bcp, pt))
  		self.bounds = bounds
  
new_contents: from __future__ import print_function, division, absolute_import
  from fontTools.misc.py23 import *
  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.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
  
subject: add 'ignoreSinglePoints' argument to do like robofab.pens.boundsPen