From 23b0ffb19e676c6929d92a85a7d38d1c3dc049e8 Mon Sep 17 00:00:00 2001
From: rawcoder <werner.randelshofer@fibermail.ch>
Date: Sun, 9 Jan 2011 16:14:14 +0000
Subject: [PATCH] Fixes hit tests on BezierPath figures.

---
 .../nbproject/private/private.properties      |   2 +-
 .../java/org/jhotdraw/draw/BezierFigure.java  | 185 ++++++++++--------
 .../org/jhotdraw/draw/tool/package-info.java  |   8 +-
 .../java/org/jhotdraw/geom/BezierPath.java    |   1 +
 .../main/java/org/jhotdraw/geom/Shapes.java   |  54 +++--
 5 files changed, 144 insertions(+), 106 deletions(-)

diff --git a/jhotdraw7/nbproject/private/private.properties b/jhotdraw7/nbproject/private/private.properties
index 5e381c8f5..77faeafe6 100644
--- a/jhotdraw7/nbproject/private/private.properties
+++ b/jhotdraw7/nbproject/private/private.properties
@@ -5,4 +5,4 @@ do.jar=true
 javac.debug=true
 javadoc.preview=true
 jaxbwiz.endorsed.dirs=/Applications/NetBeans/NetBeans 6.8.app/Contents/Resources/NetBeans/ide12/modules/ext/jaxb/api
-user.properties.file=/Users/werni/.netbeans/6.8/build.properties
+user.properties.file=/Users/werni/.netbeans/6.9/build.properties
diff --git a/jhotdraw7/src/main/java/org/jhotdraw/draw/BezierFigure.java b/jhotdraw7/src/main/java/org/jhotdraw/draw/BezierFigure.java
index 86a95a95b..bb98c92da 100644
--- a/jhotdraw7/src/main/java/org/jhotdraw/draw/BezierFigure.java
+++ b/jhotdraw7/src/main/java/org/jhotdraw/draw/BezierFigure.java
@@ -8,7 +8,6 @@
  * license agreement you entered into with the copyright holders. For details
  * see accompanying license terms.
  */
-
 package org.jhotdraw.draw;
 
 import edu.umd.cs.findbugs.annotations.Nullable;
@@ -62,6 +61,7 @@ import org.jhotdraw.xml.DOMOutput;
  * @version $Id$
  */
 public class BezierFigure extends AbstractAttributedFigure {
+
     /**
      * The BezierPath.
      */
@@ -70,9 +70,9 @@ public class BezierFigure extends AbstractAttributedFigure {
      * The cappedPath BezierPath is derived from variable path.
      * We cache it to increase the drawing speed of the figure.
      */
-    @Nullable private transient BezierPath cappedPath;
-    
-    
+    @Nullable
+    private transient BezierPath cappedPath;
+
     /**
      * Creates an empty <code>BezierFigure</code>, for example without any
      * <code>BezierPath.Node</code>s.
@@ -83,6 +83,7 @@ public class BezierFigure extends AbstractAttributedFigure {
     public BezierFigure() {
         this(false);
     }
+
     /**
      * Creates an empty BezierFigure, for example without any
      * <code>BezierPath.Node</code>s.
@@ -97,7 +98,7 @@ public class BezierFigure extends AbstractAttributedFigure {
         set(PATH_CLOSED, isClosed);
         //path.setClosed(isClosed);
     }
-    
+
     // DRAWING
     // SHAPE AND BOUNDS
     // ATTRIBUTES
@@ -111,7 +112,7 @@ public class BezierFigure extends AbstractAttributedFigure {
     public Connector findConnector(Point2D.Double p, ConnectionFigure prototype) {
         return new ChopBezierConnector(this);
     }
-    
+
     @Override
     public Connector findCompatibleConnector(Connector c, boolean isStart) {
         return new ChopBezierConnector(this);
@@ -119,6 +120,7 @@ public class BezierFigure extends AbstractAttributedFigure {
     // COMPOSITE FIGURES
     // CLONING
     // EVENT HANDLING
+
     @Override
     protected void drawStroke(Graphics2D g) {
         if (isClosed()) {
@@ -127,9 +129,8 @@ public class BezierFigure extends AbstractAttributedFigure {
                 g.draw(path);
             } else {
                 GrowStroke gs = new GrowStroke(grow,
-                        AttributeKeys.getStrokeTotalWidth(this) *
-                        get(STROKE_MITER_LIMIT)
-                        );
+                        AttributeKeys.getStrokeTotalWidth(this)
+                        * get(STROKE_MITER_LIMIT));
                 g.draw(gs.createStrokedShape(path));
             }
         } else {
@@ -137,30 +138,30 @@ public class BezierFigure extends AbstractAttributedFigure {
         }
         drawCaps(g);
     }
-    
+
     protected void drawCaps(Graphics2D g) {
         if (getNodeCount() > 1) {
             if (get(START_DECORATION) != null) {
                 BezierPath cp = getCappedPath();
-                Point2D.Double p1 = path.get(0,0);
-                Point2D.Double p2 = cp.get(0,0);
+                Point2D.Double p1 = path.get(0, 0);
+                Point2D.Double p2 = cp.get(0, 0);
                 if (p2.equals(p1)) {
-                    p2 = path.get(1,0);
+                    p2 = path.get(1, 0);
                 }
                 get(START_DECORATION).draw(g, this, p1, p2);
             }
             if (get(END_DECORATION) != null) {
                 BezierPath cp = getCappedPath();
-                Point2D.Double p1 = path.get(path.size()-1,0);
-                Point2D.Double p2 = cp.get(path.size()-1,0);
+                Point2D.Double p1 = path.get(path.size() - 1, 0);
+                Point2D.Double p2 = cp.get(path.size() - 1, 0);
                 if (p2.equals(p1)) {
-                    p2 = path.get(path.size()-2,0);
+                    p2 = path.get(path.size() - 2, 0);
                 }
                 get(END_DECORATION).draw(g, this, p1, p2);
             }
         }
     }
-    
+
     @Override
     protected void drawFill(Graphics2D g) {
         if (isClosed() || get(UNCLOSED_PATH_FILLED)) {
@@ -169,14 +170,13 @@ public class BezierFigure extends AbstractAttributedFigure {
                 g.fill(path);
             } else {
                 GrowStroke gs = new GrowStroke(grow,
-                        AttributeKeys.getStrokeTotalWidth(this) *
-                        get(STROKE_MITER_LIMIT)
-                        );
+                        AttributeKeys.getStrokeTotalWidth(this)
+                        * get(STROKE_MITER_LIMIT));
                 g.fill(gs.createStrokedShape(path));
             }
         }
     }
-    
+
     @Override
     public boolean contains(Point2D.Double p) {
         double tolerance = Math.max(2f, AttributeKeys.getStrokeTotalWidth(this) / 2d);
@@ -186,9 +186,8 @@ public class BezierFigure extends AbstractAttributedFigure {
             }
             double grow = AttributeKeys.getPerpendicularHitGrowth(this) * 2d;
             GrowStroke gs = new GrowStroke(grow,
-                    AttributeKeys.getStrokeTotalWidth(this) *
-                    get(STROKE_MITER_LIMIT)
-                    );
+                    AttributeKeys.getStrokeTotalWidth(this)
+                    * get(STROKE_MITER_LIMIT));
             if (gs.createStrokedShape(path).contains(p)) {
                 return true;
             } else {
@@ -197,62 +196,63 @@ public class BezierFigure extends AbstractAttributedFigure {
                 }
             }
         }
-        if (! isClosed()) {
+        if (!isClosed()) {
             if (getCappedPath().outlineContains(p, tolerance)) {
                 return true;
             }
             if (get(START_DECORATION) != null) {
                 BezierPath cp = getCappedPath();
-                Point2D.Double p1 = path.get(0,0);
-                Point2D.Double p2 = cp.get(0,0);
+                Point2D.Double p1 = path.get(0, 0);
+                Point2D.Double p2 = cp.get(0, 0);
                 // FIXME - Check here, if caps path contains the point
-                if (Geom.lineContainsPoint(p1.x,p1.y,p2.x,p2.y, p.x, p.y, tolerance)) {
+                if (Geom.lineContainsPoint(p1.x, p1.y, p2.x, p2.y, p.x, p.y, tolerance)) {
                     return true;
                 }
             }
             if (get(END_DECORATION) != null) {
                 BezierPath cp = getCappedPath();
-                Point2D.Double p1 = path.get(path.size()-1,0);
-                Point2D.Double p2 = cp.get(path.size()-1,0);
+                Point2D.Double p1 = path.get(path.size() - 1, 0);
+                Point2D.Double p2 = cp.get(path.size() - 1, 0);
                 // FIXME - Check here, if caps path contains the point
-                if (Geom.lineContainsPoint(p1.x,p1.y,p2.x,p2.y, p.x, p.y, tolerance)) {
+                if (Geom.lineContainsPoint(p1.x, p1.y, p2.x, p2.y, p.x, p.y, tolerance)) {
                     return true;
                 }
             }
         }
         return false;
     }
-    
+
     @Override
     public Collection<Handle> createHandles(int detailLevel) {
         LinkedList<Handle> handles = new LinkedList<Handle>();
         switch (detailLevel % 2) {
-            case -1 : // Mouse hover handles
+            case -1: // Mouse hover handles
                 handles.add(new BezierOutlineHandle(this, true));
                 break;
-            case 0 :
+            case 0:
                 handles.add(new BezierOutlineHandle(this));
-                for (int i=0, n = path.size(); i < n; i++) {
+                for (int i = 0, n = path.size(); i < n; i++) {
                     handles.add(new BezierNodeHandle(this, i));
                 }
                 break;
-            case 1 :
+            case 1:
                 TransformHandleKit.addTransformHandles(this, handles);
                 handles.add(new BezierScaleHandle(this));
                 break;
         }
         return handles;
     }
-    
+
     @Override
     public Rectangle2D.Double getBounds() {
-        Rectangle2D.Double bounds =path.getBounds2D();
+        Rectangle2D.Double bounds = path.getBounds2D();
         return bounds;
     }
+
     @Override
     public Rectangle2D.Double getDrawingArea() {
         Rectangle2D.Double r = super.getDrawingArea();
-        
+
         if (getNodeCount() > 1) {
             if (get(START_DECORATION) != null) {
                 Point2D.Double p1 = getPoint(0, 0);
@@ -265,41 +265,42 @@ public class BezierFigure extends AbstractAttributedFigure {
                 r.add(get(END_DECORATION).getDrawingArea(this, p1, p2));
             }
         }
-        
+
         return r;
     }
-    
+
     @Override
     protected void validate() {
         super.validate();
         path.invalidatePath();
         cappedPath = null;
     }
-    
-    
-    
+
     /**
      * Returns a clone of the bezier path of this figure.
      */
     public BezierPath getBezierPath() {
         return (BezierPath) path.clone();
     }
+
     public void setBezierPath(BezierPath newValue) {
         path = (BezierPath) newValue.clone();
         this.setClosed(newValue.isClosed());
     }
-    
+
     public Point2D.Double getPointOnPath(float relative, double flatness) {
         return path.getPointOnPath(relative, flatness);
     }
-    
+
     public boolean isClosed() {
         return (Boolean) get(PATH_CLOSED);
     }
+
     public void setClosed(boolean newValue) {
         set(PATH_CLOSED, newValue);
         setConnectable(newValue);
     }
+
     @Override
     public <T> void set(AttributeKey<T> key, T newValue) {
         if (key == PATH_CLOSED) {
@@ -310,7 +311,7 @@ public class BezierFigure extends AbstractAttributedFigure {
         super.set(key, newValue);
         invalidate();
     }
-    
+
     /**
      * Sets the location of the first and the last <code>BezierPath.Node</code>
      * of the BezierFigure.
@@ -323,18 +324,20 @@ public class BezierFigure extends AbstractAttributedFigure {
         setEndPoint(lead);
         invalidate();
     }
+
     @Override
     public void transform(AffineTransform tx) {
         path.transform(tx);
         invalidate();
     }
+
     @Override
     public void invalidate() {
         super.invalidate();
         path.invalidatePath();
         cappedPath = null;
     }
-    
+
     /**
      * Returns a path which is cappedPath at the ends, to prevent
      * it from drawing under the end caps.
@@ -359,12 +362,12 @@ public class BezierFigure extends AbstractAttributedFigure {
                         }
                         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)));
+                        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);
@@ -373,8 +376,8 @@ public class BezierFigure extends AbstractAttributedFigure {
                         } 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)));
@@ -385,15 +388,17 @@ public class BezierFigure extends AbstractAttributedFigure {
         }
         return cappedPath;
     }
+
     public void layout() {
     }
-    
+
     /**
      * Adds a control point.
      */
     public void addNode(BezierPath.Node p) {
         addNode(getNodeCount(), p);
     }
+
     /**
      * Adds a node to the list of points.
      */
@@ -401,6 +406,7 @@ public class BezierFigure extends AbstractAttributedFigure {
         path.add(index, p);
         invalidate();
     }
+
     /**
      * Sets a control point.
      */
@@ -408,13 +414,14 @@ public class BezierFigure extends AbstractAttributedFigure {
         path.set(index, p);
         invalidate();
     }
-    
+
     /**
      * Gets a control point.
      */
     public BezierPath.Node getNode(int index) {
         return (BezierPath.Node) path.get(index).clone();
     }
+
     /**
      * Convenience method for getting the point coordinate of
      * the first control point of the specified node.
@@ -422,12 +429,14 @@ public class BezierFigure extends AbstractAttributedFigure {
     public Point2D.Double getPoint(int index) {
         return path.get(index).getControlPoint(0);
     }
+
     /**
      * Gets the point coordinate of a control point.
      */
     public Point2D.Double getPoint(int index, int coord) {
         return path.get(index).getControlPoint(coord);
     }
+
     /**
      * Sets the point coordinate of control point 0 at the specified node.
      */
@@ -435,12 +444,13 @@ public class BezierFigure extends AbstractAttributedFigure {
         BezierPath.Node node = path.get(index);
         double dx = p.x - node.x[0];
         double dy = p.y - node.y[0];
-        for (int i=0; i < node.x.length; i++) {
+        for (int i = 0; i < node.x.length; i++) {
             node.x[i] += dx;
             node.y[i] += dy;
         }
         invalidate();
     }
+
     /**
      * Sets the point coordinate of a control point.
      */
@@ -449,6 +459,7 @@ public class BezierFigure extends AbstractAttributedFigure {
         cp.setControlPoint(coord, p);
         setNode(index, cp);
     }
+
     /**
      * Convenience method for setting the point coordinate of the start point.
      * If the BezierFigure has not at least two nodes, nodes are added
@@ -456,11 +467,12 @@ public class BezierFigure extends AbstractAttributedFigure {
      */
     public void setStartPoint(Point2D.Double p) {
         // Add two nodes if we haven't at least two nodes
-        for (int i=getNodeCount(); i < 2; i++) {
+        for (int i = getNodeCount(); i < 2; i++) {
             addNode(0, new BezierPath.Node(p.x, p.y));
         }
         setPoint(0, p);
     }
+
     /**
      * Convenience method for setting the point coordinate of the end point.
      * If the BezierFigure has not at least two nodes, nodes are added
@@ -468,11 +480,12 @@ public class BezierFigure extends AbstractAttributedFigure {
      */
     public void setEndPoint(Point2D.Double p) {
         // Add two nodes if we haven't at least two nodes
-        for (int i=getNodeCount(); i < 2; i++) {
+        for (int i = getNodeCount(); i < 2; i++) {
             addNode(0, new BezierPath.Node(p.x, p.y));
         }
         setPoint(getNodeCount() - 1, p);
     }
+
     /**
      * Convenience method for getting the start point.
      */
@@ -480,6 +493,7 @@ public class BezierFigure extends AbstractAttributedFigure {
     public Point2D.Double getStartPoint() {
         return getPoint(0, 0);
     }
+
     /**
      * Convenience method for getting the end point.
      */
@@ -487,6 +501,7 @@ public class BezierFigure extends AbstractAttributedFigure {
     public Point2D.Double getEndPoint() {
         return getPoint(getNodeCount() - 1, 0);
     }
+
     /**
      * Finds a control point index.
      * Returns -1 if no control point could be found.
@@ -494,7 +509,7 @@ public class BezierFigure extends AbstractAttributedFigure {
      */
     public int findNode(Point2D.Double p) {
         BezierPath tp = path;
-        for (int i=0; i < tp.size(); i++) {
+        for (int i = 0; i < tp.size(); i++) {
             BezierPath.Node p2 = tp.get(i);
             if (p2.x[0] == p.x && p2.y[0] == p.y) {
                 return i;
@@ -502,6 +517,7 @@ public class BezierFigure extends AbstractAttributedFigure {
         }
         return -1;
     }
+
     /**
      * Gets the segment of the polyline that is hit by
      * the given Point2D.Double.
@@ -514,6 +530,7 @@ public class BezierFigure extends AbstractAttributedFigure {
     public int findSegment(Point2D.Double find, double tolerance) {
         return getBezierPath().findSegment(find, tolerance);
     }
+
     /**
      * Joins two segments into one if the given Point2D.Double hits a node
      * of the polyline.
@@ -531,6 +548,7 @@ public class BezierFigure extends AbstractAttributedFigure {
         }
         return false;
     }
+
     /**
      * Splits the segment at the given Point2D.Double if a segment was hit.
      * @return the index of the segment or -1 if no segment was hit.
@@ -544,27 +562,30 @@ public class BezierFigure extends AbstractAttributedFigure {
         if (i != -1) {
             addNode(i + 1, new BezierPath.Node(split));
         }
-        return i+1;
+        return i + 1;
     }
+
     /**
      * Removes the Node at the specified index.
      */
     public BezierPath.Node removeNode(int index) {
-       return path.remove(index);
+        return path.remove(index);
     }
+
     /**
      * Removes the Point2D.Double at the specified index.
      */
     protected void removeAllNodes() {
         path.clear();
     }
+
     /**
      * Gets the node count.
      */
     public int getNodeCount() {
         return path.size();
     }
-    
+
     @Override
     public BezierFigure clone() {
         BezierFigure that = (BezierFigure) super.clone();
@@ -572,17 +593,17 @@ public class BezierFigure extends AbstractAttributedFigure {
         that.invalidate();
         return that;
     }
-    
+
     @Override
     public void restoreTransformTo(Object geometry) {
         path.setTo((BezierPath) geometry);
     }
-    
+
     @Override
     public Object getTransformRestoreData() {
         return path.clone();
     }
-    
+
     public Point2D.Double chop(Point2D.Double p) {
         if (isClosed()) {
             double grow = AttributeKeys.getPerpendicularHitGrowth(this);
@@ -590,22 +611,23 @@ public class BezierFigure extends AbstractAttributedFigure {
                 return path.chop(p);
             } else {
                 GrowStroke gs = new GrowStroke(grow,
-                        AttributeKeys.getStrokeTotalWidth(this) *
-                        get(STROKE_MITER_LIMIT)
-                        );
+                        AttributeKeys.getStrokeTotalWidth(this)
+                        * get(STROKE_MITER_LIMIT));
                 return Geom.chop(gs.createStrokedShape(path), p);
             }
         } else {
             return path.chop(p);
         }
     }
-    
+
     public Point2D.Double getCenter() {
         return path.getCenter();
     }
+
     public Point2D.Double getOutermostPoint() {
         return path.get(path.indexOfOutermostNode()).getControlPoint(0);
     }
+
     /**
      * Joins two segments into one if the given Point2D.Double hits a node
      * of the polyline.
@@ -614,6 +636,7 @@ public class BezierFigure extends AbstractAttributedFigure {
     public int joinSegments(Point2D.Double join, float tolerance) {
         return path.joinSegments(join, tolerance);
     }
+
     /**
      * Splits the segment at the given Point2D.Double if a segment was hit.
      * @return the index of the segment or -1 if no segment was hit.
@@ -621,21 +644,25 @@ public class BezierFigure extends AbstractAttributedFigure {
     public int splitSegment(Point2D.Double split, float tolerance) {
         return path.splitSegment(split, tolerance);
     }
+
     /**
      * Handles a mouse click.
      */
-    @Override public boolean handleMouseClick(Point2D.Double p, MouseEvent evt, DrawingView view) {
+    @Override
+    public boolean handleMouseClick(Point2D.Double p, MouseEvent evt, DrawingView view) {
         if (evt.getClickCount() == 2 && view.getHandleDetailLevel() % 2 == 0) {
             willChange();
             final int index = splitSegment(p, 5f / view.getScaleFactor());
             if (index != -1) {
                 final BezierPath.Node newNode = getNode(index);
                 fireUndoableEditHappened(new AbstractUndoableEdit() {
+
                     @Override
                     public String getPresentationName() {
                         ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels");
                         return labels.getString("edit.bezierPath.splitSegment.text");
                     }
+
                     @Override
                     public void redo() throws CannotRedoException {
                         super.redo();
@@ -643,7 +670,7 @@ public class BezierFigure extends AbstractAttributedFigure {
                         addNode(index, newNode);
                         changed();
                     }
-                    
+
                     @Override
                     public void undo() throws CannotUndoException {
                         super.undo();
@@ -651,7 +678,6 @@ public class BezierFigure extends AbstractAttributedFigure {
                         removeNode(index);
                         changed();
                     }
-                    
                 });
                 changed();
                 evt.consume();
@@ -660,18 +686,19 @@ public class BezierFigure extends AbstractAttributedFigure {
         }
         return false;
     }
-    
+
     @Override
     public void write(DOMOutput out) throws IOException {
         writePoints(out);
         writeAttributes(out);
     }
+
     protected void writePoints(DOMOutput out) throws IOException {
         out.openElement("points");
         if (isClosed()) {
             out.addAttribute("closed", true);
         }
-        for (int i=0, n = getNodeCount(); i < n; i++) {
+        for (int i = 0, n = getNodeCount(); i < n; i++) {
             BezierPath.Node node = getNode(i);
             out.openElement("p");
             out.addAttribute("mask", node.mask, 0);
@@ -686,18 +713,19 @@ public class BezierFigure extends AbstractAttributedFigure {
         }
         out.closeElement();
     }
-    
+
     @Override
     public void read(DOMInput in) throws IOException {
         readPoints(in);
         readAttributes(in);
     }
+
     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++) {
+
+        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),
@@ -706,8 +734,7 @@ public class BezierFigure extends AbstractAttributedFigure {
                     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))
-                    );
+                    in.getAttribute("c2y", in.getAttribute("y", 0d)));
             node.keepColinear = in.getAttribute("colinear", true);
             path.add(node);
             path.invalidatePath();
@@ -715,4 +742,4 @@ public class BezierFigure extends AbstractAttributedFigure {
         }
         in.closeElement();
     }
-}
\ No newline at end of file
+}
diff --git a/jhotdraw7/src/main/java/org/jhotdraw/draw/tool/package-info.java b/jhotdraw7/src/main/java/org/jhotdraw/draw/tool/package-info.java
index 22e8e5e69..1af4a876a 100644
--- a/jhotdraw7/src/main/java/org/jhotdraw/draw/tool/package-info.java
+++ b/jhotdraw7/src/main/java/org/jhotdraw/draw/tool/package-info.java
@@ -3,11 +3,9 @@
  * Copyright (c) 1996-2010 by the original authors of JHotDraw and all its
  * contributors. All rights reserved.
  *
- * The copyright of this software is owned by the authors and
- * contributors of the JHotDraw project ("the copyright holders").
- * You may not use, copy or modify this software, except in
- * accordance with the license agreement you entered into with
- * the copyright holders. For details see accompanying license terms.
+ * You may not use, copy or modify this file, except in compliance with the
+ * license agreement you entered into with the copyright holders. For details
+ * see accompanying license terms.
  *
  * @author Werner Randelshofer
  * @version $Id$
diff --git a/jhotdraw7/src/main/java/org/jhotdraw/geom/BezierPath.java b/jhotdraw7/src/main/java/org/jhotdraw/geom/BezierPath.java
index 389810177..b240d4b37 100644
--- a/jhotdraw7/src/main/java/org/jhotdraw/geom/BezierPath.java
+++ b/jhotdraw7/src/main/java/org/jhotdraw/geom/BezierPath.java
@@ -196,6 +196,7 @@ public class BezierPath extends ArrayList<BezierPath.Node>
     @Override
         public String toString() {
             StringBuilder buf = new StringBuilder();
+            buf.append(super.toString());
             buf.append('[');
             for (int i = 0; i < 3; i++) {
                 if (i != 0) {
diff --git a/jhotdraw7/src/main/java/org/jhotdraw/geom/Shapes.java b/jhotdraw7/src/main/java/org/jhotdraw/geom/Shapes.java
index 9096e7ad5..a87d26656 100644
--- a/jhotdraw7/src/main/java/org/jhotdraw/geom/Shapes.java
+++ b/jhotdraw7/src/main/java/org/jhotdraw/geom/Shapes.java
@@ -8,7 +8,6 @@
  * license agreement you entered into with the copyright holders. For details
  * see accompanying license terms.
  */
-
 package org.jhotdraw.geom;
 
 import java.awt.*;
@@ -21,11 +20,11 @@ import java.awt.geom.*;
  * @version $Id$
  */
 public class Shapes {
-    
+
     /** Creates a new instance. */
     private Shapes() {
     }
-    
+
     /**
      * Returns true, if the outline of this bezier path contains the specified
      * point.
@@ -34,26 +33,39 @@ public class Shapes {
      * @param tolerance The tolerance for the test.
      */
     public static boolean outlineContains(Shape shape, Point2D.Double p, double tolerance) {
-        PathIterator i = shape.getPathIterator(new AffineTransform(), tolerance);
-        if (! i.isDone()) {
-            double[] coords = new double[6];
-            double prevX = coords[0];
-            double prevY = coords[1];
-            i.next();
-            while (! i.isDone()) {
-                i.currentSegment(coords);
-                if (Geom.lineContainsPoint(
-                        prevX, prevY, coords[0], coords[1],
-                        p.x, p.y, tolerance)
-                        ) {
-                    return true;
-                }
-                prevX = coords[0];
-                prevY = coords[1];
-                i.next();
+        double[] coords = new double[6];
+        double prevX = 0, prevY = 0;
+        double moveX = 0, moveY = 0;
+        for (PathIterator i = new FlatteningPathIterator(shape.getPathIterator(new AffineTransform(), tolerance), tolerance); !i.isDone(); i.next()) {
+            switch (i.currentSegment(coords)) {
+                case PathIterator.SEG_CLOSE:
+                    if (Geom.lineContainsPoint(
+                            prevX, prevY, moveX, moveY,
+                            p.x, p.y, tolerance)) {
+                        return true;
+                    }
+                    break;
+                case PathIterator.SEG_CUBICTO:
+                    break;
+                case PathIterator.SEG_LINETO:
+                    if (Geom.lineContainsPoint(
+                            prevX, prevY, coords[0], coords[1],
+                            p.x, p.y, tolerance)) {
+                        return true;
+                    }
+                    break;
+                case PathIterator.SEG_MOVETO:
+                    moveX = coords[0];
+                    moveY = coords[1];
+                    break;
+                case PathIterator.SEG_QUADTO:
+                    break;
+                default:
+                    break;
             }
+            prevX = coords[0];
+            prevY = coords[1];
         }
         return false;
     }
-    
 }
-- 
GitLab