< prev index next >

src/java.desktop/share/classes/java/awt/geom/AffineTransform.java

Print this page




  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.beans.ConstructorProperties;
  30 
  31 /**
  32  * The <code>AffineTransform</code> class represents a 2D affine transform
  33  * that performs a linear mapping from 2D coordinates to other 2D
  34  * coordinates that preserves the "straightness" and
  35  * "parallelness" of lines.  Affine transformations can be constructed
  36  * using sequences of translations, scales, flips, rotations, and shears.
  37  * <p>
  38  * Such a coordinate transformation can be represented by a 3 row by
  39  * 3 column matrix with an implied last row of [ 0 0 1 ].  This matrix
  40  * transforms source coordinates {@code (x,y)} into
  41  * destination coordinates {@code (x',y')} by considering
  42  * them to be a column vector and multiplying the coordinate vector
  43  * by the matrix according to the following process:
  44  * <pre>
  45  *      [ x']   [  m00  m01  m02  ] [ x ]   [ m00x + m01y + m02 ]
  46  *      [ y'] = [  m10  m11  m12  ] [ y ] = [ m10x + m11y + m12 ]
  47  *      [ 1 ]   [   0    0    1   ] [ 1 ]   [         1         ]
  48  * </pre>
  49  * <h3><a name="quadrantapproximation">Handling 90-Degree Rotations</a></h3>
  50  * <p>
  51  * In some variations of the <code>rotate</code> methods in the
  52  * <code>AffineTransform</code> class, a double-precision argument
  53  * specifies the angle of rotation in radians.
  54  * These methods have special handling for rotations of approximately
  55  * 90 degrees (including multiples such as 180, 270, and 360 degrees),
  56  * so that the common case of quadrant rotation is handled more
  57  * efficiently.
  58  * This special handling can cause angles very close to multiples of
  59  * 90 degrees to be treated as if they were exact multiples of
  60  * 90 degrees.
  61  * For small multiples of 90 degrees the range of angles treated
  62  * as a quadrant rotation is approximately 0.00000121 degrees wide.
  63  * This section explains why such special care is needed and how
  64  * it is implemented.
  65  * <p>
  66  * Since 90 degrees is represented as <code>PI/2</code> in radians,
  67  * and since PI is a transcendental (and therefore irrational) number,
  68  * it is not possible to exactly represent a multiple of 90 degrees as
  69  * an exact double precision value measured in radians.
  70  * As a result it is theoretically impossible to describe quadrant
  71  * rotations (90, 180, 270 or 360 degrees) using these values.
  72  * Double precision floating point values can get very close to
  73  * non-zero multiples of <code>PI/2</code> but never close enough
  74  * for the sine or cosine to be exactly 0.0, 1.0 or -1.0.
  75  * The implementations of <code>Math.sin()</code> and
  76  * <code>Math.cos()</code> correspondingly never return 0.0
  77  * for any case other than <code>Math.sin(0.0)</code>.
  78  * These same implementations do, however, return exactly 1.0 and
  79  * -1.0 for some range of numbers around each multiple of 90
  80  * degrees since the correct answer is so close to 1.0 or -1.0 that
  81  * the double precision significand cannot represent the difference
  82  * as accurately as it can for numbers that are near 0.0.
  83  * <p>
  84  * The net result of these issues is that if the
  85  * <code>Math.sin()</code> and <code>Math.cos()</code> methods
  86  * are used to directly generate the values for the matrix modifications
  87  * during these radian-based rotation operations then the resulting
  88  * transform is never strictly classifiable as a quadrant rotation
  89  * even for a simple case like <code>rotate(Math.PI/2.0)</code>,
  90  * due to minor variations in the matrix caused by the non-0.0 values
  91  * obtained for the sine and cosine.
  92  * If these transforms are not classified as quadrant rotations then
  93  * subsequent code which attempts to optimize further operations based
  94  * upon the type of the transform will be relegated to its most general
  95  * implementation.
  96  * <p>
  97  * Because quadrant rotations are fairly common,
  98  * this class should handle these cases reasonably quickly, both in
  99  * applying the rotations to the transform and in applying the resulting
 100  * transform to the coordinates.
 101  * To facilitate this optimal handling, the methods which take an angle
 102  * of rotation measured in radians attempt to detect angles that are
 103  * intended to be quadrant rotations and treat them as such.
 104  * These methods therefore treat an angle <em>theta</em> as a quadrant
 105  * rotation if either <code>Math.sin(<em>theta</em>)</code> or
 106  * <code>Math.cos(<em>theta</em>)</code> returns exactly 1.0 or -1.0.
 107  * As a rule of thumb, this property holds true for a range of
 108  * approximately 0.0000000211 radians (or 0.00000121 degrees) around
 109  * small multiples of <code>Math.PI/2.0</code>.
 110  *
 111  * @author Jim Graham
 112  * @since 1.2
 113  */
 114 public class AffineTransform implements Cloneable, java.io.Serializable {
 115 
 116     /*
 117      * This constant is only useful for the cached type field.
 118      * It indicates that the type has been decached and must be recalculated.
 119      */
 120     private static final int TYPE_UNKNOWN = -1;
 121 
 122     /**
 123      * This constant indicates that the transform defined by this object
 124      * is an identity transform.
 125      * An identity transform is one in which the output coordinates are
 126      * always the same as the input coordinates.
 127      * If this transform is anything other than the identity transform,
 128      * the type will either be the constant GENERAL_TRANSFORM or a
 129      * combination of the appropriate flag bits for the various coordinate


 450      * @see #TYPE_UNKNOWN
 451      * @see #getType
 452      */
 453     private transient int type;
 454 
 455     private AffineTransform(double m00, double m10,
 456                             double m01, double m11,
 457                             double m02, double m12,
 458                             int state) {
 459         this.m00 = m00;
 460         this.m10 = m10;
 461         this.m01 = m01;
 462         this.m11 = m11;
 463         this.m02 = m02;
 464         this.m12 = m12;
 465         this.state = state;
 466         this.type = TYPE_UNKNOWN;
 467     }
 468 
 469     /**
 470      * Constructs a new <code>AffineTransform</code> representing the
 471      * Identity transformation.
 472      * @since 1.2
 473      */
 474     public AffineTransform() {
 475         m00 = m11 = 1.0;
 476         // m01 = m10 = m02 = m12 = 0.0;         /* Not needed. */
 477         // state = APPLY_IDENTITY;              /* Not needed. */
 478         // type = TYPE_IDENTITY;                /* Not needed. */
 479     }
 480 
 481     /**
 482      * Constructs a new <code>AffineTransform</code> that is a copy of
 483      * the specified <code>AffineTransform</code> object.
 484      * @param Tx the <code>AffineTransform</code> object to copy
 485      * @since 1.2
 486      */
 487     public AffineTransform(AffineTransform Tx) {
 488         this.m00 = Tx.m00;
 489         this.m10 = Tx.m10;
 490         this.m01 = Tx.m01;
 491         this.m11 = Tx.m11;
 492         this.m02 = Tx.m02;
 493         this.m12 = Tx.m12;
 494         this.state = Tx.state;
 495         this.type = Tx.type;
 496     }
 497 
 498     /**
 499      * Constructs a new <code>AffineTransform</code> from 6 floating point
 500      * values representing the 6 specifiable entries of the 3x3
 501      * transformation matrix.
 502      *
 503      * @param m00 the X coordinate scaling element of the 3x3 matrix
 504      * @param m10 the Y coordinate shearing element of the 3x3 matrix
 505      * @param m01 the X coordinate shearing element of the 3x3 matrix
 506      * @param m11 the Y coordinate scaling element of the 3x3 matrix
 507      * @param m02 the X coordinate translation element of the 3x3 matrix
 508      * @param m12 the Y coordinate translation element of the 3x3 matrix
 509      * @since 1.2
 510      */
 511     @ConstructorProperties({ "scaleX", "shearY", "shearX", "scaleY", "translateX", "translateY" })
 512     public AffineTransform(float m00, float m10,
 513                            float m01, float m11,
 514                            float m02, float m12) {
 515         this.m00 = m00;
 516         this.m10 = m10;
 517         this.m01 = m01;
 518         this.m11 = m11;
 519         this.m02 = m02;
 520         this.m12 = m12;
 521         updateState();
 522     }
 523 
 524     /**
 525      * Constructs a new <code>AffineTransform</code> from an array of
 526      * floating point values representing either the 4 non-translation
 527      * entries or the 6 specifiable entries of the 3x3 transformation
 528      * matrix.  The values are retrieved from the array as
 529      * {&nbsp;m00&nbsp;m10&nbsp;m01&nbsp;m11&nbsp;[m02&nbsp;m12]}.
 530      * @param flatmatrix the float array containing the values to be set
 531      * in the new <code>AffineTransform</code> object. The length of the
 532      * array is assumed to be at least 4. If the length of the array is
 533      * less than 6, only the first 4 values are taken. If the length of
 534      * the array is greater than 6, the first 6 values are taken.
 535      * @since 1.2
 536      */
 537     public AffineTransform(float[] flatmatrix) {
 538         m00 = flatmatrix[0];
 539         m10 = flatmatrix[1];
 540         m01 = flatmatrix[2];
 541         m11 = flatmatrix[3];
 542         if (flatmatrix.length > 5) {
 543             m02 = flatmatrix[4];
 544             m12 = flatmatrix[5];
 545         }
 546         updateState();
 547     }
 548 
 549     /**
 550      * Constructs a new <code>AffineTransform</code> from 6 double
 551      * precision values representing the 6 specifiable entries of the 3x3
 552      * transformation matrix.
 553      *
 554      * @param m00 the X coordinate scaling element of the 3x3 matrix
 555      * @param m10 the Y coordinate shearing element of the 3x3 matrix
 556      * @param m01 the X coordinate shearing element of the 3x3 matrix
 557      * @param m11 the Y coordinate scaling element of the 3x3 matrix
 558      * @param m02 the X coordinate translation element of the 3x3 matrix
 559      * @param m12 the Y coordinate translation element of the 3x3 matrix
 560      * @since 1.2
 561      */
 562     public AffineTransform(double m00, double m10,
 563                            double m01, double m11,
 564                            double m02, double m12) {
 565         this.m00 = m00;
 566         this.m10 = m10;
 567         this.m01 = m01;
 568         this.m11 = m11;
 569         this.m02 = m02;
 570         this.m12 = m12;
 571         updateState();
 572     }
 573 
 574     /**
 575      * Constructs a new <code>AffineTransform</code> from an array of
 576      * double precision values representing either the 4 non-translation
 577      * entries or the 6 specifiable entries of the 3x3 transformation
 578      * matrix. The values are retrieved from the array as
 579      * {&nbsp;m00&nbsp;m10&nbsp;m01&nbsp;m11&nbsp;[m02&nbsp;m12]}.
 580      * @param flatmatrix the double array containing the values to be set
 581      * in the new <code>AffineTransform</code> object. The length of the
 582      * array is assumed to be at least 4. If the length of the array is
 583      * less than 6, only the first 4 values are taken. If the length of
 584      * the array is greater than 6, the first 6 values are taken.
 585      * @since 1.2
 586      */
 587     public AffineTransform(double[] flatmatrix) {
 588         m00 = flatmatrix[0];
 589         m10 = flatmatrix[1];
 590         m01 = flatmatrix[2];
 591         m11 = flatmatrix[3];
 592         if (flatmatrix.length > 5) {
 593             m02 = flatmatrix[4];
 594             m12 = flatmatrix[5];
 595         }
 596         updateState();
 597     }
 598 
 599     /**
 600      * Returns a transform representing a translation transformation.
 601      * The matrix representing the returned transform is:
 602      * <pre>
 603      *          [   1    0    tx  ]
 604      *          [   0    1    ty  ]
 605      *          [   0    0    1   ]
 606      * </pre>
 607      * @param tx the distance by which coordinates are translated in the
 608      * X axis direction
 609      * @param ty the distance by which coordinates are translated in the
 610      * Y axis direction
 611      * @return an <code>AffineTransform</code> object that represents a
 612      *  translation transformation, created with the specified vector.
 613      * @since 1.2
 614      */
 615     public static AffineTransform getTranslateInstance(double tx, double ty) {
 616         AffineTransform Tx = new AffineTransform();
 617         Tx.setToTranslation(tx, ty);
 618         return Tx;
 619     }
 620 
 621     /**
 622      * Returns a transform representing a rotation transformation.
 623      * The matrix representing the returned transform is:
 624      * <pre>
 625      *          [   cos(theta)    -sin(theta)    0   ]
 626      *          [   sin(theta)     cos(theta)    0   ]
 627      *          [       0              0         1   ]
 628      * </pre>
 629      * Rotating by a positive angle theta rotates points on the positive
 630      * X axis toward the positive Y axis.
 631      * Note also the discussion of
 632      * <a href="#quadrantapproximation">Handling 90-Degree Rotations</a>
 633      * above.
 634      * @param theta the angle of rotation measured in radians
 635      * @return an <code>AffineTransform</code> object that is a rotation
 636      *  transformation, created with the specified angle of rotation.
 637      * @since 1.2
 638      */
 639     public static AffineTransform getRotateInstance(double theta) {
 640         AffineTransform Tx = new AffineTransform();
 641         Tx.setToRotation(theta);
 642         return Tx;
 643     }
 644 
 645     /**
 646      * Returns a transform that rotates coordinates around an anchor point.
 647      * This operation is equivalent to translating the coordinates so
 648      * that the anchor point is at the origin (S1), then rotating them
 649      * about the new origin (S2), and finally translating so that the
 650      * intermediate origin is restored to the coordinates of the original
 651      * anchor point (S3).
 652      * <p>
 653      * This operation is equivalent to the following sequence of calls:
 654      * <pre>
 655      *     AffineTransform Tx = new AffineTransform();
 656      *     Tx.translate(anchorx, anchory);    // S3: final translation
 657      *     Tx.rotate(theta);                  // S2: rotate around anchor
 658      *     Tx.translate(-anchorx, -anchory);  // S1: translate anchor to origin
 659      * </pre>
 660      * The matrix representing the returned transform is:
 661      * <pre>
 662      *          [   cos(theta)    -sin(theta)    x-x*cos+y*sin  ]
 663      *          [   sin(theta)     cos(theta)    y-x*sin-y*cos  ]
 664      *          [       0              0               1        ]
 665      * </pre>
 666      * Rotating by a positive angle theta rotates points on the positive
 667      * X axis toward the positive Y axis.
 668      * Note also the discussion of
 669      * <a href="#quadrantapproximation">Handling 90-Degree Rotations</a>
 670      * above.
 671      *
 672      * @param theta the angle of rotation measured in radians
 673      * @param anchorx the X coordinate of the rotation anchor point
 674      * @param anchory the Y coordinate of the rotation anchor point
 675      * @return an <code>AffineTransform</code> object that rotates
 676      *  coordinates around the specified point by the specified angle of
 677      *  rotation.
 678      * @since 1.2
 679      */
 680     public static AffineTransform getRotateInstance(double theta,
 681                                                     double anchorx,
 682                                                     double anchory)
 683     {
 684         AffineTransform Tx = new AffineTransform();
 685         Tx.setToRotation(theta, anchorx, anchory);
 686         return Tx;
 687     }
 688 
 689     /**
 690      * Returns a transform that rotates coordinates according to
 691      * a rotation vector.
 692      * All coordinates rotate about the origin by the same amount.
 693      * The amount of rotation is such that coordinates along the former
 694      * positive X axis will subsequently align with the vector pointing
 695      * from the origin to the specified vector coordinates.
 696      * If both <code>vecx</code> and <code>vecy</code> are 0.0,
 697      * an identity transform is returned.
 698      * This operation is equivalent to calling:
 699      * <pre>
 700      *     AffineTransform.getRotateInstance(Math.atan2(vecy, vecx));
 701      * </pre>
 702      *
 703      * @param vecx the X coordinate of the rotation vector
 704      * @param vecy the Y coordinate of the rotation vector
 705      * @return an <code>AffineTransform</code> object that rotates
 706      *  coordinates according to the specified rotation vector.
 707      * @since 1.6
 708      */
 709     public static AffineTransform getRotateInstance(double vecx, double vecy) {
 710         AffineTransform Tx = new AffineTransform();
 711         Tx.setToRotation(vecx, vecy);
 712         return Tx;
 713     }
 714 
 715     /**
 716      * Returns a transform that rotates coordinates around an anchor
 717      * point according to a rotation vector.
 718      * All coordinates rotate about the specified anchor coordinates
 719      * by the same amount.
 720      * The amount of rotation is such that coordinates along the former
 721      * positive X axis will subsequently align with the vector pointing
 722      * from the origin to the specified vector coordinates.
 723      * If both <code>vecx</code> and <code>vecy</code> are 0.0,
 724      * an identity transform is returned.
 725      * This operation is equivalent to calling:
 726      * <pre>
 727      *     AffineTransform.getRotateInstance(Math.atan2(vecy, vecx),
 728      *                                       anchorx, anchory);
 729      * </pre>
 730      *
 731      * @param vecx the X coordinate of the rotation vector
 732      * @param vecy the Y coordinate of the rotation vector
 733      * @param anchorx the X coordinate of the rotation anchor point
 734      * @param anchory the Y coordinate of the rotation anchor point
 735      * @return an <code>AffineTransform</code> object that rotates
 736      *  coordinates around the specified point according to the
 737      *  specified rotation vector.
 738      * @since 1.6
 739      */
 740     public static AffineTransform getRotateInstance(double vecx,
 741                                                     double vecy,
 742                                                     double anchorx,
 743                                                     double anchory)
 744     {
 745         AffineTransform Tx = new AffineTransform();
 746         Tx.setToRotation(vecx, vecy, anchorx, anchory);
 747         return Tx;
 748     }
 749 
 750     /**
 751      * Returns a transform that rotates coordinates by the specified
 752      * number of quadrants.
 753      * This operation is equivalent to calling:
 754      * <pre>
 755      *     AffineTransform.getRotateInstance(numquadrants * Math.PI / 2.0);
 756      * </pre>
 757      * Rotating by a positive number of quadrants rotates points on
 758      * the positive X axis toward the positive Y axis.
 759      * @param numquadrants the number of 90 degree arcs to rotate by
 760      * @return an <code>AffineTransform</code> object that rotates
 761      *  coordinates by the specified number of quadrants.
 762      * @since 1.6
 763      */
 764     public static AffineTransform getQuadrantRotateInstance(int numquadrants) {
 765         AffineTransform Tx = new AffineTransform();
 766         Tx.setToQuadrantRotation(numquadrants);
 767         return Tx;
 768     }
 769 
 770     /**
 771      * Returns a transform that rotates coordinates by the specified
 772      * number of quadrants around the specified anchor point.
 773      * This operation is equivalent to calling:
 774      * <pre>
 775      *     AffineTransform.getRotateInstance(numquadrants * Math.PI / 2.0,
 776      *                                       anchorx, anchory);
 777      * </pre>
 778      * Rotating by a positive number of quadrants rotates points on
 779      * the positive X axis toward the positive Y axis.
 780      *
 781      * @param numquadrants the number of 90 degree arcs to rotate by
 782      * @param anchorx the X coordinate of the rotation anchor point
 783      * @param anchory the Y coordinate of the rotation anchor point
 784      * @return an <code>AffineTransform</code> object that rotates
 785      *  coordinates by the specified number of quadrants around the
 786      *  specified anchor point.
 787      * @since 1.6
 788      */
 789     public static AffineTransform getQuadrantRotateInstance(int numquadrants,
 790                                                             double anchorx,
 791                                                             double anchory)
 792     {
 793         AffineTransform Tx = new AffineTransform();
 794         Tx.setToQuadrantRotation(numquadrants, anchorx, anchory);
 795         return Tx;
 796     }
 797 
 798     /**
 799      * Returns a transform representing a scaling transformation.
 800      * The matrix representing the returned transform is:
 801      * <pre>
 802      *          [   sx   0    0   ]
 803      *          [   0    sy   0   ]
 804      *          [   0    0    1   ]
 805      * </pre>
 806      * @param sx the factor by which coordinates are scaled along the
 807      * X axis direction
 808      * @param sy the factor by which coordinates are scaled along the
 809      * Y axis direction
 810      * @return an <code>AffineTransform</code> object that scales
 811      *  coordinates by the specified factors.
 812      * @since 1.2
 813      */
 814     public static AffineTransform getScaleInstance(double sx, double sy) {
 815         AffineTransform Tx = new AffineTransform();
 816         Tx.setToScale(sx, sy);
 817         return Tx;
 818     }
 819 
 820     /**
 821      * Returns a transform representing a shearing transformation.
 822      * The matrix representing the returned transform is:
 823      * <pre>
 824      *          [   1   shx   0   ]
 825      *          [  shy   1    0   ]
 826      *          [   0    0    1   ]
 827      * </pre>
 828      * @param shx the multiplier by which coordinates are shifted in the
 829      * direction of the positive X axis as a factor of their Y coordinate
 830      * @param shy the multiplier by which coordinates are shifted in the
 831      * direction of the positive Y axis as a factor of their X coordinate
 832      * @return an <code>AffineTransform</code> object that shears
 833      *  coordinates by the specified multipliers.
 834      * @since 1.2
 835      */
 836     public static AffineTransform getShearInstance(double shx, double shy) {
 837         AffineTransform Tx = new AffineTransform();
 838         Tx.setToShear(shx, shy);
 839         return Tx;
 840     }
 841 
 842     /**
 843      * Retrieves the flag bits describing the conversion properties of
 844      * this transform.
 845      * The return value is either one of the constants TYPE_IDENTITY
 846      * or TYPE_GENERAL_TRANSFORM, or a combination of the
 847      * appropriate flag bits.
 848      * A valid combination of flag bits is an exclusive OR operation
 849      * that can combine
 850      * the TYPE_TRANSLATION flag bit
 851      * in addition to either of the
 852      * TYPE_UNIFORM_SCALE or TYPE_GENERAL_SCALE flag bits


 998     }
 999 
1000     /**
1001      * Returns the determinant of the matrix representation of the transform.
1002      * The determinant is useful both to determine if the transform can
1003      * be inverted and to get a single value representing the
1004      * combined X and Y scaling of the transform.
1005      * <p>
1006      * If the determinant is non-zero, then this transform is
1007      * invertible and the various methods that depend on the inverse
1008      * transform do not need to throw a
1009      * {@link NoninvertibleTransformException}.
1010      * If the determinant is zero then this transform can not be
1011      * inverted since the transform maps all input coordinates onto
1012      * a line or a point.
1013      * If the determinant is near enough to zero then inverse transform
1014      * operations might not carry enough precision to produce meaningful
1015      * results.
1016      * <p>
1017      * If this transform represents a uniform scale, as indicated by
1018      * the <code>getType</code> method then the determinant also
1019      * represents the square of the uniform scale factor by which all of
1020      * the points are expanded from or contracted towards the origin.
1021      * If this transform represents a non-uniform scale or more general
1022      * transform then the determinant is not likely to represent a
1023      * value useful for any purpose other than determining if inverse
1024      * transforms are possible.
1025      * <p>
1026      * Mathematically, the determinant is calculated using the formula:
1027      * <pre>
1028      *          |  m00  m01  m02  |
1029      *          |  m10  m11  m12  |  =  m00 * m11 - m01 * m10
1030      *          |   0    0    1   |
1031      * </pre>
1032      *
1033      * @return the determinant of the matrix used to transform the
1034      * coordinates.
1035      * @see #getType
1036      * @see #createInverse
1037      * @see #inverseTransform
1038      * @see #TYPE_UNIFORM_SCALE


1217      */
1218     public double getTranslateX() {
1219         return m02;
1220     }
1221 
1222     /**
1223      * Returns the Y coordinate of the translation element (m12) of the
1224      * 3x3 affine transformation matrix.
1225      * @return a double value that is the Y coordinate of the translation
1226      *  element of the affine transformation matrix.
1227      * @see #getMatrix
1228      * @since 1.2
1229      */
1230     public double getTranslateY() {
1231         return m12;
1232     }
1233 
1234     /**
1235      * Concatenates this transform with a translation transformation.
1236      * This is equivalent to calling concatenate(T), where T is an
1237      * <code>AffineTransform</code> represented by the following matrix:
1238      * <pre>
1239      *          [   1    0    tx  ]
1240      *          [   0    1    ty  ]
1241      *          [   0    0    1   ]
1242      * </pre>
1243      * @param tx the distance by which coordinates are translated in the
1244      * X axis direction
1245      * @param ty the distance by which coordinates are translated in the
1246      * Y axis direction
1247      * @since 1.2
1248      */
1249     public void translate(double tx, double ty) {
1250         switch (state) {
1251         default:
1252             stateError();
1253             /* NOTREACHED */
1254             return;
1255         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
1256             m02 = tx * m00 + ty * m01 + m02;
1257             m12 = tx * m10 + ty * m11 + m12;


1377     private final void rotate270() {
1378         double M0 = m00;
1379         m00 = -m01;
1380         m01 = M0;
1381         M0 = m10;
1382         m10 = -m11;
1383         m11 = M0;
1384         int state = rot90conversion[this.state];
1385         if ((state & (APPLY_SHEAR | APPLY_SCALE)) == APPLY_SCALE &&
1386             m00 == 1.0 && m11 == 1.0)
1387         {
1388             state -= APPLY_SCALE;
1389         }
1390         this.state = state;
1391         type = TYPE_UNKNOWN;
1392     }
1393 
1394     /**
1395      * Concatenates this transform with a rotation transformation.
1396      * This is equivalent to calling concatenate(R), where R is an
1397      * <code>AffineTransform</code> represented by the following matrix:
1398      * <pre>
1399      *          [   cos(theta)    -sin(theta)    0   ]
1400      *          [   sin(theta)     cos(theta)    0   ]
1401      *          [       0              0         1   ]
1402      * </pre>
1403      * Rotating by a positive angle theta rotates points on the positive
1404      * X axis toward the positive Y axis.
1405      * Note also the discussion of
1406      * <a href="#quadrantapproximation">Handling 90-Degree Rotations</a>
1407      * above.
1408      * @param theta the angle of rotation measured in radians
1409      * @since 1.2
1410      */
1411     public void rotate(double theta) {
1412         double sin = Math.sin(theta);
1413         if (sin == 1.0) {
1414             rotate90();
1415         } else if (sin == -1.0) {
1416             rotate270();
1417         } else {


1456      *
1457      * @param theta the angle of rotation measured in radians
1458      * @param anchorx the X coordinate of the rotation anchor point
1459      * @param anchory the Y coordinate of the rotation anchor point
1460      * @since 1.2
1461      */
1462     public void rotate(double theta, double anchorx, double anchory) {
1463         // REMIND: Simple for now - optimize later
1464         translate(anchorx, anchory);
1465         rotate(theta);
1466         translate(-anchorx, -anchory);
1467     }
1468 
1469     /**
1470      * Concatenates this transform with a transform that rotates
1471      * coordinates according to a rotation vector.
1472      * All coordinates rotate about the origin by the same amount.
1473      * The amount of rotation is such that coordinates along the former
1474      * positive X axis will subsequently align with the vector pointing
1475      * from the origin to the specified vector coordinates.
1476      * If both <code>vecx</code> and <code>vecy</code> are 0.0,
1477      * no additional rotation is added to this transform.
1478      * This operation is equivalent to calling:
1479      * <pre>
1480      *          rotate(Math.atan2(vecy, vecx));
1481      * </pre>
1482      *
1483      * @param vecx the X coordinate of the rotation vector
1484      * @param vecy the Y coordinate of the rotation vector
1485      * @since 1.6
1486      */
1487     public void rotate(double vecx, double vecy) {
1488         if (vecy == 0.0) {
1489             if (vecx < 0.0) {
1490                 rotate180();
1491             }
1492             // If vecx > 0.0 - no rotation
1493             // If vecx == 0.0 - undefined rotation - treat as no rotation
1494         } else if (vecx == 0.0) {
1495             if (vecy > 0.0) {
1496                 rotate90();


1506             M1 = m01;
1507             m00 =  cos * M0 + sin * M1;
1508             m01 = -sin * M0 + cos * M1;
1509             M0 = m10;
1510             M1 = m11;
1511             m10 =  cos * M0 + sin * M1;
1512             m11 = -sin * M0 + cos * M1;
1513             updateState();
1514         }
1515     }
1516 
1517     /**
1518      * Concatenates this transform with a transform that rotates
1519      * coordinates around an anchor point according to a rotation
1520      * vector.
1521      * All coordinates rotate about the specified anchor coordinates
1522      * by the same amount.
1523      * The amount of rotation is such that coordinates along the former
1524      * positive X axis will subsequently align with the vector pointing
1525      * from the origin to the specified vector coordinates.
1526      * If both <code>vecx</code> and <code>vecy</code> are 0.0,
1527      * the transform is not modified in any way.
1528      * This method is equivalent to calling:
1529      * <pre>
1530      *     rotate(Math.atan2(vecy, vecx), anchorx, anchory);
1531      * </pre>
1532      *
1533      * @param vecx the X coordinate of the rotation vector
1534      * @param vecy the Y coordinate of the rotation vector
1535      * @param anchorx the X coordinate of the rotation anchor point
1536      * @param anchory the Y coordinate of the rotation anchor point
1537      * @since 1.6
1538      */
1539     public void rotate(double vecx, double vecy,
1540                        double anchorx, double anchory)
1541     {
1542         // REMIND: Simple for now - optimize later
1543         translate(anchorx, anchory);
1544         rotate(vecx, vecy);
1545         translate(-anchorx, -anchory);
1546     }


1604             m02 += anchorx * (m00 + m00) + anchory * (m01 + m01);
1605             m12 += anchorx * (m10 + m10) + anchory * (m11 + m11);
1606             rotate180();
1607             break;
1608         case 3:
1609             m02 += anchorx * (m00 + m01) + anchory * (m01 - m00);
1610             m12 += anchorx * (m10 + m11) + anchory * (m11 - m10);
1611             rotate270();
1612             break;
1613         }
1614         if (m02 == 0.0 && m12 == 0.0) {
1615             state &= ~APPLY_TRANSLATE;
1616         } else {
1617             state |= APPLY_TRANSLATE;
1618         }
1619     }
1620 
1621     /**
1622      * Concatenates this transform with a scaling transformation.
1623      * This is equivalent to calling concatenate(S), where S is an
1624      * <code>AffineTransform</code> represented by the following matrix:
1625      * <pre>
1626      *          [   sx   0    0   ]
1627      *          [   0    sy   0   ]
1628      *          [   0    0    1   ]
1629      * </pre>
1630      * @param sx the factor by which coordinates are scaled along the
1631      * X axis direction
1632      * @param sy the factor by which coordinates are scaled along the
1633      * Y axis direction
1634      * @since 1.2
1635      */
1636     @SuppressWarnings("fallthrough")
1637     public void scale(double sx, double sy) {
1638         int state = this.state;
1639         switch (state) {
1640         default:
1641             stateError();
1642             /* NOTREACHED */
1643         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
1644         case (APPLY_SHEAR | APPLY_SCALE):


1673                              : TYPE_TRANSLATION);
1674             } else {
1675                 this.type = TYPE_UNKNOWN;
1676             }
1677             return;
1678         case (APPLY_TRANSLATE):
1679         case (APPLY_IDENTITY):
1680             m00 = sx;
1681             m11 = sy;
1682             if (sx != 1.0 || sy != 1.0) {
1683                 this.state = state | APPLY_SCALE;
1684                 this.type = TYPE_UNKNOWN;
1685             }
1686             return;
1687         }
1688     }
1689 
1690     /**
1691      * Concatenates this transform with a shearing transformation.
1692      * This is equivalent to calling concatenate(SH), where SH is an
1693      * <code>AffineTransform</code> represented by the following matrix:
1694      * <pre>
1695      *          [   1   shx   0   ]
1696      *          [  shy   1    0   ]
1697      *          [   0    0    1   ]
1698      * </pre>
1699      * @param shx the multiplier by which coordinates are shifted in the
1700      * direction of the positive X axis as a factor of their Y coordinate
1701      * @param shy the multiplier by which coordinates are shifted in the
1702      * direction of the positive Y axis as a factor of their X coordinate
1703      * @since 1.2
1704      */
1705     public void shear(double shx, double shy) {
1706         int state = this.state;
1707         switch (state) {
1708         default:
1709             stateError();
1710             /* NOTREACHED */
1711             return;
1712         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
1713         case (APPLY_SHEAR | APPLY_SCALE):


1873      */
1874     public void setToRotation(double theta, double anchorx, double anchory) {
1875         setToRotation(theta);
1876         double sin = m10;
1877         double oneMinusCos = 1.0 - m00;
1878         m02 = anchorx * oneMinusCos + anchory * sin;
1879         m12 = anchory * oneMinusCos - anchorx * sin;
1880         if (m02 != 0.0 || m12 != 0.0) {
1881             state |= APPLY_TRANSLATE;
1882             type |= TYPE_TRANSLATION;
1883         }
1884     }
1885 
1886     /**
1887      * Sets this transform to a rotation transformation that rotates
1888      * coordinates according to a rotation vector.
1889      * All coordinates rotate about the origin by the same amount.
1890      * The amount of rotation is such that coordinates along the former
1891      * positive X axis will subsequently align with the vector pointing
1892      * from the origin to the specified vector coordinates.
1893      * If both <code>vecx</code> and <code>vecy</code> are 0.0,
1894      * the transform is set to an identity transform.
1895      * This operation is equivalent to calling:
1896      * <pre>
1897      *     setToRotation(Math.atan2(vecy, vecx));
1898      * </pre>
1899      *
1900      * @param vecx the X coordinate of the rotation vector
1901      * @param vecy the Y coordinate of the rotation vector
1902      * @since 1.6
1903      */
1904     public void setToRotation(double vecx, double vecy) {
1905         double sin, cos;
1906         if (vecy == 0) {
1907             sin = 0.0;
1908             if (vecx < 0.0) {
1909                 cos = -1.0;
1910                 state = APPLY_SCALE;
1911                 type = TYPE_QUADRANT_ROTATION;
1912             } else {
1913                 cos = 1.0;


1926             state = APPLY_SHEAR | APPLY_SCALE;
1927             type = TYPE_GENERAL_ROTATION;
1928         }
1929         m00 =  cos;
1930         m10 =  sin;
1931         m01 = -sin;
1932         m11 =  cos;
1933         m02 =  0.0;
1934         m12 =  0.0;
1935     }
1936 
1937     /**
1938      * Sets this transform to a rotation transformation that rotates
1939      * coordinates around an anchor point according to a rotation
1940      * vector.
1941      * All coordinates rotate about the specified anchor coordinates
1942      * by the same amount.
1943      * The amount of rotation is such that coordinates along the former
1944      * positive X axis will subsequently align with the vector pointing
1945      * from the origin to the specified vector coordinates.
1946      * If both <code>vecx</code> and <code>vecy</code> are 0.0,
1947      * the transform is set to an identity transform.
1948      * This operation is equivalent to calling:
1949      * <pre>
1950      *     setToTranslation(Math.atan2(vecy, vecx), anchorx, anchory);
1951      * </pre>
1952      *
1953      * @param vecx the X coordinate of the rotation vector
1954      * @param vecy the Y coordinate of the rotation vector
1955      * @param anchorx the X coordinate of the rotation anchor point
1956      * @param anchory the Y coordinate of the rotation anchor point
1957      * @since 1.6
1958      */
1959     public void setToRotation(double vecx, double vecy,
1960                               double anchorx, double anchory)
1961     {
1962         setToRotation(vecx, vecy);
1963         double sin = m10;
1964         double oneMinusCos = 1.0 - m00;
1965         m02 = anchorx * oneMinusCos + anchory * sin;
1966         m12 = anchory * oneMinusCos - anchorx * sin;


2150      * @since 1.2
2151      */
2152     public void setToShear(double shx, double shy) {
2153         m00 = 1.0;
2154         m01 = shx;
2155         m10 = shy;
2156         m11 = 1.0;
2157         m02 = 0.0;
2158         m12 = 0.0;
2159         if (shx != 0.0 || shy != 0.0) {
2160             state = (APPLY_SHEAR | APPLY_SCALE);
2161             type = TYPE_UNKNOWN;
2162         } else {
2163             state = APPLY_IDENTITY;
2164             type = TYPE_IDENTITY;
2165         }
2166     }
2167 
2168     /**
2169      * Sets this transform to a copy of the transform in the specified
2170      * <code>AffineTransform</code> object.
2171      * @param Tx the <code>AffineTransform</code> object from which to
2172      * copy the transform
2173      * @since 1.2
2174      */
2175     public void setTransform(AffineTransform Tx) {
2176         this.m00 = Tx.m00;
2177         this.m10 = Tx.m10;
2178         this.m01 = Tx.m01;
2179         this.m11 = Tx.m11;
2180         this.m02 = Tx.m02;
2181         this.m12 = Tx.m12;
2182         this.state = Tx.state;
2183         this.type = Tx.type;
2184     }
2185 
2186     /**
2187      * Sets this transform to the matrix specified by the 6
2188      * double precision values.
2189      *
2190      * @param m00 the X coordinate scaling element of the 3x3 matrix
2191      * @param m10 the Y coordinate shearing element of the 3x3 matrix
2192      * @param m01 the X coordinate shearing element of the 3x3 matrix
2193      * @param m11 the Y coordinate scaling element of the 3x3 matrix
2194      * @param m02 the X coordinate translation element of the 3x3 matrix
2195      * @param m12 the Y coordinate translation element of the 3x3 matrix
2196      * @since 1.2
2197      */
2198     public void setTransform(double m00, double m10,
2199                              double m01, double m11,
2200                              double m02, double m12) {
2201         this.m00 = m00;
2202         this.m10 = m10;
2203         this.m01 = m01;
2204         this.m11 = m11;
2205         this.m02 = m02;
2206         this.m12 = m12;
2207         updateState();
2208     }
2209 
2210     /**
2211      * Concatenates an <code>AffineTransform</code> <code>Tx</code> to
2212      * this <code>AffineTransform</code> Cx in the most commonly useful
2213      * way to provide a new user space
2214      * that is mapped to the former user space by <code>Tx</code>.
2215      * Cx is updated to perform the combined transformation.
2216      * Transforming a point p by the updated transform Cx' is
2217      * equivalent to first transforming p by <code>Tx</code> and then
2218      * transforming the result by the original transform Cx like this:
2219      * Cx'(p) = Cx(Tx(p))
2220      * In matrix notation, if this transform Cx is
2221      * represented by the matrix [this] and <code>Tx</code> is represented
2222      * by the matrix [Tx] then this method does the following:
2223      * <pre>
2224      *          [this] = [this] x [Tx]
2225      * </pre>
2226      * @param Tx the <code>AffineTransform</code> object to be
2227      * concatenated with this <code>AffineTransform</code> object.
2228      * @see #preConcatenate
2229      * @since 1.2
2230      */
2231     @SuppressWarnings("fallthrough")
2232     public void concatenate(AffineTransform Tx) {
2233         double M0, M1;
2234         double T00, T01, T10, T11;
2235         double T02, T12;
2236         int mystate = state;
2237         int txstate = Tx.state;
2238         switch ((txstate << HI_SHIFT) | mystate) {
2239 
2240             /* ---------- Tx == IDENTITY cases ---------- */
2241         case (HI_IDENTITY | APPLY_IDENTITY):
2242         case (HI_IDENTITY | APPLY_TRANSLATE):
2243         case (HI_IDENTITY | APPLY_SCALE):
2244         case (HI_IDENTITY | APPLY_SCALE | APPLY_TRANSLATE):
2245         case (HI_IDENTITY | APPLY_SHEAR):
2246         case (HI_IDENTITY | APPLY_SHEAR | APPLY_TRANSLATE):
2247         case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE):


2397             m11  = T11 * M0;
2398             m12 += T12 * M0;
2399             break;
2400 
2401         case (APPLY_TRANSLATE):
2402             m00  = T00;
2403             m01  = T01;
2404             m02 += T02;
2405 
2406             m10  = T10;
2407             m11  = T11;
2408             m12 += T12;
2409             state = txstate | APPLY_TRANSLATE;
2410             type = TYPE_UNKNOWN;
2411             return;
2412         }
2413         updateState();
2414     }
2415 
2416     /**
2417      * Concatenates an <code>AffineTransform</code> <code>Tx</code> to
2418      * this <code>AffineTransform</code> Cx
2419      * in a less commonly used way such that <code>Tx</code> modifies the
2420      * coordinate transformation relative to the absolute pixel
2421      * space rather than relative to the existing user space.
2422      * Cx is updated to perform the combined transformation.
2423      * Transforming a point p by the updated transform Cx' is
2424      * equivalent to first transforming p by the original transform
2425      * Cx and then transforming the result by
2426      * <code>Tx</code> like this:
2427      * Cx'(p) = Tx(Cx(p))
2428      * In matrix notation, if this transform Cx
2429      * is represented by the matrix [this] and <code>Tx</code> is
2430      * represented by the matrix [Tx] then this method does the
2431      * following:
2432      * <pre>
2433      *          [this] = [Tx] x [this]
2434      * </pre>
2435      * @param Tx the <code>AffineTransform</code> object to be
2436      * concatenated with this <code>AffineTransform</code> object.
2437      * @see #concatenate
2438      * @since 1.2
2439      */
2440     @SuppressWarnings("fallthrough")
2441     public void preConcatenate(AffineTransform Tx) {
2442         double M0, M1;
2443         double T00, T01, T10, T11;
2444         double T02, T12;
2445         int mystate = state;
2446         int txstate = Tx.state;
2447         switch ((txstate << HI_SHIFT) | mystate) {
2448         case (HI_IDENTITY | APPLY_IDENTITY):
2449         case (HI_IDENTITY | APPLY_TRANSLATE):
2450         case (HI_IDENTITY | APPLY_SCALE):
2451         case (HI_IDENTITY | APPLY_SCALE | APPLY_TRANSLATE):
2452         case (HI_IDENTITY | APPLY_SHEAR):
2453         case (HI_IDENTITY | APPLY_SHEAR | APPLY_TRANSLATE):
2454         case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE):
2455         case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2456             // Tx is IDENTITY...


2615 
2616             /* NOBREAK */
2617         case (APPLY_IDENTITY):
2618             m02 = T02;
2619             m12 = T12;
2620 
2621             m00 = T00;
2622             m10 = T10;
2623 
2624             m01 = T01;
2625             m11 = T11;
2626 
2627             state = mystate | txstate;
2628             type = TYPE_UNKNOWN;
2629             return;
2630         }
2631         updateState();
2632     }
2633 
2634     /**
2635      * Returns an <code>AffineTransform</code> object representing the
2636      * inverse transformation.
2637      * The inverse transform Tx' of this transform Tx
2638      * maps coordinates transformed by Tx back
2639      * to their original coordinates.
2640      * In other words, Tx'(Tx(p)) = p = Tx(Tx'(p)).
2641      * <p>
2642      * If this transform maps all coordinates onto a point or a line
2643      * then it will not have an inverse, since coordinates that do
2644      * not lie on the destination point or line will not have an inverse
2645      * mapping.
2646      * The <code>getDeterminant</code> method can be used to determine if this
2647      * transform has no inverse, in which case an exception will be
2648      * thrown if the <code>createInverse</code> method is called.
2649      * @return a new <code>AffineTransform</code> object representing the
2650      * inverse transformation.
2651      * @see #getDeterminant
2652      * @exception NoninvertibleTransformException
2653      * if the matrix cannot be inverted.
2654      * @since 1.2
2655      */
2656     public AffineTransform createInverse()
2657         throws NoninvertibleTransformException
2658     {
2659         double det;
2660         switch (state) {
2661         default:
2662             stateError();
2663             /* NOTREACHED */
2664             return null;
2665         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2666             det = m00 * m11 - m01 * m10;
2667             if (Math.abs(det) <= Double.MIN_VALUE) {
2668                 throw new NoninvertibleTransformException("Determinant is "+
2669                                                           det);


2723                                        -m02, -m12,
2724                                        (APPLY_TRANSLATE));
2725         case (APPLY_IDENTITY):
2726             return new AffineTransform();
2727         }
2728 
2729         /* NOTREACHED */
2730     }
2731 
2732     /**
2733      * Sets this transform to the inverse of itself.
2734      * The inverse transform Tx' of this transform Tx
2735      * maps coordinates transformed by Tx back
2736      * to their original coordinates.
2737      * In other words, Tx'(Tx(p)) = p = Tx(Tx'(p)).
2738      * <p>
2739      * If this transform maps all coordinates onto a point or a line
2740      * then it will not have an inverse, since coordinates that do
2741      * not lie on the destination point or line will not have an inverse
2742      * mapping.
2743      * The <code>getDeterminant</code> method can be used to determine if this
2744      * transform has no inverse, in which case an exception will be
2745      * thrown if the <code>invert</code> method is called.
2746      * @see #getDeterminant
2747      * @exception NoninvertibleTransformException
2748      * if the matrix cannot be inverted.
2749      * @since 1.6
2750      */
2751     public void invert()
2752         throws NoninvertibleTransformException
2753     {
2754         double M00, M01, M02;
2755         double M10, M11, M12;
2756         double det;
2757         switch (state) {
2758         default:
2759             stateError();
2760             /* NOTREACHED */
2761             return;
2762         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2763             M00 = m00; M01 = m01; M02 = m02;
2764             M10 = m10; M11 = m11; M12 = m12;
2765             det = M00 * M11 - M01 * M10;


2844         case (APPLY_TRANSLATE):
2845             // m00 = 1.0;
2846             // m10 = 0.0;
2847             // m01 = 0.0;
2848             // m11 = 1.0;
2849             m02 = -m02;
2850             m12 = -m12;
2851             break;
2852         case (APPLY_IDENTITY):
2853             // m00 = 1.0;
2854             // m10 = 0.0;
2855             // m01 = 0.0;
2856             // m11 = 1.0;
2857             // m02 = 0.0;
2858             // m12 = 0.0;
2859             break;
2860         }
2861     }
2862 
2863     /**
2864      * Transforms the specified <code>ptSrc</code> and stores the result
2865      * in <code>ptDst</code>.
2866      * If <code>ptDst</code> is <code>null</code>, a new {@link Point2D}
2867      * object is allocated and then the result of the transformation is
2868      * stored in this object.
2869      * In either case, <code>ptDst</code>, which contains the
2870      * transformed point, is returned for convenience.
2871      * If <code>ptSrc</code> and <code>ptDst</code> are the same
2872      * object, the input point is correctly overwritten with
2873      * the transformed point.
2874      * @param ptSrc the specified <code>Point2D</code> to be transformed
2875      * @param ptDst the specified <code>Point2D</code> that stores the
2876      * result of transforming <code>ptSrc</code>
2877      * @return the <code>ptDst</code> after transforming
2878      * <code>ptSrc</code> and storing the result in <code>ptDst</code>.
2879      * @since 1.2
2880      */
2881     public Point2D transform(Point2D ptSrc, Point2D ptDst) {
2882         if (ptDst == null) {
2883             if (ptSrc instanceof Point2D.Double) {
2884                 ptDst = new Point2D.Double();
2885             } else {
2886                 ptDst = new Point2D.Float();
2887             }
2888         }
2889         // Copy source coords into local variables in case src == dst
2890         double x = ptSrc.getX();
2891         double y = ptSrc.getY();
2892         switch (state) {
2893         default:
2894             stateError();
2895             /* NOTREACHED */
2896             return null;
2897         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2898             ptDst.setLocation(x * m00 + y * m01 + m02,


2909             return ptDst;
2910         case (APPLY_SCALE | APPLY_TRANSLATE):
2911             ptDst.setLocation(x * m00 + m02, y * m11 + m12);
2912             return ptDst;
2913         case (APPLY_SCALE):
2914             ptDst.setLocation(x * m00, y * m11);
2915             return ptDst;
2916         case (APPLY_TRANSLATE):
2917             ptDst.setLocation(x + m02, y + m12);
2918             return ptDst;
2919         case (APPLY_IDENTITY):
2920             ptDst.setLocation(x, y);
2921             return ptDst;
2922         }
2923 
2924         /* NOTREACHED */
2925     }
2926 
2927     /**
2928      * Transforms an array of point objects by this transform.
2929      * If any element of the <code>ptDst</code> array is
2930      * <code>null</code>, a new <code>Point2D</code> object is allocated
2931      * and stored into that element before storing the results of the
2932      * transformation.
2933      * <p>
2934      * Note that this method does not take any precautions to
2935      * avoid problems caused by storing results into <code>Point2D</code>
2936      * objects that will be used as the source for calculations
2937      * further down the source array.
2938      * This method does guarantee that if a specified <code>Point2D</code>
2939      * object is both the source and destination for the same single point
2940      * transform operation then the results will not be stored until
2941      * the calculations are complete to avoid storing the results on
2942      * top of the operands.
2943      * If, however, the destination <code>Point2D</code> object for one
2944      * operation is the same object as the source <code>Point2D</code>
2945      * object for another operation further down the source array then
2946      * the original coordinates in that point are overwritten before
2947      * they can be converted.
2948      * @param ptSrc the array containing the source point objects
2949      * @param ptDst the array into which the transform point objects are
2950      * returned
2951      * @param srcOff the offset to the first point object to be
2952      * transformed in the source array
2953      * @param dstOff the offset to the location of the first
2954      * transformed point object that is stored in the destination array
2955      * @param numPts the number of point objects to be transformed
2956      * @since 1.2
2957      */
2958     public void transform(Point2D[] ptSrc, int srcOff,
2959                           Point2D[] ptDst, int dstOff,
2960                           int numPts) {
2961         int state = this.state;
2962         while (--numPts >= 0) {
2963             // Copy source coords into local variables in case src == dst
2964             Point2D src = ptSrc[srcOff++];


3000             case (APPLY_TRANSLATE):
3001                 dst.setLocation(x + m02, y + m12);
3002                 break;
3003             case (APPLY_IDENTITY):
3004                 dst.setLocation(x, y);
3005                 break;
3006             }
3007         }
3008 
3009         /* NOTREACHED */
3010     }
3011 
3012     /**
3013      * Transforms an array of floating point coordinates by this transform.
3014      * The two coordinate array sections can be exactly the same or
3015      * can be overlapping sections of the same array without affecting the
3016      * validity of the results.
3017      * This method ensures that no source coordinates are overwritten by a
3018      * previous operation before they can be transformed.
3019      * The coordinates are stored in the arrays starting at the specified
3020      * offset in the order <code>[x0, y0, x1, y1, ..., xn, yn]</code>.
3021      * @param srcPts the array containing the source point coordinates.
3022      * Each point is stored as a pair of x,&nbsp;y coordinates.
3023      * @param dstPts the array into which the transformed point coordinates
3024      * are returned.  Each point is stored as a pair of x,&nbsp;y
3025      * coordinates.
3026      * @param srcOff the offset to the first point to be transformed
3027      * in the source array
3028      * @param dstOff the offset to the location of the first
3029      * transformed point that is stored in the destination array
3030      * @param numPts the number of points to be transformed
3031      * @since 1.2
3032      */
3033     public void transform(float[] srcPts, int srcOff,
3034                           float[] dstPts, int dstOff,
3035                           int numPts) {
3036         double M00, M01, M02, M10, M11, M12;    // For caching
3037         if (dstPts == srcPts &&
3038             dstOff > srcOff && dstOff < srcOff + numPts * 2)
3039         {
3040             // If the arrays overlap partially with the destination higher


3115             return;
3116         case (APPLY_IDENTITY):
3117             if (srcPts != dstPts || srcOff != dstOff) {
3118                 System.arraycopy(srcPts, srcOff, dstPts, dstOff,
3119                                  numPts * 2);
3120             }
3121             return;
3122         }
3123 
3124         /* NOTREACHED */
3125     }
3126 
3127     /**
3128      * Transforms an array of double precision coordinates by this transform.
3129      * The two coordinate array sections can be exactly the same or
3130      * can be overlapping sections of the same array without affecting the
3131      * validity of the results.
3132      * This method ensures that no source coordinates are
3133      * overwritten by a previous operation before they can be transformed.
3134      * The coordinates are stored in the arrays starting at the indicated
3135      * offset in the order <code>[x0, y0, x1, y1, ..., xn, yn]</code>.
3136      * @param srcPts the array containing the source point coordinates.
3137      * Each point is stored as a pair of x,&nbsp;y coordinates.
3138      * @param dstPts the array into which the transformed point
3139      * coordinates are returned.  Each point is stored as a pair of
3140      * x,&nbsp;y coordinates.
3141      * @param srcOff the offset to the first point to be transformed
3142      * in the source array
3143      * @param dstOff the offset to the location of the first
3144      * transformed point that is stored in the destination array
3145      * @param numPts the number of point objects to be transformed
3146      * @since 1.2
3147      */
3148     public void transform(double[] srcPts, int srcOff,
3149                           double[] dstPts, int dstOff,
3150                           int numPts) {
3151         double M00, M01, M02, M10, M11, M12;    // For caching
3152         if (dstPts == srcPts &&
3153             dstOff > srcOff && dstOff < srcOff + numPts * 2)
3154         {
3155             // If the arrays overlap partially with the destination higher


3226             while (--numPts >= 0) {
3227                 dstPts[dstOff++] = srcPts[srcOff++] + M02;
3228                 dstPts[dstOff++] = srcPts[srcOff++] + M12;
3229             }
3230             return;
3231         case (APPLY_IDENTITY):
3232             if (srcPts != dstPts || srcOff != dstOff) {
3233                 System.arraycopy(srcPts, srcOff, dstPts, dstOff,
3234                                  numPts * 2);
3235             }
3236             return;
3237         }
3238 
3239         /* NOTREACHED */
3240     }
3241 
3242     /**
3243      * Transforms an array of floating point coordinates by this transform
3244      * and stores the results into an array of doubles.
3245      * The coordinates are stored in the arrays starting at the specified
3246      * offset in the order <code>[x0, y0, x1, y1, ..., xn, yn]</code>.
3247      * @param srcPts the array containing the source point coordinates.
3248      * Each point is stored as a pair of x,&nbsp;y coordinates.
3249      * @param dstPts the array into which the transformed point coordinates
3250      * are returned.  Each point is stored as a pair of x,&nbsp;y
3251      * coordinates.
3252      * @param srcOff the offset to the first point to be transformed
3253      * in the source array
3254      * @param dstOff the offset to the location of the first
3255      * transformed point that is stored in the destination array
3256      * @param numPts the number of points to be transformed
3257      * @since 1.2
3258      */
3259     public void transform(float[] srcPts, int srcOff,
3260                           double[] dstPts, int dstOff,
3261                           int numPts) {
3262         double M00, M01, M02, M10, M11, M12;    // For caching
3263         switch (state) {
3264         default:
3265             stateError();
3266             /* NOTREACHED */


3322             while (--numPts >= 0) {
3323                 dstPts[dstOff++] = srcPts[srcOff++] + M02;
3324                 dstPts[dstOff++] = srcPts[srcOff++] + M12;
3325             }
3326             return;
3327         case (APPLY_IDENTITY):
3328             while (--numPts >= 0) {
3329                 dstPts[dstOff++] = srcPts[srcOff++];
3330                 dstPts[dstOff++] = srcPts[srcOff++];
3331             }
3332             return;
3333         }
3334 
3335         /* NOTREACHED */
3336     }
3337 
3338     /**
3339      * Transforms an array of double precision coordinates by this transform
3340      * and stores the results into an array of floats.
3341      * The coordinates are stored in the arrays starting at the specified
3342      * offset in the order <code>[x0, y0, x1, y1, ..., xn, yn]</code>.
3343      * @param srcPts the array containing the source point coordinates.
3344      * Each point is stored as a pair of x,&nbsp;y coordinates.
3345      * @param dstPts the array into which the transformed point
3346      * coordinates are returned.  Each point is stored as a pair of
3347      * x,&nbsp;y coordinates.
3348      * @param srcOff the offset to the first point to be transformed
3349      * in the source array
3350      * @param dstOff the offset to the location of the first
3351      * transformed point that is stored in the destination array
3352      * @param numPts the number of point objects to be transformed
3353      * @since 1.2
3354      */
3355     public void transform(double[] srcPts, int srcOff,
3356                           float[] dstPts, int dstOff,
3357                           int numPts) {
3358         double M00, M01, M02, M10, M11, M12;    // For caching
3359         switch (state) {
3360         default:
3361             stateError();
3362             /* NOTREACHED */


3415             return;
3416         case (APPLY_TRANSLATE):
3417             M02 = m02; M12 = m12;
3418             while (--numPts >= 0) {
3419                 dstPts[dstOff++] = (float) (srcPts[srcOff++] + M02);
3420                 dstPts[dstOff++] = (float) (srcPts[srcOff++] + M12);
3421             }
3422             return;
3423         case (APPLY_IDENTITY):
3424             while (--numPts >= 0) {
3425                 dstPts[dstOff++] = (float) (srcPts[srcOff++]);
3426                 dstPts[dstOff++] = (float) (srcPts[srcOff++]);
3427             }
3428             return;
3429         }
3430 
3431         /* NOTREACHED */
3432     }
3433 
3434     /**
3435      * Inverse transforms the specified <code>ptSrc</code> and stores the
3436      * result in <code>ptDst</code>.
3437      * If <code>ptDst</code> is <code>null</code>, a new
3438      * <code>Point2D</code> object is allocated and then the result of the
3439      * transform is stored in this object.
3440      * In either case, <code>ptDst</code>, which contains the transformed
3441      * point, is returned for convenience.
3442      * If <code>ptSrc</code> and <code>ptDst</code> are the same
3443      * object, the input point is correctly overwritten with the
3444      * transformed point.
3445      * @param ptSrc the point to be inverse transformed
3446      * @param ptDst the resulting transformed point
3447      * @return <code>ptDst</code>, which contains the result of the
3448      * inverse transform.
3449      * @exception NoninvertibleTransformException  if the matrix cannot be
3450      *                                         inverted.
3451      * @since 1.2
3452      */
3453     @SuppressWarnings("fallthrough")
3454     public Point2D inverseTransform(Point2D ptSrc, Point2D ptDst)
3455         throws NoninvertibleTransformException
3456     {
3457         if (ptDst == null) {
3458             if (ptSrc instanceof Point2D.Double) {
3459                 ptDst = new Point2D.Double();
3460             } else {
3461                 ptDst = new Point2D.Float();
3462             }
3463         }
3464         // Copy source coords into local variables in case src == dst
3465         double x = ptSrc.getX();
3466         double y = ptSrc.getY();
3467         switch (state) {


3504         case (APPLY_TRANSLATE):
3505             ptDst.setLocation(x - m02, y - m12);
3506             return ptDst;
3507         case (APPLY_IDENTITY):
3508             ptDst.setLocation(x, y);
3509             return ptDst;
3510         }
3511 
3512         /* NOTREACHED */
3513     }
3514 
3515     /**
3516      * Inverse transforms an array of double precision coordinates by
3517      * this transform.
3518      * The two coordinate array sections can be exactly the same or
3519      * can be overlapping sections of the same array without affecting the
3520      * validity of the results.
3521      * This method ensures that no source coordinates are
3522      * overwritten by a previous operation before they can be transformed.
3523      * The coordinates are stored in the arrays starting at the specified
3524      * offset in the order <code>[x0, y0, x1, y1, ..., xn, yn]</code>.
3525      * @param srcPts the array containing the source point coordinates.
3526      * Each point is stored as a pair of x,&nbsp;y coordinates.
3527      * @param dstPts the array into which the transformed point
3528      * coordinates are returned.  Each point is stored as a pair of
3529      * x,&nbsp;y coordinates.
3530      * @param srcOff the offset to the first point to be transformed
3531      * in the source array
3532      * @param dstOff the offset to the location of the first
3533      * transformed point that is stored in the destination array
3534      * @param numPts the number of point objects to be transformed
3535      * @exception NoninvertibleTransformException  if the matrix cannot be
3536      *                                         inverted.
3537      * @since 1.2
3538      */
3539     public void inverseTransform(double[] srcPts, int srcOff,
3540                                  double[] dstPts, int dstOff,
3541                                  int numPts)
3542         throws NoninvertibleTransformException
3543     {
3544         double M00, M01, M02, M10, M11, M12;    // For caching


3640         case (APPLY_TRANSLATE):
3641             M02 = m02; M12 = m12;
3642             while (--numPts >= 0) {
3643                 dstPts[dstOff++] = srcPts[srcOff++] - M02;
3644                 dstPts[dstOff++] = srcPts[srcOff++] - M12;
3645             }
3646             return;
3647         case (APPLY_IDENTITY):
3648             if (srcPts != dstPts || srcOff != dstOff) {
3649                 System.arraycopy(srcPts, srcOff, dstPts, dstOff,
3650                                  numPts * 2);
3651             }
3652             return;
3653         }
3654 
3655         /* NOTREACHED */
3656     }
3657 
3658     /**
3659      * Transforms the relative distance vector specified by
3660      * <code>ptSrc</code> and stores the result in <code>ptDst</code>.
3661      * A relative distance vector is transformed without applying the
3662      * translation components of the affine transformation matrix
3663      * using the following equations:
3664      * <pre>
3665      *  [  x' ]   [  m00  m01 (m02) ] [  x  ]   [ m00x + m01y ]
3666      *  [  y' ] = [  m10  m11 (m12) ] [  y  ] = [ m10x + m11y ]
3667      *  [ (1) ]   [  (0)  (0) ( 1 ) ] [ (1) ]   [     (1)     ]
3668      * </pre>
3669      * If <code>ptDst</code> is <code>null</code>, a new
3670      * <code>Point2D</code> object is allocated and then the result of the
3671      * transform is stored in this object.
3672      * In either case, <code>ptDst</code>, which contains the
3673      * transformed point, is returned for convenience.
3674      * If <code>ptSrc</code> and <code>ptDst</code> are the same object,
3675      * the input point is correctly overwritten with the transformed
3676      * point.
3677      * @param ptSrc the distance vector to be delta transformed
3678      * @param ptDst the resulting transformed distance vector
3679      * @return <code>ptDst</code>, which contains the result of the
3680      * transformation.
3681      * @since 1.2
3682      */
3683     public Point2D deltaTransform(Point2D ptSrc, Point2D ptDst) {
3684         if (ptDst == null) {
3685             if (ptSrc instanceof Point2D.Double) {
3686                 ptDst = new Point2D.Double();
3687             } else {
3688                 ptDst = new Point2D.Float();
3689             }
3690         }
3691         // Copy source coords into local variables in case src == dst
3692         double x = ptSrc.getX();
3693         double y = ptSrc.getY();
3694         switch (state) {
3695         default:
3696             stateError();
3697             /* NOTREACHED */
3698             return null;
3699         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):


3717         /* NOTREACHED */
3718     }
3719 
3720     /**
3721      * Transforms an array of relative distance vectors by this
3722      * transform.
3723      * A relative distance vector is transformed without applying the
3724      * translation components of the affine transformation matrix
3725      * using the following equations:
3726      * <pre>
3727      *  [  x' ]   [  m00  m01 (m02) ] [  x  ]   [ m00x + m01y ]
3728      *  [  y' ] = [  m10  m11 (m12) ] [  y  ] = [ m10x + m11y ]
3729      *  [ (1) ]   [  (0)  (0) ( 1 ) ] [ (1) ]   [     (1)     ]
3730      * </pre>
3731      * The two coordinate array sections can be exactly the same or
3732      * can be overlapping sections of the same array without affecting the
3733      * validity of the results.
3734      * This method ensures that no source coordinates are
3735      * overwritten by a previous operation before they can be transformed.
3736      * The coordinates are stored in the arrays starting at the indicated
3737      * offset in the order <code>[x0, y0, x1, y1, ..., xn, yn]</code>.
3738      * @param srcPts the array containing the source distance vectors.
3739      * Each vector is stored as a pair of relative x,&nbsp;y coordinates.
3740      * @param dstPts the array into which the transformed distance vectors
3741      * are returned.  Each vector is stored as a pair of relative
3742      * x,&nbsp;y coordinates.
3743      * @param srcOff the offset to the first vector to be transformed
3744      * in the source array
3745      * @param dstOff the offset to the location of the first
3746      * transformed vector that is stored in the destination array
3747      * @param numPts the number of vector coordinate pairs to be
3748      * transformed
3749      * @since 1.2
3750      */
3751     public void deltaTransform(double[] srcPts, int srcOff,
3752                                double[] dstPts, int dstOff,
3753                                int numPts) {
3754         double M00, M01, M10, M11;      // For caching
3755         if (dstPts == srcPts &&
3756             dstOff > srcOff && dstOff < srcOff + numPts * 2)
3757         {


3797             M00 = m00; M11 = m11;
3798             while (--numPts >= 0) {
3799                 dstPts[dstOff++] = srcPts[srcOff++] * M00;
3800                 dstPts[dstOff++] = srcPts[srcOff++] * M11;
3801             }
3802             return;
3803         case (APPLY_TRANSLATE):
3804         case (APPLY_IDENTITY):
3805             if (srcPts != dstPts || srcOff != dstOff) {
3806                 System.arraycopy(srcPts, srcOff, dstPts, dstOff,
3807                                  numPts * 2);
3808             }
3809             return;
3810         }
3811 
3812         /* NOTREACHED */
3813     }
3814 
3815     /**
3816      * Returns a new {@link Shape} object defined by the geometry of the
3817      * specified <code>Shape</code> after it has been transformed by
3818      * this transform.
3819      * @param pSrc the specified <code>Shape</code> object to be
3820      * transformed by this transform.
3821      * @return a new <code>Shape</code> object that defines the geometry
3822      * of the transformed <code>Shape</code>, or null if {@code pSrc} is null.
3823      * @since 1.2
3824      */
3825     public Shape createTransformedShape(Shape pSrc) {
3826         if (pSrc == null) {
3827             return null;
3828         }
3829         return new Path2D.Double(pSrc, this);
3830     }
3831 
3832     // Round values to sane precision for printing
3833     // Note that Math.sin(Math.PI) has an error of about 10^-16
3834     private static double _matround(double matval) {
3835         return Math.rint(matval * 1E15) / 1E15;
3836     }
3837 
3838     /**
3839      * Returns a <code>String</code> that represents the value of this
3840      * {@link Object}.
3841      * @return a <code>String</code> representing the value of this
3842      * <code>Object</code>.
3843      * @since 1.2
3844      */
3845     public String toString() {
3846         return ("AffineTransform[["
3847                 + _matround(m00) + ", "
3848                 + _matround(m01) + ", "
3849                 + _matround(m02) + "], ["
3850                 + _matround(m10) + ", "
3851                 + _matround(m11) + ", "
3852                 + _matround(m12) + "]]");
3853     }
3854 
3855     /**
3856      * Returns <code>true</code> if this <code>AffineTransform</code> is
3857      * an identity transform.
3858      * @return <code>true</code> if this <code>AffineTransform</code> is
3859      * an identity transform; <code>false</code> otherwise.
3860      * @since 1.2
3861      */
3862     public boolean isIdentity() {
3863         return (state == APPLY_IDENTITY || (getType() == TYPE_IDENTITY));
3864     }
3865 
3866     /**
3867      * Returns a copy of this <code>AffineTransform</code> object.
3868      * @return an <code>Object</code> that is a copy of this
3869      * <code>AffineTransform</code> object.
3870      * @since 1.2
3871      */
3872     public Object clone() {
3873         try {
3874             return super.clone();
3875         } catch (CloneNotSupportedException e) {
3876             // this shouldn't happen, since we are Cloneable
3877             throw new InternalError(e);
3878         }
3879     }
3880 
3881     /**
3882      * Returns the hashcode for this transform.
3883      * @return      a hash code for this transform.
3884      * @since 1.2
3885      */
3886     public int hashCode() {
3887         long bits = Double.doubleToLongBits(m00);
3888         bits = bits * 31 + Double.doubleToLongBits(m01);
3889         bits = bits * 31 + Double.doubleToLongBits(m02);
3890         bits = bits * 31 + Double.doubleToLongBits(m10);
3891         bits = bits * 31 + Double.doubleToLongBits(m11);
3892         bits = bits * 31 + Double.doubleToLongBits(m12);
3893         return (((int) bits) ^ ((int) (bits >> 32)));
3894     }
3895 
3896     /**
3897      * Returns <code>true</code> if this <code>AffineTransform</code>
3898      * represents the same affine coordinate transform as the specified
3899      * argument.
3900      * @param obj the <code>Object</code> to test for equality with this
3901      * <code>AffineTransform</code>
3902      * @return <code>true</code> if <code>obj</code> equals this
3903      * <code>AffineTransform</code> object; <code>false</code> otherwise.
3904      * @since 1.2
3905      */
3906     public boolean equals(Object obj) {
3907         if (!(obj instanceof AffineTransform)) {
3908             return false;
3909         }
3910 
3911         AffineTransform a = (AffineTransform)obj;
3912 
3913         return ((m00 == a.m00) && (m01 == a.m01) && (m02 == a.m02) &&
3914                 (m10 == a.m10) && (m11 == a.m11) && (m12 == a.m12));
3915     }
3916 
3917     /* Serialization support.  A readObject method is neccessary because
3918      * the state field is part of the implementation of this particular
3919      * AffineTransform and not part of the public specification.  The
3920      * state variable's value needs to be recalculated on the fly by the
3921      * readObject method as it is in the 6-argument matrix constructor.
3922      */
3923 


  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.beans.ConstructorProperties;
  30 
  31 /**
  32  * The {@code AffineTransform} class represents a 2D affine transform
  33  * that performs a linear mapping from 2D coordinates to other 2D
  34  * coordinates that preserves the "straightness" and
  35  * "parallelness" of lines.  Affine transformations can be constructed
  36  * using sequences of translations, scales, flips, rotations, and shears.
  37  * <p>
  38  * Such a coordinate transformation can be represented by a 3 row by
  39  * 3 column matrix with an implied last row of [ 0 0 1 ].  This matrix
  40  * transforms source coordinates {@code (x,y)} into
  41  * destination coordinates {@code (x',y')} by considering
  42  * them to be a column vector and multiplying the coordinate vector
  43  * by the matrix according to the following process:
  44  * <pre>
  45  *      [ x']   [  m00  m01  m02  ] [ x ]   [ m00x + m01y + m02 ]
  46  *      [ y'] = [  m10  m11  m12  ] [ y ] = [ m10x + m11y + m12 ]
  47  *      [ 1 ]   [   0    0    1   ] [ 1 ]   [         1         ]
  48  * </pre>
  49  * <h3><a name="quadrantapproximation">Handling 90-Degree Rotations</a></h3>
  50  * <p>
  51  * In some variations of the {@code rotate} methods in the
  52  * {@code AffineTransform} class, a double-precision argument
  53  * specifies the angle of rotation in radians.
  54  * These methods have special handling for rotations of approximately
  55  * 90 degrees (including multiples such as 180, 270, and 360 degrees),
  56  * so that the common case of quadrant rotation is handled more
  57  * efficiently.
  58  * This special handling can cause angles very close to multiples of
  59  * 90 degrees to be treated as if they were exact multiples of
  60  * 90 degrees.
  61  * For small multiples of 90 degrees the range of angles treated
  62  * as a quadrant rotation is approximately 0.00000121 degrees wide.
  63  * This section explains why such special care is needed and how
  64  * it is implemented.
  65  * <p>
  66  * Since 90 degrees is represented as {@code PI/2} in radians,
  67  * and since PI is a transcendental (and therefore irrational) number,
  68  * it is not possible to exactly represent a multiple of 90 degrees as
  69  * an exact double precision value measured in radians.
  70  * As a result it is theoretically impossible to describe quadrant
  71  * rotations (90, 180, 270 or 360 degrees) using these values.
  72  * Double precision floating point values can get very close to
  73  * non-zero multiples of {@code PI/2} but never close enough
  74  * for the sine or cosine to be exactly 0.0, 1.0 or -1.0.
  75  * The implementations of {@code Math.sin()} and
  76  * {@code Math.cos()} correspondingly never return 0.0
  77  * for any case other than {@code Math.sin(0.0)}.
  78  * These same implementations do, however, return exactly 1.0 and
  79  * -1.0 for some range of numbers around each multiple of 90
  80  * degrees since the correct answer is so close to 1.0 or -1.0 that
  81  * the double precision significand cannot represent the difference
  82  * as accurately as it can for numbers that are near 0.0.
  83  * <p>
  84  * The net result of these issues is that if the
  85  * {@code Math.sin()} and {@code Math.cos()} methods
  86  * are used to directly generate the values for the matrix modifications
  87  * during these radian-based rotation operations then the resulting
  88  * transform is never strictly classifiable as a quadrant rotation
  89  * even for a simple case like {@code rotate(Math.PI/2.0)},
  90  * due to minor variations in the matrix caused by the non-0.0 values
  91  * obtained for the sine and cosine.
  92  * If these transforms are not classified as quadrant rotations then
  93  * subsequent code which attempts to optimize further operations based
  94  * upon the type of the transform will be relegated to its most general
  95  * implementation.
  96  * <p>
  97  * Because quadrant rotations are fairly common,
  98  * this class should handle these cases reasonably quickly, both in
  99  * applying the rotations to the transform and in applying the resulting
 100  * transform to the coordinates.
 101  * To facilitate this optimal handling, the methods which take an angle
 102  * of rotation measured in radians attempt to detect angles that are
 103  * intended to be quadrant rotations and treat them as such.
 104  * These methods therefore treat an angle <em>theta</em> as a quadrant
 105  * rotation if either <code>Math.sin(<em>theta</em>)</code> or
 106  * <code>Math.cos(<em>theta</em>)</code> returns exactly 1.0 or -1.0.
 107  * As a rule of thumb, this property holds true for a range of
 108  * approximately 0.0000000211 radians (or 0.00000121 degrees) around
 109  * small multiples of {@code Math.PI/2.0}.
 110  *
 111  * @author Jim Graham
 112  * @since 1.2
 113  */
 114 public class AffineTransform implements Cloneable, java.io.Serializable {
 115 
 116     /*
 117      * This constant is only useful for the cached type field.
 118      * It indicates that the type has been decached and must be recalculated.
 119      */
 120     private static final int TYPE_UNKNOWN = -1;
 121 
 122     /**
 123      * This constant indicates that the transform defined by this object
 124      * is an identity transform.
 125      * An identity transform is one in which the output coordinates are
 126      * always the same as the input coordinates.
 127      * If this transform is anything other than the identity transform,
 128      * the type will either be the constant GENERAL_TRANSFORM or a
 129      * combination of the appropriate flag bits for the various coordinate


 450      * @see #TYPE_UNKNOWN
 451      * @see #getType
 452      */
 453     private transient int type;
 454 
 455     private AffineTransform(double m00, double m10,
 456                             double m01, double m11,
 457                             double m02, double m12,
 458                             int state) {
 459         this.m00 = m00;
 460         this.m10 = m10;
 461         this.m01 = m01;
 462         this.m11 = m11;
 463         this.m02 = m02;
 464         this.m12 = m12;
 465         this.state = state;
 466         this.type = TYPE_UNKNOWN;
 467     }
 468 
 469     /**
 470      * Constructs a new {@code AffineTransform} representing the
 471      * Identity transformation.
 472      * @since 1.2
 473      */
 474     public AffineTransform() {
 475         m00 = m11 = 1.0;
 476         // m01 = m10 = m02 = m12 = 0.0;         /* Not needed. */
 477         // state = APPLY_IDENTITY;              /* Not needed. */
 478         // type = TYPE_IDENTITY;                /* Not needed. */
 479     }
 480 
 481     /**
 482      * Constructs a new {@code AffineTransform} that is a copy of
 483      * the specified {@code AffineTransform} object.
 484      * @param Tx the {@code AffineTransform} object to copy
 485      * @since 1.2
 486      */
 487     public AffineTransform(AffineTransform Tx) {
 488         this.m00 = Tx.m00;
 489         this.m10 = Tx.m10;
 490         this.m01 = Tx.m01;
 491         this.m11 = Tx.m11;
 492         this.m02 = Tx.m02;
 493         this.m12 = Tx.m12;
 494         this.state = Tx.state;
 495         this.type = Tx.type;
 496     }
 497 
 498     /**
 499      * Constructs a new {@code AffineTransform} from 6 floating point
 500      * values representing the 6 specifiable entries of the 3x3
 501      * transformation matrix.
 502      *
 503      * @param m00 the X coordinate scaling element of the 3x3 matrix
 504      * @param m10 the Y coordinate shearing element of the 3x3 matrix
 505      * @param m01 the X coordinate shearing element of the 3x3 matrix
 506      * @param m11 the Y coordinate scaling element of the 3x3 matrix
 507      * @param m02 the X coordinate translation element of the 3x3 matrix
 508      * @param m12 the Y coordinate translation element of the 3x3 matrix
 509      * @since 1.2
 510      */
 511     @ConstructorProperties({ "scaleX", "shearY", "shearX", "scaleY", "translateX", "translateY" })
 512     public AffineTransform(float m00, float m10,
 513                            float m01, float m11,
 514                            float m02, float m12) {
 515         this.m00 = m00;
 516         this.m10 = m10;
 517         this.m01 = m01;
 518         this.m11 = m11;
 519         this.m02 = m02;
 520         this.m12 = m12;
 521         updateState();
 522     }
 523 
 524     /**
 525      * Constructs a new {@code AffineTransform} from an array of
 526      * floating point values representing either the 4 non-translation
 527      * entries or the 6 specifiable entries of the 3x3 transformation
 528      * matrix.  The values are retrieved from the array as
 529      * {&nbsp;m00&nbsp;m10&nbsp;m01&nbsp;m11&nbsp;[m02&nbsp;m12]}.
 530      * @param flatmatrix the float array containing the values to be set
 531      * in the new {@code AffineTransform} object. The length of the
 532      * array is assumed to be at least 4. If the length of the array is
 533      * less than 6, only the first 4 values are taken. If the length of
 534      * the array is greater than 6, the first 6 values are taken.
 535      * @since 1.2
 536      */
 537     public AffineTransform(float[] flatmatrix) {
 538         m00 = flatmatrix[0];
 539         m10 = flatmatrix[1];
 540         m01 = flatmatrix[2];
 541         m11 = flatmatrix[3];
 542         if (flatmatrix.length > 5) {
 543             m02 = flatmatrix[4];
 544             m12 = flatmatrix[5];
 545         }
 546         updateState();
 547     }
 548 
 549     /**
 550      * Constructs a new {@code AffineTransform} from 6 double
 551      * precision values representing the 6 specifiable entries of the 3x3
 552      * transformation matrix.
 553      *
 554      * @param m00 the X coordinate scaling element of the 3x3 matrix
 555      * @param m10 the Y coordinate shearing element of the 3x3 matrix
 556      * @param m01 the X coordinate shearing element of the 3x3 matrix
 557      * @param m11 the Y coordinate scaling element of the 3x3 matrix
 558      * @param m02 the X coordinate translation element of the 3x3 matrix
 559      * @param m12 the Y coordinate translation element of the 3x3 matrix
 560      * @since 1.2
 561      */
 562     public AffineTransform(double m00, double m10,
 563                            double m01, double m11,
 564                            double m02, double m12) {
 565         this.m00 = m00;
 566         this.m10 = m10;
 567         this.m01 = m01;
 568         this.m11 = m11;
 569         this.m02 = m02;
 570         this.m12 = m12;
 571         updateState();
 572     }
 573 
 574     /**
 575      * Constructs a new {@code AffineTransform} from an array of
 576      * double precision values representing either the 4 non-translation
 577      * entries or the 6 specifiable entries of the 3x3 transformation
 578      * matrix. The values are retrieved from the array as
 579      * {&nbsp;m00&nbsp;m10&nbsp;m01&nbsp;m11&nbsp;[m02&nbsp;m12]}.
 580      * @param flatmatrix the double array containing the values to be set
 581      * in the new {@code AffineTransform} object. The length of the
 582      * array is assumed to be at least 4. If the length of the array is
 583      * less than 6, only the first 4 values are taken. If the length of
 584      * the array is greater than 6, the first 6 values are taken.
 585      * @since 1.2
 586      */
 587     public AffineTransform(double[] flatmatrix) {
 588         m00 = flatmatrix[0];
 589         m10 = flatmatrix[1];
 590         m01 = flatmatrix[2];
 591         m11 = flatmatrix[3];
 592         if (flatmatrix.length > 5) {
 593             m02 = flatmatrix[4];
 594             m12 = flatmatrix[5];
 595         }
 596         updateState();
 597     }
 598 
 599     /**
 600      * Returns a transform representing a translation transformation.
 601      * The matrix representing the returned transform is:
 602      * <pre>
 603      *          [   1    0    tx  ]
 604      *          [   0    1    ty  ]
 605      *          [   0    0    1   ]
 606      * </pre>
 607      * @param tx the distance by which coordinates are translated in the
 608      * X axis direction
 609      * @param ty the distance by which coordinates are translated in the
 610      * Y axis direction
 611      * @return an {@code AffineTransform} object that represents a
 612      *  translation transformation, created with the specified vector.
 613      * @since 1.2
 614      */
 615     public static AffineTransform getTranslateInstance(double tx, double ty) {
 616         AffineTransform Tx = new AffineTransform();
 617         Tx.setToTranslation(tx, ty);
 618         return Tx;
 619     }
 620 
 621     /**
 622      * Returns a transform representing a rotation transformation.
 623      * The matrix representing the returned transform is:
 624      * <pre>
 625      *          [   cos(theta)    -sin(theta)    0   ]
 626      *          [   sin(theta)     cos(theta)    0   ]
 627      *          [       0              0         1   ]
 628      * </pre>
 629      * Rotating by a positive angle theta rotates points on the positive
 630      * X axis toward the positive Y axis.
 631      * Note also the discussion of
 632      * <a href="#quadrantapproximation">Handling 90-Degree Rotations</a>
 633      * above.
 634      * @param theta the angle of rotation measured in radians
 635      * @return an {@code AffineTransform} object that is a rotation
 636      *  transformation, created with the specified angle of rotation.
 637      * @since 1.2
 638      */
 639     public static AffineTransform getRotateInstance(double theta) {
 640         AffineTransform Tx = new AffineTransform();
 641         Tx.setToRotation(theta);
 642         return Tx;
 643     }
 644 
 645     /**
 646      * Returns a transform that rotates coordinates around an anchor point.
 647      * This operation is equivalent to translating the coordinates so
 648      * that the anchor point is at the origin (S1), then rotating them
 649      * about the new origin (S2), and finally translating so that the
 650      * intermediate origin is restored to the coordinates of the original
 651      * anchor point (S3).
 652      * <p>
 653      * This operation is equivalent to the following sequence of calls:
 654      * <pre>
 655      *     AffineTransform Tx = new AffineTransform();
 656      *     Tx.translate(anchorx, anchory);    // S3: final translation
 657      *     Tx.rotate(theta);                  // S2: rotate around anchor
 658      *     Tx.translate(-anchorx, -anchory);  // S1: translate anchor to origin
 659      * </pre>
 660      * The matrix representing the returned transform is:
 661      * <pre>
 662      *          [   cos(theta)    -sin(theta)    x-x*cos+y*sin  ]
 663      *          [   sin(theta)     cos(theta)    y-x*sin-y*cos  ]
 664      *          [       0              0               1        ]
 665      * </pre>
 666      * Rotating by a positive angle theta rotates points on the positive
 667      * X axis toward the positive Y axis.
 668      * Note also the discussion of
 669      * <a href="#quadrantapproximation">Handling 90-Degree Rotations</a>
 670      * above.
 671      *
 672      * @param theta the angle of rotation measured in radians
 673      * @param anchorx the X coordinate of the rotation anchor point
 674      * @param anchory the Y coordinate of the rotation anchor point
 675      * @return an {@code AffineTransform} object that rotates
 676      *  coordinates around the specified point by the specified angle of
 677      *  rotation.
 678      * @since 1.2
 679      */
 680     public static AffineTransform getRotateInstance(double theta,
 681                                                     double anchorx,
 682                                                     double anchory)
 683     {
 684         AffineTransform Tx = new AffineTransform();
 685         Tx.setToRotation(theta, anchorx, anchory);
 686         return Tx;
 687     }
 688 
 689     /**
 690      * Returns a transform that rotates coordinates according to
 691      * a rotation vector.
 692      * All coordinates rotate about the origin by the same amount.
 693      * The amount of rotation is such that coordinates along the former
 694      * positive X axis will subsequently align with the vector pointing
 695      * from the origin to the specified vector coordinates.
 696      * If both {@code vecx} and {@code vecy} are 0.0,
 697      * an identity transform is returned.
 698      * This operation is equivalent to calling:
 699      * <pre>
 700      *     AffineTransform.getRotateInstance(Math.atan2(vecy, vecx));
 701      * </pre>
 702      *
 703      * @param vecx the X coordinate of the rotation vector
 704      * @param vecy the Y coordinate of the rotation vector
 705      * @return an {@code AffineTransform} object that rotates
 706      *  coordinates according to the specified rotation vector.
 707      * @since 1.6
 708      */
 709     public static AffineTransform getRotateInstance(double vecx, double vecy) {
 710         AffineTransform Tx = new AffineTransform();
 711         Tx.setToRotation(vecx, vecy);
 712         return Tx;
 713     }
 714 
 715     /**
 716      * Returns a transform that rotates coordinates around an anchor
 717      * point according to a rotation vector.
 718      * All coordinates rotate about the specified anchor coordinates
 719      * by the same amount.
 720      * The amount of rotation is such that coordinates along the former
 721      * positive X axis will subsequently align with the vector pointing
 722      * from the origin to the specified vector coordinates.
 723      * If both {@code vecx} and {@code vecy} are 0.0,
 724      * an identity transform is returned.
 725      * This operation is equivalent to calling:
 726      * <pre>
 727      *     AffineTransform.getRotateInstance(Math.atan2(vecy, vecx),
 728      *                                       anchorx, anchory);
 729      * </pre>
 730      *
 731      * @param vecx the X coordinate of the rotation vector
 732      * @param vecy the Y coordinate of the rotation vector
 733      * @param anchorx the X coordinate of the rotation anchor point
 734      * @param anchory the Y coordinate of the rotation anchor point
 735      * @return an {@code AffineTransform} object that rotates
 736      *  coordinates around the specified point according to the
 737      *  specified rotation vector.
 738      * @since 1.6
 739      */
 740     public static AffineTransform getRotateInstance(double vecx,
 741                                                     double vecy,
 742                                                     double anchorx,
 743                                                     double anchory)
 744     {
 745         AffineTransform Tx = new AffineTransform();
 746         Tx.setToRotation(vecx, vecy, anchorx, anchory);
 747         return Tx;
 748     }
 749 
 750     /**
 751      * Returns a transform that rotates coordinates by the specified
 752      * number of quadrants.
 753      * This operation is equivalent to calling:
 754      * <pre>
 755      *     AffineTransform.getRotateInstance(numquadrants * Math.PI / 2.0);
 756      * </pre>
 757      * Rotating by a positive number of quadrants rotates points on
 758      * the positive X axis toward the positive Y axis.
 759      * @param numquadrants the number of 90 degree arcs to rotate by
 760      * @return an {@code AffineTransform} object that rotates
 761      *  coordinates by the specified number of quadrants.
 762      * @since 1.6
 763      */
 764     public static AffineTransform getQuadrantRotateInstance(int numquadrants) {
 765         AffineTransform Tx = new AffineTransform();
 766         Tx.setToQuadrantRotation(numquadrants);
 767         return Tx;
 768     }
 769 
 770     /**
 771      * Returns a transform that rotates coordinates by the specified
 772      * number of quadrants around the specified anchor point.
 773      * This operation is equivalent to calling:
 774      * <pre>
 775      *     AffineTransform.getRotateInstance(numquadrants * Math.PI / 2.0,
 776      *                                       anchorx, anchory);
 777      * </pre>
 778      * Rotating by a positive number of quadrants rotates points on
 779      * the positive X axis toward the positive Y axis.
 780      *
 781      * @param numquadrants the number of 90 degree arcs to rotate by
 782      * @param anchorx the X coordinate of the rotation anchor point
 783      * @param anchory the Y coordinate of the rotation anchor point
 784      * @return an {@code AffineTransform} object that rotates
 785      *  coordinates by the specified number of quadrants around the
 786      *  specified anchor point.
 787      * @since 1.6
 788      */
 789     public static AffineTransform getQuadrantRotateInstance(int numquadrants,
 790                                                             double anchorx,
 791                                                             double anchory)
 792     {
 793         AffineTransform Tx = new AffineTransform();
 794         Tx.setToQuadrantRotation(numquadrants, anchorx, anchory);
 795         return Tx;
 796     }
 797 
 798     /**
 799      * Returns a transform representing a scaling transformation.
 800      * The matrix representing the returned transform is:
 801      * <pre>
 802      *          [   sx   0    0   ]
 803      *          [   0    sy   0   ]
 804      *          [   0    0    1   ]
 805      * </pre>
 806      * @param sx the factor by which coordinates are scaled along the
 807      * X axis direction
 808      * @param sy the factor by which coordinates are scaled along the
 809      * Y axis direction
 810      * @return an {@code AffineTransform} object that scales
 811      *  coordinates by the specified factors.
 812      * @since 1.2
 813      */
 814     public static AffineTransform getScaleInstance(double sx, double sy) {
 815         AffineTransform Tx = new AffineTransform();
 816         Tx.setToScale(sx, sy);
 817         return Tx;
 818     }
 819 
 820     /**
 821      * Returns a transform representing a shearing transformation.
 822      * The matrix representing the returned transform is:
 823      * <pre>
 824      *          [   1   shx   0   ]
 825      *          [  shy   1    0   ]
 826      *          [   0    0    1   ]
 827      * </pre>
 828      * @param shx the multiplier by which coordinates are shifted in the
 829      * direction of the positive X axis as a factor of their Y coordinate
 830      * @param shy the multiplier by which coordinates are shifted in the
 831      * direction of the positive Y axis as a factor of their X coordinate
 832      * @return an {@code AffineTransform} object that shears
 833      *  coordinates by the specified multipliers.
 834      * @since 1.2
 835      */
 836     public static AffineTransform getShearInstance(double shx, double shy) {
 837         AffineTransform Tx = new AffineTransform();
 838         Tx.setToShear(shx, shy);
 839         return Tx;
 840     }
 841 
 842     /**
 843      * Retrieves the flag bits describing the conversion properties of
 844      * this transform.
 845      * The return value is either one of the constants TYPE_IDENTITY
 846      * or TYPE_GENERAL_TRANSFORM, or a combination of the
 847      * appropriate flag bits.
 848      * A valid combination of flag bits is an exclusive OR operation
 849      * that can combine
 850      * the TYPE_TRANSLATION flag bit
 851      * in addition to either of the
 852      * TYPE_UNIFORM_SCALE or TYPE_GENERAL_SCALE flag bits


 998     }
 999 
1000     /**
1001      * Returns the determinant of the matrix representation of the transform.
1002      * The determinant is useful both to determine if the transform can
1003      * be inverted and to get a single value representing the
1004      * combined X and Y scaling of the transform.
1005      * <p>
1006      * If the determinant is non-zero, then this transform is
1007      * invertible and the various methods that depend on the inverse
1008      * transform do not need to throw a
1009      * {@link NoninvertibleTransformException}.
1010      * If the determinant is zero then this transform can not be
1011      * inverted since the transform maps all input coordinates onto
1012      * a line or a point.
1013      * If the determinant is near enough to zero then inverse transform
1014      * operations might not carry enough precision to produce meaningful
1015      * results.
1016      * <p>
1017      * If this transform represents a uniform scale, as indicated by
1018      * the {@code getType} method then the determinant also
1019      * represents the square of the uniform scale factor by which all of
1020      * the points are expanded from or contracted towards the origin.
1021      * If this transform represents a non-uniform scale or more general
1022      * transform then the determinant is not likely to represent a
1023      * value useful for any purpose other than determining if inverse
1024      * transforms are possible.
1025      * <p>
1026      * Mathematically, the determinant is calculated using the formula:
1027      * <pre>
1028      *          |  m00  m01  m02  |
1029      *          |  m10  m11  m12  |  =  m00 * m11 - m01 * m10
1030      *          |   0    0    1   |
1031      * </pre>
1032      *
1033      * @return the determinant of the matrix used to transform the
1034      * coordinates.
1035      * @see #getType
1036      * @see #createInverse
1037      * @see #inverseTransform
1038      * @see #TYPE_UNIFORM_SCALE


1217      */
1218     public double getTranslateX() {
1219         return m02;
1220     }
1221 
1222     /**
1223      * Returns the Y coordinate of the translation element (m12) of the
1224      * 3x3 affine transformation matrix.
1225      * @return a double value that is the Y coordinate of the translation
1226      *  element of the affine transformation matrix.
1227      * @see #getMatrix
1228      * @since 1.2
1229      */
1230     public double getTranslateY() {
1231         return m12;
1232     }
1233 
1234     /**
1235      * Concatenates this transform with a translation transformation.
1236      * This is equivalent to calling concatenate(T), where T is an
1237      * {@code AffineTransform} represented by the following matrix:
1238      * <pre>
1239      *          [   1    0    tx  ]
1240      *          [   0    1    ty  ]
1241      *          [   0    0    1   ]
1242      * </pre>
1243      * @param tx the distance by which coordinates are translated in the
1244      * X axis direction
1245      * @param ty the distance by which coordinates are translated in the
1246      * Y axis direction
1247      * @since 1.2
1248      */
1249     public void translate(double tx, double ty) {
1250         switch (state) {
1251         default:
1252             stateError();
1253             /* NOTREACHED */
1254             return;
1255         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
1256             m02 = tx * m00 + ty * m01 + m02;
1257             m12 = tx * m10 + ty * m11 + m12;


1377     private final void rotate270() {
1378         double M0 = m00;
1379         m00 = -m01;
1380         m01 = M0;
1381         M0 = m10;
1382         m10 = -m11;
1383         m11 = M0;
1384         int state = rot90conversion[this.state];
1385         if ((state & (APPLY_SHEAR | APPLY_SCALE)) == APPLY_SCALE &&
1386             m00 == 1.0 && m11 == 1.0)
1387         {
1388             state -= APPLY_SCALE;
1389         }
1390         this.state = state;
1391         type = TYPE_UNKNOWN;
1392     }
1393 
1394     /**
1395      * Concatenates this transform with a rotation transformation.
1396      * This is equivalent to calling concatenate(R), where R is an
1397      * {@code AffineTransform} represented by the following matrix:
1398      * <pre>
1399      *          [   cos(theta)    -sin(theta)    0   ]
1400      *          [   sin(theta)     cos(theta)    0   ]
1401      *          [       0              0         1   ]
1402      * </pre>
1403      * Rotating by a positive angle theta rotates points on the positive
1404      * X axis toward the positive Y axis.
1405      * Note also the discussion of
1406      * <a href="#quadrantapproximation">Handling 90-Degree Rotations</a>
1407      * above.
1408      * @param theta the angle of rotation measured in radians
1409      * @since 1.2
1410      */
1411     public void rotate(double theta) {
1412         double sin = Math.sin(theta);
1413         if (sin == 1.0) {
1414             rotate90();
1415         } else if (sin == -1.0) {
1416             rotate270();
1417         } else {


1456      *
1457      * @param theta the angle of rotation measured in radians
1458      * @param anchorx the X coordinate of the rotation anchor point
1459      * @param anchory the Y coordinate of the rotation anchor point
1460      * @since 1.2
1461      */
1462     public void rotate(double theta, double anchorx, double anchory) {
1463         // REMIND: Simple for now - optimize later
1464         translate(anchorx, anchory);
1465         rotate(theta);
1466         translate(-anchorx, -anchory);
1467     }
1468 
1469     /**
1470      * Concatenates this transform with a transform that rotates
1471      * coordinates according to a rotation vector.
1472      * All coordinates rotate about the origin by the same amount.
1473      * The amount of rotation is such that coordinates along the former
1474      * positive X axis will subsequently align with the vector pointing
1475      * from the origin to the specified vector coordinates.
1476      * If both {@code vecx} and {@code vecy} are 0.0,
1477      * no additional rotation is added to this transform.
1478      * This operation is equivalent to calling:
1479      * <pre>
1480      *          rotate(Math.atan2(vecy, vecx));
1481      * </pre>
1482      *
1483      * @param vecx the X coordinate of the rotation vector
1484      * @param vecy the Y coordinate of the rotation vector
1485      * @since 1.6
1486      */
1487     public void rotate(double vecx, double vecy) {
1488         if (vecy == 0.0) {
1489             if (vecx < 0.0) {
1490                 rotate180();
1491             }
1492             // If vecx > 0.0 - no rotation
1493             // If vecx == 0.0 - undefined rotation - treat as no rotation
1494         } else if (vecx == 0.0) {
1495             if (vecy > 0.0) {
1496                 rotate90();


1506             M1 = m01;
1507             m00 =  cos * M0 + sin * M1;
1508             m01 = -sin * M0 + cos * M1;
1509             M0 = m10;
1510             M1 = m11;
1511             m10 =  cos * M0 + sin * M1;
1512             m11 = -sin * M0 + cos * M1;
1513             updateState();
1514         }
1515     }
1516 
1517     /**
1518      * Concatenates this transform with a transform that rotates
1519      * coordinates around an anchor point according to a rotation
1520      * vector.
1521      * All coordinates rotate about the specified anchor coordinates
1522      * by the same amount.
1523      * The amount of rotation is such that coordinates along the former
1524      * positive X axis will subsequently align with the vector pointing
1525      * from the origin to the specified vector coordinates.
1526      * If both {@code vecx} and {@code vecy} are 0.0,
1527      * the transform is not modified in any way.
1528      * This method is equivalent to calling:
1529      * <pre>
1530      *     rotate(Math.atan2(vecy, vecx), anchorx, anchory);
1531      * </pre>
1532      *
1533      * @param vecx the X coordinate of the rotation vector
1534      * @param vecy the Y coordinate of the rotation vector
1535      * @param anchorx the X coordinate of the rotation anchor point
1536      * @param anchory the Y coordinate of the rotation anchor point
1537      * @since 1.6
1538      */
1539     public void rotate(double vecx, double vecy,
1540                        double anchorx, double anchory)
1541     {
1542         // REMIND: Simple for now - optimize later
1543         translate(anchorx, anchory);
1544         rotate(vecx, vecy);
1545         translate(-anchorx, -anchory);
1546     }


1604             m02 += anchorx * (m00 + m00) + anchory * (m01 + m01);
1605             m12 += anchorx * (m10 + m10) + anchory * (m11 + m11);
1606             rotate180();
1607             break;
1608         case 3:
1609             m02 += anchorx * (m00 + m01) + anchory * (m01 - m00);
1610             m12 += anchorx * (m10 + m11) + anchory * (m11 - m10);
1611             rotate270();
1612             break;
1613         }
1614         if (m02 == 0.0 && m12 == 0.0) {
1615             state &= ~APPLY_TRANSLATE;
1616         } else {
1617             state |= APPLY_TRANSLATE;
1618         }
1619     }
1620 
1621     /**
1622      * Concatenates this transform with a scaling transformation.
1623      * This is equivalent to calling concatenate(S), where S is an
1624      * {@code AffineTransform} represented by the following matrix:
1625      * <pre>
1626      *          [   sx   0    0   ]
1627      *          [   0    sy   0   ]
1628      *          [   0    0    1   ]
1629      * </pre>
1630      * @param sx the factor by which coordinates are scaled along the
1631      * X axis direction
1632      * @param sy the factor by which coordinates are scaled along the
1633      * Y axis direction
1634      * @since 1.2
1635      */
1636     @SuppressWarnings("fallthrough")
1637     public void scale(double sx, double sy) {
1638         int state = this.state;
1639         switch (state) {
1640         default:
1641             stateError();
1642             /* NOTREACHED */
1643         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
1644         case (APPLY_SHEAR | APPLY_SCALE):


1673                              : TYPE_TRANSLATION);
1674             } else {
1675                 this.type = TYPE_UNKNOWN;
1676             }
1677             return;
1678         case (APPLY_TRANSLATE):
1679         case (APPLY_IDENTITY):
1680             m00 = sx;
1681             m11 = sy;
1682             if (sx != 1.0 || sy != 1.0) {
1683                 this.state = state | APPLY_SCALE;
1684                 this.type = TYPE_UNKNOWN;
1685             }
1686             return;
1687         }
1688     }
1689 
1690     /**
1691      * Concatenates this transform with a shearing transformation.
1692      * This is equivalent to calling concatenate(SH), where SH is an
1693      * {@code AffineTransform} represented by the following matrix:
1694      * <pre>
1695      *          [   1   shx   0   ]
1696      *          [  shy   1    0   ]
1697      *          [   0    0    1   ]
1698      * </pre>
1699      * @param shx the multiplier by which coordinates are shifted in the
1700      * direction of the positive X axis as a factor of their Y coordinate
1701      * @param shy the multiplier by which coordinates are shifted in the
1702      * direction of the positive Y axis as a factor of their X coordinate
1703      * @since 1.2
1704      */
1705     public void shear(double shx, double shy) {
1706         int state = this.state;
1707         switch (state) {
1708         default:
1709             stateError();
1710             /* NOTREACHED */
1711             return;
1712         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
1713         case (APPLY_SHEAR | APPLY_SCALE):


1873      */
1874     public void setToRotation(double theta, double anchorx, double anchory) {
1875         setToRotation(theta);
1876         double sin = m10;
1877         double oneMinusCos = 1.0 - m00;
1878         m02 = anchorx * oneMinusCos + anchory * sin;
1879         m12 = anchory * oneMinusCos - anchorx * sin;
1880         if (m02 != 0.0 || m12 != 0.0) {
1881             state |= APPLY_TRANSLATE;
1882             type |= TYPE_TRANSLATION;
1883         }
1884     }
1885 
1886     /**
1887      * Sets this transform to a rotation transformation that rotates
1888      * coordinates according to a rotation vector.
1889      * All coordinates rotate about the origin by the same amount.
1890      * The amount of rotation is such that coordinates along the former
1891      * positive X axis will subsequently align with the vector pointing
1892      * from the origin to the specified vector coordinates.
1893      * If both {@code vecx} and {@code vecy} are 0.0,
1894      * the transform is set to an identity transform.
1895      * This operation is equivalent to calling:
1896      * <pre>
1897      *     setToRotation(Math.atan2(vecy, vecx));
1898      * </pre>
1899      *
1900      * @param vecx the X coordinate of the rotation vector
1901      * @param vecy the Y coordinate of the rotation vector
1902      * @since 1.6
1903      */
1904     public void setToRotation(double vecx, double vecy) {
1905         double sin, cos;
1906         if (vecy == 0) {
1907             sin = 0.0;
1908             if (vecx < 0.0) {
1909                 cos = -1.0;
1910                 state = APPLY_SCALE;
1911                 type = TYPE_QUADRANT_ROTATION;
1912             } else {
1913                 cos = 1.0;


1926             state = APPLY_SHEAR | APPLY_SCALE;
1927             type = TYPE_GENERAL_ROTATION;
1928         }
1929         m00 =  cos;
1930         m10 =  sin;
1931         m01 = -sin;
1932         m11 =  cos;
1933         m02 =  0.0;
1934         m12 =  0.0;
1935     }
1936 
1937     /**
1938      * Sets this transform to a rotation transformation that rotates
1939      * coordinates around an anchor point according to a rotation
1940      * vector.
1941      * All coordinates rotate about the specified anchor coordinates
1942      * by the same amount.
1943      * The amount of rotation is such that coordinates along the former
1944      * positive X axis will subsequently align with the vector pointing
1945      * from the origin to the specified vector coordinates.
1946      * If both {@code vecx} and {@code vecy} are 0.0,
1947      * the transform is set to an identity transform.
1948      * This operation is equivalent to calling:
1949      * <pre>
1950      *     setToTranslation(Math.atan2(vecy, vecx), anchorx, anchory);
1951      * </pre>
1952      *
1953      * @param vecx the X coordinate of the rotation vector
1954      * @param vecy the Y coordinate of the rotation vector
1955      * @param anchorx the X coordinate of the rotation anchor point
1956      * @param anchory the Y coordinate of the rotation anchor point
1957      * @since 1.6
1958      */
1959     public void setToRotation(double vecx, double vecy,
1960                               double anchorx, double anchory)
1961     {
1962         setToRotation(vecx, vecy);
1963         double sin = m10;
1964         double oneMinusCos = 1.0 - m00;
1965         m02 = anchorx * oneMinusCos + anchory * sin;
1966         m12 = anchory * oneMinusCos - anchorx * sin;


2150      * @since 1.2
2151      */
2152     public void setToShear(double shx, double shy) {
2153         m00 = 1.0;
2154         m01 = shx;
2155         m10 = shy;
2156         m11 = 1.0;
2157         m02 = 0.0;
2158         m12 = 0.0;
2159         if (shx != 0.0 || shy != 0.0) {
2160             state = (APPLY_SHEAR | APPLY_SCALE);
2161             type = TYPE_UNKNOWN;
2162         } else {
2163             state = APPLY_IDENTITY;
2164             type = TYPE_IDENTITY;
2165         }
2166     }
2167 
2168     /**
2169      * Sets this transform to a copy of the transform in the specified
2170      * {@code AffineTransform} object.
2171      * @param Tx the {@code AffineTransform} object from which to
2172      * copy the transform
2173      * @since 1.2
2174      */
2175     public void setTransform(AffineTransform Tx) {
2176         this.m00 = Tx.m00;
2177         this.m10 = Tx.m10;
2178         this.m01 = Tx.m01;
2179         this.m11 = Tx.m11;
2180         this.m02 = Tx.m02;
2181         this.m12 = Tx.m12;
2182         this.state = Tx.state;
2183         this.type = Tx.type;
2184     }
2185 
2186     /**
2187      * Sets this transform to the matrix specified by the 6
2188      * double precision values.
2189      *
2190      * @param m00 the X coordinate scaling element of the 3x3 matrix
2191      * @param m10 the Y coordinate shearing element of the 3x3 matrix
2192      * @param m01 the X coordinate shearing element of the 3x3 matrix
2193      * @param m11 the Y coordinate scaling element of the 3x3 matrix
2194      * @param m02 the X coordinate translation element of the 3x3 matrix
2195      * @param m12 the Y coordinate translation element of the 3x3 matrix
2196      * @since 1.2
2197      */
2198     public void setTransform(double m00, double m10,
2199                              double m01, double m11,
2200                              double m02, double m12) {
2201         this.m00 = m00;
2202         this.m10 = m10;
2203         this.m01 = m01;
2204         this.m11 = m11;
2205         this.m02 = m02;
2206         this.m12 = m12;
2207         updateState();
2208     }
2209 
2210     /**
2211      * Concatenates an {@code AffineTransform Tx} to
2212      * this {@code AffineTransform} Cx in the most commonly useful
2213      * way to provide a new user space
2214      * that is mapped to the former user space by {@code Tx}.
2215      * Cx is updated to perform the combined transformation.
2216      * Transforming a point p by the updated transform Cx' is
2217      * equivalent to first transforming p by {@code Tx} and then
2218      * transforming the result by the original transform Cx like this:
2219      * Cx'(p) = Cx(Tx(p))
2220      * In matrix notation, if this transform Cx is
2221      * represented by the matrix [this] and {@code Tx} is represented
2222      * by the matrix [Tx] then this method does the following:
2223      * <pre>
2224      *          [this] = [this] x [Tx]
2225      * </pre>
2226      * @param Tx the {@code AffineTransform} object to be
2227      * concatenated with this {@code AffineTransform} object.
2228      * @see #preConcatenate
2229      * @since 1.2
2230      */
2231     @SuppressWarnings("fallthrough")
2232     public void concatenate(AffineTransform Tx) {
2233         double M0, M1;
2234         double T00, T01, T10, T11;
2235         double T02, T12;
2236         int mystate = state;
2237         int txstate = Tx.state;
2238         switch ((txstate << HI_SHIFT) | mystate) {
2239 
2240             /* ---------- Tx == IDENTITY cases ---------- */
2241         case (HI_IDENTITY | APPLY_IDENTITY):
2242         case (HI_IDENTITY | APPLY_TRANSLATE):
2243         case (HI_IDENTITY | APPLY_SCALE):
2244         case (HI_IDENTITY | APPLY_SCALE | APPLY_TRANSLATE):
2245         case (HI_IDENTITY | APPLY_SHEAR):
2246         case (HI_IDENTITY | APPLY_SHEAR | APPLY_TRANSLATE):
2247         case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE):


2397             m11  = T11 * M0;
2398             m12 += T12 * M0;
2399             break;
2400 
2401         case (APPLY_TRANSLATE):
2402             m00  = T00;
2403             m01  = T01;
2404             m02 += T02;
2405 
2406             m10  = T10;
2407             m11  = T11;
2408             m12 += T12;
2409             state = txstate | APPLY_TRANSLATE;
2410             type = TYPE_UNKNOWN;
2411             return;
2412         }
2413         updateState();
2414     }
2415 
2416     /**
2417      * Concatenates an {@code AffineTransform Tx} to
2418      * this {@code AffineTransform} Cx
2419      * in a less commonly used way such that {@code Tx} modifies the
2420      * coordinate transformation relative to the absolute pixel
2421      * space rather than relative to the existing user space.
2422      * Cx is updated to perform the combined transformation.
2423      * Transforming a point p by the updated transform Cx' is
2424      * equivalent to first transforming p by the original transform
2425      * Cx and then transforming the result by
2426      * {@code Tx} like this:
2427      * Cx'(p) = Tx(Cx(p))
2428      * In matrix notation, if this transform Cx
2429      * is represented by the matrix [this] and {@code Tx} is
2430      * represented by the matrix [Tx] then this method does the
2431      * following:
2432      * <pre>
2433      *          [this] = [Tx] x [this]
2434      * </pre>
2435      * @param Tx the {@code AffineTransform} object to be
2436      * concatenated with this {@code AffineTransform} object.
2437      * @see #concatenate
2438      * @since 1.2
2439      */
2440     @SuppressWarnings("fallthrough")
2441     public void preConcatenate(AffineTransform Tx) {
2442         double M0, M1;
2443         double T00, T01, T10, T11;
2444         double T02, T12;
2445         int mystate = state;
2446         int txstate = Tx.state;
2447         switch ((txstate << HI_SHIFT) | mystate) {
2448         case (HI_IDENTITY | APPLY_IDENTITY):
2449         case (HI_IDENTITY | APPLY_TRANSLATE):
2450         case (HI_IDENTITY | APPLY_SCALE):
2451         case (HI_IDENTITY | APPLY_SCALE | APPLY_TRANSLATE):
2452         case (HI_IDENTITY | APPLY_SHEAR):
2453         case (HI_IDENTITY | APPLY_SHEAR | APPLY_TRANSLATE):
2454         case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE):
2455         case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2456             // Tx is IDENTITY...


2615 
2616             /* NOBREAK */
2617         case (APPLY_IDENTITY):
2618             m02 = T02;
2619             m12 = T12;
2620 
2621             m00 = T00;
2622             m10 = T10;
2623 
2624             m01 = T01;
2625             m11 = T11;
2626 
2627             state = mystate | txstate;
2628             type = TYPE_UNKNOWN;
2629             return;
2630         }
2631         updateState();
2632     }
2633 
2634     /**
2635      * Returns an {@code AffineTransform} object representing the
2636      * inverse transformation.
2637      * The inverse transform Tx' of this transform Tx
2638      * maps coordinates transformed by Tx back
2639      * to their original coordinates.
2640      * In other words, Tx'(Tx(p)) = p = Tx(Tx'(p)).
2641      * <p>
2642      * If this transform maps all coordinates onto a point or a line
2643      * then it will not have an inverse, since coordinates that do
2644      * not lie on the destination point or line will not have an inverse
2645      * mapping.
2646      * The {@code getDeterminant} method can be used to determine if this
2647      * transform has no inverse, in which case an exception will be
2648      * thrown if the {@code createInverse} method is called.
2649      * @return a new {@code AffineTransform} object representing the
2650      * inverse transformation.
2651      * @see #getDeterminant
2652      * @exception NoninvertibleTransformException
2653      * if the matrix cannot be inverted.
2654      * @since 1.2
2655      */
2656     public AffineTransform createInverse()
2657         throws NoninvertibleTransformException
2658     {
2659         double det;
2660         switch (state) {
2661         default:
2662             stateError();
2663             /* NOTREACHED */
2664             return null;
2665         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2666             det = m00 * m11 - m01 * m10;
2667             if (Math.abs(det) <= Double.MIN_VALUE) {
2668                 throw new NoninvertibleTransformException("Determinant is "+
2669                                                           det);


2723                                        -m02, -m12,
2724                                        (APPLY_TRANSLATE));
2725         case (APPLY_IDENTITY):
2726             return new AffineTransform();
2727         }
2728 
2729         /* NOTREACHED */
2730     }
2731 
2732     /**
2733      * Sets this transform to the inverse of itself.
2734      * The inverse transform Tx' of this transform Tx
2735      * maps coordinates transformed by Tx back
2736      * to their original coordinates.
2737      * In other words, Tx'(Tx(p)) = p = Tx(Tx'(p)).
2738      * <p>
2739      * If this transform maps all coordinates onto a point or a line
2740      * then it will not have an inverse, since coordinates that do
2741      * not lie on the destination point or line will not have an inverse
2742      * mapping.
2743      * The {@code getDeterminant} method can be used to determine if this
2744      * transform has no inverse, in which case an exception will be
2745      * thrown if the {@code invert} method is called.
2746      * @see #getDeterminant
2747      * @exception NoninvertibleTransformException
2748      * if the matrix cannot be inverted.
2749      * @since 1.6
2750      */
2751     public void invert()
2752         throws NoninvertibleTransformException
2753     {
2754         double M00, M01, M02;
2755         double M10, M11, M12;
2756         double det;
2757         switch (state) {
2758         default:
2759             stateError();
2760             /* NOTREACHED */
2761             return;
2762         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2763             M00 = m00; M01 = m01; M02 = m02;
2764             M10 = m10; M11 = m11; M12 = m12;
2765             det = M00 * M11 - M01 * M10;


2844         case (APPLY_TRANSLATE):
2845             // m00 = 1.0;
2846             // m10 = 0.0;
2847             // m01 = 0.0;
2848             // m11 = 1.0;
2849             m02 = -m02;
2850             m12 = -m12;
2851             break;
2852         case (APPLY_IDENTITY):
2853             // m00 = 1.0;
2854             // m10 = 0.0;
2855             // m01 = 0.0;
2856             // m11 = 1.0;
2857             // m02 = 0.0;
2858             // m12 = 0.0;
2859             break;
2860         }
2861     }
2862 
2863     /**
2864      * Transforms the specified {@code ptSrc} and stores the result
2865      * in {@code ptDst}.
2866      * If {@code ptDst} is {@code null}, a new {@link Point2D}
2867      * object is allocated and then the result of the transformation is
2868      * stored in this object.
2869      * In either case, {@code ptDst}, which contains the
2870      * transformed point, is returned for convenience.
2871      * If {@code ptSrc} and {@code ptDst} are the same
2872      * object, the input point is correctly overwritten with
2873      * the transformed point.
2874      * @param ptSrc the specified {@code Point2D} to be transformed
2875      * @param ptDst the specified {@code Point2D} that stores the
2876      * result of transforming {@code ptSrc}
2877      * @return the {@code ptDst} after transforming
2878      * {@code ptSrc} and storing the result in {@code ptDst}.
2879      * @since 1.2
2880      */
2881     public Point2D transform(Point2D ptSrc, Point2D ptDst) {
2882         if (ptDst == null) {
2883             if (ptSrc instanceof Point2D.Double) {
2884                 ptDst = new Point2D.Double();
2885             } else {
2886                 ptDst = new Point2D.Float();
2887             }
2888         }
2889         // Copy source coords into local variables in case src == dst
2890         double x = ptSrc.getX();
2891         double y = ptSrc.getY();
2892         switch (state) {
2893         default:
2894             stateError();
2895             /* NOTREACHED */
2896             return null;
2897         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2898             ptDst.setLocation(x * m00 + y * m01 + m02,


2909             return ptDst;
2910         case (APPLY_SCALE | APPLY_TRANSLATE):
2911             ptDst.setLocation(x * m00 + m02, y * m11 + m12);
2912             return ptDst;
2913         case (APPLY_SCALE):
2914             ptDst.setLocation(x * m00, y * m11);
2915             return ptDst;
2916         case (APPLY_TRANSLATE):
2917             ptDst.setLocation(x + m02, y + m12);
2918             return ptDst;
2919         case (APPLY_IDENTITY):
2920             ptDst.setLocation(x, y);
2921             return ptDst;
2922         }
2923 
2924         /* NOTREACHED */
2925     }
2926 
2927     /**
2928      * Transforms an array of point objects by this transform.
2929      * If any element of the {@code ptDst} array is
2930      * {@code null}, a new {@code Point2D} object is allocated
2931      * and stored into that element before storing the results of the
2932      * transformation.
2933      * <p>
2934      * Note that this method does not take any precautions to
2935      * avoid problems caused by storing results into {@code Point2D}
2936      * objects that will be used as the source for calculations
2937      * further down the source array.
2938      * This method does guarantee that if a specified {@code Point2D}
2939      * object is both the source and destination for the same single point
2940      * transform operation then the results will not be stored until
2941      * the calculations are complete to avoid storing the results on
2942      * top of the operands.
2943      * If, however, the destination {@code Point2D} object for one
2944      * operation is the same object as the source {@code Point2D}
2945      * object for another operation further down the source array then
2946      * the original coordinates in that point are overwritten before
2947      * they can be converted.
2948      * @param ptSrc the array containing the source point objects
2949      * @param ptDst the array into which the transform point objects are
2950      * returned
2951      * @param srcOff the offset to the first point object to be
2952      * transformed in the source array
2953      * @param dstOff the offset to the location of the first
2954      * transformed point object that is stored in the destination array
2955      * @param numPts the number of point objects to be transformed
2956      * @since 1.2
2957      */
2958     public void transform(Point2D[] ptSrc, int srcOff,
2959                           Point2D[] ptDst, int dstOff,
2960                           int numPts) {
2961         int state = this.state;
2962         while (--numPts >= 0) {
2963             // Copy source coords into local variables in case src == dst
2964             Point2D src = ptSrc[srcOff++];


3000             case (APPLY_TRANSLATE):
3001                 dst.setLocation(x + m02, y + m12);
3002                 break;
3003             case (APPLY_IDENTITY):
3004                 dst.setLocation(x, y);
3005                 break;
3006             }
3007         }
3008 
3009         /* NOTREACHED */
3010     }
3011 
3012     /**
3013      * Transforms an array of floating point coordinates by this transform.
3014      * The two coordinate array sections can be exactly the same or
3015      * can be overlapping sections of the same array without affecting the
3016      * validity of the results.
3017      * This method ensures that no source coordinates are overwritten by a
3018      * previous operation before they can be transformed.
3019      * The coordinates are stored in the arrays starting at the specified
3020      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3021      * @param srcPts the array containing the source point coordinates.
3022      * Each point is stored as a pair of x,&nbsp;y coordinates.
3023      * @param dstPts the array into which the transformed point coordinates
3024      * are returned.  Each point is stored as a pair of x,&nbsp;y
3025      * coordinates.
3026      * @param srcOff the offset to the first point to be transformed
3027      * in the source array
3028      * @param dstOff the offset to the location of the first
3029      * transformed point that is stored in the destination array
3030      * @param numPts the number of points to be transformed
3031      * @since 1.2
3032      */
3033     public void transform(float[] srcPts, int srcOff,
3034                           float[] dstPts, int dstOff,
3035                           int numPts) {
3036         double M00, M01, M02, M10, M11, M12;    // For caching
3037         if (dstPts == srcPts &&
3038             dstOff > srcOff && dstOff < srcOff + numPts * 2)
3039         {
3040             // If the arrays overlap partially with the destination higher


3115             return;
3116         case (APPLY_IDENTITY):
3117             if (srcPts != dstPts || srcOff != dstOff) {
3118                 System.arraycopy(srcPts, srcOff, dstPts, dstOff,
3119                                  numPts * 2);
3120             }
3121             return;
3122         }
3123 
3124         /* NOTREACHED */
3125     }
3126 
3127     /**
3128      * Transforms an array of double precision coordinates by this transform.
3129      * The two coordinate array sections can be exactly the same or
3130      * can be overlapping sections of the same array without affecting the
3131      * validity of the results.
3132      * This method ensures that no source coordinates are
3133      * overwritten by a previous operation before they can be transformed.
3134      * The coordinates are stored in the arrays starting at the indicated
3135      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3136      * @param srcPts the array containing the source point coordinates.
3137      * Each point is stored as a pair of x,&nbsp;y coordinates.
3138      * @param dstPts the array into which the transformed point
3139      * coordinates are returned.  Each point is stored as a pair of
3140      * x,&nbsp;y coordinates.
3141      * @param srcOff the offset to the first point to be transformed
3142      * in the source array
3143      * @param dstOff the offset to the location of the first
3144      * transformed point that is stored in the destination array
3145      * @param numPts the number of point objects to be transformed
3146      * @since 1.2
3147      */
3148     public void transform(double[] srcPts, int srcOff,
3149                           double[] dstPts, int dstOff,
3150                           int numPts) {
3151         double M00, M01, M02, M10, M11, M12;    // For caching
3152         if (dstPts == srcPts &&
3153             dstOff > srcOff && dstOff < srcOff + numPts * 2)
3154         {
3155             // If the arrays overlap partially with the destination higher


3226             while (--numPts >= 0) {
3227                 dstPts[dstOff++] = srcPts[srcOff++] + M02;
3228                 dstPts[dstOff++] = srcPts[srcOff++] + M12;
3229             }
3230             return;
3231         case (APPLY_IDENTITY):
3232             if (srcPts != dstPts || srcOff != dstOff) {
3233                 System.arraycopy(srcPts, srcOff, dstPts, dstOff,
3234                                  numPts * 2);
3235             }
3236             return;
3237         }
3238 
3239         /* NOTREACHED */
3240     }
3241 
3242     /**
3243      * Transforms an array of floating point coordinates by this transform
3244      * and stores the results into an array of doubles.
3245      * The coordinates are stored in the arrays starting at the specified
3246      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3247      * @param srcPts the array containing the source point coordinates.
3248      * Each point is stored as a pair of x,&nbsp;y coordinates.
3249      * @param dstPts the array into which the transformed point coordinates
3250      * are returned.  Each point is stored as a pair of x,&nbsp;y
3251      * coordinates.
3252      * @param srcOff the offset to the first point to be transformed
3253      * in the source array
3254      * @param dstOff the offset to the location of the first
3255      * transformed point that is stored in the destination array
3256      * @param numPts the number of points to be transformed
3257      * @since 1.2
3258      */
3259     public void transform(float[] srcPts, int srcOff,
3260                           double[] dstPts, int dstOff,
3261                           int numPts) {
3262         double M00, M01, M02, M10, M11, M12;    // For caching
3263         switch (state) {
3264         default:
3265             stateError();
3266             /* NOTREACHED */


3322             while (--numPts >= 0) {
3323                 dstPts[dstOff++] = srcPts[srcOff++] + M02;
3324                 dstPts[dstOff++] = srcPts[srcOff++] + M12;
3325             }
3326             return;
3327         case (APPLY_IDENTITY):
3328             while (--numPts >= 0) {
3329                 dstPts[dstOff++] = srcPts[srcOff++];
3330                 dstPts[dstOff++] = srcPts[srcOff++];
3331             }
3332             return;
3333         }
3334 
3335         /* NOTREACHED */
3336     }
3337 
3338     /**
3339      * Transforms an array of double precision coordinates by this transform
3340      * and stores the results into an array of floats.
3341      * The coordinates are stored in the arrays starting at the specified
3342      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3343      * @param srcPts the array containing the source point coordinates.
3344      * Each point is stored as a pair of x,&nbsp;y coordinates.
3345      * @param dstPts the array into which the transformed point
3346      * coordinates are returned.  Each point is stored as a pair of
3347      * x,&nbsp;y coordinates.
3348      * @param srcOff the offset to the first point to be transformed
3349      * in the source array
3350      * @param dstOff the offset to the location of the first
3351      * transformed point that is stored in the destination array
3352      * @param numPts the number of point objects to be transformed
3353      * @since 1.2
3354      */
3355     public void transform(double[] srcPts, int srcOff,
3356                           float[] dstPts, int dstOff,
3357                           int numPts) {
3358         double M00, M01, M02, M10, M11, M12;    // For caching
3359         switch (state) {
3360         default:
3361             stateError();
3362             /* NOTREACHED */


3415             return;
3416         case (APPLY_TRANSLATE):
3417             M02 = m02; M12 = m12;
3418             while (--numPts >= 0) {
3419                 dstPts[dstOff++] = (float) (srcPts[srcOff++] + M02);
3420                 dstPts[dstOff++] = (float) (srcPts[srcOff++] + M12);
3421             }
3422             return;
3423         case (APPLY_IDENTITY):
3424             while (--numPts >= 0) {
3425                 dstPts[dstOff++] = (float) (srcPts[srcOff++]);
3426                 dstPts[dstOff++] = (float) (srcPts[srcOff++]);
3427             }
3428             return;
3429         }
3430 
3431         /* NOTREACHED */
3432     }
3433 
3434     /**
3435      * Inverse transforms the specified {@code ptSrc} and stores the
3436      * result in {@code ptDst}.
3437      * If {@code ptDst} is {@code null}, a new
3438      * {@code Point2D} object is allocated and then the result of the
3439      * transform is stored in this object.
3440      * In either case, {@code ptDst}, which contains the transformed
3441      * point, is returned for convenience.
3442      * If {@code ptSrc} and {@code ptDst} are the same
3443      * object, the input point is correctly overwritten with the
3444      * transformed point.
3445      * @param ptSrc the point to be inverse transformed
3446      * @param ptDst the resulting transformed point
3447      * @return {@code ptDst}, which contains the result of the
3448      * inverse transform.
3449      * @exception NoninvertibleTransformException  if the matrix cannot be
3450      *                                         inverted.
3451      * @since 1.2
3452      */
3453     @SuppressWarnings("fallthrough")
3454     public Point2D inverseTransform(Point2D ptSrc, Point2D ptDst)
3455         throws NoninvertibleTransformException
3456     {
3457         if (ptDst == null) {
3458             if (ptSrc instanceof Point2D.Double) {
3459                 ptDst = new Point2D.Double();
3460             } else {
3461                 ptDst = new Point2D.Float();
3462             }
3463         }
3464         // Copy source coords into local variables in case src == dst
3465         double x = ptSrc.getX();
3466         double y = ptSrc.getY();
3467         switch (state) {


3504         case (APPLY_TRANSLATE):
3505             ptDst.setLocation(x - m02, y - m12);
3506             return ptDst;
3507         case (APPLY_IDENTITY):
3508             ptDst.setLocation(x, y);
3509             return ptDst;
3510         }
3511 
3512         /* NOTREACHED */
3513     }
3514 
3515     /**
3516      * Inverse transforms an array of double precision coordinates by
3517      * this transform.
3518      * The two coordinate array sections can be exactly the same or
3519      * can be overlapping sections of the same array without affecting the
3520      * validity of the results.
3521      * This method ensures that no source coordinates are
3522      * overwritten by a previous operation before they can be transformed.
3523      * The coordinates are stored in the arrays starting at the specified
3524      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3525      * @param srcPts the array containing the source point coordinates.
3526      * Each point is stored as a pair of x,&nbsp;y coordinates.
3527      * @param dstPts the array into which the transformed point
3528      * coordinates are returned.  Each point is stored as a pair of
3529      * x,&nbsp;y coordinates.
3530      * @param srcOff the offset to the first point to be transformed
3531      * in the source array
3532      * @param dstOff the offset to the location of the first
3533      * transformed point that is stored in the destination array
3534      * @param numPts the number of point objects to be transformed
3535      * @exception NoninvertibleTransformException  if the matrix cannot be
3536      *                                         inverted.
3537      * @since 1.2
3538      */
3539     public void inverseTransform(double[] srcPts, int srcOff,
3540                                  double[] dstPts, int dstOff,
3541                                  int numPts)
3542         throws NoninvertibleTransformException
3543     {
3544         double M00, M01, M02, M10, M11, M12;    // For caching


3640         case (APPLY_TRANSLATE):
3641             M02 = m02; M12 = m12;
3642             while (--numPts >= 0) {
3643                 dstPts[dstOff++] = srcPts[srcOff++] - M02;
3644                 dstPts[dstOff++] = srcPts[srcOff++] - M12;
3645             }
3646             return;
3647         case (APPLY_IDENTITY):
3648             if (srcPts != dstPts || srcOff != dstOff) {
3649                 System.arraycopy(srcPts, srcOff, dstPts, dstOff,
3650                                  numPts * 2);
3651             }
3652             return;
3653         }
3654 
3655         /* NOTREACHED */
3656     }
3657 
3658     /**
3659      * Transforms the relative distance vector specified by
3660      * {@code ptSrc} and stores the result in {@code ptDst}.
3661      * A relative distance vector is transformed without applying the
3662      * translation components of the affine transformation matrix
3663      * using the following equations:
3664      * <pre>
3665      *  [  x' ]   [  m00  m01 (m02) ] [  x  ]   [ m00x + m01y ]
3666      *  [  y' ] = [  m10  m11 (m12) ] [  y  ] = [ m10x + m11y ]
3667      *  [ (1) ]   [  (0)  (0) ( 1 ) ] [ (1) ]   [     (1)     ]
3668      * </pre>
3669      * If {@code ptDst} is {@code null}, a new
3670      * {@code Point2D} object is allocated and then the result of the
3671      * transform is stored in this object.
3672      * In either case, {@code ptDst}, which contains the
3673      * transformed point, is returned for convenience.
3674      * If {@code ptSrc} and {@code ptDst} are the same object,
3675      * the input point is correctly overwritten with the transformed
3676      * point.
3677      * @param ptSrc the distance vector to be delta transformed
3678      * @param ptDst the resulting transformed distance vector
3679      * @return {@code ptDst}, which contains the result of the
3680      * transformation.
3681      * @since 1.2
3682      */
3683     public Point2D deltaTransform(Point2D ptSrc, Point2D ptDst) {
3684         if (ptDst == null) {
3685             if (ptSrc instanceof Point2D.Double) {
3686                 ptDst = new Point2D.Double();
3687             } else {
3688                 ptDst = new Point2D.Float();
3689             }
3690         }
3691         // Copy source coords into local variables in case src == dst
3692         double x = ptSrc.getX();
3693         double y = ptSrc.getY();
3694         switch (state) {
3695         default:
3696             stateError();
3697             /* NOTREACHED */
3698             return null;
3699         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):


3717         /* NOTREACHED */
3718     }
3719 
3720     /**
3721      * Transforms an array of relative distance vectors by this
3722      * transform.
3723      * A relative distance vector is transformed without applying the
3724      * translation components of the affine transformation matrix
3725      * using the following equations:
3726      * <pre>
3727      *  [  x' ]   [  m00  m01 (m02) ] [  x  ]   [ m00x + m01y ]
3728      *  [  y' ] = [  m10  m11 (m12) ] [  y  ] = [ m10x + m11y ]
3729      *  [ (1) ]   [  (0)  (0) ( 1 ) ] [ (1) ]   [     (1)     ]
3730      * </pre>
3731      * The two coordinate array sections can be exactly the same or
3732      * can be overlapping sections of the same array without affecting the
3733      * validity of the results.
3734      * This method ensures that no source coordinates are
3735      * overwritten by a previous operation before they can be transformed.
3736      * The coordinates are stored in the arrays starting at the indicated
3737      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3738      * @param srcPts the array containing the source distance vectors.
3739      * Each vector is stored as a pair of relative x,&nbsp;y coordinates.
3740      * @param dstPts the array into which the transformed distance vectors
3741      * are returned.  Each vector is stored as a pair of relative
3742      * x,&nbsp;y coordinates.
3743      * @param srcOff the offset to the first vector to be transformed
3744      * in the source array
3745      * @param dstOff the offset to the location of the first
3746      * transformed vector that is stored in the destination array
3747      * @param numPts the number of vector coordinate pairs to be
3748      * transformed
3749      * @since 1.2
3750      */
3751     public void deltaTransform(double[] srcPts, int srcOff,
3752                                double[] dstPts, int dstOff,
3753                                int numPts) {
3754         double M00, M01, M10, M11;      // For caching
3755         if (dstPts == srcPts &&
3756             dstOff > srcOff && dstOff < srcOff + numPts * 2)
3757         {


3797             M00 = m00; M11 = m11;
3798             while (--numPts >= 0) {
3799                 dstPts[dstOff++] = srcPts[srcOff++] * M00;
3800                 dstPts[dstOff++] = srcPts[srcOff++] * M11;
3801             }
3802             return;
3803         case (APPLY_TRANSLATE):
3804         case (APPLY_IDENTITY):
3805             if (srcPts != dstPts || srcOff != dstOff) {
3806                 System.arraycopy(srcPts, srcOff, dstPts, dstOff,
3807                                  numPts * 2);
3808             }
3809             return;
3810         }
3811 
3812         /* NOTREACHED */
3813     }
3814 
3815     /**
3816      * Returns a new {@link Shape} object defined by the geometry of the
3817      * specified {@code Shape} after it has been transformed by
3818      * this transform.
3819      * @param pSrc the specified {@code Shape} object to be
3820      * transformed by this transform.
3821      * @return a new {@code Shape} object that defines the geometry
3822      * of the transformed {@code Shape}, or null if {@code pSrc} is null.
3823      * @since 1.2
3824      */
3825     public Shape createTransformedShape(Shape pSrc) {
3826         if (pSrc == null) {
3827             return null;
3828         }
3829         return new Path2D.Double(pSrc, this);
3830     }
3831 
3832     // Round values to sane precision for printing
3833     // Note that Math.sin(Math.PI) has an error of about 10^-16
3834     private static double _matround(double matval) {
3835         return Math.rint(matval * 1E15) / 1E15;
3836     }
3837 
3838     /**
3839      * Returns a {@code String} that represents the value of this
3840      * {@link Object}.
3841      * @return a {@code String} representing the value of this
3842      * {@code Object}.
3843      * @since 1.2
3844      */
3845     public String toString() {
3846         return ("AffineTransform[["
3847                 + _matround(m00) + ", "
3848                 + _matround(m01) + ", "
3849                 + _matround(m02) + "], ["
3850                 + _matround(m10) + ", "
3851                 + _matround(m11) + ", "
3852                 + _matround(m12) + "]]");
3853     }
3854 
3855     /**
3856      * Returns {@code true} if this {@code AffineTransform} is
3857      * an identity transform.
3858      * @return {@code true} if this {@code AffineTransform} is
3859      * an identity transform; {@code false} otherwise.
3860      * @since 1.2
3861      */
3862     public boolean isIdentity() {
3863         return (state == APPLY_IDENTITY || (getType() == TYPE_IDENTITY));
3864     }
3865 
3866     /**
3867      * Returns a copy of this {@code AffineTransform} object.
3868      * @return an {@code Object} that is a copy of this
3869      * {@code AffineTransform} object.
3870      * @since 1.2
3871      */
3872     public Object clone() {
3873         try {
3874             return super.clone();
3875         } catch (CloneNotSupportedException e) {
3876             // this shouldn't happen, since we are Cloneable
3877             throw new InternalError(e);
3878         }
3879     }
3880 
3881     /**
3882      * Returns the hashcode for this transform.
3883      * @return      a hash code for this transform.
3884      * @since 1.2
3885      */
3886     public int hashCode() {
3887         long bits = Double.doubleToLongBits(m00);
3888         bits = bits * 31 + Double.doubleToLongBits(m01);
3889         bits = bits * 31 + Double.doubleToLongBits(m02);
3890         bits = bits * 31 + Double.doubleToLongBits(m10);
3891         bits = bits * 31 + Double.doubleToLongBits(m11);
3892         bits = bits * 31 + Double.doubleToLongBits(m12);
3893         return (((int) bits) ^ ((int) (bits >> 32)));
3894     }
3895 
3896     /**
3897      * Returns {@code true} if this {@code AffineTransform}
3898      * represents the same affine coordinate transform as the specified
3899      * argument.
3900      * @param obj the {@code Object} to test for equality with this
3901      * {@code AffineTransform}
3902      * @return {@code true} if {@code obj} equals this
3903      * {@code AffineTransform} object; {@code false} otherwise.
3904      * @since 1.2
3905      */
3906     public boolean equals(Object obj) {
3907         if (!(obj instanceof AffineTransform)) {
3908             return false;
3909         }
3910 
3911         AffineTransform a = (AffineTransform)obj;
3912 
3913         return ((m00 == a.m00) && (m01 == a.m01) && (m02 == a.m02) &&
3914                 (m10 == a.m10) && (m11 == a.m11) && (m12 == a.m12));
3915     }
3916 
3917     /* Serialization support.  A readObject method is neccessary because
3918      * the state field is part of the implementation of this particular
3919      * AffineTransform and not part of the public specification.  The
3920      * state variable's value needs to be recalculated on the fly by the
3921      * readObject method as it is in the 6-argument matrix constructor.
3922      */
3923 
< prev index next >