def test_sectRect(): intersects, rect = sectRect((0, 10, 20, 30), (0, 40, 20, 50)) assert not intersects intersects, rect = sectRect((0, 10, 20, 30), (5, 20, 35, 50)) assert intersects assert rect == (5, 20, 20, 30)
def checkPair(self, g1, g2): """New checking method contributed by Frederik Returns a Boolean if overlapping. """ kern = self.getKerning(g1, g2) # Check sidebearings first (PvB's idea) if self.rsb[g1] + self.lsb[g2] + kern > 0: return False # get the bounds and check them bounds1 = g1.box if bounds1 is None: return False bounds2 = g2.box if bounds2 is None: return False # shift bounds2 bounds2 = offsetRect(bounds2, g1.width+kern, 0) # check for intersection bounds intersectingBounds, _ = sectRect(bounds1, bounds2) if not intersectingBounds: return False # move bounds1 back, moving bounds is faster then moving all coordinates in a glyph bounds1 = offsetRect(bounds1, -g2.width-kern, 0) # create a pen for g1 with a shifted rect, draw the glyph into the pen pen1 = findPossibleOverlappingSegmentsPen.FindPossibleOverlappingSegmentsPen(g1.getParent(), bounds2) g1.draw(pen1) # create a pen for g2 with a shifted rect and move each found segment with the width and kerning pen2 = findPossibleOverlappingSegmentsPen.FindPossibleOverlappingSegmentsPen(g2.getParent(), bounds1, (g1.width+kern, 0)) # draw the glyph into the pen g2.draw(pen2) for segment1 in pen1.segments: for segment2 in pen2.segments: if len(segment1) == 4 and len(segment2) == 4: a1, a2, a3, a4 = segment1 b1, b2, b3, b4 = segment2 result = intersectCubicCubic(a1, a2, a3, a4, b1, b2, b3, b4) elif len(segment1) == 4: p1, p2, p3, p4 = segment1 a1, a2 = segment2 result = intersectCubicLine(p1, p2, p3, p4, a1, a2) elif len(segment2) == 4: p1, p2, p3, p4 = segment2 a1, a2 = segment1 result = intersectCubicLine(p1, p2, p3, p4, a1, a2) else: a1, a2 = segment1 b1, b2 = segment2 result = intersectLineLine(a1, a2, b1, b2) if result.status == "Intersection": return True return False
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 contourInside(self, other, segmentLength=10): """ Returns a boolean indicating if **other** is in the "black" area of the contour. This uses a flattened version of other's curves to calculate the location of the curves within this contour. **segmentLength** defines the desired length for the flattening process. A lower value will yeild higher accuracy but will require more computation time. """ if segmentLength < 1: segmentLength = 1 # test bounding boxes for intersection rect1 = self.bounds rect2 = other.bounds if not arrayTools.sectRect(rect1, rect2)[0]: return False # test existing on curves testedPoints = set() for point in other: if point.segmentType is None: continue pt = (point.x, point.y) if pt in testedPoints: continue if not self.pointInside(pt): return False testedPoints.add(pt) # flatten into line and test new points flat2 = other.getRepresentation("defcon.contour.flattened", approximateSegmentLength=segmentLength, segmentLines=True) for point in flat2: pt = (point.x, point.y) if pt in testedPoints: continue if not self.pointInside(pt): return False testedPoints.add(pt) return True
def checkPair(self, g1, g2): """New checking method contributed by Frederik Returns a Boolean if overlapping. """ kern = g1._layer.rightKerningForLayer_(g2._layer) if kern > 10000: kern = 0 # Check sidebearings first (PvB's idea) if self.rsb[g1] + self.lsb[g2] + kern > 0: return False # get the bounds and check them bounds1 = g1.box if bounds1 is None: return False bounds2 = g2.box if bounds2 is None: return False bounds2 = offsetRect(bounds2, g1.width + kern, 0) # check for intersection bounds intersectingBounds, _ = sectRect(bounds1, bounds2) if not intersectingBounds: return False # create a pen for g1 with a shifted rect, draw the glyph into the pen pen1 = self.penCache.get(g1.name, None) if not pen1: pen1 = SegmentsPen.SegmentsPen(self.font) g1.draw(pen1) self.penCache[g1.name] = pen1 # create a pen for g2 with a shifted rect and move each found segment with the width and kerning pen2 = self.penCache.get(g2.name, None) if not pen2: pen2 = SegmentsPen.SegmentsPen(self.font) g2.draw(pen2) self.penCache[g2.name] = pen2 offset = g1.width + kern for segment1 in pen1.segments: if not segmentInBound(segment1, bounds2): continue for segment2 in pen2.segments: segment2 = [(p[0] + offset, p[1]) for p in segment2] if not segmentInBound(segment2, bounds1): continue if len(segment1) == 4 and len(segment2) == 4: a1, a2, a3, a4 = segment1 b1, b2, b3, b4 = segment2 result = GSIntersectBezier3Bezier3(a1, a2, a3, a4, b1, b2, b3, b4) elif len(segment1) == 4: p1, p2, p3, p4 = segment1 a1, a2 = segment2 result = GSIntersectBezier3Line(p1, p2, p3, p4, a1, a2) elif len(segment2) == 4: p1, p2, p3, p4 = segment2 a1, a2 = segment1 result = GSIntersectBezier3Line(p1, p2, p3, p4, a1, a2) else: a1, a2 = segment1 b1, b2 = segment2 result = GSIntersectLineLine(a1, a2, b1, b2) result = result.x < 100000 if result: return True return False
def checkPair(self, g1, g2): """New checking method contributed by Frederik Returns a Boolean if overlapping. """ kern = g1._layer.rightKerningForLayer_(g2._layer) if kern > 10000: kern = 0 # Check sidebearings first (PvB's idea) if self.rsb[g1] + self.lsb[g2] + kern > 0: return False # get the bounds and check them bounds1 = g1.box if bounds1 is None: return False bounds2 = g2.box if bounds2 is None: return False bounds2 = offsetRect(bounds2, g1.width+kern, 0) # check for intersection bounds intersectingBounds, _ = sectRect(bounds1, bounds2) if not intersectingBounds: return False # create a pen for g1 with a shifted rect, draw the glyph into the pen pen1 = self.penCache.get(g1.name, None) if not pen1: pen1 = SegmentsPen.SegmentsPen(self.font) g1.draw(pen1) self.penCache[g1.name] = pen1 # create a pen for g2 with a shifted rect and move each found segment with the width and kerning pen2 = self.penCache.get(g2.name, None) if not pen2: pen2 = SegmentsPen.SegmentsPen(self.font) g2.draw(pen2) self.penCache[g2.name] = pen2 offset = g1.width+kern for segment1 in pen1.segments: if not segmentInBound(segment1, bounds2): continue for segment2 in pen2.segments: segment2 = [(p[0] + offset, p[1]) for p in segment2] if not segmentInBound(segment2, bounds1): continue if len(segment1) == 4 and len(segment2) == 4: a1, a2, a3, a4 = segment1 b1, b2, b3, b4 = segment2 result = GSIntersectBezier3Bezier3(a1, a2, a3, a4, b1, b2, b3, b4) elif len(segment1) == 4: p1, p2, p3, p4 = segment1 a1, a2 = segment2 result = GSIntersectBezier3Line(p1, p2, p3, p4, a1, a2) elif len(segment2) == 4: p1, p2, p3, p4 = segment2 a1, a2 = segment1 result = GSIntersectBezier3Line(p1, p2, p3, p4, a1, a2) else: a1, a2 = segment1 b1, b2 = segment2 result = GSIntersectLineLine(a1, a2, b1, b2) result = result.x < 100000 if result: return True return False
def _curve_curve_intersections_t(curve1, curve2, precision=1e-3, range1=None, range2=None): bounds1 = _curve_bounds(curve1) bounds2 = _curve_bounds(curve2) if not range1: range1 = (0.0, 1.0) if not range2: range2 = (0.0, 1.0) # If bounds don't intersect, go home intersects, _ = sectRect(bounds1, bounds2) if not intersects: return [] def midpoint(r): return 0.5 * (r[0] + r[1]) # If they do overlap but they're tiny, approximate if rectArea(bounds1) < precision and rectArea(bounds2) < precision: return [(midpoint(range1), midpoint(range2))] c11, c12 = _split_segment_at_t(curve1, 0.5) c11_range = (range1[0], midpoint(range1)) c12_range = (midpoint(range1), range1[1]) c21, c22 = _split_segment_at_t(curve2, 0.5) c21_range = (range2[0], midpoint(range2)) c22_range = (midpoint(range2), range2[1]) found = [] found.extend( _curve_curve_intersections_t(c11, c21, precision, range1=c11_range, range2=c21_range)) found.extend( _curve_curve_intersections_t(c12, c21, precision, range1=c12_range, range2=c21_range)) found.extend( _curve_curve_intersections_t(c11, c22, precision, range1=c11_range, range2=c22_range)) found.extend( _curve_curve_intersections_t(c12, c22, precision, range1=c12_range, range2=c22_range)) unique_key = lambda ts: (int(ts[0] / precision), int(ts[1] / precision)) seen = set() unique_values = [] for ts in found: key = unique_key(ts) if key in seen: continue seen.add(key) unique_values.append(ts) return unique_values
def checkPair(self, g1, g2): """New checking method contributed by Frederik Returns a Boolean if overlapping. """ kern = self.getKerning(g1, g2) # Check sidebearings first (PvB's idea) if self.rsb[g1] + self.lsb[g2] + kern > 0: return False # get the bounds and check them bounds1 = g1.box if bounds1 is None: return False bounds2 = g2.box if bounds2 is None: return False # shift bounds2 bounds2 = offsetRect(bounds2, g1.width + kern, 0) # check for intersection bounds intersectingBounds, _ = sectRect(bounds1, bounds2) if not intersectingBounds: return False # move bounds1 back, moving bounds is faster then moving all coordinates in a glyph bounds1 = offsetRect(bounds1, -g2.width - kern, 0) # create a pen for g1 with a shifted rect, draw the glyph into the pen pen1 = findPossibleOverlappingSegmentsPen.FindPossibleOverlappingSegmentsPen( g1.getParent(), bounds2) g1.draw(pen1) # create a pen for g2 with a shifted rect and move each found segment with the width and kerning pen2 = findPossibleOverlappingSegmentsPen.FindPossibleOverlappingSegmentsPen( g2.getParent(), bounds1, (g1.width + kern, 0)) # draw the glyph into the pen g2.draw(pen2) for segment1 in pen1.segments: for segment2 in pen2.segments: if len(segment1) == 4 and len(segment2) == 4: a1, a2, a3, a4 = segment1 b1, b2, b3, b4 = segment2 result = intersectCubicCubic(a1, a2, a3, a4, b1, b2, b3, b4) elif len(segment1) == 4: p1, p2, p3, p4 = segment1 a1, a2 = segment2 result = intersectCubicLine(p1, p2, p3, p4, a1, a2) elif len(segment2) == 4: p1, p2, p3, p4 = segment2 a1, a2 = segment1 result = intersectCubicLine(p1, p2, p3, p4, a1, a2) else: a1, a2 = segment1 b1, b2 = segment2 result = intersectLineLine(a1, a2, b1, b2) if result.status == "Intersection": return True return False
def checkIfPairOverlaps(g1, g2): assert g1.getParent() is g2.getParent(), 'the two glyphs do not belong to the same font' """Checking method from Touche! Returns a Boolean if overlapping. """ kern = g1.getParent().naked().flatKerning.get((g1.name, g2.name), 0) # Check sidebearings first (PvB's idea) if g1.rightMargin + g2.leftMargin + kern > 0: return False # get the bounds and check them if version[0] == '2': bounds1 = g1.bounds else: bounds1 = g1.box if bounds1 is None: return False if version[0] == '2': bounds2 = g2.bounds else: bounds2 = g2.box if bounds2 is None: return False # shift bounds2 bounds2 = offsetRect(bounds2, g1.width+kern, 0) # check for intersection bounds intersectingBounds, _ = sectRect(bounds1, bounds2) if not intersectingBounds: return False # move bounds1 back, moving bounds is faster then moving all coordinates in a glyph bounds1 = offsetRect(bounds1, -g2.width-kern, 0) # create a pen for g1 with a shifted rect, draw the glyph into the pen pen1 = FindPossibleOverlappingSegmentsPen(g1.getParent(), bounds2) g1.draw(pen1) # create a pen for g2 with a shifted rect and move each found segment with the width and kerning pen2 = FindPossibleOverlappingSegmentsPen(g2.getParent(), bounds1, (g1.width+kern, 0)) # draw the glyph into the pen g2.draw(pen2) for segment1 in pen1.segments: for segment2 in pen2.segments: if len(segment1) == 4 and len(segment2) == 4: a1, a2, a3, a4 = segment1 b1, b2, b3, b4 = segment2 result = intersectCubicCubic(a1, a2, a3, a4, b1, b2, b3, b4) elif len(segment1) == 4: p1, p2, p3, p4 = segment1 a1, a2 = segment2 result = intersectCubicLine(p1, p2, p3, p4, a1, a2) elif len(segment2) == 4: p1, p2, p3, p4 = segment2 a1, a2 = segment1 result = intersectCubicLine(p1, p2, p3, p4, a1, a2) else: a1, a2 = segment1 b1, b2 = segment2 result = intersectLineLine(a1, a2, b1, b2) if result.status == "Intersection": return True return False