Skip to content

adding SplittedPen #44

@typemytype

Description

@typemytype

similar to FlattenPen but splits the curve segment into small curves

from fontTools.misc.bezierTools import calcCubicArcLength, splitCubicAtT
from fontTools.pens.basePen import BasePen

from fontPens.penTools import distance, interpolatePoint


class SplittedPen(BasePen):
    
    def __init__(self, otherPen, approximateSegmentLength=5):
        self.approximateSegmentLength = approximateSegmentLength
        super().__init__({})
        self.otherPen = otherPen
    
    def _moveTo(self, pt):
        self.otherPen.moveTo(pt)
        self.currentPt = pt
        self.firstPt = pt
    
    def _lineTo(self, pt):                
        d = distance(self.currentPt, pt)
        maxSteps = int(round(d / self.approximateSegmentLength))
        if maxSteps < 1:
            self.otherPen.lineTo(pt)
            self.currentPt = pt
            return
        step = 1.0 / maxSteps
        for factor in range(1, maxSteps + 1):
            self.otherPen.lineTo(interpolatePoint(self.currentPt, pt, factor * step))
        self.currentPt = pt
        
    def _curveToOne(self, pt1, pt2, pt3):
        falseCurve = (pt1 == self.currentPt) and (pt2 == pt3)
        if falseCurve:
            self._lineTo(pt3)
            return
        
        maxSteps = int(round(calcCubicArcLength(self.currentPt, pt1, pt2, pt3) / self.approximateSegmentLength))
        if maxSteps < 1:
            self.otherPen.lineTo(pt3)
            self.currentPt = pt3
            return
        
        tValues = [i / maxSteps for i in range(1, maxSteps)]
        for curve in splitCubicAtT(self.currentPt, pt1, pt2, pt3, *tValues):
            self.otherPen.curveTo(*curve[1:])

        self.currentPt = pt3
    
    def _closePath(self):
        self.lineTo(self.firstPt)
        self.otherPen.closePath()

    def _endPath(self):
        self.otherPen.endPath()

    def addComponent(self, glyphName, transformation):
        self.otherPen.addComponent(glyphName, transformation) 

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions