Tutorial request: BezierPath() to pen
-
Is there some example code on how to feed a
BezierPath
into a custom pen (where I manipulate the coordinates with a function and change the_lineTo
) and then draw that transformed path in my canvas?thanks, j
-
hallo @jo,
here’s a quick example using FlattenPen:
from fontParts.fontshell import RGlyph from fontPens.flattenPen import FlattenPen # make a bezier shape (oval) srcShape = BezierPath() srcShape.oval(100, 100, 600, 600) # draw bezier shape into a glyph srcGlyph = RGlyph() srcPen = srcGlyph.getPen() srcShape.drawToPen(srcPen) # flatten glyph into a new glyph dstGlyph = RGlyph() dstPen = dstGlyph.getPen() flattenPen = FlattenPen(dstPen, approximateSegmentLength=200) srcGlyph.draw(flattenPen) # draw the result into a bezier shape dstShape = BezierPath() dstGlyph.draw(dstShape) drawPath(dstShape)
maybe there are better ways to do it…
-
thanks Gustavo!
A
BezierPath
acts already like a pen or pointPen object and can be draw into a pen usingpath.drawToPen(anotherPen)
orpath.drawToPointPen(anotherPointPen)
-
@frederik thanks for the clarification. (polymorphism FTW!)
here’s a variation of the example script above, using BezierPaths directly as pens:
'''transform a bezier path using a pen''' from fontPens.flattenPen import FlattenPen # make a source shape srcShape = BezierPath() srcShape.oval(100, 100, 600, 600) # make a new shape for the result dstShape = BezierPath() # get a flatten pen to draw the result flattenPen = FlattenPen(dstShape, approximateSegmentLength=200) # feed the source shape into the pen srcShape.drawToPen(flattenPen) # draw the resulting shape drawPath(dstShape)
-
thanks @gferreira and @frederik!
great help. i managed to botch my rough attempt at type on a curve.# -------------------------------- # imports from fontTools.pens.basePen import BasePen # -------------------------------- # settings pw = ph = 400 r = 89 angle = pi * 3.1 baseline = ph/2 + r txt = 'HELLO' tang_f = .333 # tangent factor center = pw/2, baseline focus = pw/2, baseline - r # -------------------------------- # functions def ip(a, b, f): return a + (b-a) * f def conv_point(p): x, y = p f = (x - pw/2) / (pw/2) a = -angle/2 * f x_conv = center[0] + cos(a + pi/2) * (r + y - baseline) y_conv = center[1] + sin(a + pi/2) * (r + y - baseline) - r return x_conv, y_conv class convert_path_pen(BasePen): def __init__(self, targetPen): self.targetPen = targetPen def _moveTo(self, pt): self.targetPen.moveTo( conv_point(pt) ) self.prev_pt = pt def _lineTo(self, pt): if self.prev_pt[0] == pt[0]: self.targetPen.lineTo( conv_point(pt) ) else: tang_1 = ip(self.prev_pt[0], pt[0], tang_f), ip(self.prev_pt[1], pt[1], tang_f) tang_2 = ip(self.prev_pt[0], pt[0], 1-tang_f), ip(self.prev_pt[1], pt[1], 1-tang_f) self.targetPen.curveTo(conv_point(tang_1), conv_point(tang_2), conv_point(pt)) self.prev_pt = pt def _curveToOne(self, tang_1, tang_2, pt): self.targetPen.curveTo(conv_point(tang_1), conv_point(tang_2), conv_point(pt)) self.prev_pt = pt def _closePath(self): self.targetPen.closePath() # -------------------------------- # drawings path = BezierPath() path.text(txt, font="Helvetica", fontSize = 80, align = 'center', offset=(0, baseline)) newPage(pw, ph) trans_path = BezierPath() trans_pen = convert_path_pen( trans_path ) path.drawToPen( trans_pen ) drawPath(trans_path)
obligatory gifs
-
looking good!!
-
@jo this is very nice. thanks for sharing it!
-
found it back: this reminds me a thing I wrote some years ago