1 /*
   2  * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.awt.geom;
  27 
  28 import java.awt.Shape;
  29 import java.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 id="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
 130      * conversions that this transform performs.
 131      * @see #TYPE_TRANSLATION
 132      * @see #TYPE_UNIFORM_SCALE
 133      * @see #TYPE_GENERAL_SCALE
 134      * @see #TYPE_FLIP
 135      * @see #TYPE_QUADRANT_ROTATION
 136      * @see #TYPE_GENERAL_ROTATION
 137      * @see #TYPE_GENERAL_TRANSFORM
 138      * @see #getType
 139      * @since 1.2
 140      */
 141     public static final int TYPE_IDENTITY = 0;
 142 
 143     /**
 144      * This flag bit indicates that the transform defined by this object
 145      * performs a translation in addition to the conversions indicated
 146      * by other flag bits.
 147      * A translation moves the coordinates by a constant amount in x
 148      * and y without changing the length or angle of vectors.
 149      * @see #TYPE_IDENTITY
 150      * @see #TYPE_UNIFORM_SCALE
 151      * @see #TYPE_GENERAL_SCALE
 152      * @see #TYPE_FLIP
 153      * @see #TYPE_QUADRANT_ROTATION
 154      * @see #TYPE_GENERAL_ROTATION
 155      * @see #TYPE_GENERAL_TRANSFORM
 156      * @see #getType
 157      * @since 1.2
 158      */
 159     public static final int TYPE_TRANSLATION = 1;
 160 
 161     /**
 162      * This flag bit indicates that the transform defined by this object
 163      * performs a uniform scale in addition to the conversions indicated
 164      * by other flag bits.
 165      * A uniform scale multiplies the length of vectors by the same amount
 166      * in both the x and y directions without changing the angle between
 167      * vectors.
 168      * This flag bit is mutually exclusive with the TYPE_GENERAL_SCALE flag.
 169      * @see #TYPE_IDENTITY
 170      * @see #TYPE_TRANSLATION
 171      * @see #TYPE_GENERAL_SCALE
 172      * @see #TYPE_FLIP
 173      * @see #TYPE_QUADRANT_ROTATION
 174      * @see #TYPE_GENERAL_ROTATION
 175      * @see #TYPE_GENERAL_TRANSFORM
 176      * @see #getType
 177      * @since 1.2
 178      */
 179     public static final int TYPE_UNIFORM_SCALE = 2;
 180 
 181     /**
 182      * This flag bit indicates that the transform defined by this object
 183      * performs a general scale in addition to the conversions indicated
 184      * by other flag bits.
 185      * A general scale multiplies the length of vectors by different
 186      * amounts in the x and y directions without changing the angle
 187      * between perpendicular vectors.
 188      * This flag bit is mutually exclusive with the TYPE_UNIFORM_SCALE flag.
 189      * @see #TYPE_IDENTITY
 190      * @see #TYPE_TRANSLATION
 191      * @see #TYPE_UNIFORM_SCALE
 192      * @see #TYPE_FLIP
 193      * @see #TYPE_QUADRANT_ROTATION
 194      * @see #TYPE_GENERAL_ROTATION
 195      * @see #TYPE_GENERAL_TRANSFORM
 196      * @see #getType
 197      * @since 1.2
 198      */
 199     public static final int TYPE_GENERAL_SCALE = 4;
 200 
 201     /**
 202      * This constant is a bit mask for any of the scale flag bits.
 203      * @see #TYPE_UNIFORM_SCALE
 204      * @see #TYPE_GENERAL_SCALE
 205      * @since 1.2
 206      */
 207     public static final int TYPE_MASK_SCALE = (TYPE_UNIFORM_SCALE |
 208                                                TYPE_GENERAL_SCALE);
 209 
 210     /**
 211      * This flag bit indicates that the transform defined by this object
 212      * performs a mirror image flip about some axis which changes the
 213      * normally right handed coordinate system into a left handed
 214      * system in addition to the conversions indicated by other flag bits.
 215      * A right handed coordinate system is one where the positive X
 216      * axis rotates counterclockwise to overlay the positive Y axis
 217      * similar to the direction that the fingers on your right hand
 218      * curl when you stare end on at your thumb.
 219      * A left handed coordinate system is one where the positive X
 220      * axis rotates clockwise to overlay the positive Y axis similar
 221      * to the direction that the fingers on your left hand curl.
 222      * There is no mathematical way to determine the angle of the
 223      * original flipping or mirroring transformation since all angles
 224      * of flip are identical given an appropriate adjusting rotation.
 225      * @see #TYPE_IDENTITY
 226      * @see #TYPE_TRANSLATION
 227      * @see #TYPE_UNIFORM_SCALE
 228      * @see #TYPE_GENERAL_SCALE
 229      * @see #TYPE_QUADRANT_ROTATION
 230      * @see #TYPE_GENERAL_ROTATION
 231      * @see #TYPE_GENERAL_TRANSFORM
 232      * @see #getType
 233      * @since 1.2
 234      */
 235     public static final int TYPE_FLIP = 64;
 236     /* NOTE: TYPE_FLIP was added after GENERAL_TRANSFORM was in public
 237      * circulation and the flag bits could no longer be conveniently
 238      * renumbered without introducing binary incompatibility in outside
 239      * code.
 240      */
 241 
 242     /**
 243      * This flag bit indicates that the transform defined by this object
 244      * performs a quadrant rotation by some multiple of 90 degrees in
 245      * addition to the conversions indicated by other flag bits.
 246      * A rotation changes the angles of vectors by the same amount
 247      * regardless of the original direction of the vector and without
 248      * changing the length of the vector.
 249      * This flag bit is mutually exclusive with the TYPE_GENERAL_ROTATION flag.
 250      * @see #TYPE_IDENTITY
 251      * @see #TYPE_TRANSLATION
 252      * @see #TYPE_UNIFORM_SCALE
 253      * @see #TYPE_GENERAL_SCALE
 254      * @see #TYPE_FLIP
 255      * @see #TYPE_GENERAL_ROTATION
 256      * @see #TYPE_GENERAL_TRANSFORM
 257      * @see #getType
 258      * @since 1.2
 259      */
 260     public static final int TYPE_QUADRANT_ROTATION = 8;
 261 
 262     /**
 263      * This flag bit indicates that the transform defined by this object
 264      * performs a rotation by an arbitrary angle in addition to the
 265      * conversions indicated by other flag bits.
 266      * A rotation changes the angles of vectors by the same amount
 267      * regardless of the original direction of the vector and without
 268      * changing the length of the vector.
 269      * This flag bit is mutually exclusive with the
 270      * TYPE_QUADRANT_ROTATION flag.
 271      * @see #TYPE_IDENTITY
 272      * @see #TYPE_TRANSLATION
 273      * @see #TYPE_UNIFORM_SCALE
 274      * @see #TYPE_GENERAL_SCALE
 275      * @see #TYPE_FLIP
 276      * @see #TYPE_QUADRANT_ROTATION
 277      * @see #TYPE_GENERAL_TRANSFORM
 278      * @see #getType
 279      * @since 1.2
 280      */
 281     public static final int TYPE_GENERAL_ROTATION = 16;
 282 
 283     /**
 284      * This constant is a bit mask for any of the rotation flag bits.
 285      * @see #TYPE_QUADRANT_ROTATION
 286      * @see #TYPE_GENERAL_ROTATION
 287      * @since 1.2
 288      */
 289     public static final int TYPE_MASK_ROTATION = (TYPE_QUADRANT_ROTATION |
 290                                                   TYPE_GENERAL_ROTATION);
 291 
 292     /**
 293      * This constant indicates that the transform defined by this object
 294      * performs an arbitrary conversion of the input coordinates.
 295      * If this transform can be classified by any of the above constants,
 296      * the type will either be the constant TYPE_IDENTITY or a
 297      * combination of the appropriate flag bits for the various coordinate
 298      * conversions that this transform performs.
 299      * @see #TYPE_IDENTITY
 300      * @see #TYPE_TRANSLATION
 301      * @see #TYPE_UNIFORM_SCALE
 302      * @see #TYPE_GENERAL_SCALE
 303      * @see #TYPE_FLIP
 304      * @see #TYPE_QUADRANT_ROTATION
 305      * @see #TYPE_GENERAL_ROTATION
 306      * @see #getType
 307      * @since 1.2
 308      */
 309     public static final int TYPE_GENERAL_TRANSFORM = 32;
 310 
 311     /**
 312      * This constant is used for the internal state variable to indicate
 313      * that no calculations need to be performed and that the source
 314      * coordinates only need to be copied to their destinations to
 315      * complete the transformation equation of this transform.
 316      * @see #APPLY_TRANSLATE
 317      * @see #APPLY_SCALE
 318      * @see #APPLY_SHEAR
 319      * @see #state
 320      */
 321     static final int APPLY_IDENTITY = 0;
 322 
 323     /**
 324      * This constant is used for the internal state variable to indicate
 325      * that the translation components of the matrix (m02 and m12) need
 326      * to be added to complete the transformation equation of this transform.
 327      * @see #APPLY_IDENTITY
 328      * @see #APPLY_SCALE
 329      * @see #APPLY_SHEAR
 330      * @see #state
 331      */
 332     static final int APPLY_TRANSLATE = 1;
 333 
 334     /**
 335      * This constant is used for the internal state variable to indicate
 336      * that the scaling components of the matrix (m00 and m11) need
 337      * to be factored in to complete the transformation equation of
 338      * this transform.  If the APPLY_SHEAR bit is also set then it
 339      * indicates that the scaling components are not both 0.0.  If the
 340      * APPLY_SHEAR bit is not also set then it indicates that the
 341      * scaling components are not both 1.0.  If neither the APPLY_SHEAR
 342      * nor the APPLY_SCALE bits are set then the scaling components
 343      * are both 1.0, which means that the x and y components contribute
 344      * to the transformed coordinate, but they are not multiplied by
 345      * any scaling factor.
 346      * @see #APPLY_IDENTITY
 347      * @see #APPLY_TRANSLATE
 348      * @see #APPLY_SHEAR
 349      * @see #state
 350      */
 351     static final int APPLY_SCALE = 2;
 352 
 353     /**
 354      * This constant is used for the internal state variable to indicate
 355      * that the shearing components of the matrix (m01 and m10) need
 356      * to be factored in to complete the transformation equation of this
 357      * transform.  The presence of this bit in the state variable changes
 358      * the interpretation of the APPLY_SCALE bit as indicated in its
 359      * documentation.
 360      * @see #APPLY_IDENTITY
 361      * @see #APPLY_TRANSLATE
 362      * @see #APPLY_SCALE
 363      * @see #state
 364      */
 365     static final int APPLY_SHEAR = 4;
 366 
 367     /*
 368      * For methods which combine together the state of two separate
 369      * transforms and dispatch based upon the combination, these constants
 370      * specify how far to shift one of the states so that the two states
 371      * are mutually non-interfering and provide constants for testing the
 372      * bits of the shifted (HI) state.  The methods in this class use
 373      * the convention that the state of "this" transform is unshifted and
 374      * the state of the "other" or "argument" transform is shifted (HI).
 375      */
 376     private static final int HI_SHIFT = 3;
 377     private static final int HI_IDENTITY = APPLY_IDENTITY << HI_SHIFT;
 378     private static final int HI_TRANSLATE = APPLY_TRANSLATE << HI_SHIFT;
 379     private static final int HI_SCALE = APPLY_SCALE << HI_SHIFT;
 380     private static final int HI_SHEAR = APPLY_SHEAR << HI_SHIFT;
 381 
 382     /**
 383      * The X coordinate scaling element of the 3x3
 384      * affine transformation matrix.
 385      *
 386      * @serial
 387      */
 388     double m00;
 389 
 390     /**
 391      * The Y coordinate shearing element of the 3x3
 392      * affine transformation matrix.
 393      *
 394      * @serial
 395      */
 396      double m10;
 397 
 398     /**
 399      * The X coordinate shearing element of the 3x3
 400      * affine transformation matrix.
 401      *
 402      * @serial
 403      */
 404      double m01;
 405 
 406     /**
 407      * The Y coordinate scaling element of the 3x3
 408      * affine transformation matrix.
 409      *
 410      * @serial
 411      */
 412      double m11;
 413 
 414     /**
 415      * The X coordinate of the translation element of the
 416      * 3x3 affine transformation matrix.
 417      *
 418      * @serial
 419      */
 420      double m02;
 421 
 422     /**
 423      * The Y coordinate of the translation element of the
 424      * 3x3 affine transformation matrix.
 425      *
 426      * @serial
 427      */
 428      double m12;
 429 
 430     /**
 431      * This field keeps track of which components of the matrix need to
 432      * be applied when performing a transformation.
 433      * @see #APPLY_IDENTITY
 434      * @see #APPLY_TRANSLATE
 435      * @see #APPLY_SCALE
 436      * @see #APPLY_SHEAR
 437      */
 438     transient int state;
 439 
 440     /**
 441      * This field caches the current transformation type of the matrix.
 442      * @see #TYPE_IDENTITY
 443      * @see #TYPE_TRANSLATION
 444      * @see #TYPE_UNIFORM_SCALE
 445      * @see #TYPE_GENERAL_SCALE
 446      * @see #TYPE_FLIP
 447      * @see #TYPE_QUADRANT_ROTATION
 448      * @see #TYPE_GENERAL_ROTATION
 449      * @see #TYPE_GENERAL_TRANSFORM
 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
 853      * as well as either of the
 854      * TYPE_QUADRANT_ROTATION or TYPE_GENERAL_ROTATION flag bits.
 855      * @return the OR combination of any of the indicated flags that
 856      * apply to this transform
 857      * @see #TYPE_IDENTITY
 858      * @see #TYPE_TRANSLATION
 859      * @see #TYPE_UNIFORM_SCALE
 860      * @see #TYPE_GENERAL_SCALE
 861      * @see #TYPE_QUADRANT_ROTATION
 862      * @see #TYPE_GENERAL_ROTATION
 863      * @see #TYPE_GENERAL_TRANSFORM
 864      * @since 1.2
 865      */
 866     public int getType() {
 867         if (type == TYPE_UNKNOWN) {
 868             calculateType();
 869         }
 870         return type;
 871     }
 872 
 873     /**
 874      * This is the utility function to calculate the flag bits when
 875      * they have not been cached.
 876      * @see #getType
 877      */
 878     @SuppressWarnings("fallthrough")
 879     private void calculateType() {
 880         int ret = TYPE_IDENTITY;
 881         boolean sgn0, sgn1;
 882         double M0, M1, M2, M3;
 883         updateState();
 884         switch (state) {
 885         default:
 886             stateError();
 887             /* NOTREACHED */
 888         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
 889             ret = TYPE_TRANSLATION;
 890             /* NOBREAK */
 891         case (APPLY_SHEAR | APPLY_SCALE):
 892             if ((M0 = m00) * (M2 = m01) + (M3 = m10) * (M1 = m11) != 0) {
 893                 // Transformed unit vectors are not perpendicular...
 894                 this.type = TYPE_GENERAL_TRANSFORM;
 895                 return;
 896             }
 897             sgn0 = (M0 >= 0.0);
 898             sgn1 = (M1 >= 0.0);
 899             if (sgn0 == sgn1) {
 900                 // sgn(M0) == sgn(M1) therefore sgn(M2) == -sgn(M3)
 901                 // This is the "unflipped" (right-handed) state
 902                 if (M0 != M1 || M2 != -M3) {
 903                     ret |= (TYPE_GENERAL_ROTATION | TYPE_GENERAL_SCALE);
 904                 } else if (M0 * M1 - M2 * M3 != 1.0) {
 905                     ret |= (TYPE_GENERAL_ROTATION | TYPE_UNIFORM_SCALE);
 906                 } else {
 907                     ret |= TYPE_GENERAL_ROTATION;
 908                 }
 909             } else {
 910                 // sgn(M0) == -sgn(M1) therefore sgn(M2) == sgn(M3)
 911                 // This is the "flipped" (left-handed) state
 912                 if (M0 != -M1 || M2 != M3) {
 913                     ret |= (TYPE_GENERAL_ROTATION |
 914                             TYPE_FLIP |
 915                             TYPE_GENERAL_SCALE);
 916                 } else if (M0 * M1 - M2 * M3 != 1.0) {
 917                     ret |= (TYPE_GENERAL_ROTATION |
 918                             TYPE_FLIP |
 919                             TYPE_UNIFORM_SCALE);
 920                 } else {
 921                     ret |= (TYPE_GENERAL_ROTATION | TYPE_FLIP);
 922                 }
 923             }
 924             break;
 925         case (APPLY_SHEAR | APPLY_TRANSLATE):
 926             ret = TYPE_TRANSLATION;
 927             /* NOBREAK */
 928         case (APPLY_SHEAR):
 929             sgn0 = ((M0 = m01) >= 0.0);
 930             sgn1 = ((M1 = m10) >= 0.0);
 931             if (sgn0 != sgn1) {
 932                 // Different signs - simple 90 degree rotation
 933                 if (M0 != -M1) {
 934                     ret |= (TYPE_QUADRANT_ROTATION | TYPE_GENERAL_SCALE);
 935                 } else if (M0 != 1.0 && M0 != -1.0) {
 936                     ret |= (TYPE_QUADRANT_ROTATION | TYPE_UNIFORM_SCALE);
 937                 } else {
 938                     ret |= TYPE_QUADRANT_ROTATION;
 939                 }
 940             } else {
 941                 // Same signs - 90 degree rotation plus an axis flip too
 942                 if (M0 == M1) {
 943                     ret |= (TYPE_QUADRANT_ROTATION |
 944                             TYPE_FLIP |
 945                             TYPE_UNIFORM_SCALE);
 946                 } else {
 947                     ret |= (TYPE_QUADRANT_ROTATION |
 948                             TYPE_FLIP |
 949                             TYPE_GENERAL_SCALE);
 950                 }
 951             }
 952             break;
 953         case (APPLY_SCALE | APPLY_TRANSLATE):
 954             ret = TYPE_TRANSLATION;
 955             /* NOBREAK */
 956         case (APPLY_SCALE):
 957             sgn0 = ((M0 = m00) >= 0.0);
 958             sgn1 = ((M1 = m11) >= 0.0);
 959             if (sgn0 == sgn1) {
 960                 if (sgn0) {
 961                     // Both scaling factors non-negative - simple scale
 962                     // Note: APPLY_SCALE implies M0, M1 are not both 1
 963                     if (M0 == M1) {
 964                         ret |= TYPE_UNIFORM_SCALE;
 965                     } else {
 966                         ret |= TYPE_GENERAL_SCALE;
 967                     }
 968                 } else {
 969                     // Both scaling factors negative - 180 degree rotation
 970                     if (M0 != M1) {
 971                         ret |= (TYPE_QUADRANT_ROTATION | TYPE_GENERAL_SCALE);
 972                     } else if (M0 != -1.0) {
 973                         ret |= (TYPE_QUADRANT_ROTATION | TYPE_UNIFORM_SCALE);
 974                     } else {
 975                         ret |= TYPE_QUADRANT_ROTATION;
 976                     }
 977                 }
 978             } else {
 979                 // Scaling factor signs different - flip about some axis
 980                 if (M0 == -M1) {
 981                     if (M0 == 1.0 || M0 == -1.0) {
 982                         ret |= TYPE_FLIP;
 983                     } else {
 984                         ret |= (TYPE_FLIP | TYPE_UNIFORM_SCALE);
 985                     }
 986                 } else {
 987                     ret |= (TYPE_FLIP | TYPE_GENERAL_SCALE);
 988                 }
 989             }
 990             break;
 991         case (APPLY_TRANSLATE):
 992             ret = TYPE_TRANSLATION;
 993             break;
 994         case (APPLY_IDENTITY):
 995             break;
 996         }
 997         this.type = ret;
 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
1039      * @since 1.2
1040      */
1041     @SuppressWarnings("fallthrough")
1042     public double getDeterminant() {
1043         switch (state) {
1044         default:
1045             stateError();
1046             /* NOTREACHED */
1047         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
1048         case (APPLY_SHEAR | APPLY_SCALE):
1049             return m00 * m11 - m01 * m10;
1050         case (APPLY_SHEAR | APPLY_TRANSLATE):
1051         case (APPLY_SHEAR):
1052             return -(m01 * m10);
1053         case (APPLY_SCALE | APPLY_TRANSLATE):
1054         case (APPLY_SCALE):
1055             return m00 * m11;
1056         case (APPLY_TRANSLATE):
1057         case (APPLY_IDENTITY):
1058             return 1.0;
1059         }
1060     }
1061 
1062     /**
1063      * Manually recalculates the state of the transform when the matrix
1064      * changes too much to predict the effects on the state.
1065      * The following table specifies what the various settings of the
1066      * state field say about the values of the corresponding matrix
1067      * element fields.
1068      * Note that the rules governing the SCALE fields are slightly
1069      * different depending on whether the SHEAR flag is also set.
1070      * <pre>
1071      *                     SCALE            SHEAR          TRANSLATE
1072      *                    m00/m11          m01/m10          m02/m12
1073      *
1074      * IDENTITY             1.0              0.0              0.0
1075      * TRANSLATE (TR)       1.0              0.0          not both 0.0
1076      * SCALE (SC)       not both 1.0         0.0              0.0
1077      * TR | SC          not both 1.0         0.0          not both 0.0
1078      * SHEAR (SH)           0.0          not both 0.0         0.0
1079      * TR | SH              0.0          not both 0.0     not both 0.0
1080      * SC | SH          not both 0.0     not both 0.0         0.0
1081      * TR | SC | SH     not both 0.0     not both 0.0     not both 0.0
1082      * </pre>
1083      */
1084     void updateState() {
1085         if (m01 == 0.0 && m10 == 0.0) {
1086             if (m00 == 1.0 && m11 == 1.0) {
1087                 if (m02 == 0.0 && m12 == 0.0) {
1088                     state = APPLY_IDENTITY;
1089                     type = TYPE_IDENTITY;
1090                 } else {
1091                     state = APPLY_TRANSLATE;
1092                     type = TYPE_TRANSLATION;
1093                 }
1094             } else {
1095                 if (m02 == 0.0 && m12 == 0.0) {
1096                     state = APPLY_SCALE;
1097                     type = TYPE_UNKNOWN;
1098                 } else {
1099                     state = (APPLY_SCALE | APPLY_TRANSLATE);
1100                     type = TYPE_UNKNOWN;
1101                 }
1102             }
1103         } else {
1104             if (m00 == 0.0 && m11 == 0.0) {
1105                 if (m02 == 0.0 && m12 == 0.0) {
1106                     state = APPLY_SHEAR;
1107                     type = TYPE_UNKNOWN;
1108                 } else {
1109                     state = (APPLY_SHEAR | APPLY_TRANSLATE);
1110                     type = TYPE_UNKNOWN;
1111                 }
1112             } else {
1113                 if (m02 == 0.0 && m12 == 0.0) {
1114                     state = (APPLY_SHEAR | APPLY_SCALE);
1115                     type = TYPE_UNKNOWN;
1116                 } else {
1117                     state = (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE);
1118                     type = TYPE_UNKNOWN;
1119                 }
1120             }
1121         }
1122     }
1123 
1124     /*
1125      * Convenience method used internally to throw exceptions when
1126      * a case was forgotten in a switch statement.
1127      */
1128     private void stateError() {
1129         throw new InternalError("missing case in transform state switch");
1130     }
1131 
1132     /**
1133      * Retrieves the 6 specifiable values in the 3x3 affine transformation
1134      * matrix and places them into an array of double precisions values.
1135      * The values are stored in the array as
1136      * {&nbsp;m00&nbsp;m10&nbsp;m01&nbsp;m11&nbsp;m02&nbsp;m12&nbsp;}.
1137      * An array of 4 doubles can also be specified, in which case only the
1138      * first four elements representing the non-transform
1139      * parts of the array are retrieved and the values are stored into
1140      * the array as {&nbsp;m00&nbsp;m10&nbsp;m01&nbsp;m11&nbsp;}
1141      * @param flatmatrix the double array used to store the returned
1142      * values.
1143      * @see #getScaleX
1144      * @see #getScaleY
1145      * @see #getShearX
1146      * @see #getShearY
1147      * @see #getTranslateX
1148      * @see #getTranslateY
1149      * @since 1.2
1150      */
1151     public void getMatrix(double[] flatmatrix) {
1152         flatmatrix[0] = m00;
1153         flatmatrix[1] = m10;
1154         flatmatrix[2] = m01;
1155         flatmatrix[3] = m11;
1156         if (flatmatrix.length > 5) {
1157             flatmatrix[4] = m02;
1158             flatmatrix[5] = m12;
1159         }
1160     }
1161 
1162     /**
1163      * Returns the {@code m00} element of the 3x3 affine transformation matrix.
1164      * This matrix factor determines how input X coordinates will affect output
1165      * X coordinates and is one element of the scale of the transform.
1166      * To measure the full amount by which X coordinates are stretched or
1167      * contracted by this transform, use the following code:
1168      * <pre>
1169      *     Point2D p = new Point2D.Double(1, 0);
1170      *     p = tx.deltaTransform(p, p);
1171      *     double scaleX = p.distance(0, 0);
1172      * </pre>
1173      * @return a double value that is {@code m00} element of the
1174      *         3x3 affine transformation matrix.
1175      * @see #getMatrix
1176      * @since 1.2
1177      */
1178     public double getScaleX() {
1179         return m00;
1180     }
1181 
1182     /**
1183      * Returns the {@code m11} element of the 3x3 affine transformation matrix.
1184      * This matrix factor determines how input Y coordinates will affect output
1185      * Y coordinates and is one element of the scale of the transform.
1186      * To measure the full amount by which Y coordinates are stretched or
1187      * contracted by this transform, use the following code:
1188      * <pre>
1189      *     Point2D p = new Point2D.Double(0, 1);
1190      *     p = tx.deltaTransform(p, p);
1191      *     double scaleY = p.distance(0, 0);
1192      * </pre>
1193      * @return a double value that is {@code m11} element of the
1194      *         3x3 affine transformation matrix.
1195      * @see #getMatrix
1196      * @since 1.2
1197      */
1198     public double getScaleY() {
1199         return m11;
1200     }
1201 
1202     /**
1203      * Returns the X coordinate shearing element (m01) of the 3x3
1204      * affine transformation matrix.
1205      * @return a double value that is the X coordinate of the shearing
1206      *  element of the affine transformation matrix.
1207      * @see #getMatrix
1208      * @since 1.2
1209      */
1210     public double getShearX() {
1211         return m01;
1212     }
1213 
1214     /**
1215      * Returns the Y coordinate shearing element (m10) of the 3x3
1216      * affine transformation matrix.
1217      * @return a double value that is the Y coordinate of the shearing
1218      *  element of the affine transformation matrix.
1219      * @see #getMatrix
1220      * @since 1.2
1221      */
1222     public double getShearY() {
1223         return m10;
1224     }
1225 
1226     /**
1227      * Returns the X coordinate of the translation element (m02) of the
1228      * 3x3 affine transformation matrix.
1229      * @return a double value that is the X coordinate of the translation
1230      *  element of the affine transformation matrix.
1231      * @see #getMatrix
1232      * @since 1.2
1233      */
1234     public double getTranslateX() {
1235         return m02;
1236     }
1237 
1238     /**
1239      * Returns the Y coordinate of the translation element (m12) of the
1240      * 3x3 affine transformation matrix.
1241      * @return a double value that is the Y coordinate of the translation
1242      *  element of the affine transformation matrix.
1243      * @see #getMatrix
1244      * @since 1.2
1245      */
1246     public double getTranslateY() {
1247         return m12;
1248     }
1249 
1250     /**
1251      * Concatenates this transform with a translation transformation.
1252      * This is equivalent to calling concatenate(T), where T is an
1253      * {@code AffineTransform} represented by the following matrix:
1254      * <pre>
1255      *          [   1    0    tx  ]
1256      *          [   0    1    ty  ]
1257      *          [   0    0    1   ]
1258      * </pre>
1259      * @param tx the distance by which coordinates are translated in the
1260      * X axis direction
1261      * @param ty the distance by which coordinates are translated in the
1262      * Y axis direction
1263      * @since 1.2
1264      */
1265     public void translate(double tx, double ty) {
1266         switch (state) {
1267         default:
1268             stateError();
1269             /* NOTREACHED */
1270             return;
1271         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
1272             m02 = tx * m00 + ty * m01 + m02;
1273             m12 = tx * m10 + ty * m11 + m12;
1274             if (m02 == 0.0 && m12 == 0.0) {
1275                 state = APPLY_SHEAR | APPLY_SCALE;
1276                 if (type != TYPE_UNKNOWN) {
1277                     type -= TYPE_TRANSLATION;
1278                 }
1279             }
1280             return;
1281         case (APPLY_SHEAR | APPLY_SCALE):
1282             m02 = tx * m00 + ty * m01;
1283             m12 = tx * m10 + ty * m11;
1284             if (m02 != 0.0 || m12 != 0.0) {
1285                 state = APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE;
1286                 type |= TYPE_TRANSLATION;
1287             }
1288             return;
1289         case (APPLY_SHEAR | APPLY_TRANSLATE):
1290             m02 = ty * m01 + m02;
1291             m12 = tx * m10 + m12;
1292             if (m02 == 0.0 && m12 == 0.0) {
1293                 state = APPLY_SHEAR;
1294                 if (type != TYPE_UNKNOWN) {
1295                     type -= TYPE_TRANSLATION;
1296                 }
1297             }
1298             return;
1299         case (APPLY_SHEAR):
1300             m02 = ty * m01;
1301             m12 = tx * m10;
1302             if (m02 != 0.0 || m12 != 0.0) {
1303                 state = APPLY_SHEAR | APPLY_TRANSLATE;
1304                 type |= TYPE_TRANSLATION;
1305             }
1306             return;
1307         case (APPLY_SCALE | APPLY_TRANSLATE):
1308             m02 = tx * m00 + m02;
1309             m12 = ty * m11 + m12;
1310             if (m02 == 0.0 && m12 == 0.0) {
1311                 state = APPLY_SCALE;
1312                 if (type != TYPE_UNKNOWN) {
1313                     type -= TYPE_TRANSLATION;
1314                 }
1315             }
1316             return;
1317         case (APPLY_SCALE):
1318             m02 = tx * m00;
1319             m12 = ty * m11;
1320             if (m02 != 0.0 || m12 != 0.0) {
1321                 state = APPLY_SCALE | APPLY_TRANSLATE;
1322                 type |= TYPE_TRANSLATION;
1323             }
1324             return;
1325         case (APPLY_TRANSLATE):
1326             m02 = tx + m02;
1327             m12 = ty + m12;
1328             if (m02 == 0.0 && m12 == 0.0) {
1329                 state = APPLY_IDENTITY;
1330                 type = TYPE_IDENTITY;
1331             }
1332             return;
1333         case (APPLY_IDENTITY):
1334             m02 = tx;
1335             m12 = ty;
1336             if (tx != 0.0 || ty != 0.0) {
1337                 state = APPLY_TRANSLATE;
1338                 type = TYPE_TRANSLATION;
1339             }
1340             return;
1341         }
1342     }
1343 
1344     // Utility methods to optimize rotate methods.
1345     // These tables translate the flags during predictable quadrant
1346     // rotations where the shear and scale values are swapped and negated.
1347     private static final int rot90conversion[] = {
1348         /* IDENTITY => */        APPLY_SHEAR,
1349         /* TRANSLATE (TR) => */  APPLY_SHEAR | APPLY_TRANSLATE,
1350         /* SCALE (SC) => */      APPLY_SHEAR,
1351         /* SC | TR => */         APPLY_SHEAR | APPLY_TRANSLATE,
1352         /* SHEAR (SH) => */      APPLY_SCALE,
1353         /* SH | TR => */         APPLY_SCALE | APPLY_TRANSLATE,
1354         /* SH | SC => */         APPLY_SHEAR | APPLY_SCALE,
1355         /* SH | SC | TR => */    APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE,
1356     };
1357     private final void rotate90() {
1358         double M0 = m00;
1359         m00 = m01;
1360         m01 = -M0;
1361         M0 = m10;
1362         m10 = m11;
1363         m11 = -M0;
1364         int state = rot90conversion[this.state];
1365         if ((state & (APPLY_SHEAR | APPLY_SCALE)) == APPLY_SCALE &&
1366             m00 == 1.0 && m11 == 1.0)
1367         {
1368             state -= APPLY_SCALE;
1369         }
1370         this.state = state;
1371         type = TYPE_UNKNOWN;
1372     }
1373     private final void rotate180() {
1374         m00 = -m00;
1375         m11 = -m11;
1376         int state = this.state;
1377         if ((state & (APPLY_SHEAR)) != 0) {
1378             // If there was a shear, then this rotation has no
1379             // effect on the state.
1380             m01 = -m01;
1381             m10 = -m10;
1382         } else {
1383             // No shear means the SCALE state may toggle when
1384             // m00 and m11 are negated.
1385             if (m00 == 1.0 && m11 == 1.0) {
1386                 this.state = state & ~APPLY_SCALE;
1387             } else {
1388                 this.state = state | APPLY_SCALE;
1389             }
1390         }
1391         type = TYPE_UNKNOWN;
1392     }
1393     private final void rotate270() {
1394         double M0 = m00;
1395         m00 = -m01;
1396         m01 = M0;
1397         M0 = m10;
1398         m10 = -m11;
1399         m11 = M0;
1400         int state = rot90conversion[this.state];
1401         if ((state & (APPLY_SHEAR | APPLY_SCALE)) == APPLY_SCALE &&
1402             m00 == 1.0 && m11 == 1.0)
1403         {
1404             state -= APPLY_SCALE;
1405         }
1406         this.state = state;
1407         type = TYPE_UNKNOWN;
1408     }
1409 
1410     /**
1411      * Concatenates this transform with a rotation transformation.
1412      * This is equivalent to calling concatenate(R), where R is an
1413      * {@code AffineTransform} represented by the following matrix:
1414      * <pre>
1415      *          [   cos(theta)    -sin(theta)    0   ]
1416      *          [   sin(theta)     cos(theta)    0   ]
1417      *          [       0              0         1   ]
1418      * </pre>
1419      * Rotating by a positive angle theta rotates points on the positive
1420      * X axis toward the positive Y axis.
1421      * Note also the discussion of
1422      * <a href="#quadrantapproximation">Handling 90-Degree Rotations</a>
1423      * above.
1424      * @param theta the angle of rotation measured in radians
1425      * @since 1.2
1426      */
1427     public void rotate(double theta) {
1428         double sin = Math.sin(theta);
1429         if (sin == 1.0) {
1430             rotate90();
1431         } else if (sin == -1.0) {
1432             rotate270();
1433         } else {
1434             double cos = Math.cos(theta);
1435             if (cos == -1.0) {
1436                 rotate180();
1437             } else if (cos != 1.0) {
1438                 double M0, M1;
1439                 M0 = m00;
1440                 M1 = m01;
1441                 m00 =  cos * M0 + sin * M1;
1442                 m01 = -sin * M0 + cos * M1;
1443                 M0 = m10;
1444                 M1 = m11;
1445                 m10 =  cos * M0 + sin * M1;
1446                 m11 = -sin * M0 + cos * M1;
1447                 updateState();
1448             }
1449         }
1450     }
1451 
1452     /**
1453      * Concatenates this transform with a transform that rotates
1454      * coordinates around an anchor point.
1455      * This operation is equivalent to translating the coordinates so
1456      * that the anchor point is at the origin (S1), then rotating them
1457      * about the new origin (S2), and finally translating so that the
1458      * intermediate origin is restored to the coordinates of the original
1459      * anchor point (S3).
1460      * <p>
1461      * This operation is equivalent to the following sequence of calls:
1462      * <pre>
1463      *     translate(anchorx, anchory);      // S3: final translation
1464      *     rotate(theta);                    // S2: rotate around anchor
1465      *     translate(-anchorx, -anchory);    // S1: translate anchor to origin
1466      * </pre>
1467      * Rotating by a positive angle theta rotates points on the positive
1468      * X axis toward the positive Y axis.
1469      * Note also the discussion of
1470      * <a href="#quadrantapproximation">Handling 90-Degree Rotations</a>
1471      * above.
1472      *
1473      * @param theta the angle of rotation measured in radians
1474      * @param anchorx the X coordinate of the rotation anchor point
1475      * @param anchory the Y coordinate of the rotation anchor point
1476      * @since 1.2
1477      */
1478     public void rotate(double theta, double anchorx, double anchory) {
1479         // REMIND: Simple for now - optimize later
1480         translate(anchorx, anchory);
1481         rotate(theta);
1482         translate(-anchorx, -anchory);
1483     }
1484 
1485     /**
1486      * Concatenates this transform with a transform that rotates
1487      * coordinates according to a rotation vector.
1488      * All coordinates rotate about the origin by the same amount.
1489      * The amount of rotation is such that coordinates along the former
1490      * positive X axis will subsequently align with the vector pointing
1491      * from the origin to the specified vector coordinates.
1492      * If both {@code vecx} and {@code vecy} are 0.0,
1493      * no additional rotation is added to this transform.
1494      * This operation is equivalent to calling:
1495      * <pre>
1496      *          rotate(Math.atan2(vecy, vecx));
1497      * </pre>
1498      *
1499      * @param vecx the X coordinate of the rotation vector
1500      * @param vecy the Y coordinate of the rotation vector
1501      * @since 1.6
1502      */
1503     public void rotate(double vecx, double vecy) {
1504         if (vecy == 0.0) {
1505             if (vecx < 0.0) {
1506                 rotate180();
1507             }
1508             // If vecx > 0.0 - no rotation
1509             // If vecx == 0.0 - undefined rotation - treat as no rotation
1510         } else if (vecx == 0.0) {
1511             if (vecy > 0.0) {
1512                 rotate90();
1513             } else {  // vecy must be < 0.0
1514                 rotate270();
1515             }
1516         } else {
1517             double len = Math.sqrt(vecx * vecx + vecy * vecy);
1518             double sin = vecy / len;
1519             double cos = vecx / len;
1520             double M0, M1;
1521             M0 = m00;
1522             M1 = m01;
1523             m00 =  cos * M0 + sin * M1;
1524             m01 = -sin * M0 + cos * M1;
1525             M0 = m10;
1526             M1 = m11;
1527             m10 =  cos * M0 + sin * M1;
1528             m11 = -sin * M0 + cos * M1;
1529             updateState();
1530         }
1531     }
1532 
1533     /**
1534      * Concatenates this transform with a transform that rotates
1535      * coordinates around an anchor point according to a rotation
1536      * vector.
1537      * All coordinates rotate about the specified anchor coordinates
1538      * by the same amount.
1539      * The amount of rotation is such that coordinates along the former
1540      * positive X axis will subsequently align with the vector pointing
1541      * from the origin to the specified vector coordinates.
1542      * If both {@code vecx} and {@code vecy} are 0.0,
1543      * the transform is not modified in any way.
1544      * This method is equivalent to calling:
1545      * <pre>
1546      *     rotate(Math.atan2(vecy, vecx), anchorx, anchory);
1547      * </pre>
1548      *
1549      * @param vecx the X coordinate of the rotation vector
1550      * @param vecy the Y coordinate of the rotation vector
1551      * @param anchorx the X coordinate of the rotation anchor point
1552      * @param anchory the Y coordinate of the rotation anchor point
1553      * @since 1.6
1554      */
1555     public void rotate(double vecx, double vecy,
1556                        double anchorx, double anchory)
1557     {
1558         // REMIND: Simple for now - optimize later
1559         translate(anchorx, anchory);
1560         rotate(vecx, vecy);
1561         translate(-anchorx, -anchory);
1562     }
1563 
1564     /**
1565      * Concatenates this transform with a transform that rotates
1566      * coordinates by the specified number of quadrants.
1567      * This is equivalent to calling:
1568      * <pre>
1569      *     rotate(numquadrants * Math.PI / 2.0);
1570      * </pre>
1571      * Rotating by a positive number of quadrants rotates points on
1572      * the positive X axis toward the positive Y axis.
1573      * @param numquadrants the number of 90 degree arcs to rotate by
1574      * @since 1.6
1575      */
1576     public void quadrantRotate(int numquadrants) {
1577         switch (numquadrants & 3) {
1578         case 0:
1579             break;
1580         case 1:
1581             rotate90();
1582             break;
1583         case 2:
1584             rotate180();
1585             break;
1586         case 3:
1587             rotate270();
1588             break;
1589         }
1590     }
1591 
1592     /**
1593      * Concatenates this transform with a transform that rotates
1594      * coordinates by the specified number of quadrants around
1595      * the specified anchor point.
1596      * This method is equivalent to calling:
1597      * <pre>
1598      *     rotate(numquadrants * Math.PI / 2.0, anchorx, anchory);
1599      * </pre>
1600      * Rotating by a positive number of quadrants rotates points on
1601      * the positive X axis toward the positive Y axis.
1602      *
1603      * @param numquadrants the number of 90 degree arcs to rotate by
1604      * @param anchorx the X coordinate of the rotation anchor point
1605      * @param anchory the Y coordinate of the rotation anchor point
1606      * @since 1.6
1607      */
1608     public void quadrantRotate(int numquadrants,
1609                                double anchorx, double anchory)
1610     {
1611         switch (numquadrants & 3) {
1612         case 0:
1613             return;
1614         case 1:
1615             m02 += anchorx * (m00 - m01) + anchory * (m01 + m00);
1616             m12 += anchorx * (m10 - m11) + anchory * (m11 + m10);
1617             rotate90();
1618             break;
1619         case 2:
1620             m02 += anchorx * (m00 + m00) + anchory * (m01 + m01);
1621             m12 += anchorx * (m10 + m10) + anchory * (m11 + m11);
1622             rotate180();
1623             break;
1624         case 3:
1625             m02 += anchorx * (m00 + m01) + anchory * (m01 - m00);
1626             m12 += anchorx * (m10 + m11) + anchory * (m11 - m10);
1627             rotate270();
1628             break;
1629         }
1630         if (m02 == 0.0 && m12 == 0.0) {
1631             state &= ~APPLY_TRANSLATE;
1632         } else {
1633             state |= APPLY_TRANSLATE;
1634         }
1635     }
1636 
1637     /**
1638      * Concatenates this transform with a scaling transformation.
1639      * This is equivalent to calling concatenate(S), where S is an
1640      * {@code AffineTransform} represented by the following matrix:
1641      * <pre>
1642      *          [   sx   0    0   ]
1643      *          [   0    sy   0   ]
1644      *          [   0    0    1   ]
1645      * </pre>
1646      * @param sx the factor by which coordinates are scaled along the
1647      * X axis direction
1648      * @param sy the factor by which coordinates are scaled along the
1649      * Y axis direction
1650      * @since 1.2
1651      */
1652     @SuppressWarnings("fallthrough")
1653     public void scale(double sx, double sy) {
1654         int state = this.state;
1655         switch (state) {
1656         default:
1657             stateError();
1658             /* NOTREACHED */
1659         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
1660         case (APPLY_SHEAR | APPLY_SCALE):
1661             m00 *= sx;
1662             m11 *= sy;
1663             /* NOBREAK */
1664         case (APPLY_SHEAR | APPLY_TRANSLATE):
1665         case (APPLY_SHEAR):
1666             m01 *= sy;
1667             m10 *= sx;
1668             if (m01 == 0 && m10 == 0) {
1669                 state &= APPLY_TRANSLATE;
1670                 if (m00 == 1.0 && m11 == 1.0) {
1671                     this.type = (state == APPLY_IDENTITY
1672                                  ? TYPE_IDENTITY
1673                                  : TYPE_TRANSLATION);
1674                 } else {
1675                     state |= APPLY_SCALE;
1676                     this.type = TYPE_UNKNOWN;
1677                 }
1678                 this.state = state;
1679             }
1680             return;
1681         case (APPLY_SCALE | APPLY_TRANSLATE):
1682         case (APPLY_SCALE):
1683             m00 *= sx;
1684             m11 *= sy;
1685             if (m00 == 1.0 && m11 == 1.0) {
1686                 this.state = (state &= APPLY_TRANSLATE);
1687                 this.type = (state == APPLY_IDENTITY
1688                              ? TYPE_IDENTITY
1689                              : TYPE_TRANSLATION);
1690             } else {
1691                 this.type = TYPE_UNKNOWN;
1692             }
1693             return;
1694         case (APPLY_TRANSLATE):
1695         case (APPLY_IDENTITY):
1696             m00 = sx;
1697             m11 = sy;
1698             if (sx != 1.0 || sy != 1.0) {
1699                 this.state = state | APPLY_SCALE;
1700                 this.type = TYPE_UNKNOWN;
1701             }
1702             return;
1703         }
1704     }
1705 
1706     /**
1707      * Concatenates this transform with a shearing transformation.
1708      * This is equivalent to calling concatenate(SH), where SH is an
1709      * {@code AffineTransform} represented by the following matrix:
1710      * <pre>
1711      *          [   1   shx   0   ]
1712      *          [  shy   1    0   ]
1713      *          [   0    0    1   ]
1714      * </pre>
1715      * @param shx the multiplier by which coordinates are shifted in the
1716      * direction of the positive X axis as a factor of their Y coordinate
1717      * @param shy the multiplier by which coordinates are shifted in the
1718      * direction of the positive Y axis as a factor of their X coordinate
1719      * @since 1.2
1720      */
1721     public void shear(double shx, double shy) {
1722         int state = this.state;
1723         switch (state) {
1724         default:
1725             stateError();
1726             /* NOTREACHED */
1727             return;
1728         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
1729         case (APPLY_SHEAR | APPLY_SCALE):
1730             double M0, M1;
1731             M0 = m00;
1732             M1 = m01;
1733             m00 = M0 + M1 * shy;
1734             m01 = M0 * shx + M1;
1735 
1736             M0 = m10;
1737             M1 = m11;
1738             m10 = M0 + M1 * shy;
1739             m11 = M0 * shx + M1;
1740             updateState();
1741             return;
1742         case (APPLY_SHEAR | APPLY_TRANSLATE):
1743         case (APPLY_SHEAR):
1744             m00 = m01 * shy;
1745             m11 = m10 * shx;
1746             if (m00 != 0.0 || m11 != 0.0) {
1747                 this.state = state | APPLY_SCALE;
1748             }
1749             this.type = TYPE_UNKNOWN;
1750             return;
1751         case (APPLY_SCALE | APPLY_TRANSLATE):
1752         case (APPLY_SCALE):
1753             m01 = m00 * shx;
1754             m10 = m11 * shy;
1755             if (m01 != 0.0 || m10 != 0.0) {
1756                 this.state = state | APPLY_SHEAR;
1757             }
1758             this.type = TYPE_UNKNOWN;
1759             return;
1760         case (APPLY_TRANSLATE):
1761         case (APPLY_IDENTITY):
1762             m01 = shx;
1763             m10 = shy;
1764             if (m01 != 0.0 || m10 != 0.0) {
1765                 this.state = state | APPLY_SCALE | APPLY_SHEAR;
1766                 this.type = TYPE_UNKNOWN;
1767             }
1768             return;
1769         }
1770     }
1771 
1772     /**
1773      * Resets this transform to the Identity transform.
1774      * @since 1.2
1775      */
1776     public void setToIdentity() {
1777         m00 = m11 = 1.0;
1778         m10 = m01 = m02 = m12 = 0.0;
1779         state = APPLY_IDENTITY;
1780         type = TYPE_IDENTITY;
1781     }
1782 
1783     /**
1784      * Sets this transform to a translation transformation.
1785      * The matrix representing this transform becomes:
1786      * <pre>
1787      *          [   1    0    tx  ]
1788      *          [   0    1    ty  ]
1789      *          [   0    0    1   ]
1790      * </pre>
1791      * @param tx the distance by which coordinates are translated in the
1792      * X axis direction
1793      * @param ty the distance by which coordinates are translated in the
1794      * Y axis direction
1795      * @since 1.2
1796      */
1797     public void setToTranslation(double tx, double ty) {
1798         m00 = 1.0;
1799         m10 = 0.0;
1800         m01 = 0.0;
1801         m11 = 1.0;
1802         m02 = tx;
1803         m12 = ty;
1804         if (tx != 0.0 || ty != 0.0) {
1805             state = APPLY_TRANSLATE;
1806             type = TYPE_TRANSLATION;
1807         } else {
1808             state = APPLY_IDENTITY;
1809             type = TYPE_IDENTITY;
1810         }
1811     }
1812 
1813     /**
1814      * Sets this transform to a rotation transformation.
1815      * The matrix representing this transform becomes:
1816      * <pre>
1817      *          [   cos(theta)    -sin(theta)    0   ]
1818      *          [   sin(theta)     cos(theta)    0   ]
1819      *          [       0              0         1   ]
1820      * </pre>
1821      * Rotating by a positive angle theta rotates points on the positive
1822      * X axis toward the positive Y axis.
1823      * Note also the discussion of
1824      * <a href="#quadrantapproximation">Handling 90-Degree Rotations</a>
1825      * above.
1826      * @param theta the angle of rotation measured in radians
1827      * @since 1.2
1828      */
1829     public void setToRotation(double theta) {
1830         double sin = Math.sin(theta);
1831         double cos;
1832         if (sin == 1.0 || sin == -1.0) {
1833             cos = 0.0;
1834             state = APPLY_SHEAR;
1835             type = TYPE_QUADRANT_ROTATION;
1836         } else {
1837             cos = Math.cos(theta);
1838             if (cos == -1.0) {
1839                 sin = 0.0;
1840                 state = APPLY_SCALE;
1841                 type = TYPE_QUADRANT_ROTATION;
1842             } else if (cos == 1.0) {
1843                 sin = 0.0;
1844                 state = APPLY_IDENTITY;
1845                 type = TYPE_IDENTITY;
1846             } else {
1847                 state = APPLY_SHEAR | APPLY_SCALE;
1848                 type = TYPE_GENERAL_ROTATION;
1849             }
1850         }
1851         m00 =  cos;
1852         m10 =  sin;
1853         m01 = -sin;
1854         m11 =  cos;
1855         m02 =  0.0;
1856         m12 =  0.0;
1857     }
1858 
1859     /**
1860      * Sets this transform to a translated rotation transformation.
1861      * This operation is equivalent to translating the coordinates so
1862      * that the anchor point is at the origin (S1), then rotating them
1863      * about the new origin (S2), and finally translating so that the
1864      * intermediate origin is restored to the coordinates of the original
1865      * anchor point (S3).
1866      * <p>
1867      * This operation is equivalent to the following sequence of calls:
1868      * <pre>
1869      *     setToTranslation(anchorx, anchory); // S3: final translation
1870      *     rotate(theta);                      // S2: rotate around anchor
1871      *     translate(-anchorx, -anchory);      // S1: translate anchor to origin
1872      * </pre>
1873      * The matrix representing this transform becomes:
1874      * <pre>
1875      *          [   cos(theta)    -sin(theta)    x-x*cos+y*sin  ]
1876      *          [   sin(theta)     cos(theta)    y-x*sin-y*cos  ]
1877      *          [       0              0               1        ]
1878      * </pre>
1879      * Rotating by a positive angle theta rotates points on the positive
1880      * X axis toward the positive Y axis.
1881      * Note also the discussion of
1882      * <a href="#quadrantapproximation">Handling 90-Degree Rotations</a>
1883      * above.
1884      *
1885      * @param theta the angle of rotation measured in radians
1886      * @param anchorx the X coordinate of the rotation anchor point
1887      * @param anchory the Y coordinate of the rotation anchor point
1888      * @since 1.2
1889      */
1890     public void setToRotation(double theta, double anchorx, double anchory) {
1891         setToRotation(theta);
1892         double sin = m10;
1893         double oneMinusCos = 1.0 - m00;
1894         m02 = anchorx * oneMinusCos + anchory * sin;
1895         m12 = anchory * oneMinusCos - anchorx * sin;
1896         if (m02 != 0.0 || m12 != 0.0) {
1897             state |= APPLY_TRANSLATE;
1898             type |= TYPE_TRANSLATION;
1899         }
1900     }
1901 
1902     /**
1903      * Sets this transform to a rotation transformation that rotates
1904      * coordinates according to a rotation vector.
1905      * All coordinates rotate about the origin by the same amount.
1906      * The amount of rotation is such that coordinates along the former
1907      * positive X axis will subsequently align with the vector pointing
1908      * from the origin to the specified vector coordinates.
1909      * If both {@code vecx} and {@code vecy} are 0.0,
1910      * the transform is set to an identity transform.
1911      * This operation is equivalent to calling:
1912      * <pre>
1913      *     setToRotation(Math.atan2(vecy, vecx));
1914      * </pre>
1915      *
1916      * @param vecx the X coordinate of the rotation vector
1917      * @param vecy the Y coordinate of the rotation vector
1918      * @since 1.6
1919      */
1920     public void setToRotation(double vecx, double vecy) {
1921         double sin, cos;
1922         if (vecy == 0) {
1923             sin = 0.0;
1924             if (vecx < 0.0) {
1925                 cos = -1.0;
1926                 state = APPLY_SCALE;
1927                 type = TYPE_QUADRANT_ROTATION;
1928             } else {
1929                 cos = 1.0;
1930                 state = APPLY_IDENTITY;
1931                 type = TYPE_IDENTITY;
1932             }
1933         } else if (vecx == 0) {
1934             cos = 0.0;
1935             sin = (vecy > 0.0) ? 1.0 : -1.0;
1936             state = APPLY_SHEAR;
1937             type = TYPE_QUADRANT_ROTATION;
1938         } else {
1939             double len = Math.sqrt(vecx * vecx + vecy * vecy);
1940             cos = vecx / len;
1941             sin = vecy / len;
1942             state = APPLY_SHEAR | APPLY_SCALE;
1943             type = TYPE_GENERAL_ROTATION;
1944         }
1945         m00 =  cos;
1946         m10 =  sin;
1947         m01 = -sin;
1948         m11 =  cos;
1949         m02 =  0.0;
1950         m12 =  0.0;
1951     }
1952 
1953     /**
1954      * Sets this transform to a rotation transformation that rotates
1955      * coordinates around an anchor point according to a rotation
1956      * vector.
1957      * All coordinates rotate about the specified anchor coordinates
1958      * by the same amount.
1959      * The amount of rotation is such that coordinates along the former
1960      * positive X axis will subsequently align with the vector pointing
1961      * from the origin to the specified vector coordinates.
1962      * If both {@code vecx} and {@code vecy} are 0.0,
1963      * the transform is set to an identity transform.
1964      * This operation is equivalent to calling:
1965      * <pre>
1966      *     setToTranslation(Math.atan2(vecy, vecx), anchorx, anchory);
1967      * </pre>
1968      *
1969      * @param vecx the X coordinate of the rotation vector
1970      * @param vecy the Y coordinate of the rotation vector
1971      * @param anchorx the X coordinate of the rotation anchor point
1972      * @param anchory the Y coordinate of the rotation anchor point
1973      * @since 1.6
1974      */
1975     public void setToRotation(double vecx, double vecy,
1976                               double anchorx, double anchory)
1977     {
1978         setToRotation(vecx, vecy);
1979         double sin = m10;
1980         double oneMinusCos = 1.0 - m00;
1981         m02 = anchorx * oneMinusCos + anchory * sin;
1982         m12 = anchory * oneMinusCos - anchorx * sin;
1983         if (m02 != 0.0 || m12 != 0.0) {
1984             state |= APPLY_TRANSLATE;
1985             type |= TYPE_TRANSLATION;
1986         }
1987     }
1988 
1989     /**
1990      * Sets this transform to a rotation transformation that rotates
1991      * coordinates by the specified number of quadrants.
1992      * This operation is equivalent to calling:
1993      * <pre>
1994      *     setToRotation(numquadrants * Math.PI / 2.0);
1995      * </pre>
1996      * Rotating by a positive number of quadrants rotates points on
1997      * the positive X axis toward the positive Y axis.
1998      * @param numquadrants the number of 90 degree arcs to rotate by
1999      * @since 1.6
2000      */
2001     public void setToQuadrantRotation(int numquadrants) {
2002         switch (numquadrants & 3) {
2003         case 0:
2004             m00 =  1.0;
2005             m10 =  0.0;
2006             m01 =  0.0;
2007             m11 =  1.0;
2008             m02 =  0.0;
2009             m12 =  0.0;
2010             state = APPLY_IDENTITY;
2011             type = TYPE_IDENTITY;
2012             break;
2013         case 1:
2014             m00 =  0.0;
2015             m10 =  1.0;
2016             m01 = -1.0;
2017             m11 =  0.0;
2018             m02 =  0.0;
2019             m12 =  0.0;
2020             state = APPLY_SHEAR;
2021             type = TYPE_QUADRANT_ROTATION;
2022             break;
2023         case 2:
2024             m00 = -1.0;
2025             m10 =  0.0;
2026             m01 =  0.0;
2027             m11 = -1.0;
2028             m02 =  0.0;
2029             m12 =  0.0;
2030             state = APPLY_SCALE;
2031             type = TYPE_QUADRANT_ROTATION;
2032             break;
2033         case 3:
2034             m00 =  0.0;
2035             m10 = -1.0;
2036             m01 =  1.0;
2037             m11 =  0.0;
2038             m02 =  0.0;
2039             m12 =  0.0;
2040             state = APPLY_SHEAR;
2041             type = TYPE_QUADRANT_ROTATION;
2042             break;
2043         }
2044     }
2045 
2046     /**
2047      * Sets this transform to a translated rotation transformation
2048      * that rotates coordinates by the specified number of quadrants
2049      * around the specified anchor point.
2050      * This operation is equivalent to calling:
2051      * <pre>
2052      *     setToRotation(numquadrants * Math.PI / 2.0, anchorx, anchory);
2053      * </pre>
2054      * Rotating by a positive number of quadrants rotates points on
2055      * the positive X axis toward the positive Y axis.
2056      *
2057      * @param numquadrants the number of 90 degree arcs to rotate by
2058      * @param anchorx the X coordinate of the rotation anchor point
2059      * @param anchory the Y coordinate of the rotation anchor point
2060      * @since 1.6
2061      */
2062     public void setToQuadrantRotation(int numquadrants,
2063                                       double anchorx, double anchory)
2064     {
2065         switch (numquadrants & 3) {
2066         case 0:
2067             m00 =  1.0;
2068             m10 =  0.0;
2069             m01 =  0.0;
2070             m11 =  1.0;
2071             m02 =  0.0;
2072             m12 =  0.0;
2073             state = APPLY_IDENTITY;
2074             type = TYPE_IDENTITY;
2075             break;
2076         case 1:
2077             m00 =  0.0;
2078             m10 =  1.0;
2079             m01 = -1.0;
2080             m11 =  0.0;
2081             m02 =  anchorx + anchory;
2082             m12 =  anchory - anchorx;
2083             if (m02 == 0.0 && m12 == 0.0) {
2084                 state = APPLY_SHEAR;
2085                 type = TYPE_QUADRANT_ROTATION;
2086             } else {
2087                 state = APPLY_SHEAR | APPLY_TRANSLATE;
2088                 type = TYPE_QUADRANT_ROTATION | TYPE_TRANSLATION;
2089             }
2090             break;
2091         case 2:
2092             m00 = -1.0;
2093             m10 =  0.0;
2094             m01 =  0.0;
2095             m11 = -1.0;
2096             m02 =  anchorx + anchorx;
2097             m12 =  anchory + anchory;
2098             if (m02 == 0.0 && m12 == 0.0) {
2099                 state = APPLY_SCALE;
2100                 type = TYPE_QUADRANT_ROTATION;
2101             } else {
2102                 state = APPLY_SCALE | APPLY_TRANSLATE;
2103                 type = TYPE_QUADRANT_ROTATION | TYPE_TRANSLATION;
2104             }
2105             break;
2106         case 3:
2107             m00 =  0.0;
2108             m10 = -1.0;
2109             m01 =  1.0;
2110             m11 =  0.0;
2111             m02 =  anchorx - anchory;
2112             m12 =  anchory + anchorx;
2113             if (m02 == 0.0 && m12 == 0.0) {
2114                 state = APPLY_SHEAR;
2115                 type = TYPE_QUADRANT_ROTATION;
2116             } else {
2117                 state = APPLY_SHEAR | APPLY_TRANSLATE;
2118                 type = TYPE_QUADRANT_ROTATION | TYPE_TRANSLATION;
2119             }
2120             break;
2121         }
2122     }
2123 
2124     /**
2125      * Sets this transform to a scaling transformation.
2126      * The matrix representing this transform becomes:
2127      * <pre>
2128      *          [   sx   0    0   ]
2129      *          [   0    sy   0   ]
2130      *          [   0    0    1   ]
2131      * </pre>
2132      * @param sx the factor by which coordinates are scaled along the
2133      * X axis direction
2134      * @param sy the factor by which coordinates are scaled along the
2135      * Y axis direction
2136      * @since 1.2
2137      */
2138     public void setToScale(double sx, double sy) {
2139         m00 = sx;
2140         m10 = 0.0;
2141         m01 = 0.0;
2142         m11 = sy;
2143         m02 = 0.0;
2144         m12 = 0.0;
2145         if (sx != 1.0 || sy != 1.0) {
2146             state = APPLY_SCALE;
2147             type = TYPE_UNKNOWN;
2148         } else {
2149             state = APPLY_IDENTITY;
2150             type = TYPE_IDENTITY;
2151         }
2152     }
2153 
2154     /**
2155      * Sets this transform to a shearing transformation.
2156      * The matrix representing this transform becomes:
2157      * <pre>
2158      *          [   1   shx   0   ]
2159      *          [  shy   1    0   ]
2160      *          [   0    0    1   ]
2161      * </pre>
2162      * @param shx the multiplier by which coordinates are shifted in the
2163      * direction of the positive X axis as a factor of their Y coordinate
2164      * @param shy the multiplier by which coordinates are shifted in the
2165      * direction of the positive Y axis as a factor of their X coordinate
2166      * @since 1.2
2167      */
2168     public void setToShear(double shx, double shy) {
2169         m00 = 1.0;
2170         m01 = shx;
2171         m10 = shy;
2172         m11 = 1.0;
2173         m02 = 0.0;
2174         m12 = 0.0;
2175         if (shx != 0.0 || shy != 0.0) {
2176             state = (APPLY_SHEAR | APPLY_SCALE);
2177             type = TYPE_UNKNOWN;
2178         } else {
2179             state = APPLY_IDENTITY;
2180             type = TYPE_IDENTITY;
2181         }
2182     }
2183 
2184     /**
2185      * Sets this transform to a copy of the transform in the specified
2186      * {@code AffineTransform} object.
2187      * @param Tx the {@code AffineTransform} object from which to
2188      * copy the transform
2189      * @since 1.2
2190      */
2191     public void setTransform(AffineTransform Tx) {
2192         this.m00 = Tx.m00;
2193         this.m10 = Tx.m10;
2194         this.m01 = Tx.m01;
2195         this.m11 = Tx.m11;
2196         this.m02 = Tx.m02;
2197         this.m12 = Tx.m12;
2198         this.state = Tx.state;
2199         this.type = Tx.type;
2200     }
2201 
2202     /**
2203      * Sets this transform to the matrix specified by the 6
2204      * double precision values.
2205      *
2206      * @param m00 the X coordinate scaling element of the 3x3 matrix
2207      * @param m10 the Y coordinate shearing element of the 3x3 matrix
2208      * @param m01 the X coordinate shearing element of the 3x3 matrix
2209      * @param m11 the Y coordinate scaling element of the 3x3 matrix
2210      * @param m02 the X coordinate translation element of the 3x3 matrix
2211      * @param m12 the Y coordinate translation element of the 3x3 matrix
2212      * @since 1.2
2213      */
2214     public void setTransform(double m00, double m10,
2215                              double m01, double m11,
2216                              double m02, double m12) {
2217         this.m00 = m00;
2218         this.m10 = m10;
2219         this.m01 = m01;
2220         this.m11 = m11;
2221         this.m02 = m02;
2222         this.m12 = m12;
2223         updateState();
2224     }
2225 
2226     /**
2227      * Concatenates an {@code AffineTransform Tx} to
2228      * this {@code AffineTransform} Cx in the most commonly useful
2229      * way to provide a new user space
2230      * that is mapped to the former user space by {@code Tx}.
2231      * Cx is updated to perform the combined transformation.
2232      * Transforming a point p by the updated transform Cx' is
2233      * equivalent to first transforming p by {@code Tx} and then
2234      * transforming the result by the original transform Cx like this:
2235      * Cx'(p) = Cx(Tx(p))
2236      * In matrix notation, if this transform Cx is
2237      * represented by the matrix [this] and {@code Tx} is represented
2238      * by the matrix [Tx] then this method does the following:
2239      * <pre>
2240      *          [this] = [this] x [Tx]
2241      * </pre>
2242      * @param Tx the {@code AffineTransform} object to be
2243      * concatenated with this {@code AffineTransform} object.
2244      * @see #preConcatenate
2245      * @since 1.2
2246      */
2247     @SuppressWarnings("fallthrough")
2248     public void concatenate(AffineTransform Tx) {
2249         double M0, M1;
2250         double T00, T01, T10, T11;
2251         double T02, T12;
2252         int mystate = state;
2253         int txstate = Tx.state;
2254         switch ((txstate << HI_SHIFT) | mystate) {
2255 
2256             /* ---------- Tx == IDENTITY cases ---------- */
2257         case (HI_IDENTITY | APPLY_IDENTITY):
2258         case (HI_IDENTITY | APPLY_TRANSLATE):
2259         case (HI_IDENTITY | APPLY_SCALE):
2260         case (HI_IDENTITY | APPLY_SCALE | APPLY_TRANSLATE):
2261         case (HI_IDENTITY | APPLY_SHEAR):
2262         case (HI_IDENTITY | APPLY_SHEAR | APPLY_TRANSLATE):
2263         case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE):
2264         case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2265             return;
2266 
2267             /* ---------- this == IDENTITY cases ---------- */
2268         case (HI_SHEAR | HI_SCALE | HI_TRANSLATE | APPLY_IDENTITY):
2269             m01 = Tx.m01;
2270             m10 = Tx.m10;
2271             /* NOBREAK */
2272         case (HI_SCALE | HI_TRANSLATE | APPLY_IDENTITY):
2273             m00 = Tx.m00;
2274             m11 = Tx.m11;
2275             /* NOBREAK */
2276         case (HI_TRANSLATE | APPLY_IDENTITY):
2277             m02 = Tx.m02;
2278             m12 = Tx.m12;
2279             state = txstate;
2280             type = Tx.type;
2281             return;
2282         case (HI_SHEAR | HI_SCALE | APPLY_IDENTITY):
2283             m01 = Tx.m01;
2284             m10 = Tx.m10;
2285             /* NOBREAK */
2286         case (HI_SCALE | APPLY_IDENTITY):
2287             m00 = Tx.m00;
2288             m11 = Tx.m11;
2289             state = txstate;
2290             type = Tx.type;
2291             return;
2292         case (HI_SHEAR | HI_TRANSLATE | APPLY_IDENTITY):
2293             m02 = Tx.m02;
2294             m12 = Tx.m12;
2295             /* NOBREAK */
2296         case (HI_SHEAR | APPLY_IDENTITY):
2297             m01 = Tx.m01;
2298             m10 = Tx.m10;
2299             m00 = m11 = 0.0;
2300             state = txstate;
2301             type = Tx.type;
2302             return;
2303 
2304             /* ---------- Tx == TRANSLATE cases ---------- */
2305         case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2306         case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE):
2307         case (HI_TRANSLATE | APPLY_SHEAR | APPLY_TRANSLATE):
2308         case (HI_TRANSLATE | APPLY_SHEAR):
2309         case (HI_TRANSLATE | APPLY_SCALE | APPLY_TRANSLATE):
2310         case (HI_TRANSLATE | APPLY_SCALE):
2311         case (HI_TRANSLATE | APPLY_TRANSLATE):
2312             translate(Tx.m02, Tx.m12);
2313             return;
2314 
2315             /* ---------- Tx == SCALE cases ---------- */
2316         case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2317         case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE):
2318         case (HI_SCALE | APPLY_SHEAR | APPLY_TRANSLATE):
2319         case (HI_SCALE | APPLY_SHEAR):
2320         case (HI_SCALE | APPLY_SCALE | APPLY_TRANSLATE):
2321         case (HI_SCALE | APPLY_SCALE):
2322         case (HI_SCALE | APPLY_TRANSLATE):
2323             scale(Tx.m00, Tx.m11);
2324             return;
2325 
2326             /* ---------- Tx == SHEAR cases ---------- */
2327         case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2328         case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE):
2329             T01 = Tx.m01; T10 = Tx.m10;
2330             M0 = m00;
2331             m00 = m01 * T10;
2332             m01 = M0 * T01;
2333             M0 = m10;
2334             m10 = m11 * T10;
2335             m11 = M0 * T01;
2336             type = TYPE_UNKNOWN;
2337             return;
2338         case (HI_SHEAR | APPLY_SHEAR | APPLY_TRANSLATE):
2339         case (HI_SHEAR | APPLY_SHEAR):
2340             m00 = m01 * Tx.m10;
2341             m01 = 0.0;
2342             m11 = m10 * Tx.m01;
2343             m10 = 0.0;
2344             state = mystate ^ (APPLY_SHEAR | APPLY_SCALE);
2345             type = TYPE_UNKNOWN;
2346             return;
2347         case (HI_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2348         case (HI_SHEAR | APPLY_SCALE):
2349             m01 = m00 * Tx.m01;
2350             m00 = 0.0;
2351             m10 = m11 * Tx.m10;
2352             m11 = 0.0;
2353             state = mystate ^ (APPLY_SHEAR | APPLY_SCALE);
2354             type = TYPE_UNKNOWN;
2355             return;
2356         case (HI_SHEAR | APPLY_TRANSLATE):
2357             m00 = 0.0;
2358             m01 = Tx.m01;
2359             m10 = Tx.m10;
2360             m11 = 0.0;
2361             state = APPLY_TRANSLATE | APPLY_SHEAR;
2362             type = TYPE_UNKNOWN;
2363             return;
2364         }
2365         // If Tx has more than one attribute, it is not worth optimizing
2366         // all of those cases...
2367         T00 = Tx.m00; T01 = Tx.m01; T02 = Tx.m02;
2368         T10 = Tx.m10; T11 = Tx.m11; T12 = Tx.m12;
2369         switch (mystate) {
2370         default:
2371             stateError();
2372             /* NOTREACHED */
2373         case (APPLY_SHEAR | APPLY_SCALE):
2374             state = mystate | txstate;
2375             /* NOBREAK */
2376         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2377             M0 = m00;
2378             M1 = m01;
2379             m00  = T00 * M0 + T10 * M1;
2380             m01  = T01 * M0 + T11 * M1;
2381             m02 += T02 * M0 + T12 * M1;
2382 
2383             M0 = m10;
2384             M1 = m11;
2385             m10  = T00 * M0 + T10 * M1;
2386             m11  = T01 * M0 + T11 * M1;
2387             m12 += T02 * M0 + T12 * M1;
2388             type = TYPE_UNKNOWN;
2389             return;
2390 
2391         case (APPLY_SHEAR | APPLY_TRANSLATE):
2392         case (APPLY_SHEAR):
2393             M0 = m01;
2394             m00  = T10 * M0;
2395             m01  = T11 * M0;
2396             m02 += T12 * M0;
2397 
2398             M0 = m10;
2399             m10  = T00 * M0;
2400             m11  = T01 * M0;
2401             m12 += T02 * M0;
2402             break;
2403 
2404         case (APPLY_SCALE | APPLY_TRANSLATE):
2405         case (APPLY_SCALE):
2406             M0 = m00;
2407             m00  = T00 * M0;
2408             m01  = T01 * M0;
2409             m02 += T02 * M0;
2410 
2411             M0 = m11;
2412             m10  = T10 * M0;
2413             m11  = T11 * M0;
2414             m12 += T12 * M0;
2415             break;
2416 
2417         case (APPLY_TRANSLATE):
2418             m00  = T00;
2419             m01  = T01;
2420             m02 += T02;
2421 
2422             m10  = T10;
2423             m11  = T11;
2424             m12 += T12;
2425             state = txstate | APPLY_TRANSLATE;
2426             type = TYPE_UNKNOWN;
2427             return;
2428         }
2429         updateState();
2430     }
2431 
2432     /**
2433      * Concatenates an {@code AffineTransform Tx} to
2434      * this {@code AffineTransform} Cx
2435      * in a less commonly used way such that {@code Tx} modifies the
2436      * coordinate transformation relative to the absolute pixel
2437      * space rather than relative to the existing user space.
2438      * Cx is updated to perform the combined transformation.
2439      * Transforming a point p by the updated transform Cx' is
2440      * equivalent to first transforming p by the original transform
2441      * Cx and then transforming the result by
2442      * {@code Tx} like this:
2443      * Cx'(p) = Tx(Cx(p))
2444      * In matrix notation, if this transform Cx
2445      * is represented by the matrix [this] and {@code Tx} is
2446      * represented by the matrix [Tx] then this method does the
2447      * following:
2448      * <pre>
2449      *          [this] = [Tx] x [this]
2450      * </pre>
2451      * @param Tx the {@code AffineTransform} object to be
2452      * concatenated with this {@code AffineTransform} object.
2453      * @see #concatenate
2454      * @since 1.2
2455      */
2456     @SuppressWarnings("fallthrough")
2457     public void preConcatenate(AffineTransform Tx) {
2458         double M0, M1;
2459         double T00, T01, T10, T11;
2460         double T02, T12;
2461         int mystate = state;
2462         int txstate = Tx.state;
2463         switch ((txstate << HI_SHIFT) | mystate) {
2464         case (HI_IDENTITY | APPLY_IDENTITY):
2465         case (HI_IDENTITY | APPLY_TRANSLATE):
2466         case (HI_IDENTITY | APPLY_SCALE):
2467         case (HI_IDENTITY | APPLY_SCALE | APPLY_TRANSLATE):
2468         case (HI_IDENTITY | APPLY_SHEAR):
2469         case (HI_IDENTITY | APPLY_SHEAR | APPLY_TRANSLATE):
2470         case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE):
2471         case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2472             // Tx is IDENTITY...
2473             return;
2474 
2475         case (HI_TRANSLATE | APPLY_IDENTITY):
2476         case (HI_TRANSLATE | APPLY_SCALE):
2477         case (HI_TRANSLATE | APPLY_SHEAR):
2478         case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE):
2479             // Tx is TRANSLATE, this has no TRANSLATE
2480             m02 = Tx.m02;
2481             m12 = Tx.m12;
2482             state = mystate | APPLY_TRANSLATE;
2483             type |= TYPE_TRANSLATION;
2484             return;
2485 
2486         case (HI_TRANSLATE | APPLY_TRANSLATE):
2487         case (HI_TRANSLATE | APPLY_SCALE | APPLY_TRANSLATE):
2488         case (HI_TRANSLATE | APPLY_SHEAR | APPLY_TRANSLATE):
2489         case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2490             // Tx is TRANSLATE, this has one too
2491             m02 = m02 + Tx.m02;
2492             m12 = m12 + Tx.m12;
2493             return;
2494 
2495         case (HI_SCALE | APPLY_TRANSLATE):
2496         case (HI_SCALE | APPLY_IDENTITY):
2497             // Only these two existing states need a new state
2498             state = mystate | APPLY_SCALE;
2499             /* NOBREAK */
2500         case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2501         case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE):
2502         case (HI_SCALE | APPLY_SHEAR | APPLY_TRANSLATE):
2503         case (HI_SCALE | APPLY_SHEAR):
2504         case (HI_SCALE | APPLY_SCALE | APPLY_TRANSLATE):
2505         case (HI_SCALE | APPLY_SCALE):
2506             // Tx is SCALE, this is anything
2507             T00 = Tx.m00;
2508             T11 = Tx.m11;
2509             if ((mystate & APPLY_SHEAR) != 0) {
2510                 m01 = m01 * T00;
2511                 m10 = m10 * T11;
2512                 if ((mystate & APPLY_SCALE) != 0) {
2513                     m00 = m00 * T00;
2514                     m11 = m11 * T11;
2515                 }
2516             } else {
2517                 m00 = m00 * T00;
2518                 m11 = m11 * T11;
2519             }
2520             if ((mystate & APPLY_TRANSLATE) != 0) {
2521                 m02 = m02 * T00;
2522                 m12 = m12 * T11;
2523             }
2524             type = TYPE_UNKNOWN;
2525             return;
2526         case (HI_SHEAR | APPLY_SHEAR | APPLY_TRANSLATE):
2527         case (HI_SHEAR | APPLY_SHEAR):
2528             mystate = mystate | APPLY_SCALE;
2529             /* NOBREAK */
2530         case (HI_SHEAR | APPLY_TRANSLATE):
2531         case (HI_SHEAR | APPLY_IDENTITY):
2532         case (HI_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2533         case (HI_SHEAR | APPLY_SCALE):
2534             state = mystate ^ APPLY_SHEAR;
2535             /* NOBREAK */
2536         case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2537         case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE):
2538             // Tx is SHEAR, this is anything
2539             T01 = Tx.m01;
2540             T10 = Tx.m10;
2541 
2542             M0 = m00;
2543             m00 = m10 * T01;
2544             m10 = M0 * T10;
2545 
2546             M0 = m01;
2547             m01 = m11 * T01;
2548             m11 = M0 * T10;
2549 
2550             M0 = m02;
2551             m02 = m12 * T01;
2552             m12 = M0 * T10;
2553             type = TYPE_UNKNOWN;
2554             return;
2555         }
2556         // If Tx has more than one attribute, it is not worth optimizing
2557         // all of those cases...
2558         T00 = Tx.m00; T01 = Tx.m01; T02 = Tx.m02;
2559         T10 = Tx.m10; T11 = Tx.m11; T12 = Tx.m12;
2560         switch (mystate) {
2561         default:
2562             stateError();
2563             /* NOTREACHED */
2564         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2565             M0 = m02;
2566             M1 = m12;
2567             T02 += M0 * T00 + M1 * T01;
2568             T12 += M0 * T10 + M1 * T11;
2569 
2570             /* NOBREAK */
2571         case (APPLY_SHEAR | APPLY_SCALE):
2572             m02 = T02;
2573             m12 = T12;
2574 
2575             M0 = m00;
2576             M1 = m10;
2577             m00 = M0 * T00 + M1 * T01;
2578             m10 = M0 * T10 + M1 * T11;
2579 
2580             M0 = m01;
2581             M1 = m11;
2582             m01 = M0 * T00 + M1 * T01;
2583             m11 = M0 * T10 + M1 * T11;
2584             break;
2585 
2586         case (APPLY_SHEAR | APPLY_TRANSLATE):
2587             M0 = m02;
2588             M1 = m12;
2589             T02 += M0 * T00 + M1 * T01;
2590             T12 += M0 * T10 + M1 * T11;
2591 
2592             /* NOBREAK */
2593         case (APPLY_SHEAR):
2594             m02 = T02;
2595             m12 = T12;
2596 
2597             M0 = m10;
2598             m00 = M0 * T01;
2599             m10 = M0 * T11;
2600 
2601             M0 = m01;
2602             m01 = M0 * T00;
2603             m11 = M0 * T10;
2604             break;
2605 
2606         case (APPLY_SCALE | APPLY_TRANSLATE):
2607             M0 = m02;
2608             M1 = m12;
2609             T02 += M0 * T00 + M1 * T01;
2610             T12 += M0 * T10 + M1 * T11;
2611 
2612             /* NOBREAK */
2613         case (APPLY_SCALE):
2614             m02 = T02;
2615             m12 = T12;
2616 
2617             M0 = m00;
2618             m00 = M0 * T00;
2619             m10 = M0 * T10;
2620 
2621             M0 = m11;
2622             m01 = M0 * T01;
2623             m11 = M0 * T11;
2624             break;
2625 
2626         case (APPLY_TRANSLATE):
2627             M0 = m02;
2628             M1 = m12;
2629             T02 += M0 * T00 + M1 * T01;
2630             T12 += M0 * T10 + M1 * T11;
2631 
2632             /* NOBREAK */
2633         case (APPLY_IDENTITY):
2634             m02 = T02;
2635             m12 = T12;
2636 
2637             m00 = T00;
2638             m10 = T10;
2639 
2640             m01 = T01;
2641             m11 = T11;
2642 
2643             state = mystate | txstate;
2644             type = TYPE_UNKNOWN;
2645             return;
2646         }
2647         updateState();
2648     }
2649 
2650     /**
2651      * Returns an {@code AffineTransform} object representing the
2652      * inverse transformation.
2653      * The inverse transform Tx' of this transform Tx
2654      * maps coordinates transformed by Tx back
2655      * to their original coordinates.
2656      * In other words, Tx'(Tx(p)) = p = Tx(Tx'(p)).
2657      * <p>
2658      * If this transform maps all coordinates onto a point or a line
2659      * then it will not have an inverse, since coordinates that do
2660      * not lie on the destination point or line will not have an inverse
2661      * mapping.
2662      * The {@code getDeterminant} method can be used to determine if this
2663      * transform has no inverse, in which case an exception will be
2664      * thrown if the {@code createInverse} method is called.
2665      * @return a new {@code AffineTransform} object representing the
2666      * inverse transformation.
2667      * @see #getDeterminant
2668      * @exception NoninvertibleTransformException
2669      * if the matrix cannot be inverted.
2670      * @since 1.2
2671      */
2672     public AffineTransform createInverse()
2673         throws NoninvertibleTransformException
2674     {
2675         double det;
2676         switch (state) {
2677         default:
2678             stateError();
2679             /* NOTREACHED */
2680             return null;
2681         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2682             det = m00 * m11 - m01 * m10;
2683             if (Math.abs(det) <= Double.MIN_VALUE) {
2684                 throw new NoninvertibleTransformException("Determinant is "+
2685                                                           det);
2686             }
2687             return new AffineTransform( m11 / det, -m10 / det,
2688                                        -m01 / det,  m00 / det,
2689                                        (m01 * m12 - m11 * m02) / det,
2690                                        (m10 * m02 - m00 * m12) / det,
2691                                        (APPLY_SHEAR |
2692                                         APPLY_SCALE |
2693                                         APPLY_TRANSLATE));
2694         case (APPLY_SHEAR | APPLY_SCALE):
2695             det = m00 * m11 - m01 * m10;
2696             if (Math.abs(det) <= Double.MIN_VALUE) {
2697                 throw new NoninvertibleTransformException("Determinant is "+
2698                                                           det);
2699             }
2700             return new AffineTransform( m11 / det, -m10 / det,
2701                                        -m01 / det,  m00 / det,
2702                                         0.0,        0.0,
2703                                        (APPLY_SHEAR | APPLY_SCALE));
2704         case (APPLY_SHEAR | APPLY_TRANSLATE):
2705             if (m01 == 0.0 || m10 == 0.0) {
2706                 throw new NoninvertibleTransformException("Determinant is 0");
2707             }
2708             return new AffineTransform( 0.0,        1.0 / m01,
2709                                         1.0 / m10,  0.0,
2710                                        -m12 / m10, -m02 / m01,
2711                                        (APPLY_SHEAR | APPLY_TRANSLATE));
2712         case (APPLY_SHEAR):
2713             if (m01 == 0.0 || m10 == 0.0) {
2714                 throw new NoninvertibleTransformException("Determinant is 0");
2715             }
2716             return new AffineTransform(0.0,       1.0 / m01,
2717                                        1.0 / m10, 0.0,
2718                                        0.0,       0.0,
2719                                        (APPLY_SHEAR));
2720         case (APPLY_SCALE | APPLY_TRANSLATE):
2721             if (m00 == 0.0 || m11 == 0.0) {
2722                 throw new NoninvertibleTransformException("Determinant is 0");
2723             }
2724             return new AffineTransform( 1.0 / m00,  0.0,
2725                                         0.0,        1.0 / m11,
2726                                        -m02 / m00, -m12 / m11,
2727                                        (APPLY_SCALE | APPLY_TRANSLATE));
2728         case (APPLY_SCALE):
2729             if (m00 == 0.0 || m11 == 0.0) {
2730                 throw new NoninvertibleTransformException("Determinant is 0");
2731             }
2732             return new AffineTransform(1.0 / m00, 0.0,
2733                                        0.0,       1.0 / m11,
2734                                        0.0,       0.0,
2735                                        (APPLY_SCALE));
2736         case (APPLY_TRANSLATE):
2737             return new AffineTransform( 1.0,  0.0,
2738                                         0.0,  1.0,
2739                                        -m02, -m12,
2740                                        (APPLY_TRANSLATE));
2741         case (APPLY_IDENTITY):
2742             return new AffineTransform();
2743         }
2744 
2745         /* NOTREACHED */
2746     }
2747 
2748     /**
2749      * Sets this transform to the inverse of itself.
2750      * The inverse transform Tx' of this transform Tx
2751      * maps coordinates transformed by Tx back
2752      * to their original coordinates.
2753      * In other words, Tx'(Tx(p)) = p = Tx(Tx'(p)).
2754      * <p>
2755      * If this transform maps all coordinates onto a point or a line
2756      * then it will not have an inverse, since coordinates that do
2757      * not lie on the destination point or line will not have an inverse
2758      * mapping.
2759      * The {@code getDeterminant} method can be used to determine if this
2760      * transform has no inverse, in which case an exception will be
2761      * thrown if the {@code invert} method is called.
2762      * @see #getDeterminant
2763      * @exception NoninvertibleTransformException
2764      * if the matrix cannot be inverted.
2765      * @since 1.6
2766      */
2767     public void invert()
2768         throws NoninvertibleTransformException
2769     {
2770         double M00, M01, M02;
2771         double M10, M11, M12;
2772         double det;
2773         switch (state) {
2774         default:
2775             stateError();
2776             /* NOTREACHED */
2777             return;
2778         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2779             M00 = m00; M01 = m01; M02 = m02;
2780             M10 = m10; M11 = m11; M12 = m12;
2781             det = M00 * M11 - M01 * M10;
2782             if (Math.abs(det) <= Double.MIN_VALUE) {
2783                 throw new NoninvertibleTransformException("Determinant is "+
2784                                                           det);
2785             }
2786             m00 =  M11 / det;
2787             m10 = -M10 / det;
2788             m01 = -M01 / det;
2789             m11 =  M00 / det;
2790             m02 = (M01 * M12 - M11 * M02) / det;
2791             m12 = (M10 * M02 - M00 * M12) / det;
2792             break;
2793         case (APPLY_SHEAR | APPLY_SCALE):
2794             M00 = m00; M01 = m01;
2795             M10 = m10; M11 = m11;
2796             det = M00 * M11 - M01 * M10;
2797             if (Math.abs(det) <= Double.MIN_VALUE) {
2798                 throw new NoninvertibleTransformException("Determinant is "+
2799                                                           det);
2800             }
2801             m00 =  M11 / det;
2802             m10 = -M10 / det;
2803             m01 = -M01 / det;
2804             m11 =  M00 / det;
2805             // m02 = 0.0;
2806             // m12 = 0.0;
2807             break;
2808         case (APPLY_SHEAR | APPLY_TRANSLATE):
2809             M01 = m01; M02 = m02;
2810             M10 = m10; M12 = m12;
2811             if (M01 == 0.0 || M10 == 0.0) {
2812                 throw new NoninvertibleTransformException("Determinant is 0");
2813             }
2814             // m00 = 0.0;
2815             m10 = 1.0 / M01;
2816             m01 = 1.0 / M10;
2817             // m11 = 0.0;
2818             m02 = -M12 / M10;
2819             m12 = -M02 / M01;
2820             break;
2821         case (APPLY_SHEAR):
2822             M01 = m01;
2823             M10 = m10;
2824             if (M01 == 0.0 || M10 == 0.0) {
2825                 throw new NoninvertibleTransformException("Determinant is 0");
2826             }
2827             // m00 = 0.0;
2828             m10 = 1.0 / M01;
2829             m01 = 1.0 / M10;
2830             // m11 = 0.0;
2831             // m02 = 0.0;
2832             // m12 = 0.0;
2833             break;
2834         case (APPLY_SCALE | APPLY_TRANSLATE):
2835             M00 = m00; M02 = m02;
2836             M11 = m11; M12 = m12;
2837             if (M00 == 0.0 || M11 == 0.0) {
2838                 throw new NoninvertibleTransformException("Determinant is 0");
2839             }
2840             m00 = 1.0 / M00;
2841             // m10 = 0.0;
2842             // m01 = 0.0;
2843             m11 = 1.0 / M11;
2844             m02 = -M02 / M00;
2845             m12 = -M12 / M11;
2846             break;
2847         case (APPLY_SCALE):
2848             M00 = m00;
2849             M11 = m11;
2850             if (M00 == 0.0 || M11 == 0.0) {
2851                 throw new NoninvertibleTransformException("Determinant is 0");
2852             }
2853             m00 = 1.0 / M00;
2854             // m10 = 0.0;
2855             // m01 = 0.0;
2856             m11 = 1.0 / M11;
2857             // m02 = 0.0;
2858             // m12 = 0.0;
2859             break;
2860         case (APPLY_TRANSLATE):
2861             // m00 = 1.0;
2862             // m10 = 0.0;
2863             // m01 = 0.0;
2864             // m11 = 1.0;
2865             m02 = -m02;
2866             m12 = -m12;
2867             break;
2868         case (APPLY_IDENTITY):
2869             // m00 = 1.0;
2870             // m10 = 0.0;
2871             // m01 = 0.0;
2872             // m11 = 1.0;
2873             // m02 = 0.0;
2874             // m12 = 0.0;
2875             break;
2876         }
2877     }
2878 
2879     /**
2880      * Transforms the specified {@code ptSrc} and stores the result
2881      * in {@code ptDst}.
2882      * If {@code ptDst} is {@code null}, a new {@link Point2D}
2883      * object is allocated and then the result of the transformation is
2884      * stored in this object.
2885      * In either case, {@code ptDst}, which contains the
2886      * transformed point, is returned for convenience.
2887      * If {@code ptSrc} and {@code ptDst} are the same
2888      * object, the input point is correctly overwritten with
2889      * the transformed point.
2890      * @param ptSrc the specified {@code Point2D} to be transformed
2891      * @param ptDst the specified {@code Point2D} that stores the
2892      * result of transforming {@code ptSrc}
2893      * @return the {@code ptDst} after transforming
2894      * {@code ptSrc} and storing the result in {@code ptDst}.
2895      * @since 1.2
2896      */
2897     public Point2D transform(Point2D ptSrc, Point2D ptDst) {
2898         if (ptDst == null) {
2899             if (ptSrc instanceof Point2D.Double) {
2900                 ptDst = new Point2D.Double();
2901             } else {
2902                 ptDst = new Point2D.Float();
2903             }
2904         }
2905         // Copy source coords into local variables in case src == dst
2906         double x = ptSrc.getX();
2907         double y = ptSrc.getY();
2908         switch (state) {
2909         default:
2910             stateError();
2911             /* NOTREACHED */
2912             return null;
2913         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2914             ptDst.setLocation(x * m00 + y * m01 + m02,
2915                               x * m10 + y * m11 + m12);
2916             return ptDst;
2917         case (APPLY_SHEAR | APPLY_SCALE):
2918             ptDst.setLocation(x * m00 + y * m01, x * m10 + y * m11);
2919             return ptDst;
2920         case (APPLY_SHEAR | APPLY_TRANSLATE):
2921             ptDst.setLocation(y * m01 + m02, x * m10 + m12);
2922             return ptDst;
2923         case (APPLY_SHEAR):
2924             ptDst.setLocation(y * m01, x * m10);
2925             return ptDst;
2926         case (APPLY_SCALE | APPLY_TRANSLATE):
2927             ptDst.setLocation(x * m00 + m02, y * m11 + m12);
2928             return ptDst;
2929         case (APPLY_SCALE):
2930             ptDst.setLocation(x * m00, y * m11);
2931             return ptDst;
2932         case (APPLY_TRANSLATE):
2933             ptDst.setLocation(x + m02, y + m12);
2934             return ptDst;
2935         case (APPLY_IDENTITY):
2936             ptDst.setLocation(x, y);
2937             return ptDst;
2938         }
2939 
2940         /* NOTREACHED */
2941     }
2942 
2943     /**
2944      * Transforms an array of point objects by this transform.
2945      * If any element of the {@code ptDst} array is
2946      * {@code null}, a new {@code Point2D} object is allocated
2947      * and stored into that element before storing the results of the
2948      * transformation.
2949      * <p>
2950      * Note that this method does not take any precautions to
2951      * avoid problems caused by storing results into {@code Point2D}
2952      * objects that will be used as the source for calculations
2953      * further down the source array.
2954      * This method does guarantee that if a specified {@code Point2D}
2955      * object is both the source and destination for the same single point
2956      * transform operation then the results will not be stored until
2957      * the calculations are complete to avoid storing the results on
2958      * top of the operands.
2959      * If, however, the destination {@code Point2D} object for one
2960      * operation is the same object as the source {@code Point2D}
2961      * object for another operation further down the source array then
2962      * the original coordinates in that point are overwritten before
2963      * they can be converted.
2964      * @param ptSrc the array containing the source point objects
2965      * @param ptDst the array into which the transform point objects are
2966      * returned
2967      * @param srcOff the offset to the first point object to be
2968      * transformed in the source array
2969      * @param dstOff the offset to the location of the first
2970      * transformed point object that is stored in the destination array
2971      * @param numPts the number of point objects to be transformed
2972      * @since 1.2
2973      */
2974     public void transform(Point2D[] ptSrc, int srcOff,
2975                           Point2D[] ptDst, int dstOff,
2976                           int numPts) {
2977         int state = this.state;
2978         while (--numPts >= 0) {
2979             // Copy source coords into local variables in case src == dst
2980             Point2D src = ptSrc[srcOff++];
2981             double x = src.getX();
2982             double y = src.getY();
2983             Point2D dst = ptDst[dstOff++];
2984             if (dst == null) {
2985                 if (src instanceof Point2D.Double) {
2986                     dst = new Point2D.Double();
2987                 } else {
2988                     dst = new Point2D.Float();
2989                 }
2990                 ptDst[dstOff - 1] = dst;
2991             }
2992             switch (state) {
2993             default:
2994                 stateError();
2995                 /* NOTREACHED */
2996                 return;
2997             case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2998                 dst.setLocation(x * m00 + y * m01 + m02,
2999                                 x * m10 + y * m11 + m12);
3000                 break;
3001             case (APPLY_SHEAR | APPLY_SCALE):
3002                 dst.setLocation(x * m00 + y * m01, x * m10 + y * m11);
3003                 break;
3004             case (APPLY_SHEAR | APPLY_TRANSLATE):
3005                 dst.setLocation(y * m01 + m02, x * m10 + m12);
3006                 break;
3007             case (APPLY_SHEAR):
3008                 dst.setLocation(y * m01, x * m10);
3009                 break;
3010             case (APPLY_SCALE | APPLY_TRANSLATE):
3011                 dst.setLocation(x * m00 + m02, y * m11 + m12);
3012                 break;
3013             case (APPLY_SCALE):
3014                 dst.setLocation(x * m00, y * m11);
3015                 break;
3016             case (APPLY_TRANSLATE):
3017                 dst.setLocation(x + m02, y + m12);
3018                 break;
3019             case (APPLY_IDENTITY):
3020                 dst.setLocation(x, y);
3021                 break;
3022             }
3023         }
3024 
3025         /* NOTREACHED */
3026     }
3027 
3028     /**
3029      * Transforms an array of floating point coordinates by this transform.
3030      * The two coordinate array sections can be exactly the same or
3031      * can be overlapping sections of the same array without affecting the
3032      * validity of the results.
3033      * This method ensures that no source coordinates are overwritten by a
3034      * previous operation before they can be transformed.
3035      * The coordinates are stored in the arrays starting at the specified
3036      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3037      * @param srcPts the array containing the source point coordinates.
3038      * Each point is stored as a pair of x,&nbsp;y coordinates.
3039      * @param dstPts the array into which the transformed point coordinates
3040      * are returned.  Each point is stored as a pair of x,&nbsp;y
3041      * coordinates.
3042      * @param srcOff the offset to the first point to be transformed
3043      * in the source array
3044      * @param dstOff the offset to the location of the first
3045      * transformed point that is stored in the destination array
3046      * @param numPts the number of points to be transformed
3047      * @since 1.2
3048      */
3049     public void transform(float[] srcPts, int srcOff,
3050                           float[] dstPts, int dstOff,
3051                           int numPts) {
3052         double M00, M01, M02, M10, M11, M12;    // For caching
3053         if (dstPts == srcPts &&
3054             dstOff > srcOff && dstOff < srcOff + numPts * 2)
3055         {
3056             // If the arrays overlap partially with the destination higher
3057             // than the source and we transform the coordinates normally
3058             // we would overwrite some of the later source coordinates
3059             // with results of previous transformations.
3060             // To get around this we use arraycopy to copy the points
3061             // to their final destination with correct overwrite
3062             // handling and then transform them in place in the new
3063             // safer location.
3064             System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts * 2);
3065             // srcPts = dstPts;         // They are known to be equal.
3066             srcOff = dstOff;
3067         }
3068         switch (state) {
3069         default:
3070             stateError();
3071             /* NOTREACHED */
3072             return;
3073         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
3074             M00 = m00; M01 = m01; M02 = m02;
3075             M10 = m10; M11 = m11; M12 = m12;
3076             while (--numPts >= 0) {
3077                 double x = srcPts[srcOff++];
3078                 double y = srcPts[srcOff++];
3079                 dstPts[dstOff++] = (float) (M00 * x + M01 * y + M02);
3080                 dstPts[dstOff++] = (float) (M10 * x + M11 * y + M12);
3081             }
3082             return;
3083         case (APPLY_SHEAR | APPLY_SCALE):
3084             M00 = m00; M01 = m01;
3085             M10 = m10; M11 = m11;
3086             while (--numPts >= 0) {
3087                 double x = srcPts[srcOff++];
3088                 double y = srcPts[srcOff++];
3089                 dstPts[dstOff++] = (float) (M00 * x + M01 * y);
3090                 dstPts[dstOff++] = (float) (M10 * x + M11 * y);
3091             }
3092             return;
3093         case (APPLY_SHEAR | APPLY_TRANSLATE):
3094             M01 = m01; M02 = m02;
3095             M10 = m10; M12 = m12;
3096             while (--numPts >= 0) {
3097                 double x = srcPts[srcOff++];
3098                 dstPts[dstOff++] = (float) (M01 * srcPts[srcOff++] + M02);
3099                 dstPts[dstOff++] = (float) (M10 * x + M12);
3100             }
3101             return;
3102         case (APPLY_SHEAR):
3103             M01 = m01; M10 = m10;
3104             while (--numPts >= 0) {
3105                 double x = srcPts[srcOff++];
3106                 dstPts[dstOff++] = (float) (M01 * srcPts[srcOff++]);
3107                 dstPts[dstOff++] = (float) (M10 * x);
3108             }
3109             return;
3110         case (APPLY_SCALE | APPLY_TRANSLATE):
3111             M00 = m00; M02 = m02;
3112             M11 = m11; M12 = m12;
3113             while (--numPts >= 0) {
3114                 dstPts[dstOff++] = (float) (M00 * srcPts[srcOff++] + M02);
3115                 dstPts[dstOff++] = (float) (M11 * srcPts[srcOff++] + M12);
3116             }
3117             return;
3118         case (APPLY_SCALE):
3119             M00 = m00; M11 = m11;
3120             while (--numPts >= 0) {
3121                 dstPts[dstOff++] = (float) (M00 * srcPts[srcOff++]);
3122                 dstPts[dstOff++] = (float) (M11 * srcPts[srcOff++]);
3123             }
3124             return;
3125         case (APPLY_TRANSLATE):
3126             M02 = m02; M12 = m12;
3127             while (--numPts >= 0) {
3128                 dstPts[dstOff++] = (float) (srcPts[srcOff++] + M02);
3129                 dstPts[dstOff++] = (float) (srcPts[srcOff++] + M12);
3130             }
3131             return;
3132         case (APPLY_IDENTITY):
3133             if (srcPts != dstPts || srcOff != dstOff) {
3134                 System.arraycopy(srcPts, srcOff, dstPts, dstOff,
3135                                  numPts * 2);
3136             }
3137             return;
3138         }
3139 
3140         /* NOTREACHED */
3141     }
3142 
3143     /**
3144      * Transforms an array of double precision coordinates by this transform.
3145      * The two coordinate array sections can be exactly the same or
3146      * can be overlapping sections of the same array without affecting the
3147      * validity of the results.
3148      * This method ensures that no source coordinates are
3149      * overwritten by a previous operation before they can be transformed.
3150      * The coordinates are stored in the arrays starting at the indicated
3151      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3152      * @param srcPts the array containing the source point coordinates.
3153      * Each point is stored as a pair of x,&nbsp;y coordinates.
3154      * @param dstPts the array into which the transformed point
3155      * coordinates are returned.  Each point is stored as a pair of
3156      * x,&nbsp;y coordinates.
3157      * @param srcOff the offset to the first point to be transformed
3158      * in the source array
3159      * @param dstOff the offset to the location of the first
3160      * transformed point that is stored in the destination array
3161      * @param numPts the number of point objects to be transformed
3162      * @since 1.2
3163      */
3164     public void transform(double[] srcPts, int srcOff,
3165                           double[] dstPts, int dstOff,
3166                           int numPts) {
3167         double M00, M01, M02, M10, M11, M12;    // For caching
3168         if (dstPts == srcPts &&
3169             dstOff > srcOff && dstOff < srcOff + numPts * 2)
3170         {
3171             // If the arrays overlap partially with the destination higher
3172             // than the source and we transform the coordinates normally
3173             // we would overwrite some of the later source coordinates
3174             // with results of previous transformations.
3175             // To get around this we use arraycopy to copy the points
3176             // to their final destination with correct overwrite
3177             // handling and then transform them in place in the new
3178             // safer location.
3179             System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts * 2);
3180             // srcPts = dstPts;         // They are known to be equal.
3181             srcOff = dstOff;
3182         }
3183         switch (state) {
3184         default:
3185             stateError();
3186             /* NOTREACHED */
3187             return;
3188         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
3189             M00 = m00; M01 = m01; M02 = m02;
3190             M10 = m10; M11 = m11; M12 = m12;
3191             while (--numPts >= 0) {
3192                 double x = srcPts[srcOff++];
3193                 double y = srcPts[srcOff++];
3194                 dstPts[dstOff++] = M00 * x + M01 * y + M02;
3195                 dstPts[dstOff++] = M10 * x + M11 * y + M12;
3196             }
3197             return;
3198         case (APPLY_SHEAR | APPLY_SCALE):
3199             M00 = m00; M01 = m01;
3200             M10 = m10; M11 = m11;
3201             while (--numPts >= 0) {
3202                 double x = srcPts[srcOff++];
3203                 double y = srcPts[srcOff++];
3204                 dstPts[dstOff++] = M00 * x + M01 * y;
3205                 dstPts[dstOff++] = M10 * x + M11 * y;
3206             }
3207             return;
3208         case (APPLY_SHEAR | APPLY_TRANSLATE):
3209             M01 = m01; M02 = m02;
3210             M10 = m10; M12 = m12;
3211             while (--numPts >= 0) {
3212                 double x = srcPts[srcOff++];
3213                 dstPts[dstOff++] = M01 * srcPts[srcOff++] + M02;
3214                 dstPts[dstOff++] = M10 * x + M12;
3215             }
3216             return;
3217         case (APPLY_SHEAR):
3218             M01 = m01; M10 = m10;
3219             while (--numPts >= 0) {
3220                 double x = srcPts[srcOff++];
3221                 dstPts[dstOff++] = M01 * srcPts[srcOff++];
3222                 dstPts[dstOff++] = M10 * x;
3223             }
3224             return;
3225         case (APPLY_SCALE | APPLY_TRANSLATE):
3226             M00 = m00; M02 = m02;
3227             M11 = m11; M12 = m12;
3228             while (--numPts >= 0) {
3229                 dstPts[dstOff++] = M00 * srcPts[srcOff++] + M02;
3230                 dstPts[dstOff++] = M11 * srcPts[srcOff++] + M12;
3231             }
3232             return;
3233         case (APPLY_SCALE):
3234             M00 = m00; M11 = m11;
3235             while (--numPts >= 0) {
3236                 dstPts[dstOff++] = M00 * srcPts[srcOff++];
3237                 dstPts[dstOff++] = M11 * srcPts[srcOff++];
3238             }
3239             return;
3240         case (APPLY_TRANSLATE):
3241             M02 = m02; M12 = m12;
3242             while (--numPts >= 0) {
3243                 dstPts[dstOff++] = srcPts[srcOff++] + M02;
3244                 dstPts[dstOff++] = srcPts[srcOff++] + M12;
3245             }
3246             return;
3247         case (APPLY_IDENTITY):
3248             if (srcPts != dstPts || srcOff != dstOff) {
3249                 System.arraycopy(srcPts, srcOff, dstPts, dstOff,
3250                                  numPts * 2);
3251             }
3252             return;
3253         }
3254 
3255         /* NOTREACHED */
3256     }
3257 
3258     /**
3259      * Transforms an array of floating point coordinates by this transform
3260      * and stores the results into an array of doubles.
3261      * The coordinates are stored in the arrays starting at the specified
3262      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3263      * @param srcPts the array containing the source point coordinates.
3264      * Each point is stored as a pair of x,&nbsp;y coordinates.
3265      * @param dstPts the array into which the transformed point coordinates
3266      * are returned.  Each point is stored as a pair of x,&nbsp;y
3267      * coordinates.
3268      * @param srcOff the offset to the first point to be transformed
3269      * in the source array
3270      * @param dstOff the offset to the location of the first
3271      * transformed point that is stored in the destination array
3272      * @param numPts the number of points to be transformed
3273      * @since 1.2
3274      */
3275     public void transform(float[] srcPts, int srcOff,
3276                           double[] dstPts, int dstOff,
3277                           int numPts) {
3278         double M00, M01, M02, M10, M11, M12;    // For caching
3279         switch (state) {
3280         default:
3281             stateError();
3282             /* NOTREACHED */
3283             return;
3284         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
3285             M00 = m00; M01 = m01; M02 = m02;
3286             M10 = m10; M11 = m11; M12 = m12;
3287             while (--numPts >= 0) {
3288                 double x = srcPts[srcOff++];
3289                 double y = srcPts[srcOff++];
3290                 dstPts[dstOff++] = M00 * x + M01 * y + M02;
3291                 dstPts[dstOff++] = M10 * x + M11 * y + M12;
3292             }
3293             return;
3294         case (APPLY_SHEAR | APPLY_SCALE):
3295             M00 = m00; M01 = m01;
3296             M10 = m10; M11 = m11;
3297             while (--numPts >= 0) {
3298                 double x = srcPts[srcOff++];
3299                 double y = srcPts[srcOff++];
3300                 dstPts[dstOff++] = M00 * x + M01 * y;
3301                 dstPts[dstOff++] = M10 * x + M11 * y;
3302             }
3303             return;
3304         case (APPLY_SHEAR | APPLY_TRANSLATE):
3305             M01 = m01; M02 = m02;
3306             M10 = m10; M12 = m12;
3307             while (--numPts >= 0) {
3308                 double x = srcPts[srcOff++];
3309                 dstPts[dstOff++] = M01 * srcPts[srcOff++] + M02;
3310                 dstPts[dstOff++] = M10 * x + M12;
3311             }
3312             return;
3313         case (APPLY_SHEAR):
3314             M01 = m01; M10 = m10;
3315             while (--numPts >= 0) {
3316                 double x = srcPts[srcOff++];
3317                 dstPts[dstOff++] = M01 * srcPts[srcOff++];
3318                 dstPts[dstOff++] = M10 * x;
3319             }
3320             return;
3321         case (APPLY_SCALE | APPLY_TRANSLATE):
3322             M00 = m00; M02 = m02;
3323             M11 = m11; M12 = m12;
3324             while (--numPts >= 0) {
3325                 dstPts[dstOff++] = M00 * srcPts[srcOff++] + M02;
3326                 dstPts[dstOff++] = M11 * srcPts[srcOff++] + M12;
3327             }
3328             return;
3329         case (APPLY_SCALE):
3330             M00 = m00; M11 = m11;
3331             while (--numPts >= 0) {
3332                 dstPts[dstOff++] = M00 * srcPts[srcOff++];
3333                 dstPts[dstOff++] = M11 * srcPts[srcOff++];
3334             }
3335             return;
3336         case (APPLY_TRANSLATE):
3337             M02 = m02; M12 = m12;
3338             while (--numPts >= 0) {
3339                 dstPts[dstOff++] = srcPts[srcOff++] + M02;
3340                 dstPts[dstOff++] = srcPts[srcOff++] + M12;
3341             }
3342             return;
3343         case (APPLY_IDENTITY):
3344             while (--numPts >= 0) {
3345                 dstPts[dstOff++] = srcPts[srcOff++];
3346                 dstPts[dstOff++] = srcPts[srcOff++];
3347             }
3348             return;
3349         }
3350 
3351         /* NOTREACHED */
3352     }
3353 
3354     /**
3355      * Transforms an array of double precision coordinates by this transform
3356      * and stores the results into an array of floats.
3357      * The coordinates are stored in the arrays starting at the specified
3358      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3359      * @param srcPts the array containing the source point coordinates.
3360      * Each point is stored as a pair of x,&nbsp;y coordinates.
3361      * @param dstPts the array into which the transformed point
3362      * coordinates are returned.  Each point is stored as a pair of
3363      * x,&nbsp;y coordinates.
3364      * @param srcOff the offset to the first point to be transformed
3365      * in the source array
3366      * @param dstOff the offset to the location of the first
3367      * transformed point that is stored in the destination array
3368      * @param numPts the number of point objects to be transformed
3369      * @since 1.2
3370      */
3371     public void transform(double[] srcPts, int srcOff,
3372                           float[] dstPts, int dstOff,
3373                           int numPts) {
3374         double M00, M01, M02, M10, M11, M12;    // For caching
3375         switch (state) {
3376         default:
3377             stateError();
3378             /* NOTREACHED */
3379             return;
3380         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
3381             M00 = m00; M01 = m01; M02 = m02;
3382             M10 = m10; M11 = m11; M12 = m12;
3383             while (--numPts >= 0) {
3384                 double x = srcPts[srcOff++];
3385                 double y = srcPts[srcOff++];
3386                 dstPts[dstOff++] = (float) (M00 * x + M01 * y + M02);
3387                 dstPts[dstOff++] = (float) (M10 * x + M11 * y + M12);
3388             }
3389             return;
3390         case (APPLY_SHEAR | APPLY_SCALE):
3391             M00 = m00; M01 = m01;
3392             M10 = m10; M11 = m11;
3393             while (--numPts >= 0) {
3394                 double x = srcPts[srcOff++];
3395                 double y = srcPts[srcOff++];
3396                 dstPts[dstOff++] = (float) (M00 * x + M01 * y);
3397                 dstPts[dstOff++] = (float) (M10 * x + M11 * y);
3398             }
3399             return;
3400         case (APPLY_SHEAR | APPLY_TRANSLATE):
3401             M01 = m01; M02 = m02;
3402             M10 = m10; M12 = m12;
3403             while (--numPts >= 0) {
3404                 double x = srcPts[srcOff++];
3405                 dstPts[dstOff++] = (float) (M01 * srcPts[srcOff++] + M02);
3406                 dstPts[dstOff++] = (float) (M10 * x + M12);
3407             }
3408             return;
3409         case (APPLY_SHEAR):
3410             M01 = m01; M10 = m10;
3411             while (--numPts >= 0) {
3412                 double x = srcPts[srcOff++];
3413                 dstPts[dstOff++] = (float) (M01 * srcPts[srcOff++]);
3414                 dstPts[dstOff++] = (float) (M10 * x);
3415             }
3416             return;
3417         case (APPLY_SCALE | APPLY_TRANSLATE):
3418             M00 = m00; M02 = m02;
3419             M11 = m11; M12 = m12;
3420             while (--numPts >= 0) {
3421                 dstPts[dstOff++] = (float) (M00 * srcPts[srcOff++] + M02);
3422                 dstPts[dstOff++] = (float) (M11 * srcPts[srcOff++] + M12);
3423             }
3424             return;
3425         case (APPLY_SCALE):
3426             M00 = m00; M11 = m11;
3427             while (--numPts >= 0) {
3428                 dstPts[dstOff++] = (float) (M00 * srcPts[srcOff++]);
3429                 dstPts[dstOff++] = (float) (M11 * srcPts[srcOff++]);
3430             }
3431             return;
3432         case (APPLY_TRANSLATE):
3433             M02 = m02; M12 = m12;
3434             while (--numPts >= 0) {
3435                 dstPts[dstOff++] = (float) (srcPts[srcOff++] + M02);
3436                 dstPts[dstOff++] = (float) (srcPts[srcOff++] + M12);
3437             }
3438             return;
3439         case (APPLY_IDENTITY):
3440             while (--numPts >= 0) {
3441                 dstPts[dstOff++] = (float) (srcPts[srcOff++]);
3442                 dstPts[dstOff++] = (float) (srcPts[srcOff++]);
3443             }
3444             return;
3445         }
3446 
3447         /* NOTREACHED */
3448     }
3449 
3450     /**
3451      * Inverse transforms the specified {@code ptSrc} and stores the
3452      * result in {@code ptDst}.
3453      * If {@code ptDst} is {@code null}, a new
3454      * {@code Point2D} object is allocated and then the result of the
3455      * transform is stored in this object.
3456      * In either case, {@code ptDst}, which contains the transformed
3457      * point, is returned for convenience.
3458      * If {@code ptSrc} and {@code ptDst} are the same
3459      * object, the input point is correctly overwritten with the
3460      * transformed point.
3461      * @param ptSrc the point to be inverse transformed
3462      * @param ptDst the resulting transformed point
3463      * @return {@code ptDst}, which contains the result of the
3464      * inverse transform.
3465      * @exception NoninvertibleTransformException  if the matrix cannot be
3466      *                                         inverted.
3467      * @since 1.2
3468      */
3469     @SuppressWarnings("fallthrough")
3470     public Point2D inverseTransform(Point2D ptSrc, Point2D ptDst)
3471         throws NoninvertibleTransformException
3472     {
3473         if (ptDst == null) {
3474             if (ptSrc instanceof Point2D.Double) {
3475                 ptDst = new Point2D.Double();
3476             } else {
3477                 ptDst = new Point2D.Float();
3478             }
3479         }
3480         // Copy source coords into local variables in case src == dst
3481         double x = ptSrc.getX();
3482         double y = ptSrc.getY();
3483         switch (state) {
3484         default:
3485             stateError();
3486             /* NOTREACHED */
3487         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
3488             x -= m02;
3489             y -= m12;
3490             /* NOBREAK */
3491         case (APPLY_SHEAR | APPLY_SCALE):
3492             double det = m00 * m11 - m01 * m10;
3493             if (Math.abs(det) <= Double.MIN_VALUE) {
3494                 throw new NoninvertibleTransformException("Determinant is "+
3495                                                           det);
3496             }
3497             ptDst.setLocation((x * m11 - y * m01) / det,
3498                               (y * m00 - x * m10) / det);
3499             return ptDst;
3500         case (APPLY_SHEAR | APPLY_TRANSLATE):
3501             x -= m02;
3502             y -= m12;
3503             /* NOBREAK */
3504         case (APPLY_SHEAR):
3505             if (m01 == 0.0 || m10 == 0.0) {
3506                 throw new NoninvertibleTransformException("Determinant is 0");
3507             }
3508             ptDst.setLocation(y / m10, x / m01);
3509             return ptDst;
3510         case (APPLY_SCALE | APPLY_TRANSLATE):
3511             x -= m02;
3512             y -= m12;
3513             /* NOBREAK */
3514         case (APPLY_SCALE):
3515             if (m00 == 0.0 || m11 == 0.0) {
3516                 throw new NoninvertibleTransformException("Determinant is 0");
3517             }
3518             ptDst.setLocation(x / m00, y / m11);
3519             return ptDst;
3520         case (APPLY_TRANSLATE):
3521             ptDst.setLocation(x - m02, y - m12);
3522             return ptDst;
3523         case (APPLY_IDENTITY):
3524             ptDst.setLocation(x, y);
3525             return ptDst;
3526         }
3527 
3528         /* NOTREACHED */
3529     }
3530 
3531     /**
3532      * Inverse transforms an array of double precision coordinates by
3533      * this transform.
3534      * The two coordinate array sections can be exactly the same or
3535      * can be overlapping sections of the same array without affecting the
3536      * validity of the results.
3537      * This method ensures that no source coordinates are
3538      * overwritten by a previous operation before they can be transformed.
3539      * The coordinates are stored in the arrays starting at the specified
3540      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3541      * @param srcPts the array containing the source point coordinates.
3542      * Each point is stored as a pair of x,&nbsp;y coordinates.
3543      * @param dstPts the array into which the transformed point
3544      * coordinates are returned.  Each point is stored as a pair of
3545      * x,&nbsp;y coordinates.
3546      * @param srcOff the offset to the first point to be transformed
3547      * in the source array
3548      * @param dstOff the offset to the location of the first
3549      * transformed point that is stored in the destination array
3550      * @param numPts the number of point objects to be transformed
3551      * @exception NoninvertibleTransformException  if the matrix cannot be
3552      *                                         inverted.
3553      * @since 1.2
3554      */
3555     public void inverseTransform(double[] srcPts, int srcOff,
3556                                  double[] dstPts, int dstOff,
3557                                  int numPts)
3558         throws NoninvertibleTransformException
3559     {
3560         double M00, M01, M02, M10, M11, M12;    // For caching
3561         double det;
3562         if (dstPts == srcPts &&
3563             dstOff > srcOff && dstOff < srcOff + numPts * 2)
3564         {
3565             // If the arrays overlap partially with the destination higher
3566             // than the source and we transform the coordinates normally
3567             // we would overwrite some of the later source coordinates
3568             // with results of previous transformations.
3569             // To get around this we use arraycopy to copy the points
3570             // to their final destination with correct overwrite
3571             // handling and then transform them in place in the new
3572             // safer location.
3573             System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts * 2);
3574             // srcPts = dstPts;         // They are known to be equal.
3575             srcOff = dstOff;
3576         }
3577         switch (state) {
3578         default:
3579             stateError();
3580             /* NOTREACHED */
3581             return;
3582         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
3583             M00 = m00; M01 = m01; M02 = m02;
3584             M10 = m10; M11 = m11; M12 = m12;
3585             det = M00 * M11 - M01 * M10;
3586             if (Math.abs(det) <= Double.MIN_VALUE) {
3587                 throw new NoninvertibleTransformException("Determinant is "+
3588                                                           det);
3589             }
3590             while (--numPts >= 0) {
3591                 double x = srcPts[srcOff++] - M02;
3592                 double y = srcPts[srcOff++] - M12;
3593                 dstPts[dstOff++] = (x * M11 - y * M01) / det;
3594                 dstPts[dstOff++] = (y * M00 - x * M10) / det;
3595             }
3596             return;
3597         case (APPLY_SHEAR | APPLY_SCALE):
3598             M00 = m00; M01 = m01;
3599             M10 = m10; M11 = m11;
3600             det = M00 * M11 - M01 * M10;
3601             if (Math.abs(det) <= Double.MIN_VALUE) {
3602                 throw new NoninvertibleTransformException("Determinant is "+
3603                                                           det);
3604             }
3605             while (--numPts >= 0) {
3606                 double x = srcPts[srcOff++];
3607                 double y = srcPts[srcOff++];
3608                 dstPts[dstOff++] = (x * M11 - y * M01) / det;
3609                 dstPts[dstOff++] = (y * M00 - x * M10) / det;
3610             }
3611             return;
3612         case (APPLY_SHEAR | APPLY_TRANSLATE):
3613             M01 = m01; M02 = m02;
3614             M10 = m10; M12 = m12;
3615             if (M01 == 0.0 || M10 == 0.0) {
3616                 throw new NoninvertibleTransformException("Determinant is 0");
3617             }
3618             while (--numPts >= 0) {
3619                 double x = srcPts[srcOff++] - M02;
3620                 dstPts[dstOff++] = (srcPts[srcOff++] - M12) / M10;
3621                 dstPts[dstOff++] = x / M01;
3622             }
3623             return;
3624         case (APPLY_SHEAR):
3625             M01 = m01; M10 = m10;
3626             if (M01 == 0.0 || M10 == 0.0) {
3627                 throw new NoninvertibleTransformException("Determinant is 0");
3628             }
3629             while (--numPts >= 0) {
3630                 double x = srcPts[srcOff++];
3631                 dstPts[dstOff++] = srcPts[srcOff++] / M10;
3632                 dstPts[dstOff++] = x / M01;
3633             }
3634             return;
3635         case (APPLY_SCALE | APPLY_TRANSLATE):
3636             M00 = m00; M02 = m02;
3637             M11 = m11; M12 = m12;
3638             if (M00 == 0.0 || M11 == 0.0) {
3639                 throw new NoninvertibleTransformException("Determinant is 0");
3640             }
3641             while (--numPts >= 0) {
3642                 dstPts[dstOff++] = (srcPts[srcOff++] - M02) / M00;
3643                 dstPts[dstOff++] = (srcPts[srcOff++] - M12) / M11;
3644             }
3645             return;
3646         case (APPLY_SCALE):
3647             M00 = m00; M11 = m11;
3648             if (M00 == 0.0 || M11 == 0.0) {
3649                 throw new NoninvertibleTransformException("Determinant is 0");
3650             }
3651             while (--numPts >= 0) {
3652                 dstPts[dstOff++] = srcPts[srcOff++] / M00;
3653                 dstPts[dstOff++] = srcPts[srcOff++] / M11;
3654             }
3655             return;
3656         case (APPLY_TRANSLATE):
3657             M02 = m02; M12 = m12;
3658             while (--numPts >= 0) {
3659                 dstPts[dstOff++] = srcPts[srcOff++] - M02;
3660                 dstPts[dstOff++] = srcPts[srcOff++] - M12;
3661             }
3662             return;
3663         case (APPLY_IDENTITY):
3664             if (srcPts != dstPts || srcOff != dstOff) {
3665                 System.arraycopy(srcPts, srcOff, dstPts, dstOff,
3666                                  numPts * 2);
3667             }
3668             return;
3669         }
3670 
3671         /* NOTREACHED */
3672     }
3673 
3674     /**
3675      * Transforms the relative distance vector specified by
3676      * {@code ptSrc} and stores the result in {@code ptDst}.
3677      * A relative distance vector is transformed without applying the
3678      * translation components of the affine transformation matrix
3679      * using the following equations:
3680      * <pre>
3681      *  [  x' ]   [  m00  m01 (m02) ] [  x  ]   [ m00x + m01y ]
3682      *  [  y' ] = [  m10  m11 (m12) ] [  y  ] = [ m10x + m11y ]
3683      *  [ (1) ]   [  (0)  (0) ( 1 ) ] [ (1) ]   [     (1)     ]
3684      * </pre>
3685      * If {@code ptDst} is {@code null}, a new
3686      * {@code Point2D} object is allocated and then the result of the
3687      * transform is stored in this object.
3688      * In either case, {@code ptDst}, which contains the
3689      * transformed point, is returned for convenience.
3690      * If {@code ptSrc} and {@code ptDst} are the same object,
3691      * the input point is correctly overwritten with the transformed
3692      * point.
3693      * @param ptSrc the distance vector to be delta transformed
3694      * @param ptDst the resulting transformed distance vector
3695      * @return {@code ptDst}, which contains the result of the
3696      * transformation.
3697      * @since 1.2
3698      */
3699     public Point2D deltaTransform(Point2D ptSrc, Point2D ptDst) {
3700         if (ptDst == null) {
3701             if (ptSrc instanceof Point2D.Double) {
3702                 ptDst = new Point2D.Double();
3703             } else {
3704                 ptDst = new Point2D.Float();
3705             }
3706         }
3707         // Copy source coords into local variables in case src == dst
3708         double x = ptSrc.getX();
3709         double y = ptSrc.getY();
3710         switch (state) {
3711         default:
3712             stateError();
3713             /* NOTREACHED */
3714             return null;
3715         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
3716         case (APPLY_SHEAR | APPLY_SCALE):
3717             ptDst.setLocation(x * m00 + y * m01, x * m10 + y * m11);
3718             return ptDst;
3719         case (APPLY_SHEAR | APPLY_TRANSLATE):
3720         case (APPLY_SHEAR):
3721             ptDst.setLocation(y * m01, x * m10);
3722             return ptDst;
3723         case (APPLY_SCALE | APPLY_TRANSLATE):
3724         case (APPLY_SCALE):
3725             ptDst.setLocation(x * m00, y * m11);
3726             return ptDst;
3727         case (APPLY_TRANSLATE):
3728         case (APPLY_IDENTITY):
3729             ptDst.setLocation(x, y);
3730             return ptDst;
3731         }
3732 
3733         /* NOTREACHED */
3734     }
3735 
3736     /**
3737      * Transforms an array of relative distance vectors by this
3738      * transform.
3739      * A relative distance vector is transformed without applying the
3740      * translation components of the affine transformation matrix
3741      * using the following equations:
3742      * <pre>
3743      *  [  x' ]   [  m00  m01 (m02) ] [  x  ]   [ m00x + m01y ]
3744      *  [  y' ] = [  m10  m11 (m12) ] [  y  ] = [ m10x + m11y ]
3745      *  [ (1) ]   [  (0)  (0) ( 1 ) ] [ (1) ]   [     (1)     ]
3746      * </pre>
3747      * The two coordinate array sections can be exactly the same or
3748      * can be overlapping sections of the same array without affecting the
3749      * validity of the results.
3750      * This method ensures that no source coordinates are
3751      * overwritten by a previous operation before they can be transformed.
3752      * The coordinates are stored in the arrays starting at the indicated
3753      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3754      * @param srcPts the array containing the source distance vectors.
3755      * Each vector is stored as a pair of relative x,&nbsp;y coordinates.
3756      * @param dstPts the array into which the transformed distance vectors
3757      * are returned.  Each vector is stored as a pair of relative
3758      * x,&nbsp;y coordinates.
3759      * @param srcOff the offset to the first vector to be transformed
3760      * in the source array
3761      * @param dstOff the offset to the location of the first
3762      * transformed vector that is stored in the destination array
3763      * @param numPts the number of vector coordinate pairs to be
3764      * transformed
3765      * @since 1.2
3766      */
3767     public void deltaTransform(double[] srcPts, int srcOff,
3768                                double[] dstPts, int dstOff,
3769                                int numPts) {
3770         double M00, M01, M10, M11;      // For caching
3771         if (dstPts == srcPts &&
3772             dstOff > srcOff && dstOff < srcOff + numPts * 2)
3773         {
3774             // If the arrays overlap partially with the destination higher
3775             // than the source and we transform the coordinates normally
3776             // we would overwrite some of the later source coordinates
3777             // with results of previous transformations.
3778             // To get around this we use arraycopy to copy the points
3779             // to their final destination with correct overwrite
3780             // handling and then transform them in place in the new
3781             // safer location.
3782             System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts * 2);
3783             // srcPts = dstPts;         // They are known to be equal.
3784             srcOff = dstOff;
3785         }
3786         switch (state) {
3787         default:
3788             stateError();
3789             /* NOTREACHED */
3790             return;
3791         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
3792         case (APPLY_SHEAR | APPLY_SCALE):
3793             M00 = m00; M01 = m01;
3794             M10 = m10; M11 = m11;
3795             while (--numPts >= 0) {
3796                 double x = srcPts[srcOff++];
3797                 double y = srcPts[srcOff++];
3798                 dstPts[dstOff++] = x * M00 + y * M01;
3799                 dstPts[dstOff++] = x * M10 + y * M11;
3800             }
3801             return;
3802         case (APPLY_SHEAR | APPLY_TRANSLATE):
3803         case (APPLY_SHEAR):
3804             M01 = m01; M10 = m10;
3805             while (--numPts >= 0) {
3806                 double x = srcPts[srcOff++];
3807                 dstPts[dstOff++] = srcPts[srcOff++] * M01;
3808                 dstPts[dstOff++] = x * M10;
3809             }
3810             return;
3811         case (APPLY_SCALE | APPLY_TRANSLATE):
3812         case (APPLY_SCALE):
3813             M00 = m00; M11 = m11;
3814             while (--numPts >= 0) {
3815                 dstPts[dstOff++] = srcPts[srcOff++] * M00;
3816                 dstPts[dstOff++] = srcPts[srcOff++] * M11;
3817             }
3818             return;
3819         case (APPLY_TRANSLATE):
3820         case (APPLY_IDENTITY):
3821             if (srcPts != dstPts || srcOff != dstOff) {
3822                 System.arraycopy(srcPts, srcOff, dstPts, dstOff,
3823                                  numPts * 2);
3824             }
3825             return;
3826         }
3827 
3828         /* NOTREACHED */
3829     }
3830 
3831     /**
3832      * Returns a new {@link Shape} object defined by the geometry of the
3833      * specified {@code Shape} after it has been transformed by
3834      * this transform.
3835      * @param pSrc the specified {@code Shape} object to be
3836      * transformed by this transform.
3837      * @return a new {@code Shape} object that defines the geometry
3838      * of the transformed {@code Shape}, or null if {@code pSrc} is null.
3839      * @since 1.2
3840      */
3841     public Shape createTransformedShape(Shape pSrc) {
3842         if (pSrc == null) {
3843             return null;
3844         }
3845         return new Path2D.Double(pSrc, this);
3846     }
3847 
3848     // Round values to sane precision for printing
3849     // Note that Math.sin(Math.PI) has an error of about 10^-16
3850     private static double _matround(double matval) {
3851         return Math.rint(matval * 1E15) / 1E15;
3852     }
3853 
3854     /**
3855      * Returns a {@code String} that represents the value of this
3856      * {@link Object}.
3857      * @return a {@code String} representing the value of this
3858      * {@code Object}.
3859      * @since 1.2
3860      */
3861     public String toString() {
3862         return ("AffineTransform[["
3863                 + _matround(m00) + ", "
3864                 + _matround(m01) + ", "
3865                 + _matround(m02) + "], ["
3866                 + _matround(m10) + ", "
3867                 + _matround(m11) + ", "
3868                 + _matround(m12) + "]]");
3869     }
3870 
3871     /**
3872      * Returns {@code true} if this {@code AffineTransform} is
3873      * an identity transform.
3874      * @return {@code true} if this {@code AffineTransform} is
3875      * an identity transform; {@code false} otherwise.
3876      * @since 1.2
3877      */
3878     public boolean isIdentity() {
3879         return (state == APPLY_IDENTITY || (getType() == TYPE_IDENTITY));
3880     }
3881 
3882     /**
3883      * Returns a copy of this {@code AffineTransform} object.
3884      * @return an {@code Object} that is a copy of this
3885      * {@code AffineTransform} object.
3886      * @since 1.2
3887      */
3888     public Object clone() {
3889         try {
3890             return super.clone();
3891         } catch (CloneNotSupportedException e) {
3892             // this shouldn't happen, since we are Cloneable
3893             throw new InternalError(e);
3894         }
3895     }
3896 
3897     /**
3898      * Returns the hashcode for this transform.
3899      * @return      a hash code for this transform.
3900      * @since 1.2
3901      */
3902     public int hashCode() {
3903         long bits = Double.doubleToLongBits(m00);
3904         bits = bits * 31 + Double.doubleToLongBits(m01);
3905         bits = bits * 31 + Double.doubleToLongBits(m02);
3906         bits = bits * 31 + Double.doubleToLongBits(m10);
3907         bits = bits * 31 + Double.doubleToLongBits(m11);
3908         bits = bits * 31 + Double.doubleToLongBits(m12);
3909         return (((int) bits) ^ ((int) (bits >> 32)));
3910     }
3911 
3912     /**
3913      * Returns {@code true} if this {@code AffineTransform}
3914      * represents the same affine coordinate transform as the specified
3915      * argument.
3916      * @param obj the {@code Object} to test for equality with this
3917      * {@code AffineTransform}
3918      * @return {@code true} if {@code obj} equals this
3919      * {@code AffineTransform} object; {@code false} otherwise.
3920      * @since 1.2
3921      */
3922     public boolean equals(Object obj) {
3923         if (!(obj instanceof AffineTransform)) {
3924             return false;
3925         }
3926 
3927         AffineTransform a = (AffineTransform)obj;
3928 
3929         return ((m00 == a.m00) && (m01 == a.m01) && (m02 == a.m02) &&
3930                 (m10 == a.m10) && (m11 == a.m11) && (m12 == a.m12));
3931     }
3932 
3933     /* Serialization support.  A readObject method is neccessary because
3934      * the state field is part of the implementation of this particular
3935      * AffineTransform and not part of the public specification.  The
3936      * state variable's value needs to be recalculated on the fly by the
3937      * readObject method as it is in the 6-argument matrix constructor.
3938      */
3939 
3940     /*
3941      * JDK 1.2 serialVersionUID
3942      */
3943     private static final long serialVersionUID = 1330973210523860834L;
3944 
3945     private void writeObject(java.io.ObjectOutputStream s)
3946         throws java.lang.ClassNotFoundException, java.io.IOException
3947     {
3948         s.defaultWriteObject();
3949     }
3950 
3951     private void readObject(java.io.ObjectInputStream s)
3952         throws java.lang.ClassNotFoundException, java.io.IOException
3953     {
3954         s.defaultReadObject();
3955         updateState();
3956     }
3957 }