1 /*
   2  * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 
  25 import java.awt.Rectangle;
  26 import java.awt.geom.AffineTransform;
  27 import java.awt.geom.GeneralPath;
  28 import java.awt.geom.IllegalPathStateException;
  29 import java.awt.geom.Path2D;
  30 import java.awt.geom.PathIterator;
  31 import java.awt.geom.Point2D;
  32 import java.awt.geom.Rectangle2D;
  33 import java.util.Arrays;
  34 
  35 /**
  36  * @test
  37  * @bug 8076419 8078192
  38  * @summary Check Path2D copy constructor (trims arrays)
  39  *          and constructor with zero capacity
  40  *          and Path2D.trimToSize()
  41  * @run main Path2DCopyConstructor
  42  */
  43 public class Path2DCopyConstructor {
  44 
  45     private final static float EPSILON = 5e-6f;
  46     private final static float FLATNESS = 1e-2f;
  47 
  48     private final static AffineTransform at
  49         = AffineTransform.getScaleInstance(1.3, 2.4);
  50 
  51     private final static Rectangle2D.Double rect2d
  52         = new Rectangle2D.Double(3.2, 4.1, 5.0, 10.0);
  53 
  54     private final static Point2D.Double pt2d
  55         = new Point2D.Double(2.0, 2.5);
  56 
  57     public static boolean verbose;
  58 
  59     static void log(String msg) {
  60         if (verbose) {
  61             System.out.println(msg);
  62         }
  63     }
  64 
  65     public static void main(String argv[]) {
  66         verbose = (argv.length != 0);
  67 
  68         testEmptyDoublePaths();
  69         testDoublePaths();
  70 
  71         testEmptyFloatPaths();
  72         testFloatPaths();
  73 
  74         testEmptyGeneralPath();
  75         testGeneralPath();
  76     }
  77 
  78     static void testEmptyDoublePaths() {
  79         log("\n - Test(Path2D.Double[0]) ---");
  80         test(() -> new Path2D.Double(Path2D.WIND_NON_ZERO, 0));
  81     }
  82 
  83     static void testDoublePaths() {
  84         log("\n - Test(Path2D.Double) ---");
  85         test(() -> new Path2D.Double());
  86     }
  87 
  88     static void testEmptyFloatPaths() {
  89         log("\n - Test(Path2D.Float[0]) ---");
  90         test(() -> new Path2D.Float(Path2D.WIND_NON_ZERO, 0));
  91     }
  92 
  93     static void testFloatPaths() {
  94         log("\n - Test(Path2D.Float) ---");
  95         test(() -> new Path2D.Float());
  96     }
  97 
  98     static void testEmptyGeneralPath() {
  99         log("\n - Test(GeneralPath[0]) ---");
 100         test(() -> new GeneralPath(Path2D.WIND_NON_ZERO, 0));
 101     }
 102 
 103     static void testGeneralPath() {
 104         log("\n - Test(GeneralPath) ---");
 105         test(() -> new GeneralPath());
 106     }
 107 
 108     interface PathFactory {
 109         Path2D makePath();
 110     }
 111 
 112     static void test(PathFactory pf) {
 113         log("\n --- test: path(empty) ---");
 114         test(pf.makePath(), true);
 115         log("\n\n --- test: path(addMove) ---");
 116         test(addMove(pf.makePath()), false);
 117         log("\n\n --- test: path(addMoveAndLines) ---");
 118         test(addMoveAndLines(pf.makePath()), false);
 119         log("\n\n --- test: path(addMoveAndQuads) ---");
 120         test(addMoveAndQuads(pf.makePath()), false);
 121         log("\n\n --- test: path(addMoveAndCubics) ---");
 122         test(addMoveAndCubics(pf.makePath()), false);
 123         log("\n\n --- test: path(addMoveAndClose) ---");
 124         test(addMoveAndClose(pf.makePath()), false);
 125     }
 126 
 127     static Path2D addMove(Path2D p2d) {
 128         p2d.moveTo(1.0, 0.5);
 129         return p2d;
 130     }
 131 
 132     static Path2D addMoveAndLines(Path2D p2d) {
 133         addMove(p2d);
 134         addLines(p2d);
 135         return p2d;
 136     }
 137 
 138     static Path2D addLines(Path2D p2d) {
 139         for (int i = 0; i < 10; i++) {
 140             p2d.lineTo(1.1 * i, 2.3 * i);
 141         }
 142         return p2d;
 143     }
 144 
 145     static Path2D addMoveAndCubics(Path2D p2d) {
 146         addMove(p2d);
 147         addCubics(p2d);
 148         return p2d;
 149     }
 150 
 151     static Path2D addCubics(Path2D p2d) {
 152         for (int i = 0; i < 10; i++) {
 153             p2d.curveTo(1.1 * i, 1.2 * i, 1.3 * i, 1.4 * i, 1.5 * i, 1.6 * i);
 154         }
 155         return p2d;
 156     }
 157 
 158     static Path2D addMoveAndQuads(Path2D p2d) {
 159         addMove(p2d);
 160         addQuads(p2d);
 161         return p2d;
 162     }
 163 
 164     static Path2D addQuads(Path2D p2d) {
 165         for (int i = 0; i < 10; i++) {
 166             p2d.quadTo(1.1 * i, 1.2 * i, 1.3 * i, 1.4 * i);
 167         }
 168         return p2d;
 169     }
 170 
 171     static Path2D addMoveAndClose(Path2D p2d) {
 172         addMove(p2d);
 173         addClose(p2d);
 174         return p2d;
 175     }
 176 
 177     static Path2D addClose(Path2D p2d) {
 178         p2d.closePath();
 179         return p2d;
 180     }
 181 
 182     static void test(Path2D p2d, boolean isEmpty) {
 183         Path2D c;
 184         Path2D.Float pf;
 185         Path2D.Double pd;
 186         GeneralPath gp;
 187 
 188         pf = new Path2D.Float(p2d);
 189         testEqual(pf, p2d);
 190         pf.trimToSize();
 191         testEqual(pf, p2d);
 192         pd = new Path2D.Double(p2d);
 193         testEqual(pd, p2d);
 194         pd.trimToSize();
 195         testEqual(pd, p2d);
 196         c = (Path2D)p2d.clone();
 197         testEqual(c, p2d);
 198         c.trimToSize();
 199         testEqual(c, p2d);
 200         gp = new GeneralPath(p2d);
 201         testEqual(gp, p2d);
 202         gp.trimToSize();
 203         testEqual(gp, p2d);
 204 
 205         pf = new Path2D.Float(p2d);
 206         testIterator(pf, p2d);
 207         pf.trimToSize();
 208         testIterator(pf, p2d);
 209         pd = new Path2D.Double(p2d);
 210         testIterator(pd, p2d);
 211         pd.trimToSize();
 212         testIterator(pd, p2d);
 213         c = (Path2D)p2d.clone();
 214         testIterator(c, p2d);
 215         c.trimToSize();
 216         testIterator(c, p2d);
 217         gp = new GeneralPath(p2d);
 218         testIterator(gp, p2d);
 219         gp.trimToSize();
 220         testIterator(gp, p2d);
 221 
 222         pf = new Path2D.Float(p2d);
 223         testFlattening(pf, p2d);
 224         pf.trimToSize();
 225         testFlattening(pf, p2d);
 226         pd = new Path2D.Double(p2d);
 227         testFlattening(pd, p2d);
 228         pd.trimToSize();
 229         testFlattening(pd, p2d);
 230         c = (Path2D)p2d.clone();
 231         testFlattening(c, p2d);
 232         c.trimToSize();
 233         testFlattening(c, p2d);
 234         gp = new GeneralPath(p2d);
 235         testFlattening(gp, p2d);
 236         gp.trimToSize();
 237         testFlattening(gp, p2d);
 238 
 239         pf = new Path2D.Float(p2d);
 240         testAddMove(pf);
 241         pf.trimToSize();
 242         testAddMove(pf);
 243         pd = new Path2D.Double(p2d);
 244         testAddMove(pd);
 245         pd.trimToSize();
 246         testAddMove(pd);
 247         c = (Path2D)p2d.clone();
 248         testAddMove(c);
 249         c.trimToSize();
 250         testAddMove(c);
 251         gp = new GeneralPath(p2d);
 252         testAddMove(gp);
 253         gp.trimToSize();
 254         testAddMove(gp);
 255 
 256         // These should expect exception if empty
 257         pf = new Path2D.Float(p2d);
 258         testAddLine(pf, isEmpty);
 259         pf.trimToSize();
 260         testAddLine(pf, isEmpty);
 261         pd = new Path2D.Double(p2d);
 262         testAddLine(pd, isEmpty);
 263         pd.trimToSize();
 264         testAddLine(pd, isEmpty);
 265         c = (Path2D)p2d.clone();
 266         testAddLine(c, isEmpty);
 267         c.trimToSize();
 268         testAddLine(c, isEmpty);
 269         gp = new GeneralPath(p2d);
 270         testAddLine(gp, isEmpty);
 271         gp.trimToSize();
 272         testAddLine(gp, isEmpty);
 273 
 274         pf = new Path2D.Float(p2d);
 275         testAddQuad(pf, isEmpty);
 276         pf.trimToSize();
 277         testAddQuad(pf, isEmpty);
 278         pd = new Path2D.Double(p2d);
 279         testAddQuad(pd, isEmpty);
 280         pd.trimToSize();
 281         testAddQuad(pd, isEmpty);
 282         c = (Path2D)p2d.clone();
 283         testAddQuad(c, isEmpty);
 284         c.trimToSize();
 285         testAddQuad(c, isEmpty);
 286         gp = new GeneralPath(p2d);
 287         testAddQuad(gp, isEmpty);
 288         gp.trimToSize();
 289         testAddQuad(gp, isEmpty);
 290 
 291         pf = new Path2D.Float(p2d);
 292         testAddCubic(pf, isEmpty);
 293         pf.trimToSize();
 294         testAddCubic(pf, isEmpty);
 295         pd = new Path2D.Double(p2d);
 296         testAddCubic(pd, isEmpty);
 297         pd.trimToSize();
 298         testAddCubic(pd, isEmpty);
 299         c = (Path2D)p2d.clone();
 300         testAddCubic(c, isEmpty);
 301         c.trimToSize();
 302         testAddCubic(c, isEmpty);
 303         gp = new GeneralPath(p2d);
 304         testAddCubic(gp, isEmpty);
 305         gp.trimToSize();
 306         testAddCubic(gp, isEmpty);
 307 
 308         pf = new Path2D.Float(p2d);
 309         testAddClose(pf, isEmpty);
 310         pf.trimToSize();
 311         testAddClose(pf, isEmpty);
 312         pd = new Path2D.Double(p2d);
 313         testAddClose(pd, isEmpty);
 314         pd.trimToSize();
 315         testAddClose(pd, isEmpty);
 316         c = (Path2D)p2d.clone();
 317         testAddClose(c, isEmpty);
 318         c.trimToSize();
 319         testAddClose(c, isEmpty);
 320         gp = new GeneralPath(p2d);
 321         testAddClose(gp, isEmpty);
 322         gp.trimToSize();
 323         testAddClose(gp, isEmpty);
 324 
 325         pf = new Path2D.Float(p2d);
 326         testGetBounds(pf, p2d);
 327         pf.trimToSize();
 328         testGetBounds(pf, p2d);
 329         pd = new Path2D.Double(p2d);
 330         testGetBounds(pd, p2d);
 331         pd.trimToSize();
 332         testGetBounds(pd, p2d);
 333         c = (Path2D)p2d.clone();
 334         testGetBounds(c, p2d);
 335         c.trimToSize();
 336         testGetBounds(c, p2d);
 337         gp = new GeneralPath(p2d);
 338         testGetBounds(gp, p2d);
 339         gp.trimToSize();
 340         testGetBounds(gp, p2d);
 341 
 342         pf = new Path2D.Float(p2d);
 343         testTransform(pf);
 344         pf.trimToSize();
 345         testTransform(pf);
 346         pd = new Path2D.Double(p2d);
 347         testTransform(pd);
 348         pd.trimToSize();
 349         testTransform(pd);
 350         c = (Path2D)p2d.clone();
 351         testTransform(c);
 352         c.trimToSize();
 353         testTransform(c);
 354         gp = new GeneralPath(p2d);
 355         testTransform(gp);
 356         gp.trimToSize();
 357         testTransform(gp);
 358 
 359         pf = new Path2D.Float(p2d);
 360         testIntersect(pf, p2d);
 361         pf.trimToSize();
 362         testIntersect(pf, p2d);
 363         pd = new Path2D.Double(p2d);
 364         testIntersect(pd, p2d);
 365         pd.trimToSize();
 366         testIntersect(pd, p2d);
 367         c = (Path2D)p2d.clone();
 368         testIntersect(c, p2d);
 369         c.trimToSize();
 370         testIntersect(c, p2d);
 371         gp = new GeneralPath(p2d);
 372         testIntersect(gp, p2d);
 373         gp.trimToSize();
 374         testIntersect(gp, p2d);
 375 
 376         pf = new Path2D.Float(p2d);
 377         testContains(pf, p2d);
 378         pf.trimToSize();
 379         testContains(pf, p2d);
 380         pd = new Path2D.Double(p2d);
 381         testContains(pd, p2d);
 382         pd.trimToSize();
 383         testContains(pd, p2d);
 384         c = (Path2D)p2d.clone();
 385         testContains(c, p2d);
 386         c.trimToSize();
 387         testContains(c, p2d);
 388         gp = new GeneralPath(p2d);
 389         testContains(gp, p2d);
 390         gp.trimToSize();
 391         testContains(gp, p2d);
 392 
 393         pf = new Path2D.Float(p2d);
 394         testGetCurrentPoint(pf, p2d);
 395         pf.trimToSize();
 396         testGetCurrentPoint(pf, p2d);
 397         pd = new Path2D.Double(p2d);
 398         testGetCurrentPoint(pd, p2d);
 399         pd.trimToSize();
 400         testGetCurrentPoint(pd, p2d);
 401         c = (Path2D)p2d.clone();
 402         testGetCurrentPoint(c, p2d);
 403         c.trimToSize();
 404         testGetCurrentPoint(c, p2d);
 405         gp = new GeneralPath(p2d);
 406         testGetCurrentPoint(gp, p2d);
 407         gp.trimToSize();
 408         testGetCurrentPoint(gp, p2d);
 409     }
 410 
 411     static void testEqual(Path2D pathA, Path2D pathB) {
 412         final PathIterator itA = pathA.getPathIterator(null);
 413         final PathIterator itB = pathB.getPathIterator(null);
 414 
 415         float[] coordsA = new float[6];
 416         float[] coordsB = new float[6];
 417 
 418         int n = 0;
 419         for (; !itA.isDone() && !itB.isDone(); itA.next(), itB.next(), n++) {
 420             int typeA = itA.currentSegment(coordsA);
 421             int typeB = itB.currentSegment(coordsB);
 422 
 423             if (typeA != typeB) {
 424                 throw new IllegalStateException("Path-segment[" + n + "] "
 425                     + " type are not equals [" + typeA + "|" + typeB + "] !");
 426             }
 427             if (!equalsArray(coordsA, coordsB, getLength(typeA))) {
 428                 throw new IllegalStateException("Path-segment[" + n + "] coords"
 429                     + " are not equals [" + Arrays.toString(coordsA) + "|"
 430                     + Arrays.toString(coordsB) + "] !");
 431             }
 432         }
 433         if (!itA.isDone() || !itB.isDone()) {
 434             throw new IllegalStateException("Paths do not have same lengths !");
 435         }
 436         log("testEqual: " + n + " segments.");
 437     }
 438 
 439     static void testIterator(Path2D pathA, Path2D pathB) {
 440         final PathIterator itA = pathA.getPathIterator(at);
 441         final PathIterator itB = pathB.getPathIterator(at);
 442 
 443         float[] coordsA = new float[6];
 444         float[] coordsB = new float[6];
 445 
 446         int n = 0;
 447         for (; !itA.isDone() && !itB.isDone(); itA.next(), itB.next(), n++) {
 448             int typeA = itA.currentSegment(coordsA);
 449             int typeB = itB.currentSegment(coordsB);
 450 
 451             if (typeA != typeB) {
 452                 throw new IllegalStateException("Path-segment[" + n + "] "
 453                     + "type are not equals [" + typeA + "|" + typeB + "] !");
 454             }
 455             // Take care of floating-point precision:
 456             if (!equalsArrayEps(coordsA, coordsB, getLength(typeA))) {
 457                 throw new IllegalStateException("Path-segment[" + n + "] coords"
 458                     + " are not equals [" + Arrays.toString(coordsA) + "|"
 459                     + Arrays.toString(coordsB) + "] !");
 460             }
 461         }
 462         if (!itA.isDone() || !itB.isDone()) {
 463             throw new IllegalStateException("Paths do not have same lengths !");
 464         }
 465         log("testIterator: " + n + " segments.");
 466     }
 467 
 468     static void testFlattening(Path2D pathA, Path2D pathB) {
 469         final PathIterator itA = pathA.getPathIterator(at, FLATNESS);
 470         final PathIterator itB = pathB.getPathIterator(at, FLATNESS);
 471 
 472         float[] coordsA = new float[6];
 473         float[] coordsB = new float[6];
 474 
 475         int n = 0;
 476         for (; !itA.isDone() && !itB.isDone(); itA.next(), itB.next(), n++) {
 477             int typeA = itA.currentSegment(coordsA);
 478             int typeB = itB.currentSegment(coordsB);
 479 
 480             if (typeA != typeB) {
 481                 throw new IllegalStateException("Path-segment[" + n + "] "
 482                     + "type are not equals [" + typeA + "|" + typeB + "] !");
 483             }
 484             // Take care of floating-point precision:
 485             if (!equalsArrayEps(coordsA, coordsB, getLength(typeA))) {
 486                 throw new IllegalStateException("Path-segment[" + n + "] coords"
 487                     + " are not equals [" + Arrays.toString(coordsA) + "|"
 488                     + Arrays.toString(coordsB) + "] !");
 489             }
 490         }
 491         if (!itA.isDone() || !itB.isDone()) {
 492             throw new IllegalStateException("Paths do not have same lengths !");
 493         }
 494         log("testFlattening: " + n + " segments.");
 495     }
 496 
 497     static void testAddMove(Path2D pathA) {
 498         addMove(pathA);
 499         log("testAddMove: passed.");
 500     }
 501 
 502     static void testAddLine(Path2D pathA, boolean isEmpty) {
 503         try {
 504             addLines(pathA);
 505         }
 506         catch (IllegalPathStateException ipse) {
 507             if (isEmpty) {
 508                 log("testAddLine: passed "
 509                     + "(expected IllegalPathStateException catched).");
 510                 return;
 511             } else {
 512                 throw ipse;
 513             }
 514         }
 515         if (isEmpty) {
 516             throw new IllegalStateException("IllegalPathStateException not thrown !");
 517         }
 518         log("testAddLine: passed.");
 519     }
 520 
 521     static void testAddQuad(Path2D pathA, boolean isEmpty) {
 522         try {
 523             addQuads(pathA);
 524         }
 525         catch (IllegalPathStateException ipse) {
 526             if (isEmpty) {
 527                 log("testAddQuad: passed "
 528                     + "(expected IllegalPathStateException catched).");
 529                 return;
 530             } else {
 531                 throw ipse;
 532             }
 533         }
 534         if (isEmpty) {
 535             throw new IllegalStateException("IllegalPathStateException not thrown !");
 536         }
 537         log("testAddQuad: passed.");
 538     }
 539 
 540     static void testAddCubic(Path2D pathA, boolean isEmpty) {
 541         try {
 542             addCubics(pathA);
 543         }
 544         catch (IllegalPathStateException ipse) {
 545             if (isEmpty) {
 546                 log("testAddCubic: passed "
 547                     + "(expected IllegalPathStateException catched).");
 548                 return;
 549             } else {
 550                 throw ipse;
 551             }
 552         }
 553         if (isEmpty) {
 554             throw new IllegalStateException("IllegalPathStateException not thrown !");
 555         }
 556         log("testAddCubic: passed.");
 557     }
 558 
 559     static void testAddClose(Path2D pathA, boolean isEmpty) {
 560         try {
 561             addClose(pathA);
 562         }
 563         catch (IllegalPathStateException ipse) {
 564             if (isEmpty) {
 565                 log("testAddClose: passed "
 566                     + "(expected IllegalPathStateException catched).");
 567                 return;
 568             } else {
 569                 throw ipse;
 570             }
 571         }
 572         if (isEmpty) {
 573             throw new IllegalStateException("IllegalPathStateException not thrown !");
 574         }
 575         log("testAddClose: passed.");
 576     }
 577 
 578     static void testGetBounds(Path2D pathA, Path2D pathB) {
 579         final Rectangle rA = pathA.getBounds();
 580         final Rectangle rB = pathB.getBounds();
 581 
 582         if (!rA.equals(rB)) {
 583             throw new IllegalStateException("Bounds are not equals [" + rA
 584                 + "|" + rB + "] !");
 585         }
 586         final Rectangle2D r2dA = pathA.getBounds2D();
 587         final Rectangle2D r2dB = pathB.getBounds2D();
 588 
 589         if (!equalsRectangle2D(r2dA, r2dB)) {
 590             throw new IllegalStateException("Bounds2D are not equals ["
 591                 + r2dA + "|" + r2dB + "] !");
 592         }
 593         log("testGetBounds: passed.");
 594     }
 595 
 596     static void testTransform(Path2D pathA) {
 597         pathA.transform(at);
 598         log("testTransform: passed.");
 599     }
 600 
 601     static void testIntersect(Path2D pathA, Path2D pathB) {
 602         boolean resA = pathA.intersects(rect2d);
 603         boolean resB = pathB.intersects(rect2d);
 604         if (resA != resB) {
 605             throw new IllegalStateException("Intersects(rect2d) are not equals ["
 606                 + resA + "|" + resB + "] !");
 607         }
 608         resA = pathA.intersects(1.0, 2.0, 13.0, 17.0);
 609         resB = pathB.intersects(1.0, 2.0, 13.0, 17.0);
 610         if (resA != resB) {
 611             throw new IllegalStateException("Intersects(doubles) are not equals ["
 612                 + resA + "|" + resB + "] !");
 613         }
 614         log("testIntersect: passed.");
 615     }
 616 
 617     static void testContains(Path2D pathA, Path2D pathB) {
 618         boolean resA = pathA.contains(pt2d);
 619         boolean resB = pathB.contains(pt2d);
 620         if (resA != resB) {
 621             throw new IllegalStateException("Contains(pt) are not equals ["
 622                 + resA + "|" + resB + "] !");
 623         }
 624         resA = pathA.contains(pt2d.getX(), pt2d.getY());
 625         resB = pathB.contains(pt2d.getX(), pt2d.getY());
 626         if (resA != resB) {
 627             throw new IllegalStateException("Contains(x,y) are not equals ["
 628                 + resA + "|" + resB + "] !");
 629         }
 630         resA = pathA.contains(rect2d);
 631         resB = pathB.contains(rect2d);
 632         if (resA != resB) {
 633             throw new IllegalStateException("Contains(rect2d) are not equals ["
 634                 + resA + "|" + resB + "] !");
 635         }
 636         resA = pathA.contains(1.0, 2.0, 13.0, 17.0);
 637         resB = pathB.contains(1.0, 2.0, 13.0, 17.0);
 638         if (resA != resB) {
 639             throw new IllegalStateException("Contains(doubles) are not equals ["
 640                 + resA + "|" + resB + "] !");
 641         }
 642         log("testContains: passed.");
 643     }
 644 
 645     static void testGetCurrentPoint(Path2D pathA, Path2D pathB) {
 646         final Point2D ptA = pathA.getCurrentPoint();
 647         final Point2D ptB = pathA.getCurrentPoint();
 648         if (((ptA == null) && (ptB != null))
 649             || ((ptA != null) && !ptA.equals(ptB)))
 650         {
 651             throw new IllegalStateException("getCurrentPoint() are not equals ["
 652                 + ptA + "|" + ptB + "] !");
 653         }
 654         log("testGetCurrentPoint: passed.");
 655     }
 656 
 657     static int getLength(int type) {
 658         switch(type) {
 659             case PathIterator.SEG_CUBICTO:
 660                 return 6;
 661             case PathIterator.SEG_QUADTO:
 662                 return 4;
 663             case PathIterator.SEG_LINETO:
 664             case PathIterator.SEG_MOVETO:
 665                 return 2;
 666             case PathIterator.SEG_CLOSE:
 667                 return 0;
 668             default:
 669                 throw new IllegalStateException("Invalid type: " + type);
 670         }
 671     }
 672 
 673 
 674     // Custom equals methods ---
 675 
 676     public static boolean equalsArray(float[] a, float[] a2, final int len) {
 677         for (int i = 0; i < len; i++) {
 678             if (Float.floatToIntBits(a[i]) != Float.floatToIntBits(a2[i])) {
 679                 return false;
 680             }
 681         }
 682         return true;
 683     }
 684 
 685     static boolean equalsArrayEps(float[] a, float[] a2, final int len) {
 686         for (int i = 0; i < len; i++) {
 687             if (!equalsEps(a[i], a2[i])) {
 688                 return false;
 689             }
 690         }
 691 
 692         return true;
 693     }
 694 
 695     static boolean equalsRectangle2D(Rectangle2D a, Rectangle2D b) {
 696         if (a == b) {
 697             return true;
 698         }
 699         return equalsEps(a.getX(), b.getX())
 700             && equalsEps(a.getY(), b.getY())
 701             && equalsEps(a.getWidth(), b.getWidth())
 702             && equalsEps(a.getHeight(), b.getHeight());
 703     }
 704 
 705     static boolean equalsEps(float a, float b) {
 706         return (Math.abs(a - b) <= EPSILON);
 707     }
 708 
 709     static boolean equalsEps(double a, double b) {
 710         return (Math.abs(a - b) <= EPSILON);
 711     }
 712 }