def addPoint(self, pt, segmentType=None, smooth=False, name=None, **kwargs): """Add a point to the current sub path.""" if segmentType in ['curve', 'qcurve']: # it's an offcurve, let's buffer them until we get another oncurve # and we know what to do with them self._offCurveBuffer.append((pt, segmentType, smooth, name, kwargs)) return elif segmentType == "move": # start of an open contour self.otherPointPen.addPoint(pt, segmentType, smooth, name) # how to add kwargs? self._lastPt = pt self._offCurveBuffer = [] elif segmentType == "line": if self._lastPt is None: self.otherPointPen.addPoint(pt, segmentType, smooth, name) # how to add kwargs? self._lastPt = pt elif distance(pt, self._lastPt) >= self.threshold: # we're oncurve and far enough from the last oncurve if self._offCurveBuffer: # empty any buffered offcurves for buf_pt, buf_segmentType, buf_smooth, buf_name, buf_kwargs in self._offCurveBuffer: self.otherPointPen.addPoint(buf_pt, buf_segmentType, buf_smooth, buf_name) # how to add kwargs? self._offCurveBuffer = [] # finally add the oncurve. self.otherPointPen.addPoint(pt, segmentType, smooth, name) # how to add kwargs? self._lastPt = pt else: # we're too short, so we're not going to make it. # we need to clear out the offcurve buffer. self._offCurveBuffer = []
def _lineTo(self, pt): if pt == self.currentPt: return d = distance(self.currentPt, pt) maxSteps = int(round(d / self.approximateSegmentLength)) if maxSteps < 1: self.currentPt = pt return step = 1.0 / maxSteps for factor in range(1, maxSteps + 1): pti = interpolatePoint(self.currentPt, pt, factor * step) prev_pt = interpolatePoint(self.currentPt, pt, (factor - 1) * step) dist = distance(pti, self.point) if self.bestDistance > dist: self.bestDistance = dist self.closest = pti self.orthoPt = self.getOrtho(prev_pt, pti) self.currentPt = pt
def _lineTo(self, pt): if self.filterDoubles: if pt == self.currentPt: return if not self.segmentLines: self.otherPen.lineTo(pt) self.currentPt = pt return 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 _qCurveToOne(self, pt1, pt2): falseCurve = (pt1 == self.currentPt) or (pt1 == pt2) if falseCurve: self._lineTo(pt2) return est = calcQuadraticArcLength(self.currentPt, pt1, pt2) / self.approximateSegmentLength maxSteps = int(round(est)) if maxSteps < 1: self.currentPt = pt2 return step = 1.0 / maxSteps for factor in range(1, maxSteps + 1): pt = getQuadraticPoint(factor * step, self.currentPt, pt1, pt2) prev_pt = getQuadraticPoint((factor-1) * step, self.currentPt, pt1, pt2) dist = distance(pt, self.point) if self.bestDistance > dist: self.bestDistance = dist self.closest = pt self.orthoPt = self.getOrtho(prev_pt, pt) self.currentPt = pt2
def _curveToOne(self, pt1, pt2, pt3): falseCurve = (pt1 == self.currentPt) and (pt2 == pt3) if falseCurve: self._lineTo(pt3) return est = estimateCubicCurveLength(self.currentPt, pt1, pt2, pt3) / self.approximateSegmentLength maxSteps = int(round(est)) if maxSteps < 1: self.currentPt = pt3 return step = 1.0 / maxSteps for factor in range(1, maxSteps + 1): pt = getCubicPoint(factor * step, self.currentPt, pt1, pt2, pt3) prev_pt = getCubicPoint((factor-1) * step, self.currentPt, pt1, pt2, pt3) dist = distance(pt, self.point) if self.bestDistance > dist: self.bestDistance = dist self.closest = pt self.orthoPt = self.getOrtho(prev_pt, pt) self.currentPt = pt3
def qCurveTo(self, *points): if self.threshold <= distance(points[-1], self._lastPt): self.otherPen.qCurveTo(*points) self._lastPt = points[-1]
def curveTo(self, pt1, pt2, pt3): if self.threshold <= distance(pt3, self._lastPt): self.otherPen.curveTo(pt1, pt2, pt3) self._lastPt = pt3
def lineTo(self, pt, smooth=False): if self.threshold <= distance(pt, self._lastPt): self.otherPen.lineTo(pt) self._lastPt = pt
def drawClosest(self, info): if not self.activDraw: return if self.closest and self.ortho: p = self.closest[0], self.closest[1] s = info['scale'] r = 2.5 * s rOutline = 5 * s rOutline2 = 8 * s strokeWidth(.5 * s) normOrtho = self.normalize(self.ortho) save() newPath() stroke(.2) moveTo((p)) endOut = p[0] + normOrtho[0] * 2000, p[1] + normOrtho[1] * 2000 lineTo(endOut) closePath() drawPath() restore() save() newPath() stroke(.2) moveTo((p)) endIn = p[0] - normOrtho[0] * 2000, p[1] - normOrtho[1] * 2000 lineTo(endIn) closePath() drawPath() restore() save() fill(None) stroke(1, 0, 1) oval(p[0] - rOutline, p[1] - rOutline, 2 * rOutline, 2 * rOutline) oval(p[0] - rOutline2, p[1] - rOutline2, 2 * rOutline2, 2 * rOutline2) restore() self.sections = IntersectGlyphWithLine(self.g, (endOut, endIn), canHaveComponent=True, addSideBearings=False) self.sections.sort() save() lens = len(self.sections) if lens > 1: for i in range(lens - 1): cur = self.sections[i] next = self.sections[(i + 1) % lens] dist = distance(cur, next) fontsize = 9 * s #*(max(1, min(1.5, 100/dist))) midPt = (cur[0] + next[0]) * .5, (cur[1] + next[1]) * .5 if self.g.pointInside(midPt): fillText = 0 fillDisc = 1 else: fillText = 1 fillDisc = 0 save() fill(1, 0, 1) stroke(None) oval(cur[0] - r, cur[1] - r, 2 * r, 2 * r) restore() txt = str(int(dist)) stroke(None) fill(fillDisc, fillDisc, fillDisc, .8) oval(midPt[0] - fontsize * 1.5, midPt[1] - fontsize * 1.35, 2 * fontsize * 1.5, 2 * fontsize * 1.5) font('Menlo-Bold', fontsize) fill(fillText) text(txt, midPt[0] - fontsize * .3 * len(txt), midPt[1] - fontsize * .5) save() fill(1, 0, 1) stroke(None) oval(next[0] - r, next[1] - r, 2 * r, 2 * r) restore() restore()