# filterPen

class fontTools.pens.filterPen.FilterPen(outPen)

  Bases: `_PassThruComponentsMixin`, `AbstractPen`

  Base class for pens that apply some transformation to the coordinates they receive and pass them to another pen.

  You can override any of its methods. The default implementation does nothing, but passes the commands unmodified to the other pen.

      >>> from fontTools.pens.recordingPen import RecordingPen
      >>> rec = RecordingPen()
      >>> pen = FilterPen(rec)
      >>> v = iter(rec.value)

      >>> pen.moveTo((0, 0))
      >>> next(v)
      ('moveTo', ((0, 0),))

      >>> pen.lineTo((1, 1))
      >>> next(v)
      ('lineTo', ((1, 1),))

      >>> pen.curveTo((2, 2), (3, 3), (4, 4))
      >>> next(v)
      ('curveTo', ((2, 2), (3, 3), (4, 4)))

      >>> pen.qCurveTo((5, 5), (6, 6), (7, 7), (8, 8))
      >>> next(v)
      ('qCurveTo', ((5, 5), (6, 6), (7, 7), (8, 8)))

      >>> pen.closePath()
      >>> next(v)
      ('closePath', ())

      >>> pen.moveTo((9, 9))
      >>> next(v)
      ('moveTo', ((9, 9),))

      >>> pen.endPath()
      >>> next(v)
      ('endPath', ())

      >>> pen.addComponent('foo', (1, 0, 0, 1, 0, 0))
      >>> next(v)
      ('addComponent', ('foo', (1, 0, 0, 1, 0, 0)))

  moveTo(pt)
  lineTo(pt)
  curveTo(*points)
  qCurveTo(*points)
  closePath()
  endPath()

class fontTools.pens.filterPen.ContourFilterPen(outPen)

  Bases: `_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.

  Components are passed through unchanged.

  closePath()
  endPath()
  filterContour(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” and “endPath”. 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.

class fontTools.pens.filterPen.FilterPointPen(outPen)

  Bases: `_PassThruComponentsMixin`, `AbstractPointPen`

  Baseclass for point pens that apply some transformation to the coordinates they receive and pass them to another point pen.

  You can override any of its methods. The default implementation does nothing, but passes the commands unmodified to the other pen.

      >>> from fontTools.pens.recordingPen import RecordingPointPen
      >>> rec = RecordingPointPen()
      >>> pen = FilterPointPen(rec)
      >>> v = iter(rec.value)
      >>> pen.beginPath(identifier="abc")
      >>> next(v)
      ('beginPath', (), {'identifier': 'abc'})
      >>> pen.addPoint((1, 2), "line", False)
      >>> next(v)
      ('addPoint', ((1, 2), 'line', False, None), {})
      >>> pen.addComponent("a", (2, 0, 0, 2, 10, -10), identifier="0001")
      >>> next(v)
      ('addComponent', ('a', (2, 0, 0, 2, 10, -10)), {'identifier': '0001'})
      >>> pen.endPath()
      >>> next(v)
      ('endPath', (), {})

  beginPath(identifier=None, **kwargs)
  endPath()
  addPoint(pt, segmentType=None, smooth=False, name=None, identifier=None, **kwargs)

class fontTools.pens.filterPen.DecomposingFilterPen(outPen, glyphSet, skipMissingComponents=None, reverseFlipped: bool = False, include: set[str] | None = None, decomposeNested: bool = True, **kwargs)

  Bases: `_DecomposingFilterPenMixin`, `DecomposingPen`, `FilterPen`

  Filter pen that draws components as regular contours.

class fontTools.pens.filterPen.DecomposingFilterPointPen(outPen, glyphSet, skipMissingComponents=None, reverseFlipped: bool | ReverseFlipped = False, include: set[str] | None = None, decomposeNested: bool = True, **kwargs)

  Bases: `_DecomposingFilterPointPenMixin`, `DecomposingPointPen`, `FilterPointPen`

  Filter point pen that draws components as regular contours.

class fontTools.pens.filterPen.ContourFilterPointPen(outPen)

  Bases: `_PassThruComponentsMixin`, `AbstractPointPen`

  A “buffered” filter point 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 point pen.

  Components are passed through unchanged.

  The `filterContour` method can modify the contour in-place (return None) or return a new contour to replace it.

  beginPath(identifier=None, **kwargs)
  endPath()
  filterContour(contour)

    Subclasses must override this to perform the filtering.

    The contour is a list of (pt, segmentType, smooth, name, kwargs) tuples. If the method doesn’t return a value (i.e. returns None), it’s assumed that the contour was modified in-place. Otherwise, the return value replaces the original contour.

  addPoint(pt, segmentType=None, smooth=False, name=None, identifier=None, **kwargs)

class fontTools.pens.filterPen.OnCurveFirstPointPen(outPen)

  Bases: `ContourFilterPointPen`

  Filter point pen that ensures closed contours start with an on-curve point.

  If a closed contour starts with an off-curve point (segmentType=None), it rotates the points list so that the first on-curve point (segmentType != None) becomes the start point. Open contours and contours already starting with on-curve points are passed through unchanged.

      >>> from fontTools.pens.recordingPen import RecordingPointPen
      >>> rec = RecordingPointPen()
      >>> pen = OnCurveFirstPointPen(rec)
      >>> # Closed contour starting with off-curve - will be rotated
      >>> pen.beginPath()
      >>> pen.addPoint((0, 0), None)  # off-curve
      >>> pen.addPoint((100, 100), "line")  # on-curve - will become start
      >>> pen.addPoint((200, 0), None)  # off-curve
      >>> pen.addPoint((300, 100), "curve")  # on-curve
      >>> pen.endPath()
      >>> # The contour should now start with (100, 100) "line"
      >>> rec.value[0]
      ('beginPath', (), {})
      >>> rec.value[1]
      ('addPoint', ((100, 100), 'line', False, None), {})
      >>> rec.value[2]
      ('addPoint', ((200, 0), None, False, None), {})
      >>> rec.value[3]
      ('addPoint', ((300, 100), 'curve', False, None), {})
      >>> rec.value[4]
      ('addPoint', ((0, 0), None, False, None), {})

  filterContour(contour)

    Rotate closed contour to start with first on-curve point if needed.