[pens.areaPen] Clean up a bit

Based on discussion in
https://github.com/behdad/fonttools/pull/618#issuecomment-226105824
This commit is contained in:
Behdad Esfahbod 2016-06-15 14:10:44 +04:00
parent b3414e9ffd
commit 220ff2b238

View File

@ -5,29 +5,6 @@ from fontTools.misc.py23 import *
from fontTools.pens.basePen import BasePen from fontTools.pens.basePen import BasePen
def polygon_area(p0, p1):
return -(p1[0] - p0[0]) * (p1[1] + p0[1]) * 0.5
def quadratic_curve_area(p0, p1, p2):
x0, y0 = p0[0], p0[1]
x1, y1 = p1[0] - x0, p1[1] - y0
x2, y2 = p2[0] - x0, p2[1] - y0
return (x1*y2 - x2*y1) / 3
def cubic_curve_area(p0, p1, p2, p3):
x0, y0 = p0[0], p0[1]
x1, y1 = p1[0] - x0, p1[1] - y0
x2, y2 = p2[0] - x0, p2[1] - y0
x3, y3 = p3[0] - x0, p3[1] - y0
return -(
x1 * ( - y2 - y3) +
x2 * (y1 - 2*y3) +
x3 * (y1 + 2*y2 )
) * 0.15
class AreaPen(BasePen): class AreaPen(BasePen):
def __init__(self, glyphset=None): def __init__(self, glyphset=None):
@ -35,23 +12,56 @@ class AreaPen(BasePen):
self.value = 0 self.value = 0
def _moveTo(self, p0): def _moveTo(self, p0):
self.__startPoint = p0 """Remember the first point in this contour, in case it's closed. Also
set the initial value for p0 in this contour, which will always refer to
the most recent point.
"""
self._p0 = self._startPoint = p0
def _lineTo(self, p1): def _lineTo(self, p1):
p0 = self._getCurrentPoint() """Add the signed area beneath the line from the latest point to this
self.value += polygon_area(p0, p1) one. Signed areas cancel each other based on the horizontal direction of
the line.
def _curveToOne(self, p1, p2, p3): """
p0 = self._getCurrentPoint() x0, y0 = self._p0
self.value += cubic_curve_area(p0, p1, p2, p3) x1, y1 = p1
self.value += polygon_area(p0, p3) self.value -= (x1 - x0) * (y1 + y0) * .5
self._p0 = p1
def _qCurveToOne(self, p1, p2): def _qCurveToOne(self, p1, p2):
p0 = self._getCurrentPoint() """Add the signed area of this quadratic curve.
self.value += quadratic_curve_area(p0, p1, p2) https://github.com/Pomax/bezierinfo/issues/44
self.value += polygon_area(p0, p2) """
p0 = self._p0
x0, y0 = p0[0], p0[1]
x1, y1 = p1[0] - x0, p1[1] - y0
x2, y2 = p2[0] - x0, p2[1] - y0
self.value -= (x2 * y1 - x1 * y2) / 3
self._lineTo(p2)
self._p0 = p2
def _curveToOne(self, p1, p2, p3):
"""Add the signed area of this cubic curve.
https://github.com/Pomax/bezierinfo/issues/44
"""
p0 = self._p0
x0, y0 = p0[0], p0[1]
x1, y1 = p1[0] - x0, p1[1] - y0
x2, y2 = p2[0] - x0, p2[1] - y0
x3, y3 = p3[0] - x0, p3[1] - y0
self.value -= (
x1 * ( - y2 - y3) +
x2 * (y1 - 2*y3) +
x3 * (y1 + 2*y2 )
) * 0.15
self._lineTo(p3)
self._p0 = p3
def _closePath(self): def _closePath(self):
p0 = self._getCurrentPoint() """Add the area beneath this contour's closing line."""
if p0 != self.__startPoint: self._lineTo(self._startPoint)
self.value += polygon_area(p0, self.__startPoint) del self._p0, self._startPoint
def _endPath(self):
"""Area is not defined for open contours."""
raise NotImplementedError