8203027: Open source tests for "java.awt.geom"
authorserb
Tue, 22 May 2018 17:33:31 -0700
changeset 50344 8039dc75f125
parent 50343 80a5ff734fcd
child 50345 276cb4b17f79
8203027: Open source tests for "java.awt.geom" Reviewed-by: prr, jdv
test/jdk/java/awt/geom/AffineTransform/QuadRotInverseBug.java
test/jdk/java/awt/geom/Arc2D/Arc2DIntersectsTest.java
test/jdk/java/awt/geom/Arc2D/ChordContainsTest.java
test/jdk/java/awt/geom/Arc2D/NotConvexPieTest.java
test/jdk/java/awt/geom/Arc2D/SetAnglesTest.java
test/jdk/java/awt/geom/Arc2D/SmallExtAngleTest.java
test/jdk/java/awt/geom/Area/ArcSubtractEllipseBug.java
test/jdk/java/awt/geom/Area/AreaNaNBug.java
test/jdk/java/awt/geom/Area/AreaTransformTest.java
test/jdk/java/awt/geom/Area/BoundsCache.java
test/jdk/java/awt/geom/Area/EqualsNull.java
test/jdk/java/awt/geom/Area/NPETests.java
test/jdk/java/awt/geom/Area/PolygonAdd.java
test/jdk/java/awt/geom/Area/PolygonSubtract.java
test/jdk/java/awt/geom/Area/QuadCurveOOMBug.java
test/jdk/java/awt/geom/Area/TightBBox.java
test/jdk/java/awt/geom/Area/TransformPrecision.java
test/jdk/java/awt/geom/CubicCurve2D/ContainsHang.java
test/jdk/java/awt/geom/CubicCurve2D/ContainsPoint.java
test/jdk/java/awt/geom/EqualsHashcode.java
test/jdk/java/awt/geom/GeneralPath/ContainsNaN.java
test/jdk/java/awt/geom/GeneralPath/ContainsPoint.java
test/jdk/java/awt/geom/GeneralPath/CreateTxReturnsGP.java
test/jdk/java/awt/geom/GeneralPath/EmptyRectHitTest.java
test/jdk/java/awt/geom/GeneralPath/IntersectsRect.java
test/jdk/java/awt/geom/Line2D/AALineTest.java
test/jdk/java/awt/geom/Line2D/NegLineDistSqBug.java
test/jdk/java/awt/geom/Path2D/CreateTxReturnsSame.java
test/jdk/java/awt/geom/Path2D/NonFiniteTests.java
test/jdk/java/awt/geom/Path2D/UnitTest.java
test/jdk/java/awt/geom/QuadCurve2D/Quad2DContainsTest.java
test/jdk/java/awt/geom/Rectangle2D/CreateIntersectBug.java
test/jdk/java/awt/geom/Rectangle2D/IntersectsLineHang.java
test/jdk/java/awt/geom/SerialTest.java
test/jdk/java/awt/geom/serial_1_6.out
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/AffineTransform/QuadRotInverseBug.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4388199
+ * @summary Tests inverse transform of an array of points with
+ *          shearing and translation components in the AffineTransform
+ */
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Point2D;
+
+/*
+ * The AffineTransform method
+ * inverseTransform(double[],int,double[],int,int) produces incorrect
+ * results for pure shearing transformations or for shearing and
+ * translation transformations.  The simpliest example of which is a
+ * rotation by 90 degrees.
+ */
+public class QuadRotInverseBug {
+    public static void main(String[] args) {
+        // First test a transform which rotates the coordinate system by 90
+        // degrees.
+        System.out.println("Using 90 degree rotation:");
+        AffineTransform xform = AffineTransform.getRotateInstance(Math.PI/2);
+        boolean test1failed = test(xform);
+        // Next test the transform with an added translation component
+        System.out.println("Using 90 degree rotation with translation:");
+        xform.translate(2,2);
+        boolean test2failed = test(xform);
+        if (test1failed || test2failed) {
+            throw new RuntimeException("test failed, see printout");
+        }
+    }
+
+    public static boolean test(AffineTransform xform) {
+        // Make needed arrays.
+        double[] originalPoint = new double[2];
+        double[] transformedPoint = new double[2];
+        double[] inverseFromOriginalXForm = new double[2];
+
+        Point2D originalPoint2D = new Point2D.Double();
+        Point2D transformedPoint2D = new Point2D.Double();
+        Point2D inverseFromOriginalPoint2D = new Point2D.Double();
+
+        // Make the original point to check (x,y)=(1,1).
+        originalPoint[0] = 1.;
+        originalPoint[1] = 1.;
+
+        try {
+
+            originalPoint2D.setLocation(originalPoint[0], originalPoint[1]);
+
+            // Make the transformed point.
+            xform.transform(originalPoint,0,transformedPoint,0,1);
+            xform.transform(originalPoint2D, transformedPoint2D);
+
+            // Transform the point back using the original transformation.
+            xform.inverseTransform(transformedPoint,0,
+                                   inverseFromOriginalXForm,0,1);
+            xform.inverseTransform(transformedPoint2D,
+                                   inverseFromOriginalPoint2D);
+        } catch (NoninvertibleTransformException e) {
+            throw new InternalError("transform wasn't invertible!");
+        }
+
+        System.out.println("Both points should be identical:");
+        System.out.println("Original Point: "+
+                           originalPoint[0]+" "+
+                           originalPoint[1]);
+        System.out.println("inverseTransform method used: "+
+                           inverseFromOriginalXForm[0]+" "+
+                           inverseFromOriginalXForm[1]);
+        System.out.println("Original Point2D: "+ originalPoint2D);
+        System.out.println("inverseTransform method used: "+
+                           inverseFromOriginalPoint2D);
+        return (originalPoint[0] != inverseFromOriginalXForm[0] ||
+                originalPoint[1] != inverseFromOriginalXForm[1] ||
+                !originalPoint2D.equals(inverseFromOriginalPoint2D));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Arc2D/Arc2DIntersectsTest.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4724569
+ * @summary Arc2D "contains" and "intersects" problems, part II: fix enclosed.
+ */
+
+import java.awt.Shape;
+import java.awt.geom.Arc2D;
+import java.awt.geom.Rectangle2D;
+
+public class Arc2DIntersectsTest {
+
+    static Shape[][] trues = {
+        {
+            new Arc2D.Double(0, 0, 100, 100, -45, 90, Arc2D.PIE),
+            new Rectangle2D.Double(0, 0, 100, 100),
+        },
+        {
+            new Arc2D.Double(0, 0, 100, 100, -45, 90, Arc2D.PIE),
+            new Rectangle2D.Double(25, 25, 50, 50)
+        },
+        {
+            new Arc2D.Double(0, 0, 100, 100, -45, 90, Arc2D.PIE),
+            new Rectangle2D.Double(60, 0, 20, 100)
+        },
+        {
+            new Arc2D.Double(0, 0, 100, 100, -135, 270, Arc2D.CHORD),
+            new Rectangle2D.Double(20, 0, 20, 100)
+        }
+    };
+    static Shape[][] falses = {
+        {
+            new Arc2D.Double(0, 0, 100, 100, 0, 360, Arc2D.PIE),
+            new Rectangle2D.Double(0, 100, 100, 100)
+        },
+        {
+            new Arc2D.Double(0, 0, 100, 100, 45, 20, Arc2D.PIE),
+            new Rectangle2D.Double(75, 75, 100, 100)
+        },
+        {
+            new Arc2D.Double(0, 0, 100, 100, -10, 10, Arc2D.PIE),
+            new Rectangle2D.Double(50, 75, 50, 100)
+        },
+        {
+            new Arc2D.Double(0, 0, 100, 100, -10, 10, Arc2D.CHORD),
+            new Rectangle2D.Double(60, 0, 10, 100)
+        }
+    };
+
+    public static void main(String[] args) {
+
+        for (int i = 0; i < trues.length; i++) {
+            checkPair((Arc2D)trues[i][0], (Rectangle2D)trues[i][1], true);
+        }
+
+        for (int i = 0; i < falses.length; i++) {
+            checkPair((Arc2D)falses[i][0], (Rectangle2D)falses[i][1], false);
+        }
+    }
+
+    public static void checkPair(Arc2D arc, Rectangle2D rect, boolean expect) {
+
+        if (arc.intersects(rect) != expect) {
+            String errMsg = "Intersection of Arc(" +
+                            arc.getX() + ", " + arc.getY() + ", " +
+                            arc.getWidth() + ", " + arc.getHeight() + ", " +
+                            "start = " + arc.getAngleStart() + ", " +
+                            "extent = " + arc.getAngleExtent() + ", " +
+                            typeName(arc.getArcType()) + ") and Rectangle(" +
+                            rect.getX() + ", " + rect.getY() + ", " +
+                            rect.getWidth() + ", " + rect.getHeight() + ") " +
+                            "should be " + expect + ", BUT IT IS NOT.";
+            throw new RuntimeException(errMsg);
+        }
+    }
+
+    public static String typeName(int type) {
+
+        if (type == Arc2D.OPEN)
+            return "Open";
+        if (type == Arc2D.CHORD)
+            return "Chord";
+        if (type == Arc2D.PIE)
+            return "Pie";
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Arc2D/ChordContainsTest.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4724563
+ * @summary Test the points out of arc to recognize as not containing.
+ */
+
+import java.awt.geom.Arc2D;
+import java.awt.geom.Point2D;
+
+public class ChordContainsTest {
+
+    public void runTest() {
+
+        Arc2D a = new Arc2D.Double(-20, -20, 40, 40, -60, 120, Arc2D.CHORD);
+
+        // this point is surely out of chorded arc,
+        // it's closer to center
+        Point2D p = new Point2D.Double( a.getWidth() / 6, 0);
+
+        if (a.contains(p.getX(), p.getY())) {
+            throw new RuntimeException("Point out of arc recognized as containing");
+        }
+    }
+
+    public static void main(String[] args) {
+        ChordContainsTest test = new ChordContainsTest();
+        test.runTest();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Arc2D/NotConvexPieTest.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4725016
+ * @summary Tests the contains() method for not a convex pie with negative ext
+ */
+
+import java.awt.geom.Arc2D;
+import java.awt.geom.Rectangle2D;
+
+public class NotConvexPieTest {
+
+    Arc2D aNegative = new Arc2D.Double(-100, -100, 200, 200,
+                                       -45, -270, Arc2D.PIE);
+    // this rectangle surely have all vertices inside the
+    // arc above but intersects the pie slices
+    Rectangle2D rect = new Rectangle2D.Double(-20, -40, 40, 80);
+
+    String failText = "Test failed: rect should not be contained in arc due to "
+            + "intersections with radii";
+
+    public void runTest() {
+
+        boolean contains = aNegative.contains(rect.getX(),
+                                              rect.getY(),
+                                              rect.getWidth(),
+                                              rect.getHeight());
+        if (contains) {
+            // test failed
+            throw new RuntimeException(failText);
+        }
+    }
+
+    public static void main(String[] args) {
+        NotConvexPieTest test = new NotConvexPieTest();
+        test.runTest();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Arc2D/SetAnglesTest.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4724580
+ * @summary Pie slices should be colinear with vectors used to set angles.
+ */
+
+import java.awt.geom.Arc2D;
+import java.awt.geom.Point2D;
+
+public class SetAnglesTest {
+
+    public void runTest() {
+
+        Arc2D arc = new Arc2D.Double(-10, -40, 20, 80, 0, 0, Arc2D.PIE);
+        Point2D p1 = new Point2D.Double(10, 10);
+        Point2D p2 = new Point2D.Double(10, -10);
+        double threshold = 1.0E-10;
+
+        arc.setAngles(p1.getX(), p1.getY(), p2.getX(), p2.getY());
+
+        Point2D start = arc.getStartPoint();
+        Point2D end   = arc.getEndPoint();
+
+        checkColinear(start.getX(), start.getY(), p1.getX(), p1.getY());
+        checkColinear(end.getX(), end.getY(), p2.getX(), p2.getY());
+    }
+
+    void checkColinear(double dx1, double dy1, double dx2, double dy2) {
+
+        double threshold = 1.0E-10;
+
+        if (!(dx1 * dx2 >= 0 &&
+              dy1 * dy2 >= 0 &&
+              Math.abs(dx1 * dy2 - dx2 * dy1) <= threshold)) {
+            throw new RuntimeException("Angles difference is too much");
+        }
+    }
+
+    public static void main(String[] args) {
+        SetAnglesTest test = new SetAnglesTest();
+        test.runTest();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Arc2D/SmallExtAngleTest.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4836495
+ * @summary Very small ext angle of arc should not give NaNs in SEG_CUBICTO
+ */
+
+import java.awt.geom.Arc2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Rectangle2D;
+
+public class SmallExtAngleTest {
+
+    public static void main(String[] args) {
+
+        String errorMsg = "NaN occured in coordinates of SEG_CUBICTO";
+        Rectangle2D bounds = new Rectangle2D.Double(-100, -100, 200, 200);
+        Arc2D arc = new Arc2D.Double(bounds, 90, -1.0E-7, Arc2D.PIE);
+        double[] coords = new double[6];
+
+        PathIterator p = arc.getPathIterator(null);
+        while (!p.isDone()) {
+
+            if (p.currentSegment(coords) == PathIterator.SEG_CUBICTO) {
+
+                for (int i = 0; i < 6; i++) {
+                    if (coords[i] != coords[i]) {
+                        throw new RuntimeException(errorMsg);
+                    }
+                }
+            }
+            p.next();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Area/ArcSubtractEllipseBug.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6356485
+ * @summary Checks that subtracting a particular ellipse from an Arc
+ *          does not cause an InternalError to be thrown.
+ */
+import java.awt.geom.Arc2D;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+
+public class ArcSubtractEllipseBug {
+    public static void main(String[] args) {
+        double x = -4.250000000000002;
+        double y = 0.0;
+        double width = 8.5;
+        double height = 8.5;
+        double start = -450.0;
+        double extent = 180.0;
+
+        Arc2D outerArc = new Arc2D.Double(x, y, width, height,
+                                          start, extent, Arc2D.PIE);
+
+        Area tmp = new Area(outerArc);
+
+        x = -4.000000000000002;
+        y = 0.25;
+        width = 8.0;
+        height = 8.0;
+
+        Ellipse2D innerArc = new Ellipse2D.Double(x, y, width, height);
+
+        tmp.subtract(new Area(innerArc));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Area/AreaNaNBug.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6398602
+ * @summary Checks that problems finding the roots of curves does not
+ *          cause the Area class to end up with NaN coordinates after
+ *          being constructed from an otherwise normal and unremarkable
+ *          path.
+ */
+
+import java.awt.geom.Area;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Rectangle2D;
+
+public class AreaNaNBug {
+    public static void main(String argv[]) {
+        GeneralPath gp = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
+        gp.moveTo(-38.05311f, 75.25694f);
+        gp.curveTo(-48.18971f, 71.23722f,
+                   -46.495422f, -113.844574f,
+                   124.16219f, 87.604744f);
+        gp.quadTo(105.644554f, 114.52495f,
+                  72.98282f, -78.52084f);
+        gp.lineTo(107.358795f, 29.33548f);
+        gp.quadTo(-16.562698f, -43.91586f,
+                  51.50203f, 38.51295f);
+        gp.lineTo(20.715876f, 44.4093f);
+        gp.closePath();
+        Area a = new Area(gp);
+        Rectangle2D r2d = a.getBounds2D();
+        if (Double.isNaN(r2d.getX()) ||
+            Double.isNaN(r2d.getY()) ||
+            Double.isNaN(r2d.getWidth()) ||
+            Double.isNaN(r2d.getHeight()))
+        {
+            throw new RuntimeException("Area bounds have NaN");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Area/AreaTransformTest.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6385010
+ * @summary Checks that transform does not fail with exception
+ */
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+import java.awt.geom.GeneralPath;
+
+/* Minimized testcase from bug report */
+
+public class AreaTransformTest {
+
+    public static void main(String[] args) {
+        AffineTransform t = AffineTransform.getRotateInstance(Math.PI/8);
+        GeneralPath path = new GeneralPath();
+
+        path.moveTo(-4516.23223633003f,10983.71557514126f);
+        path.lineTo(-1451.4908513919768f, 13100.559659959084f);
+        path.quadTo(-54.38163118565376f, 13679.261247085042f,
+                    1470.6331984752403f, 13679.261247085042f);
+        path.closePath();
+
+        Area area = new Area(path);
+
+        for (int i = 0; i < 8; i++) {
+            area.transform(t);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Area/BoundsCache.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4188529 4240423
+ * @summary Verifies that the Area methods do not cache the bounds
+ *          across operations.
+ */
+
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+
+public class BoundsCache {
+
+    public static void main(String s[]) {
+        Ellipse2D cir = new Ellipse2D.Double(110.0,100.0, 50.0, 50.0);
+        Ellipse2D cir2 = new Ellipse2D.Double(110.0,100.0, 50.0, 50.0);
+        Area area_cir = new Area (cir);
+
+        System.out.println("before operation (bounds should be non-empty):");
+        System.out.println("   bounds are "+area_cir.getBounds());
+        System.out.println("   2D bounds are "+area_cir.getBounds2D());
+        System.out.println("   isEmpty returns "+area_cir.isEmpty());
+        area_cir.subtract(new Area (cir2));
+        System.out.println("after operation (bounds should be empty):");
+        System.out.println("   bounds are "+area_cir.getBounds());
+        System.out.println("   2D bounds are "+area_cir.getBounds2D());
+        System.out.println("   isEmpty returns "+area_cir.isEmpty());
+        if (!area_cir.isEmpty() ||
+            !area_cir.getBounds().isEmpty() ||
+            !area_cir.getBounds2D().isEmpty())
+        {
+            throw new RuntimeException("result was not empty!");
+        }
+
+        Area area = new Area(cir);
+        area.getBounds();
+        area.reset();
+        if (!area.getBounds().isEmpty()) {
+            throw new RuntimeException("result was not empty!");
+        }
+
+        area = new Area(cir);
+        Rectangle r = area.getBounds();
+        area.transform(new AffineTransform(1, 0, 0, 1, 10, 0));
+        if (area.getBounds().equals(r)) {
+            throw new RuntimeException("bounds not updated in transform!");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Area/EqualsNull.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4245905
+ * @summary Verifies that the Area.equals(null) returns false
+ */
+
+import java.awt.geom.Area;
+
+public class EqualsNull {
+    public static void main(String argv[]) {
+        if (new Area().equals(null)) {
+            throw new RuntimeException("Area object equaled null");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Area/NPETests.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6304542
+ * @summary Verifies that various Area methods throw NPE for null arguments
+ */
+
+import java.awt.geom.Area;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+public class NPETests {
+    static boolean verbose;
+    static int numfailures = 0;
+
+    public static void main(String argv[]) {
+        verbose = (argv.length > 0);
+        test(new Runnable() {
+            public void run() { new Area(null); }
+        });
+        test(new Runnable() {
+            public void run() { new Area().add(null); }
+        });
+        test(new Runnable() {
+            public void run() { new Area().subtract(null); }
+        });
+        test(new Runnable() {
+            public void run() { new Area().intersect(null); }
+        });
+        test(new Runnable() {
+            public void run() { new Area().exclusiveOr(null); }
+        });
+        test(new Runnable() {
+            public void run() { new Area().transform(null); }
+        });
+        test(new Runnable() {
+            public void run() { new Area().createTransformedArea(null); }
+        });
+        test(new Runnable() {
+            public void run() { new Area().contains((Point2D) null); }
+        });
+        test(new Runnable() {
+            public void run() { new Area().contains((Rectangle2D) null); }
+        });
+        test(new Runnable() {
+            public void run() { new Area().intersects((Rectangle2D) null); }
+        });
+        if (numfailures > 0) {
+            throw new RuntimeException(numfailures+
+                                       " methods failed to throw NPE");
+        }
+    }
+
+    public static void test(Runnable r) {
+        try {
+            r.run();
+            numfailures++;
+            if (verbose) {
+                new RuntimeException(r+" failed to throw NPE")
+                    .printStackTrace();
+            }
+        } catch (NullPointerException e) {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Area/PolygonAdd.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4286894
+ * @summary Verifies that a particular case of Polygon addition
+ *          correctly calculates the ordering of the Polygon edges.
+ */
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+
+public class PolygonAdd {
+    public static void main(String argv[]) {
+        // Original shapes: 4 touching rectangles
+        // (area works correctly with them if not transformed)
+        Shape b = new Rectangle(0,0,100,10);
+        Shape t = new Rectangle(0,90,100,10);
+        Shape l = new Rectangle(0,10,10,80);
+        Shape r = new Rectangle(90,10,10,80);
+
+        // Create a transform to rotate them by 10 degrees
+        AffineTransform M = new AffineTransform();
+        M.translate(-50,-50);
+        M.scale(3,3);
+        M.rotate(Math.toRadians(10));
+        M.translate(70,40);
+
+        Area area = new Area();
+        area.add(new Area(M.createTransformedShape(b)));
+        area.add(new Area(M.createTransformedShape(l)));
+        area.add(new Area(M.createTransformedShape(t)));
+        area.add(new Area(M.createTransformedShape(r)));
+
+        if (!area.contains(295, 145, 5, 5)) {
+            throw new RuntimeException("Area addition failed!");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Area/PolygonSubtract.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4217589
+ * @summary Verifies that a particular case of Polygon subtraction
+ *          correctly calculates the ordering of the Polygon edges.
+ */
+
+import java.awt.geom.Area;
+import java.awt.geom.GeneralPath;
+
+public class PolygonSubtract {
+    public static void main(String argv[]) {
+        Area area = new Area();
+
+        GeneralPath ring1 = new GeneralPath();
+
+        ring1.moveTo(0, 45);
+        ring1.lineTo(90, 0);
+        ring1.lineTo(60, -45);
+        ring1.lineTo(-60, -45);
+        ring1.lineTo(-90, 0);
+
+        ring1.closePath();
+
+        area.add(new Area(ring1));
+
+        GeneralPath ring2 = new GeneralPath();
+
+        ring2.moveTo(0, 20);
+        ring2.lineTo(100, 0);
+        ring2.lineTo(30, -20);
+        ring2.lineTo(-30, -20);
+        ring2.lineTo(-100, 0);
+        ring2.closePath();
+
+        area.subtract(new Area(ring2));
+
+        if (!area.contains(50, 13, 2, 2)) {
+            throw new RuntimeException("Area subtraction failed!");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Area/QuadCurveOOMBug.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6372340
+ * @summary Checks for infinite loop and OOM bugs dealing with Quad curves.
+ * @run main/timeout=20/othervm QuadCurveOOMBug
+ */
+
+import java.awt.Shape;
+import java.awt.geom.Area;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.PathIterator;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class QuadCurveOOMBug {
+    public static final String SEG_CLOSE = " SEG_CLOSE";
+    public static final String SEG_CUBICTO = " SEG_CUBICTO";
+    public static final String SEG_LINETO = " SEG_LINETO";
+    public static final String SEG_MOVETO = " SEG_MOVETO";
+    public static final String SEG_QUADTO = " SEG_QUADTO";
+
+    public static final byte[] strokedLineToSubtract = {
+        0,  11,  32,  83,  69,  71,  95,  77,  79,  86,
+        69,  84,  79,  68,  117,  7,  -63,  67,  15,  6,
+        87,  0,  11,  32,  83,  69,  71,  95,  76,  73,
+        78,  69,  84,  79,  68,  117,  31,  16,  67,  15,
+        23,  5,  0,  11,  32,  83,  69,  71,  95,  81,
+        85,  65,  68,  84,  79,  68,  117,  68,  -12,  67,
+        15,  50,  54,  68,  117,  103,  16,  67,  15,  50,
+        59,  0,  11,  32,  83,  69,  71,  95,  76,  73,
+        78,  69,  84,  79,  68,  117,  110,  14,  67,  15,
+        50,  59,  0,  11,  32,  83,  69,  71,  95,  81,
+        85,  65,  68,  84,  79,  68,  117,  -56,  26,  67,
+        15,  48,  -15,  68,  118,  22,  75,  67,  14,  112,
+        95,  0,  11,  32,  83,  69,  71,  95,  81,  85,
+        65,  68,  84,  79,  68,  118,  61,  115,  67,  14,
+        15,  10,  68,  118,  94,  93,  67,  13,  127,  -74,
+        0,  11,  32,  83,  69,  71,  95,  76,  73,  78,
+        69,  84,  79,  68,  118,  103,  -80,  67,  13,  87,
+        15,  0,  11,  32,  83,  69,  71,  95,  81,  85,
+        65,  68,  84,  79,  68,  118,  21,  -76,  67,  14,
+        -81,  -105,  68,  117,  -100,  -84,  67,  14,  -72,  72,
+        0,  11,  32,  83,  69,  71,  95,  76,  73,  78,
+        69,  84,  79,  68,  117,  -88,  84,  67,  14,  -72,
+        72,  0,  11,  32,  83,  69,  71,  95,  81,  85,
+        65,  68,  84,  79,  68,  117,  108,  85,  67,  14,
+        -73,  106,  68,  117,  53,  117,  67,  14,  74,
+        -61,  0,  11,  32,  83,  69,  71,  95,  76,  73,  78,
+        69,  84,  79,  68,  117,  72,  27,  67,  14,  112,
+        14,  0,  11,  32,  83,  69,  71,  95,  76,  73,
+        78,  69,  84,  79,  68,  118,  87,  -51,  67,  5,
+        -16,  100,  0,  11,  32,  83,  69,  71,  95,  76,
+        73,  78,  69,  84,  79,  68,  118,  69,  39,  67,
+        5,  -53,  25,  0,  11,  32,  83,  69,  71,  95,
+        81,  85,  65,  68,  84,  79,  68,  117,  -5,  -93,
+        67,  5,  57,  38,  68,  117,  -88,  84,  67,  5,
+        56,  72,  0,  11,  32,  83,  69,  71,  95,  76,
+        73,  78,  69,  84,  79,  68,  117,  -100,  -84,  67,
+        5,  56,  72,  0,  11,  32,  83,  69,  71,  95,
+        81,  85,  65,  68,  84,  79,  68,  117,  12,  86,
+        67,  5,  64,  -7,  68,  116,  -89,  -76,  67,
+        6,  -22,  -51,  0,  11,  32,  83,  69,  71,  95,  76,
+        73,  78,  69,  84,  79,  68,  116,  -98,  97,  67,
+        7,  19,  116,  0,  11,  32,  83,  69,  71,  95,
+        81,  85,  65,  68,  84,  79,  68,  116,  -75,  -100,
+        67,  6,  -83,  -7,  68,  116,  -44,  -9,  67,  6,
+        95,  -59,  0,  11,  32,  83,  69,  71,  95,  81,
+        85,  65,  68,  84,  79,  68,  117,  26,  -119,  67,
+        5,  -76,  14,  68,  117,  110,  14,  67,  5,  -78,
+        59,  0,  11,  32,  83,  69,  71,  95,  76,  73,
+        78,  69,  84,  79,  68,  117,  103,  16,  67,  5,
+        -78,  59,  0,  11,  32,  83,  69,  71,  95,  81,
+        85,  65,  68,  84,  79,  68,  117,  122,  -71,  67,
+        5,  -78,  22,  68,  117,  -119,  -60,  67,  5,  -68,
+        -61,  0,  11,  32,  83,  69,  71,  95,  76,  73,
+        78,  69,  84,  79,  68,  117,  114,  117,  67,  5,
+        -84,  21,  0,  11,  32,  83,  69,  71,  95,  76,
+        73,  78,  69,  84,  79,  68,  117,  7,  -63,  67,
+        15,  6,  87,  0,  10,  32,  83,  69,  71,  95,
+        67,  76,  79,  83,  69,
+    };
+
+    public static final byte[] negSpace = {
+        0,  11,  32,  83,  69,  71,  95,  77,  79,  86,
+        69,  84,  79,  68,  116,  -33,  -12,  67,  4,  30,
+        -23,  0,  11,  32,  83,  69,  71,  95,  76,  73,
+        78,  69,  84,  79,  68,  118,  59,  73,  67,  6,
+        -43,  -109,  0,  11,  32,  83,  69,  71,  95,  76,
+        73,  78,  69,  84,  79,  68,  117,  100,  -97,  67,
+        13,  -118,  -32,  0,  11,  32,  83,  69,  71,  95,
+        76,  73,  78,  69,  84,  79,  68,  116,  9,  75,
+        67,  10,  -44,  54,  0,  10,  32,  83,  69,  71,
+        95,  67,  76,  79,  83,  69,
+    };
+
+    public static final byte[] strokedLineToAdd = {
+        0,  11,  32,  83,  69,  71,  95,  77,  79,  86,
+        69,  84,  79,  68,  98,  -100,  -76,  67,  -85,  -36,
+        6,  0,  11,  32,  83,  69,  71,  95,  76,  73,
+        78,  69,  84,  79,  68,  98,  -76,  4,  67,  -85,
+        -48,  21,  0,  11,  32,  83,  69,  71,  95,  81,
+        85,  65,  68,  84,  79,  68,  98,  -102,  -29,  67,
+        -85,  -36,  -5,  68,  98,  -112,  107,  67,  -85,
+        -35,  5,  0,  11,  32,  83,  69,  71,  95,  76,  73,
+        78,  69,  84,  79,  68,  98,  -84,  99,  67,  -85,
+        -35,  5,  0,  11,  32,  83,  69,  71,  95,  81,
+        85,  65,  68,  84,  79,  68,  98,  -87,  1,  67,
+        -85,  -35,  1,  68,  98,  -107,  -10,  67,  -85,  -43,
+        23,  0,  11,  32,  83,  69,  71,  95,  76,  73,
+        78,  69,  84,  79,  68,  98,  -95,  -98,  67,  -85,
+        -39,  -11,  0,  11,  32,  83,  69,  71,  95,  81,
+        85,  65,  68,  84,  79,  68,  98,  -53,  -8,  67,
+        -85,  -21,  -99,  68,  98,  -10,  -6,  67,  -85,
+        -21,  -95,  0,  11,  32,  83,  69,  71,  95,  76,  73,
+        78,  69,  84,  79,  68,  99,  2,  -94,  67,  -85,
+        -21,  -95,  0,  11,  32,  83,  69,  71,  95,  81,
+        85,  65,  68,  84,  79,  68,  98,  -56,  -104, 67,
+        -85,  -21,  61,  68,  98,  -109,  28,  67,  -85,  -73,
+        -35,  0,  11,  32,  83,  69,  71,  95,  76,  73,
+        78,  69,  84,  79,  68,  98,  -91,  -62,  67,  -85,
+        -55,  -22,  0,  11,  32,  83,  69,  71,  95,  76,
+        73,  78,  69,  84,  79,  68,  99,  -82,  -62,  67,
+        -89,  -125,  126,  0,  11,  32,  83,  69,  71,  95,
+        76,  73,  78,  69,  84,  79,  68,  99,  -100,  28,
+        67,  -89,  113,  113,  0,  11,  32,  83,  69,  71,
+        95,  81,  85,  65,  68,  84,  79,  68,  99,  83,
+        -6,  67,  -89,  44,  5,  68,  99,  2,  -94,  67,
+        -89,  43,  -95,  0,  11,  32,  83,  69,  71,  95,
+        76,  73,  78,  69,  84,  79,  68,  98,  -10,  -6,
+        67,  -89,  43,  -95,  0,  11,  32,  83,  69,  71,
+        95,  81,  85,  65,  68,  84,  79,  68,  99,  10,
+        -82,  67,  -89,  43,  -91,  68,  99,  29,  -72,  67,
+        -89,  51,  -113,  0,  11,  32,  83,  69,  71,  95,
+        76,  73,  78,  69,  84,  79,  68,  99,  18,  16,
+        67,  -89,  46,  -79,  0,  11,  32,  83,  69,  71,
+        95,  81,  85,  65,  68,  84,  79,  68,  98,  -25,
+        -73,  67,  -89,  29,  9,  68,  98,  -84,  99,  67,
+        -89,  29,  5,  0,  11,  32,  83,  69,  71,  95,
+        76,  73,  78,  69,  84,  79,  68,  98,  -112,  107,
+        67,  -89,  29,  5,  0,  11,  32,  83,  69,  71,
+        95,  81,  85,  65,  68,  84,  79,  68,  98,  78,
+        121,  67,  -89,  28,  -15,  68,  98,  29,  -110,  67,
+        -89,  53,  -27,  0,  11,  32,  83,  69,  71,  95,
+        76,  73,  78,  69,  84,  79,  68,  98,  6,  66,
+        67,  -89,  65,  -42,  0,  11,  32,  83,  69,  71,
+        95,  76,  73,  78,  69,  84,  79,  68,  98,  -100,
+        -76,  67,  -85,  -36,  6,  0,  10,  32,  83,  69,
+        71,  95,  67,  76,  79,  83,  69,
+    };
+
+    public static final byte[] shapeAdded = {
+        0,  11,  32,  83,  69,  71,  95,  77,  79,  86,
+        69,  84,  79,  68,  102,  54,  -63,  67,  -84,  -102,
+        29,  0,  11,  32,  83,  69,  71,  95,  76,  73,  78,
+        69,  84,  79,  68,  96,  -120,  114,  67,  -94,
+        2,  48,  0,  11,  32,  83,  69,  71,  95,  76,  73,
+        78,  69,  84,  79,  68,  94,  -119,  0,  67,
+        -86,  67,  -25,  0,  10,  32,  83,  69,  71,  95,
+        67,  76,  79,  83,  69,
+    };
+
+    public static void main(String[] args) {
+        // Reversing the order of these try blocks has no effect.
+        try {
+            testAdd();
+        } catch (IOException ioe) {
+            ioe.printStackTrace();
+        }
+
+        try {
+            testSubtract();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private static void testSubtract() throws IOException
+    {
+        Shape lineShape = loadShape(strokedLineToSubtract, "Line");
+        Shape negShape = loadShape(negSpace, "Space");
+        Area lineArea = new Area(lineShape);
+        Area negArea = new Area(negShape);
+        System.err.println("Attempting to subtract ... ");
+        lineArea.subtract(negArea); // This is what throws the OutOfMemoryError
+        System.err.println("Subtraction succeeded.");
+    }
+
+    private static void testAdd() throws IOException
+    {
+        Shape lineShape = loadShape(strokedLineToAdd, "Line");
+        Shape negShape = loadShape(shapeAdded, "Space");
+        Area lineArea = new Area(lineShape);
+        Area negArea = new Area(negShape);
+        System.err.println("Attempting to add ... ");
+        lineArea.add(negArea); // This is what throws the OutOfMemoryError
+        System.err.println("Addition succeeded.");
+    }
+
+    /**
+     * Although this method isn't used by this test case, this is the method
+     * used to create the two data sets that the test case uses.
+     * @param name The name to give to the variable
+     * @param shape
+     */
+    public static void saveShapeData(Shape shape, String name)
+    {
+        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+        DataOutputStream os = new DataOutputStream(byteStream);
+        try {
+            saveShapeToStream(shape, os);
+            System.out.println("\npublic static final byte[] " +
+                               name + " = {\n");
+            byte[] data = byteStream.toByteArray();
+            int ii=0;
+            for (byte bt : data)
+                System.out.print("  " + Byte.toString(bt) + "," +
+                                 ((++ii)%20==0? "\n":""));
+            System.out.println("};");
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private static void saveShapeToStream(Shape shape, DataOutputStream pOs)
+        throws IOException
+    {
+        PathIterator iter = shape.getPathIterator(null);
+        float[] coords = new float[6];
+        while(!iter.isDone()) {
+            int type = iter.currentSegment(coords);
+            switch(type) {
+            case PathIterator.SEG_CLOSE:
+                pOs.writeUTF(SEG_CLOSE);
+                break;
+            case PathIterator.SEG_CUBICTO:
+                pOs.writeUTF(SEG_CUBICTO);
+                for (float coord : coords)
+                    pOs.writeFloat(coord);
+                break;
+            case PathIterator.SEG_LINETO:
+                pOs.writeUTF(SEG_LINETO);
+                pOs.writeFloat(coords[0]);
+                pOs.writeFloat(coords[1]);
+                break;
+            case PathIterator.SEG_MOVETO:
+                pOs.writeUTF(SEG_MOVETO);
+                pOs.writeFloat(coords[0]);
+                pOs.writeFloat(coords[1]);
+                break;
+            case PathIterator.SEG_QUADTO:
+                pOs.writeUTF(SEG_QUADTO);
+                for (int ii=0; ii<4; ++ii)
+                    pOs.writeFloat(coords[ii]);
+                break;
+            default:
+                System.err.print(" UNKNOWN:" + type);
+                break;
+            }
+            iter.next();
+        }
+    }
+
+
+    public static Shape loadShape(byte[] fileData, String name)
+        throws IOException
+    {
+        System.out.println("\n\n" + name + ":");
+        GeneralPath path = new GeneralPath();
+        path.setWindingRule(GeneralPath.WIND_NON_ZERO);
+        DataInputStream is=null;
+        is = new DataInputStream(new ByteArrayInputStream(fileData));
+        float[] coords = new float[6];
+        while (is.available()>0)
+        {
+            String type = is.readUTF();
+            System.out.print("\n" + type + "\n   ");
+            if (type.equals(SEG_CLOSE)) {
+                path.closePath();
+            } else if (type.equals(SEG_CUBICTO)) {
+                for (int ii=0; ii<6; ++ii)
+                    coords[ii] = readFloat(is);
+                path.curveTo(coords[0], coords[1],
+                             coords[2], coords[3],
+                             coords[4], coords[5]);
+            } else if (type.equals(SEG_LINETO)) {
+                for (int ii=0; ii<2; ++ii)
+                    coords[ii] = readFloat(is);
+                path.lineTo(coords[0], coords[1]);
+            } else if (type.equals(SEG_MOVETO)) {
+                for (int ii=0; ii<2; ++ii)
+                    coords[ii] = readFloat(is);
+                path.moveTo(coords[0], coords[1]);
+            } else if (type.equals(SEG_QUADTO)) {
+                for (int ii=0; ii<4; ++ii)
+                    coords[ii] = readFloat(is);
+                path.quadTo(coords[0], coords[1], coords[2], coords[3]);
+            }
+        }
+        return path;
+    }
+
+    /**
+     * This call reads all the float values and prints them out.
+     * @param is
+     * @return
+     * @throws IOException
+     */
+    private static float readFloat(DataInputStream is) throws IOException
+    {
+        float ft = is.readFloat();
+        System.out.print("" + ft + ", ");
+        return ft;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Area/TightBBox.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4276812
+ * @summary Verifies that the Area.getBounds2D() method returns a very tight
+ *          bounding box
+ */
+
+import java.awt.geom.Area;
+import java.awt.geom.CubicCurve2D;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+import java.awt.geom.QuadCurve2D;
+import java.awt.geom.Rectangle2D;
+
+public class TightBBox {
+    public static void main(String argv[]) {
+        Point2D points[] = {
+            new Point2D.Double(0.0, 0.0),
+            new Point2D.Double(1.0, 0.0),
+            new Point2D.Double(1.0, 1.0),
+            new Point2D.Double(0.0, 1.0),
+        };
+        for (int i = 0; i < 4; i++) {
+            testCubic(points);
+            testQuad(points);
+            testLines(points);
+            rotate(points);
+        }
+    }
+
+    public static void testCubic(Point2D points[]) {
+        CubicCurve2D cubic =
+            new CubicCurve2D.Double(points[0].getX(), points[0].getY(),
+                                    points[1].getX(), points[1].getY(),
+                                    points[2].getX(), points[2].getY(),
+                                    points[3].getX(), points[3].getY());
+        Area a = new Area(cubic);
+        if (!cubic.getBounds2D().contains(a.getBounds2D())) {
+            throw new RuntimeException("Area bbox is larger than cubic");
+        }
+        double x = (points[0].getX() +
+                    (points[1].getX() + points[2].getX()) * 3.0 +
+                    points[3].getX()) / 8.0;
+        double y = (points[0].getY() +
+                    (points[1].getY() + points[2].getY()) * 3.0 +
+                    points[3].getY()) / 8.0;
+        Rectangle2D r =
+            new Rectangle2D.Double(points[0].getX(), points[0].getY(), 0, 0);
+        r.add(points[3].getX(), points[3].getY());
+        r.add(x, y);
+        checkBox(r, a.getBounds2D());
+    }
+
+    public static void testQuad(Point2D points[]) {
+        QuadCurve2D quad =
+            new QuadCurve2D.Double(points[0].getX(), points[0].getY(),
+                                   (points[1].getX() + points[2].getX()) / 2.0,
+                                   (points[1].getY() + points[2].getY()) / 2.0,
+                                   points[3].getX(), points[3].getY());
+        Area a = new Area(quad);
+        if (!quad.getBounds2D().contains(a.getBounds2D())) {
+            throw new RuntimeException("Area bbox is larger than quad");
+        }
+        // p0 + 2cp + p1 == p0 + 2(cp0+cp1)/2 + p1 == p0 + cp0 + cp1 + p1
+        double x = (points[0].getX() +
+                    points[1].getX() + points[2].getX() +
+                    points[3].getX()) / 4.0;
+        double y = (points[0].getY() +
+                    points[1].getY() + points[2].getY() +
+                    points[3].getY()) / 4.0;
+        Rectangle2D r =
+            new Rectangle2D.Double(points[0].getX(), points[0].getY(), 0, 0);
+        r.add(points[3].getX(), points[3].getY());
+        r.add(x, y);
+        checkBox(r, a.getBounds2D());
+    }
+
+    public static void testLines(Point2D points[]) {
+        GeneralPath gp = new GeneralPath();
+        gp.moveTo((float) points[0].getX(), (float) points[0].getY());
+        gp.lineTo((float) points[2].getX(), (float) points[2].getY());
+        gp.lineTo((float) points[1].getX(), (float) points[1].getY());
+        gp.lineTo((float) points[3].getX(), (float) points[3].getY());
+        gp.closePath();
+        Area a = new Area(gp);
+        if (!gp.getBounds2D().contains(a.getBounds2D())) {
+            throw new RuntimeException("Area bbox is larger than poly");
+        }
+        Rectangle2D r =
+            new Rectangle2D.Double(points[3].getX(), points[3].getY(), 0, 0);
+        for (int i = 0; i < 3; i++) {
+            r.add(points[i].getX(), points[i].getY());
+        }
+        checkBox(r, a.getBounds2D());
+    }
+
+    public static void checkBox(Rectangle2D r1, Rectangle2D r2) {
+        checkVal(r1.getMinX(), r2.getMinX());
+        checkVal(r1.getMinY(), r2.getMinY());
+        checkVal(r2.getMaxX(), r1.getMaxX());
+        checkVal(r2.getMaxY(), r1.getMaxY());
+    }
+
+    /*
+     * v1 and v2 should be roughly equal.  The amount of computation
+     * involved in calculating bounding boxes is complex enough that
+     * you might expect the values to be slightly off and this should
+     * perhaps be a loose comparison, but our runtime seems to produce
+     * values that are exactly equal (even with double arithmetic),
+     * so this test will enforce exact equality for now.
+     */
+    public static void checkVal(double v1, double v2) {
+        if (v1 != v2) {
+            throw new RuntimeException("bounding box not minimal");
+        }
+    }
+
+    public static void rotate(Point2D[] points) {
+        Point2D p = points[0];
+        System.arraycopy(points, 1, points, 0, 3);
+        points[3] = p;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Area/TransformPrecision.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4632108
+ * @summary Verifies that the Area transform methods maintain double precision
+ */
+
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+
+public class TransformPrecision {
+    public static void main(String argv[]) {
+        int x = 1 << 27;
+        int y = 1 << 26;
+
+        AffineTransform tx = AffineTransform.getTranslateInstance(x, y);
+        AffineTransform untx = AffineTransform.getTranslateInstance(-x, -y);
+
+        Rectangle r = new Rectangle(10, 10, 20, 20);
+        Area a = new Area(r);
+
+        Area b = new Area(r);
+        b.transform(tx);
+        b.transform(untx);
+        if (!a.equals(b)) {
+            throw new RuntimeException("large translation hurt precision!");
+        }
+
+        b = a.createTransformedArea(tx);
+        b = b.createTransformedArea(untx);
+        if (!a.equals(b)) {
+            throw new RuntimeException("large translation hurt precision!");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/CubicCurve2D/ContainsHang.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4246661
+ * @summary Verifies that the CubicCurve2D.contains method does not hang
+ * @run main/timeout=5 ContainsHang
+ */
+
+import java.awt.geom.CubicCurve2D;
+
+public class ContainsHang {
+    public static void main(String args[]) {
+        CubicCurve2D curve =
+            new CubicCurve2D.Double(83.0, 101.0,
+                                    -5.3919918959078075, 94.23530547506019,
+                                    71.0, 39.0,
+                                    122.0, 44.0);
+
+        System.out.println("Checking contains() >>>");
+        curve.contains(71.0, 44.0);
+        System.out.println("Check complete!!");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/CubicCurve2D/ContainsPoint.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6396047
+ * @summary tests the CubicCurve2D.contains(x, y) method
+ */
+
+import java.awt.geom.CubicCurve2D;
+
+public class ContainsPoint {
+    public static void main(String args[]) {
+        CubicCurve2D curve =
+            new CubicCurve2D.Double(100.0, 100.0,
+                                    200.0, 100.0,
+                                    200.0, 200.0,
+                                    100.0, 200.0);
+        if (curve.contains(0.0, 100.0)) {
+            throw new RuntimeException("contains point clearly "+
+                                       "outside of curve");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/EqualsHashcode.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,475 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6210287
+ * @summary Verifies that the various utility shapes implement
+ *          the equals(Object) and hashCode methods adequately
+ */
+
+import java.awt.geom.Arc2D;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import java.util.Vector;
+
+public class EqualsHashcode {
+    public static final int NUMTESTS = 1000;
+
+    public static void main(String argv[]) {
+        new FloatRectangleTester().test();
+        new DoubleRectangleTester().test();
+
+        new FloatEllipseTester().test();
+        new DoubleEllipseTester().test();
+
+        new FloatArcTester().test();
+        new DoubleArcTester().test();
+
+        new FloatRoundRectTester().test();
+        new DoubleRoundRectTester().test();
+    }
+
+    /**
+     * Base utility class for random parameters for testing
+     */
+    public static abstract class Val {
+        protected String name;
+
+        protected Val(String name) {
+            this.name = name;
+        }
+
+        public abstract Object save();
+        public abstract void restore(Object save);
+
+        public abstract void randomize();
+        public abstract void perturb();
+    }
+
+    /**
+     * Base subclass for parameters with "special" values (Infinity, NaN, etc.)
+     */
+    public static abstract class SpecialVal extends Val {
+        protected SpecialVal(String name) {
+            super(name);
+        }
+
+        public abstract void setSpecial();
+
+        public abstract boolean isNaN();
+    }
+
+    /**
+     * Floating point parameter
+     */
+    public static class FloatVal extends SpecialVal {
+        private float v;
+
+        public FloatVal(String name) {
+            super(name);
+        }
+
+        public float getVal() {
+            return v;
+        }
+
+        public String toString() {
+            return name+" = "+v+" (flt)";
+        }
+
+        public Object save() {
+            return new Float(v);
+        }
+
+        public void restore(Object o) {
+            v = ((Float) o).floatValue();
+        }
+
+        public void randomize() {
+            v = (float) (Math.random() * 100);
+        }
+
+        public void perturb() {
+            v = v + 1;
+        }
+
+        public boolean hasSpecialCases() {
+            return true;
+        }
+
+        public void setSpecial() {
+            switch ((int) (Math.random() * 3)) {
+            case 0:
+                v = Float.NaN;
+                break;
+            case 1:
+                v = Float.POSITIVE_INFINITY;
+                break;
+            case 2:
+                v = Float.NEGATIVE_INFINITY;
+                break;
+            default:
+                throw new InternalError();
+            }
+        }
+
+        public boolean isNaN() {
+            return (v != v);
+        }
+    }
+
+    /**
+     * Double precision parameter
+     */
+    public static class DoubleVal extends SpecialVal {
+        private double v;
+
+        public DoubleVal(String name) {
+            super(name);
+        }
+
+        public double getVal() {
+            return v;
+        }
+
+        public String toString() {
+            return name+" = "+v+" (dbl)";
+        }
+
+        public Object save() {
+            return new Double(v);
+        }
+
+        public void restore(Object o) {
+            v = ((Double) o).doubleValue();
+        }
+
+        public void randomize() {
+            v = Math.random() * 100;
+        }
+
+        public void perturb() {
+            v = v + 1;
+        }
+
+        public boolean hasSpecialCases() {
+            return true;
+        }
+
+        public void setSpecial() {
+            switch ((int) (Math.random() * 3)) {
+            case 0:
+                v = Double.NaN;
+                break;
+            case 1:
+                v = Double.POSITIVE_INFINITY;
+                break;
+            case 2:
+                v = Double.NEGATIVE_INFINITY;
+                break;
+            default:
+                throw new InternalError();
+            }
+        }
+
+        public boolean isNaN() {
+            return (v != v);
+        }
+    }
+
+    /**
+     * Integer value with a specified min/max range.
+     */
+    public static class IntRangeVal extends Val {
+        public int v;
+        public int min;
+        public int max;
+
+        public IntRangeVal(String name, int min, int max) {
+            super(name);
+            this.min = min;
+            this.max = max;
+        }
+
+        public int getVal() {
+            return v;
+        }
+
+        public String toString() {
+            return name+" = "+v;
+        }
+
+        public Object save() {
+            return new Integer(v);
+        }
+
+        public void restore(Object o) {
+            v = ((Integer) o).intValue();
+        }
+
+        public void randomize() {
+            v = min + (int) (Math.random() * (max-min+1));
+        }
+
+        public void perturb() {
+            v = v + 1;
+            if (v > max) {
+                v = min;
+            }
+        }
+    }
+
+    /**
+     * Base class for testing a given type of shape.
+     * Subclasses must register all of their "parameters" which
+     * need to be randomized, specialized, and perturbed for
+     * testing.
+     * Subclasses must also implement makeShape() which makes
+     * a new shape object according to the current values of
+     * all of their parameters.
+     */
+    public static abstract class ShapeTester {
+        public Vector params = new Vector();
+
+        public void addParam(Val v) {
+            params.add(v);
+        }
+
+        public Val[] getParamArray() {
+            Val ret[] = new Val[params.size()];
+            for (int i = 0; i < params.size(); i++) {
+                ret[i] = (Val) params.get(i);
+            }
+            return ret;
+        }
+
+        public void error(String desc) {
+            Val params[] = getParamArray();
+            for (int j = 0; j < params.length; j++) {
+                System.err.println(params[j]);
+            }
+            throw new RuntimeException(desc);
+        }
+
+        public abstract Object makeShape();
+
+        public void test() {
+            Val params[] = getParamArray();
+            for (int i = 0; i < NUMTESTS; i++) {
+                // First, randomize all parameters
+                for (int j = 0; j < params.length; j++) {
+                    params[j].randomize();
+                }
+
+                // Now make 2 copies from the same params and verify equals()
+                Object o1 = makeShape();
+                if (!o1.equals(o1)) {
+                    error("Shapes not equal to itself!");
+                }
+                Object o2 = makeShape();
+                if (!o1.equals(o2)) {
+                    error("Identical shapes not equal!");
+                }
+                if (o1.hashCode() != o2.hashCode()) {
+                    error("Identical hashes not equal!");
+                }
+
+                // Now perturb the params 1 by 1 and verify !equals()
+                for (int j = 0; j < params.length; j++) {
+                    Val param = params[j];
+                    Object save = param.save();
+
+                    param.perturb();
+                    Object o3 = makeShape();
+                    if (o1.equals(o3)) {
+                        error("Perturbed shape still equal!");
+                    }
+
+                    // If param has "special values", test them as well
+                    if (param instanceof SpecialVal) {
+                        SpecialVal sparam = (SpecialVal) param;
+                        sparam.setSpecial();
+                        Object o4 = makeShape();
+                        if (o1.equals(o4)) {
+                            error("Specialized shape still equal!");
+                        }
+                        Object o5 = makeShape();
+                        // objects equal iff param is not a NaN
+                        if (o4.equals(o5) == sparam.isNaN()) {
+                            error("Identical specialized shapes not equal!");
+                        }
+                        // hash codes always equal, even if NaN
+                        // (Note: equals()/hashCode() contract allows this)
+                        if (o4.hashCode() != o5.hashCode()) {
+                            error("Identical specialized hashes not equal!");
+                        }
+                    }
+
+                    // Restore original value of param and make sure
+                    param.restore(save);
+                    Object o6 = makeShape();
+                    if (!o1.equals(o6)) {
+                        error("Restored shape not equal!");
+                    }
+                    if (o1.hashCode() != o6.hashCode()) {
+                        error("Restored hash not equal!");
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Base tester class for objects with floating point xywh bounds
+     */
+    public static abstract class FloatBoundedShape extends ShapeTester {
+        public FloatVal x = new FloatVal("x");
+        public FloatVal y = new FloatVal("y");
+        public FloatVal w = new FloatVal("w");
+        public FloatVal h = new FloatVal("h");
+
+        public FloatBoundedShape() {
+            addParam(x);
+            addParam(y);
+            addParam(w);
+            addParam(h);
+        }
+    }
+
+    /**
+     * Base tester class for objects with double precision xywh bounds
+     */
+    public static abstract class DoubleBoundedShape extends ShapeTester {
+        public DoubleVal x = new DoubleVal("x");
+        public DoubleVal y = new DoubleVal("y");
+        public DoubleVal w = new DoubleVal("w");
+        public DoubleVal h = new DoubleVal("h");
+
+        public DoubleBoundedShape() {
+            addParam(x);
+            addParam(y);
+            addParam(w);
+            addParam(h);
+        }
+    }
+
+    public static class FloatRectangleTester extends FloatBoundedShape {
+        public Object makeShape() {
+            return new Rectangle2D.Float(x.getVal(), y.getVal(),
+                                         w.getVal(), h.getVal());
+        }
+    }
+
+    public static class DoubleRectangleTester extends DoubleBoundedShape {
+        public Object makeShape() {
+            return new Rectangle2D.Double(x.getVal(), y.getVal(),
+                                          w.getVal(), h.getVal());
+        }
+    }
+
+    public static class FloatEllipseTester extends FloatBoundedShape {
+        public Object makeShape() {
+            return new Ellipse2D.Float(x.getVal(), y.getVal(),
+                                       w.getVal(), h.getVal());
+        }
+    }
+
+    public static class DoubleEllipseTester extends DoubleBoundedShape {
+        public Object makeShape() {
+            return new Ellipse2D.Double(x.getVal(), y.getVal(),
+                                        w.getVal(), h.getVal());
+        }
+    }
+
+    public static class FloatArcTester extends FloatBoundedShape {
+        public FloatVal start = new FloatVal("start");
+        public FloatVal extent = new FloatVal("extent");
+        public IntRangeVal type = new IntRangeVal("type", 0, 2);
+
+        public FloatArcTester() {
+            addParam(start);
+            addParam(extent);
+            addParam(type);
+        }
+
+        public Object makeShape() {
+            return new Arc2D.Float(x.getVal(), y.getVal(),
+                                   w.getVal(), h.getVal(),
+                                   start.getVal(), extent.getVal(),
+                                   type.getVal());
+        }
+    }
+
+    public static class DoubleArcTester extends DoubleBoundedShape {
+        public DoubleVal start = new DoubleVal("start");
+        public DoubleVal extent = new DoubleVal("extent");
+        public IntRangeVal type = new IntRangeVal("type", 0, 2);
+
+        public DoubleArcTester() {
+            addParam(start);
+            addParam(extent);
+            addParam(type);
+        }
+
+        public Object makeShape() {
+            return new Arc2D.Double(x.getVal(), y.getVal(),
+                                    w.getVal(), h.getVal(),
+                                    start.getVal(), extent.getVal(),
+                                    type.getVal());
+        }
+    }
+
+    public static class FloatRoundRectTester extends FloatBoundedShape {
+        public FloatVal arcw = new FloatVal("arcw");
+        public FloatVal arch = new FloatVal("arch");
+
+        public FloatRoundRectTester() {
+            addParam(arcw);
+            addParam(arch);
+        }
+
+        public Object makeShape() {
+            return new RoundRectangle2D.Float(x.getVal(), y.getVal(),
+                                              w.getVal(), h.getVal(),
+                                              arcw.getVal(), arch.getVal());
+        }
+    }
+
+    public static class DoubleRoundRectTester extends DoubleBoundedShape {
+        public DoubleVal arcw = new DoubleVal("arcw");
+        public DoubleVal arch = new DoubleVal("arch");
+
+        public DoubleRoundRectTester() {
+            addParam(arcw);
+            addParam(arch);
+        }
+
+        public Object makeShape() {
+            return new RoundRectangle2D.Double(x.getVal(), y.getVal(),
+                                               w.getVal(), h.getVal(),
+                                               arcw.getVal(), arch.getVal());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/GeneralPath/ContainsNaN.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6409478
+ * @summary Tests all hit testing methods of GeneralPath and Path2D
+ *          for graceful (i.e. non-infinite-loop) returns when any
+ *          of the path coordinates or test coordinates are
+ *          NaN or Infinite or even very large numbers.
+ * @run main/timeout=15 ContainsNaN
+ */
+
+import java.awt.geom.GeneralPath;
+
+public class ContainsNaN {
+    public static void main(String argv[]) {
+        GeneralPath gp = new GeneralPath();
+        gp.moveTo(0, 0);
+        gp.quadTo(100, 0, 100, 100);
+        gp.contains(Double.NaN, Double.NaN);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/GeneralPath/ContainsPoint.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6396047
+ * @summary tests the GeneralPath.contains(x, y) method
+ */
+
+import java.awt.geom.GeneralPath;
+
+public class ContainsPoint {
+    public static void main(String args[]) {
+        GeneralPath gp = new GeneralPath(GeneralPath.WIND_NON_ZERO);
+        gp.moveTo(46.69187927246094f, 95.8778305053711f);
+        gp.curveTo(-122.75305938720703f, 14.31462574005127f,
+                   66.84117889404297f, 26.061769485473633f,
+                   -62.62519073486328f, -13.041547775268555f);
+        gp.closePath();
+        if (gp.contains(-122.75305938720703, -13.041547775268555)) {
+            throw new RuntimeException("contains point clearly "+
+                                       "outside of curve");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/GeneralPath/CreateTxReturnsGP.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6404847
+ * @summary Tests that GeneralPath.createTransformedShape() returns
+ *          a GeneralPath object for backwards compatibility.
+ */
+
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.GeneralPath;
+
+public class CreateTxReturnsGP {
+    public static void main(String argv[]) {
+        GeneralPath gp = new GeneralPath();
+        gp.moveTo(0, 0);
+        gp.lineTo(10, 10);
+        Shape s1 = gp.createTransformedShape(null);
+        Shape s2 = gp.createTransformedShape(new AffineTransform());
+        if (!(s1 instanceof GeneralPath) || !(s2 instanceof GeneralPath)) {
+            throw new RuntimeException("GeneralPath.createTransformedShape() "+
+                                       "did not return a GeneralPath");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/GeneralPath/EmptyRectHitTest.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6284484
+ * @summary Verifies that GeneralPath objects do not "contain" or "intersect"
+ *          empty rectangles
+ */
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.GeneralPath;
+
+public class EmptyRectHitTest {
+    public static int numerrors;
+
+    public static void main(String argv[]) {
+        Rectangle select1 = new Rectangle(1, 1, 1, 1);
+        Rectangle select2 = new Rectangle(1, 1, 0, 0);
+        Rectangle select3 = new Rectangle(100, 100, 1, 1);
+        Rectangle select4 = new Rectangle(100, 100, 0, 0);
+
+        Rectangle rect = new Rectangle(-5, -5, 10, 10);
+        test(rect, select1, true,  true);
+        test(rect, select2, false, false);
+        test(rect, select3, false, false);
+        test(rect, select4, false, false);
+
+        GeneralPath gp = new GeneralPath(rect);
+        test(gp, select1, true,  true);
+        test(gp, select2, false, false);
+        test(gp, select3, false, false);
+        test(gp, select4, false, false);
+
+        AffineTransform xform = new AffineTransform();
+        xform.setToRotation(Math.PI / 4);
+        Shape shape = xform.createTransformedShape(rect);
+        test(shape, select1, true,  true);
+        test(shape, select2, false, false);
+        test(shape, select3, false, false);
+        test(shape, select4, false, false);
+
+        if (numerrors > 0) {
+            throw new RuntimeException(numerrors+" errors in tests");
+        }
+    }
+
+    public static void test(Shape testshape, Rectangle rect,
+                            boolean shouldcontain, boolean shouldintersect)
+    {
+        if (testshape.contains(rect) != shouldcontain) {
+            error(testshape, rect, "contains", !shouldcontain);
+        }
+        if (testshape.intersects(rect) != shouldintersect) {
+            error(testshape, rect, "intersects", !shouldintersect);
+        }
+    }
+
+    public static void error(Shape t, Rectangle r, String type, boolean res) {
+        numerrors++;
+        System.err.println(t+type+"("+r+") == "+res);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/GeneralPath/IntersectsRect.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6396047
+ * @summary tests the GeneralPath.intersects(x, y, w, h) method
+ */
+
+import java.awt.geom.GeneralPath;
+
+public class IntersectsRect {
+    public static void main(String args[]) {
+        GeneralPath gp = new GeneralPath(GeneralPath.WIND_NON_ZERO);
+        gp.moveTo(-12.820351600646973f, 22.158836364746094f);
+        gp.quadTo(-26.008909225463867f, 83.72308349609375f,
+                  84.20527648925781f, 13.218562126159668f);
+        gp.quadTo(107.0041275024414f, 38.3076171875f,
+                  -55.382022857666016f, -113.43235778808594f);
+        gp.lineTo(-43.795501708984375f, 52.847373962402344f);
+        gp.curveTo(37.72114944458008f, 70.46839141845703f,
+                   -26.205299377441406f, -103.99849700927734f,
+                   108.40007781982422f, 101.23545837402344f);
+        gp.closePath();
+
+        if (gp.intersects(34.614093600596874, 22.15252370704289,
+                          0.5, 0.5) != false)
+        {
+            throw new RuntimeException("intersects rect clearly "+
+                                       "outside of path");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Line2D/AALineTest.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 5089985
+ * @summary Test checks that drawing AA lines don't crash the VM
+ */
+
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.GeneralPath;
+import java.awt.image.BufferedImage;
+
+public class AALineTest {
+
+    /* Pairs of endpoints which cause VM crash */
+
+    public static int xBound [][] = {
+        {634,25,640,33},
+        {634,57,640,65},
+        {634,89,640,97},
+        {634,121,640,129},
+        {634,153,640,161},
+        {634,185,640,193},
+        {634,217,640,225},
+        {634,249,640,257},
+        {634,281,640,289},
+        {634,313,640,321},
+        {634,345,640,353},
+        {634,377,640,385},
+        {634,409,640,417},
+        {634,441,640,449}
+    };
+
+    public static int yBound [][] = {
+        {25, 634,33, 640},
+        {57, 634,65, 640},
+        {89, 634,97, 640},
+        {121,634,129,640},
+        {153,634,161,640},
+        {185,634,193,640},
+        {217,634,225,640},
+        {249,634,257,640},
+        {281,634,289,640},
+        {313,634,321,640},
+        {345,634,353,640},
+        {377,634,385,640},
+        {409,634,417,640},
+        {441,634,449,640}
+    };
+
+    public static void main(String[] args) {
+        BufferedImage image =
+            new BufferedImage(640, 480, BufferedImage.TYPE_INT_ARGB);
+
+        Graphics2D graphics = image.createGraphics();
+        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                                  RenderingHints.VALUE_ANTIALIAS_ON);
+
+        GeneralPath path = new GeneralPath();
+        for(int i=0; i < xBound.length; i++) {
+            path.reset();
+            path.moveTo(0, 0);
+            path.lineTo(xBound[i][0],xBound[i][1]);
+            path.lineTo(xBound[i][2],xBound[i][3]);
+            path.closePath();
+            graphics.draw(path);
+        }
+
+        image = new BufferedImage(480, 640, BufferedImage.TYPE_INT_ARGB);
+
+        graphics = image.createGraphics();
+        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                                  RenderingHints.VALUE_ANTIALIAS_ON);
+
+        for(int i=0; i < yBound.length; i++) {
+            path.reset();
+            path.moveTo(0, 0);
+            path.lineTo(yBound[i][0],yBound[i][1]);
+            path.lineTo(yBound[i][2],yBound[i][3]);
+            path.closePath();
+            graphics.draw(path);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Line2D/NegLineDistSqBug.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4335024
+ * @summary Verifies that the ptXXXDistSq methods return non-negative numbers
+ */
+
+import java.awt.geom.Line2D;
+
+public class NegLineDistSqBug {
+    static int errored;
+
+    public static void main (String[] args) {
+        // First a sanity check
+        test(1, 2, 3, 4, 15, 19, 21, 32);
+        // Next, the test numbers from bug report 4335024
+        test(-313.0, 241.0, -97.0, 75.0,
+             126.15362619253153, -96.49769420351959, -97.0, 75.0);
+        // Next test 100 points along the line from bug report 4335024
+        for (double fract = 0.0; fract <= 0.5; fract += 0.01) {
+            test(-313.0, 241.0, -97.0, 75.0,
+                 interp(-313.0, -97.0, fract), interp(241.0, 75.0, fract),
+                 interp(-313.0, -97.0, 1-fract), interp(241.0, 75.0, 1-fract));
+        }
+        if (errored > 0) {
+            throw new RuntimeException(errored+" negative distances!");
+        }
+    }
+
+    public static double interp(double v1, double v2, double t) {
+        return (v1 * (1-t) + v2 * t);
+    }
+
+    public static void test(double l1x1, double l1y1,
+                            double l1x2, double l1y2,
+                            double l2x1, double l2y1,
+                            double l2x2, double l2y2)
+    {
+        Line2D l1 = new Line2D.Double(l1x1, l1y1, l1x2, l1y2);
+        Line2D l2 = new Line2D.Double(l2x1, l2y1, l2x2, l2y2);
+        System.out.println("Line distances:");
+        verify(l1.ptLineDistSq(l2.getP1()));
+        verify(l1.ptLineDistSq(l2.getP2()));
+        System.out.println("Segment distances:");
+        verify(l1.ptSegDistSq(l2.getP1()));
+        verify(l1.ptSegDistSq(l2.getP2()));
+    }
+
+    public static void verify(double distSq) {
+        System.out.println(distSq);
+        if (distSq < 0) {
+            errored++;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Path2D/CreateTxReturnsSame.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6404847
+ * @summary Tests that Path2D.createTransformedShape() returns
+ *          the same kind of object as the source.
+ */
+
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Path2D;
+
+public class CreateTxReturnsSame {
+    public static void main(String argv[]) {
+        test(new GeneralPath());
+        test(new Path2D.Float());
+        test(new Path2D.Double());
+    }
+
+    public static void test(Path2D p2d) {
+        p2d.moveTo(0, 0);
+        p2d.lineTo(10, 10);
+        Shape s1 = p2d.createTransformedShape(null);
+        Shape s2 = p2d.createTransformedShape(new AffineTransform());
+        if (s1.getClass() != p2d.getClass() ||
+            s2.getClass() != p2d.getClass())
+        {
+            throw new RuntimeException(p2d.getClass().getName()+
+                                       ".createTransformedShape() "+
+                                       "did not return a "+
+                                       p2d.getClass().getName());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Path2D/NonFiniteTests.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6409478
+ * @summary Tests all hit testing methods of GeneralPath and Path2D
+ *          for graceful (i.e. non-infinite-loop) returns when any
+ *          of the path coordinates or test coordinates are
+ *          NaN or Infinite or even very large numbers.
+ * @run main/timeout=15 NonFiniteTests
+ */
+
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Path2D;
+import java.awt.geom.PathIterator;
+
+public class NonFiniteTests {
+    public static final double DBL_NaN = Double.NaN;
+    public static final double DBL_POS_INF = Double.POSITIVE_INFINITY;
+    public static final double DBL_NEG_INF = Double.NEGATIVE_INFINITY;
+    public static final double DBL_MAX = Double.MAX_VALUE;
+    public static final double DBL_MIN = -Double.MAX_VALUE;
+    public static final double FLT_MAX = Float.MAX_VALUE;
+    public static final double FLT_MIN = -Float.MAX_VALUE;
+
+    public static final int SEG_MOVETO = PathIterator.SEG_MOVETO;
+    public static final int SEG_LINETO = PathIterator.SEG_LINETO;
+    public static final int SEG_QUADTO = PathIterator.SEG_QUADTO;
+    public static final int SEG_CUBICTO = PathIterator.SEG_CUBICTO;
+    public static final int SEG_CLOSE = PathIterator.SEG_CLOSE;
+
+    public static int types[] = {
+        SEG_MOVETO,
+        SEG_LINETO,
+        SEG_QUADTO,
+        SEG_CUBICTO,
+        SEG_CLOSE,
+    };
+
+    public static double coords[] = {
+        // SEG_MOVETO coords
+          0.0,    0.0,
+
+        // SEG_LINETO coords
+         50.0,   10.0,
+
+        // SEG_QUADTO coords
+        100.0,   20.0,
+        100.0,  100.0,
+
+        // SEG_CUBICTO coords
+         50.0,  150.0,
+          0.0,  100.0,
+        -50.0,   50.0,
+
+        // SEG_CLOSE coords
+    };
+
+    public static double testpoints[] = {
+               -100,        -100,
+                  0,           0,
+                 50,          50,
+            DBL_NaN,     DBL_NaN,
+        DBL_POS_INF, DBL_POS_INF,
+        DBL_NEG_INF, DBL_NEG_INF,
+        DBL_POS_INF, DBL_NEG_INF,
+        DBL_NEG_INF, DBL_POS_INF,
+    };
+
+    public static double testrects[] = {
+               -100,        -100,          10,          10,
+                  0,           0,          10,          10,
+                 50,          50,          10,          10,
+            DBL_NaN,     DBL_NaN,          10,          10,
+                 10,          10,     DBL_NaN,     DBL_NaN,
+            DBL_NaN,     DBL_NaN,     DBL_NaN,     DBL_NaN,
+                 10,          10, DBL_POS_INF, DBL_POS_INF,
+                 10,          10, DBL_NEG_INF, DBL_NEG_INF,
+                 10,          10, DBL_POS_INF, DBL_NEG_INF,
+                 10,          10, DBL_NEG_INF, DBL_POS_INF,
+        DBL_NEG_INF, DBL_NEG_INF, DBL_POS_INF, DBL_POS_INF,
+        DBL_POS_INF, DBL_POS_INF,          10,          10,
+        DBL_NEG_INF, DBL_NEG_INF,          10,          10,
+        DBL_POS_INF, DBL_NEG_INF,          10,          10,
+        DBL_NEG_INF, DBL_POS_INF,          10,          10,
+    };
+
+    public static double replacecoords[] = {
+        DBL_NEG_INF,
+        DBL_MIN,
+        FLT_MIN,
+        DBL_NaN,
+        FLT_MAX,
+        DBL_MAX,
+        DBL_POS_INF,
+    };
+
+    public static void main(String argv[]) {
+        test(types, coords);
+        testNonFinites(types, coords, 2);
+    }
+
+    public static void testNonFinites(int types[], double coords[],
+                                      int numvalues)
+    {
+        if (numvalues == 0) {
+            test(types, coords);
+            return;
+        }
+        numvalues--;
+        for (int i = 0; i < coords.length; i++) {
+            double savedval = coords[i];
+
+            //System.out.println("replacing coord #"+i);
+            for (int j = 0; j < replacecoords.length; j++) {
+                coords[i] = replacecoords[j];
+                testNonFinites(types, coords, numvalues);
+            }
+
+            coords[i] = savedval;
+        }
+    }
+
+    public static void test(int types[], double coords[]) {
+        testGP(new GeneralPath(), types, coords);
+        try {
+            P2DTest.test(types, coords);
+        } catch (NoClassDefFoundError e) {
+            // Skip Path2D tests on older runtimes...
+        }
+    }
+
+    public static void testGP(GeneralPath gp, int types[], double coords[]) {
+        int ci = 0;
+        for (int i = 0; i < types.length; i++) {
+            switch (types[i]) {
+            case SEG_MOVETO:
+                gp.moveTo((float) coords[ci++], (float) coords[ci++]);
+                break;
+            case SEG_LINETO:
+                gp.lineTo((float) coords[ci++], (float) coords[ci++]);
+                break;
+            case SEG_QUADTO:
+                gp.quadTo((float) coords[ci++], (float) coords[ci++],
+                          (float) coords[ci++], (float) coords[ci++]);
+                break;
+            case SEG_CUBICTO:
+                gp.curveTo((float) coords[ci++], (float) coords[ci++],
+                           (float) coords[ci++], (float) coords[ci++],
+                           (float) coords[ci++], (float) coords[ci++]);
+                break;
+            case SEG_CLOSE:
+                gp.closePath();
+                break;
+            }
+        }
+        testGP(gp);
+    }
+
+    public static void testGP(GeneralPath gp) {
+        for (int i = 0; i < testpoints.length; i += 2) {
+            gp.contains(testpoints[i+0], testpoints[i+1]);
+        }
+
+        for (int i = 0; i < testrects.length; i += 4) {
+            gp.contains(testrects[i+0], testrects[i+1],
+                        testrects[i+2], testrects[i+3]);
+            gp.intersects(testrects[i+0], testrects[i+1],
+                          testrects[i+2], testrects[i+3]);
+        }
+    }
+
+    public static class P2DTest {
+        public static void test(int types[], double coords[]) {
+            testPath(new Path2D.Float(), types, coords);
+            testPath(new Path2D.Double(), types, coords);
+        }
+
+        public static void testPath(Path2D p2d, int types[], double coords[]) {
+            int ci = 0;
+            for (int i = 0; i < types.length; i++) {
+                switch (types[i]) {
+                case SEG_MOVETO:
+                    p2d.moveTo(coords[ci++], coords[ci++]);
+                    break;
+                case SEG_LINETO:
+                    p2d.lineTo(coords[ci++], coords[ci++]);
+                    break;
+                case SEG_QUADTO:
+                    p2d.quadTo(coords[ci++], coords[ci++],
+                               coords[ci++], coords[ci++]);
+                    break;
+                case SEG_CUBICTO:
+                    p2d.curveTo(coords[ci++], coords[ci++],
+                                coords[ci++], coords[ci++],
+                                coords[ci++], coords[ci++]);
+                    break;
+                case SEG_CLOSE:
+                    p2d.closePath();
+                    break;
+                }
+            }
+            testPath(p2d);
+        }
+
+        public static void testPath(Path2D p2d) {
+            // contains point
+            for (int i = 0; i < testpoints.length; i += 2) {
+                p2d.contains(testpoints[i+0], testpoints[i+1]);
+                contains(p2d, testpoints[i+0], testpoints[i+1]);
+            }
+
+            for (int i = 0; i < testrects.length; i += 4) {
+                p2d.contains(testrects[i+0], testrects[i+1],
+                             testrects[i+2], testrects[i+3]);
+                contains(p2d,
+                         testrects[i+0], testrects[i+1],
+                         testrects[i+2], testrects[i+3]);
+                p2d.intersects(testrects[i+0], testrects[i+1],
+                               testrects[i+2], testrects[i+3]);
+                intersects(p2d,
+                           testrects[i+0], testrects[i+1],
+                           testrects[i+2], testrects[i+3]);
+            }
+        }
+
+        public static boolean contains(Path2D p2d, double x, double y) {
+            return Path2D.contains(p2d.getPathIterator(null), x, y);
+        }
+
+        public static boolean contains(Path2D p2d,
+                                       double x, double y, double w, double h)
+        {
+            return Path2D.contains(p2d.getPathIterator(null), x, y, w, h);
+        }
+
+        public static boolean intersects(Path2D p2d,
+                                         double x, double y, double w, double h)
+        {
+            return Path2D.intersects(p2d.getPathIterator(null), x, y, w, h);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Path2D/UnitTest.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,1350 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4172661
+ * @summary Tests all public methods of Path2D classes on all 3 variants
+ *          Path2D.Float, Path2D.Double, and GeneralPath.
+ *          REMIND: Note that the hit testing tests will fail
+ *          occasionally due to precision bugs in the various hit
+ *          testing methods in the geometry classes.
+ *          (Failure rates vary from 1 per 100 runs to 1 per thousands).
+ *          See bug 6396047 to track progress on these failures.
+ */
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Arc2D;
+import java.awt.geom.Area;
+import java.awt.geom.CubicCurve2D;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.FlatteningPathIterator;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Line2D;
+import java.awt.geom.Path2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.geom.QuadCurve2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import java.util.NoSuchElementException;
+
+public class UnitTest {
+    public static boolean verbose;
+
+    public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO;
+    public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD;
+
+    public static int CoordsForType[] = { 2, 2, 4, 6, 0 };
+
+    public static AffineTransform TxIdentity = new AffineTransform();
+    public static AffineTransform TxComplex = makeAT();
+
+    public static Shape TestShapes[];
+    public static SampleShape ShortSampleNonZero;
+    public static SampleShape ShortSampleEvenOdd;
+    public static SampleShape LongSampleNonZero;
+    public static SampleShape LongSampleEvenOdd;
+
+    public static Shape EmptyShapeNonZero =
+        new EmptyShape(WIND_NON_ZERO);
+    public static Shape EmptyShapeEvenOdd =
+        new EmptyShape(WIND_EVEN_ODD);
+
+    // Note: We pick a shape that is not anywhere near any of
+    // our test shapes so that the Path2D does not try to collapse
+    // out the connecting segment - an optimization that is too
+    // difficult to account for in the AppendedShape code.
+    public static Shape AppendShape = new Arc2D.Double(1000, 1000, 40, 40,
+                                                       Math.PI/4, Math.PI,
+                                                       Arc2D.CHORD);
+
+    public static AffineTransform makeAT() {
+        AffineTransform at = new AffineTransform();
+        at.scale(0.66, 0.23);
+        at.rotate(Math.toRadians(35.0));
+        at.shear(0.78, 1.32);
+        return at;
+    }
+
+    public static void init() {
+        TestShapes = new Shape[] {
+            EmptyShapeNonZero,
+            EmptyShapeEvenOdd,
+            new Line2D.Double(),
+            new Line2D.Double(rpc(), rpc(), rpc(), rpc()),
+            new Line2D.Double(rnc(), rnc(), rnc(), rnc()),
+            new Rectangle2D.Double(),
+            new Rectangle2D.Double(rpc(), rpc(), -1, -1),
+            new Rectangle2D.Double(rpc(), rpc(), rd(), rd()),
+            new Rectangle2D.Double(rnc(), rnc(), rd(), rd()),
+            new Ellipse2D.Double(),
+            new Ellipse2D.Double(rpc(), rpc(), -1, -1),
+            new Ellipse2D.Double(rpc(), rpc(), rd(), rd()),
+            new Ellipse2D.Double(rnc(), rnc(), rd(), rd()),
+            new Arc2D.Double(Arc2D.OPEN),
+            new Arc2D.Double(Arc2D.CHORD),
+            new Arc2D.Double(Arc2D.PIE),
+            new Arc2D.Double(rpc(), rpc(), -1, -1, rt(), rt(), Arc2D.OPEN),
+            new Arc2D.Double(rpc(), rpc(), -1, -1, rt(), rt(), Arc2D.CHORD),
+            new Arc2D.Double(rpc(), rpc(), -1, -1, rt(), rt(), Arc2D.PIE),
+            new Arc2D.Double(rpc(), rpc(), rd(), rd(), rt(), rt(), Arc2D.OPEN),
+            new Arc2D.Double(rpc(), rpc(), rd(), rd(), rt(), rt(), Arc2D.CHORD),
+            new Arc2D.Double(rpc(), rpc(), rd(), rd(), rt(), rt(), Arc2D.PIE),
+            new Arc2D.Double(rnc(), rnc(), rd(), rd(), rt(), rt(), Arc2D.OPEN),
+            new Arc2D.Double(rnc(), rnc(), rd(), rd(), rt(), rt(), Arc2D.CHORD),
+            new Arc2D.Double(rnc(), rnc(), rd(), rd(), rt(), rt(), Arc2D.PIE),
+            new RoundRectangle2D.Double(),
+            new RoundRectangle2D.Double(rpc(), rpc(), -1, -1, ra(), ra()),
+            new RoundRectangle2D.Double(rpc(), rpc(), rd(), rd(), ra(), ra()),
+            new RoundRectangle2D.Double(rnc(), rnc(), rd(), rd(), ra(), ra()),
+            new QuadCurve2D.Double(),
+            new QuadCurve2D.Double(rpc(), rpc(), rpc(), rpc(), rpc(), rpc()),
+            new QuadCurve2D.Double(rnc(), rnc(), rnc(), rnc(), rnc(), rnc()),
+            new CubicCurve2D.Double(),
+            new CubicCurve2D.Double(rpc(), rpc(), rpc(), rpc(),
+                                    rpc(), rpc(), rpc(), rpc()),
+            new CubicCurve2D.Double(rnc(), rnc(), rnc(), rnc(),
+                                    rnc(), rnc(), rnc(), rnc()),
+            makeGeneralPath(WIND_NON_ZERO, 1.0),
+            makeGeneralPath(WIND_EVEN_ODD, 1.0),
+            makeGeneralPath(WIND_NON_ZERO, -1.0),
+            makeGeneralPath(WIND_EVEN_ODD, -1.0),
+        };
+
+        int types[] = new int[100];
+        int i = 0;
+        types[i++] = PathIterator.SEG_MOVETO;
+        types[i++] = PathIterator.SEG_LINETO;
+        types[i++] = PathIterator.SEG_QUADTO;
+        types[i++] = PathIterator.SEG_CUBICTO;
+        types[i++] = PathIterator.SEG_CLOSE;
+        int shortlen = i;
+        int prevt = types[i-1];
+        while (i < types.length) {
+            int t;
+            do {
+                t = (int) (Math.random() * 5);
+            } while (t == prevt &&
+                     (t == PathIterator.SEG_MOVETO ||
+                      t == PathIterator.SEG_CLOSE));
+            types[i++] = t;
+            prevt = t;
+        }
+
+        int numcoords = 0;
+        int numshortcoords = 0;
+        for (i = 0; i < types.length; i++) {
+            if (i == shortlen) {
+                numshortcoords = numcoords;
+            }
+            numcoords += CoordsForType[types[i]];
+        }
+        double coords[] = new double[numcoords];
+        for (i = 0; i < coords.length; i++) {
+            coords[i] = rpc();
+        }
+        ShortSampleNonZero = new SampleShape(WIND_NON_ZERO,
+                                             types, coords,
+                                             shortlen, numshortcoords);
+        ShortSampleEvenOdd = new SampleShape(WIND_EVEN_ODD,
+                                             types, coords,
+                                             shortlen, numshortcoords);
+        LongSampleNonZero = new SampleShape(WIND_NON_ZERO,
+                                            types, coords,
+                                            types.length, numcoords);
+        LongSampleEvenOdd = new SampleShape(WIND_EVEN_ODD,
+                                            types, coords,
+                                            types.length, numcoords);
+    }
+
+    public static GeneralPath makeGeneralPath(int windingrule, double sign) {
+        GeneralPath gp = new GeneralPath(windingrule);
+        gp.moveTo((float) (sign * rpc()), (float) (sign * rpc()));
+        gp.lineTo((float) (sign * rpc()), (float) (sign * rpc()));
+        gp.quadTo((float) (sign * rpc()), (float) (sign * rpc()),
+                  (float) (sign * rpc()), (float) (sign * rpc()));
+        gp.curveTo((float) (sign * rpc()), (float) (sign * rpc()),
+                   (float) (sign * rpc()), (float) (sign * rpc()),
+                   (float) (sign * rpc()), (float) (sign * rpc()));
+        gp.closePath();
+        return gp;
+    }
+
+    // Due to odd issues with the sizes of errors when the values
+    // being manipulated are near zero, we try to avoid values
+    // near zero by ensuring that both the rpc (positive coords)
+    // stay away from zero and also by ensuring that the rpc+rd
+    // (positive coords + dimensions) stay away from zero.  We
+    // also ensure that rnc+rd (negative coords + dimension) stay
+    // suitably negative without approaching zero.
+
+    // Random positive coordinate (10 -> 110)
+    // rpc + rd gives a total range of (30 -> 170)
+    public static double rpc() {
+        return (Math.random() * 100.0) + 10.0;
+    }
+
+    // Random negative coordinate (-200 -> -100)
+    // rnc + rd gives a total range of (-180 -> -40)
+    public static double rnc() {
+        return (Math.random() * 100.0) - 200.0;
+    }
+
+    // Random dimension (20 -> 60)
+    public static double rd() {
+        return (Math.random() * 40.0) + 20.0;
+    }
+
+    // Random arc width/height (0.1 -> 5.1)
+    public static double ra() {
+        return (Math.random() * 5.0) + 0.1;
+    }
+
+    // Random arc angle (theta) (PI/4 => 5PI/4)
+    public static double rt() {
+        return (Math.random() * Math.PI) + Math.PI/4;
+    }
+
+    public static int fltulpdiff(double v1, double v2) {
+        if (v1 == v2) {
+            return 0;
+        }
+        float vf1 = (float) v1;
+        float vf2 = (float) v2;
+        if (vf1 == vf2) {
+            return 0;
+        }
+        float diff = Math.abs(vf1-vf2);
+        //float ulp = Math.ulp((float) ((vf1 + vf2)/2f));
+        float ulp = Math.max(Math.ulp(vf1), Math.ulp(vf2));
+        if (verbose && diff > ulp) {
+            System.out.println("v1 = "+vf1+", ulp = "+Math.ulp(vf1));
+            System.out.println("v2 = "+vf2+", ulp = "+Math.ulp(vf2));
+            System.out.println((diff/ulp)+" ulps");
+        }
+        return (int) (diff/ulp);
+    }
+
+    public static int fltulpless(double v1, double v2) {
+        if (v1 >= v2) {
+            return 0;
+        }
+        float vf1 = (float) v1;
+        float vf2 = (float) v2;
+        if (vf1 >= vf2) {
+            return 0;
+        }
+        float diff = Math.abs(vf1-vf2);
+        //float ulp = Math.ulp((float) ((vf1 + vf2)/2f));
+        float ulp = Math.max(Math.ulp(vf1), Math.ulp(vf2));
+        if (verbose && diff > ulp) {
+            System.out.println("v1 = "+vf1+", ulp = "+Math.ulp(vf1));
+            System.out.println("v2 = "+vf2+", ulp = "+Math.ulp(vf2));
+            System.out.println((diff/ulp)+" ulps");
+        }
+        return (int) (diff/ulp);
+    }
+
+    public static int dblulpdiff(double v1, double v2) {
+        if (v1 == v2) {
+            return 0;
+        }
+        double diff = Math.abs(v1-v2);
+        //double ulp = Math.ulp((v1 + v2)/2.0);
+        double ulp = Math.max(Math.ulp(v1), Math.ulp(v2));
+        if (verbose && diff > ulp) {
+            System.out.println("v1 = "+v1+", ulp = "+Math.ulp(v1));
+            System.out.println("v2 = "+v2+", ulp = "+Math.ulp(v2));
+            System.out.println((diff/ulp)+" ulps");
+        }
+        return (int) (diff/ulp);
+    }
+
+    public static abstract class Creator {
+        public abstract Path2D makePath();
+        public abstract Path2D makePath(int windingrule);
+        public abstract Path2D makePath(int windingrule, int capacity);
+        public abstract Path2D makePath(Shape s);
+        public abstract Path2D makePath(Shape s, AffineTransform at);
+
+        public abstract boolean supportsFloatCompose();
+        public abstract int getRecommendedTxMaxUlp();
+
+        public abstract void compare(PathIterator testpi,
+                                     PathIterator refpi,
+                                     AffineTransform at,
+                                     int maxulp);
+    }
+
+    public static class FltCreator extends Creator {
+        public Path2D makePath() {
+            return new Path2D.Float();
+        }
+        public Path2D makePath(int windingrule) {
+            return new Path2D.Float(windingrule);
+        }
+        public Path2D makePath(int windingrule, int capacity) {
+            return new Path2D.Float(windingrule, capacity);
+        }
+        public Path2D makePath(Shape s) {
+            return new Path2D.Float(s);
+        }
+        public Path2D makePath(Shape s, AffineTransform at) {
+            return new Path2D.Float(s, at);
+        }
+
+        public boolean supportsFloatCompose() {
+            return true;
+        }
+        public int getRecommendedTxMaxUlp() {
+            return 5;
+        }
+
+        public void compare(PathIterator testpi,
+                            PathIterator refpi,
+                            AffineTransform at,
+                            int maxulp)
+        {
+            if (testpi.getWindingRule() != refpi.getWindingRule()) {
+                throw new RuntimeException("wrong winding rule");
+            }
+            float testcoords[] = new float[6];
+            float refcoords[] = new float[6];
+            while (!testpi.isDone()) {
+                if (refpi.isDone()) {
+                    throw new RuntimeException("too many segments");
+                }
+                int testtype = testpi.currentSegment(testcoords);
+                int reftype = refpi.currentSegment(refcoords);
+                if (testtype != reftype) {
+                    throw new RuntimeException("different segment types");
+                }
+                if (at != null) {
+                    at.transform(refcoords, 0, refcoords, 0,
+                                 CoordsForType[reftype]/2);
+                }
+                for (int i = 0; i < CoordsForType[testtype]; i++) {
+                    int ulps = fltulpdiff(testcoords[i], refcoords[i]);
+                    if (ulps > maxulp) {
+                        throw new RuntimeException("coords are different: "+
+                                                   testcoords[i]+" != "+
+                                                   refcoords[i]+
+                                                   " ("+ulps+" ulps)");
+                    }
+                }
+                testpi.next();
+                refpi.next();
+            }
+            if (!refpi.isDone()) {
+                throw new RuntimeException("not enough segments");
+            }
+        }
+    }
+
+    public static class DblCreator extends Creator {
+        public Path2D makePath() {
+            return new Path2D.Double();
+        }
+        public Path2D makePath(int windingrule) {
+            return new Path2D.Double(windingrule);
+        }
+        public Path2D makePath(int windingrule, int capacity) {
+            return new Path2D.Double(windingrule, capacity);
+        }
+        public Path2D makePath(Shape s) {
+            return new Path2D.Double(s);
+        }
+        public Path2D makePath(Shape s, AffineTransform at) {
+            return new Path2D.Double(s, at);
+        }
+
+        public boolean supportsFloatCompose() {
+            return false;
+        }
+        public int getRecommendedTxMaxUlp() {
+            return 3;
+        }
+
+        public void compare(PathIterator testpi,
+                            PathIterator refpi,
+                            AffineTransform at,
+                            int maxulp)
+        {
+            if (testpi.getWindingRule() != refpi.getWindingRule()) {
+                throw new RuntimeException("wrong winding rule");
+            }
+            double testcoords[] = new double[6];
+            double refcoords[] = new double[6];
+            while (!testpi.isDone()) {
+                if (refpi.isDone()) {
+                    throw new RuntimeException("too many segments");
+                }
+                int testtype = testpi.currentSegment(testcoords);
+                int reftype = refpi.currentSegment(refcoords);
+                if (testtype != reftype) {
+                    throw new RuntimeException("different segment types");
+                }
+                if (at != null) {
+                    at.transform(refcoords, 0, refcoords, 0,
+                                 CoordsForType[reftype]/2);
+                }
+                for (int i = 0; i < CoordsForType[testtype]; i++) {
+                    int ulps = dblulpdiff(testcoords[i], refcoords[i]);
+                    if (ulps > maxulp) {
+                        throw new RuntimeException("coords are different: "+
+                                                   testcoords[i]+" != "+
+                                                   refcoords[i]+
+                                                   " ("+ulps+" ulps)");
+                    }
+                }
+                testpi.next();
+                refpi.next();
+            }
+            if (!refpi.isDone()) {
+                throw new RuntimeException("not enough segments");
+            }
+        }
+
+    }
+
+    public static class GPCreator extends FltCreator {
+        public Path2D makePath() {
+            return new GeneralPath();
+        }
+        public Path2D makePath(int windingrule) {
+            return new GeneralPath(windingrule);
+        }
+        public Path2D makePath(int windingrule, int capacity) {
+            return new GeneralPath(windingrule, capacity);
+        }
+        public Path2D makePath(Shape s) {
+            return new GeneralPath(s);
+        }
+        public Path2D makePath(Shape s, AffineTransform at) {
+            GeneralPath gp = new GeneralPath();
+            PathIterator pi = s.getPathIterator(at);
+            gp.setWindingRule(pi.getWindingRule());
+            gp.append(pi, false);
+            return gp;
+        }
+
+        public boolean supportsFloatCompose() {
+            return true;
+        }
+    }
+
+    public static class EmptyShape implements Shape {
+        private int windingrule;
+
+        public EmptyShape(int windingrule) {
+            this.windingrule = windingrule;
+        }
+
+        public Rectangle getBounds() {
+            return new Rectangle();
+        }
+        public Rectangle2D getBounds2D() {
+            return new Rectangle();
+        }
+        public boolean contains(double x, double y) {
+            return false;
+        }
+        public boolean contains(Point2D p) {
+            return false;
+        }
+        public boolean intersects(double x, double y, double w, double h) {
+            return false;
+        }
+        public boolean intersects(Rectangle2D r) {
+            return false;
+        }
+        public boolean contains(double x, double y, double w, double h) {
+            return false;
+        }
+        public boolean contains(Rectangle2D r) {
+            return false;
+        }
+        public PathIterator getPathIterator(AffineTransform at) {
+            return new PathIterator() {
+                public int getWindingRule() {
+                    return windingrule;
+                }
+                public boolean isDone() {
+                    return true;
+                }
+                public void next() {}
+                public int currentSegment(float[] coords) {
+                    throw new NoSuchElementException();
+                }
+                public int currentSegment(double[] coords) {
+                    throw new NoSuchElementException();
+                }
+            };
+        }
+        public PathIterator getPathIterator(AffineTransform at,
+                                            double flatness)
+        {
+            return getPathIterator(at);
+        }
+    }
+
+    public static class SampleShape implements Shape {
+        int windingrule;
+        int theTypes[];
+        double theCoords[];
+        int numTypes;
+        int numCoords;
+
+        public SampleShape(int windingrule,
+                           int types[], double coords[],
+                           int numtypes, int numcoords)
+        {
+            this.windingrule = windingrule;
+            this.theTypes = types;
+            this.theCoords = coords;
+            this.numTypes = numtypes;
+            this.numCoords = numcoords;
+        }
+
+        private Shape testshape;
+
+        public Shape getTestShape() {
+            if (testshape == null) {
+                testshape = new Area(this);
+            }
+            return testshape;
+        }
+
+        private Rectangle2D cachedBounds;
+        public Rectangle2D getCachedBounds2D() {
+            if (cachedBounds == null) {
+                double xmin, ymin, xmax, ymax;
+                int ci = 0;
+                xmin = xmax = theCoords[ci++];
+                ymin = ymax = theCoords[ci++];
+                while (ci < numCoords) {
+                    double c = theCoords[ci++];
+                    if (xmin > c) xmin = c;
+                    if (xmax < c) xmax = c;
+                    c = theCoords[ci++];
+                    if (ymin > c) ymin = c;
+                    if (ymax < c) ymax = c;
+                }
+                cachedBounds = new Rectangle2D.Double(xmin, ymin,
+                                                      xmax - xmin,
+                                                      ymax - ymin);
+            }
+            return cachedBounds;
+        }
+
+        public Rectangle getBounds() {
+            return getCachedBounds2D().getBounds();
+        }
+        public Rectangle2D getBounds2D() {
+            return getCachedBounds2D().getBounds2D();
+        }
+        public boolean contains(double x, double y) {
+            return getTestShape().contains(x, y);
+        }
+        public boolean contains(Point2D p) {
+            return getTestShape().contains(p);
+        }
+        public boolean intersects(double x, double y, double w, double h) {
+            return getTestShape().intersects(x, y, w, h);
+        }
+        public boolean intersects(Rectangle2D r) {
+            return getTestShape().intersects(r);
+        }
+        public boolean contains(double x, double y, double w, double h) {
+            return getTestShape().contains(x, y, w, h);
+        }
+        public boolean contains(Rectangle2D r) {
+            return getTestShape().contains(r);
+        }
+        public PathIterator getPathIterator(final AffineTransform at) {
+            return new PathIterator() {
+                int tindex;
+                int cindex;
+                public int getWindingRule() {
+                    return windingrule;
+                }
+                public boolean isDone() {
+                    return (tindex >= numTypes);
+                }
+                public void next() {
+                    cindex += CoordsForType[theTypes[tindex]];
+                    tindex++;
+                }
+                public int currentSegment(float[] coords) {
+                    int t = theTypes[tindex];
+                    int n = CoordsForType[t];
+                    if (n > 0) {
+                        // Cast to float first, then transform
+                        // to match accuracy of float paths
+                        for (int i = 0; i < n; i++) {
+                            coords[i] = (float) theCoords[cindex+i];
+                        }
+                        if (at != null) {
+                            at.transform(coords, 0, coords, 0, n/2);
+                        }
+                    }
+                    return t;
+                }
+                public int currentSegment(double[] coords) {
+                    int t = theTypes[tindex];
+                    int n = CoordsForType[t];
+                    if (n > 0) {
+                        if (at == null) {
+                            System.arraycopy(theCoords, cindex,
+                                             coords, 0, n);
+                        } else {
+                            at.transform(theCoords, cindex,
+                                         coords, 0, n/2);
+                        }
+                    }
+                    return t;
+                }
+            };
+        }
+        public PathIterator getPathIterator(AffineTransform at,
+                                            double flatness)
+        {
+            return new FlatteningPathIterator(getPathIterator(at), flatness);
+        }
+
+        public String toString() {
+            Rectangle2D r2d = getBounds2D();
+            double xmin = r2d.getMinX();
+            double ymin = r2d.getMinY();
+            double xmax = r2d.getMaxX();
+            double ymax = r2d.getMaxY();
+            return ("SampleShape["+
+                    (windingrule == WIND_NON_ZERO
+                     ? "NonZero"
+                     : "EvenOdd")+
+                    ", nsegments = "+numTypes+
+                    ", ncoords = "+numCoords+
+                    ", bounds["+(r2d.getMinX()+", "+r2d.getMinY()+", "+
+                                 r2d.getMaxX()+", "+r2d.getMaxY())+"]"+
+                    "]");
+        }
+
+        public Path2D makeFloatPath(Creator c) {
+            Path2D.Float p2df = (Path2D.Float) c.makePath(windingrule);
+            int ci = 0;
+            for (int i = 0; i < numTypes; i++) {
+                int t = theTypes[i];
+                switch (t) {
+                case PathIterator.SEG_MOVETO:
+                    p2df.moveTo((float) theCoords[ci++],
+                                (float) theCoords[ci++]);
+                    break;
+                case PathIterator.SEG_LINETO:
+                    p2df.lineTo((float) theCoords[ci++],
+                                (float) theCoords[ci++]);
+                    break;
+                case PathIterator.SEG_QUADTO:
+                    p2df.quadTo((float) theCoords[ci++],
+                                (float) theCoords[ci++],
+                                (float) theCoords[ci++],
+                                (float) theCoords[ci++]);
+                    break;
+                case PathIterator.SEG_CUBICTO:
+                    p2df.curveTo((float) theCoords[ci++],
+                                 (float) theCoords[ci++],
+                                 (float) theCoords[ci++],
+                                 (float) theCoords[ci++],
+                                 (float) theCoords[ci++],
+                                 (float) theCoords[ci++]);
+                    break;
+                case PathIterator.SEG_CLOSE:
+                    p2df.closePath();
+                    break;
+                default:
+                    throw new InternalError("unrecognized path type: "+t);
+                }
+                if (t != PathIterator.SEG_CLOSE) {
+                    Point2D curpnt = p2df.getCurrentPoint();
+                    if (((float) curpnt.getX()) != ((float) theCoords[ci-2]) ||
+                        ((float) curpnt.getY()) != ((float) theCoords[ci-1]))
+                    {
+                        throw new RuntimeException("currentpoint failed");
+                    }
+                }
+            }
+            if (ci != numCoords) {
+                throw new InternalError("numcoords did not match");
+            }
+            return p2df;
+        }
+
+        public Path2D makeDoublePath(Creator c) {
+            Path2D p2d = c.makePath(windingrule);
+            int ci = 0;
+            for (int i = 0; i < numTypes; i++) {
+                int t = theTypes[i];
+                switch (t) {
+                case PathIterator.SEG_MOVETO:
+                    p2d.moveTo(theCoords[ci++], theCoords[ci++]);
+                    break;
+                case PathIterator.SEG_LINETO:
+                    p2d.lineTo(theCoords[ci++], theCoords[ci++]);
+                    break;
+                case PathIterator.SEG_QUADTO:
+                    p2d.quadTo(theCoords[ci++], theCoords[ci++],
+                               theCoords[ci++], theCoords[ci++]);
+                    break;
+                case PathIterator.SEG_CUBICTO:
+                    p2d.curveTo(theCoords[ci++], theCoords[ci++],
+                                theCoords[ci++], theCoords[ci++],
+                                theCoords[ci++], theCoords[ci++]);
+                    break;
+                case PathIterator.SEG_CLOSE:
+                    p2d.closePath();
+                    break;
+                default:
+                    throw new InternalError("unrecognized path type: "+t);
+                }
+                if (t != PathIterator.SEG_CLOSE) {
+                    Point2D curpnt = p2d.getCurrentPoint();
+                    if (((float) curpnt.getX()) != ((float) theCoords[ci-2]) ||
+                        ((float) curpnt.getY()) != ((float) theCoords[ci-1]))
+                    {
+                        throw new RuntimeException("currentpoint failed");
+                    }
+                }
+            }
+            if (ci != numCoords) {
+                throw new InternalError("numcoords did not match");
+            }
+            return p2d;
+        }
+    }
+
+    public static class AppendedShape implements Shape {
+        Shape s1;
+        Shape s2;
+        boolean connect;
+
+        public AppendedShape(Shape s1, Shape s2, boolean connect) {
+            this.s1 = s1;
+            this.s2 = s2;
+            this.connect = connect;
+        }
+
+        public Rectangle getBounds() {
+            return getBounds2D().getBounds();
+        }
+
+        public Rectangle2D getBounds2D() {
+            return s1.getBounds2D().createUnion(s2.getBounds2D());
+        }
+
+        private Shape testshape;
+        private Shape getTestShape() {
+            if (testshape == null) {
+                testshape = new GeneralPath(this);
+            }
+            return testshape;
+        }
+
+        public boolean contains(double x, double y) {
+            return getTestShape().contains(x, y);
+        }
+
+        public boolean contains(Point2D p) {
+            return getTestShape().contains(p);
+        }
+
+        public boolean intersects(double x, double y, double w, double h) {
+            return getTestShape().intersects(x, y, w, h);
+        }
+
+        public boolean intersects(Rectangle2D r) {
+            return getTestShape().intersects(r);
+        }
+
+        public boolean contains(double x, double y, double w, double h) {
+            return getTestShape().contains(x, y, w, h);
+        }
+
+        public boolean contains(Rectangle2D r) {
+            return getTestShape().contains(r);
+        }
+
+        public PathIterator getPathIterator(final AffineTransform at) {
+            return new AppendingPathIterator(s1, s2, connect, at);
+        }
+
+        public PathIterator getPathIterator(AffineTransform at,
+                                            double flatness)
+        {
+            return new FlatteningPathIterator(getPathIterator(at), flatness);
+        }
+
+        public static class AppendingPathIterator implements PathIterator {
+            AffineTransform at;
+            PathIterator pi;
+            Shape swaiting;
+            int windingrule;
+            boolean connectrequested;
+            boolean canconnect;
+            boolean converttoline;
+
+            public AppendingPathIterator(Shape s1, Shape s2,
+                                         boolean connect,
+                                         AffineTransform at)
+            {
+                this.at = at;
+                this.pi = s1.getPathIterator(at);
+                this.swaiting = s2;
+                this.windingrule = pi.getWindingRule();
+                this.connectrequested = connect;
+
+                if (pi.isDone()) {
+                    chain();
+                }
+            }
+
+            public void chain() {
+                if (swaiting != null) {
+                    pi = swaiting.getPathIterator(at);
+                    swaiting = null;
+                    converttoline = (connectrequested && canconnect);
+                }
+            }
+
+            public int getWindingRule() {
+                return windingrule;
+            }
+
+            public boolean isDone() {
+                return (pi.isDone());
+            }
+
+            public void next() {
+                converttoline = false;
+                pi.next();
+                if (pi.isDone()) {
+                    chain();
+                }
+                canconnect = true;
+            }
+
+            public int currentSegment(float[] coords) {
+                int type = pi.currentSegment(coords);
+                if (converttoline) {
+                    type = SEG_LINETO;
+                }
+                return type;
+            }
+
+            public int currentSegment(double[] coords) {
+                int type = pi.currentSegment(coords);
+                if (converttoline) {
+                    type = SEG_LINETO;
+                }
+                return type;
+            }
+        }
+    }
+
+    public static void checkEmpty(Path2D p2d, int windingrule) {
+        checkEmpty2(p2d, windingrule);
+        p2d.setWindingRule(PathIterator.WIND_NON_ZERO);
+        checkEmpty2(p2d, PathIterator.WIND_NON_ZERO);
+        p2d.setWindingRule(PathIterator.WIND_EVEN_ODD);
+        checkEmpty2(p2d, PathIterator.WIND_EVEN_ODD);
+    }
+
+    public static void checkEmpty2(Path2D p2d, int windingrule) {
+        if (p2d.getWindingRule() != windingrule) {
+            throw new RuntimeException("wrong winding rule in Path2D");
+        }
+        PathIterator pi = p2d.getPathIterator(null);
+        if (pi.getWindingRule() != windingrule) {
+            throw new RuntimeException("wrong winding rule in iterator");
+        }
+        if (!pi.isDone()) {
+            throw new RuntimeException("path not empty");
+        }
+    }
+
+    public static void compare(Creator c, Path2D p2d, Shape ref, int maxulp) {
+        compare(c, p2d, (Shape) p2d.clone(), null, 0);
+        compare(c, p2d, ref, null, 0);
+        compare(c, p2d, ref, TxIdentity, 0);
+        p2d.transform(TxIdentity);
+        compare(c, p2d, ref, null, 0);
+        compare(c, p2d, ref, TxIdentity, 0);
+        Shape s2 = p2d.createTransformedShape(TxIdentity);
+        compare(c, s2, ref, null, 0);
+        compare(c, s2, ref, TxIdentity, 0);
+        s2 = p2d.createTransformedShape(TxComplex);
+        compare(c, s2, ref, TxComplex, maxulp);
+        p2d.transform(TxComplex);
+        compare(c, p2d, (Shape) p2d.clone(), null, 0);
+        compare(c, p2d, ref, TxComplex, maxulp);
+    }
+
+    public static void compare(Creator c,
+                               Shape p2d, Shape s,
+                               AffineTransform at, int maxulp)
+    {
+        c.compare(p2d.getPathIterator(null), s.getPathIterator(at),
+                  null, maxulp);
+        c.compare(p2d.getPathIterator(null), s.getPathIterator(null),
+                  at, maxulp);
+    }
+
+    public static void checkBounds(Shape stest, Shape sref) {
+        checkBounds(stest.getBounds2D(), sref.getBounds2D(),
+                    "2D bounds too small");
+        /*
+        checkBounds(stest.getBounds(), sref.getBounds(),
+                    "int bounds too small");
+        */
+        checkBounds(stest.getBounds(), stest.getBounds2D(),
+                    "int bounds too small for 2D bounds");
+    }
+
+    public static void checkBounds(Rectangle2D tBounds,
+                                   Rectangle2D rBounds,
+                                   String faildesc)
+    {
+        if (rBounds.isEmpty()) {
+            if (!tBounds.isEmpty()) {
+                throw new RuntimeException("bounds not empty");
+            }
+            return;
+        } else if (tBounds.isEmpty()) {
+            throw new RuntimeException("bounds empty");
+        }
+        double rxmin = rBounds.getMinX();
+        double rymin = rBounds.getMinY();
+        double rxmax = rBounds.getMaxX();
+        double rymax = rBounds.getMaxY();
+        double txmin = tBounds.getMinX();
+        double tymin = tBounds.getMinY();
+        double txmax = tBounds.getMaxX();
+        double tymax = tBounds.getMaxY();
+        if (txmin > rxmin || tymin > rymin ||
+            txmax < rxmax || tymax < rymax)
+        {
+            if (verbose) System.out.println("test bounds = "+tBounds);
+            if (verbose) System.out.println("ref bounds = "+rBounds);
+            // Allow fudge room of a couple of single precision ulps
+            double ltxmin = txmin - 5 * Math.max(Math.ulp((float) rxmin),
+                                                 Math.ulp((float) txmin));
+            double ltymin = tymin - 5 * Math.max(Math.ulp((float) rymin),
+                                                 Math.ulp((float) tymin));
+            double ltxmax = txmax + 5 * Math.max(Math.ulp((float) rxmax),
+                                                 Math.ulp((float) txmax));
+            double ltymax = tymax + 5 * Math.max(Math.ulp((float) rymax),
+                                                 Math.ulp((float) tymax));
+            if (ltxmin > rxmin || ltymin > rymin ||
+                ltxmax < rxmax || ltymax < rymax)
+            {
+                if (!verbose) System.out.println("test bounds = "+tBounds);
+                if (!verbose) System.out.println("ref bounds = "+rBounds);
+                System.out.println("xmin: "+
+                                   txmin+" + "+fltulpless(txmin, rxmin)+" = "+
+                                   rxmin+" + "+fltulpless(rxmin, txmin));
+                System.out.println("ymin: "+
+                                   tymin+" + "+fltulpless(tymin, rymin)+" = "+
+                                   rymin+" + "+fltulpless(rymin, tymin));
+                System.out.println("xmax: "+
+                                   txmax+" + "+fltulpless(txmax, rxmax)+" = "+
+                                   rxmax+" + "+fltulpless(rxmax, txmax));
+                System.out.println("ymax: "+
+                                   tymax+" + "+fltulpless(tymax, rymax)+" = "+
+                                   rymax+" + "+fltulpless(rymax, tymax));
+                System.out.println("flt tbounds = ["+
+                                   ((float) txmin)+", "+((float) tymin)+", "+
+                                   ((float) txmax)+", "+((float) tymax)+"]");
+                System.out.println("flt rbounds = ["+
+                                   ((float) rxmin)+", "+((float) rymin)+", "+
+                                   ((float) rxmax)+", "+((float) rymax)+"]");
+                System.out.println("xmin ulp = "+fltulpless(rxmin, txmin));
+                System.out.println("ymin ulp = "+fltulpless(rymin, tymin));
+                System.out.println("xmax ulp = "+fltulpless(txmax, rxmax));
+                System.out.println("ymax ulp = "+fltulpless(tymax, rymax));
+                throw new RuntimeException(faildesc);
+            }
+        }
+    }
+
+    public static void checkHits(Shape stest, Shape sref) {
+        for (int i = 0; i < 10; i++) {
+            double px = Math.random() * 500 - 250;
+            double py = Math.random() * 500 - 250;
+            Point2D pnt = new Point2D.Double(px, py);
+
+            double rw = Math.random()*10+0.4;
+            double rh = Math.random()*10+0.4;
+            double rx = px - rw/2;
+            double ry = py - rh/2;
+            Rectangle2D rect = new Rectangle2D.Double(rx, ry, rw, rh);
+            Rectangle2D empty = new Rectangle2D.Double(rx, ry, 0, 0);
+
+            if (!rect.contains(pnt)) {
+                throw new InternalError("test point not inside test rect!");
+            }
+
+            if (stest.contains(rx, ry, 0, 0)) {
+                throw new RuntimeException("contains 0x0 rect");
+            }
+            if (stest.contains(empty)) {
+                throw new RuntimeException("contains empty rect");
+            }
+            if (stest.intersects(rx, ry, 0, 0)) {
+                throw new RuntimeException("intersects 0x0 rect");
+            }
+            if (stest.intersects(empty)) {
+                throw new RuntimeException("intersects empty rect");
+            }
+
+            boolean tContainsXY = stest.contains(px, py);
+            boolean tContainsPnt = stest.contains(pnt);
+            boolean tContainsXYWH = stest.contains(rx, ry, rw, rh);
+            boolean tContainsRect = stest.contains(rect);
+            boolean tIntersectsXYWH = stest.intersects(rx, ry, rw, rh);
+            boolean tIntersectsRect = stest.intersects(rect);
+
+            if (tContainsXY != tContainsPnt) {
+                throw new RuntimeException("contains(x,y) != "+
+                                           "contains(pnt)");
+            }
+            if (tContainsXYWH != tContainsRect) {
+                throw new RuntimeException("contains(x,y,w,h) != "+
+                                           "contains(rect)");
+            }
+            if (tIntersectsXYWH != tIntersectsRect) {
+                throw new RuntimeException("intersects(x,y,w,h) != "+
+                                           "intersects(rect)");
+            }
+
+            boolean uContainsXY =
+                Path2D.contains(stest.getPathIterator(null), px, py);
+            boolean uContainsXYWH =
+                Path2D.contains(stest.getPathIterator(null), rx, ry, rw, rh);
+            boolean uIntersectsXYWH =
+                Path2D.intersects(stest.getPathIterator(null), rx, ry, rw, rh);
+
+            if (tContainsXY != uContainsXY) {
+                throw new RuntimeException("contains(x,y) "+
+                                           "does not match utility");
+            }
+            if (tContainsXYWH != uContainsXYWH) {
+                throw new RuntimeException("contains(x,y,w,h) "+
+                                           "does not match utility");
+            }
+            if (tIntersectsXYWH != uIntersectsXYWH) {
+                throw new RuntimeException("intersects(x,y,w,h) "+
+                                           "does not match utility");
+            }
+
+            // Make rect slightly smaller to be more conservative for rContains
+            double srx = rx + 0.1;
+            double sry = ry + 0.1;
+            double srw = rw - 0.2;
+            double srh = rh - 0.2;
+            Rectangle2D srect = new Rectangle2D.Double(srx, sry, srw, srh);
+            // Make rect slightly larger to be more liberal for rIntersects
+            double lrx = rx - 0.1;
+            double lry = ry - 0.1;
+            double lrw = rw + 0.2;
+            double lrh = rh + 0.2;
+            Rectangle2D lrect = new Rectangle2D.Double(lrx, lry, lrw, lrh);
+
+            if (srect.isEmpty()) {
+                throw new InternalError("smaller rect too small (empty)");
+            }
+            if (!lrect.contains(rect)) {
+                throw new InternalError("test rect not inside larger rect!");
+            }
+            if (!rect.contains(srect)) {
+                throw new InternalError("smaller rect not inside test rect!");
+            }
+
+            boolean rContainsSmaller;
+            boolean rIntersectsLarger;
+            boolean rContainsPnt;
+
+            if (sref instanceof SampleShape ||
+                sref instanceof QuadCurve2D ||
+                sref instanceof CubicCurve2D)
+            {
+                // REMIND
+                // Some of the source shapes are not proving reliable
+                // enough to do reference verification of the hit
+                // testing results.
+                // Quad/CubicCurve2D have spaghetti test methods that could
+                // very likely contain some bugs.  They return a conflicting
+                // answer in maybe 1 out of 20,000 tests.
+                // Area causes a conflicting answer maybe 1 out of
+                // 100 to 1000 runs and it infinite loops maybe 1
+                // out of 10,000 runs or so.
+                // So, we use some conservative "safe" answers for
+                // these shapes and avoid their hit testing methods.
+                rContainsSmaller = tContainsRect;
+                rIntersectsLarger = tIntersectsRect;
+                rContainsPnt = tContainsPnt;
+            } else {
+                rContainsSmaller = sref.contains(srect);
+                rIntersectsLarger = sref.intersects(lrect);
+                rContainsPnt = sref.contains(px, py);
+            }
+
+            if (tIntersectsRect) {
+                if (tContainsRect) {
+                    if (!tContainsPnt) {
+                        System.out.println("reference shape = "+sref);
+                        System.out.println("pnt = "+pnt);
+                        System.out.println("rect = "+rect);
+                        System.out.println("tbounds = "+stest.getBounds2D());
+                        throw new RuntimeException("test contains rect, "+
+                                                   "but not center point");
+                    }
+                }
+                // Note: (tContainsPnt || tContainsRect) is same as
+                // tContainsPnt because of the test above...
+                if (tContainsPnt) {
+                    if (!rIntersectsLarger) {
+                        System.out.println("reference shape = "+sref);
+                        System.out.println("pnt = "+pnt);
+                        System.out.println("rect = "+rect);
+                        System.out.println("lrect = "+lrect);
+                        System.out.println("tbounds = "+stest.getBounds2D());
+                        System.out.println("rbounds = "+sref.getBounds2D());
+                        throw new RuntimeException("test claims containment, "+
+                                                   "but no ref intersection");
+                    }
+                }
+            } else {
+                if (tContainsRect) {
+                    throw new RuntimeException("test contains rect, "+
+                                               "with no intersection");
+                }
+                if (tContainsPnt) {
+                    System.out.println("reference shape = "+sref);
+                    System.out.println("rect = "+rect);
+                    throw new RuntimeException("test contains point, "+
+                                               "with no intersection");
+                }
+                if (rContainsPnt || rContainsSmaller) {
+                    System.out.println("pnt = "+pnt);
+                    System.out.println("rect = "+rect);
+                    System.out.println("srect = "+lrect);
+                    throw new RuntimeException("test did not intersect, "+
+                                               "but ref claims containment");
+                }
+            }
+        }
+    }
+
+    public static void test(Creator c) {
+        testConstructors(c);
+        testPathConstruction(c);
+        testAppend(c);
+        testBounds(c);
+        testHits(c);
+    }
+
+    public static void testConstructors(Creator c) {
+        checkEmpty(c.makePath(), WIND_NON_ZERO);
+        checkEmpty(c.makePath(WIND_NON_ZERO), WIND_NON_ZERO);
+        checkEmpty(c.makePath(WIND_EVEN_ODD), WIND_EVEN_ODD);
+        checkEmpty(c.makePath(EmptyShapeNonZero), WIND_NON_ZERO);
+        checkEmpty(c.makePath(EmptyShapeNonZero, null), WIND_NON_ZERO);
+        checkEmpty(c.makePath(EmptyShapeNonZero, TxIdentity), WIND_NON_ZERO);
+        checkEmpty(c.makePath(EmptyShapeEvenOdd), WIND_EVEN_ODD);
+        checkEmpty(c.makePath(EmptyShapeEvenOdd, null), WIND_EVEN_ODD);
+        checkEmpty(c.makePath(EmptyShapeEvenOdd, TxIdentity), WIND_EVEN_ODD);
+        try {
+            c.makePath(null);
+            throw new RuntimeException(c+" allowed null Shape in constructor");
+        } catch (NullPointerException npe) {
+            // passes
+        }
+        try {
+            c.makePath(null, TxIdentity);
+            throw new RuntimeException(c+" allowed null Shape in constructor");
+        } catch (NullPointerException npe) {
+            // passes
+        }
+
+        for (int i = 0; i < TestShapes.length; i++) {
+            Shape sref = TestShapes[i];
+            if (verbose) System.out.println("construct testing "+sref);
+            compare(c, c.makePath(sref), sref, null, 0);
+            compare(c, c.makePath(sref), sref, TxIdentity, 0);
+            compare(c, c.makePath(sref, null), sref, null, 0);
+            compare(c, c.makePath(sref, null), sref, TxIdentity, 0);
+            compare(c, c.makePath(sref, TxIdentity), sref, null, 0);
+            compare(c, c.makePath(sref, TxIdentity), sref, TxIdentity, 0);
+            compare(c, c.makePath(sref, TxComplex), sref, TxComplex,
+                    c.getRecommendedTxMaxUlp());
+        }
+    }
+
+    public static void testPathConstruction(Creator c) {
+        testPathConstruction(c, LongSampleNonZero);
+        testPathConstruction(c, LongSampleEvenOdd);
+    }
+
+    public static void testPathConstruction(Creator c, SampleShape ref) {
+        if (c.supportsFloatCompose()) {
+            compare(c, ref.makeFloatPath(c), ref, c.getRecommendedTxMaxUlp());
+        }
+        compare(c, ref.makeDoublePath(c), ref, c.getRecommendedTxMaxUlp());
+    }
+
+    public static void testAppend(Creator c) {
+        for (int i = 0; i < TestShapes.length; i++) {
+            Shape sref = TestShapes[i];
+            if (verbose) System.out.println("append testing "+sref);
+            PathIterator spi = sref.getPathIterator(null);
+            Path2D stest = c.makePath(spi.getWindingRule());
+            stest.append(spi, false);
+            compare(c, stest, sref, null, 0);
+            stest.reset();
+            stest.append(sref, false);
+            compare(c, stest, sref, null, 0);
+            stest.reset();
+            stest.append(sref.getPathIterator(TxComplex), false);
+            compare(c, stest, sref, TxComplex, 0);
+            // multiple shape append testing...
+            if (sref.getBounds2D().isEmpty()) {
+                // If the first shape is empty, then we really
+                // are not testing multiple appended shapes,
+                // we are just testing appending the AppendShape
+                // to a null path over and over.
+                // Also note that some empty shapes will spit out
+                // a single useless SEG_MOVETO that has no affect
+                // on the outcome, but it makes duplicating the
+                // behavior that Path2D has in that case difficult
+                // when the AppenedShape utility class has to
+                // iterate the exact same segments.  So, we will
+                // just ignore all empty shapes here.
+                continue;
+            }
+            stest.reset();
+            stest.append(sref, false);
+            stest.append(AppendShape, false);
+            compare(c, stest,
+                    new AppendedShape(sref, AppendShape, false),
+                    null, 0);
+            stest.reset();
+            stest.append(sref, false);
+            stest.append(AppendShape, true);
+            compare(c, stest,
+                    new AppendedShape(sref, AppendShape, true),
+                    null, 0);
+            stest.reset();
+            stest.append(sref.getPathIterator(null), false);
+            stest.append(AppendShape.getPathIterator(null), false);
+            compare(c, stest,
+                    new AppendedShape(sref, AppendShape, false),
+                    null, 0);
+            stest.reset();
+            stest.append(sref.getPathIterator(null), false);
+            stest.append(AppendShape.getPathIterator(null), true);
+            compare(c, stest,
+                    new AppendedShape(sref, AppendShape, true),
+                    null, 0);
+            stest.reset();
+            stest.append(sref.getPathIterator(TxComplex), false);
+            stest.append(AppendShape.getPathIterator(TxComplex), false);
+            compare(c, stest,
+                    new AppendedShape(sref, AppendShape, false),
+                    TxComplex, 0);
+            stest.reset();
+            stest.append(sref.getPathIterator(TxComplex), false);
+            stest.append(AppendShape.getPathIterator(TxComplex), true);
+            compare(c, stest,
+                    new AppendedShape(sref, AppendShape, true),
+                    TxComplex, 0);
+        }
+    }
+
+    public static void testBounds(Creator c) {
+        for (int i = 0; i < TestShapes.length; i++) {
+            Shape sref = TestShapes[i];
+            if (verbose) System.out.println("bounds testing "+sref);
+            Shape stest = c.makePath(sref);
+            checkBounds(c.makePath(sref), sref);
+        }
+        testBounds(c, ShortSampleNonZero);
+        testBounds(c, ShortSampleEvenOdd);
+        testBounds(c, LongSampleNonZero);
+        testBounds(c, LongSampleEvenOdd);
+    }
+
+    public static void testBounds(Creator c, SampleShape ref) {
+        if (verbose) System.out.println("bounds testing "+ref);
+        if (c.supportsFloatCompose()) {
+            checkBounds(ref.makeFloatPath(c), ref);
+        }
+        checkBounds(ref.makeDoublePath(c), ref);
+    }
+
+    public static void testHits(Creator c) {
+        for (int i = 0; i < TestShapes.length; i++) {
+            Shape sref = TestShapes[i];
+            if (verbose) System.out.println("hit testing "+sref);
+            Shape stest = c.makePath(sref);
+            checkHits(c.makePath(sref), sref);
+        }
+        testHits(c, ShortSampleNonZero);
+        testHits(c, ShortSampleEvenOdd);
+        // These take too long to construct the Area for reference testing
+        //testHits(c, LongSampleNonZero);
+        //testHits(c, LongSampleEvenOdd);
+    }
+
+    public static void testHits(Creator c, SampleShape ref) {
+        if (verbose) System.out.println("hit testing "+ref);
+        if (c.supportsFloatCompose()) {
+            checkHits(ref.makeFloatPath(c), ref);
+        }
+        checkHits(ref.makeDoublePath(c), ref);
+    }
+
+    public static void main(String argv[]) {
+        int limit = (argv.length > 0) ? 10000 : 1;
+        verbose = (argv.length > 1);
+        for (int i = 0; i < limit; i++) {
+            if (limit > 1) {
+                System.out.println("loop #"+(i+1));
+            }
+            init();
+            test(new GPCreator());
+            test(new FltCreator());
+            test(new DblCreator());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/QuadCurve2D/Quad2DContainsTest.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4682078
+ * @summary QuadCurve2D contains() returns true for far away point
+ */
+
+import java.awt.geom.Point2D;
+import java.awt.geom.QuadCurve2D;
+
+public class Quad2DContainsTest {
+
+    static Object[][] trues = {
+        {
+            new QuadCurve2D.Double(0, 0, 50, 200, 100, 0),
+            new Point2D.Double(50, 50)
+        },
+        {
+            new QuadCurve2D.Double(0, 100, 100, 100, 100, 0),
+            new Point2D.Double(50, 50)
+        }
+    };
+    static Object[][] falses = {
+        {
+            new QuadCurve2D.Double(0, 0, 50, 200, 100, 0),
+            new Point2D.Double(0, 50)
+        },
+        {
+            new QuadCurve2D.Double(0, 0, 50, 200, 100, 0),
+            new Point2D.Double(100, 50)
+        },
+        {
+            new QuadCurve2D.Double(0, 0, 0, 100, 100, 100),
+            new Point2D.Double(0, 100)
+        },
+        {
+            new QuadCurve2D.Double(0, 0, 60, 60, 100, 100),
+            new Point2D.Double(30, 30)
+        }
+    };
+
+    public static void main(String[] args) {
+
+        for (int i = 0; i < trues.length; i++) {
+            checkPair((QuadCurve2D)trues[i][0], (Point2D)trues[i][1], true);
+        }
+
+        for (int i = 0; i < falses.length; i++) {
+            checkPair((QuadCurve2D)falses[i][0], (Point2D)falses[i][1], false);
+        }
+    }
+
+    public static void checkPair(QuadCurve2D q, Point2D p, boolean expect) {
+
+        if (q.contains(p.getX(), p.getY()) != expect) {
+            String errMsg = "QuadCurve2D " +
+                            "p1 = (" + q.getX1() + ", " + q.getY1() + ") " +
+                            "p2 = (" + q.getX2() + ", " + q.getY2() + ") " +
+                            "control = (" + q.getCtrlX() + ", " +
+                                            q.getCtrlY() + ") " +
+                            "should " + (expect ? "" : "not ") +
+                            "contain the point (" +
+                            p.getX() + ", " + p.getY() + "), " +
+                            "but method returns wrong value!";
+            throw new RuntimeException(errMsg);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Rectangle2D/CreateIntersectBug.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4374642
+ * @summary Verifies that the Rectangle2D.createIntersection method produces
+ *          an empty result rectangle if the two source rects did not intersect
+ */
+
+import java.awt.Canvas;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.geom.Rectangle2D;
+
+public class CreateIntersectBug extends Canvas {
+    public static boolean showresults = false;
+
+    public static RuntimeException t = null;
+
+    public static void main(String[] args) {
+        showresults = (args.length > 0);
+        test(50, 50, 20, 20, 100, 100, 100, 100);
+        test(-100, -100, 50, 50, 100, 100, 50, 50);
+        if (t != null) {
+            throw t;
+        }
+    }
+
+    public static void test(int x1, int y1, int w1, int h1,
+                            int x2, int y2, int w2, int h2)
+    {
+        Rectangle2D r1 = new Rectangle2D.Double(x1, y1, w1, h1);
+        Rectangle2D r2 = new Rectangle2D.Double(x2, y2, w2, h2);
+
+        write(r1, "R1");
+        write(r2, "R2");
+        if (r1.intersects(r2)) {
+            System.out.println("r1 and r2 intersect");
+        } else {
+            System.out.println("r1 and r2 don't intersect");
+        }
+        Rectangle2D r3 = r1.createIntersection(r2);
+        write(r3, "intersect");
+
+        Rectangle2D r4 = r1.createUnion(r2);
+        write(r4, "union");
+
+        if (showresults) {
+            new CreateIntersectBug(r1, r2, r3, r4);
+        }
+        if (!r1.intersects(r2) && !r3.isEmpty()) {
+            String s = ("Intersection of non-intersecting "+
+                        "rectangles is not empty!");
+            t = new RuntimeException(s);
+            System.out.println(s);
+        }
+    }
+
+    private Rectangle2D r1, r2, r3, r4;
+
+    public CreateIntersectBug(Rectangle2D r1, Rectangle2D r2,
+                              Rectangle2D r3, Rectangle2D r4)
+    {
+        this.r1 = r1;
+        this.r2 = r2;
+        this.r3 = r3;
+        this.r4 = r4;
+
+        Frame f = new Frame();
+        f.add(this);
+        f.addWindowListener(new WindowAdapter() {
+            public void windowClosing(WindowEvent e) {System.exit(0);}
+        });
+        f.pack();
+        f.show();
+    }
+
+    public Dimension getPreferredSize() {
+        return new Dimension(500, 500);
+    }
+
+
+    public void paint(Graphics g){
+        Graphics2D g2 = (Graphics2D) g;
+
+        // graphic aids to understanding - these have no
+        // effect on the problem.
+        if (!r1.intersects(r2) && !r3.isEmpty()) {
+            g2.setColor(Color.red);
+        } else {
+            g2.setColor(Color.green);
+        }
+        g2.draw(r3);
+        g2.setColor(Color.yellow);
+        g2.draw(r4);
+        g2.setColor(Color.blue);
+        g2.draw(r1);
+        g2.draw(r2);
+    }
+
+    public static void write(Rectangle2D r, String s) {
+        System.out.println(s + ": (" +
+                           (int)r.getX() + "," + (int)r.getY() + ","
+                           + (int)r.getWidth() + "," + (int)r.getHeight() +
+                           ")");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/Rectangle2D/IntersectsLineHang.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4320890
+ * @summary Verifies that the Rectangle2D.intersectsLine method does not hang
+ *          or return bad results due to inaccuracies in the outcode methods
+ * @run main/timeout=5 IntersectsLineHang
+ */
+
+import java.awt.Rectangle;
+import java.awt.geom.Rectangle2D;
+
+public class IntersectsLineHang {
+    static public void main(String args[]) {
+        Rectangle r = new Rectangle(0x70000000, 0x70000000,
+                                    0x20000000, 0x0f000000);
+        double v = 0x78000000;
+        System.out.println("Point alpha");
+        boolean result = r.intersectsLine(v, v, v+v, v+v);
+        System.out.println(result);
+        Rectangle2D rect = new Rectangle2D.Float(29.790712356567383f,
+                                                 362.3290710449219f,
+                                                 267.40679931640625f,
+                                                 267.4068298339844f);
+        System.out.println("Point A");
+        System.out.println(rect.intersectsLine(431.39777, 551.3534,
+                                               26.391, 484.71542));
+        System.out.println("Point A2");
+        System.out.println(rect.intersectsLine(431.39777, 551.3534,
+                                               268.391, 484.71542));
+        System.out.println("Point B: Never gets here!");
+        if (!result) {
+            // failure of integer rectangle intersection test
+            throw new RuntimeException("integer rectangle "+
+                                       "failed intersection test");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/geom/SerialTest.java	Tue May 22 17:33:31 2018 -0700
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4263142 4172661
+ * @summary First run verifies that objects serialize and deserialize
+ *          correctly against the current release.
+ *          Second run verifies that objects from previous releases
+ *          still deserialize correctly.  The serial_1_6.out file was
+ *          created using the "write" option under release 1.6.
+ *          The test was modified after fixing 4172661 to add testing
+ *          of Path2D serialization (and to recut the test file with
+ *          the new serialVersionUID of GeneralPath).
+ * @run main SerialTest
+ * @run main SerialTest read serial_1_6.out
+ */
+
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Arc2D;
+import java.awt.geom.CubicCurve2D;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Line2D;
+import java.awt.geom.Path2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.geom.QuadCurve2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+
+public class SerialTest {
+    public static Object testobjects[] = {
+        // non-shapes...
+        new Point2D.Float(37, 42),
+        new Point2D.Double(85, 63),
+        new AffineTransform(10, 20, 30, 40, 50, 60),
+
+        // shapes...
+        new QuadCurve2D.Float(10f, 10f, 50f, 50f, 100f, 10f),
+        new QuadCurve2D.Double(20f, 20f, 50f, 50f, 100f, 20f),
+        new CubicCurve2D.Float(10f, 10f, 50f, 10f, 10f, 50f, 50f, 50f),
+        new CubicCurve2D.Double(0.0, 0.0, 50.0, 0.0, 0.0, 50.0, 50.0, 50.0),
+        new GeneralPath(),
+        new GeneralPath(PathIterator.WIND_NON_ZERO),
+        new GeneralPath(PathIterator.WIND_EVEN_ODD),
+        makeGeneralPath(PathIterator.WIND_NON_ZERO, 5f),
+        makeGeneralPath(PathIterator.WIND_EVEN_ODD, 23f),
+        new Line2D.Float(20f, 20f, 25f, 50f),
+        new Line2D.Double(20.0, 20.0, 35.0, 50.0),
+        new Rectangle2D.Float(100f, 100f, 50f, 25f),
+        new Rectangle2D.Double(200.0, 200.0, 75.0, 35.0),
+        new RoundRectangle2D.Float(120f, 120f, 50f, 35f, 5f, 7f),
+        new RoundRectangle2D.Double(220.0, 220.0, 85.0, 45.0, 3.0, 9.0),
+        new Ellipse2D.Float(110f, 110f, 50f, 55f),
+        new Ellipse2D.Double(210.0, 210.0, 75.0, 45.0),
+        new Arc2D.Float(10f, 10f, 50f, 40f, 45f, 72f, Arc2D.OPEN),
+        new Arc2D.Float(10f, 10f, 40f, 50f, 135f, 72f, Arc2D.PIE),
+        new Arc2D.Float(10f, 10f, 40f, 60f, 225f, 72f, Arc2D.CHORD),
+        new Arc2D.Double(10.0, 20.0, 50.0, 40.0, 45.0, 72.0, Arc2D.OPEN),
+        new Arc2D.Double(10.0, 20.0, 40.0, 50.0, 135.0, 72.0, Arc2D.PIE),
+        new Arc2D.Double(10.0, 20.0, 40.0, 60.0, 225.0, 72.0, Arc2D.CHORD),
+
+        // Paths
+        new Path2D.Float(),
+        new Path2D.Float(PathIterator.WIND_NON_ZERO),
+        new Path2D.Float(PathIterator.WIND_EVEN_ODD),
+        makePath2DFloat(PathIterator.WIND_NON_ZERO, 5f),
+        makePath2DFloat(PathIterator.WIND_EVEN_ODD, 23f),
+        new Path2D.Double(),
+        new Path2D.Double(PathIterator.WIND_NON_ZERO),
+        new Path2D.Double(PathIterator.WIND_EVEN_ODD),
+        makePath2DDouble(PathIterator.WIND_NON_ZERO, 5f),
+        makePath2DDouble(PathIterator.WIND_EVEN_ODD, 23f),
+    };
+
+    public static Shape makeGeneralPath(int winding, float off) {
+        return fill(new GeneralPath(winding), off);
+    }
+
+    public static Shape makePath2DFloat(int winding, float off) {
+        return fill(new Path2D.Float(winding), off);
+    }
+
+    public static Shape makePath2DDouble(int winding, float off) {
+        return fill(new Path2D.Double(winding), off);
+    }
+
+    public static Path2D fill(Path2D p2d, float off) {
+        p2d.moveTo(off+10, off+10);
+        p2d.lineTo(off+100, off+50);
+        p2d.quadTo(off+50, off+100, off+200, off+100);
+        p2d.curveTo(off+400, off+20, off+20, off+400, off+100, off+100);
+        p2d.closePath();
+        return p2d;
+    }
+
+    static int numerrors;
+
+    public static void error(Object o1, Object o2, String reason) {
+        System.err.println("Failed comparing: "+o1+" to "+o2);
+        System.err.println(reason);
+        numerrors++;
+    }
+
+    public static void usage(int exitcode) {
+        System.err.println("usage: java SerialTest [read|write] <filename>");
+        System.exit(exitcode);
+    }
+
+    public static void main(String argv[]) {
+        if (argv.length > 0) {
+            if (argv.length < 2) {
+                usage(1);
+            }
+
+            String arg = argv[0].toLowerCase();
+            if (arg.equals("write")) {
+                serializeTo(argv[1]);
+            } else if (arg.equals("read")) {
+                testFrom(argv[1]);
+            } else {
+                usage(1);
+            }
+        } else {
+            testSerial();
+        }
+    }
+
+    public static File makeFile(String filename) {
+        return new File(System.getProperty("test.src", "."), filename);
+    }
+
+    public static void serializeTo(String filename) {
+        FileOutputStream fos;
+        try {
+            fos = new FileOutputStream(makeFile(filename));
+        } catch (IOException ioe) {
+            throw new InternalError("bad output filename: "+filename);
+        }
+        serializeTo(fos);
+    }
+
+    public static void testFrom(String filename) {
+        FileInputStream fis;
+        try {
+            fis = new FileInputStream(makeFile(filename));
+        } catch (IOException ioe) {
+            throw new InternalError("bad input filename: "+filename);
+        }
+        testFrom(fis);
+    }
+
+    public static void testSerial() {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        serializeTo(baos);
+
+        byte buf[] = baos.toByteArray();
+        ByteArrayInputStream bais = new ByteArrayInputStream(buf);
+
+        testFrom(bais);
+    }
+
+    public static void serializeTo(OutputStream os) {
+        try {
+            ObjectOutputStream oos = new ObjectOutputStream(os);
+
+            for (Object o1: testobjects) {
+                oos.writeObject(o1);
+            }
+
+            oos.close();
+        } catch (IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+    }
+
+    public static void testFrom(InputStream is) {
+        try {
+            ObjectInputStream ois = new ObjectInputStream(is);
+
+            for (Object o1: testobjects) {
+                Object o2 = ois.readObject();
+                if (o1 instanceof Shape) {
+                    compareShapes((Shape) o1, (Shape) o2);
+                } else {
+                    if (!o1.equals(o2)) {
+                        error(o1, o2, "objects not equal");
+                    }
+                }
+            }
+
+            try {
+                ois.readObject();
+                throw new RuntimeException("extra data in stream");
+            } catch (IOException ioe2) {
+            }
+        } catch (IOException ioe) {
+            throw new RuntimeException(ioe);
+        } catch (ClassNotFoundException cnfe) {
+            throw new RuntimeException(cnfe);
+        }
+    }
+
+    public static void compareShapes(Shape s1, Shape s2) {
+        PathIterator pi1 = s1.getPathIterator(null);
+        PathIterator pi2 = s2.getPathIterator(null);
+
+        if (pi1.getWindingRule() != pi2.getWindingRule()) {
+            error(s1, s2, "winding rules are different");
+        }
+
+        double coords1[] = new double[6];
+        double coords2[] = new double[6];
+
+        while (!pi1.isDone()) {
+            if (pi2.isDone()) {
+                error(s1, s2, "Shape 2 ended prematurely");
+                return;
+            }
+
+            int t1 = pi1.currentSegment(coords1);
+            int t2 = pi2.currentSegment(coords2);
+
+            if (t1 != t2) {
+                error(s1, s2, "different segment types");
+            }
+
+            int ncoords;
+            switch (t1) {
+            case PathIterator.SEG_MOVETO:  ncoords = 2; break;
+            case PathIterator.SEG_LINETO:  ncoords = 2; break;
+            case PathIterator.SEG_QUADTO:  ncoords = 4; break;
+            case PathIterator.SEG_CUBICTO: ncoords = 6; break;
+            case PathIterator.SEG_CLOSE:   ncoords = 0; break;
+
+            default:
+                throw new RuntimeException("unknown segment type");
+            }
+
+            for (int i = 0; i < ncoords; i++) {
+                if (coords1[i] != coords2[i]) {
+                    error(s1, s2, "coordinates differ");
+                }
+            }
+            pi1.next();
+            pi2.next();
+        }
+
+        if (!pi2.isDone()) {
+            error(s1, s2, "Shape 1 ended prematurely");
+        }
+    }
+}
Binary file test/jdk/java/awt/geom/serial_1_6.out has changed