/** * Returns a path which is cappedPath at the ends, to prevent it from drawing under the end caps. */ protected BezierPath getCappedPath() { if (cappedPath == null) { cappedPath = path.clone(); if (isClosed()) { cappedPath.setClosed(true); } else { if (cappedPath.size() > 1) { if (get(START_DECORATION) != null) { BezierPath.Node p0 = cappedPath.get(0); BezierPath.Node p1 = cappedPath.get(1); Point2D.Double pp; if ((p0.getMask() & BezierPath.C2_MASK) != 0) { pp = p0.getControlPoint(2); } else if ((p1.getMask() & BezierPath.C1_MASK) != 0) { pp = p1.getControlPoint(1); } else { pp = p1.getControlPoint(0); } double radius = get(START_DECORATION).getDecorationRadius(this); double lineLength = Geom.length(p0.getControlPoint(0), pp); cappedPath.set( 0, 0, Geom.cap(pp, p0.getControlPoint(0), -Math.min(radius, lineLength))); } if (get(END_DECORATION) != null) { BezierPath.Node p0 = cappedPath.get(cappedPath.size() - 1); BezierPath.Node p1 = cappedPath.get(cappedPath.size() - 2); Point2D.Double pp; if ((p0.getMask() & BezierPath.C1_MASK) != 0) { pp = p0.getControlPoint(1); } else if ((p1.getMask() & BezierPath.C2_MASK) != 0) { pp = p1.getControlPoint(2); } else { pp = p1.getControlPoint(0); } double radius = get(END_DECORATION).getDecorationRadius(this); double lineLength = Geom.length(p0.getControlPoint(0), pp); cappedPath.set( cappedPath.size() - 1, 0, Geom.cap(pp, p0.getControlPoint(0), -Math.min(radius, lineLength))); } cappedPath.invalidatePath(); } } } return cappedPath; }
protected void readPoints(DOMInput in) throws IOException { path.clear(); in.openElement("points"); setClosed(in.getAttribute("closed", false)); for (int i = 0, n = in.getElementCount("p"); i < n; i++) { in.openElement("p", i); BezierPath.Node node = new BezierPath.Node( in.getAttribute("mask", 0), in.getAttribute("x", 0d), in.getAttribute("y", 0d), in.getAttribute("c1x", in.getAttribute("x", 0d)), in.getAttribute("c1y", in.getAttribute("y", 0d)), in.getAttribute("c2x", in.getAttribute("x", 0d)), in.getAttribute("c2y", in.getAttribute("y", 0d))); node.keepColinear = in.getAttribute("colinear", true); path.add(node); path.invalidatePath(); in.closeElement(); } in.closeElement(); }
@Override protected void validate() { super.validate(); path.invalidatePath(); cappedPath = null; }
@Override public void invalidate() { super.invalidate(); path.invalidatePath(); cappedPath = null; }
public void lineout(ConnectionFigure figure) { BezierPath path = ((LineConnectionFigure) figure).getBezierPath(); Connector start = figure.getStartConnector(); Connector end = figure.getEndConnector(); if (start == null || end == null || path == null) { return; } // Special treatment if the connection connects the same figure if (figure.getStartFigure() == figure.getEndFigure()) { // Ensure path has exactly 4 nodes while (path.size() < 4) { path.add(1, new BezierPath.Node(0, 0)); } while (path.size() > 4) { path.remove(1); } Point2D.Double sp = start.findStart(figure); Point2D.Double ep = end.findEnd(figure); Rectangle2D.Double sb = start.getBounds(); Rectangle2D.Double eb = end.getBounds(); int soutcode = sb.outcode(sp); if (soutcode == 0) { soutcode = Geom.outcode(sb, eb); } int eoutcode = eb.outcode(ep); if (eoutcode == 0) { eoutcode = Geom.outcode(sb, eb); } path.get(0).moveTo(sp); path.get(path.size() - 1).moveTo(ep); switch (soutcode) { case Geom.OUT_TOP: eoutcode = Geom.OUT_LEFT; break; case Geom.OUT_RIGHT: eoutcode = Geom.OUT_TOP; break; case Geom.OUT_BOTTOM: eoutcode = Geom.OUT_RIGHT; break; case Geom.OUT_LEFT: eoutcode = Geom.OUT_BOTTOM; break; default: eoutcode = Geom.OUT_TOP; soutcode = Geom.OUT_RIGHT; break; } // path.get(0).moveTo(sp.x + shoulderSize, sp.y); path.get(0).mask = BezierPath.C2_MASK; if ((soutcode & Geom.OUT_RIGHT) != 0) { path.get(0).x[2] = sp.x + shoulderSize; path.get(0).y[2] = sp.y; } else if ((soutcode & Geom.OUT_LEFT) != 0) { path.get(0).x[2] = sp.x - shoulderSize; path.get(0).y[2] = sp.y; } else if ((soutcode & Geom.OUT_BOTTOM) != 0) { path.get(0).x[2] = sp.x; path.get(0).y[2] = sp.y + shoulderSize; } else { path.get(0).x[2] = sp.x; path.get(0).y[2] = sp.y - shoulderSize; } path.get(1).mask = BezierPath.C2_MASK; path.get(1).moveTo(sp.x + shoulderSize, (sp.y + ep.y) / 2); path.get(1).x[2] = sp.x + shoulderSize; path.get(1).y[2] = ep.y - shoulderSize; path.get(2).mask = BezierPath.C1_MASK; path.get(2).moveTo((sp.x + ep.x) / 2, ep.y - shoulderSize); path.get(2).x[1] = sp.x + shoulderSize; path.get(2).y[1] = ep.y - shoulderSize; path.get(3).mask = BezierPath.C1_MASK; if ((eoutcode & Geom.OUT_RIGHT) != 0) { path.get(3).x[1] = ep.x + shoulderSize; path.get(3).y[1] = ep.y; } else if ((eoutcode & Geom.OUT_LEFT) != 0) { path.get(3).x[1] = ep.x - shoulderSize; path.get(3).y[1] = ep.y; } else if ((eoutcode & Geom.OUT_BOTTOM) != 0) { path.get(3).x[1] = ep.x; path.get(3).y[1] = ep.y + shoulderSize; } else { path.get(3).x[1] = ep.x; path.get(3).y[1] = ep.y - shoulderSize; } } else { Point2D.Double sp = start.findStart(figure); Point2D.Double ep = end.findEnd(figure); path.clear(); if (sp.x == ep.x || sp.y == ep.y) { path.add(new BezierPath.Node(ep.x, ep.y)); } else { Rectangle2D.Double sb = start.getBounds(); sb.x += 5d; sb.y += 5d; sb.width -= 10d; sb.height -= 10d; Rectangle2D.Double eb = end.getBounds(); eb.x += 5d; eb.y += 5d; eb.width -= 10d; eb.height -= 10d; int soutcode = sb.outcode(sp); if (soutcode == 0) { soutcode = Geom.outcode(sb, eb); } int eoutcode = eb.outcode(ep); if (eoutcode == 0) { eoutcode = Geom.outcode(eb, sb); } if ((soutcode & (Geom.OUT_TOP | Geom.OUT_BOTTOM)) != 0 && (eoutcode & (Geom.OUT_TOP | Geom.OUT_BOTTOM)) != 0) { path.add( new BezierPath.Node( BezierPath.C2_MASK, sp.x, sp.y, sp.x, sp.y, sp.x, (sp.y + ep.y) / 2)); path.add( new BezierPath.Node( BezierPath.C1_MASK, ep.x, ep.y, ep.x, (sp.y + ep.y) / 2, ep.x, ep.y)); } else if ((soutcode & (Geom.OUT_LEFT | Geom.OUT_RIGHT)) != 0 && (eoutcode & (Geom.OUT_LEFT | Geom.OUT_RIGHT)) != 0) { path.add( new BezierPath.Node( BezierPath.C2_MASK, sp.x, sp.y, sp.x, sp.y, (sp.x + ep.x) / 2, sp.y)); path.add( new BezierPath.Node( BezierPath.C1_MASK, ep.x, ep.y, (sp.x + ep.x) / 2, ep.y, ep.x, ep.y)); } else if (soutcode == Geom.OUT_BOTTOM || soutcode == Geom.OUT_TOP) { path.add(new BezierPath.Node(BezierPath.C2_MASK, sp.x, sp.y, sp.x, sp.y, sp.x, ep.y)); path.add(new BezierPath.Node(ep.x, ep.y)); } else { path.add(new BezierPath.Node(BezierPath.C2_MASK, sp.x, sp.y, sp.x, sp.y, ep.x, sp.y)); path.add(new BezierPath.Node(ep.x, ep.y)); } } } path.invalidatePath(); }