def expandSegment(self, cp, segment): """Expands the Segment instance. It may contain multiple quadratics. Split into cubics and lines.""" if len(segment) == 1: # Straight line. p1 = segment.points[-1] self._cubic.append(('lineTo', (p1.x, p1.y))) cp = p1 elif len(segment) == 2: # Converts quadratic curve to cubic. p1, p2 = segment.points self.expandQuadratic2Cubic(cp.x, cp.y, p1.x, p1.y, p2.x, p2.y) cp = p2 else: # Handles implied on-curve points. for n in range(len(segment)-1): p0 = cp # Previous oncurve. p1 = segment.points[n] # next offcurve. p2 = segment.points[n+1] # offcurve or last point. if n < len(segment) - 2: # Implied point. m = APoint((p1.x + (p2.x - p1.x) / 2, p1.y + (p2.y - p1.y) / 2), True) else: # Last (oncurve) point. m = p2 self.expandQuadratic2Cubic(cp.x, cp.y, p1.x, p1.y, m.x, m.y) cp = m return cp
def _get_perpendicularMiddleLine(self): # Calculate the average middle from the projections mx = my = 0 projectionLines = self.projectionLines count = len(projectionLines) * 2 # Avoid double division of average for p, projectedP in projectionLines: mx += p.x + projectedP.x my += p.y + projectedP.y #FIXME: I'm not sure if APoint (from apoint.py) is the correct object to use here: m = APoint(mx / count, my / count) # Now project this window middle points on the two lines again. pp0 = self.point.getProjectedPoint(m) pp1 = self.parent.getProjectedPoint(m) return pp0, pp1
def projectedOnLine(self, p): u"""Answer the point context pc projects on the line of self.""" xy = pointProjectedOnLine(self.p.p, self.p1.p, p.p) return APoint(xy)
def _initialize(self): """Initializes the cached data, such as points, contours, components, segments and bounding box. """ self._points = [] # Same as self.points property with added 4 spacing points in TTF # style. self._points4 = [] self._contours = [] self._segments = [] self._cubic = [] self._boundingBox = None components = self.components coordinates = self.coordinates if coordinates or components: minX = minY = XXXL # Store bounding box as we process the coordinate. maxX = maxY = -XXXL else: minX = minY = maxX = maxY = 0 for component in components: componentName = component.baseGlyph if componentName in self.font.keys(): componentGlyph = self.font[componentName] self._cubic.append(('component', ((component.x, component.y), componentGlyph))) # Expand bounding box. cMinX, cMinY, cMaxX, cMaxY = componentGlyph.boundingBox minX = min(cMinX+component.x, minX) minY = min(cMinY+component.y, minY) maxX = max(cMaxX+component.x, maxX) maxY = max(cMaxY+component.y, maxY) flags = self.flags openContour = False openSegment = None currentOnCurve = None endPtsOfContours = set(self.endPtsOfContours) p0 = None for index, (x, y) in enumerate(coordinates): # Expand bounding box. minX = min(x, minX) maxX = max(x, maxX) minY = min(y, minY) maxY = max(y, maxY) # Create APoint, to store weakref to self and index for altering # the coordinate and onCurve. p = APoint((x, y), flags[index], self, index) self._points.append(p) if not openContour: # Also store as cubic command. self._cubic.append(('moveTo', (x, y))) p0 = p currentOnCurve = p openContour = [] self._contours.append(openContour) openContour.append(p) if not openSegment: openSegment = ASegment() self._segments.append(openSegment) openSegment.append(p) # If there is an open segment, it may contain multiple # quadratics. Split into cubics. if index in endPtsOfContours and openContour: # End of contour. if openSegment: if not p.onCurve: openSegment.append(p0) currentOnCurve = self.expandSegment(currentOnCurve, openSegment) self._cubic.append(('closePath', None)) openContour = None openSegment = None elif p.onCurve: # Inside contour. currentOnCurve = self.expandSegment(currentOnCurve, openSegment) openSegment = None # Add 4 spacing points, as default in TTF. No index, as they cannot be # written back. Instead, for writing, use self.leftMargin, # self.rightMargin and self.width. self._points4 = self._points[:] + [ APoint((minX, 0), glyph=self), APoint((0, minY), glyph=self), APoint((maxX, 0), glyph=self), APoint((0, maxY), glyph=self) ] self._boundingBox = (minX, minY, maxX, maxY) self.dirty = False # All cleaned up.
def _initialize(self): u"""Initializes the cached data, such as self.points, self.contour, self.components and self.path, as side effect of drawing the path image. TODO: Separate path creation from initialize, so we no longer need self.context here. """ self._points = [] self._points4 = [ ] # Same as self.points property with added 4 spacing points in TTF style. self._contours = [] self._segments = [] self._boundingBox = None components = self.components coordinates = self.coordinates # Get list from the font. flags = self.flags endPtsOfContours = set(self.endPtsOfContours) openContour = False openSegment = None currentOnCurve = None p0 = None minX = minY = sys.maxsize # Store bounding box as we process the coordinate. maxX = maxY = -sys.maxsize if coordinates or components: self._path = self.context.newPath() for component in components: componentName = component.baseGlyph if componentName in self.font.keys(): componentPath = self.font[componentName].path componentPath.transform((1, 0, 0, 1, component.x, component.y)) self._path.appendPath(componentPath) componentPath.transform( (1, 0, 0, 1, -component.x, -component.y)) for index, (x, y) in enumerate(coordinates): minX = min(x, minX) maxX = max(x, maxX) minY = min(y, minY) maxY = max(y, maxY) # Create APoint, to store weakref to self and index for altering the coordinate and onCurve p = APoint((x, y), flags[index], self, index) self._points.append(p) if not openContour: assert self._path is not None self._path.moveTo((x, y)) p0 = p currentOnCurve = p openContour = [] self._contours.append(openContour) openContour.append(p) if not openSegment: openSegment = ASegment() self._segments.append(openSegment) openSegment.append(p) # If there is an open segment, it may contain multiple # quadratics. Split into cubics. if index in endPtsOfContours and openContour: # End of contour. if openSegment: if not p.onCurve: openSegment.append(p0) currentOnCurve = self._drawSegment(currentOnCurve, openSegment, self._path) self._path.closePath() openContour = None openSegment = None elif p.onCurve: # Inside contour. currentOnCurve = self._drawSegment(currentOnCurve, openSegment, self._path) openSegment = None # Add 4 spacing points, as default in TTF. No index, as they cannot be written back. # Instead, for writing, use self.leftMargin, self.rightMargin and self.width. self._points4 = self._points[:] + [ APoint((minX, 0), glyph=self), APoint((0, minY), glyph=self), APoint((maxX, 0), glyph=self), APoint((0, maxY), glyph=self) ] self._boundingBox = (minX, minY, maxX, maxY) self.dirty = False # All cleaned up.