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 _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 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 _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 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 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 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))
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))