def _curveToOne(self, bcp1, bcp2, pt): bounds = self.bounds bounds = updateBounds(bounds, pt) if not pointInRect(bcp1, bounds) or not pointInRect(bcp2, bounds): bounds = unionRect(bounds, calcCubicBounds( self._getCurrentPoint(), bcp1, bcp2, pt)) self.bounds = bounds
def _checkBboxSegment(self, bcp1, bcp2, pt): # Like _checkBbox, but checks the whole segment and calculates extrema myRect = normRect((self._prev[0], self._prev[1], pt[0], pt[1])) if not pointInRect(bcp1, myRect) or not pointInRect(bcp2, myRect): extrema = getExtremaForCubic(self._prev, bcp1, bcp2, pt, h=True, v=True) for p in extrema: if self.extremum_calculate_badness: badness = self._getBadness(p, myRect) if badness >= self.extremum_ignore_badness_below: self.errors.append(OutlineError(p, "Extremum", badness)) else: self.errors.append(OutlineError(p, "Extremum"))
def _getSelectedPoints(self): if self.pStart and self.pEnd: box = self._normalizeBox(self.pStart, self.pEnd) for contour in self._glyph: for p in contour.onCurvePoints: if pointInRect((p.x, p.y), box): self.selection.addPoint(p, self.shiftDown, contour=contour) self._selectedMouseDownPoint = (p.x, p.y) for anchor in self._glyph.anchors: if pointInRect((anchor.x, anchor.y), box): self.selection.addAnchor(anchor, self.shiftDown) self._selectedMouseDownPoint = (anchor.x, anchor.y)
def _qCurveToOne(self, bcp, pt): bounds = self.bounds bounds = updateBounds(bounds, pt) if not pointInRect(bcp, bounds): bounds = unionRect( bounds, calcQuadraticBounds(self._getCurrentPoint(), bcp, pt)) self.bounds = bounds
def intersect(glyph, where, isHorizontal): """ Intersection of a glyph with a horizontal or vertical line. Intersects each segment of a glyph using fontTools bezierTools.splitCubic and splitLine methods. """ pen = CollectSegmentsPen() glyph.draw(pen) nakedGlyph = pen.getSegments() glyphIntersections = [] for i, contour in enumerate(nakedGlyph): for segment in contour: length = len(segment) if length == 2: pt1, pt2 = segment returnedSegments = splitLine(pt1, pt2, where, int(isHorizontal)) elif length == 4: pt1, pt2, pt3, pt4 = segment returnedSegments = bezierTools.splitCubic(pt1, pt2, pt3, pt4, where, int(isHorizontal)) if len(returnedSegments) > 1: intersectionPoints = findDuplicatePoints(returnedSegments) if len(intersectionPoints): box = calcBounds(segment) intersectionPoints = [point for point in intersectionPoints if arrayTools.pointInRect(point, box)] glyphIntersections.extend(intersectionPoints) return glyphIntersections
def intersect(glyph, where, isHorizontal): """ Intersect a glyph with a horizontal or vertical line. Intersect each segment of a glyph using fontTools bezierTools.splitCubic and splitLine methods. """ pen = CollectSegmentsPen(glyph.layer) glyph.draw(pen) nakedGlyph = pen.getSegments() glyphIntersections = [] for i, contour in enumerate(nakedGlyph): for segment in contour: length = len(segment) if length == 2: pt1, pt2 = segment returnedSegments = splitLine(pt1, pt2, where, int(isHorizontal)) elif length == 4: pt1, pt2, pt3, pt4 = segment returnedSegments = bezierTools.splitCubic(pt1, pt2, pt3, pt4, where, int(isHorizontal)) if len(returnedSegments) > 1: intersectionPoints = findDuplicatePoints(returnedSegments) if len(intersectionPoints): box = calcBounds(segment) intersectionPoints = [point for point in intersectionPoints if arrayTools.pointInRect(point, box)] glyphIntersections.extend(intersectionPoints) return glyphIntersections
def _qCurveToOne(self, bcp, pt): bounds = self.bounds bounds = updateBounds(bounds, pt) if not pointInRect(bcp, bounds): bounds = unionRect(bounds, calcQuadraticBounds( self._getCurrentPoint(), bcp, pt)) self.bounds = bounds
def pointBoundTouche(point, bounds): found = pointInRect(point, bounds) if not found: # lazy check x values only minX, minY, maxX, maxY = bounds found = minX <= point[0] <= maxX return found
def _getSelectedPoints(self): if self.pStart and self.pEnd: box = self._normalizeBox(self.pStart, self.pEnd) for error in self.ui.errors: p = error.position if pointInRect(p, box): self.errorSelection.addError(p, self.shiftDown) self._selectedMouseDownPoint = p
def _checkBboxSegment(self, bcp1, bcp2, pt): # Like _checkBbox, but checks the whole segment and calculates extrema myRect = normRect((self._prev[0], self._prev[1], pt[0], pt[1])) if not pointInRect(bcp1, myRect) or not pointInRect(bcp2, myRect): extrema = getExtremaForCubic(self._prev, bcp1, bcp2, pt, h=True, v=True) for p in extrema: if self.extremum_calculate_badness: badness = self._getBadness(p, myRect) if badness >= self.extremum_ignore_badness_below: self.errors.append(OutlineError( p, "Extremum", badness)) else: self.errors.append(OutlineError(p, "Extremum"))
def recalcBounds(self, glyfTable): coords, endPts, flags = self.getCoordinates(glyfTable) if len(coords) > 0: if 0: # This branch calculates exact glyph outline bounds # analytically, handling cases without on-curve # extremas, etc. However, the glyf table header # simply says that the bounds should be min/max x/y # "for coordinate data", so I suppose that means no # fancy thing here, just get extremas of all coord # points (on and off). As such, this branch is # disabled. # Collect on-curve points onCurveCoords = [coords[j] for j in range(len(coords)) if flags[j] & flagOnCurve] # Add implicit on-curve points start = 0 for end in endPts: last = end for j in range(start, end + 1): if not ((flags[j] | flags[last]) & flagOnCurve): x = (coords[last][0] + coords[j][0]) / 2 y = (coords[last][1] + coords[j][1]) / 2 onCurveCoords.append((x,y)) last = j start = end + 1 # Add bounds for curves without an explicit extrema start = 0 for end in endPts: last = end for j in range(start, end + 1): if not (flags[j] & flagOnCurve): next = j + 1 if j < end else start bbox = calcBounds([coords[last], coords[next]]) if not pointInRect(coords[j], bbox): # Ouch! warnings.warn("Outline has curve with implicit extrema.") # Ouch! Find analytical curve bounds. pthis = coords[j] plast = coords[last] if not (flags[last] & flagOnCurve): plast = ((pthis[0]+plast[0])/2, (pthis[1]+plast[1])/2) pnext = coords[next] if not (flags[next] & flagOnCurve): pnext = ((pthis[0]+pnext[0])/2, (pthis[1]+pnext[1])/2) bbox = calcQuadraticBounds(plast, pthis, pnext) onCurveCoords.append((bbox[0],bbox[1])) onCurveCoords.append((bbox[2],bbox[3])) last = j start = end + 1 self.xMin, self.yMin, self.xMax, self.yMax = calcIntBounds(onCurveCoords) else: self.xMin, self.yMin, self.xMax, self.yMax = calcIntBounds(coords) else: self.xMin, self.yMin, self.xMax, self.yMax = (0, 0, 0, 0)
def segmentInBound(segment, bounds): minX, minY, maxX, maxY = bounds for point in segment: if pointInRect(point, bounds): return True found = minX <= point[0] <= maxX if found: return True return False
def _checkBbox(self, pointToCheck, boxPoint): # boxPoint is the final point of the current node, # the other bbox point is the previous final point myRect = normRect((self._prev[0], self._prev[1], boxPoint[0], boxPoint[1])) if not pointInRect(pointToCheck, myRect): if self.extremum_calculate_badness: badness = self._getBadness(pointToCheck, myRect) if badness >= self.extremum_ignore_badness_below: self.errors.append(OutlineError(pointToCheck, "Extremum", badness)) else: self.errors.append(OutlineError(pointToCheck, "Extremum"))
def _checkBbox(self, pointToCheck, boxPoint): # boxPoint is the final point of the current node, # the other bbox point is the previous final point myRect = normRect( (self._prev[0], self._prev[1], boxPoint[0], boxPoint[1])) if not pointInRect(pointToCheck, myRect): if self.extremum_calculate_badness: badness = self._getBadness(pointToCheck, myRect) if badness >= self.extremum_ignore_badness_below: self.errors.append( OutlineError(pointToCheck, "Extremum", badness)) else: self.errors.append(OutlineError(pointToCheck, "Extremum"))
def findObjectInGlyphForPoint(self, glyph, point): found = None if self.drawingMode == COMPONENT_MODE: size = self.size for component in glyph.components: if component.baseGlyph != self.componentName: continue rect = component.box if pointInRect(point, rect): found = component break else: for contour in glyph: if contour.pointInside(point): found = contour break return found
def mouseUp(self, info): # get the glyph glyph = info["glyph"] # get the current tool tool = info["tool"] # only work when the curren tools is the editingTool if not isinstance(tool, EditingTool): return # go on when the option is down and there is no point selection in the glyph if tool.optionDown and not glyph.selection: # get the marque rect from the tool (x, y), (w, h) = tool.getMarqueRect() # normalize the rect to a minx, miny, maxx, maxy rectangle marqueRect = normRect((x, y, x + w, y + h)) # loop over all components for component in glyph.components: # get the component bounding box comonentBounds = component.box # empty components are possible if comonentBounds: # check if there an intersection between the marque rect and the component bounding box interesect, intersectionRect = sectRect(marqueRect, component.box) # if so... if interesect: # check if shift is down if tool.shiftDown: # on shift down, just toggle the current selection component.selected = not component.selected else: # othewise set the component as selected component.selected = True else: # empty component # check if the off set point of the component is inside the marque rect if pointInRect(component.offset, marqueRect): # check if shift is down if tool.shiftDown: # on shift down, just toggle the current selection component.selected = not component.selected else: # othewise set the component as selected component.selected = True # update the glyph glyph.update()
def test_pointInRect(): assert pointInRect((50, 50), (0, 0, 100, 100)) assert pointInRect((0, 0), (0, 0, 100, 100)) assert pointInRect((100, 100), (0, 0, 100, 100)) assert not pointInRect((101, 100), (0, 0, 100, 100))