1 /*
   2  * Copyright (c) 1997, 2011, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.awt.geom;
  27 
  28 import java.awt.Shape;
  29 import java.awt.Rectangle;
  30 import java.util.Arrays;
  31 import java.io.Serializable;
  32 import sun.awt.geom.Curve;
  33 
  34 import static java.lang.Math.abs;
  35 import static java.lang.Math.max;
  36 import static java.lang.Math.ulp;
  37 
  38 /**
  39  * The <code>CubicCurve2D</code> class defines a cubic parametric curve
  40  * segment in {@code (x,y)} coordinate space.
  41  * <p>
  42  * This class is only the abstract superclass for all objects which
  43  * store a 2D cubic curve segment.
  44  * The actual storage representation of the coordinates is left to
  45  * the subclass.
  46  *
  47  * @author      Jim Graham
  48  * @since 1.2
  49  */
  50 public abstract class CubicCurve2D implements Shape, Cloneable {
  51 
  52     /**
  53      * A cubic parametric curve segment specified with
  54      * {@code float} coordinates.
  55      * @since 1.2
  56      */
  57     public static class Float extends CubicCurve2D implements Serializable {
  58         /**
  59          * The X coordinate of the start point
  60          * of the cubic curve segment.
  61          * @since 1.2
  62          * @serial
  63          */
  64         public float x1;
  65 
  66         /**
  67          * The Y coordinate of the start point
  68          * of the cubic curve segment.
  69          * @since 1.2
  70          * @serial
  71          */
  72         public float y1;
  73 
  74         /**
  75          * The X coordinate of the first control point
  76          * of the cubic curve segment.
  77          * @since 1.2
  78          * @serial
  79          */
  80         public float ctrlx1;
  81 
  82         /**
  83          * The Y coordinate of the first control point
  84          * of the cubic curve segment.
  85          * @since 1.2
  86          * @serial
  87          */
  88         public float ctrly1;
  89 
  90         /**
  91          * The X coordinate of the second control point
  92          * of the cubic curve segment.
  93          * @since 1.2
  94          * @serial
  95          */
  96         public float ctrlx2;
  97 
  98         /**
  99          * The Y coordinate of the second control point
 100          * of the cubic curve segment.
 101          * @since 1.2
 102          * @serial
 103          */
 104         public float ctrly2;
 105 
 106         /**
 107          * The X coordinate of the end point
 108          * of the cubic curve segment.
 109          * @since 1.2
 110          * @serial
 111          */
 112         public float x2;
 113 
 114         /**
 115          * The Y coordinate of the end point
 116          * of the cubic curve segment.
 117          * @since 1.2
 118          * @serial
 119          */
 120         public float y2;
 121 
 122         /**
 123          * Constructs and initializes a CubicCurve with coordinates
 124          * (0, 0, 0, 0, 0, 0, 0, 0).
 125          * @since 1.2
 126          */
 127         public Float() {
 128         }
 129 
 130         /**
 131          * Constructs and initializes a {@code CubicCurve2D} from
 132          * the specified {@code float} coordinates.
 133          *
 134          * @param x1 the X coordinate for the start point
 135          *           of the resulting {@code CubicCurve2D}
 136          * @param y1 the Y coordinate for the start point
 137          *           of the resulting {@code CubicCurve2D}
 138          * @param ctrlx1 the X coordinate for the first control point
 139          *               of the resulting {@code CubicCurve2D}
 140          * @param ctrly1 the Y coordinate for the first control point
 141          *               of the resulting {@code CubicCurve2D}
 142          * @param ctrlx2 the X coordinate for the second control point
 143          *               of the resulting {@code CubicCurve2D}
 144          * @param ctrly2 the Y coordinate for the second control point
 145          *               of the resulting {@code CubicCurve2D}
 146          * @param x2 the X coordinate for the end point
 147          *           of the resulting {@code CubicCurve2D}
 148          * @param y2 the Y coordinate for the end point
 149          *           of the resulting {@code CubicCurve2D}
 150          * @since 1.2
 151          */
 152         public Float(float x1, float y1,
 153                      float ctrlx1, float ctrly1,
 154                      float ctrlx2, float ctrly2,
 155                      float x2, float y2)
 156         {
 157             setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2);
 158         }
 159 
 160         /**
 161          * {@inheritDoc}
 162          * @since 1.2
 163          */
 164         public double getX1() {
 165             return (double) x1;
 166         }
 167 
 168         /**
 169          * {@inheritDoc}
 170          * @since 1.2
 171          */
 172         public double getY1() {
 173             return (double) y1;
 174         }
 175 
 176         /**
 177          * {@inheritDoc}
 178          * @since 1.2
 179          */
 180         public Point2D getP1() {
 181             return new Point2D.Float(x1, y1);
 182         }
 183 
 184         /**
 185          * {@inheritDoc}
 186          * @since 1.2
 187          */
 188         public double getCtrlX1() {
 189             return (double) ctrlx1;
 190         }
 191 
 192         /**
 193          * {@inheritDoc}
 194          * @since 1.2
 195          */
 196         public double getCtrlY1() {
 197             return (double) ctrly1;
 198         }
 199 
 200         /**
 201          * {@inheritDoc}
 202          * @since 1.2
 203          */
 204         public Point2D getCtrlP1() {
 205             return new Point2D.Float(ctrlx1, ctrly1);
 206         }
 207 
 208         /**
 209          * {@inheritDoc}
 210          * @since 1.2
 211          */
 212         public double getCtrlX2() {
 213             return (double) ctrlx2;
 214         }
 215 
 216         /**
 217          * {@inheritDoc}
 218          * @since 1.2
 219          */
 220         public double getCtrlY2() {
 221             return (double) ctrly2;
 222         }
 223 
 224         /**
 225          * {@inheritDoc}
 226          * @since 1.2
 227          */
 228         public Point2D getCtrlP2() {
 229             return new Point2D.Float(ctrlx2, ctrly2);
 230         }
 231 
 232         /**
 233          * {@inheritDoc}
 234          * @since 1.2
 235          */
 236         public double getX2() {
 237             return (double) x2;
 238         }
 239 
 240         /**
 241          * {@inheritDoc}
 242          * @since 1.2
 243          */
 244         public double getY2() {
 245             return (double) y2;
 246         }
 247 
 248         /**
 249          * {@inheritDoc}
 250          * @since 1.2
 251          */
 252         public Point2D getP2() {
 253             return new Point2D.Float(x2, y2);
 254         }
 255 
 256         /**
 257          * {@inheritDoc}
 258          * @since 1.2
 259          */
 260         public void setCurve(double x1, double y1,
 261                              double ctrlx1, double ctrly1,
 262                              double ctrlx2, double ctrly2,
 263                              double x2, double y2)
 264         {
 265             this.x1     = (float) x1;
 266             this.y1     = (float) y1;
 267             this.ctrlx1 = (float) ctrlx1;
 268             this.ctrly1 = (float) ctrly1;
 269             this.ctrlx2 = (float) ctrlx2;
 270             this.ctrly2 = (float) ctrly2;
 271             this.x2     = (float) x2;
 272             this.y2     = (float) y2;
 273         }
 274 
 275         /**
 276          * Sets the location of the end points and control points
 277          * of this curve to the specified {@code float} coordinates.
 278          *
 279          * @param x1 the X coordinate used to set the start point
 280          *           of this {@code CubicCurve2D}
 281          * @param y1 the Y coordinate used to set the start point
 282          *           of this {@code CubicCurve2D}
 283          * @param ctrlx1 the X coordinate used to set the first control point
 284          *               of this {@code CubicCurve2D}
 285          * @param ctrly1 the Y coordinate used to set the first control point
 286          *               of this {@code CubicCurve2D}
 287          * @param ctrlx2 the X coordinate used to set the second control point
 288          *               of this {@code CubicCurve2D}
 289          * @param ctrly2 the Y coordinate used to set the second control point
 290          *               of this {@code CubicCurve2D}
 291          * @param x2 the X coordinate used to set the end point
 292          *           of this {@code CubicCurve2D}
 293          * @param y2 the Y coordinate used to set the end point
 294          *           of this {@code CubicCurve2D}
 295          * @since 1.2
 296          */
 297         public void setCurve(float x1, float y1,
 298                              float ctrlx1, float ctrly1,
 299                              float ctrlx2, float ctrly2,
 300                              float x2, float y2)
 301         {
 302             this.x1     = x1;
 303             this.y1     = y1;
 304             this.ctrlx1 = ctrlx1;
 305             this.ctrly1 = ctrly1;
 306             this.ctrlx2 = ctrlx2;
 307             this.ctrly2 = ctrly2;
 308             this.x2     = x2;
 309             this.y2     = y2;
 310         }
 311 
 312         /**
 313          * {@inheritDoc}
 314          * @since 1.2
 315          */
 316         public Rectangle2D getBounds2D() {
 317             float left   = Math.min(Math.min(x1, x2),
 318                                     Math.min(ctrlx1, ctrlx2));
 319             float top    = Math.min(Math.min(y1, y2),
 320                                     Math.min(ctrly1, ctrly2));
 321             float right  = Math.max(Math.max(x1, x2),
 322                                     Math.max(ctrlx1, ctrlx2));
 323             float bottom = Math.max(Math.max(y1, y2),
 324                                     Math.max(ctrly1, ctrly2));
 325             return new Rectangle2D.Float(left, top,
 326                                          right - left, bottom - top);
 327         }
 328 
 329         /*
 330          * JDK 1.6 serialVersionUID
 331          */
 332         private static final long serialVersionUID = -1272015596714244385L;
 333     }
 334 
 335     /**
 336      * A cubic parametric curve segment specified with
 337      * {@code double} coordinates.
 338      * @since 1.2
 339      */
 340     public static class Double extends CubicCurve2D implements Serializable {
 341         /**
 342          * The X coordinate of the start point
 343          * of the cubic curve segment.
 344          * @since 1.2
 345          * @serial
 346          */
 347         public double x1;
 348 
 349         /**
 350          * The Y coordinate of the start point
 351          * of the cubic curve segment.
 352          * @since 1.2
 353          * @serial
 354          */
 355         public double y1;
 356 
 357         /**
 358          * The X coordinate of the first control point
 359          * of the cubic curve segment.
 360          * @since 1.2
 361          * @serial
 362          */
 363         public double ctrlx1;
 364 
 365         /**
 366          * The Y coordinate of the first control point
 367          * of the cubic curve segment.
 368          * @since 1.2
 369          * @serial
 370          */
 371         public double ctrly1;
 372 
 373         /**
 374          * The X coordinate of the second control point
 375          * of the cubic curve segment.
 376          * @since 1.2
 377          * @serial
 378          */
 379         public double ctrlx2;
 380 
 381         /**
 382          * The Y coordinate of the second control point
 383          * of the cubic curve segment.
 384          * @since 1.2
 385          * @serial
 386          */
 387         public double ctrly2;
 388 
 389         /**
 390          * The X coordinate of the end point
 391          * of the cubic curve segment.
 392          * @since 1.2
 393          * @serial
 394          */
 395         public double x2;
 396 
 397         /**
 398          * The Y coordinate of the end point
 399          * of the cubic curve segment.
 400          * @since 1.2
 401          * @serial
 402          */
 403         public double y2;
 404 
 405         /**
 406          * Constructs and initializes a CubicCurve with coordinates
 407          * (0, 0, 0, 0, 0, 0, 0, 0).
 408          * @since 1.2
 409          */
 410         public Double() {
 411         }
 412 
 413         /**
 414          * Constructs and initializes a {@code CubicCurve2D} from
 415          * the specified {@code double} coordinates.
 416          *
 417          * @param x1 the X coordinate for the start point
 418          *           of the resulting {@code CubicCurve2D}
 419          * @param y1 the Y coordinate for the start point
 420          *           of the resulting {@code CubicCurve2D}
 421          * @param ctrlx1 the X coordinate for the first control point
 422          *               of the resulting {@code CubicCurve2D}
 423          * @param ctrly1 the Y coordinate for the first control point
 424          *               of the resulting {@code CubicCurve2D}
 425          * @param ctrlx2 the X coordinate for the second control point
 426          *               of the resulting {@code CubicCurve2D}
 427          * @param ctrly2 the Y coordinate for the second control point
 428          *               of the resulting {@code CubicCurve2D}
 429          * @param x2 the X coordinate for the end point
 430          *           of the resulting {@code CubicCurve2D}
 431          * @param y2 the Y coordinate for the end point
 432          *           of the resulting {@code CubicCurve2D}
 433          * @since 1.2
 434          */
 435         public Double(double x1, double y1,
 436                       double ctrlx1, double ctrly1,
 437                       double ctrlx2, double ctrly2,
 438                       double x2, double y2)
 439         {
 440             setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2);
 441         }
 442 
 443         /**
 444          * {@inheritDoc}
 445          * @since 1.2
 446          */
 447         public double getX1() {
 448             return x1;
 449         }
 450 
 451         /**
 452          * {@inheritDoc}
 453          * @since 1.2
 454          */
 455         public double getY1() {
 456             return y1;
 457         }
 458 
 459         /**
 460          * {@inheritDoc}
 461          * @since 1.2
 462          */
 463         public Point2D getP1() {
 464             return new Point2D.Double(x1, y1);
 465         }
 466 
 467         /**
 468          * {@inheritDoc}
 469          * @since 1.2
 470          */
 471         public double getCtrlX1() {
 472             return ctrlx1;
 473         }
 474 
 475         /**
 476          * {@inheritDoc}
 477          * @since 1.2
 478          */
 479         public double getCtrlY1() {
 480             return ctrly1;
 481         }
 482 
 483         /**
 484          * {@inheritDoc}
 485          * @since 1.2
 486          */
 487         public Point2D getCtrlP1() {
 488             return new Point2D.Double(ctrlx1, ctrly1);
 489         }
 490 
 491         /**
 492          * {@inheritDoc}
 493          * @since 1.2
 494          */
 495         public double getCtrlX2() {
 496             return ctrlx2;
 497         }
 498 
 499         /**
 500          * {@inheritDoc}
 501          * @since 1.2
 502          */
 503         public double getCtrlY2() {
 504             return ctrly2;
 505         }
 506 
 507         /**
 508          * {@inheritDoc}
 509          * @since 1.2
 510          */
 511         public Point2D getCtrlP2() {
 512             return new Point2D.Double(ctrlx2, ctrly2);
 513         }
 514 
 515         /**
 516          * {@inheritDoc}
 517          * @since 1.2
 518          */
 519         public double getX2() {
 520             return x2;
 521         }
 522 
 523         /**
 524          * {@inheritDoc}
 525          * @since 1.2
 526          */
 527         public double getY2() {
 528             return y2;
 529         }
 530 
 531         /**
 532          * {@inheritDoc}
 533          * @since 1.2
 534          */
 535         public Point2D getP2() {
 536             return new Point2D.Double(x2, y2);
 537         }
 538 
 539         /**
 540          * {@inheritDoc}
 541          * @since 1.2
 542          */
 543         public void setCurve(double x1, double y1,
 544                              double ctrlx1, double ctrly1,
 545                              double ctrlx2, double ctrly2,
 546                              double x2, double y2)
 547         {
 548             this.x1     = x1;
 549             this.y1     = y1;
 550             this.ctrlx1 = ctrlx1;
 551             this.ctrly1 = ctrly1;
 552             this.ctrlx2 = ctrlx2;
 553             this.ctrly2 = ctrly2;
 554             this.x2     = x2;
 555             this.y2     = y2;
 556         }
 557 
 558         /**
 559          * {@inheritDoc}
 560          * @since 1.2
 561          */
 562         public Rectangle2D getBounds2D() {
 563             double left   = Math.min(Math.min(x1, x2),
 564                                      Math.min(ctrlx1, ctrlx2));
 565             double top    = Math.min(Math.min(y1, y2),
 566                                      Math.min(ctrly1, ctrly2));
 567             double right  = Math.max(Math.max(x1, x2),
 568                                      Math.max(ctrlx1, ctrlx2));
 569             double bottom = Math.max(Math.max(y1, y2),
 570                                      Math.max(ctrly1, ctrly2));
 571             return new Rectangle2D.Double(left, top,
 572                                           right - left, bottom - top);
 573         }
 574 
 575         /*
 576          * JDK 1.6 serialVersionUID
 577          */
 578         private static final long serialVersionUID = -4202960122839707295L;
 579     }
 580 
 581     /**
 582      * This is an abstract class that cannot be instantiated directly.
 583      * Type-specific implementation subclasses are available for
 584      * instantiation and provide a number of formats for storing
 585      * the information necessary to satisfy the various accessor
 586      * methods below.
 587      *
 588      * @see java.awt.geom.CubicCurve2D.Float
 589      * @see java.awt.geom.CubicCurve2D.Double
 590      * @since 1.2
 591      */
 592     protected CubicCurve2D() {
 593     }
 594 
 595     /**
 596      * Returns the X coordinate of the start point in double precision.
 597      * @return the X coordinate of the start point of the
 598      *         {@code CubicCurve2D}.
 599      * @since 1.2
 600      */
 601     public abstract double getX1();
 602 
 603     /**
 604      * Returns the Y coordinate of the start point in double precision.
 605      * @return the Y coordinate of the start point of the
 606      *         {@code CubicCurve2D}.
 607      * @since 1.2
 608      */
 609     public abstract double getY1();
 610 
 611     /**
 612      * Returns the start point.
 613      * @return a {@code Point2D} that is the start point of
 614      *         the {@code CubicCurve2D}.
 615      * @since 1.2
 616      */
 617     public abstract Point2D getP1();
 618 
 619     /**
 620      * Returns the X coordinate of the first control point in double precision.
 621      * @return the X coordinate of the first control point of the
 622      *         {@code CubicCurve2D}.
 623      * @since 1.2
 624      */
 625     public abstract double getCtrlX1();
 626 
 627     /**
 628      * Returns the Y coordinate of the first control point in double precision.
 629      * @return the Y coordinate of the first control point of the
 630      *         {@code CubicCurve2D}.
 631      * @since 1.2
 632      */
 633     public abstract double getCtrlY1();
 634 
 635     /**
 636      * Returns the first control point.
 637      * @return a {@code Point2D} that is the first control point of
 638      *         the {@code CubicCurve2D}.
 639      * @since 1.2
 640      */
 641     public abstract Point2D getCtrlP1();
 642 
 643     /**
 644      * Returns the X coordinate of the second control point
 645      * in double precision.
 646      * @return the X coordinate of the second control point of the
 647      *         {@code CubicCurve2D}.
 648      * @since 1.2
 649      */
 650     public abstract double getCtrlX2();
 651 
 652     /**
 653      * Returns the Y coordinate of the second control point
 654      * in double precision.
 655      * @return the Y coordinate of the second control point of the
 656      *         {@code CubicCurve2D}.
 657      * @since 1.2
 658      */
 659     public abstract double getCtrlY2();
 660 
 661     /**
 662      * Returns the second control point.
 663      * @return a {@code Point2D} that is the second control point of
 664      *         the {@code CubicCurve2D}.
 665      * @since 1.2
 666      */
 667     public abstract Point2D getCtrlP2();
 668 
 669     /**
 670      * Returns the X coordinate of the end point in double precision.
 671      * @return the X coordinate of the end point of the
 672      *         {@code CubicCurve2D}.
 673      * @since 1.2
 674      */
 675     public abstract double getX2();
 676 
 677     /**
 678      * Returns the Y coordinate of the end point in double precision.
 679      * @return the Y coordinate of the end point of the
 680      *         {@code CubicCurve2D}.
 681      * @since 1.2
 682      */
 683     public abstract double getY2();
 684 
 685     /**
 686      * Returns the end point.
 687      * @return a {@code Point2D} that is the end point of
 688      *         the {@code CubicCurve2D}.
 689      * @since 1.2
 690      */
 691     public abstract Point2D getP2();
 692 
 693     /**
 694      * Sets the location of the end points and control points of this curve
 695      * to the specified double coordinates.
 696      *
 697      * @param x1 the X coordinate used to set the start point
 698      *           of this {@code CubicCurve2D}
 699      * @param y1 the Y coordinate used to set the start point
 700      *           of this {@code CubicCurve2D}
 701      * @param ctrlx1 the X coordinate used to set the first control point
 702      *               of this {@code CubicCurve2D}
 703      * @param ctrly1 the Y coordinate used to set the first control point
 704      *               of this {@code CubicCurve2D}
 705      * @param ctrlx2 the X coordinate used to set the second control point
 706      *               of this {@code CubicCurve2D}
 707      * @param ctrly2 the Y coordinate used to set the second control point
 708      *               of this {@code CubicCurve2D}
 709      * @param x2 the X coordinate used to set the end point
 710      *           of this {@code CubicCurve2D}
 711      * @param y2 the Y coordinate used to set the end point
 712      *           of this {@code CubicCurve2D}
 713      * @since 1.2
 714      */
 715     public abstract void setCurve(double x1, double y1,
 716                                   double ctrlx1, double ctrly1,
 717                                   double ctrlx2, double ctrly2,
 718                                   double x2, double y2);
 719 
 720     /**
 721      * Sets the location of the end points and control points of this curve
 722      * to the double coordinates at the specified offset in the specified
 723      * array.
 724      * @param coords a double array containing coordinates
 725      * @param offset the index of <code>coords</code> from which to begin
 726      *          setting the end points and control points of this curve
 727      *          to the coordinates contained in <code>coords</code>
 728      * @since 1.2
 729      */
 730     public void setCurve(double[] coords, int offset) {
 731         setCurve(coords[offset + 0], coords[offset + 1],
 732                  coords[offset + 2], coords[offset + 3],
 733                  coords[offset + 4], coords[offset + 5],
 734                  coords[offset + 6], coords[offset + 7]);
 735     }
 736 
 737     /**
 738      * Sets the location of the end points and control points of this curve
 739      * to the specified <code>Point2D</code> coordinates.
 740      * @param p1 the first specified <code>Point2D</code> used to set the
 741      *          start point of this curve
 742      * @param cp1 the second specified <code>Point2D</code> used to set the
 743      *          first control point of this curve
 744      * @param cp2 the third specified <code>Point2D</code> used to set the
 745      *          second control point of this curve
 746      * @param p2 the fourth specified <code>Point2D</code> used to set the
 747      *          end point of this curve
 748      * @since 1.2
 749      */
 750     public void setCurve(Point2D p1, Point2D cp1, Point2D cp2, Point2D p2) {
 751         setCurve(p1.getX(), p1.getY(), cp1.getX(), cp1.getY(),
 752                  cp2.getX(), cp2.getY(), p2.getX(), p2.getY());
 753     }
 754 
 755     /**
 756      * Sets the location of the end points and control points of this curve
 757      * to the coordinates of the <code>Point2D</code> objects at the specified
 758      * offset in the specified array.
 759      * @param pts an array of <code>Point2D</code> objects
 760      * @param offset  the index of <code>pts</code> from which to begin setting
 761      *          the end points and control points of this curve to the
 762      *          points contained in <code>pts</code>
 763      * @since 1.2
 764      */
 765     public void setCurve(Point2D[] pts, int offset) {
 766         setCurve(pts[offset + 0].getX(), pts[offset + 0].getY(),
 767                  pts[offset + 1].getX(), pts[offset + 1].getY(),
 768                  pts[offset + 2].getX(), pts[offset + 2].getY(),
 769                  pts[offset + 3].getX(), pts[offset + 3].getY());
 770     }
 771 
 772     /**
 773      * Sets the location of the end points and control points of this curve
 774      * to the same as those in the specified <code>CubicCurve2D</code>.
 775      * @param c the specified <code>CubicCurve2D</code>
 776      * @since 1.2
 777      */
 778     public void setCurve(CubicCurve2D c) {
 779         setCurve(c.getX1(), c.getY1(), c.getCtrlX1(), c.getCtrlY1(),
 780                  c.getCtrlX2(), c.getCtrlY2(), c.getX2(), c.getY2());
 781     }
 782 
 783     /**
 784      * Returns the square of the flatness of the cubic curve specified
 785      * by the indicated control points. The flatness is the maximum distance
 786      * of a control point from the line connecting the end points.
 787      *
 788      * @param x1 the X coordinate that specifies the start point
 789      *           of a {@code CubicCurve2D}
 790      * @param y1 the Y coordinate that specifies the start point
 791      *           of a {@code CubicCurve2D}
 792      * @param ctrlx1 the X coordinate that specifies the first control point
 793      *               of a {@code CubicCurve2D}
 794      * @param ctrly1 the Y coordinate that specifies the first control point
 795      *               of a {@code CubicCurve2D}
 796      * @param ctrlx2 the X coordinate that specifies the second control point
 797      *               of a {@code CubicCurve2D}
 798      * @param ctrly2 the Y coordinate that specifies the second control point
 799      *               of a {@code CubicCurve2D}
 800      * @param x2 the X coordinate that specifies the end point
 801      *           of a {@code CubicCurve2D}
 802      * @param y2 the Y coordinate that specifies the end point
 803      *           of a {@code CubicCurve2D}
 804      * @return the square of the flatness of the {@code CubicCurve2D}
 805      *          represented by the specified coordinates.
 806      * @since 1.2
 807      */
 808     public static double getFlatnessSq(double x1, double y1,
 809                                        double ctrlx1, double ctrly1,
 810                                        double ctrlx2, double ctrly2,
 811                                        double x2, double y2) {
 812         return Math.max(Line2D.ptSegDistSq(x1, y1, x2, y2, ctrlx1, ctrly1),
 813                         Line2D.ptSegDistSq(x1, y1, x2, y2, ctrlx2, ctrly2));
 814 
 815     }
 816 
 817     /**
 818      * Returns the flatness of the cubic curve specified
 819      * by the indicated control points. The flatness is the maximum distance
 820      * of a control point from the line connecting the end points.
 821      *
 822      * @param x1 the X coordinate that specifies the start point
 823      *           of a {@code CubicCurve2D}
 824      * @param y1 the Y coordinate that specifies the start point
 825      *           of a {@code CubicCurve2D}
 826      * @param ctrlx1 the X coordinate that specifies the first control point
 827      *               of a {@code CubicCurve2D}
 828      * @param ctrly1 the Y coordinate that specifies the first control point
 829      *               of a {@code CubicCurve2D}
 830      * @param ctrlx2 the X coordinate that specifies the second control point
 831      *               of a {@code CubicCurve2D}
 832      * @param ctrly2 the Y coordinate that specifies the second control point
 833      *               of a {@code CubicCurve2D}
 834      * @param x2 the X coordinate that specifies the end point
 835      *           of a {@code CubicCurve2D}
 836      * @param y2 the Y coordinate that specifies the end point
 837      *           of a {@code CubicCurve2D}
 838      * @return the flatness of the {@code CubicCurve2D}
 839      *          represented by the specified coordinates.
 840      * @since 1.2
 841      */
 842     public static double getFlatness(double x1, double y1,
 843                                      double ctrlx1, double ctrly1,
 844                                      double ctrlx2, double ctrly2,
 845                                      double x2, double y2) {
 846         return Math.sqrt(getFlatnessSq(x1, y1, ctrlx1, ctrly1,
 847                                        ctrlx2, ctrly2, x2, y2));
 848     }
 849 
 850     /**
 851      * Returns the square of the flatness of the cubic curve specified
 852      * by the control points stored in the indicated array at the
 853      * indicated index. The flatness is the maximum distance
 854      * of a control point from the line connecting the end points.
 855      * @param coords an array containing coordinates
 856      * @param offset the index of <code>coords</code> from which to begin
 857      *          getting the end points and control points of the curve
 858      * @return the square of the flatness of the <code>CubicCurve2D</code>
 859      *          specified by the coordinates in <code>coords</code> at
 860      *          the specified offset.
 861      * @since 1.2
 862      */
 863     public static double getFlatnessSq(double coords[], int offset) {
 864         return getFlatnessSq(coords[offset + 0], coords[offset + 1],
 865                              coords[offset + 2], coords[offset + 3],
 866                              coords[offset + 4], coords[offset + 5],
 867                              coords[offset + 6], coords[offset + 7]);
 868     }
 869 
 870     /**
 871      * Returns the flatness of the cubic curve specified
 872      * by the control points stored in the indicated array at the
 873      * indicated index.  The flatness is the maximum distance
 874      * of a control point from the line connecting the end points.
 875      * @param coords an array containing coordinates
 876      * @param offset the index of <code>coords</code> from which to begin
 877      *          getting the end points and control points of the curve
 878      * @return the flatness of the <code>CubicCurve2D</code>
 879      *          specified by the coordinates in <code>coords</code> at
 880      *          the specified offset.
 881      * @since 1.2
 882      */
 883     public static double getFlatness(double coords[], int offset) {
 884         return getFlatness(coords[offset + 0], coords[offset + 1],
 885                            coords[offset + 2], coords[offset + 3],
 886                            coords[offset + 4], coords[offset + 5],
 887                            coords[offset + 6], coords[offset + 7]);
 888     }
 889 
 890     /**
 891      * Returns the square of the flatness of this curve.  The flatness is the
 892      * maximum distance of a control point from the line connecting the
 893      * end points.
 894      * @return the square of the flatness of this curve.
 895      * @since 1.2
 896      */
 897     public double getFlatnessSq() {
 898         return getFlatnessSq(getX1(), getY1(), getCtrlX1(), getCtrlY1(),
 899                              getCtrlX2(), getCtrlY2(), getX2(), getY2());
 900     }
 901 
 902     /**
 903      * Returns the flatness of this curve.  The flatness is the
 904      * maximum distance of a control point from the line connecting the
 905      * end points.
 906      * @return the flatness of this curve.
 907      * @since 1.2
 908      */
 909     public double getFlatness() {
 910         return getFlatness(getX1(), getY1(), getCtrlX1(), getCtrlY1(),
 911                            getCtrlX2(), getCtrlY2(), getX2(), getY2());
 912     }
 913 
 914     /**
 915      * Subdivides this cubic curve and stores the resulting two
 916      * subdivided curves into the left and right curve parameters.
 917      * Either or both of the left and right objects may be the same
 918      * as this object or null.
 919      * @param left the cubic curve object for storing for the left or
 920      * first half of the subdivided curve
 921      * @param right the cubic curve object for storing for the right or
 922      * second half of the subdivided curve
 923      * @since 1.2
 924      */
 925     public void subdivide(CubicCurve2D left, CubicCurve2D right) {
 926         subdivide(this, left, right);
 927     }
 928 
 929     /**
 930      * Subdivides the cubic curve specified by the <code>src</code> parameter
 931      * and stores the resulting two subdivided curves into the
 932      * <code>left</code> and <code>right</code> curve parameters.
 933      * Either or both of the <code>left</code> and <code>right</code> objects
 934      * may be the same as the <code>src</code> object or <code>null</code>.
 935      * @param src the cubic curve to be subdivided
 936      * @param left the cubic curve object for storing the left or
 937      * first half of the subdivided curve
 938      * @param right the cubic curve object for storing the right or
 939      * second half of the subdivided curve
 940      * @since 1.2
 941      */
 942     public static void subdivide(CubicCurve2D src,
 943                                  CubicCurve2D left,
 944                                  CubicCurve2D right) {
 945         double x1 = src.getX1();
 946         double y1 = src.getY1();
 947         double ctrlx1 = src.getCtrlX1();
 948         double ctrly1 = src.getCtrlY1();
 949         double ctrlx2 = src.getCtrlX2();
 950         double ctrly2 = src.getCtrlY2();
 951         double x2 = src.getX2();
 952         double y2 = src.getY2();
 953         double centerx = (ctrlx1 + ctrlx2) / 2.0;
 954         double centery = (ctrly1 + ctrly2) / 2.0;
 955         ctrlx1 = (x1 + ctrlx1) / 2.0;
 956         ctrly1 = (y1 + ctrly1) / 2.0;
 957         ctrlx2 = (x2 + ctrlx2) / 2.0;
 958         ctrly2 = (y2 + ctrly2) / 2.0;
 959         double ctrlx12 = (ctrlx1 + centerx) / 2.0;
 960         double ctrly12 = (ctrly1 + centery) / 2.0;
 961         double ctrlx21 = (ctrlx2 + centerx) / 2.0;
 962         double ctrly21 = (ctrly2 + centery) / 2.0;
 963         centerx = (ctrlx12 + ctrlx21) / 2.0;
 964         centery = (ctrly12 + ctrly21) / 2.0;
 965         if (left != null) {
 966             left.setCurve(x1, y1, ctrlx1, ctrly1,
 967                           ctrlx12, ctrly12, centerx, centery);
 968         }
 969         if (right != null) {
 970             right.setCurve(centerx, centery, ctrlx21, ctrly21,
 971                            ctrlx2, ctrly2, x2, y2);
 972         }
 973     }
 974 
 975     /**
 976      * Subdivides the cubic curve specified by the coordinates
 977      * stored in the <code>src</code> array at indices <code>srcoff</code>
 978      * through (<code>srcoff</code>&nbsp;+&nbsp;7) and stores the
 979      * resulting two subdivided curves into the two result arrays at the
 980      * corresponding indices.
 981      * Either or both of the <code>left</code> and <code>right</code>
 982      * arrays may be <code>null</code> or a reference to the same array
 983      * as the <code>src</code> array.
 984      * Note that the last point in the first subdivided curve is the
 985      * same as the first point in the second subdivided curve. Thus,
 986      * it is possible to pass the same array for <code>left</code>
 987      * and <code>right</code> and to use offsets, such as <code>rightoff</code>
 988      * equals (<code>leftoff</code> + 6), in order
 989      * to avoid allocating extra storage for this common point.
 990      * @param src the array holding the coordinates for the source curve
 991      * @param srcoff the offset into the array of the beginning of the
 992      * the 6 source coordinates
 993      * @param left the array for storing the coordinates for the first
 994      * half of the subdivided curve
 995      * @param leftoff the offset into the array of the beginning of the
 996      * the 6 left coordinates
 997      * @param right the array for storing the coordinates for the second
 998      * half of the subdivided curve
 999      * @param rightoff the offset into the array of the beginning of the
1000      * the 6 right coordinates
1001      * @since 1.2
1002      */
1003     public static void subdivide(double src[], int srcoff,
1004                                  double left[], int leftoff,
1005                                  double right[], int rightoff) {
1006         double x1 = src[srcoff + 0];
1007         double y1 = src[srcoff + 1];
1008         double ctrlx1 = src[srcoff + 2];
1009         double ctrly1 = src[srcoff + 3];
1010         double ctrlx2 = src[srcoff + 4];
1011         double ctrly2 = src[srcoff + 5];
1012         double x2 = src[srcoff + 6];
1013         double y2 = src[srcoff + 7];
1014         if (left != null) {
1015             left[leftoff + 0] = x1;
1016             left[leftoff + 1] = y1;
1017         }
1018         if (right != null) {
1019             right[rightoff + 6] = x2;
1020             right[rightoff + 7] = y2;
1021         }
1022         x1 = (x1 + ctrlx1) / 2.0;
1023         y1 = (y1 + ctrly1) / 2.0;
1024         x2 = (x2 + ctrlx2) / 2.0;
1025         y2 = (y2 + ctrly2) / 2.0;
1026         double centerx = (ctrlx1 + ctrlx2) / 2.0;
1027         double centery = (ctrly1 + ctrly2) / 2.0;
1028         ctrlx1 = (x1 + centerx) / 2.0;
1029         ctrly1 = (y1 + centery) / 2.0;
1030         ctrlx2 = (x2 + centerx) / 2.0;
1031         ctrly2 = (y2 + centery) / 2.0;
1032         centerx = (ctrlx1 + ctrlx2) / 2.0;
1033         centery = (ctrly1 + ctrly2) / 2.0;
1034         if (left != null) {
1035             left[leftoff + 2] = x1;
1036             left[leftoff + 3] = y1;
1037             left[leftoff + 4] = ctrlx1;
1038             left[leftoff + 5] = ctrly1;
1039             left[leftoff + 6] = centerx;
1040             left[leftoff + 7] = centery;
1041         }
1042         if (right != null) {
1043             right[rightoff + 0] = centerx;
1044             right[rightoff + 1] = centery;
1045             right[rightoff + 2] = ctrlx2;
1046             right[rightoff + 3] = ctrly2;
1047             right[rightoff + 4] = x2;
1048             right[rightoff + 5] = y2;
1049         }
1050     }
1051 
1052     /**
1053      * Solves the cubic whose coefficients are in the <code>eqn</code>
1054      * array and places the non-complex roots back into the same array,
1055      * returning the number of roots.  The solved cubic is represented
1056      * by the equation:
1057      * <pre>
1058      *     eqn = {c, b, a, d}
1059      *     dx^3 + ax^2 + bx + c = 0
1060      * </pre>
1061      * A return value of -1 is used to distinguish a constant equation
1062      * that might be always 0 or never 0 from an equation that has no
1063      * zeroes.
1064      * @param eqn an array containing coefficients for a cubic
1065      * @return the number of roots, or -1 if the equation is a constant.
1066      * @since 1.2
1067      */
1068     public static int solveCubic(double eqn[]) {
1069         return solveCubic(eqn, eqn);
1070     }
1071 
1072     /**
1073      * Solve the cubic whose coefficients are in the <code>eqn</code>
1074      * array and place the non-complex roots into the <code>res</code>
1075      * array, returning the number of roots.
1076      * The cubic solved is represented by the equation:
1077      *     eqn = {c, b, a, d}
1078      *     dx^3 + ax^2 + bx + c = 0
1079      * A return value of -1 is used to distinguish a constant equation,
1080      * which may be always 0 or never 0, from an equation which has no
1081      * zeroes.
1082      * @param eqn the specified array of coefficients to use to solve
1083      *        the cubic equation
1084      * @param res the array that contains the non-complex roots
1085      *        resulting from the solution of the cubic equation
1086      * @return the number of roots, or -1 if the equation is a constant
1087      * @since 1.3
1088      */
1089     public static int solveCubic(double eqn[], double res[]) {
1090         // From Graphics Gems:
1091         // http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c
1092         final double d = eqn[3];
1093         if (d == 0) {
1094             return QuadCurve2D.solveQuadratic(eqn, res);
1095         }
1096 
1097         /* normal form: x^3 + Ax^2 + Bx + C = 0 */
1098         final double A = eqn[2] / d;
1099         final double B = eqn[1] / d;
1100         final double C = eqn[0] / d;
1101 
1102 
1103         //  substitute x = y - A/3 to eliminate quadratic term:
1104         //     x^3 +Px + Q = 0
1105         //
1106         // Since we actually need P/3 and Q/2 for all of the
1107         // calculations that follow, we will calculate
1108         // p = P/3
1109         // q = Q/2
1110         // instead and use those values for simplicity of the code.
1111         double sq_A = A * A;
1112         double p = 1.0/3 * (-1.0/3 * sq_A + B);
1113         double q = 1.0/2 * (2.0/27 * A * sq_A - 1.0/3 * A * B + C);
1114 
1115         /* use Cardano's formula */
1116 
1117         double cb_p = p * p * p;
1118         double D = q * q + cb_p;
1119 
1120         final double sub = 1.0/3 * A;
1121 
1122         int num;
1123         if (D < 0) { /* Casus irreducibilis: three real solutions */
1124             // see: http://en.wikipedia.org/wiki/Cubic_function#Trigonometric_.28and_hyperbolic.29_method
1125             double phi = 1.0/3 * Math.acos(-q / Math.sqrt(-cb_p));
1126             double t = 2 * Math.sqrt(-p);
1127 
1128             if (res == eqn) {
1129                 eqn = Arrays.copyOf(eqn, 4);
1130             }
1131 
1132             res[ 0 ] =  ( t * Math.cos(phi));
1133             res[ 1 ] =  (-t * Math.cos(phi + Math.PI / 3));
1134             res[ 2 ] =  (-t * Math.cos(phi - Math.PI / 3));
1135             num = 3;
1136 
1137             for (int i = 0; i < num; ++i) {
1138                 res[ i ] -= sub;
1139             }
1140 
1141         } else {
1142             // Please see the comment in fixRoots marked 'XXX' before changing
1143             // any of the code in this case.
1144             double sqrt_D = Math.sqrt(D);
1145             double u = Math.cbrt(sqrt_D - q);
1146             double v = - Math.cbrt(sqrt_D + q);
1147             double uv = u+v;
1148 
1149             num = 1;
1150 
1151             double err = 1200000000*ulp(abs(uv) + abs(sub));
1152             if (iszero(D, err) || within(u, v, err)) {
1153                 if (res == eqn) {
1154                     eqn = Arrays.copyOf(eqn, 4);
1155                 }
1156                 res[1] = -(uv / 2) - sub;
1157                 num = 2;
1158             }
1159             // this must be done after the potential Arrays.copyOf
1160             res[ 0 ] =  uv - sub;
1161         }
1162 
1163         if (num > 1) { // num == 3 || num == 2
1164             num = fixRoots(eqn, res, num);
1165         }
1166         if (num > 2 && (res[2] == res[1] || res[2] == res[0])) {
1167             num--;
1168         }
1169         if (num > 1 && res[1] == res[0]) {
1170             res[1] = res[--num]; // Copies res[2] to res[1] if needed
1171         }
1172         return num;
1173     }
1174 
1175     // preconditions: eqn != res && eqn[3] != 0 && num > 1
1176     // This method tries to improve the accuracy of the roots of eqn (which
1177     // should be in res). It also might eliminate roots in res if it decideds
1178     // that they're not real roots. It will not check for roots that the
1179     // computation of res might have missed, so this method should only be
1180     // used when the roots in res have been computed using an algorithm
1181     // that never underestimates the number of roots (such as solveCubic above)
1182     private static int fixRoots(double[] eqn, double[] res, int num) {
1183         double[] intervals = {eqn[1], 2*eqn[2], 3*eqn[3]};
1184         int critCount = QuadCurve2D.solveQuadratic(intervals, intervals);
1185         if (critCount == 2 && intervals[0] == intervals[1]) {
1186             critCount--;
1187         }
1188         if (critCount == 2 && intervals[0] > intervals[1]) {
1189             double tmp = intervals[0];
1190             intervals[0] = intervals[1];
1191             intervals[1] = tmp;
1192         }
1193 
1194         // below we use critCount to possibly filter out roots that shouldn't
1195         // have been computed. We require that eqn[3] != 0, so eqn is a proper
1196         // cubic, which means that its limits at -/+inf are -/+inf or +/-inf.
1197         // Therefore, if critCount==2, the curve is shaped like a sideways S,
1198         // and it could have 1-3 roots. If critCount==0 it is monotonic, and
1199         // if critCount==1 it is monotonic with a single point where it is
1200         // flat. In the last 2 cases there can only be 1 root. So in cases
1201         // where num > 1 but critCount < 2, we eliminate all roots in res
1202         // except one.
1203 
1204         if (num == 3) {
1205             double xe = getRootUpperBound(eqn);
1206             double x0 = -xe;
1207 
1208             Arrays.sort(res, 0, num);
1209             if (critCount == 2) {
1210                 // this just tries to improve the accuracy of the computed
1211                 // roots using Newton's method.
1212                 res[0] = refineRootWithHint(eqn, x0, intervals[0], res[0]);
1213                 res[1] = refineRootWithHint(eqn, intervals[0], intervals[1], res[1]);
1214                 res[2] = refineRootWithHint(eqn, intervals[1], xe, res[2]);
1215                 return 3;
1216             } else if (critCount == 1) {
1217                 // we only need fx0 and fxe for the sign of the polynomial
1218                 // at -inf and +inf respectively, so we don't need to do
1219                 // fx0 = solveEqn(eqn, 3, x0); fxe = solveEqn(eqn, 3, xe)
1220                 double fxe = eqn[3];
1221                 double fx0 = -fxe;
1222 
1223                 double x1 = intervals[0];
1224                 double fx1 = solveEqn(eqn, 3, x1);
1225 
1226                 // if critCount == 1 or critCount == 0, but num == 3 then
1227                 // something has gone wrong. This branch and the one below
1228                 // would ideally never execute, but if they do we can't know
1229                 // which of the computed roots is closest to the real root;
1230                 // therefore, we can't use refineRootWithHint. But even if
1231                 // we did know, being here most likely means that the
1232                 // curve is very flat close to two of the computed roots
1233                 // (or maybe even all three). This might make Newton's method
1234                 // fail altogether, which would be a pain to detect and fix.
1235                 // This is why we use a very stable bisection method.
1236                 if (oppositeSigns(fx0, fx1)) {
1237                     res[0] = bisectRootWithHint(eqn, x0, x1, res[0]);
1238                 } else if (oppositeSigns(fx1, fxe)) {
1239                     res[0] = bisectRootWithHint(eqn, x1, xe, res[2]);
1240                 } else /* fx1 must be 0 */ {
1241                     res[0] = x1;
1242                 }
1243                 // return 1
1244             } else if (critCount == 0) {
1245                 res[0] = bisectRootWithHint(eqn, x0, xe, res[1]);
1246                 // return 1
1247             }
1248         } else if (num == 2 && critCount == 2) {
1249             // XXX: here we assume that res[0] has better accuracy than res[1].
1250             // This is true because this method is only used from solveCubic
1251             // which puts in res[0] the root that it would compute anyway even
1252             // if num==1. If this method is ever used from any other method, or
1253             // if the solveCubic implementation changes, this assumption should
1254             // be reevaluated, and the choice of goodRoot might have to become
1255             // goodRoot = (abs(eqn'(res[0])) > abs(eqn'(res[1]))) ? res[0] : res[1]
1256             // where eqn' is the derivative of eqn.
1257             double goodRoot = res[0];
1258             double badRoot = res[1];
1259             double x1 = intervals[0];
1260             double x2 = intervals[1];
1261             // If a cubic curve really has 2 roots, one of those roots must be
1262             // at a critical point. That can't be goodRoot, so we compute x to
1263             // be the farthest critical point from goodRoot. If there are two
1264             // roots, x must be the second one, so we evaluate eqn at x, and if
1265             // it is zero (or close enough) we put x in res[1] (or badRoot, if
1266             // |solveEqn(eqn, 3, badRoot)| < |solveEqn(eqn, 3, x)| but this
1267             // shouldn't happen often).
1268             double x = abs(x1 - goodRoot) > abs(x2 - goodRoot) ? x1 : x2;
1269             double fx = solveEqn(eqn, 3, x);
1270 
1271             if (iszero(fx, 10000000*ulp(x))) {
1272                 double badRootVal = solveEqn(eqn, 3, badRoot);
1273                 res[1] = abs(badRootVal) < abs(fx) ? badRoot : x;
1274                 return 2;
1275             }
1276         } // else there can only be one root - goodRoot, and it is already in res[0]
1277 
1278         return 1;
1279     }
1280 
1281     // use newton's method.
1282     private static double refineRootWithHint(double[] eqn, double min, double max, double t) {
1283         if (!inInterval(t, min, max)) {
1284             return t;
1285         }
1286         double[] deriv = {eqn[1], 2*eqn[2], 3*eqn[3]};
1287         double origt = t;
1288         for (int i = 0; i < 3; i++) {
1289             double slope = solveEqn(deriv, 2, t);
1290             double y = solveEqn(eqn, 3, t);
1291             double delta = - (y / slope);
1292             double newt = t + delta;
1293 
1294             if (slope == 0 || y == 0 || t == newt) {
1295                 break;
1296             }
1297 
1298             t = newt;
1299         }
1300         if (within(t, origt, 1000*ulp(origt)) && inInterval(t, min, max)) {
1301             return t;
1302         }
1303         return origt;
1304     }
1305 
1306     private static double bisectRootWithHint(double[] eqn, double x0, double xe, double hint) {
1307         double delta1 = Math.min(abs(hint - x0) / 64, 0.0625);
1308         double delta2 = Math.min(abs(hint - xe) / 64, 0.0625);
1309         double x02 = hint - delta1;
1310         double xe2 = hint + delta2;
1311         double fx02 = solveEqn(eqn, 3, x02);
1312         double fxe2 = solveEqn(eqn, 3, xe2);
1313         while (oppositeSigns(fx02, fxe2)) {
1314             if (x02 >= xe2) {
1315                 return x02;
1316             }
1317             x0 = x02;
1318             xe = xe2;
1319             delta1 /= 64;
1320             delta2 /= 64;
1321             x02 = hint - delta1;
1322             xe2 = hint + delta2;
1323             fx02 = solveEqn(eqn, 3, x02);
1324             fxe2 = solveEqn(eqn, 3, xe2);
1325         }
1326         if (fx02 == 0) {
1327             return x02;
1328         }
1329         if (fxe2 == 0) {
1330             return xe2;
1331         }
1332 
1333         return bisectRoot(eqn, x0, xe);
1334     }
1335 
1336     private static double bisectRoot(double[] eqn, double x0, double xe) {
1337         double fx0 = solveEqn(eqn, 3, x0);
1338         double m = x0 + (xe - x0) / 2;
1339         while (m != x0 && m != xe) {
1340             double fm = solveEqn(eqn, 3, m);
1341             if (fm == 0) {
1342                 return m;
1343             }
1344             if (oppositeSigns(fx0, fm)) {
1345                 xe = m;
1346             } else {
1347                 fx0 = fm;
1348                 x0 = m;
1349             }
1350             m = x0 + (xe-x0)/2;
1351         }
1352         return m;
1353     }
1354 
1355     private static boolean inInterval(double t, double min, double max) {
1356         return min <= t && t <= max;
1357     }
1358 
1359     private static boolean within(double x, double y, double err) {
1360         double d = y - x;
1361         return (d <= err && d >= -err);
1362     }
1363 
1364     private static boolean iszero(double x, double err) {
1365         return within(x, 0, err);
1366     }
1367 
1368     private static boolean oppositeSigns(double x1, double x2) {
1369         return (x1 < 0 && x2 > 0) || (x1 > 0 && x2 < 0);
1370     }
1371 
1372     private static double solveEqn(double eqn[], int order, double t) {
1373         double v = eqn[order];
1374         while (--order >= 0) {
1375             v = v * t + eqn[order];
1376         }
1377         return v;
1378     }
1379 
1380     /*
1381      * Computes M+1 where M is an upper bound for all the roots in of eqn.
1382      * See: http://en.wikipedia.org/wiki/Sturm%27s_theorem#Applications.
1383      * The above link doesn't contain a proof, but I [dlila] proved it myself
1384      * so the result is reliable. The proof isn't difficult, but it's a bit
1385      * long to include here.
1386      * Precondition: eqn must represent a cubic polynomial
1387      */
1388     private static double getRootUpperBound(double[] eqn) {
1389         double d = eqn[3];
1390         double a = eqn[2];
1391         double b = eqn[1];
1392         double c = eqn[0];
1393 
1394         double M = 1 + max(max(abs(a), abs(b)), abs(c)) / abs(d);
1395         M += ulp(M) + 1;
1396         return M;
1397     }
1398 
1399 
1400     /**
1401      * {@inheritDoc}
1402      * @since 1.2
1403      */
1404     public boolean contains(double x, double y) {
1405         if (!(x * 0.0 + y * 0.0 == 0.0)) {
1406             /* Either x or y was infinite or NaN.
1407              * A NaN always produces a negative response to any test
1408              * and Infinity values cannot be "inside" any path so
1409              * they should return false as well.
1410              */
1411             return false;
1412         }
1413         // We count the "Y" crossings to determine if the point is
1414         // inside the curve bounded by its closing line.
1415         double x1 = getX1();
1416         double y1 = getY1();
1417         double x2 = getX2();
1418         double y2 = getY2();
1419         int crossings =
1420             (Curve.pointCrossingsForLine(x, y, x1, y1, x2, y2) +
1421              Curve.pointCrossingsForCubic(x, y,
1422                                           x1, y1,
1423                                           getCtrlX1(), getCtrlY1(),
1424                                           getCtrlX2(), getCtrlY2(),
1425                                           x2, y2, 0));
1426         return ((crossings & 1) == 1);
1427     }
1428 
1429     /**
1430      * {@inheritDoc}
1431      * @since 1.2
1432      */
1433     public boolean contains(Point2D p) {
1434         return contains(p.getX(), p.getY());
1435     }
1436 
1437     /**
1438      * {@inheritDoc}
1439      * @since 1.2
1440      */
1441     public boolean intersects(double x, double y, double w, double h) {
1442         // Trivially reject non-existant rectangles
1443         if (w <= 0 || h <= 0) {
1444             return false;
1445         }
1446 
1447         int numCrossings = rectCrossings(x, y, w, h);
1448         // the intended return value is
1449         // numCrossings != 0 || numCrossings == Curve.RECT_INTERSECTS
1450         // but if (numCrossings != 0) numCrossings == INTERSECTS won't matter
1451         // and if !(numCrossings != 0) then numCrossings == 0, so
1452         // numCrossings != RECT_INTERSECT
1453         return numCrossings != 0;
1454     }
1455 
1456     /**
1457      * {@inheritDoc}
1458      * @since 1.2
1459      */
1460     public boolean intersects(Rectangle2D r) {
1461         return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
1462     }
1463 
1464     /**
1465      * {@inheritDoc}
1466      * @since 1.2
1467      */
1468     public boolean contains(double x, double y, double w, double h) {
1469         if (w <= 0 || h <= 0) {
1470             return false;
1471         }
1472 
1473         int numCrossings = rectCrossings(x, y, w, h);
1474         return !(numCrossings == 0 || numCrossings == Curve.RECT_INTERSECTS);
1475     }
1476 
1477     private int rectCrossings(double x, double y, double w, double h) {
1478         int crossings = 0;
1479         if (!(getX1() == getX2() && getY1() == getY2())) {
1480             crossings = Curve.rectCrossingsForLine(crossings,
1481                                                    x, y,
1482                                                    x+w, y+h,
1483                                                    getX1(), getY1(),
1484                                                    getX2(), getY2());
1485             if (crossings == Curve.RECT_INTERSECTS) {
1486                 return crossings;
1487             }
1488         }
1489         // we call this with the curve's direction reversed, because we wanted
1490         // to call rectCrossingsForLine first, because it's cheaper.
1491         return Curve.rectCrossingsForCubic(crossings,
1492                                            x, y,
1493                                            x+w, y+h,
1494                                            getX2(), getY2(),
1495                                            getCtrlX2(), getCtrlY2(),
1496                                            getCtrlX1(), getCtrlY1(),
1497                                            getX1(), getY1(), 0);
1498     }
1499 
1500     /**
1501      * {@inheritDoc}
1502      * @since 1.2
1503      */
1504     public boolean contains(Rectangle2D r) {
1505         return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
1506     }
1507 
1508     /**
1509      * {@inheritDoc}
1510      * @since 1.2
1511      */
1512     public Rectangle getBounds() {
1513         return getBounds2D().getBounds();
1514     }
1515 
1516     /**
1517      * Returns an iteration object that defines the boundary of the
1518      * shape.
1519      * The iterator for this class is not multi-threaded safe,
1520      * which means that this <code>CubicCurve2D</code> class does not
1521      * guarantee that modifications to the geometry of this
1522      * <code>CubicCurve2D</code> object do not affect any iterations of
1523      * that geometry that are already in process.
1524      * @param at an optional <code>AffineTransform</code> to be applied to the
1525      * coordinates as they are returned in the iteration, or <code>null</code>
1526      * if untransformed coordinates are desired
1527      * @return    the <code>PathIterator</code> object that returns the
1528      *          geometry of the outline of this <code>CubicCurve2D</code>, one
1529      *          segment at a time.
1530      * @since 1.2
1531      */
1532     public PathIterator getPathIterator(AffineTransform at) {
1533         return new CubicIterator(this, at);
1534     }
1535 
1536     /**
1537      * Return an iteration object that defines the boundary of the
1538      * flattened shape.
1539      * The iterator for this class is not multi-threaded safe,
1540      * which means that this <code>CubicCurve2D</code> class does not
1541      * guarantee that modifications to the geometry of this
1542      * <code>CubicCurve2D</code> object do not affect any iterations of
1543      * that geometry that are already in process.
1544      * @param at an optional <code>AffineTransform</code> to be applied to the
1545      * coordinates as they are returned in the iteration, or <code>null</code>
1546      * if untransformed coordinates are desired
1547      * @param flatness the maximum amount that the control points
1548      * for a given curve can vary from colinear before a subdivided
1549      * curve is replaced by a straight line connecting the end points
1550      * @return    the <code>PathIterator</code> object that returns the
1551      * geometry of the outline of this <code>CubicCurve2D</code>,
1552      * one segment at a time.
1553      * @since 1.2
1554      */
1555     public PathIterator getPathIterator(AffineTransform at, double flatness) {
1556         return new FlatteningPathIterator(getPathIterator(at), flatness);
1557     }
1558 
1559     /**
1560      * Creates a new object of the same class as this object.
1561      *
1562      * @return     a clone of this instance.
1563      * @exception  OutOfMemoryError            if there is not enough memory.
1564      * @see        java.lang.Cloneable
1565      * @since      1.2
1566      */
1567     public Object clone() {
1568         try {
1569             return super.clone();
1570         } catch (CloneNotSupportedException e) {
1571             // this shouldn't happen, since we are Cloneable
1572             throw new InternalError();
1573         }
1574     }
1575 }