This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

FYI: [gui] java.awt.geeom merge with GNU Classpath


Hi,

This merges in the work done by Sven de Marothy on java.awt.geom.

2004-08-08  Mark Wielaard  <mark@klomp.org>

	* java/awt/geom/CubicCurve2D.java (solveCubic): Removed duplicate
	comments.

2004-08-01  Sven de Marothy  <sven@physto.se>

	* java/awt/geom/CubicCurve2D.java: Reindent.
	(contains): Implemented.
	(intersects): Implemented.
	* java/awt/geom/QuadCurve2D.java: Likewise.
	* java/awt/geom/GeneralPath.java: Reindent and document.
	Fully (re)implemented using separate xpoints and ypoints
	float[] coords.
	* java/awt/geom/RoundRectangle2D.java: Several bugfixes (Bug #6007).

Committed to the gui branch.

Cheers,

Mark
Index: java/awt/geom/CubicCurve2D.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/geom/CubicCurve2D.java,v
retrieving revision 1.4
diff -u -r1.4 CubicCurve2D.java
--- java/awt/geom/CubicCurve2D.java	5 Jan 2004 19:19:29 -0000	1.4
+++ java/awt/geom/CubicCurve2D.java	8 Aug 2004 19:38:26 -0000
@@ -1,5 +1,5 @@
 /* CubicCurve2D.java -- represents a parameterized cubic curve in 2-D space
-   Copyright (C) 2002, 2003 Free Software Foundation
+   Copyright (C) 2002, 2003, 2004 Free Software Foundation
 
 This file is part of GNU Classpath.
 
@@ -35,7 +35,6 @@
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
-
 package java.awt.geom;
 
 import java.awt.Rectangle;
@@ -53,12 +52,14 @@
  * @author Eric Blake (ebb9@email.byu.edu)
  * @author Graydon Hoare (graydon@redhat.com)
  * @author Sascha Brawer (brawer@dandelis.ch)
+ * @author Sven de Marothy (sven@physto.se)
  *
  * @since 1.2
  */
-public abstract class CubicCurve2D
-  implements Shape, Cloneable
+public abstract class CubicCurve2D implements Shape, Cloneable
 {
+  private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0;
+
   /**
    * Constructs a new CubicCurve2D. Typical users will want to
    * construct instances of a subclass, such as {@link
@@ -68,87 +69,74 @@
   {
   }
 
-
   /**
    * Returns the <i>x</i> coordinate of the curve&#x2019;s start
    * point.
    */
   public abstract double getX1();
 
-
   /**
    * Returns the <i>y</i> coordinate of the curve&#x2019;s start
    * point.
    */
   public abstract double getY1();
 
-
   /**
    * Returns the curve&#x2019;s start point.
    */
   public abstract Point2D getP1();
 
-
   /**
    * Returns the <i>x</i> coordinate of the curve&#x2019;s first
    * control point.
    */
   public abstract double getCtrlX1();
 
-
   /**
    * Returns the <i>y</i> coordinate of the curve&#x2019;s first
    * control point.
    */
   public abstract double getCtrlY1();
 
-
   /**
    * Returns the curve&#x2019;s first control point.
    */
   public abstract Point2D getCtrlP1();
 
-
   /**
    * Returns the <i>x</i> coordinate of the curve&#x2019;s second
    * control point.
    */
   public abstract double getCtrlX2();
 
-
   /**
    * Returns the <i>y</i> coordinate of the curve&#x2019;s second
    * control point.
    */
   public abstract double getCtrlY2();
 
-
   /**
    * Returns the curve&#x2019;s second control point.
    */
   public abstract Point2D getCtrlP2();
 
-
   /**
    * Returns the <i>x</i> coordinate of the curve&#x2019;s end
    * point.
    */
   public abstract double getX2();
 
-
   /**
    * Returns the <i>y</i> coordinate of the curve&#x2019;s end
    * point.
    */
   public abstract double getY2();
 
-
   /**
    * Returns the curve&#x2019;s end point.
    */
   public abstract Point2D getP2();
 
-
   /**
    * Changes the curve geometry, separately specifying each coordinate
    * value.
@@ -183,7 +171,6 @@
   public abstract void setCurve(double x1, double y1, double cx1, double cy1,
                                 double cx2, double cy2, double x2, double y2);
 
-
   /**
    * Changes the curve geometry, specifying coordinate values in an
    * array.
@@ -206,13 +193,11 @@
    */
   public void setCurve(double[] coords, int offset)
   {
-    setCurve(coords[offset++], coords[offset++],
-             coords[offset++], coords[offset++],
-             coords[offset++], coords[offset++],
+    setCurve(coords[offset++], coords[offset++], coords[offset++],
+             coords[offset++], coords[offset++], coords[offset++],
              coords[offset++], coords[offset++]);
   }
 
-
   /**
    * Changes the curve geometry, specifying coordinate values in
    * separate Point objects.
@@ -232,11 +217,10 @@
    */
   public void setCurve(Point2D p1, Point2D c1, Point2D c2, Point2D p2)
   {
-    setCurve(p1.getX(), p1.getY(), c1.getX(), c1.getY(),
-             c2.getX(), c2.getY(), p2.getX(), p2.getY());
+    setCurve(p1.getX(), p1.getY(), c1.getX(), c1.getY(), c2.getX(), c2.getY(),
+             p2.getX(), p2.getY());
   }
 
-
   /**
    * Changes the curve geometry, specifying coordinate values in an
    * array of Point objects.
@@ -258,12 +242,10 @@
    */
   public void setCurve(Point2D[] pts, int offset)
   {
-    setCurve(pts[offset].getX(), pts[offset++].getY(),
-             pts[offset].getX(), pts[offset++].getY(),
-             pts[offset].getX(), pts[offset++].getY(),
+    setCurve(pts[offset].getX(), pts[offset++].getY(), pts[offset].getX(),
+             pts[offset++].getY(), pts[offset].getX(), pts[offset++].getY(),
              pts[offset].getX(), pts[offset++].getY());
   }
-  
 
   /**
    * Changes the curve geometry to that of another curve.
@@ -276,7 +258,6 @@
              c.getCtrlX2(), c.getCtrlY2(), c.getX2(), c.getY2());
   }
 
-
   /**
    * Calculates the squared flatness of a cubic curve, directly
    * specifying each coordinate value. The flatness is the maximal
@@ -309,7 +290,6 @@
                     Line2D.ptSegDistSq(x1, y1, x2, y2, cx2, cy2));
   }
 
-
   /**
    * Calculates the flatness of a cubic curve, directly specifying
    * each coordinate value. The flatness is the maximal distance of a
@@ -340,7 +320,6 @@
     return Math.sqrt(getFlatnessSq(x1, y1, cx1, cy1, cx2, cy2, x2, y2));
   }
 
-
   /**
    * Calculates the squared flatness of a cubic curve, specifying the
    * coordinate values in an array. The flatness is the maximal
@@ -374,13 +353,11 @@
    */
   public static double getFlatnessSq(double[] coords, int offset)
   {
-    return getFlatnessSq(coords[offset++], coords[offset++],
-                         coords[offset++], coords[offset++],
-                         coords[offset++], coords[offset++],
+    return getFlatnessSq(coords[offset++], coords[offset++], coords[offset++],
+                         coords[offset++], coords[offset++], coords[offset++],
                          coords[offset++], coords[offset++]);
   }
 
-
   /**
    * Calculates the flatness of a cubic curve, specifying the
    * coordinate values in an array. The flatness is the maximal
@@ -420,7 +397,6 @@
                                    coords[offset++], coords[offset++]));
   }
 
-
   /**
    * Calculates the squared flatness of this curve.  The flatness is
    * the maximal distance of a control point to the line between start
@@ -441,7 +417,6 @@
                          getCtrlX2(), getCtrlY2(), getX2(), getY2());
   }
 
-
   /**
    * Calculates the flatness of this curve.  The flatness is the
    * maximal distance of a control point to the line between start and
@@ -458,12 +433,10 @@
    */
   public double getFlatness()
   {
-    return Math.sqrt(getFlatnessSq(getX1(), getY1(), getCtrlX1(),
-                                   getCtrlY1(), getCtrlX2(), getCtrlY2(),
-                                   getX2(), getY2()));
+    return Math.sqrt(getFlatnessSq(getX1(), getY1(), getCtrlX1(), getCtrlY1(),
+                                   getCtrlX2(), getCtrlY2(), getX2(), getY2()));
   }
 
-
   /**
    * Subdivides this curve into two halves.
    *
@@ -482,9 +455,11 @@
   public void subdivide(CubicCurve2D left, CubicCurve2D right)
   {
     // Use empty slots at end to share single array.
-    double[] d = new double[] { getX1(), getY1(), getCtrlX1(), getCtrlY1(),
-                                getCtrlX2(), getCtrlY2(), getX2(), getY2(),
-                                0, 0, 0, 0, 0, 0 };
+    double[] d = new double[]
+                 {
+                   getX1(), getY1(), getCtrlX1(), getCtrlY1(), getCtrlX2(),
+                   getCtrlY2(), getX2(), getY2(), 0, 0, 0, 0, 0, 0
+                 };
     subdivide(d, 0, d, 0, d, 6);
     if (left != null)
       left.setCurve(d, 0);
@@ -492,7 +467,6 @@
       right.setCurve(d, 6);
   }
 
-
   /**
    * Subdivides a cubic curve into two halves.
    *
@@ -510,13 +484,12 @@
    * of <code>src</code>, or <code>null</code> if the caller is not
    * interested in the right half.
    */
-  public static void subdivide(CubicCurve2D src,
-                               CubicCurve2D left, CubicCurve2D right)
+  public static void subdivide(CubicCurve2D src, CubicCurve2D left,
+                               CubicCurve2D right)
   {
     src.subdivide(left, right);
   }
 
-
   /**
    * Subdivides a cubic curve into two halves, passing all coordinates
    * in an array.
@@ -563,18 +536,29 @@
    * index where the start point&#x2019;s <i>x</i> coordinate will be
    * stored.
    */
-  public static void subdivide(double[] src, int srcOff,
-                               double[] left, int leftOff,
-                               double[] right, int rightOff)
+  public static void subdivide(double[] src, int srcOff, double[] left,
+                               int leftOff, double[] right, int rightOff)
   {
     // To understand this code, please have a look at the image
     // "CubicCurve2D-3.png" in the sub-directory "doc-files".
-    double src_C1_x, src_C1_y, src_C2_x, src_C2_y;
-    double left_P1_x, left_P1_y;
-    double left_C1_x, left_C1_y, left_C2_x, left_C2_y;
-    double right_C1_x, right_C1_y, right_C2_x, right_C2_y;
-    double right_P2_x, right_P2_y;
-    double Mid_x, Mid_y; // Mid = left.P2 = right.P1
+    double src_C1_x;
+    double src_C1_y;
+    double src_C2_x;
+    double src_C2_y;
+    double left_P1_x;
+    double left_P1_y;
+    double left_C1_x;
+    double left_C1_y;
+    double left_C2_x;
+    double left_C2_y;
+    double right_C1_x;
+    double right_C1_y;
+    double right_C2_x;
+    double right_C2_y;
+    double right_P2_x;
+    double right_P2_y;
+    double Mid_x; // Mid = left.P2 = right.P1
+    double Mid_y; // Mid = left.P2 = right.P1
 
     left_P1_x = src[srcOff];
     left_P1_y = src[srcOff + 1];
@@ -599,31 +583,30 @@
     Mid_y = (left_C2_y + right_C1_y) / 2;
 
     if (left != null)
-    {
-      left[leftOff] = left_P1_x;
-      left[leftOff + 1] = left_P1_y;
-      left[leftOff + 2] = left_C1_x;
-      left[leftOff + 3] = left_C1_y;
-      left[leftOff + 4] = left_C2_x;
-      left[leftOff + 5] = left_C2_y;
-      left[leftOff + 6] = Mid_x;
-      left[leftOff + 7] = Mid_y;
-    }
+      {
+	left[leftOff] = left_P1_x;
+	left[leftOff + 1] = left_P1_y;
+	left[leftOff + 2] = left_C1_x;
+	left[leftOff + 3] = left_C1_y;
+	left[leftOff + 4] = left_C2_x;
+	left[leftOff + 5] = left_C2_y;
+	left[leftOff + 6] = Mid_x;
+	left[leftOff + 7] = Mid_y;
+      }
 
     if (right != null)
-    {
-      right[rightOff] = Mid_x;
-      right[rightOff + 1] = Mid_y;
-      right[rightOff + 2] = right_C1_x;
-      right[rightOff + 3] = right_C1_y;
-      right[rightOff + 4] = right_C2_x;
-      right[rightOff + 5] = right_C2_y;
-      right[rightOff + 6] = right_P2_x;
-      right[rightOff + 7] = right_P2_y;
-    }
+      {
+	right[rightOff] = Mid_x;
+	right[rightOff + 1] = Mid_y;
+	right[rightOff + 2] = right_C1_x;
+	right[rightOff + 3] = right_C1_y;
+	right[rightOff + 4] = right_C2_x;
+	right[rightOff + 5] = right_C2_y;
+	right[rightOff + 6] = right_P2_x;
+	right[rightOff + 7] = right_P2_y;
+      }
   }
 
-
   /**
    * Finds the non-complex roots of a cubic equation, placing the
    * results into the same array as the equation coefficients. The
@@ -670,7 +653,6 @@
     return solveCubic(eqn, eqn);
   }
 
-
   /**
    * Finds the non-complex roots of a cubic equation. The following
    * equation is being solved:
@@ -727,9 +709,19 @@
     // The Java implementation is very similar to the GSL code, but
     // not a strict one-to-one copy. For example, GSL would sort the
     // result.
-
-    double a, b, c, q, r, Q, R;
-    double c3, Q3, R2, CR2, CQ3;
+    
+    double a;
+    double b;
+    double c;
+    double q;
+    double r;
+    double Q;
+    double R;
+    double c3;
+    double Q3;
+    double R2;
+    double CR2;
+    double CQ3;
 
     // If the cubic coefficient is zero, we have a quadratic equation.
     c3 = eqn[3];
@@ -755,219 +747,267 @@
     CQ3 = 2916 * q * q * q;
 
     if (R == 0 && Q == 0)
-    {
-      // The GNU Scientific Library would return three identical
-      // solutions in this case.
-      res[0] = -a/3;
-      return 1;
-    }
-
-    if (CR2 == CQ3) 
-    {
-      /* this test is actually R2 == Q3, written in a form suitable
-         for exact computation with integers */
-
-      /* Due to finite precision some double roots may be missed, and
-         considered to be a pair of complex roots z = x +/- epsilon i
-         close to the real axis. */
-
-      double sqrtQ = Math.sqrt(Q);
-
-      if (R > 0)
       {
-        res[0] = -2 * sqrtQ - a/3;
-        res[1] = sqrtQ - a/3;
+	// The GNU Scientific Library would return three identical
+	// solutions in this case.
+	res[0] = -a / 3;
+	return 1;
       }
-      else
+
+    if (CR2 == CQ3)
       {
-        res[0] = -sqrtQ - a/3;
-        res[1] = 2 * sqrtQ - a/3;
+	/* this test is actually R2 == Q3, written in a form suitable
+	   for exact computation with integers */
+	/* Due to finite precision some double roots may be missed, and
+	   considered to be a pair of complex roots z = x +/- epsilon i
+	   close to the real axis. */
+	double sqrtQ = Math.sqrt(Q);
+
+	if (R > 0)
+	  {
+	    res[0] = -2 * sqrtQ - a / 3;
+	    res[1] = sqrtQ - a / 3;
+	  }
+	else
+	  {
+	    res[0] = -sqrtQ - a / 3;
+	    res[1] = 2 * sqrtQ - a / 3;
+	  }
+	return 2;
       }
-      return 2;
-    }
 
     if (CR2 < CQ3) /* equivalent to R2 < Q3 */
-    {
-      double sqrtQ = Math.sqrt(Q);
-      double sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
-      double theta = Math.acos(R / sqrtQ3);
-      double norm = -2 * sqrtQ;
-      res[0] = norm * Math.cos(theta / 3) - a / 3;
-      res[1] = norm * Math.cos((theta + 2.0 * Math.PI) / 3) - a/3;
-      res[2] = norm * Math.cos((theta - 2.0 * Math.PI) / 3) - a/3;
+      {
+	double sqrtQ = Math.sqrt(Q);
+	double sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
+	double theta = Math.acos(R / sqrtQ3);
+	double norm = -2 * sqrtQ;
+	res[0] = norm * Math.cos(theta / 3) - a / 3;
+	res[1] = norm * Math.cos((theta + 2.0 * Math.PI) / 3) - a / 3;
+	res[2] = norm * Math.cos((theta - 2.0 * Math.PI) / 3) - a / 3;
 
-      // The GNU Scientific Library sorts the results. We don't.
-      return 3;
-    }
+	// The GNU Scientific Library sorts the results. We don't.
+	return 3;
+      }
 
     double sgnR = (R >= 0 ? 1 : -1);
-    double A = -sgnR * Math.pow(Math.abs(R) + Math.sqrt(R2 - Q3), 1.0/3.0);
-    double B = Q / A ;
-    res[0] = A + B - a/3;
+    double A = -sgnR * Math.pow(Math.abs(R) + Math.sqrt(R2 - Q3), 1.0 / 3.0);
+    double B = Q / A;
+    res[0] = A + B - a / 3;
     return 1;
   }
 
-
   /**
-   * Determines whether a position lies inside the area that is bounded
+   * Determines whether a position lies inside the area bounded
    * by the curve and the straight line connecting its end points.
    *
    * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
    * alt="A drawing of the area spanned by the curve" />
    *
    * <p>The above drawing illustrates in which area points are
-   * considered &#x201c;contained&#x201d; in a CubicCurve2D.
+   * considered &#x201c;inside&#x201d; a CubicCurve2D.
    */
   public boolean contains(double x, double y)
   {
-    // XXX Implement.
-    throw new Error("not implemented");
-  }
+    if (! getBounds2D().contains(x, y))
+      return false;
 
+    return ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0);
+  }
 
   /**
-   * Determines whether a point lies inside the area that is bounded
+   * Determines whether a point lies inside the area bounded
    * by the curve and the straight line connecting its end points.
    *
    * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
    * alt="A drawing of the area spanned by the curve" />
    *
    * <p>The above drawing illustrates in which area points are
-   * considered &#x201c;contained&#x201d; in a CubicCurve2D.
+   * considered &#x201c;inside&#x201d; a CubicCurve2D.
    */
   public boolean contains(Point2D p)
   {
     return contains(p.getX(), p.getY());
   }
 
-
+  /**
+   * Determines whether any part of a rectangle is inside the area bounded
+   * by the curve and the straight line connecting its end points.
+   *
+   * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
+   * alt="A drawing of the area spanned by the curve" />
+   *
+   * <p>The above drawing illustrates in which area points are
+   * considered &#x201c;inside&#x201d; in a CubicCurve2D.
+   * @see #contains(double, double)
+   */
   public boolean intersects(double x, double y, double w, double h)
   {
-    // XXX Implement.
-    throw new Error("not implemented");
-  }
+    if (! getBounds2D().contains(x, y, w, h))
+      return false;
 
+    /* Does any edge intersect? */
+    if (getAxisIntersections(x, y, true, w) != 0 /* top */
+        || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
+        || getAxisIntersections(x + w, y, false, h) != 0 /* right */
+        || getAxisIntersections(x, y, false, h) != 0) /* left */
+      return true;
 
+    /* No intersections, is any point inside? */
+    if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
+      return true;
+
+    return false;
+  }
+
+  /**
+   * Determines whether any part of a Rectangle2D is inside the area bounded 
+   * by the curve and the straight line connecting its end points.
+   * @see #intersects(double, double, double, double)
+   */
   public boolean intersects(Rectangle2D r)
   {
     return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
   }
 
-
+  /**
+   * Determine whether a rectangle is entirely inside the area that is bounded
+   * by the curve and the straight line connecting its end points.
+   *
+   * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
+   * alt="A drawing of the area spanned by the curve" />
+   *
+   * <p>The above drawing illustrates in which area points are
+   * considered &#x201c;inside&#x201d; a CubicCurve2D.
+   * @see #contains(double, double)
+   */
   public boolean contains(double x, double y, double w, double h)
   {
-    // XXX Implement.
-    throw new Error("not implemented");
-  }
+    if (! getBounds2D().intersects(x, y, w, h))
+      return false;
+
+    /* Does any edge intersect? */
+    if (getAxisIntersections(x, y, true, w) != 0 /* top */
+        || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
+        || getAxisIntersections(x + w, y, false, h) != 0 /* right */
+        || getAxisIntersections(x, y, false, h) != 0) /* left */
+      return false;
 
+    /* No intersections, is any point inside? */
+    if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
+      return true;
 
+    return false;
+  }
+
+  /**
+   * Determine whether a Rectangle2D is entirely inside the area that is 
+   * bounded by the curve and the straight line connecting its end points.
+   *
+   * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
+   * alt="A drawing of the area spanned by the curve" />
+   *
+   * <p>The above drawing illustrates in which area points are
+   * considered &#x201c;inside&#x201d; a CubicCurve2D.
+   * @see #contains(double, double)
+   */
   public boolean contains(Rectangle2D r)
   {
     return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
   }
 
-
   /**
    * Determines the smallest rectangle that encloses the
-   * curve&#x2019;s start, end and control points. As the illustration
-   * below shows, the invisible control points may cause the bounds to
-   * be much larger than the area that is actually covered by the
-   * curve.
-   *
-   * <p><img src="doc-files/CubicCurve2D-2.png" width="350" height="180"
-   * alt="An illustration of the bounds of a CubicCurve2D" />
+   * curve&#x2019;s start, end and control points.
    */
   public Rectangle getBounds()
   {
     return getBounds2D().getBounds();
   }
 
-
   public PathIterator getPathIterator(final AffineTransform at)
   {
     return new PathIterator()
-    {
-      /** Current coordinate. */
-      private int current = 0;
-
-      public int getWindingRule()
-      {
-        return WIND_NON_ZERO;
-      }
-
-      public boolean isDone()
       {
-        return current >= 2;
-      }
-
-      public void next()
-      {
-        current++;
-      }
+	/** Current coordinate. */
+	private int current = 0;
 
-      public int currentSegment(float[] coords)
-      {
-        int result;
-        switch (current)
-          {
-          case 0:
-            coords[0] = (float) getX1();
-            coords[1] = (float) getY1();
-            result = SEG_MOVETO;
-            break;            
-          case 1:
-            coords[0] = (float) getCtrlX1();
-            coords[1] = (float) getCtrlY1();
-            coords[2] = (float) getCtrlX2();
-            coords[3] = (float) getCtrlY2();
-            coords[4] = (float) getX2();
-            coords[5] = (float) getY2();
-            result = SEG_CUBICTO;
-            break;
-          default:
-            throw new NoSuchElementException("cubic iterator out of bounds");            
-          }
-        if (at != null)
-          at.transform(coords, 0, coords, 0, 3);
-        return result;
-      }
-
-      public int currentSegment(double[] coords)
-      {
-        int result;
-        switch (current)
-          {
-          case 0:
-            coords[0] = getX1();
-            coords[1] = getY1();
-            result = SEG_MOVETO;
-            break;
-          case 1:
-            coords[0] = getCtrlX1();
-            coords[1] = getCtrlY1();
-            coords[2] = getCtrlX2();
-            coords[3] = getCtrlY2();
-            coords[4] = getX2();
-            coords[5] = getY2();
-            result = SEG_CUBICTO;
-            break;
-          default:
-            throw new NoSuchElementException("cubic iterator out of bounds");
-          }        
-        if (at != null)
-          at.transform(coords, 0, coords, 0, 3);
-        return result;
-      }
-    };
+	public int getWindingRule()
+	{
+	  return WIND_NON_ZERO;
+	}
+
+	public boolean isDone()
+	{
+	  return current >= 2;
+	}
+
+	public void next()
+	{
+	  current++;
+	}
+
+	public int currentSegment(float[] coords)
+	{
+	  int result;
+	  switch (current)
+	    {
+	    case 0:
+	      coords[0] = (float) getX1();
+	      coords[1] = (float) getY1();
+	      result = SEG_MOVETO;
+	      break;
+	    case 1:
+	      coords[0] = (float) getCtrlX1();
+	      coords[1] = (float) getCtrlY1();
+	      coords[2] = (float) getCtrlX2();
+	      coords[3] = (float) getCtrlY2();
+	      coords[4] = (float) getX2();
+	      coords[5] = (float) getY2();
+	      result = SEG_CUBICTO;
+	      break;
+	    default:
+	      throw new NoSuchElementException("cubic iterator out of bounds");
+	    }
+	  if (at != null)
+	    at.transform(coords, 0, coords, 0, 3);
+	  return result;
+	}
+
+	public int currentSegment(double[] coords)
+	{
+	  int result;
+	  switch (current)
+	    {
+	    case 0:
+	      coords[0] = getX1();
+	      coords[1] = getY1();
+	      result = SEG_MOVETO;
+	      break;
+	    case 1:
+	      coords[0] = getCtrlX1();
+	      coords[1] = getCtrlY1();
+	      coords[2] = getCtrlX2();
+	      coords[3] = getCtrlY2();
+	      coords[4] = getX2();
+	      coords[5] = getY2();
+	      result = SEG_CUBICTO;
+	      break;
+	    default:
+	      throw new NoSuchElementException("cubic iterator out of bounds");
+	    }
+	  if (at != null)
+	    at.transform(coords, 0, coords, 0, 3);
+	  return result;
+	}
+      };
   }
 
-
   public PathIterator getPathIterator(AffineTransform at, double flatness)
   {
     return new FlatteningPathIterator(getPathIterator(at), flatness);
   }
 
-
   /**
    * Create a new curve with the same contents as this one.
    *
@@ -976,15 +1016,118 @@
   public Object clone()
   {
     try
-    {
-      return super.clone();
-    }
+      {
+	return super.clone();
+      }
     catch (CloneNotSupportedException e)
-    {
-      throw (Error) new InternalError().initCause(e); // Impossible
-    }
+      {
+	throw (Error) new InternalError().initCause(e); // Impossible
+      }
   }
 
+  /**
+   * Helper method used by contains() and intersects() methods, that
+   * returns the number of curve/line intersections on a given axis
+   * extending from a certain point.
+   *
+   * @param x x coordinate of the origin point
+   * @param y y coordinate of the origin point
+   * @param useYaxis axis used, if true the positive Y axis is used,
+   * false uses the positive X axis.
+   *
+   * This is an implementation of the line-crossings algorithm,
+   * Detailed in an article on Eric Haines' page:
+   * http://www.acm.org/tog/editors/erich/ptinpoly/
+   *
+   * A special-case not adressed in this code is self-intersections
+   * of the curve, e.g. if the axis intersects the self-itersection,
+   * the degenerate roots of the polynomial will erroneously count as 
+   * a single intersection of the curve, and not two.
+   */
+  private int getAxisIntersections(double x, double y, boolean useYaxis,
+                                   double distance)
+  {
+    int nCrossings = 0;
+    double a0;
+    double a1;
+    double a2;
+    double a3;
+    double b0;
+    double b1;
+    double b2;
+    double b3;
+    double[] r = new double[4];
+    int nRoots;
+
+    a0 = a3 = 0.0;
+
+    if (useYaxis)
+      {
+	a0 = getY1() - y;
+	a1 = getCtrlY1() - y;
+	a2 = getCtrlY2() - y;
+	a3 = getY2() - y;
+	b0 = getX1() - x;
+	b1 = getCtrlX1() - x;
+	b2 = getCtrlX2() - x;
+	b3 = getX2() - x;
+      }
+    else
+      {
+	a0 = getX1() - x;
+	a1 = getCtrlX1() - x;
+	a2 = getCtrlX2() - x;
+	a3 = getX2() - x;
+	b0 = getY1() - y;
+	b1 = getCtrlY1() - y;
+	b2 = getCtrlY2() - y;
+	b3 = getY2() - y;
+      }
+
+    /* If the axis intersects a start/endpoint, shift it up by some small 
+       amount to guarantee the line is 'inside'
+       If this is not done, bad behaviour may result for points on that axis.*/
+    if (a0 == 0.0 || a3 == 0.0)
+      {
+	double small = getFlatness() * (1E-10);
+	if (a0 == 0.0)
+	  a0 += small;
+	if (a3 == 0.0)
+	  a3 += small;
+      }
+
+    if (useYaxis)
+      {
+	if (Line2D.linesIntersect(b0, a0, b3, a3, 0.0, 0.0, distance, 0.0))
+	  nCrossings++;
+      }
+    else
+      {
+	if (Line2D.linesIntersect(a0, b0, a3, b3, 0.0, 0.0, 0.0, distance))
+	  nCrossings++;
+      }
+
+    r[0] = a0;
+    r[1] = 3 * (a1 - a0);
+    r[2] = 3 * (a2 + a0 - 2 * a1);
+    r[3] = a3 - 3 * a2 + 3 * a1 - a0;
+
+    if ((nRoots = solveCubic(r)) != 0)
+      for (int i = 0; i < nRoots; i++)
+        {
+	  double t = r[i];
+	  if (t >= 0.0 && t <= 1.0)
+	    {
+	      double crossing = -(t * t * t) * (b0 - 3 * b1 + 3 * b2 - b3)
+	                        + 3 * t * t * (b0 - 2 * b1 + b2)
+	                        + 3 * t * (b1 - b0) + b0;
+	      if (crossing > 0.0 && crossing <= distance)
+		nCrossings++;
+	    }
+        }
+
+    return (nCrossings);
+  }
 
   /**
    * A two-dimensional curve that is parameterized with a cubic
@@ -996,57 +1139,48 @@
    * @author Eric Blake (ebb9@email.byu.edu)
    * @author Sascha Brawer (brawer@dandelis.ch)
    */
-  public static class Double
-    extends CubicCurve2D
+  public static class Double extends CubicCurve2D
   {
     /**
      * The <i>x</i> coordinate of the curve&#x2019;s start point.
      */
     public double x1;
 
-
     /**
      * The <i>y</i> coordinate of the curve&#x2019;s start point.
      */
     public double y1;
 
-
     /**
      * The <i>x</i> coordinate of the curve&#x2019;s first control point.
      */
     public double ctrlx1;
 
-
     /**
      * The <i>y</i> coordinate of the curve&#x2019;s first control point.
      */
     public double ctrly1;
 
-
     /**
      * The <i>x</i> coordinate of the curve&#x2019;s second control point.
      */
     public double ctrlx2;
 
-
     /**
      * The <i>y</i> coordinate of the curve&#x2019;s second control point.
      */
     public double ctrly2;
 
-
     /**
      * The <i>x</i> coordinate of the curve&#x2019;s end point.
      */
     public double x2;
 
-
     /**
      * The <i>y</i> coordinate of the curve&#x2019;s end point.
      */
     public double y2;
 
-
     /**
      * Constructs a new CubicCurve2D that stores its coordinate values
      * in double-precision floating-point format. All points are
@@ -1056,7 +1190,6 @@
     {
     }
 
-
     /**
      * Constructs a new CubicCurve2D that stores its coordinate values
      * in double-precision floating-point format, specifying the
@@ -1089,8 +1222,8 @@
      * @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
      * point.
      */
-    public Double(double x1, double y1, double cx1, double cy1,
-                  double cx2, double cy2, double x2, double y2)
+    public Double(double x1, double y1, double cx1, double cy1, double cx2,
+                  double cy2, double x2, double y2)
     {
       this.x1 = x1;
       this.y1 = y1;
@@ -1102,7 +1235,6 @@
       this.y2 = y2;
     }
 
-
     /**
      * Returns the <i>x</i> coordinate of the curve&#x2019;s start
      * point.
@@ -1112,7 +1244,6 @@
       return x1;
     }
 
-
     /**
      * Returns the <i>y</i> coordinate of the curve&#x2019;s start
      * point.
@@ -1122,7 +1253,6 @@
       return y1;
     }
 
-
     /**
      * Returns the curve&#x2019;s start point.
      */
@@ -1131,7 +1261,6 @@
       return new Point2D.Double(x1, y1);
     }
 
-
     /**
      * Returns the <i>x</i> coordinate of the curve&#x2019;s first
      * control point.
@@ -1141,7 +1270,6 @@
       return ctrlx1;
     }
 
-
     /**
      * Returns the <i>y</i> coordinate of the curve&#x2019;s first
      * control point.
@@ -1151,7 +1279,6 @@
       return ctrly1;
     }
 
-
     /**
      * Returns the curve&#x2019;s first control point.
      */
@@ -1160,7 +1287,6 @@
       return new Point2D.Double(ctrlx1, ctrly1);
     }
 
-
     /**
      * Returns the <i>x</i> coordinate of the curve&#x2019;s second
      * control point.
@@ -1170,7 +1296,6 @@
       return ctrlx2;
     }
 
-
     /**
      * Returns the <i>y</i> coordinate of the curve&#x2019;s second
      * control point.
@@ -1180,7 +1305,6 @@
       return ctrly2;
     }
 
-
     /**
      * Returns the curve&#x2019;s second control point.
      */
@@ -1189,7 +1313,6 @@
       return new Point2D.Double(ctrlx2, ctrly2);
     }
 
-
     /**
      * Returns the <i>x</i> coordinate of the curve&#x2019;s end
      * point.
@@ -1199,7 +1322,6 @@
       return x2;
     }
 
-
     /**
      * Returns the <i>y</i> coordinate of the curve&#x2019;s end
      * point.
@@ -1209,7 +1331,6 @@
       return y2;
     }
 
-
     /**
      * Returns the curve&#x2019;s end point.
      */
@@ -1218,7 +1339,6 @@
       return new Point2D.Double(x2, y2);
     }
 
-
     /**
      * Changes the curve geometry, separately specifying each coordinate
      * value.
@@ -1263,7 +1383,6 @@
       this.y2 = y2;
     }
 
-
     /**
      * Determines the smallest rectangle that encloses the
      * curve&#x2019;s start, end and control points. As the
@@ -1284,7 +1403,6 @@
     }
   }
 
-
   /**
    * A two-dimensional curve that is parameterized with a cubic
    * function and stores coordinate values in single-precision
@@ -1295,57 +1413,48 @@
    * @author Eric Blake (ebb9@email.byu.edu)
    * @author Sascha Brawer (brawer@dandelis.ch)
    */
-  public static class Float
-    extends CubicCurve2D
+  public static class Float extends CubicCurve2D
   {
     /**
      * The <i>x</i> coordinate of the curve&#x2019;s start point.
      */
     public float x1;
 
-
     /**
      * The <i>y</i> coordinate of the curve&#x2019;s start point.
      */
     public float y1;
 
-
     /**
      * The <i>x</i> coordinate of the curve&#x2019;s first control point.
      */
     public float ctrlx1;
 
-
     /**
      * The <i>y</i> coordinate of the curve&#x2019;s first control point.
      */
     public float ctrly1;
 
-
     /**
      * The <i>x</i> coordinate of the curve&#x2019;s second control point.
      */
     public float ctrlx2;
 
-
     /**
      * The <i>y</i> coordinate of the curve&#x2019;s second control point.
      */
     public float ctrly2;
 
-
     /**
      * The <i>x</i> coordinate of the curve&#x2019;s end point.
      */
     public float x2;
 
-
     /**
      * The <i>y</i> coordinate of the curve&#x2019;s end point.
      */
     public float y2;
 
-
     /**
      * Constructs a new CubicCurve2D that stores its coordinate values
      * in single-precision floating-point format. All points are
@@ -1355,7 +1464,6 @@
     {
     }
 
-
     /**
      * Constructs a new CubicCurve2D that stores its coordinate values
      * in single-precision floating-point format, specifying the
@@ -1388,8 +1496,8 @@
      * @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
      * point.
      */
-    public Float(float x1, float y1, float cx1, float cy1,
-                 float cx2, float cy2, float x2, float y2)
+    public Float(float x1, float y1, float cx1, float cy1, float cx2,
+                 float cy2, float x2, float y2)
     {
       this.x1 = x1;
       this.y1 = y1;
@@ -1401,7 +1509,6 @@
       this.y2 = y2;
     }
 
-
     /**
      * Returns the <i>x</i> coordinate of the curve&#x2019;s start
      * point.
@@ -1411,7 +1518,6 @@
       return x1;
     }
 
-
     /**
      * Returns the <i>y</i> coordinate of the curve&#x2019;s start
      * point.
@@ -1421,7 +1527,6 @@
       return y1;
     }
 
-
     /**
      * Returns the curve&#x2019;s start point.
      */
@@ -1430,7 +1535,6 @@
       return new Point2D.Float(x1, y1);
     }
 
-
     /**
      * Returns the <i>x</i> coordinate of the curve&#x2019;s first
      * control point.
@@ -1440,7 +1544,6 @@
       return ctrlx1;
     }
 
-
     /**
      * Returns the <i>y</i> coordinate of the curve&#x2019;s first
      * control point.
@@ -1450,7 +1553,6 @@
       return ctrly1;
     }
 
-
     /**
      * Returns the curve&#x2019;s first control point.
      */
@@ -1459,7 +1561,6 @@
       return new Point2D.Float(ctrlx1, ctrly1);
     }
 
-
     /**
      * Returns the <i>s</i> coordinate of the curve&#x2019;s second
      * control point.
@@ -1469,7 +1570,6 @@
       return ctrlx2;
     }
 
-
     /**
      * Returns the <i>y</i> coordinate of the curve&#x2019;s second
      * control point.
@@ -1479,7 +1579,6 @@
       return ctrly2;
     }
 
-
     /**
      * Returns the curve&#x2019;s second control point.
      */
@@ -1488,7 +1587,6 @@
       return new Point2D.Float(ctrlx2, ctrly2);
     }
 
-
     /**
      * Returns the <i>x</i> coordinate of the curve&#x2019;s end
      * point.
@@ -1498,7 +1596,6 @@
       return x2;
     }
 
-
     /**
      * Returns the <i>y</i> coordinate of the curve&#x2019;s end
      * point.
@@ -1508,7 +1605,6 @@
       return y2;
     }
 
-
     /**
      * Returns the curve&#x2019;s end point.
      */
@@ -1517,7 +1613,6 @@
       return new Point2D.Float(x2, y2);
     }
 
-
     /**
      * Changes the curve geometry, separately specifying each coordinate
      * value as a double-precision floating-point number.
@@ -1562,7 +1657,6 @@
       this.y2 = (float) y2;
     }
 
-
     /**
      * Changes the curve geometry, separately specifying each coordinate
      * value as a single-precision floating-point number.
@@ -1594,8 +1688,8 @@
      * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new end
      * point.
      */
-    public void setCurve(float x1, float y1, float cx1, float cy1,
-                         float cx2, float cy2, float x2, float y2)
+    public void setCurve(float x1, float y1, float cx1, float cy1, float cx2,
+                         float cy2, float x2, float y2)
     {
       this.x1 = x1;
       this.y1 = y1;
@@ -1607,7 +1701,6 @@
       this.y2 = y2;
     }
 
-
     /**
      * Determines the smallest rectangle that encloses the
      * curve&#x2019;s start, end and control points. As the
Index: java/awt/geom/GeneralPath.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/geom/GeneralPath.java,v
retrieving revision 1.3
diff -u -r1.3 GeneralPath.java
--- java/awt/geom/GeneralPath.java	21 Oct 2003 13:18:22 -0000	1.3
+++ java/awt/geom/GeneralPath.java	8 Aug 2004 19:38:26 -0000
@@ -1,50 +1,80 @@
 /* GeneralPath.java -- represents a shape built from subpaths
-   Copyright (C) 2002, 2003 Free Software Foundation
+   Copyright (C) 2002, 2003, 2004 Free Software Foundation
 
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING.  If not, write to the
-Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-02111-1307 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library.  Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module.  An independent module is a module which is not derived from
-or based on this library.  If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so.  If you do not wish to do so, delete this
-exception statement from your version. */
+   This file is part of GNU Classpath.
 
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version. */
 
 package java.awt.geom;
 
 import java.awt.Rectangle;
 import java.awt.Shape;
 
+
 /**
- * STUBS ONLY
- * XXX Implement and document. Note that Sun's implementation only expects
- * float precision, not double.
+ * A general geometric path, consisting of any number of subpaths
+ * constructed out of straight lines and cubic or quadratic Bezier
+ * curves.
+ *
+ * <p>The inside of the curve is defined for drawing purposes by a winding
+ * rule. Either the WIND_EVEN_ODD or WIND_NON_ZERO winding rule can be chosen.
+ *
+ * <p><img src="doc-files/GeneralPath-1.png" width="300" height="210"
+ * alt="A drawing of a GeneralPath" />
+ * <p>The EVEN_ODD winding rule defines a point as inside a path if:
+ * A ray from the point towards infinity in an arbitrary direction
+ * intersects the path an odd number of times. Points <b>A</b> and
+ * <b>C</b> in the image are considered to be outside the path.
+ * (both intersect twice)
+ * Point <b>B</b> intersects once, and is inside.
+ *
+ * <p>The NON_ZERO winding rule defines a point as inside a path if:
+ * The path intersects the ray in an equal number of opposite directions.
+ * Point <b>A</b> in the image is outside (one intersection in the 
+ * &#x2019;up&#x2019;
+ * direction, one in the &#x2019;down&#x2019; direction) Point <b>B</b> in 
+ * the image is inside (one intersection &#x2019;down&#x2019;)
+ * Point <b>C</b> in the image is outside (two intersections 
+ * &#x2019;down&#x2019;)
+ *
+ * @see Line2D
+ * @see CubicCurve2D
+ * @see QuadCurve2D
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * @author Sven de Marothy (sven@physto.se)
+ *
+ * @since 1.2
  */
 public final class GeneralPath implements Shape, Cloneable
 {
@@ -52,35 +82,63 @@
   public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO;
 
   /** Initial size if not specified. */
-  private static final int INIT_SIZE = 20;
+  private static final int INIT_SIZE = 10;
+
+  /** A big number, but not so big it can't survive a few float operations */
+  private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0;
 
   /** The winding rule. */
   private int rule;
+
   /**
-   * The path type in points. Note that points[index] maps to
-   * types[index >> 1]; the control points of quad and cubic paths map as
+   * The path type in points. Note that xpoints[index] and ypoints[index] maps
+   * to types[index]; the control points of quad and cubic paths map as
    * well but are ignored.
    */
   private byte[] types;
+
   /**
    * The list of all points seen. Since you can only append floats, it makes
-   * sense for this to be a float[]. I have no idea why Sun didn't choose to
+   * sense for these to be float[]. I have no idea why Sun didn't choose to
    * allow a general path of double precision points.
+   * Note: Storing x and y coords seperately makes for a slower transforms,
+   * But it speeds up and simplifies box-intersection checking a lot.
    */
-  private float[] points;
+  private float[] xpoints;
+  private float[] ypoints;
+
   /** The index of the most recent moveto point, or null. */
   private int subpath = -1;
+
   /** The next available index into points. */
   private int index;
 
+  /**
+   * Constructs a GeneralPath with the default (NON_ZERO)
+   * winding rule and initial capacity (20).
+   */
   public GeneralPath()
   {
     this(WIND_NON_ZERO, INIT_SIZE);
   }
+
+  /**
+   * Constructs a GeneralPath with a specific winding rule
+   * and the default initial capacity (20).
+   * @param rule the winding rule (WIND_NON_ZERO or WIND_EVEN_ODD)
+   */
   public GeneralPath(int rule)
   {
     this(rule, INIT_SIZE);
   }
+
+  /**
+   * Constructs a GeneralPath with a specific winding rule
+   * and the initial capacity. The initial capacity should be
+   * the approximate number of path segments to be used.
+   * @param rule the winding rule (WIND_NON_ZERO or WIND_EVEN_ODD)
+   * @param capacity the inital capacity, in path segments
+   */
   public GeneralPath(int rule, int capacity)
   {
     if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO)
@@ -88,68 +146,112 @@
     this.rule = rule;
     if (capacity < INIT_SIZE)
       capacity = INIT_SIZE;
-    types = new byte[capacity >> 1];
-    points = new float[capacity];
+    types = new byte[capacity];
+    xpoints = new float[capacity];
+    ypoints = new float[capacity];
   }
+
+  /**
+   * Constructs a GeneralPath from an arbitrary shape object.
+   * The Shapes PathIterator path and winding rule will be used.
+   * @param s the shape
+   */
   public GeneralPath(Shape s)
   {
-    types = new byte[INIT_SIZE >> 1];
-    points = new float[INIT_SIZE];
+    types = new byte[INIT_SIZE];
+    xpoints = new float[INIT_SIZE];
+    ypoints = new float[INIT_SIZE];
     PathIterator pi = s.getPathIterator(null);
     setWindingRule(pi.getWindingRule());
     append(pi, false);
   }
 
+  /**
+   * Adds a new point to a path.
+   */
   public void moveTo(float x, float y)
   {
     subpath = index;
-    ensureSize(index + 2);
-    types[index >> 1] = PathIterator.SEG_MOVETO;
-    points[index++] = x;
-    points[index++] = y;
+    ensureSize(index + 1);
+    types[index] = PathIterator.SEG_MOVETO;
+    xpoints[index] = x;
+    ypoints[index++] = y;
   }
+
+  /**
+   * Appends a straight line to the current path.
+   * @param x x coordinate of the line endpoint.
+   * @param y y coordinate of the line endpoint.
+   */
   public void lineTo(float x, float y)
   {
-    ensureSize(index + 2);
-    types[index >> 1] = PathIterator.SEG_LINETO;
-    points[index++] = x;
-    points[index++] = y;
+    ensureSize(index + 1);
+    types[index] = PathIterator.SEG_LINETO;
+    xpoints[index] = x;
+    ypoints[index++] = y;
   }
+
+  /**
+   * Appends a quadratic Bezier curve to the current path.
+   * @param x1 x coordinate of the control point
+   * @param y1 y coordinate of the control point
+   * @param x2 x coordinate of the curve endpoint.
+   * @param y2 y coordinate of the curve endpoint.
+   */
   public void quadTo(float x1, float y1, float x2, float y2)
   {
-    ensureSize(index + 4);
-    types[index >> 1] = PathIterator.SEG_QUADTO;
-    points[index++] = x1;
-    points[index++] = y1;
-    points[index++] = x2;
-    points[index++] = y2;
-  }
-  public void curveTo(float x1, float y1, float x2, float y2,
-                      float x3, float y3)
-  {
-    ensureSize(index + 6);
-    types[index >> 1] = PathIterator.SEG_CUBICTO;
-    points[index++] = x1;
-    points[index++] = y1;
-    points[index++] = x2;
-    points[index++] = y2;
-    points[index++] = x3;
-    points[index++] = y3;
+    ensureSize(index + 2);
+    types[index] = PathIterator.SEG_QUADTO;
+    xpoints[index] = x1;
+    ypoints[index++] = y1;
+    xpoints[index] = x2;
+    ypoints[index++] = y2;
   }
+
+  /**
+   * Appends a cubic Bezier curve to the current path.
+   * @param x1 x coordinate of the first control point
+   * @param y1 y coordinate of the first control point
+   * @param x2 x coordinate of the second control point
+   * @param y2 y coordinate of the second control point
+   * @param x3 x coordinate of the curve endpoint.
+   * @param y3 y coordinate of the curve endpoint.
+   */
+  public void curveTo(float x1, float y1, float x2, float y2, float x3,
+                      float y3)
+  {
+    ensureSize(index + 3);
+    types[index] = PathIterator.SEG_CUBICTO;
+    xpoints[index] = x1;
+    ypoints[index++] = y1;
+    xpoints[index] = x2;
+    ypoints[index++] = y2;
+    xpoints[index] = x3;
+    ypoints[index++] = y3;
+  }
+
+  /**
+   * Closes the current subpath by drawing a line
+   * back to the point of the last moveTo.
+   */
   public void closePath()
   {
-    ensureSize(index + 2);
-    types[index >> 1] = PathIterator.SEG_CLOSE;
-    points[index++] = points[subpath];
-    points[index++] = points[subpath + 1];
+    ensureSize(index + 1);
+    types[index] = PathIterator.SEG_CLOSE;
+    xpoints[index] = xpoints[subpath];
+    ypoints[index++] = ypoints[subpath];
   }
 
+  /**
+   * Appends the segments of a Shape to the path. If <code>connect</code> is 
+   * true, the new path segments are connected to the existing one with a line.
+   * The winding rule of the Shape is ignored.
+   */
   public void append(Shape s, boolean connect)
   {
     append(s.getPathIterator(null), connect);
   }
 
-
   /**
    * Appends the segments of a PathIterator to this GeneralPath.
    * Optionally, the initial {@link PathIterator#SEG_MOVETO} segment
@@ -158,7 +260,7 @@
    *
    * @param iter the PathIterator specifying which segments shall be
    * appended.
-   * 
+   *
    * @param connect <code>true</code> for substituting the initial
    * {@link PathIterator#SEG_MOVETO} segment by a {@link
    * PathIterator#SEG_LINETO}, or <code>false</code> for not
@@ -171,50 +273,55 @@
   {
     // A bad implementation of this method had caused Classpath bug #6076.
     float[] f = new float[6];
-    while (!iter.isDone())
-    {
-      switch (iter.currentSegment(f))
+    while (! iter.isDone())
       {
-      case PathIterator.SEG_MOVETO:
-        if (!connect || (index == 0))
-        {
-          moveTo(f[0], f[1]);
-          break;
-        }
+	switch (iter.currentSegment(f))
+	  {
+	  case PathIterator.SEG_MOVETO:
+	    if (! connect || (index == 0))
+	      {
+		moveTo(f[0], f[1]);
+		break;
+	      }
+	    if ((index >= 1) && (types[index - 1] == PathIterator.SEG_CLOSE)
+	        && (f[0] == xpoints[index - 1])
+	        && (f[1] == ypoints[index - 1]))
+	      break;
+
+	  // Fall through.
+	  case PathIterator.SEG_LINETO:
+	    lineTo(f[0], f[1]);
+	    break;
+	  case PathIterator.SEG_QUADTO:
+	    quadTo(f[0], f[1], f[2], f[3]);
+	    break;
+	  case PathIterator.SEG_CUBICTO:
+	    curveTo(f[0], f[1], f[2], f[3], f[4], f[5]);
+	    break;
+	  case PathIterator.SEG_CLOSE:
+	    closePath();
+	    break;
+	  }
 
-        if ((index >= 2) && (types[(index - 2) >> 2] == PathIterator.SEG_CLOSE)
-            && (f[0] == points[index - 2]) && (f[1] == points[index - 1]))
-          break;
-        
-        // Fall through.
-
-      case PathIterator.SEG_LINETO:
-        lineTo(f[0], f[1]);
-        break;
-
-      case PathIterator.SEG_QUADTO:
-        quadTo(f[0], f[1], f[2], f[3]);
-        break;
-
-      case PathIterator.SEG_CUBICTO:
-        curveTo(f[0], f[1], f[2], f[3], f[4], f[5]);
-        break;
-
-      case PathIterator.SEG_CLOSE:
-        closePath();
-        break;
+	connect = false;
+	iter.next();
       }
-
-      connect = false;
-      iter.next();
-    }
   }
 
-
+  /**
+   * Returns the path&#x2019;s current winding rule.
+   */
   public int getWindingRule()
   {
     return rule;
   }
+
+  /**
+   * Sets the path&#x2019;s winding rule, which controls which areas are 
+   * considered &#x2019;inside&#x2019; or &#x2019;outside&#x2019; the path 
+   * on drawing. Valid rules are WIND_EVEN_ODD for an even-odd winding rule, 
+   * or WIND_NON_ZERO for a non-zero winding rule.
+   */
   public void setWindingRule(int rule)
   {
     if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO)
@@ -222,22 +329,48 @@
     this.rule = rule;
   }
 
+  /**
+   * Returns the current appending point of the path.
+   */
   public Point2D getCurrentPoint()
   {
     if (subpath < 0)
       return null;
-    return new Point2D.Float(points[index - 2], points[index - 1]);
+    return new Point2D.Float(xpoints[index - 1], ypoints[index - 1]);
   }
+
+  /**
+   * Resets the path. All points and segments are destroyed.
+   */
   public void reset()
   {
     subpath = -1;
     index = 0;
   }
 
+  /**
+   * Applies a transform to the path.
+   */
   public void transform(AffineTransform xform)
   {
-    xform.transform(points, 0, points, 0, index >> 1);
+    double nx;
+    double ny;
+    double[] m = new double[6];
+    xform.getMatrix(m);
+    for (int i = 0; i < index; i++)
+      {
+	nx = m[0] * xpoints[i] + m[2] * ypoints[i] + m[4];
+	ny = m[1] * xpoints[i] + m[3] * ypoints[i] + m[5];
+	xpoints[i] = (float) nx;
+	ypoints[i] = (float) ny;
+      }
   }
+
+  /**
+   * Creates a transformed version of the path.
+   * @param xform the transform to apply
+   * @return a new transformed GeneralPath
+   */
   public Shape createTransformedShape(AffineTransform xform)
   {
     GeneralPath p = new GeneralPath(this);
@@ -245,85 +378,174 @@
     return p;
   }
 
+  /**
+   * Returns the path&#x2019;s bounding box.
+   */
   public Rectangle getBounds()
   {
     return getBounds2D().getBounds();
   }
+
+  /**
+   * Returns the path&#x2019;s bounding box, in <code>float</code> precision
+   */
   public Rectangle2D getBounds2D()
   {
-    // XXX Implement.
-    throw new Error("not implemented");
+    float x1;
+    float y1;
+    float x2;
+    float y2;
+
+    if (index > 0)
+      {
+	x1 = x2 = xpoints[0];
+	y1 = y2 = ypoints[0];
+      }
+    else
+      x1 = x2 = y1 = y2 = 0.0f;
+
+    for (int i = 0; i < index; i++)
+      {
+	x1 = Math.min(xpoints[i], x1);
+	y1 = Math.min(ypoints[i], y1);
+	x2 = Math.max(xpoints[i], x2);
+	y2 = Math.max(ypoints[i], y2);
+      }
+    return (new Rectangle2D.Float(x1, y1, x2 - x1, y2 - y1));
   }
 
+  /**
+   * Evaluates if a point is within the GeneralPath,
+   * The NON_ZERO winding rule is used, regardless of the
+   * set winding rule.
+   * @param x x coordinate of the point to evaluate
+   * @param y y coordinate of the point to evaluate
+   * @return true if the point is within the path, false otherwise
+   */
   public boolean contains(double x, double y)
   {
-    // XXX Implement.
-    throw new Error("not implemented");
+    return (getWindingNumber(x, y) != 0);
   }
+
+  /**
+   * Evaluates if a Point2D is within the GeneralPath,
+   * The NON_ZERO winding rule is used, regardless of the
+   * set winding rule.
+   * @param p The Point2D to evaluate
+   * @return true if the point is within the path, false otherwise
+   */
   public boolean contains(Point2D p)
   {
     return contains(p.getX(), p.getY());
   }
+
+  /**
+   * Evaluates if a rectangle is completely contained within the path.
+   * This method will return false in the cases when the box
+   * intersects an inner segment of the path.
+   * (i.e.: The method is accurate for the EVEN_ODD winding rule)
+   */
   public boolean contains(double x, double y, double w, double h)
   {
-    // XXX Implement.
-    throw new Error("not implemented");
+    if (! getBounds2D().intersects(x, y, w, h))
+      return false;
+
+    /* Does any edge intersect? */
+    if (getAxisIntersections(x, y, false, w) != 0 /* top */
+        || getAxisIntersections(x, y + h, false, w) != 0 /* bottom */
+        || getAxisIntersections(x + w, y, true, h) != 0 /* right */
+        || getAxisIntersections(x, y, true, h) != 0) /* left */
+      return false;
+
+    /* No intersections, is any point inside? */
+    if (getWindingNumber(x, y) != 0)
+      return true;
+
+    return false;
   }
+
+  /**
+   * Evaluates if a rectangle is completely contained within the path.
+   * This method will return false in the cases when the box
+   * intersects an inner segment of the path.
+   * (i.e.: The method is accurate for the EVEN_ODD winding rule)
+   * @param r the rectangle
+   * @return <code>true</code> if the rectangle is completely contained
+   * within the path, <code>false</code> otherwise
+   */
   public boolean contains(Rectangle2D r)
   {
     return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
   }
 
+  /**
+   * Evaluates if a rectangle intersects the path.
+   * @param x x coordinate of the rectangle
+   * @param y y coordinate of the rectangle
+   * @param w width of the rectangle
+   * @param h height of the rectangle
+   * @return <code>true</code> if the rectangle intersects the path,
+   * <code>false</code> otherwise
+   */
   public boolean intersects(double x, double y, double w, double h)
   {
-    // XXX Implement.
-    throw new Error("not implemented");
+    /* Does any edge intersect? */
+    if (getAxisIntersections(x, y, false, w) != 0 /* top */
+        || getAxisIntersections(x, y + h, false, w) != 0 /* bottom */
+        || getAxisIntersections(x + w, y, true, h) != 0 /* right */
+        || getAxisIntersections(x, y, true, h) != 0) /* left */
+      return true;
+
+    /* No intersections, is any point inside? */
+    if (getWindingNumber(x, y) != 0)
+      return true;
+
+    return false;
   }
+
+  /**
+   * Evaluates if a Rectangle2D intersects the path.
+   * @param r The rectangle
+   * @return <code>true</code> if the rectangle intersects the path,
+   * <code>false</code> otherwise
+   */
   public boolean intersects(Rectangle2D r)
   {
     return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
   }
 
-
   /**
    * A PathIterator that iterates over the segments of a GeneralPath.
    *
    * @author Sascha Brawer (brawer@dandelis.ch)
    */
-  private static class GeneralPathIterator
-    implements PathIterator
+  private static class GeneralPathIterator implements PathIterator
   {
     /**
      * The number of coordinate values for each segment type.
      */
-    private static final int[] NUM_COORDS =
-    {
-      /* 0: SEG_MOVETO */ 2,
-      /* 1: SEG_LINETO */ 2,
-      /* 2: SEG_QUADTO */ 4,
-      /* 3: SEG_CUBICTO */ 6,
-      /* 4: SEG_CLOSE */ 0
-    };
-
+    private static final int[] NUM_COORDS = { 
+                                            /* 0: SEG_MOVETO */ 1, 
+                                            /* 1: SEG_LINETO */ 1, 
+                                            /* 2: SEG_QUADTO */ 2, 
+                                            /* 3: SEG_CUBICTO */ 3, 
+                                            /* 4: SEG_CLOSE */ 0};
 
     /**
      * The GeneralPath whose segments are being iterated.
      */
     private final GeneralPath path;
 
-
     /**
      * The affine transformation used to transform coordinates.
      */
     private final AffineTransform transform;
 
-
     /**
      * The current position of the iterator.
      */
     private int pos;
 
-
     /**
      * Constructs a new iterator for enumerating the segments of a
      * GeneralPath.
@@ -338,7 +560,6 @@
       this.transform = transform;
     }
 
-
     /**
      * Returns the current winding rule of the GeneralPath.
      */
@@ -347,7 +568,6 @@
       return path.rule;
     }
 
-
     /**
      * Determines whether the iterator has reached the last segment in
      * the path.
@@ -357,7 +577,6 @@
       return pos >= path.index;
     }
 
-
     /**
      * Advances the iterator position by one segment.
      */
@@ -365,70 +584,72 @@
     {
       int seg;
 
-      /* Increment pos by the number of coordinate values. Note that
-       * we store two values even for a SEG_CLOSE segment, which is
-       * why we increment pos at least by 2. 
+      /*
+       * Increment pos by the number of coordinate pairs.
        */
-      seg = path.types[pos >> 1];
+      seg = path.types[pos];
       if (seg == SEG_CLOSE)
-        pos += 2;
+	pos++;
       else
-        pos += NUM_COORDS[seg];
+	pos += NUM_COORDS[seg];
     }
 
-
     /**
      * Returns the current segment in float coordinates.
      */
     public int currentSegment(float[] coords)
     {
-      int seg, numCoords;
+      int seg;
+      int numCoords;
 
-      seg = path.types[pos >> 1];
+      seg = path.types[pos];
       numCoords = NUM_COORDS[seg];
       if (numCoords > 0)
-      {
-        if (transform == null)
-          System.arraycopy(path.points, pos, coords, 0, numCoords);
-        else
-          transform.transform(/* src */ path.points, /* srcOffset */ pos,
-                              /* dest */ coords, /* destOffset */ 0,
-                              /* numPoints */ numCoords >> 1);
-      }
+        {
+	  for (int i = 0; i < numCoords; i++)
+	    {
+	      coords[i << 1] = path.xpoints[pos + i];
+	      coords[(i << 1) + 1] = path.ypoints[pos + i];
+	    }
+
+	  if (transform != null)
+	    transform.transform( /* src */
+	    coords, /* srcOffset */
+	    0, /* dest */ coords, /* destOffset */
+	    0, /* numPoints */ numCoords);
+        }
       return seg;
     }
 
-
     /**
      * Returns the current segment in double coordinates.
      */
     public int currentSegment(double[] coords)
     {
-      int seg, numCoords;
+      int seg;
+      int numCoords;
 
-      seg = path.types[pos >> 1];
+      seg = path.types[pos];
       numCoords = NUM_COORDS[seg];
       if (numCoords > 0)
-      {
-        if (transform == null)
         {
-          // System.arraycopy throws an exception if the source and destination
-          // array are not of the same primitive type.
-          for (int i = 0; i < numCoords; i++)
-            coords[i] = (double) path.points[pos + i];
+	  for (int i = 0; i < numCoords; i++)
+	    {
+	      coords[i << 1] = (double) path.xpoints[pos + i];
+	      coords[(i << 1) + 1] = (double) path.ypoints[pos + i];
+	    }
+	  if (transform != null)
+	    transform.transform( /* src */
+	    coords, /* srcOffset */
+	    pos, /* dest */ coords, /* destOffset */
+	    0, /* numPoints */ numCoords);
         }
-        else
-          transform.transform(/* src */ path.points, /* srcOffset */ pos,
-                              /* dest */ coords, /* destOffset */ 0,
-                              /* numPoints */ numCoords >> 1);
-      }
       return seg;
     }
   }
 
-
   /**
-   * Creates a PathIterator for iterating along the segments of this path.
+   * Creates a PathIterator for iterating along the segments of the path.
    *
    * @param at an affine transformation for projecting the returned
    * points, or <code>null</code> to let the created iterator return
@@ -439,15 +660,17 @@
     return new GeneralPathIterator(this, at);
   }
 
-
+  /**
+   * Creates a new FlatteningPathIterator for the path
+   */
   public PathIterator getPathIterator(AffineTransform at, double flatness)
   {
     return new FlatteningPathIterator(getPathIterator(at), flatness);
   }
 
   /**
-   * Create a new shape of the same run-time type with the same contents as
-   * this one.
+   * Creates a new shape of the same run-time type with the same contents 
+   * as this one.
    *
    * @return the clone
    *
@@ -461,17 +684,261 @@
     return new GeneralPath(this);
   }
 
+  /**
+   * Helper method - ensure the size of the data arrays,
+   * otherwise, reallocate new ones twice the size
+   */
   private void ensureSize(int size)
   {
     if (subpath < 0)
       throw new IllegalPathStateException("need initial moveto");
-    if (size <= points.length)
+    if (size <= xpoints.length)
       return;
-    byte[] b = new byte[points.length];
-    System.arraycopy(types, 0, b, 0, index >> 1);
+    byte[] b = new byte[types.length << 1];
+    System.arraycopy(types, 0, b, 0, index);
     types = b;
-    float[] f = new float[points.length << 1];
-    System.arraycopy(points, 0, f, 0, index);
-    points = f;
+    float[] f = new float[xpoints.length << 1];
+    System.arraycopy(xpoints, 0, f, 0, index);
+    xpoints = f;
+    f = new float[ypoints.length << 1];
+    System.arraycopy(ypoints, 0, f, 0, index);
+    ypoints = f;
+  }
+
+  /**
+   * Helper method - Get the total number of intersections from (x,y) along 
+   * a given axis, within a given distance.
+   */
+  private int getAxisIntersections(double x, double y, boolean useYaxis,
+                                   double distance)
+  {
+    return (evaluateCrossings(x, y, false, useYaxis, distance));
+  }
+
+  /**
+   * Helper method - returns the winding number of a point.
+   */
+  private int getWindingNumber(double x, double y)
+  {
+    /* Evaluate the crossings from x,y to infinity on the y axis (arbitrary 
+       choice). Note that we don't actually use Double.INFINITY, since that's 
+       slower, and may cause problems. */
+    return (evaluateCrossings(x, y, true, true, BIG_VALUE));
+  }
+
+  /**
+   * Helper method - evaluates the number of intersections on an axis from 
+   * the point (x,y) to the point (x,y+distance) or (x+distance,y).
+   * @param x x coordinate.
+   * @param y y coordinate.
+   * @param neg True if opposite-directed intersections should cancel, 
+   * false to sum all intersections.
+   * @param useYaxis Use the Y axis, false uses the X axis.
+   * @param distance Interval from (x,y) on the selected axis to find 
+   * intersections.
+   */
+  private int evaluateCrossings(double x, double y, boolean neg,
+                                boolean useYaxis, double distance)
+  {
+    float cx = 0.0f;
+    float cy = 0.0f;
+    float firstx = 0.0f;
+    float firsty = 0.0f;
+
+    int negative = (neg) ? -1 : 1;
+    double x0;
+    double x1;
+    double x2;
+    double x3;
+    double y0;
+    double y1;
+    double y2;
+    double y3;
+    double[] r = new double[4];
+    int nRoots;
+    double epsilon = 0.0;
+    int pos = 0;
+    int windingNumber = 0;
+    boolean pathStarted = false;
+
+    if (index == 0)
+      return (0);
+    if (useYaxis)
+      {
+	float[] swap1;
+	swap1 = ypoints;
+	ypoints = xpoints;
+	xpoints = swap1;
+	double swap2;
+	swap2 = y;
+	y = x;
+	x = swap2;
+      }
+
+    /* Get a value which is hopefully small but not insignificant relative
+     the path. */
+    epsilon = ypoints[0] * 1E-9;
+
+    pos = 0;
+    while (pos < index)
+      {
+	switch (types[pos])
+	  {
+	  case PathIterator.SEG_MOVETO:
+	    if (pathStarted) // close old path
+	      {
+		x0 = cx;
+		y0 = cy;
+		x1 = firstx;
+		y1 = firsty;
+
+		if (y0 == 0.0)
+		  y0 += epsilon;
+		if (y1 == 0.0)
+		  y1 += epsilon;
+		if (Line2D.linesIntersect(x0, y0, x1, y1, 0.0, 0.0, distance,
+		                          0.0))
+		  windingNumber += (y1 < y0) ? 1 : negative;
+
+		cx = firstx;
+		cy = firsty;
+	      }
+	    cx = firstx = xpoints[pos] - (float) x;
+	    cy = firsty = ypoints[pos++] - (float) y;
+	    pathStarted = true;
+	    break;
+	  case PathIterator.SEG_CLOSE:
+	    x0 = cx;
+	    y0 = cy;
+	    x1 = firstx;
+	    y1 = firsty;
+
+	    if (y0 == 0.0)
+	      y0 += epsilon;
+	    if (y1 == 0.0)
+	      y1 += epsilon;
+	    if (Line2D.linesIntersect(x0, y0, x1, y1, 0.0, 0.0, distance, 0.0))
+	      windingNumber += (y1 < y0) ? 1 : negative;
+
+	    cx = firstx;
+	    cy = firsty;
+	    pos++;
+	    pathStarted = false;
+	    break;
+	  case PathIterator.SEG_LINETO:
+	    x0 = cx;
+	    y0 = cy;
+	    x1 = xpoints[pos] - (float) x;
+	    y1 = ypoints[pos++] - (float) y;
+
+	    if (y0 == 0.0)
+	      y0 += epsilon;
+	    if (y1 == 0.0)
+	      y1 += epsilon;
+	    if (Line2D.linesIntersect(x0, y0, x1, y1, 0.0, 0.0, distance, 0.0))
+	      windingNumber += (y1 < y0) ? 1 : negative;
+
+	    cx = xpoints[pos - 1] - (float) x;
+	    cy = ypoints[pos - 1] - (float) y;
+	    break;
+	  case PathIterator.SEG_QUADTO:
+	    x0 = cx;
+	    y0 = cy;
+	    x1 = xpoints[pos] - x;
+	    y1 = ypoints[pos++] - y;
+	    x2 = xpoints[pos] - x;
+	    y2 = ypoints[pos++] - y;
+
+	    /* check if curve may intersect X+ axis. */
+	    if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0)
+	        && (y0 * y1 <= 0 || y1 * y2 <= 0))
+	      {
+		if (y0 == 0.0)
+		  y0 += epsilon;
+		if (y2 == 0.0)
+		  y2 += epsilon;
+
+		r[0] = y0;
+		r[1] = 2 * (y1 - y0);
+		r[2] = (y2 - 2 * y1 + y0);
+
+		/* degenerate roots (=tangent points) do not
+		   contribute to the winding number. */
+		if ((nRoots = QuadCurve2D.solveQuadratic(r)) == 2)
+		  for (int i = 0; i < nRoots; i++)
+		    {
+		      float t = (float) r[i];
+		      if (t > 0.0f && t < 1.0f)
+		        {
+			  double crossing = t * t * (x2 - 2 * x1 + x0)
+			                    + 2 * t * (x1 - x0) + x0;
+			  if (crossing >= 0.0 && crossing <= distance)
+			    windingNumber += (2 * t * (y2 - 2 * y1 + y0)
+			                   + 2 * (y1 - y0) < 0) ? 1 : negative;
+		        }
+		    }
+	      }
+
+	    cx = xpoints[pos - 1] - (float) x;
+	    cy = ypoints[pos - 1] - (float) y;
+	    break;
+	  case PathIterator.SEG_CUBICTO:
+	    x0 = cx;
+	    y0 = cy;
+	    x1 = xpoints[pos] - x;
+	    y1 = ypoints[pos++] - y;
+	    x2 = xpoints[pos] - x;
+	    y2 = ypoints[pos++] - y;
+	    x3 = xpoints[pos] - x;
+	    y3 = ypoints[pos++] - y;
+
+	    /* check if curve may intersect X+ axis. */
+	    if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0 || x3 > 0.0)
+	        && (y0 * y1 <= 0 || y1 * y2 <= 0 || y2 * y3 <= 0))
+	      {
+		if (y0 == 0.0)
+		  y0 += epsilon;
+		if (y3 == 0.0)
+		  y3 += epsilon;
+
+		r[0] = y0;
+		r[1] = 3 * (y1 - y0);
+		r[2] = 3 * (y2 + y0 - 2 * y1);
+		r[3] = y3 - 3 * y2 + 3 * y1 - y0;
+
+		if ((nRoots = CubicCurve2D.solveCubic(r)) != 0)
+		  for (int i = 0; i < nRoots; i++)
+		    {
+		      float t = (float) r[i];
+		      if (t > 0.0 && t < 1.0)
+		        {
+			  double crossing = -(t * t * t) * (x0 - 3 * x1
+			                    + 3 * x2 - x3)
+			                    + 3 * t * t * (x0 - 2 * x1 + x2)
+			                    + 3 * t * (x1 - x0) + x0;
+			  if (crossing >= 0 && crossing <= distance)
+			    windingNumber += (3 * t * t * (y3 + 3 * y1
+			                     - 3 * y2 - y0)
+			                     + 6 * t * (y0 - 2 * y1 + y2)
+			                   + 3 * (y1 - y0) < 0) ? 1 : negative;
+		        }
+		    }
+	      }
+
+	    cx = xpoints[pos - 1] - (float) x;
+	    cy = ypoints[pos - 1] - (float) y;
+	    break;
+	  }
+      }
+
+    // swap coordinates back
+    if (useYaxis)
+      {
+	float[] swap;
+	swap = ypoints;
+	ypoints = xpoints;
+	xpoints = swap;
+      }
+    return (windingNumber);
   }
 } // class GeneralPath
Index: java/awt/geom/QuadCurve2D.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/geom/QuadCurve2D.java,v
retrieving revision 1.6
diff -u -r1.6 QuadCurve2D.java
--- java/awt/geom/QuadCurve2D.java	5 Jan 2004 19:19:29 -0000	1.6
+++ java/awt/geom/QuadCurve2D.java	8 Aug 2004 19:38:26 -0000
@@ -1,5 +1,5 @@
 /* QuadCurve2D.java -- represents a parameterized quadratic curve in 2-D space
-   Copyright (C) 2002, 2003 Free Software Foundation
+   Copyright (C) 2002, 2003, 2004 Free Software Foundation
 
 This file is part of GNU Classpath.
 
@@ -35,7 +35,6 @@
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
-
 package java.awt.geom;
 
 import java.awt.Rectangle;
@@ -53,12 +52,14 @@
  * @author Eric Blake (ebb9@email.byu.edu)
  * @author Graydon Hoare (graydon@redhat.com)
  * @author Sascha Brawer (brawer@dandelis.ch)
+ * @author Sven de Marothy (sven@physto.se)
  *
  * @since 1.2
  */
-public abstract class QuadCurve2D
-  implements Shape, Cloneable
+public abstract class QuadCurve2D implements Shape, Cloneable
 {
+  private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0;
+
   /**
    * Constructs a new QuadCurve2D. Typical users will want to
    * construct instances of a subclass, such as {@link
@@ -68,67 +69,57 @@
   {
   }
 
-
   /**
    * Returns the <i>x</i> coordinate of the curve&#x2019;s start
    * point.
    */
   public abstract double getX1();
 
-
   /**
    * Returns the <i>y</i> coordinate of the curve&#x2019;s start
    * point.
    */
   public abstract double getY1();
 
-
   /**
    * Returns the curve&#x2019;s start point.
    */
   public abstract Point2D getP1();
 
-
   /**
    * Returns the <i>x</i> coordinate of the curve&#x2019;s control
    * point.
    */
   public abstract double getCtrlX();
 
-
   /**
    * Returns the <i>y</i> coordinate of the curve&#x2019;s control
    * point.
    */
   public abstract double getCtrlY();
 
-
   /**
    * Returns the curve&#x2019;s control point.
    */
   public abstract Point2D getCtrlPt();
 
-
   /**
    * Returns the <i>x</i> coordinate of the curve&#x2019;s end
    * point.
    */
   public abstract double getX2();
 
-
   /**
    * Returns the <i>y</i> coordinate of the curve&#x2019;s end
    * point.
    */
   public abstract double getY2();
 
-
   /**
    * Returns the curve&#x2019;s end point.
    */
   public abstract Point2D getP2();
 
-
   /**
    * Changes the curve geometry, separately specifying each coordinate
    * value.
@@ -154,7 +145,6 @@
   public abstract void setCurve(double x1, double y1, double cx, double cy,
                                 double x2, double y2);
 
-
   /**
    * Changes the curve geometry, passing coordinate values in an
    * array.
@@ -174,12 +164,10 @@
    */
   public void setCurve(double[] coords, int offset)
   {
-    setCurve(coords[offset++], coords[offset++],
-             coords[offset++], coords[offset++],
-             coords[offset++], coords[offset++]);
+    setCurve(coords[offset++], coords[offset++], coords[offset++],
+             coords[offset++], coords[offset++], coords[offset++]);
   }
 
-
   /**
    * Changes the curve geometry, specifying coordinate values in
    * separate Point objects.
@@ -198,11 +186,9 @@
    */
   public void setCurve(Point2D p1, Point2D c, Point2D p2)
   {
-    setCurve(p1.getX(), p1.getY(), c.getX(), c.getY(),
-             p2.getX(), p2.getY());
+    setCurve(p1.getX(), p1.getY(), c.getX(), c.getY(), p2.getX(), p2.getY());
   }
 
-
   /**
    * Changes the curve geometry, specifying coordinate values in an
    * array of Point objects.
@@ -223,12 +209,11 @@
    */
   public void setCurve(Point2D[] pts, int offset)
   {
-    setCurve(pts[offset].getX(), pts[offset].getY(),
-             pts[offset + 1].getX(), pts[offset + 1].getY(),
-             pts[offset + 2].getX(), pts[offset + 2].getY());
+    setCurve(pts[offset].getX(), pts[offset].getY(), pts[offset + 1].getX(),
+             pts[offset + 1].getY(), pts[offset + 2].getX(),
+             pts[offset + 2].getY());
   }
 
-
   /**
    * Changes the geometry of the curve to that of another curve.
    *
@@ -236,11 +221,10 @@
    */
   public void setCurve(QuadCurve2D c)
   {
-    setCurve(c.getX1(), c.getY1(), c.getCtrlX(), c.getCtrlY(),
-             c.getX2(), c.getY2());
+    setCurve(c.getX1(), c.getY1(), c.getCtrlX(), c.getCtrlY(), c.getX2(),
+             c.getY2());
   }
 
-
   /**
    * Calculates the squared flatness of a quadratic curve, directly
    * specifying each coordinate value. The flatness is the distance of
@@ -267,7 +251,6 @@
     return Line2D.ptSegDistSq(x1, y1, x2, y2, cx, cy);
   }
 
-
   /**
    * Calculates the flatness of a quadratic curve, directly specifying
    * each coordinate value. The flatness is the distance of the
@@ -294,7 +277,6 @@
     return Line2D.ptSegDist(x1, y1, x2, y2, cx, cy);
   }
 
-
   /**
    * Calculates the squared flatness of a quadratic curve, specifying
    * the coordinate values in an array. The flatness is the distance
@@ -328,7 +310,6 @@
                               coords[offset + 2], coords[offset + 3]);
   }
 
-
   /**
    * Calculates the flatness of a quadratic curve, specifying the
    * coordinate values in an array. The flatness is the distance of
@@ -362,7 +343,6 @@
                             coords[offset + 2], coords[offset + 3]);
   }
 
-
   /**
    * Calculates the squared flatness of this curve. The flatness is
    * the distance of the control point to the line between start and
@@ -378,12 +358,10 @@
    */
   public double getFlatnessSq()
   {
-    return Line2D.ptSegDistSq(getX1(), getY1(),
-                              getX2(), getY2(),
-                              getCtrlX(), getCtrlY());
+    return Line2D.ptSegDistSq(getX1(), getY1(), getX2(), getY2(), getCtrlX(),
+                              getCtrlY());
   }
 
-
   /**
    * Calculates the flatness of this curve. The flatness is the
    * distance of the control point to the line between start and end
@@ -399,12 +377,10 @@
    */
   public double getFlatness()
   {
-    return Line2D.ptSegDist(getX1(), getY1(),
-                            getX2(), getY2(),
-                            getCtrlX(), getCtrlY());
+    return Line2D.ptSegDist(getX1(), getY1(), getX2(), getY2(), getCtrlX(),
+                            getCtrlY());
   }
 
-
   /**
    * Subdivides this curve into two halves.
    *
@@ -423,8 +399,11 @@
   public void subdivide(QuadCurve2D left, QuadCurve2D right)
   {
     // Use empty slots at end to share single array.
-    double[] d = new double[] { getX1(), getY1(), getCtrlX(), getCtrlY(),
-                                getX2(), getY2(), 0, 0, 0, 0 };
+    double[] d = new double[]
+                 {
+                   getX1(), getY1(), getCtrlX(), getCtrlY(), getX2(), getY2(),
+                   0, 0, 0, 0
+                 };
     subdivide(d, 0, d, 0, d, 4);
     if (left != null)
       left.setCurve(d, 0);
@@ -432,7 +411,6 @@
       right.setCurve(d, 4);
   }
 
-
   /**
    * Subdivides a quadratic curve into two halves.
    *
@@ -456,7 +434,6 @@
     src.subdivide(left, right);
   }
 
-
   /**
    * Subdivides a quadratic curve into two halves, passing all
    * coordinates in an array.
@@ -500,11 +477,15 @@
    * index where the start point&#x2019;s <i>x</i> coordinate will be
    * stored.
    */
-  public static void subdivide(double[] src, int srcOff,
-                               double[] left, int leftOff,
-                               double[] right, int rightOff)
+  public static void subdivide(double[] src, int srcOff, double[] left,
+                               int leftOff, double[] right, int rightOff)
   {
-    double x1, y1, xc, yc, x2, y2;
+    double x1;
+    double y1;
+    double xc;
+    double yc;
+    double x2;
+    double y2;
 
     x1 = src[srcOff];
     y1 = src[srcOff + 1];
@@ -514,16 +495,16 @@
     y2 = src[srcOff + 5];
 
     if (left != null)
-    {
-      left[leftOff] = x1;
-      left[leftOff + 1] = y1;
-    }
+      {
+	left[leftOff] = x1;
+	left[leftOff + 1] = y1;
+      }
 
     if (right != null)
-    {
-      right[rightOff + 4] = x2;
-      right[rightOff + 5] = y2;
-    }
+      {
+	right[rightOff + 4] = x2;
+	right[rightOff + 5] = y2;
+      }
 
     x1 = (x1 + xc) / 2;
     x2 = (xc + x2) / 2;
@@ -533,23 +514,22 @@
     yc = (y1 + y2) / 2;
 
     if (left != null)
-    {
-      left[leftOff + 2] = x1;
-      left[leftOff + 3] = y1;
-      left[leftOff + 4] = xc;
-      left[leftOff + 5] = yc;
-    }
+      {
+	left[leftOff + 2] = x1;
+	left[leftOff + 3] = y1;
+	left[leftOff + 4] = xc;
+	left[leftOff + 5] = yc;
+      }
 
     if (right != null)
-    {
-      right[rightOff] = xc;
-      right[rightOff + 1] = yc;
-      right[rightOff + 2] = x2;
-      right[rightOff + 3] = y2;
-    }
+      {
+	right[rightOff] = xc;
+	right[rightOff + 1] = yc;
+	right[rightOff + 2] = x2;
+	right[rightOff + 3] = y2;
+      }
   }
 
-
   /**
    * Finds the non-complex roots of a quadratic equation, placing the
    * results into the same array as the equation coefficients. The
@@ -594,7 +574,6 @@
     return solveQuadratic(eqn, eqn);
   }
 
-
   /**
    * Finds the non-complex roots of a quadratic equation. The
    * following equation is being solved:
@@ -649,8 +628,10 @@
     // The Java implementation is very similar to the GSL code, but
     // not a strict one-to-one copy. For example, GSL would sort the
     // result.
-
-    double a, b, c, disc;
+    double a;
+    double b;
+    double c;
+    double disc;
 
     c = eqn[0];
     b = eqn[1];
@@ -661,13 +642,13 @@
     // wouldn't return -1 for constant functions, and 2 instead of 1
     // for linear functions.
     if (a == 0)
-    {
-      if (b == 0)
-        return -1;
-      
-      res[0] = -c / b;
-      return 1;
-    }
+      {
+	if (b == 0)
+	  return -1;
+
+	res[0] = -c / b;
+	return 1;
+      }
 
     disc = b * b - 4 * a * c;
 
@@ -675,96 +656,149 @@
       return 0;
 
     if (disc == 0)
-    {
-      // The GNU Scientific Library returns two identical results here.
-      // We just return one.
-      res[0] = -0.5 * b / a ;
-      return 1;
-    }
+      {
+	// The GNU Scientific Library returns two identical results here.
+	// We just return one.
+	res[0] = -0.5 * b / a;
+	return 1;
+      }
 
     // disc > 0
     if (b == 0)
-    {
-      double r;
+      {
+	double r;
 
-      r = Math.abs(0.5 * Math.sqrt(disc) / a);
-      res[0] = -r;
-      res[1] = r;
-    }
+	r = Math.abs(0.5 * Math.sqrt(disc) / a);
+	res[0] = -r;
+	res[1] = r;
+      }
     else
-    {
-      double sgnb, temp;
-      
-      sgnb = (b > 0 ? 1 : -1);
-      temp = -0.5 * (b + sgnb * Math.sqrt(disc));
-
-      // The GNU Scientific Library sorts the result here. We don't.
-      res[0] = temp / a;
-      res[1] = c / temp;
-    }
+      {
+	double sgnb;
+	double temp;
+
+	sgnb = (b > 0 ? 1 : -1);
+	temp = -0.5 * (b + sgnb * Math.sqrt(disc));
+
+	// The GNU Scientific Library sorts the result here. We don't.
+	res[0] = temp / a;
+	res[1] = c / temp;
+      }
     return 2;
   }
 
-
   /**
-   * Determines whether a point lies inside the area that is bounded
+   * Determines whether a point is inside the area bounded
    * by the curve and the straight line connecting its end points.
    *
    * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
    * alt="A drawing of the area spanned by the curve" />
    *
    * <p>The above drawing illustrates in which area points are
-   * considered &#x201c;contained&#x201d; in a QuadCurve2D.
+   * considered &#x201c;inside&#x201d; a QuadCurve2D.
    */
   public boolean contains(double x, double y)
   {
-    // XXX Implement.
-    throw new Error("not implemented");
-  }
+    if (! getBounds2D().contains(x, y))
+      return false;
 
+    return ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0);
+  }
 
   /**
-   * Determines whether a point lies inside the area that is bounded
+   * Determines whether a point is inside the area bounded
    * by the curve and the straight line connecting its end points.
    *
    * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
    * alt="A drawing of the area spanned by the curve" />
    *
    * <p>The above drawing illustrates in which area points are
-   * considered &#x201c;contained&#x201d; in a QuadCurve2D.
+   * considered &#x201c;inside&#x201d; a QuadCurve2D.
    */
   public boolean contains(Point2D p)
   {
     return contains(p.getX(), p.getY());
   }
 
-
+  /**
+   * Determines whether any part of a rectangle is inside the area bounded
+   * by the curve and the straight line connecting its end points.
+   *
+   * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
+   * alt="A drawing of the area spanned by the curve" />
+   *
+   * <p>The above drawing illustrates in which area points are
+   * considered &#x201c;inside&#x201d; in a CubicCurve2D.
+   */
   public boolean intersects(double x, double y, double w, double h)
   {
-    // XXX Implement.
-    throw new Error("not implemented");
-  }
+    if (! getBounds2D().contains(x, y, w, h))
+      return false;
+
+    /* Does any edge intersect? */
+    if (getAxisIntersections(x, y, true, w) != 0 /* top */
+        || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
+        || getAxisIntersections(x + w, y, false, h) != 0 /* right */
+        || getAxisIntersections(x, y, false, h) != 0) /* left */
+      return true;
+
+    /* No intersections, is any point inside? */
+    if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
+      return true;
 
+    return false;
+  }
 
+  /**
+   * Determines whether any part of a Rectangle2D is inside the area bounded 
+   * by the curve and the straight line connecting its end points.
+   * @see #intersects(double, double, double, double)
+   */
   public boolean intersects(Rectangle2D r)
   {
     return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
   }
 
-
+  /**
+   * Determines whether a rectangle is entirely inside the area bounded
+   * by the curve and the straight line connecting its end points.
+   *
+   * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
+   * alt="A drawing of the area spanned by the curve" />
+   *
+   * <p>The above drawing illustrates in which area points are
+   * considered &#x201c;inside&#x201d; a QuadCurve2D.
+   * @see #contains(double, double)
+   */
   public boolean contains(double x, double y, double w, double h)
   {
-    // XXX Implement.
-    throw new Error("not implemented");
-  }
+    if (! getBounds2D().intersects(x, y, w, h))
+      return false;
+
+    /* Does any edge intersect? */
+    if (getAxisIntersections(x, y, true, w) != 0 /* top */
+        || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
+        || getAxisIntersections(x + w, y, false, h) != 0 /* right */
+        || getAxisIntersections(x, y, false, h) != 0) /* left */
+      return false;
 
+    /* No intersections, is any point inside? */
+    if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
+      return true;
+
+    return false;
+  }
 
+  /**
+   * Determines whether a Rectangle2D is entirely inside the area that is 
+   * bounded by the curve and the straight line connecting its end points.
+   * @see #contains(double, double, double, double)
+   */
   public boolean contains(Rectangle2D r)
   {
     return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
   }
 
-
   /**
    * Determines the smallest rectangle that encloses the
    * curve&#x2019;s start, end and control point. As the illustration
@@ -780,97 +814,85 @@
     return getBounds2D().getBounds();
   }
 
-
   public PathIterator getPathIterator(final AffineTransform at)
   {
     return new PathIterator()
-    {
-      /** Current coordinate. */
-      private int current = 0;
-
-
-      public int getWindingRule()
-      {
-        return WIND_NON_ZERO;
-      }
-
-
-      public boolean isDone()
-      {
-        return current >= 2;
-      }
-
-
-      public void next()
-      {
-        current++;
-      }
-
-
-      public int currentSegment(float[] coords)
       {
-        int result;
-        switch (current)
-        {
-        case 0:
-          coords[0] = (float) getX1();
-          coords[1] = (float) getY1();
-          result = SEG_MOVETO;
-          break;
-
-        case 1:
-          coords[0] = (float) getCtrlX();
-          coords[1] = (float) getCtrlY();
-          coords[2] = (float) getX2();
-          coords[3] = (float) getY2();
-          result = SEG_QUADTO;
-          break;
-
-        default:
-          throw new NoSuchElementException("quad iterator out of bounds");
-        }
-        if (at != null)
-          at.transform(coords, 0, coords, 0, 2);
-        return result;
-      }
-
+	/** Current coordinate. */
+	private int current = 0;
 
-      public int currentSegment(double[] coords)
-      {
-        int result;
-        switch (current)
-        {
-        case 0:
-          coords[0] = getX1();
-          coords[1] = getY1();
-          result = SEG_MOVETO;
-          break;
-
-        case 1:
-          coords[0] = getCtrlX();
-          coords[1] = getCtrlY();
-          coords[2] = getX2();
-          coords[3] = getY2();
-          result = SEG_QUADTO;
-          break;
-
-        default:
-          throw new NoSuchElementException("quad iterator out of bounds");
-        }
-        if (at != null)
-          at.transform(coords, 0, coords, 0, 2);
-        return result;
-      }
-    };
+	public int getWindingRule()
+	{
+	  return WIND_NON_ZERO;
+	}
+
+	public boolean isDone()
+	{
+	  return current >= 2;
+	}
+
+	public void next()
+	{
+	  current++;
+	}
+
+	public int currentSegment(float[] coords)
+	{
+	  int result;
+	  switch (current)
+	    {
+	    case 0:
+	      coords[0] = (float) getX1();
+	      coords[1] = (float) getY1();
+	      result = SEG_MOVETO;
+	      break;
+	    case 1:
+	      coords[0] = (float) getCtrlX();
+	      coords[1] = (float) getCtrlY();
+	      coords[2] = (float) getX2();
+	      coords[3] = (float) getY2();
+	      result = SEG_QUADTO;
+	      break;
+	    default:
+	      throw new NoSuchElementException("quad iterator out of bounds");
+	    }
+	  if (at != null)
+	    at.transform(coords, 0, coords, 0, 2);
+	  return result;
+	}
+
+	public int currentSegment(double[] coords)
+	{
+	  int result;
+	  switch (current)
+	    {
+	    case 0:
+	      coords[0] = getX1();
+	      coords[1] = getY1();
+	      result = SEG_MOVETO;
+	      break;
+	    case 1:
+	      coords[0] = getCtrlX();
+	      coords[1] = getCtrlY();
+	      coords[2] = getX2();
+	      coords[3] = getY2();
+	      result = SEG_QUADTO;
+	      break;
+	    default:
+	      throw new NoSuchElementException("quad iterator out of bounds");
+	    }
+	  if (at != null)
+	    at.transform(coords, 0, coords, 0, 2);
+	  return result;
+	}
+      };
   }
 
-
   public PathIterator getPathIterator(AffineTransform at, double flatness)
   {
     return new FlatteningPathIterator(getPathIterator(at), flatness);
   }
 
-
   /**
    * Creates a new curve with the same contents as this one.
    *
@@ -879,15 +901,106 @@
   public Object clone()
   {
     try
-    {
-      return super.clone();
-    }
+      {
+	return super.clone();
+      }
     catch (CloneNotSupportedException e)
-    {
-      throw (Error) new InternalError().initCause(e); // Impossible
-    }
+      {
+	throw (Error) new InternalError().initCause(e); // Impossible
+      }
   }
 
+  /**
+   * Helper method used by contains() and intersects() methods
+   * Return the number of curve/line intersections on a given axis
+   * extending from a certain point. useYaxis is true for using the Y axis,
+   * @param x x coordinate of the origin point
+   * @param y y coordinate of the origin point
+   * @param useYaxis axis to follow, if true the positive Y axis is used,
+   * false uses the positive X axis.
+   *
+   * This is an implementation of the line-crossings algorithm,
+   * Detailed in an article on Eric Haines' page:
+   * http://www.acm.org/tog/editors/erich/ptinpoly/
+   */
+  private int getAxisIntersections(double x, double y, boolean useYaxis,
+                                   double distance)
+  {
+    int nCrossings = 0;
+    double a0;
+    double a1;
+    double a2;
+    double b0;
+    double b1;
+    double b2;
+    double[] r = new double[3];
+    int nRoots;
+
+    a0 = a2 = 0.0;
+
+    if (useYaxis)
+      {
+	a0 = getY1() - y;
+	a1 = getCtrlY() - y;
+	a2 = getY2() - y;
+	b0 = getX1() - x;
+	b1 = getCtrlX() - x;
+	b2 = getX2() - x;
+      }
+    else
+      {
+	a0 = getX1() - x;
+	a1 = getCtrlX() - x;
+	a2 = getX2() - x;
+	b0 = getY1() - y;
+	b1 = getCtrlY() - y;
+	b2 = getY2() - y;
+      }
+
+    /* If the axis intersects a start/endpoint, shift it up by some small 
+       amount to guarantee the line is 'inside'
+       If this is not done,bad behaviour may result for points on that axis. */
+    if (a0 == 0.0 || a2 == 0.0)
+      {
+	double small = getFlatness() * (1E-10);
+	if (a0 == 0.0)
+	  a0 += small;
+
+	if (a2 == 0.0)
+	  a2 += small;
+      }
+
+    r[0] = a0;
+    r[1] = 2 * (a1 - a0);
+    r[2] = (a2 - 2 * a1 + a0);
+
+    nRoots = solveQuadratic(r);
+    for (int i = 0; i < nRoots; i++)
+      {
+	double t = r[i];
+	if (t >= 0.0 && t <= 1.0)
+	  {
+	    double crossing = t * t * (b2 - 2 * b1 + b0) + 2 * t * (b1 - b0)
+	                      + b0;
+	    /* single root is always doubly degenerate in quads */
+	    if (crossing > 0 && crossing < distance)
+	      nCrossings += (nRoots == 1) ? 2 : 1;
+	  }
+      }
+
+    if (useYaxis)
+      {
+	if (Line2D.linesIntersect(b0, a0, b2, a2, 0.0, 0.0, distance, 0.0))
+	  nCrossings++;
+      }
+    else
+      {
+	if (Line2D.linesIntersect(a0, b0, a2, b2, 0.0, 0.0, 0.0, distance))
+	  nCrossings++;
+      }
+
+    return (nCrossings);
+  }
 
   /**
    * A two-dimensional curve that is parameterized with a quadratic
@@ -899,45 +1012,38 @@
    * @author Eric Blake (ebb9@email.byu.edu)
    * @author Sascha Brawer (brawer@dandelis.ch)
    */
-  public static class Double
-    extends QuadCurve2D
+  public static class Double extends QuadCurve2D
   {
     /**
      * The <i>x</i> coordinate of the curve&#x2019;s start point.
      */
     public double x1;
 
-
     /**
      * The <i>y</i> coordinate of the curve&#x2019;s start point.
      */
     public double y1;
 
-
     /**
      * The <i>x</i> coordinate of the curve&#x2019;s control point.
      */
     public double ctrlx;
 
-
     /**
      * The <i>y</i> coordinate of the curve&#x2019;s control point.
      */
     public double ctrly;
 
-
     /**
      * The <i>x</i> coordinate of the curve&#x2019;s end point.
      */
     public double x2;
 
-
     /**
      * The <i>y</i> coordinate of the curve&#x2019;s end point.
      */
     public double y2;
 
-
     /**
      * Constructs a new QuadCurve2D that stores its coordinate values
      * in double-precision floating-point format. All points are
@@ -947,7 +1053,6 @@
     {
     }
 
-
     /**
      * Constructs a new QuadCurve2D that stores its coordinate values
      * in double-precision floating-point format, specifying the
@@ -971,8 +1076,8 @@
      * @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
      * point.
      */
-    public Double(double x1, double y1, double cx, double cy,
-                  double x2, double y2)
+    public Double(double x1, double y1, double cx, double cy, double x2,
+                  double y2)
     {
       this.x1 = x1;
       this.y1 = y1;
@@ -982,7 +1087,6 @@
       this.y2 = y2;
     }
 
-
     /**
      * Returns the <i>x</i> coordinate of the curve&#x2019;s start
      * point.
@@ -992,7 +1096,6 @@
       return x1;
     }
 
-
     /**
      * Returns the <i>y</i> coordinate of the curve&#x2019;s start
      * point.
@@ -1002,7 +1105,6 @@
       return y1;
     }
 
-
     /**
      * Returns the curve&#x2019;s start point.
      */
@@ -1011,7 +1113,6 @@
       return new Point2D.Double(x1, y1);
     }
 
-
     /**
      * Returns the <i>x</i> coordinate of the curve&#x2019;s control
      * point.
@@ -1021,7 +1122,6 @@
       return ctrlx;
     }
 
-
     /**
      * Returns the <i>y</i> coordinate of the curve&#x2019;s control
      * point.
@@ -1031,7 +1131,6 @@
       return ctrly;
     }
 
-
     /**
      * Returns the curve&#x2019;s control point.
      */
@@ -1040,7 +1139,6 @@
       return new Point2D.Double(ctrlx, ctrly);
     }
 
-
     /**
      * Returns the <i>x</i> coordinate of the curve&#x2019;s end
      * point.
@@ -1050,7 +1148,6 @@
       return x2;
     }
 
-
     /**
      * Returns the <i>y</i> coordinate of the curve&#x2019;s end
      * point.
@@ -1060,7 +1157,6 @@
       return y2;
     }
 
-
     /**
      * Returns the curve&#x2019;s end point.
      */
@@ -1069,7 +1165,6 @@
       return new Point2D.Double(x2, y2);
     }
 
-
     /**
      * Changes the geometry of the curve.
      *
@@ -1102,7 +1197,6 @@
       this.y2 = y2;
     }
 
-
     /**
      * Determines the smallest rectangle that encloses the
      * curve&#x2019;s start, end and control point. As the
@@ -1123,7 +1217,6 @@
     }
   }
 
-
   /**
    * A two-dimensional curve that is parameterized with a quadratic
    * function and stores coordinate values in single-precision
@@ -1134,45 +1227,38 @@
    * @author Eric Blake (ebb9@email.byu.edu)
    * @author Sascha Brawer (brawer@dandelis.ch)
    */
-  public static class Float
-    extends QuadCurve2D
+  public static class Float extends QuadCurve2D
   {
     /**
      * The <i>x</i> coordinate of the curve&#x2019;s start point.
      */
     public float x1;
 
-
     /**
      * The <i>y</i> coordinate of the curve&#x2019;s start point.
      */
     public float y1;
 
-
     /**
      * The <i>x</i> coordinate of the curve&#x2019;s control point.
      */
     public float ctrlx;
 
-
     /**
      * The <i>y</i> coordinate of the curve&#x2019;s control point.
      */
     public float ctrly;
 
-
     /**
      * The <i>x</i> coordinate of the curve&#x2019;s end point.
      */
     public float x2;
 
-
     /**
      * The <i>y</i> coordinate of the curve&#x2019;s end point.
      */
     public float y2;
 
-
     /**
      * Constructs a new QuadCurve2D that stores its coordinate values
      * in single-precision floating-point format. All points are
@@ -1182,7 +1268,6 @@
     {
     }
 
-
     /**
      * Constructs a new QuadCurve2D that stores its coordinate values
      * in single-precision floating-point format, specifying the
@@ -1206,8 +1291,7 @@
      * @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
      * point.
      */
-    public Float(float x1, float y1, float cx, float cy,
-                 float x2, float y2)
+    public Float(float x1, float y1, float cx, float cy, float x2, float y2)
     {
       this.x1 = x1;
       this.y1 = y1;
@@ -1217,7 +1301,6 @@
       this.y2 = y2;
     }
 
-
     /**
      * Returns the <i>x</i> coordinate of the curve&#x2019;s start
      * point.
@@ -1227,7 +1310,6 @@
       return x1;
     }
 
-
     /**
      * Returns the <i>y</i> coordinate of the curve&#x2019;s start
      * point.
@@ -1237,7 +1319,6 @@
       return y1;
     }
 
-
     /**
      * Returns the curve&#x2019;s start point.
      */
@@ -1246,7 +1327,6 @@
       return new Point2D.Float(x1, y1);
     }
 
-
     /**
      * Returns the <i>x</i> coordinate of the curve&#x2019;s control
      * point.
@@ -1256,7 +1336,6 @@
       return ctrlx;
     }
 
-
     /**
      * Returns the <i>y</i> coordinate of the curve&#x2019;s control
      * point.
@@ -1266,7 +1345,6 @@
       return ctrly;
     }
 
-
     /**
      * Returns the curve&#x2019;s control point.
      */
@@ -1275,7 +1353,6 @@
       return new Point2D.Float(ctrlx, ctrly);
     }
 
-
     /**
      * Returns the <i>x</i> coordinate of the curve&#x2019;s end
      * point.
@@ -1285,7 +1362,6 @@
       return x2;
     }
 
-
     /**
      * Returns the <i>y</i> coordinate of the curve&#x2019;s end
      * point.
@@ -1295,7 +1371,6 @@
       return y2;
     }
 
-
     /**
      * Returns the curve&#x2019;s end point.
      */
@@ -1304,7 +1379,6 @@
       return new Point2D.Float(x2, y2);
     }
 
-
     /**
      * Changes the geometry of the curve, specifying coordinate values
      * as double-precision floating-point numbers.
@@ -1338,7 +1412,6 @@
       this.y2 = (float) y2;
     }
 
-
     /**
      * Changes the geometry of the curve, specifying coordinate values
      * as single-precision floating-point numbers.
@@ -1361,8 +1434,8 @@
      * @param y2 the <i>y</i> coordinate of the curve&#x2019;s new
      * end point.
      */
-    public void setCurve(float x1, float y1, float cx, float cy,
-                         float x2, float y2)
+    public void setCurve(float x1, float y1, float cx, float cy, float x2,
+                         float y2)
     {
       this.x1 = x1;
       this.y1 = y1;
@@ -1372,7 +1445,6 @@
       this.y2 = y2;
     }
 
-
     /**
      * Determines the smallest rectangle that encloses the
      * curve&#x2019;s start, end and control point. As the
Index: java/awt/geom/RoundRectangle2D.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/geom/RoundRectangle2D.java,v
retrieving revision 1.5
diff -u -r1.5 RoundRectangle2D.java
--- java/awt/geom/RoundRectangle2D.java	26 Sep 2003 15:14:21 -0000	1.5
+++ java/awt/geom/RoundRectangle2D.java	8 Aug 2004 19:38:26 -0000
@@ -1,5 +1,5 @@
 /* RoundRectangle2D.java -- represents a rectangle with rounded corners
-   Copyright (C) 2000, 2002, 2003 Free Software Foundation
+   Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation
 
 This file is part of GNU Classpath.
 
@@ -39,6 +39,7 @@
 
 import java.util.NoSuchElementException;
 
+
 /** This class implements a rectangle with rounded corners.
  * @author Tom Tromey <tromey@cygnus.com>
  * @date December 3, 2000
@@ -60,12 +61,12 @@
    * @param arcHeight The arc height
    */
   public abstract void setRoundRect(double x, double y, double w, double h,
-                                     double arcWidth, double arcHeight);
+                                    double arcWidth, double arcHeight);
 
   /** Create a RoundRectangle2D.  This is protected because this class
    * is abstract and cannot be instantiated.
    */
-  protected  RoundRectangle2D()
+  protected RoundRectangle2D()
   {
   }
 
@@ -87,8 +88,11 @@
     // Now check to see if the point is in range of an arc.
     double dy = Math.min(Math.abs(my - y), Math.abs(my + mh - y));
     double dx = Math.min(Math.abs(mx - x), Math.abs(mx + mw - x));
-    double aw = getArcWidth();
-    double ah = getArcHeight();
+
+    // The arc dimensions are that of the corresponding ellipse
+    // thus a 90 degree segment is half of that.
+    double aw = getArcWidth() / 2.0;
+    double ah = getArcHeight() / 2.0;
     if (dx > aw || dy > ah)
       return true;
 
@@ -112,8 +116,8 @@
   {
     // We have to check all four points here (for ordinary rectangles
     // we can just check opposing corners).
-    return (contains(x, y) && contains(x + w, h)
-            && contains(x, y + h) && contains(x + w, y + h));
+    return (contains(x, y) && contains(x, y + h) && contains(x + w, y + h)
+           && contains(x + w, y));
   }
 
   /** Return a new path iterator which iterates over this rectangle.
@@ -128,154 +132,161 @@
     final double arcwidth = getArcWidth();
     final double archeight = getArcHeight();
     return new PathIterator()
-    {
-      /** We iterate clockwise around the rectangle, starting in the
-       * upper left.  This variable tracks our current point, which
-       * can be on either side of a given corner.  */
-      private int current = 0;
-
-      /** Child path iterator, used for corners.  */
-      private PathIterator corner;
-
-      /** This is used when rendering the corners.  We re-use the arc
-       * for each corner.  */
-      private Arc2D arc = new Arc2D.Double();
-
-      /** Temporary array used by getPoint.  */
-      private double[] temp = new double[2];
-
-      public int getWindingRule()
-      {
-	return WIND_NON_ZERO;
-      }
-
-      public boolean isDone()
-      {
-	return current > 9;
-      }
-
-      private void getPoint(int val)
-      {
-	switch (val)
-	  {
-	  case 0:
-	  case 8:
-	    temp[0] = minx;
-	    temp[1] = miny + archeight;
-	    break;
-	  case 1:
-	    temp[0] = minx + arcwidth;
-	    temp[1] = miny;
-	    break;
-	  case 2:
-	    temp[0] = maxx - arcwidth;
-	    temp[1] = maxy;
-	    break;
-	  case 3:
-	    temp[0] = maxx;
-	    temp[1] = miny + archeight;
-	    break;
-	  case 4:
-	    temp[0] = maxx;
-	    temp[1] = maxy - archeight;
-	    break;
-	  case 5:
-	    temp[0] = maxx - arcwidth;
-	    temp[1] = maxy;
-	    break;
-	  case 6:
-	    temp[0] = minx + arcwidth;
-	    temp[1] = maxy;
-	    break;
-	  case 7:
-	    temp[0] = minx;
-	    temp[1] = maxy - archeight;
-	    break;
-	  }
-      }
-
-      public void next()
-      {
-	if (current >= 8)
-	  ++current;
-	else if (corner != null)
-	  {
-	    // We're iterating through the corner.  Work on the child
-	    // iterator; if it finishes, reset and move to the next
-	    // point along the rectangle.
-	    corner.next();
-	    if (corner.isDone())
-	      {
-		corner = null;
-		++current;
-	      }
-	  }
-	else
-	  {
-	    // Make an arc between this point on the rectangle and
-	    // the next one, and then iterate over this arc.
-	    getPoint(current);
-	    double x1 = temp[0];
-	    double y1 = temp[1];
-	    getPoint(current + 1);
-	    arc.setFrameFromDiagonal(x1, y1, temp[0], temp[1]);
-	    arc.setAngles(x1, y1, temp[0], temp[1]);
-	    corner = arc.getPathIterator(at);
-	  }
-      }
-
-      public int currentSegment(float[] coords)
-      {
-	if (corner != null)
-	  {
-	    int r = corner.currentSegment(coords);
-	    if (r == SEG_MOVETO)
-	      r = SEG_LINETO;
-	    return r;
-	  }
-
-	if (current < 9)
-	  {
-	    getPoint(current);
-	    coords[0] = (float) temp[0];
-	    coords[1] = (float) temp[1];
-	  }
-	else if (current == 9)
-	  return SEG_CLOSE;
-	else
-	  throw new NoSuchElementException("rect iterator out of bounds");
-
-	if (at != null)
-	  at.transform(coords, 0, coords, 0, 1);
-	return current == 0 ? SEG_MOVETO : SEG_LINETO;
-      }
-
-      public int currentSegment(double[] coords)
       {
-	if (corner != null)
-	  {
-	    int r = corner.currentSegment(coords);
-	    if (r == SEG_MOVETO)
-	      r = SEG_LINETO;
-	    return r;
-	  }
-
-	if (current < 9)
-	  {
-	    getPoint(current);
-	    coords[0] = temp[0];
-	    coords[1] = temp[1];
-	  }
-	else if (current == 9)
-	  return SEG_CLOSE;
-	else
-	  throw new NoSuchElementException("rect iterator out of bounds");
-
-	if (at != null)
-	  at.transform(coords, 0, coords, 0, 1);
-	return current == 0 ? SEG_MOVETO : SEG_LINETO;
-      }
-    };
+	/** We iterate counterclockwise around the rectangle, starting in the
+	 * upper right.  This variable tracks our current point, which
+	 * can be on either side of a given corner.  */
+	private int current = 0;
+
+	/** Child path iterator, used for corners.  */
+	private PathIterator corner;
+
+	/** This is used when rendering the corners.  We re-use the arc
+	 * for each corner.  */
+	private Arc2D arc = new Arc2D.Double();
+
+	/** Temporary array used by getPoint.  */
+	private double[] temp = new double[2];
+
+	public int getWindingRule()
+	{
+	  return WIND_NON_ZERO;
+	}
+
+	public boolean isDone()
+	{
+	  return current > 9;
+	}
+
+	private void getPoint(int val)
+	{
+	  switch (val)
+	    {
+	    case 0:
+	    case 8:
+	      temp[0] = maxx;
+	      temp[1] = miny + archeight;
+	      break;
+	    case 7:
+	      temp[0] = maxx;
+	      temp[1] = maxy - archeight;
+	      break;
+	    case 6:
+	      temp[0] = maxx - arcwidth;
+	      temp[1] = maxy;
+	      break;
+	    case 5:
+	      temp[0] = minx + arcwidth;
+	      temp[1] = maxy;
+	      break;
+	    case 4:
+	      temp[0] = minx;
+	      temp[1] = maxy - archeight;
+	      break;
+	    case 3:
+	      temp[0] = minx;
+	      temp[1] = miny + archeight;
+	      break;
+	    case 2:
+	      temp[0] = minx + arcwidth;
+	      temp[1] = miny;
+	      break;
+	    case 1:
+	      temp[0] = maxx - arcwidth;
+	      temp[1] = miny;
+	      break;
+	    }
+	}
+
+	public void next()
+	{
+	  if (current >= 8)
+	    ++current;
+	  else if (corner != null)
+	    {
+	      // We're iterating through the corner.  Work on the child
+	      // iterator; if it finishes, reset and move to the next
+	      // point along the rectangle.
+	      corner.next();
+	      if (corner.isDone())
+	        {
+		  corner = null;
+		  ++current;
+	        }
+	    }
+	  else
+	    {
+	      // Make an arc between this point on the rectangle and
+	      // the next one, and then iterate over this arc.
+	      getPoint(current);
+	      double x1 = temp[0];
+	      double y1 = temp[1];
+	      getPoint(current + 1);
+	      Rectangle2D.Double r = new Rectangle2D.Double(Math.min(x1,
+	                                                             temp[0]),
+	                                                    Math.min(y1,
+	                                                             temp[1]),
+	                                                    Math.abs(x1
+	                                                             - temp[0]),
+	                                                    Math.abs(y1
+	                                                             - temp[1]));
+	      arc.setArc(r, (current >> 1) * 90.0, 90.0, Arc2D.OPEN);
+	      corner = arc.getPathIterator(at);
+	    }
+	}
+
+	public int currentSegment(float[] coords)
+	{
+	  if (corner != null)
+	    {
+	      int r = corner.currentSegment(coords);
+	      if (r == SEG_MOVETO)
+		r = SEG_LINETO;
+	      return r;
+	    }
+
+	  if (current < 9)
+	    {
+	      getPoint(current);
+	      coords[0] = (float) temp[0];
+	      coords[1] = (float) temp[1];
+	    }
+	  else if (current == 9)
+	    return SEG_CLOSE;
+	  else
+	    throw new NoSuchElementException("rect iterator out of bounds");
+
+	  if (at != null)
+	    at.transform(coords, 0, coords, 0, 1);
+	  return current == 0 ? SEG_MOVETO : SEG_LINETO;
+	}
+
+	public int currentSegment(double[] coords)
+	{
+	  if (corner != null)
+	    {
+	      int r = corner.currentSegment(coords);
+	      if (r == SEG_MOVETO)
+		r = SEG_LINETO;
+	      return r;
+	    }
+
+	  if (current < 9)
+	    {
+	      getPoint(current);
+	      coords[0] = temp[0];
+	      coords[1] = temp[1];
+	    }
+	  else if (current == 9)
+	    return SEG_CLOSE;
+	  else
+	    throw new NoSuchElementException("rect iterator out of bounds");
+
+	  if (at != null)
+	    at.transform(coords, 0, coords, 0, 1);
+	  return current == 0 ? SEG_MOVETO : SEG_LINETO;
+	}
+      };
   }
 
   /** Return true if the given rectangle intersects this shape.
@@ -286,14 +297,9 @@
    */
   public boolean intersects(double x, double y, double w, double h)
   {
-    // Here we can use the same code we use for an ordinary rectangle.
-    double mx = getX();
-    double mw = getWidth();
-    if (x < mx || x >= mx + mw || x + w < mx || x + w >= mx + mw)
-      return false;
-    double my = getY();
-    double mh = getHeight();
-    return y >= my && y < my + mh && y + h >= my && y + h < my + mh;
+    // Check if any corner is within the rectangle
+    return (contains(x, y) || contains(x, y + h) || contains(x + w, y + h)
+           || contains(x + w, y));
   }
 
   /** Set the boundary of this round rectangle.
@@ -315,7 +321,7 @@
   public void setRoundRect(RoundRectangle2D rr)
   {
     setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(),
-                  rr.getArcWidth(), rr.getArcHeight());
+                 rr.getArcWidth(), rr.getArcHeight());
   }
 
   /** A subclass of RoundRectangle which keeps its parameters as
@@ -353,8 +359,8 @@
      * @param arcWidth The arc width
      * @param arcHeight The arc height
      */
-    public Double(double x, double y, double w, double h,
-                   double arcWidth, double arcHeight)
+    public Double(double x, double y, double w, double h, double arcWidth,
+                  double arcHeight)
     {
       this.x = x;
       this.y = y;
@@ -405,7 +411,7 @@
     }
 
     public void setRoundRect(double x, double y, double w, double h,
-                              double arcWidth, double arcHeight)
+                             double arcWidth, double arcHeight)
     {
       this.x = x;
       this.y = y;
@@ -451,8 +457,8 @@
      * @param arcWidth The arc width
      * @param arcHeight The arc height
      */
-    public Float(float x, float y, float w, float h,
-                  float arcWidth, float arcHeight)
+    public Float(float x, float y, float w, float h, float arcWidth,
+                 float arcHeight)
     {
       this.x = x;
       this.y = y;
@@ -503,7 +509,7 @@
     }
 
     public void setRoundRect(float x, float y, float w, float h,
-                              float arcWidth, float arcHeight)
+                             float arcWidth, float arcHeight)
     {
       this.x = x;
       this.y = y;
@@ -514,7 +520,7 @@
     }
 
     public void setRoundRect(double x, double y, double w, double h,
-                              double arcWidth, double arcHeight)
+                             double arcWidth, double arcHeight)
     {
       this.x = (float) x;
       this.y = (float) y;

Attachment: signature.asc
Description: This is a digitally signed message part


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]