[filterPen] add ContourFilterPen

A filter pen that accumulates contour data, passes it through a
`filterContour` method as the contour is closed or ended, and
draws the result with the output pen.
This commit is contained in:
Cosimo Lupo 2017-10-11 21:07:17 +01:00
parent 8afa763ad2
commit ccf7ab3ab1

View File

@ -1,9 +1,16 @@
from __future__ import print_function, division, absolute_import from __future__ import print_function, division, absolute_import
from fontTools.misc.py23 import * from fontTools.misc.py23 import *
from fontTools.pens.basePen import AbstractPen from fontTools.pens.basePen import AbstractPen
from fontTools.pens.recordingPen import RecordingPen
class FilterPen(AbstractPen): class _PassThruComponentsMixin(object):
def addComponent(self, glyphName, transformation):
self._outPen.addComponent(glyphName, transformation)
class FilterPen(_PassThruComponentsMixin, AbstractPen):
""" Base class for pens that apply some transformation to the coordinates """ Base class for pens that apply some transformation to the coordinates
they receive and pass them to another pen. they receive and pass them to another pen.
@ -70,5 +77,43 @@ class FilterPen(AbstractPen):
def endPath(self): def endPath(self):
self._outPen.endPath() self._outPen.endPath()
def addComponent(self, glyphName, transformation):
self._outPen.addComponent(glyphName, transformation) class ContourFilterPen(_PassThruComponentsMixin, RecordingPen):
"""A "buffered" filter pen that accumulates contour data, passes
it through a ``filterContour`` method when the contour is closed or ended,
and finally draws the result with the output pen.
"""
def __init__(self, outPen):
super(ContourFilterPen, self).__init__()
self._outPen = outPen
def closePath(self):
super(ContourFilterPen, self).closePath()
self._flushContour()
def endPath(self):
super(ContourFilterPen, self).endPath()
self._flushContour()
def _flushContour(self):
result = self.filterContour(self.value)
if result is not None:
self.value = result
self.replay(self._outPen)
self.value = []
def filterContour(self, contour):
"""Subclasses must override this to perform the filtering.
The contour is a list of pen (operator, operands) tuples.
Operators are strings corresponding to the AbstractPen methods:
"moveTo", "lineTo", "curveTo", "qCurveTo", "closePath",
"endPath", and "addComponent". The operands are the positional
arguments that are passed to each method.
If the method doesn't return a value (i.e. returns None), it's
assumed that the argument was modified in-place.
Otherwise, the return value is drawn with the output pen.
"""
return # or return contour