[recordingPen] Add DecomposingRecordingPointPen, test new decomposing pen options
This commit is contained in:
parent
c0074ee26f
commit
cccc358c79
@ -1,7 +1,7 @@
|
|||||||
"""Pen recording operations that can be accessed or replayed."""
|
"""Pen recording operations that can be accessed or replayed."""
|
||||||
|
|
||||||
from fontTools.pens.basePen import AbstractPen, DecomposingPen
|
from fontTools.pens.basePen import AbstractPen, DecomposingPen
|
||||||
from fontTools.pens.pointPen import AbstractPointPen
|
from fontTools.pens.pointPen import AbstractPointPen, DecomposingPointPen
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
@ -85,9 +85,10 @@ class DecomposingRecordingPen(DecomposingPen, RecordingPen):
|
|||||||
"""Same as RecordingPen, except that it doesn't keep components
|
"""Same as RecordingPen, except that it doesn't keep components
|
||||||
as references, but draws them decomposed as regular contours.
|
as references, but draws them decomposed as regular contours.
|
||||||
|
|
||||||
The constructor takes a single 'glyphSet' positional argument,
|
The constructor takes a required 'glyphSet' positional argument,
|
||||||
a dictionary of glyph objects (i.e. with a 'draw' method) keyed
|
a dictionary of glyph objects (i.e. with a 'draw' method) keyed
|
||||||
by thir name::
|
by thir name; other arguments are forwarded to the DecomposingPen's
|
||||||
|
constructor::
|
||||||
|
|
||||||
>>> class SimpleGlyph(object):
|
>>> class SimpleGlyph(object):
|
||||||
... def draw(self, pen):
|
... def draw(self, pen):
|
||||||
@ -97,16 +98,42 @@ class DecomposingRecordingPen(DecomposingPen, RecordingPen):
|
|||||||
>>> class CompositeGlyph(object):
|
>>> class CompositeGlyph(object):
|
||||||
... def draw(self, pen):
|
... def draw(self, pen):
|
||||||
... pen.addComponent('a', (1, 0, 0, 1, -1, 1))
|
... pen.addComponent('a', (1, 0, 0, 1, -1, 1))
|
||||||
>>> glyphSet = {'a': SimpleGlyph(), 'b': CompositeGlyph()}
|
>>> class MissingComponent(object):
|
||||||
|
... def draw(self, pen):
|
||||||
|
... pen.addComponent('foobar', (1, 0, 0, 1, 0, 0))
|
||||||
|
>>> class FlippedComponent(object):
|
||||||
|
... def draw(self, pen):
|
||||||
|
... pen.addComponent('a', (-1, 0, 0, 1, 0, 0))
|
||||||
|
>>> glyphSet = {
|
||||||
|
... 'a': SimpleGlyph(),
|
||||||
|
... 'b': CompositeGlyph(),
|
||||||
|
... 'c': MissingComponent(),
|
||||||
|
... 'd': FlippedComponent(),
|
||||||
|
... }
|
||||||
>>> for name, glyph in sorted(glyphSet.items()):
|
>>> for name, glyph in sorted(glyphSet.items()):
|
||||||
... pen = DecomposingRecordingPen(glyphSet)
|
... pen = DecomposingRecordingPen(glyphSet)
|
||||||
|
... try:
|
||||||
|
... glyph.draw(pen)
|
||||||
|
... except pen.MissingComponentError:
|
||||||
|
... pass
|
||||||
|
... print("{}: {}".format(name, pen.value))
|
||||||
|
a: [('moveTo', ((0, 0),)), ('curveTo', ((1, 1), (2, 2), (3, 3))), ('closePath', ())]
|
||||||
|
b: [('moveTo', ((-1, 1),)), ('curveTo', ((0, 2), (1, 3), (2, 4))), ('closePath', ())]
|
||||||
|
c: []
|
||||||
|
d: [('moveTo', ((0, 0),)), ('curveTo', ((-1, 1), (-2, 2), (-3, 3))), ('closePath', ())]
|
||||||
|
>>> for name, glyph in sorted(glyphSet.items()):
|
||||||
|
... pen = DecomposingRecordingPen(
|
||||||
|
... glyphSet, skipMissingComponents=True, reverseFlipped=True,
|
||||||
|
... )
|
||||||
... glyph.draw(pen)
|
... glyph.draw(pen)
|
||||||
... print("{}: {}".format(name, pen.value))
|
... print("{}: {}".format(name, pen.value))
|
||||||
a: [('moveTo', ((0, 0),)), ('curveTo', ((1, 1), (2, 2), (3, 3))), ('closePath', ())]
|
a: [('moveTo', ((0, 0),)), ('curveTo', ((1, 1), (2, 2), (3, 3))), ('closePath', ())]
|
||||||
b: [('moveTo', ((-1, 1),)), ('curveTo', ((0, 2), (1, 3), (2, 4))), ('closePath', ())]
|
b: [('moveTo', ((-1, 1),)), ('curveTo', ((0, 2), (1, 3), (2, 4))), ('closePath', ())]
|
||||||
|
c: []
|
||||||
|
d: [('moveTo', ((0, 0),)), ('lineTo', ((-3, 3),)), ('curveTo', ((-2, 2), (-1, 1), (0, 0))), ('closePath', ())]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# raises KeyError if base glyph is not found in glyphSet
|
# raises MissingComponentError(KeyError) if base glyph is not found in glyphSet
|
||||||
skipMissingComponents = False
|
skipMissingComponents = False
|
||||||
|
|
||||||
|
|
||||||
@ -174,6 +201,96 @@ class RecordingPointPen(AbstractPointPen):
|
|||||||
drawPoints = replay
|
drawPoints = replay
|
||||||
|
|
||||||
|
|
||||||
|
class DecomposingRecordingPointPen(DecomposingPointPen, RecordingPointPen):
|
||||||
|
"""Same as RecordingPointPen, except that it doesn't keep components
|
||||||
|
as references, but draws them decomposed as regular contours.
|
||||||
|
|
||||||
|
The constructor takes a required 'glyphSet' positional argument,
|
||||||
|
a dictionary of pointPen-drawable glyph objects (i.e. with a 'drawPoints' method)
|
||||||
|
keyed by thir name; other arguments are forwarded to the DecomposingPointPen's
|
||||||
|
constructor::
|
||||||
|
|
||||||
|
>>> from pprint import pprint
|
||||||
|
>>> class SimpleGlyph(object):
|
||||||
|
... def drawPoints(self, pen):
|
||||||
|
... pen.beginPath()
|
||||||
|
... pen.addPoint((0, 0), "line")
|
||||||
|
... pen.addPoint((1, 1))
|
||||||
|
... pen.addPoint((2, 2))
|
||||||
|
... pen.addPoint((3, 3), "curve")
|
||||||
|
... pen.endPath()
|
||||||
|
>>> class CompositeGlyph(object):
|
||||||
|
... def drawPoints(self, pen):
|
||||||
|
... pen.addComponent('a', (1, 0, 0, 1, -1, 1))
|
||||||
|
>>> class MissingComponent(object):
|
||||||
|
... def drawPoints(self, pen):
|
||||||
|
... pen.addComponent('foobar', (1, 0, 0, 1, 0, 0))
|
||||||
|
>>> class FlippedComponent(object):
|
||||||
|
... def drawPoints(self, pen):
|
||||||
|
... pen.addComponent('a', (-1, 0, 0, 1, 0, 0))
|
||||||
|
>>> glyphSet = {
|
||||||
|
... 'a': SimpleGlyph(),
|
||||||
|
... 'b': CompositeGlyph(),
|
||||||
|
... 'c': MissingComponent(),
|
||||||
|
... 'd': FlippedComponent(),
|
||||||
|
... }
|
||||||
|
>>> for name, glyph in sorted(glyphSet.items()):
|
||||||
|
... pen = DecomposingRecordingPointPen(glyphSet)
|
||||||
|
... try:
|
||||||
|
... glyph.drawPoints(pen)
|
||||||
|
... except pen.MissingComponentError:
|
||||||
|
... pass
|
||||||
|
... pprint({name: pen.value})
|
||||||
|
{'a': [('beginPath', (), {}),
|
||||||
|
('addPoint', ((0, 0), 'line', False, None), {}),
|
||||||
|
('addPoint', ((1, 1), None, False, None), {}),
|
||||||
|
('addPoint', ((2, 2), None, False, None), {}),
|
||||||
|
('addPoint', ((3, 3), 'curve', False, None), {}),
|
||||||
|
('endPath', (), {})]}
|
||||||
|
{'b': [('beginPath', (), {}),
|
||||||
|
('addPoint', ((-1, 1), 'line', False, None), {}),
|
||||||
|
('addPoint', ((0, 2), None, False, None), {}),
|
||||||
|
('addPoint', ((1, 3), None, False, None), {}),
|
||||||
|
('addPoint', ((2, 4), 'curve', False, None), {}),
|
||||||
|
('endPath', (), {})]}
|
||||||
|
{'c': []}
|
||||||
|
{'d': [('beginPath', (), {}),
|
||||||
|
('addPoint', ((0, 0), 'line', False, None), {}),
|
||||||
|
('addPoint', ((-1, 1), None, False, None), {}),
|
||||||
|
('addPoint', ((-2, 2), None, False, None), {}),
|
||||||
|
('addPoint', ((-3, 3), 'curve', False, None), {}),
|
||||||
|
('endPath', (), {})]}
|
||||||
|
>>> for name, glyph in sorted(glyphSet.items()):
|
||||||
|
... pen = DecomposingRecordingPointPen(
|
||||||
|
... glyphSet, skipMissingComponents=True, reverseFlipped=True,
|
||||||
|
... )
|
||||||
|
... glyph.drawPoints(pen)
|
||||||
|
... pprint({name: pen.value})
|
||||||
|
{'a': [('beginPath', (), {}),
|
||||||
|
('addPoint', ((0, 0), 'line', False, None), {}),
|
||||||
|
('addPoint', ((1, 1), None, False, None), {}),
|
||||||
|
('addPoint', ((2, 2), None, False, None), {}),
|
||||||
|
('addPoint', ((3, 3), 'curve', False, None), {}),
|
||||||
|
('endPath', (), {})]}
|
||||||
|
{'b': [('beginPath', (), {}),
|
||||||
|
('addPoint', ((-1, 1), 'line', False, None), {}),
|
||||||
|
('addPoint', ((0, 2), None, False, None), {}),
|
||||||
|
('addPoint', ((1, 3), None, False, None), {}),
|
||||||
|
('addPoint', ((2, 4), 'curve', False, None), {}),
|
||||||
|
('endPath', (), {})]}
|
||||||
|
{'c': []}
|
||||||
|
{'d': [('beginPath', (), {}),
|
||||||
|
('addPoint', ((0, 0), 'curve', False, None), {}),
|
||||||
|
('addPoint', ((-3, 3), 'line', False, None), {}),
|
||||||
|
('addPoint', ((-2, 2), None, False, None), {}),
|
||||||
|
('addPoint', ((-1, 1), None, False, None), {}),
|
||||||
|
('endPath', (), {})]}
|
||||||
|
"""
|
||||||
|
|
||||||
|
# raises MissingComponentError(KeyError) if base glyph is not found in glyphSet
|
||||||
|
skipMissingComponents = False
|
||||||
|
|
||||||
|
|
||||||
def lerpRecordings(recording1, recording2, factor=0.5):
|
def lerpRecordings(recording1, recording2, factor=0.5):
|
||||||
"""Linearly interpolate between two recordings. The recordings
|
"""Linearly interpolate between two recordings. The recordings
|
||||||
must be decomposed, i.e. they must not contain any components.
|
must be decomposed, i.e. they must not contain any components.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user