1 /*
   2  * Copyright (c) 1996, 2013, 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 name="quadrantapproximation">Handling 90-Degree Rotations</a></h3>
  50  * <p>
  51  * In some variations of the {@code rotate} methods in the
  52  * {@code AffineTransform} class, a double-precision argument
  53  * specifies the angle of rotation in radians.
  54  * These methods have special handling for rotations of approximately
  55  * 90 degrees (including multiples such as 180, 270, and 360 degrees),
  56  * so that the common case of quadrant rotation is handled more
  57  * efficiently.
  58  * This special handling can cause angles very close to multiples of
  59  * 90 degrees to be treated as if they were exact multiples of
  60  * 90 degrees.
  61  * For small multiples of 90 degrees the range of angles treated
  62  * as a quadrant rotation is approximately 0.00000121 degrees wide.
  63  * This section explains why such special care is needed and how
  64  * it is implemented.
  65  * <p>
  66  * Since 90 degrees is represented as {@code PI/2} in radians,
  67  * and since PI is a transcendental (and therefore irrational) number,
  68  * it is not possible to exactly represent a multiple of 90 degrees as
  69  * an exact double precision value measured in radians.
  70  * As a result it is theoretically impossible to describe quadrant
  71  * rotations (90, 180, 270 or 360 degrees) using these values.
  72  * Double precision floating point values can get very close to
  73  * non-zero multiples of {@code PI/2} but never close enough
  74  * for the sine or cosine to be exactly 0.0, 1.0 or -1.0.
  75  * The implementations of {@code Math.sin()} and
  76  * {@code Math.cos()} correspondingly never return 0.0
  77  * for any case other than {@code Math.sin(0.0)}.
  78  * These same implementations do, however, return exactly 1.0 and
  79  * -1.0 for some range of numbers around each multiple of 90
  80  * degrees since the correct answer is so close to 1.0 or -1.0 that
  81  * the double precision significand cannot represent the difference
  82  * as accurately as it can for numbers that are near 0.0.
  83  * <p>
  84  * The net result of these issues is that if the
  85  * {@code Math.sin()} and {@code Math.cos()} methods
  86  * are used to directly generate the values for the matrix modifications
  87  * during these radian-based rotation operations then the resulting
  88  * transform is never strictly classifiable as a quadrant rotation
  89  * even for a simple case like {@code rotate(Math.PI/2.0)},
  90  * due to minor variations in the matrix caused by the non-0.0 values
  91  * obtained for the sine and cosine.
  92  * If these transforms are not classified as quadrant rotations then
  93  * subsequent code which attempts to optimize further operations based
  94  * upon the type of the transform will be relegated to its most general
  95  * implementation.
  96  * <p>
  97  * Because quadrant rotations are fairly common,
  98  * this class should handle these cases reasonably quickly, both in
  99  * applying the rotations to the transform and in applying the resulting
 100  * transform to the coordinates.
 101  * To facilitate this optimal handling, the methods which take an angle
 102  * of rotation measured in radians attempt to detect angles that are
 103  * intended to be quadrant rotations and treat them as such.
 104  * These methods therefore treat an angle <em>theta</em> as a quadrant
 105  * rotation if either <code>Math.sin(<em>theta</em>)</code> or
 106  * <code>Math.cos(<em>theta</em>)</code> returns exactly 1.0 or -1.0.
 107  * As a rule of thumb, this property holds true for a range of
 108  * approximately 0.0000000211 radians (or 0.00000121 degrees) around
 109  * small multiples of {@code Math.PI/2.0}.
 110  *
 111  * @author Jim Graham
 112  * @since 1.2
 113  */
 114 public class AffineTransform implements Cloneable, java.io.Serializable {
 115 
 116     /*
 117      * This constant is only useful for the cached type field.
 118      * It indicates that the type has been decached and must be recalculated.
 119      */
 120     private static final int TYPE_UNKNOWN = -1;
 121 
 122     /**
 123      * This constant indicates that the transform defined by this object
 124      * is an identity transform.
 125      * An identity transform is one in which the output coordinates are
 126      * always the same as the input coordinates.
 127      * If this transform is anything other than the identity transform,
 128      * the type will either be the constant GENERAL_TRANSFORM or a
 129      * combination of the appropriate flag bits for the various coordinate
 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 X coordinate scaling element (m00) of the 3x3
1164      * affine transformation matrix. However, this return value cannot be used
1165      * to determine the amount by which X-coordinate is stretched or contracted.
1166      * @return a double value that is the X coordinate of the scaling
1167      *  element of the affine transformation matrix.
1168      * @see #getMatrix
1169      * @since 1.2
1170      */
1171     public double getScaleX() {
1172         return m00;
1173     }
1174 
1175     /**
1176      * Returns the Y coordinate scaling element (m11) of the 3x3
1177      * affine transformation matrix. However, this return value cannot be used
1178      * to determine the amount by which Y-coordinate is stretched or contracted.
1179      * @return a double value that is the Y coordinate of the scaling
1180      *  element of the affine transformation matrix.
1181      * @see #getMatrix
1182      * @since 1.2
1183      */
1184     public double getScaleY() {
1185         return m11;
1186     }
1187 
1188     /**
1189      * Returns the X coordinate shearing element (m01) of the 3x3
1190      * affine transformation matrix.
1191      * @return a double value that is the X coordinate of the shearing
1192      *  element of the affine transformation matrix.
1193      * @see #getMatrix
1194      * @since 1.2
1195      */
1196     public double getShearX() {
1197         return m01;
1198     }
1199 
1200     /**
1201      * Returns the Y coordinate shearing element (m10) of the 3x3
1202      * affine transformation matrix.
1203      * @return a double value that is the Y coordinate of the shearing
1204      *  element of the affine transformation matrix.
1205      * @see #getMatrix
1206      * @since 1.2
1207      */
1208     public double getShearY() {
1209         return m10;
1210     }
1211 
1212     /**
1213      * Returns the X coordinate of the translation element (m02) of the
1214      * 3x3 affine transformation matrix.
1215      * @return a double value that is the X coordinate of the translation
1216      *  element of the affine transformation matrix.
1217      * @see #getMatrix
1218      * @since 1.2
1219      */
1220     public double getTranslateX() {
1221         return m02;
1222     }
1223 
1224     /**
1225      * Returns the Y coordinate of the translation element (m12) of the
1226      * 3x3 affine transformation matrix.
1227      * @return a double value that is the Y coordinate of the translation
1228      *  element of the affine transformation matrix.
1229      * @see #getMatrix
1230      * @since 1.2
1231      */
1232     public double getTranslateY() {
1233         return m12;
1234     }
1235 
1236     /**
1237      * Concatenates this transform with a translation transformation.
1238      * This is equivalent to calling concatenate(T), where T is an
1239      * {@code AffineTransform} represented by the following matrix:
1240      * <pre>
1241      *          [   1    0    tx  ]
1242      *          [   0    1    ty  ]
1243      *          [   0    0    1   ]
1244      * </pre>
1245      * @param tx the distance by which coordinates are translated in the
1246      * X axis direction
1247      * @param ty the distance by which coordinates are translated in the
1248      * Y axis direction
1249      * @since 1.2
1250      */
1251     public void translate(double tx, double ty) {
1252         switch (state) {
1253         default:
1254             stateError();
1255             /* NOTREACHED */
1256             return;
1257         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
1258             m02 = tx * m00 + ty * m01 + m02;
1259             m12 = tx * m10 + ty * m11 + m12;
1260             if (m02 == 0.0 && m12 == 0.0) {
1261                 state = APPLY_SHEAR | APPLY_SCALE;
1262                 if (type != TYPE_UNKNOWN) {
1263                     type -= TYPE_TRANSLATION;
1264                 }
1265             }
1266             return;
1267         case (APPLY_SHEAR | APPLY_SCALE):
1268             m02 = tx * m00 + ty * m01;
1269             m12 = tx * m10 + ty * m11;
1270             if (m02 != 0.0 || m12 != 0.0) {
1271                 state = APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE;
1272                 type |= TYPE_TRANSLATION;
1273             }
1274             return;
1275         case (APPLY_SHEAR | APPLY_TRANSLATE):
1276             m02 = ty * m01 + m02;
1277             m12 = tx * m10 + m12;
1278             if (m02 == 0.0 && m12 == 0.0) {
1279                 state = APPLY_SHEAR;
1280                 if (type != TYPE_UNKNOWN) {
1281                     type -= TYPE_TRANSLATION;
1282                 }
1283             }
1284             return;
1285         case (APPLY_SHEAR):
1286             m02 = ty * m01;
1287             m12 = tx * m10;
1288             if (m02 != 0.0 || m12 != 0.0) {
1289                 state = APPLY_SHEAR | APPLY_TRANSLATE;
1290                 type |= TYPE_TRANSLATION;
1291             }
1292             return;
1293         case (APPLY_SCALE | APPLY_TRANSLATE):
1294             m02 = tx * m00 + m02;
1295             m12 = ty * m11 + m12;
1296             if (m02 == 0.0 && m12 == 0.0) {
1297                 state = APPLY_SCALE;
1298                 if (type != TYPE_UNKNOWN) {
1299                     type -= TYPE_TRANSLATION;
1300                 }
1301             }
1302             return;
1303         case (APPLY_SCALE):
1304             m02 = tx * m00;
1305             m12 = ty * m11;
1306             if (m02 != 0.0 || m12 != 0.0) {
1307                 state = APPLY_SCALE | APPLY_TRANSLATE;
1308                 type |= TYPE_TRANSLATION;
1309             }
1310             return;
1311         case (APPLY_TRANSLATE):
1312             m02 = tx + m02;
1313             m12 = ty + m12;
1314             if (m02 == 0.0 && m12 == 0.0) {
1315                 state = APPLY_IDENTITY;
1316                 type = TYPE_IDENTITY;
1317             }
1318             return;
1319         case (APPLY_IDENTITY):
1320             m02 = tx;
1321             m12 = ty;
1322             if (tx != 0.0 || ty != 0.0) {
1323                 state = APPLY_TRANSLATE;
1324                 type = TYPE_TRANSLATION;
1325             }
1326             return;
1327         }
1328     }
1329 
1330     // Utility methods to optimize rotate methods.
1331     // These tables translate the flags during predictable quadrant
1332     // rotations where the shear and scale values are swapped and negated.
1333     private static final int rot90conversion[] = {
1334         /* IDENTITY => */        APPLY_SHEAR,
1335         /* TRANSLATE (TR) => */  APPLY_SHEAR | APPLY_TRANSLATE,
1336         /* SCALE (SC) => */      APPLY_SHEAR,
1337         /* SC | TR => */         APPLY_SHEAR | APPLY_TRANSLATE,
1338         /* SHEAR (SH) => */      APPLY_SCALE,
1339         /* SH | TR => */         APPLY_SCALE | APPLY_TRANSLATE,
1340         /* SH | SC => */         APPLY_SHEAR | APPLY_SCALE,
1341         /* SH | SC | TR => */    APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE,
1342     };
1343     private final void rotate90() {
1344         double M0 = m00;
1345         m00 = m01;
1346         m01 = -M0;
1347         M0 = m10;
1348         m10 = m11;
1349         m11 = -M0;
1350         int state = rot90conversion[this.state];
1351         if ((state & (APPLY_SHEAR | APPLY_SCALE)) == APPLY_SCALE &&
1352             m00 == 1.0 && m11 == 1.0)
1353         {
1354             state -= APPLY_SCALE;
1355         }
1356         this.state = state;
1357         type = TYPE_UNKNOWN;
1358     }
1359     private final void rotate180() {
1360         m00 = -m00;
1361         m11 = -m11;
1362         int state = this.state;
1363         if ((state & (APPLY_SHEAR)) != 0) {
1364             // If there was a shear, then this rotation has no
1365             // effect on the state.
1366             m01 = -m01;
1367             m10 = -m10;
1368         } else {
1369             // No shear means the SCALE state may toggle when
1370             // m00 and m11 are negated.
1371             if (m00 == 1.0 && m11 == 1.0) {
1372                 this.state = state & ~APPLY_SCALE;
1373             } else {
1374                 this.state = state | APPLY_SCALE;
1375             }
1376         }
1377         type = TYPE_UNKNOWN;
1378     }
1379     private final void rotate270() {
1380         double M0 = m00;
1381         m00 = -m01;
1382         m01 = M0;
1383         M0 = m10;
1384         m10 = -m11;
1385         m11 = M0;
1386         int state = rot90conversion[this.state];
1387         if ((state & (APPLY_SHEAR | APPLY_SCALE)) == APPLY_SCALE &&
1388             m00 == 1.0 && m11 == 1.0)
1389         {
1390             state -= APPLY_SCALE;
1391         }
1392         this.state = state;
1393         type = TYPE_UNKNOWN;
1394     }
1395 
1396     /**
1397      * Concatenates this transform with a rotation transformation.
1398      * This is equivalent to calling concatenate(R), where R is an
1399      * {@code AffineTransform} represented by the following matrix:
1400      * <pre>
1401      *          [   cos(theta)    -sin(theta)    0   ]
1402      *          [   sin(theta)     cos(theta)    0   ]
1403      *          [       0              0         1   ]
1404      * </pre>
1405      * Rotating by a positive angle theta rotates points on the positive
1406      * X axis toward the positive Y axis.
1407      * Note also the discussion of
1408      * <a href="#quadrantapproximation">Handling 90-Degree Rotations</a>
1409      * above.
1410      * @param theta the angle of rotation measured in radians
1411      * @since 1.2
1412      */
1413     public void rotate(double theta) {
1414         double sin = Math.sin(theta);
1415         if (sin == 1.0) {
1416             rotate90();
1417         } else if (sin == -1.0) {
1418             rotate270();
1419         } else {
1420             double cos = Math.cos(theta);
1421             if (cos == -1.0) {
1422                 rotate180();
1423             } else if (cos != 1.0) {
1424                 double M0, M1;
1425                 M0 = m00;
1426                 M1 = m01;
1427                 m00 =  cos * M0 + sin * M1;
1428                 m01 = -sin * M0 + cos * M1;
1429                 M0 = m10;
1430                 M1 = m11;
1431                 m10 =  cos * M0 + sin * M1;
1432                 m11 = -sin * M0 + cos * M1;
1433                 updateState();
1434             }
1435         }
1436     }
1437 
1438     /**
1439      * Concatenates this transform with a transform that rotates
1440      * coordinates around an anchor point.
1441      * This operation is equivalent to translating the coordinates so
1442      * that the anchor point is at the origin (S1), then rotating them
1443      * about the new origin (S2), and finally translating so that the
1444      * intermediate origin is restored to the coordinates of the original
1445      * anchor point (S3).
1446      * <p>
1447      * This operation is equivalent to the following sequence of calls:
1448      * <pre>
1449      *     translate(anchorx, anchory);      // S3: final translation
1450      *     rotate(theta);                    // S2: rotate around anchor
1451      *     translate(-anchorx, -anchory);    // S1: translate anchor to origin
1452      * </pre>
1453      * Rotating by a positive angle theta rotates points on the positive
1454      * X axis toward the positive Y axis.
1455      * Note also the discussion of
1456      * <a href="#quadrantapproximation">Handling 90-Degree Rotations</a>
1457      * above.
1458      *
1459      * @param theta the angle of rotation measured in radians
1460      * @param anchorx the X coordinate of the rotation anchor point
1461      * @param anchory the Y coordinate of the rotation anchor point
1462      * @since 1.2
1463      */
1464     public void rotate(double theta, double anchorx, double anchory) {
1465         // REMIND: Simple for now - optimize later
1466         translate(anchorx, anchory);
1467         rotate(theta);
1468         translate(-anchorx, -anchory);
1469     }
1470 
1471     /**
1472      * Concatenates this transform with a transform that rotates
1473      * coordinates according to a rotation vector.
1474      * All coordinates rotate about the origin by the same amount.
1475      * The amount of rotation is such that coordinates along the former
1476      * positive X axis will subsequently align with the vector pointing
1477      * from the origin to the specified vector coordinates.
1478      * If both {@code vecx} and {@code vecy} are 0.0,
1479      * no additional rotation is added to this transform.
1480      * This operation is equivalent to calling:
1481      * <pre>
1482      *          rotate(Math.atan2(vecy, vecx));
1483      * </pre>
1484      *
1485      * @param vecx the X coordinate of the rotation vector
1486      * @param vecy the Y coordinate of the rotation vector
1487      * @since 1.6
1488      */
1489     public void rotate(double vecx, double vecy) {
1490         if (vecy == 0.0) {
1491             if (vecx < 0.0) {
1492                 rotate180();
1493             }
1494             // If vecx > 0.0 - no rotation
1495             // If vecx == 0.0 - undefined rotation - treat as no rotation
1496         } else if (vecx == 0.0) {
1497             if (vecy > 0.0) {
1498                 rotate90();
1499             } else {  // vecy must be < 0.0
1500                 rotate270();
1501             }
1502         } else {
1503             double len = Math.sqrt(vecx * vecx + vecy * vecy);
1504             double sin = vecy / len;
1505             double cos = vecx / len;
1506             double M0, M1;
1507             M0 = m00;
1508             M1 = m01;
1509             m00 =  cos * M0 + sin * M1;
1510             m01 = -sin * M0 + cos * M1;
1511             M0 = m10;
1512             M1 = m11;
1513             m10 =  cos * M0 + sin * M1;
1514             m11 = -sin * M0 + cos * M1;
1515             updateState();
1516         }
1517     }
1518 
1519     /**
1520      * Concatenates this transform with a transform that rotates
1521      * coordinates around an anchor point according to a rotation
1522      * vector.
1523      * All coordinates rotate about the specified anchor coordinates
1524      * by the same amount.
1525      * The amount of rotation is such that coordinates along the former
1526      * positive X axis will subsequently align with the vector pointing
1527      * from the origin to the specified vector coordinates.
1528      * If both {@code vecx} and {@code vecy} are 0.0,
1529      * the transform is not modified in any way.
1530      * This method is equivalent to calling:
1531      * <pre>
1532      *     rotate(Math.atan2(vecy, vecx), anchorx, anchory);
1533      * </pre>
1534      *
1535      * @param vecx the X coordinate of the rotation vector
1536      * @param vecy the Y coordinate of the rotation vector
1537      * @param anchorx the X coordinate of the rotation anchor point
1538      * @param anchory the Y coordinate of the rotation anchor point
1539      * @since 1.6
1540      */
1541     public void rotate(double vecx, double vecy,
1542                        double anchorx, double anchory)
1543     {
1544         // REMIND: Simple for now - optimize later
1545         translate(anchorx, anchory);
1546         rotate(vecx, vecy);
1547         translate(-anchorx, -anchory);
1548     }
1549 
1550     /**
1551      * Concatenates this transform with a transform that rotates
1552      * coordinates by the specified number of quadrants.
1553      * This is equivalent to calling:
1554      * <pre>
1555      *     rotate(numquadrants * Math.PI / 2.0);
1556      * </pre>
1557      * Rotating by a positive number of quadrants rotates points on
1558      * the positive X axis toward the positive Y axis.
1559      * @param numquadrants the number of 90 degree arcs to rotate by
1560      * @since 1.6
1561      */
1562     public void quadrantRotate(int numquadrants) {
1563         switch (numquadrants & 3) {
1564         case 0:
1565             break;
1566         case 1:
1567             rotate90();
1568             break;
1569         case 2:
1570             rotate180();
1571             break;
1572         case 3:
1573             rotate270();
1574             break;
1575         }
1576     }
1577 
1578     /**
1579      * Concatenates this transform with a transform that rotates
1580      * coordinates by the specified number of quadrants around
1581      * the specified anchor point.
1582      * This method is equivalent to calling:
1583      * <pre>
1584      *     rotate(numquadrants * Math.PI / 2.0, anchorx, anchory);
1585      * </pre>
1586      * Rotating by a positive number of quadrants rotates points on
1587      * the positive X axis toward the positive Y axis.
1588      *
1589      * @param numquadrants the number of 90 degree arcs to rotate by
1590      * @param anchorx the X coordinate of the rotation anchor point
1591      * @param anchory the Y coordinate of the rotation anchor point
1592      * @since 1.6
1593      */
1594     public void quadrantRotate(int numquadrants,
1595                                double anchorx, double anchory)
1596     {
1597         switch (numquadrants & 3) {
1598         case 0:
1599             return;
1600         case 1:
1601             m02 += anchorx * (m00 - m01) + anchory * (m01 + m00);
1602             m12 += anchorx * (m10 - m11) + anchory * (m11 + m10);
1603             rotate90();
1604             break;
1605         case 2:
1606             m02 += anchorx * (m00 + m00) + anchory * (m01 + m01);
1607             m12 += anchorx * (m10 + m10) + anchory * (m11 + m11);
1608             rotate180();
1609             break;
1610         case 3:
1611             m02 += anchorx * (m00 + m01) + anchory * (m01 - m00);
1612             m12 += anchorx * (m10 + m11) + anchory * (m11 - m10);
1613             rotate270();
1614             break;
1615         }
1616         if (m02 == 0.0 && m12 == 0.0) {
1617             state &= ~APPLY_TRANSLATE;
1618         } else {
1619             state |= APPLY_TRANSLATE;
1620         }
1621     }
1622 
1623     /**
1624      * Concatenates this transform with a scaling transformation.
1625      * This is equivalent to calling concatenate(S), where S is an
1626      * {@code AffineTransform} represented by the following matrix:
1627      * <pre>
1628      *          [   sx   0    0   ]
1629      *          [   0    sy   0   ]
1630      *          [   0    0    1   ]
1631      * </pre>
1632      * @param sx the factor by which coordinates are scaled along the
1633      * X axis direction
1634      * @param sy the factor by which coordinates are scaled along the
1635      * Y axis direction
1636      * @since 1.2
1637      */
1638     @SuppressWarnings("fallthrough")
1639     public void scale(double sx, double sy) {
1640         int state = this.state;
1641         switch (state) {
1642         default:
1643             stateError();
1644             /* NOTREACHED */
1645         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
1646         case (APPLY_SHEAR | APPLY_SCALE):
1647             m00 *= sx;
1648             m11 *= sy;
1649             /* NOBREAK */
1650         case (APPLY_SHEAR | APPLY_TRANSLATE):
1651         case (APPLY_SHEAR):
1652             m01 *= sy;
1653             m10 *= sx;
1654             if (m01 == 0 && m10 == 0) {
1655                 state &= APPLY_TRANSLATE;
1656                 if (m00 == 1.0 && m11 == 1.0) {
1657                     this.type = (state == APPLY_IDENTITY
1658                                  ? TYPE_IDENTITY
1659                                  : TYPE_TRANSLATION);
1660                 } else {
1661                     state |= APPLY_SCALE;
1662                     this.type = TYPE_UNKNOWN;
1663                 }
1664                 this.state = state;
1665             }
1666             return;
1667         case (APPLY_SCALE | APPLY_TRANSLATE):
1668         case (APPLY_SCALE):
1669             m00 *= sx;
1670             m11 *= sy;
1671             if (m00 == 1.0 && m11 == 1.0) {
1672                 this.state = (state &= APPLY_TRANSLATE);
1673                 this.type = (state == APPLY_IDENTITY
1674                              ? TYPE_IDENTITY
1675                              : TYPE_TRANSLATION);
1676             } else {
1677                 this.type = TYPE_UNKNOWN;
1678             }
1679             return;
1680         case (APPLY_TRANSLATE):
1681         case (APPLY_IDENTITY):
1682             m00 = sx;
1683             m11 = sy;
1684             if (sx != 1.0 || sy != 1.0) {
1685                 this.state = state | APPLY_SCALE;
1686                 this.type = TYPE_UNKNOWN;
1687             }
1688             return;
1689         }
1690     }
1691 
1692     /**
1693      * Concatenates this transform with a shearing transformation.
1694      * This is equivalent to calling concatenate(SH), where SH is an
1695      * {@code AffineTransform} represented by the following matrix:
1696      * <pre>
1697      *          [   1   shx   0   ]
1698      *          [  shy   1    0   ]
1699      *          [   0    0    1   ]
1700      * </pre>
1701      * @param shx the multiplier by which coordinates are shifted in the
1702      * direction of the positive X axis as a factor of their Y coordinate
1703      * @param shy the multiplier by which coordinates are shifted in the
1704      * direction of the positive Y axis as a factor of their X coordinate
1705      * @since 1.2
1706      */
1707     public void shear(double shx, double shy) {
1708         int state = this.state;
1709         switch (state) {
1710         default:
1711             stateError();
1712             /* NOTREACHED */
1713             return;
1714         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
1715         case (APPLY_SHEAR | APPLY_SCALE):
1716             double M0, M1;
1717             M0 = m00;
1718             M1 = m01;
1719             m00 = M0 + M1 * shy;
1720             m01 = M0 * shx + M1;
1721 
1722             M0 = m10;
1723             M1 = m11;
1724             m10 = M0 + M1 * shy;
1725             m11 = M0 * shx + M1;
1726             updateState();
1727             return;
1728         case (APPLY_SHEAR | APPLY_TRANSLATE):
1729         case (APPLY_SHEAR):
1730             m00 = m01 * shy;
1731             m11 = m10 * shx;
1732             if (m00 != 0.0 || m11 != 0.0) {
1733                 this.state = state | APPLY_SCALE;
1734             }
1735             this.type = TYPE_UNKNOWN;
1736             return;
1737         case (APPLY_SCALE | APPLY_TRANSLATE):
1738         case (APPLY_SCALE):
1739             m01 = m00 * shx;
1740             m10 = m11 * shy;
1741             if (m01 != 0.0 || m10 != 0.0) {
1742                 this.state = state | APPLY_SHEAR;
1743             }
1744             this.type = TYPE_UNKNOWN;
1745             return;
1746         case (APPLY_TRANSLATE):
1747         case (APPLY_IDENTITY):
1748             m01 = shx;
1749             m10 = shy;
1750             if (m01 != 0.0 || m10 != 0.0) {
1751                 this.state = state | APPLY_SCALE | APPLY_SHEAR;
1752                 this.type = TYPE_UNKNOWN;
1753             }
1754             return;
1755         }
1756     }
1757 
1758     /**
1759      * Resets this transform to the Identity transform.
1760      * @since 1.2
1761      */
1762     public void setToIdentity() {
1763         m00 = m11 = 1.0;
1764         m10 = m01 = m02 = m12 = 0.0;
1765         state = APPLY_IDENTITY;
1766         type = TYPE_IDENTITY;
1767     }
1768 
1769     /**
1770      * Sets this transform to a translation transformation.
1771      * The matrix representing this transform becomes:
1772      * <pre>
1773      *          [   1    0    tx  ]
1774      *          [   0    1    ty  ]
1775      *          [   0    0    1   ]
1776      * </pre>
1777      * @param tx the distance by which coordinates are translated in the
1778      * X axis direction
1779      * @param ty the distance by which coordinates are translated in the
1780      * Y axis direction
1781      * @since 1.2
1782      */
1783     public void setToTranslation(double tx, double ty) {
1784         m00 = 1.0;
1785         m10 = 0.0;
1786         m01 = 0.0;
1787         m11 = 1.0;
1788         m02 = tx;
1789         m12 = ty;
1790         if (tx != 0.0 || ty != 0.0) {
1791             state = APPLY_TRANSLATE;
1792             type = TYPE_TRANSLATION;
1793         } else {
1794             state = APPLY_IDENTITY;
1795             type = TYPE_IDENTITY;
1796         }
1797     }
1798 
1799     /**
1800      * Sets this transform to a rotation transformation.
1801      * The matrix representing this transform becomes:
1802      * <pre>
1803      *          [   cos(theta)    -sin(theta)    0   ]
1804      *          [   sin(theta)     cos(theta)    0   ]
1805      *          [       0              0         1   ]
1806      * </pre>
1807      * Rotating by a positive angle theta rotates points on the positive
1808      * X axis toward the positive Y axis.
1809      * Note also the discussion of
1810      * <a href="#quadrantapproximation">Handling 90-Degree Rotations</a>
1811      * above.
1812      * @param theta the angle of rotation measured in radians
1813      * @since 1.2
1814      */
1815     public void setToRotation(double theta) {
1816         double sin = Math.sin(theta);
1817         double cos;
1818         if (sin == 1.0 || sin == -1.0) {
1819             cos = 0.0;
1820             state = APPLY_SHEAR;
1821             type = TYPE_QUADRANT_ROTATION;
1822         } else {
1823             cos = Math.cos(theta);
1824             if (cos == -1.0) {
1825                 sin = 0.0;
1826                 state = APPLY_SCALE;
1827                 type = TYPE_QUADRANT_ROTATION;
1828             } else if (cos == 1.0) {
1829                 sin = 0.0;
1830                 state = APPLY_IDENTITY;
1831                 type = TYPE_IDENTITY;
1832             } else {
1833                 state = APPLY_SHEAR | APPLY_SCALE;
1834                 type = TYPE_GENERAL_ROTATION;
1835             }
1836         }
1837         m00 =  cos;
1838         m10 =  sin;
1839         m01 = -sin;
1840         m11 =  cos;
1841         m02 =  0.0;
1842         m12 =  0.0;
1843     }
1844 
1845     /**
1846      * Sets this transform to a translated rotation transformation.
1847      * This operation is equivalent to translating the coordinates so
1848      * that the anchor point is at the origin (S1), then rotating them
1849      * about the new origin (S2), and finally translating so that the
1850      * intermediate origin is restored to the coordinates of the original
1851      * anchor point (S3).
1852      * <p>
1853      * This operation is equivalent to the following sequence of calls:
1854      * <pre>
1855      *     setToTranslation(anchorx, anchory); // S3: final translation
1856      *     rotate(theta);                      // S2: rotate around anchor
1857      *     translate(-anchorx, -anchory);      // S1: translate anchor to origin
1858      * </pre>
1859      * The matrix representing this transform becomes:
1860      * <pre>
1861      *          [   cos(theta)    -sin(theta)    x-x*cos+y*sin  ]
1862      *          [   sin(theta)     cos(theta)    y-x*sin-y*cos  ]
1863      *          [       0              0               1        ]
1864      * </pre>
1865      * Rotating by a positive angle theta rotates points on the positive
1866      * X axis toward the positive Y axis.
1867      * Note also the discussion of
1868      * <a href="#quadrantapproximation">Handling 90-Degree Rotations</a>
1869      * above.
1870      *
1871      * @param theta the angle of rotation measured in radians
1872      * @param anchorx the X coordinate of the rotation anchor point
1873      * @param anchory the Y coordinate of the rotation anchor point
1874      * @since 1.2
1875      */
1876     public void setToRotation(double theta, double anchorx, double anchory) {
1877         setToRotation(theta);
1878         double sin = m10;
1879         double oneMinusCos = 1.0 - m00;
1880         m02 = anchorx * oneMinusCos + anchory * sin;
1881         m12 = anchory * oneMinusCos - anchorx * sin;
1882         if (m02 != 0.0 || m12 != 0.0) {
1883             state |= APPLY_TRANSLATE;
1884             type |= TYPE_TRANSLATION;
1885         }
1886     }
1887 
1888     /**
1889      * Sets this transform to a rotation transformation that rotates
1890      * coordinates according to a rotation vector.
1891      * All coordinates rotate about the origin by the same amount.
1892      * The amount of rotation is such that coordinates along the former
1893      * positive X axis will subsequently align with the vector pointing
1894      * from the origin to the specified vector coordinates.
1895      * If both {@code vecx} and {@code vecy} are 0.0,
1896      * the transform is set to an identity transform.
1897      * This operation is equivalent to calling:
1898      * <pre>
1899      *     setToRotation(Math.atan2(vecy, vecx));
1900      * </pre>
1901      *
1902      * @param vecx the X coordinate of the rotation vector
1903      * @param vecy the Y coordinate of the rotation vector
1904      * @since 1.6
1905      */
1906     public void setToRotation(double vecx, double vecy) {
1907         double sin, cos;
1908         if (vecy == 0) {
1909             sin = 0.0;
1910             if (vecx < 0.0) {
1911                 cos = -1.0;
1912                 state = APPLY_SCALE;
1913                 type = TYPE_QUADRANT_ROTATION;
1914             } else {
1915                 cos = 1.0;
1916                 state = APPLY_IDENTITY;
1917                 type = TYPE_IDENTITY;
1918             }
1919         } else if (vecx == 0) {
1920             cos = 0.0;
1921             sin = (vecy > 0.0) ? 1.0 : -1.0;
1922             state = APPLY_SHEAR;
1923             type = TYPE_QUADRANT_ROTATION;
1924         } else {
1925             double len = Math.sqrt(vecx * vecx + vecy * vecy);
1926             cos = vecx / len;
1927             sin = vecy / len;
1928             state = APPLY_SHEAR | APPLY_SCALE;
1929             type = TYPE_GENERAL_ROTATION;
1930         }
1931         m00 =  cos;
1932         m10 =  sin;
1933         m01 = -sin;
1934         m11 =  cos;
1935         m02 =  0.0;
1936         m12 =  0.0;
1937     }
1938 
1939     /**
1940      * Sets this transform to a rotation transformation that rotates
1941      * coordinates around an anchor point according to a rotation
1942      * vector.
1943      * All coordinates rotate about the specified anchor coordinates
1944      * by the same amount.
1945      * The amount of rotation is such that coordinates along the former
1946      * positive X axis will subsequently align with the vector pointing
1947      * from the origin to the specified vector coordinates.
1948      * If both {@code vecx} and {@code vecy} are 0.0,
1949      * the transform is set to an identity transform.
1950      * This operation is equivalent to calling:
1951      * <pre>
1952      *     setToTranslation(Math.atan2(vecy, vecx), anchorx, anchory);
1953      * </pre>
1954      *
1955      * @param vecx the X coordinate of the rotation vector
1956      * @param vecy the Y coordinate of the rotation vector
1957      * @param anchorx the X coordinate of the rotation anchor point
1958      * @param anchory the Y coordinate of the rotation anchor point
1959      * @since 1.6
1960      */
1961     public void setToRotation(double vecx, double vecy,
1962                               double anchorx, double anchory)
1963     {
1964         setToRotation(vecx, vecy);
1965         double sin = m10;
1966         double oneMinusCos = 1.0 - m00;
1967         m02 = anchorx * oneMinusCos + anchory * sin;
1968         m12 = anchory * oneMinusCos - anchorx * sin;
1969         if (m02 != 0.0 || m12 != 0.0) {
1970             state |= APPLY_TRANSLATE;
1971             type |= TYPE_TRANSLATION;
1972         }
1973     }
1974 
1975     /**
1976      * Sets this transform to a rotation transformation that rotates
1977      * coordinates by the specified number of quadrants.
1978      * This operation is equivalent to calling:
1979      * <pre>
1980      *     setToRotation(numquadrants * Math.PI / 2.0);
1981      * </pre>
1982      * Rotating by a positive number of quadrants rotates points on
1983      * the positive X axis toward the positive Y axis.
1984      * @param numquadrants the number of 90 degree arcs to rotate by
1985      * @since 1.6
1986      */
1987     public void setToQuadrantRotation(int numquadrants) {
1988         switch (numquadrants & 3) {
1989         case 0:
1990             m00 =  1.0;
1991             m10 =  0.0;
1992             m01 =  0.0;
1993             m11 =  1.0;
1994             m02 =  0.0;
1995             m12 =  0.0;
1996             state = APPLY_IDENTITY;
1997             type = TYPE_IDENTITY;
1998             break;
1999         case 1:
2000             m00 =  0.0;
2001             m10 =  1.0;
2002             m01 = -1.0;
2003             m11 =  0.0;
2004             m02 =  0.0;
2005             m12 =  0.0;
2006             state = APPLY_SHEAR;
2007             type = TYPE_QUADRANT_ROTATION;
2008             break;
2009         case 2:
2010             m00 = -1.0;
2011             m10 =  0.0;
2012             m01 =  0.0;
2013             m11 = -1.0;
2014             m02 =  0.0;
2015             m12 =  0.0;
2016             state = APPLY_SCALE;
2017             type = TYPE_QUADRANT_ROTATION;
2018             break;
2019         case 3:
2020             m00 =  0.0;
2021             m10 = -1.0;
2022             m01 =  1.0;
2023             m11 =  0.0;
2024             m02 =  0.0;
2025             m12 =  0.0;
2026             state = APPLY_SHEAR;
2027             type = TYPE_QUADRANT_ROTATION;
2028             break;
2029         }
2030     }
2031 
2032     /**
2033      * Sets this transform to a translated rotation transformation
2034      * that rotates coordinates by the specified number of quadrants
2035      * around the specified anchor point.
2036      * This operation is equivalent to calling:
2037      * <pre>
2038      *     setToRotation(numquadrants * Math.PI / 2.0, anchorx, anchory);
2039      * </pre>
2040      * Rotating by a positive number of quadrants rotates points on
2041      * the positive X axis toward the positive Y axis.
2042      *
2043      * @param numquadrants the number of 90 degree arcs to rotate by
2044      * @param anchorx the X coordinate of the rotation anchor point
2045      * @param anchory the Y coordinate of the rotation anchor point
2046      * @since 1.6
2047      */
2048     public void setToQuadrantRotation(int numquadrants,
2049                                       double anchorx, double anchory)
2050     {
2051         switch (numquadrants & 3) {
2052         case 0:
2053             m00 =  1.0;
2054             m10 =  0.0;
2055             m01 =  0.0;
2056             m11 =  1.0;
2057             m02 =  0.0;
2058             m12 =  0.0;
2059             state = APPLY_IDENTITY;
2060             type = TYPE_IDENTITY;
2061             break;
2062         case 1:
2063             m00 =  0.0;
2064             m10 =  1.0;
2065             m01 = -1.0;
2066             m11 =  0.0;
2067             m02 =  anchorx + anchory;
2068             m12 =  anchory - anchorx;
2069             if (m02 == 0.0 && m12 == 0.0) {
2070                 state = APPLY_SHEAR;
2071                 type = TYPE_QUADRANT_ROTATION;
2072             } else {
2073                 state = APPLY_SHEAR | APPLY_TRANSLATE;
2074                 type = TYPE_QUADRANT_ROTATION | TYPE_TRANSLATION;
2075             }
2076             break;
2077         case 2:
2078             m00 = -1.0;
2079             m10 =  0.0;
2080             m01 =  0.0;
2081             m11 = -1.0;
2082             m02 =  anchorx + anchorx;
2083             m12 =  anchory + anchory;
2084             if (m02 == 0.0 && m12 == 0.0) {
2085                 state = APPLY_SCALE;
2086                 type = TYPE_QUADRANT_ROTATION;
2087             } else {
2088                 state = APPLY_SCALE | APPLY_TRANSLATE;
2089                 type = TYPE_QUADRANT_ROTATION | TYPE_TRANSLATION;
2090             }
2091             break;
2092         case 3:
2093             m00 =  0.0;
2094             m10 = -1.0;
2095             m01 =  1.0;
2096             m11 =  0.0;
2097             m02 =  anchorx - anchory;
2098             m12 =  anchory + anchorx;
2099             if (m02 == 0.0 && m12 == 0.0) {
2100                 state = APPLY_SHEAR;
2101                 type = TYPE_QUADRANT_ROTATION;
2102             } else {
2103                 state = APPLY_SHEAR | APPLY_TRANSLATE;
2104                 type = TYPE_QUADRANT_ROTATION | TYPE_TRANSLATION;
2105             }
2106             break;
2107         }
2108     }
2109 
2110     /**
2111      * Sets this transform to a scaling transformation.
2112      * The matrix representing this transform becomes:
2113      * <pre>
2114      *          [   sx   0    0   ]
2115      *          [   0    sy   0   ]
2116      *          [   0    0    1   ]
2117      * </pre>
2118      * @param sx the factor by which coordinates are scaled along the
2119      * X axis direction
2120      * @param sy the factor by which coordinates are scaled along the
2121      * Y axis direction
2122      * @since 1.2
2123      */
2124     public void setToScale(double sx, double sy) {
2125         m00 = sx;
2126         m10 = 0.0;
2127         m01 = 0.0;
2128         m11 = sy;
2129         m02 = 0.0;
2130         m12 = 0.0;
2131         if (sx != 1.0 || sy != 1.0) {
2132             state = APPLY_SCALE;
2133             type = TYPE_UNKNOWN;
2134         } else {
2135             state = APPLY_IDENTITY;
2136             type = TYPE_IDENTITY;
2137         }
2138     }
2139 
2140     /**
2141      * Sets this transform to a shearing transformation.
2142      * The matrix representing this transform becomes:
2143      * <pre>
2144      *          [   1   shx   0   ]
2145      *          [  shy   1    0   ]
2146      *          [   0    0    1   ]
2147      * </pre>
2148      * @param shx the multiplier by which coordinates are shifted in the
2149      * direction of the positive X axis as a factor of their Y coordinate
2150      * @param shy the multiplier by which coordinates are shifted in the
2151      * direction of the positive Y axis as a factor of their X coordinate
2152      * @since 1.2
2153      */
2154     public void setToShear(double shx, double shy) {
2155         m00 = 1.0;
2156         m01 = shx;
2157         m10 = shy;
2158         m11 = 1.0;
2159         m02 = 0.0;
2160         m12 = 0.0;
2161         if (shx != 0.0 || shy != 0.0) {
2162             state = (APPLY_SHEAR | APPLY_SCALE);
2163             type = TYPE_UNKNOWN;
2164         } else {
2165             state = APPLY_IDENTITY;
2166             type = TYPE_IDENTITY;
2167         }
2168     }
2169 
2170     /**
2171      * Sets this transform to a copy of the transform in the specified
2172      * {@code AffineTransform} object.
2173      * @param Tx the {@code AffineTransform} object from which to
2174      * copy the transform
2175      * @since 1.2
2176      */
2177     public void setTransform(AffineTransform Tx) {
2178         this.m00 = Tx.m00;
2179         this.m10 = Tx.m10;
2180         this.m01 = Tx.m01;
2181         this.m11 = Tx.m11;
2182         this.m02 = Tx.m02;
2183         this.m12 = Tx.m12;
2184         this.state = Tx.state;
2185         this.type = Tx.type;
2186     }
2187 
2188     /**
2189      * Sets this transform to the matrix specified by the 6
2190      * double precision values.
2191      *
2192      * @param m00 the X coordinate scaling element of the 3x3 matrix
2193      * @param m10 the Y coordinate shearing element of the 3x3 matrix
2194      * @param m01 the X coordinate shearing element of the 3x3 matrix
2195      * @param m11 the Y coordinate scaling element of the 3x3 matrix
2196      * @param m02 the X coordinate translation element of the 3x3 matrix
2197      * @param m12 the Y coordinate translation element of the 3x3 matrix
2198      * @since 1.2
2199      */
2200     public void setTransform(double m00, double m10,
2201                              double m01, double m11,
2202                              double m02, double m12) {
2203         this.m00 = m00;
2204         this.m10 = m10;
2205         this.m01 = m01;
2206         this.m11 = m11;
2207         this.m02 = m02;
2208         this.m12 = m12;
2209         updateState();
2210     }
2211 
2212     /**
2213      * Concatenates an {@code AffineTransform Tx} to
2214      * this {@code AffineTransform} Cx in the most commonly useful
2215      * way to provide a new user space
2216      * that is mapped to the former user space by {@code Tx}.
2217      * Cx is updated to perform the combined transformation.
2218      * Transforming a point p by the updated transform Cx' is
2219      * equivalent to first transforming p by {@code Tx} and then
2220      * transforming the result by the original transform Cx like this:
2221      * Cx'(p) = Cx(Tx(p))
2222      * In matrix notation, if this transform Cx is
2223      * represented by the matrix [this] and {@code Tx} is represented
2224      * by the matrix [Tx] then this method does the following:
2225      * <pre>
2226      *          [this] = [this] x [Tx]
2227      * </pre>
2228      * @param Tx the {@code AffineTransform} object to be
2229      * concatenated with this {@code AffineTransform} object.
2230      * @see #preConcatenate
2231      * @since 1.2
2232      */
2233     @SuppressWarnings("fallthrough")
2234     public void concatenate(AffineTransform Tx) {
2235         double M0, M1;
2236         double T00, T01, T10, T11;
2237         double T02, T12;
2238         int mystate = state;
2239         int txstate = Tx.state;
2240         switch ((txstate << HI_SHIFT) | mystate) {
2241 
2242             /* ---------- Tx == IDENTITY cases ---------- */
2243         case (HI_IDENTITY | APPLY_IDENTITY):
2244         case (HI_IDENTITY | APPLY_TRANSLATE):
2245         case (HI_IDENTITY | APPLY_SCALE):
2246         case (HI_IDENTITY | APPLY_SCALE | APPLY_TRANSLATE):
2247         case (HI_IDENTITY | APPLY_SHEAR):
2248         case (HI_IDENTITY | APPLY_SHEAR | APPLY_TRANSLATE):
2249         case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE):
2250         case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2251             return;
2252 
2253             /* ---------- this == IDENTITY cases ---------- */
2254         case (HI_SHEAR | HI_SCALE | HI_TRANSLATE | APPLY_IDENTITY):
2255             m01 = Tx.m01;
2256             m10 = Tx.m10;
2257             /* NOBREAK */
2258         case (HI_SCALE | HI_TRANSLATE | APPLY_IDENTITY):
2259             m00 = Tx.m00;
2260             m11 = Tx.m11;
2261             /* NOBREAK */
2262         case (HI_TRANSLATE | APPLY_IDENTITY):
2263             m02 = Tx.m02;
2264             m12 = Tx.m12;
2265             state = txstate;
2266             type = Tx.type;
2267             return;
2268         case (HI_SHEAR | HI_SCALE | APPLY_IDENTITY):
2269             m01 = Tx.m01;
2270             m10 = Tx.m10;
2271             /* NOBREAK */
2272         case (HI_SCALE | APPLY_IDENTITY):
2273             m00 = Tx.m00;
2274             m11 = Tx.m11;
2275             state = txstate;
2276             type = Tx.type;
2277             return;
2278         case (HI_SHEAR | HI_TRANSLATE | APPLY_IDENTITY):
2279             m02 = Tx.m02;
2280             m12 = Tx.m12;
2281             /* NOBREAK */
2282         case (HI_SHEAR | APPLY_IDENTITY):
2283             m01 = Tx.m01;
2284             m10 = Tx.m10;
2285             m00 = m11 = 0.0;
2286             state = txstate;
2287             type = Tx.type;
2288             return;
2289 
2290             /* ---------- Tx == TRANSLATE cases ---------- */
2291         case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2292         case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE):
2293         case (HI_TRANSLATE | APPLY_SHEAR | APPLY_TRANSLATE):
2294         case (HI_TRANSLATE | APPLY_SHEAR):
2295         case (HI_TRANSLATE | APPLY_SCALE | APPLY_TRANSLATE):
2296         case (HI_TRANSLATE | APPLY_SCALE):
2297         case (HI_TRANSLATE | APPLY_TRANSLATE):
2298             translate(Tx.m02, Tx.m12);
2299             return;
2300 
2301             /* ---------- Tx == SCALE cases ---------- */
2302         case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2303         case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE):
2304         case (HI_SCALE | APPLY_SHEAR | APPLY_TRANSLATE):
2305         case (HI_SCALE | APPLY_SHEAR):
2306         case (HI_SCALE | APPLY_SCALE | APPLY_TRANSLATE):
2307         case (HI_SCALE | APPLY_SCALE):
2308         case (HI_SCALE | APPLY_TRANSLATE):
2309             scale(Tx.m00, Tx.m11);
2310             return;
2311 
2312             /* ---------- Tx == SHEAR cases ---------- */
2313         case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2314         case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE):
2315             T01 = Tx.m01; T10 = Tx.m10;
2316             M0 = m00;
2317             m00 = m01 * T10;
2318             m01 = M0 * T01;
2319             M0 = m10;
2320             m10 = m11 * T10;
2321             m11 = M0 * T01;
2322             type = TYPE_UNKNOWN;
2323             return;
2324         case (HI_SHEAR | APPLY_SHEAR | APPLY_TRANSLATE):
2325         case (HI_SHEAR | APPLY_SHEAR):
2326             m00 = m01 * Tx.m10;
2327             m01 = 0.0;
2328             m11 = m10 * Tx.m01;
2329             m10 = 0.0;
2330             state = mystate ^ (APPLY_SHEAR | APPLY_SCALE);
2331             type = TYPE_UNKNOWN;
2332             return;
2333         case (HI_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2334         case (HI_SHEAR | APPLY_SCALE):
2335             m01 = m00 * Tx.m01;
2336             m00 = 0.0;
2337             m10 = m11 * Tx.m10;
2338             m11 = 0.0;
2339             state = mystate ^ (APPLY_SHEAR | APPLY_SCALE);
2340             type = TYPE_UNKNOWN;
2341             return;
2342         case (HI_SHEAR | APPLY_TRANSLATE):
2343             m00 = 0.0;
2344             m01 = Tx.m01;
2345             m10 = Tx.m10;
2346             m11 = 0.0;
2347             state = APPLY_TRANSLATE | APPLY_SHEAR;
2348             type = TYPE_UNKNOWN;
2349             return;
2350         }
2351         // If Tx has more than one attribute, it is not worth optimizing
2352         // all of those cases...
2353         T00 = Tx.m00; T01 = Tx.m01; T02 = Tx.m02;
2354         T10 = Tx.m10; T11 = Tx.m11; T12 = Tx.m12;
2355         switch (mystate) {
2356         default:
2357             stateError();
2358             /* NOTREACHED */
2359         case (APPLY_SHEAR | APPLY_SCALE):
2360             state = mystate | txstate;
2361             /* NOBREAK */
2362         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2363             M0 = m00;
2364             M1 = m01;
2365             m00  = T00 * M0 + T10 * M1;
2366             m01  = T01 * M0 + T11 * M1;
2367             m02 += T02 * M0 + T12 * M1;
2368 
2369             M0 = m10;
2370             M1 = m11;
2371             m10  = T00 * M0 + T10 * M1;
2372             m11  = T01 * M0 + T11 * M1;
2373             m12 += T02 * M0 + T12 * M1;
2374             type = TYPE_UNKNOWN;
2375             return;
2376 
2377         case (APPLY_SHEAR | APPLY_TRANSLATE):
2378         case (APPLY_SHEAR):
2379             M0 = m01;
2380             m00  = T10 * M0;
2381             m01  = T11 * M0;
2382             m02 += T12 * M0;
2383 
2384             M0 = m10;
2385             m10  = T00 * M0;
2386             m11  = T01 * M0;
2387             m12 += T02 * M0;
2388             break;
2389 
2390         case (APPLY_SCALE | APPLY_TRANSLATE):
2391         case (APPLY_SCALE):
2392             M0 = m00;
2393             m00  = T00 * M0;
2394             m01  = T01 * M0;
2395             m02 += T02 * M0;
2396 
2397             M0 = m11;
2398             m10  = T10 * M0;
2399             m11  = T11 * M0;
2400             m12 += T12 * M0;
2401             break;
2402 
2403         case (APPLY_TRANSLATE):
2404             m00  = T00;
2405             m01  = T01;
2406             m02 += T02;
2407 
2408             m10  = T10;
2409             m11  = T11;
2410             m12 += T12;
2411             state = txstate | APPLY_TRANSLATE;
2412             type = TYPE_UNKNOWN;
2413             return;
2414         }
2415         updateState();
2416     }
2417 
2418     /**
2419      * Concatenates an {@code AffineTransform Tx} to
2420      * this {@code AffineTransform} Cx
2421      * in a less commonly used way such that {@code Tx} modifies the
2422      * coordinate transformation relative to the absolute pixel
2423      * space rather than relative to the existing user space.
2424      * Cx is updated to perform the combined transformation.
2425      * Transforming a point p by the updated transform Cx' is
2426      * equivalent to first transforming p by the original transform
2427      * Cx and then transforming the result by
2428      * {@code Tx} like this:
2429      * Cx'(p) = Tx(Cx(p))
2430      * In matrix notation, if this transform Cx
2431      * is represented by the matrix [this] and {@code Tx} is
2432      * represented by the matrix [Tx] then this method does the
2433      * following:
2434      * <pre>
2435      *          [this] = [Tx] x [this]
2436      * </pre>
2437      * @param Tx the {@code AffineTransform} object to be
2438      * concatenated with this {@code AffineTransform} object.
2439      * @see #concatenate
2440      * @since 1.2
2441      */
2442     @SuppressWarnings("fallthrough")
2443     public void preConcatenate(AffineTransform Tx) {
2444         double M0, M1;
2445         double T00, T01, T10, T11;
2446         double T02, T12;
2447         int mystate = state;
2448         int txstate = Tx.state;
2449         switch ((txstate << HI_SHIFT) | mystate) {
2450         case (HI_IDENTITY | APPLY_IDENTITY):
2451         case (HI_IDENTITY | APPLY_TRANSLATE):
2452         case (HI_IDENTITY | APPLY_SCALE):
2453         case (HI_IDENTITY | APPLY_SCALE | APPLY_TRANSLATE):
2454         case (HI_IDENTITY | APPLY_SHEAR):
2455         case (HI_IDENTITY | APPLY_SHEAR | APPLY_TRANSLATE):
2456         case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE):
2457         case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2458             // Tx is IDENTITY...
2459             return;
2460 
2461         case (HI_TRANSLATE | APPLY_IDENTITY):
2462         case (HI_TRANSLATE | APPLY_SCALE):
2463         case (HI_TRANSLATE | APPLY_SHEAR):
2464         case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE):
2465             // Tx is TRANSLATE, this has no TRANSLATE
2466             m02 = Tx.m02;
2467             m12 = Tx.m12;
2468             state = mystate | APPLY_TRANSLATE;
2469             type |= TYPE_TRANSLATION;
2470             return;
2471 
2472         case (HI_TRANSLATE | APPLY_TRANSLATE):
2473         case (HI_TRANSLATE | APPLY_SCALE | APPLY_TRANSLATE):
2474         case (HI_TRANSLATE | APPLY_SHEAR | APPLY_TRANSLATE):
2475         case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2476             // Tx is TRANSLATE, this has one too
2477             m02 = m02 + Tx.m02;
2478             m12 = m12 + Tx.m12;
2479             return;
2480 
2481         case (HI_SCALE | APPLY_TRANSLATE):
2482         case (HI_SCALE | APPLY_IDENTITY):
2483             // Only these two existing states need a new state
2484             state = mystate | APPLY_SCALE;
2485             /* NOBREAK */
2486         case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2487         case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE):
2488         case (HI_SCALE | APPLY_SHEAR | APPLY_TRANSLATE):
2489         case (HI_SCALE | APPLY_SHEAR):
2490         case (HI_SCALE | APPLY_SCALE | APPLY_TRANSLATE):
2491         case (HI_SCALE | APPLY_SCALE):
2492             // Tx is SCALE, this is anything
2493             T00 = Tx.m00;
2494             T11 = Tx.m11;
2495             if ((mystate & APPLY_SHEAR) != 0) {
2496                 m01 = m01 * T00;
2497                 m10 = m10 * T11;
2498                 if ((mystate & APPLY_SCALE) != 0) {
2499                     m00 = m00 * T00;
2500                     m11 = m11 * T11;
2501                 }
2502             } else {
2503                 m00 = m00 * T00;
2504                 m11 = m11 * T11;
2505             }
2506             if ((mystate & APPLY_TRANSLATE) != 0) {
2507                 m02 = m02 * T00;
2508                 m12 = m12 * T11;
2509             }
2510             type = TYPE_UNKNOWN;
2511             return;
2512         case (HI_SHEAR | APPLY_SHEAR | APPLY_TRANSLATE):
2513         case (HI_SHEAR | APPLY_SHEAR):
2514             mystate = mystate | APPLY_SCALE;
2515             /* NOBREAK */
2516         case (HI_SHEAR | APPLY_TRANSLATE):
2517         case (HI_SHEAR | APPLY_IDENTITY):
2518         case (HI_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2519         case (HI_SHEAR | APPLY_SCALE):
2520             state = mystate ^ APPLY_SHEAR;
2521             /* NOBREAK */
2522         case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2523         case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE):
2524             // Tx is SHEAR, this is anything
2525             T01 = Tx.m01;
2526             T10 = Tx.m10;
2527 
2528             M0 = m00;
2529             m00 = m10 * T01;
2530             m10 = M0 * T10;
2531 
2532             M0 = m01;
2533             m01 = m11 * T01;
2534             m11 = M0 * T10;
2535 
2536             M0 = m02;
2537             m02 = m12 * T01;
2538             m12 = M0 * T10;
2539             type = TYPE_UNKNOWN;
2540             return;
2541         }
2542         // If Tx has more than one attribute, it is not worth optimizing
2543         // all of those cases...
2544         T00 = Tx.m00; T01 = Tx.m01; T02 = Tx.m02;
2545         T10 = Tx.m10; T11 = Tx.m11; T12 = Tx.m12;
2546         switch (mystate) {
2547         default:
2548             stateError();
2549             /* NOTREACHED */
2550         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2551             M0 = m02;
2552             M1 = m12;
2553             T02 += M0 * T00 + M1 * T01;
2554             T12 += M0 * T10 + M1 * T11;
2555 
2556             /* NOBREAK */
2557         case (APPLY_SHEAR | APPLY_SCALE):
2558             m02 = T02;
2559             m12 = T12;
2560 
2561             M0 = m00;
2562             M1 = m10;
2563             m00 = M0 * T00 + M1 * T01;
2564             m10 = M0 * T10 + M1 * T11;
2565 
2566             M0 = m01;
2567             M1 = m11;
2568             m01 = M0 * T00 + M1 * T01;
2569             m11 = M0 * T10 + M1 * T11;
2570             break;
2571 
2572         case (APPLY_SHEAR | APPLY_TRANSLATE):
2573             M0 = m02;
2574             M1 = m12;
2575             T02 += M0 * T00 + M1 * T01;
2576             T12 += M0 * T10 + M1 * T11;
2577 
2578             /* NOBREAK */
2579         case (APPLY_SHEAR):
2580             m02 = T02;
2581             m12 = T12;
2582 
2583             M0 = m10;
2584             m00 = M0 * T01;
2585             m10 = M0 * T11;
2586 
2587             M0 = m01;
2588             m01 = M0 * T00;
2589             m11 = M0 * T10;
2590             break;
2591 
2592         case (APPLY_SCALE | APPLY_TRANSLATE):
2593             M0 = m02;
2594             M1 = m12;
2595             T02 += M0 * T00 + M1 * T01;
2596             T12 += M0 * T10 + M1 * T11;
2597 
2598             /* NOBREAK */
2599         case (APPLY_SCALE):
2600             m02 = T02;
2601             m12 = T12;
2602 
2603             M0 = m00;
2604             m00 = M0 * T00;
2605             m10 = M0 * T10;
2606 
2607             M0 = m11;
2608             m01 = M0 * T01;
2609             m11 = M0 * T11;
2610             break;
2611 
2612         case (APPLY_TRANSLATE):
2613             M0 = m02;
2614             M1 = m12;
2615             T02 += M0 * T00 + M1 * T01;
2616             T12 += M0 * T10 + M1 * T11;
2617 
2618             /* NOBREAK */
2619         case (APPLY_IDENTITY):
2620             m02 = T02;
2621             m12 = T12;
2622 
2623             m00 = T00;
2624             m10 = T10;
2625 
2626             m01 = T01;
2627             m11 = T11;
2628 
2629             state = mystate | txstate;
2630             type = TYPE_UNKNOWN;
2631             return;
2632         }
2633         updateState();
2634     }
2635 
2636     /**
2637      * Returns an {@code AffineTransform} object representing the
2638      * inverse transformation.
2639      * The inverse transform Tx' of this transform Tx
2640      * maps coordinates transformed by Tx back
2641      * to their original coordinates.
2642      * In other words, Tx'(Tx(p)) = p = Tx(Tx'(p)).
2643      * <p>
2644      * If this transform maps all coordinates onto a point or a line
2645      * then it will not have an inverse, since coordinates that do
2646      * not lie on the destination point or line will not have an inverse
2647      * mapping.
2648      * The {@code getDeterminant} method can be used to determine if this
2649      * transform has no inverse, in which case an exception will be
2650      * thrown if the {@code createInverse} method is called.
2651      * @return a new {@code AffineTransform} object representing the
2652      * inverse transformation.
2653      * @see #getDeterminant
2654      * @exception NoninvertibleTransformException
2655      * if the matrix cannot be inverted.
2656      * @since 1.2
2657      */
2658     public AffineTransform createInverse()
2659         throws NoninvertibleTransformException
2660     {
2661         double det;
2662         switch (state) {
2663         default:
2664             stateError();
2665             /* NOTREACHED */
2666             return null;
2667         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2668             det = m00 * m11 - m01 * m10;
2669             if (Math.abs(det) <= Double.MIN_VALUE) {
2670                 throw new NoninvertibleTransformException("Determinant is "+
2671                                                           det);
2672             }
2673             return new AffineTransform( m11 / det, -m10 / det,
2674                                        -m01 / det,  m00 / det,
2675                                        (m01 * m12 - m11 * m02) / det,
2676                                        (m10 * m02 - m00 * m12) / det,
2677                                        (APPLY_SHEAR |
2678                                         APPLY_SCALE |
2679                                         APPLY_TRANSLATE));
2680         case (APPLY_SHEAR | APPLY_SCALE):
2681             det = m00 * m11 - m01 * m10;
2682             if (Math.abs(det) <= Double.MIN_VALUE) {
2683                 throw new NoninvertibleTransformException("Determinant is "+
2684                                                           det);
2685             }
2686             return new AffineTransform( m11 / det, -m10 / det,
2687                                        -m01 / det,  m00 / det,
2688                                         0.0,        0.0,
2689                                        (APPLY_SHEAR | APPLY_SCALE));
2690         case (APPLY_SHEAR | APPLY_TRANSLATE):
2691             if (m01 == 0.0 || m10 == 0.0) {
2692                 throw new NoninvertibleTransformException("Determinant is 0");
2693             }
2694             return new AffineTransform( 0.0,        1.0 / m01,
2695                                         1.0 / m10,  0.0,
2696                                        -m12 / m10, -m02 / m01,
2697                                        (APPLY_SHEAR | APPLY_TRANSLATE));
2698         case (APPLY_SHEAR):
2699             if (m01 == 0.0 || m10 == 0.0) {
2700                 throw new NoninvertibleTransformException("Determinant is 0");
2701             }
2702             return new AffineTransform(0.0,       1.0 / m01,
2703                                        1.0 / m10, 0.0,
2704                                        0.0,       0.0,
2705                                        (APPLY_SHEAR));
2706         case (APPLY_SCALE | APPLY_TRANSLATE):
2707             if (m00 == 0.0 || m11 == 0.0) {
2708                 throw new NoninvertibleTransformException("Determinant is 0");
2709             }
2710             return new AffineTransform( 1.0 / m00,  0.0,
2711                                         0.0,        1.0 / m11,
2712                                        -m02 / m00, -m12 / m11,
2713                                        (APPLY_SCALE | APPLY_TRANSLATE));
2714         case (APPLY_SCALE):
2715             if (m00 == 0.0 || m11 == 0.0) {
2716                 throw new NoninvertibleTransformException("Determinant is 0");
2717             }
2718             return new AffineTransform(1.0 / m00, 0.0,
2719                                        0.0,       1.0 / m11,
2720                                        0.0,       0.0,
2721                                        (APPLY_SCALE));
2722         case (APPLY_TRANSLATE):
2723             return new AffineTransform( 1.0,  0.0,
2724                                         0.0,  1.0,
2725                                        -m02, -m12,
2726                                        (APPLY_TRANSLATE));
2727         case (APPLY_IDENTITY):
2728             return new AffineTransform();
2729         }
2730 
2731         /* NOTREACHED */
2732     }
2733 
2734     /**
2735      * Sets this transform to the inverse of itself.
2736      * The inverse transform Tx' of this transform Tx
2737      * maps coordinates transformed by Tx back
2738      * to their original coordinates.
2739      * In other words, Tx'(Tx(p)) = p = Tx(Tx'(p)).
2740      * <p>
2741      * If this transform maps all coordinates onto a point or a line
2742      * then it will not have an inverse, since coordinates that do
2743      * not lie on the destination point or line will not have an inverse
2744      * mapping.
2745      * The {@code getDeterminant} method can be used to determine if this
2746      * transform has no inverse, in which case an exception will be
2747      * thrown if the {@code invert} method is called.
2748      * @see #getDeterminant
2749      * @exception NoninvertibleTransformException
2750      * if the matrix cannot be inverted.
2751      * @since 1.6
2752      */
2753     public void invert()
2754         throws NoninvertibleTransformException
2755     {
2756         double M00, M01, M02;
2757         double M10, M11, M12;
2758         double det;
2759         switch (state) {
2760         default:
2761             stateError();
2762             /* NOTREACHED */
2763             return;
2764         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2765             M00 = m00; M01 = m01; M02 = m02;
2766             M10 = m10; M11 = m11; M12 = m12;
2767             det = M00 * M11 - M01 * M10;
2768             if (Math.abs(det) <= Double.MIN_VALUE) {
2769                 throw new NoninvertibleTransformException("Determinant is "+
2770                                                           det);
2771             }
2772             m00 =  M11 / det;
2773             m10 = -M10 / det;
2774             m01 = -M01 / det;
2775             m11 =  M00 / det;
2776             m02 = (M01 * M12 - M11 * M02) / det;
2777             m12 = (M10 * M02 - M00 * M12) / det;
2778             break;
2779         case (APPLY_SHEAR | APPLY_SCALE):
2780             M00 = m00; M01 = m01;
2781             M10 = m10; M11 = m11;
2782             det = M00 * M11 - M01 * M10;
2783             if (Math.abs(det) <= Double.MIN_VALUE) {
2784                 throw new NoninvertibleTransformException("Determinant is "+
2785                                                           det);
2786             }
2787             m00 =  M11 / det;
2788             m10 = -M10 / det;
2789             m01 = -M01 / det;
2790             m11 =  M00 / det;
2791             // m02 = 0.0;
2792             // m12 = 0.0;
2793             break;
2794         case (APPLY_SHEAR | APPLY_TRANSLATE):
2795             M01 = m01; M02 = m02;
2796             M10 = m10; M12 = m12;
2797             if (M01 == 0.0 || M10 == 0.0) {
2798                 throw new NoninvertibleTransformException("Determinant is 0");
2799             }
2800             // m00 = 0.0;
2801             m10 = 1.0 / M01;
2802             m01 = 1.0 / M10;
2803             // m11 = 0.0;
2804             m02 = -M12 / M10;
2805             m12 = -M02 / M01;
2806             break;
2807         case (APPLY_SHEAR):
2808             M01 = m01;
2809             M10 = m10;
2810             if (M01 == 0.0 || M10 == 0.0) {
2811                 throw new NoninvertibleTransformException("Determinant is 0");
2812             }
2813             // m00 = 0.0;
2814             m10 = 1.0 / M01;
2815             m01 = 1.0 / M10;
2816             // m11 = 0.0;
2817             // m02 = 0.0;
2818             // m12 = 0.0;
2819             break;
2820         case (APPLY_SCALE | APPLY_TRANSLATE):
2821             M00 = m00; M02 = m02;
2822             M11 = m11; M12 = m12;
2823             if (M00 == 0.0 || M11 == 0.0) {
2824                 throw new NoninvertibleTransformException("Determinant is 0");
2825             }
2826             m00 = 1.0 / M00;
2827             // m10 = 0.0;
2828             // m01 = 0.0;
2829             m11 = 1.0 / M11;
2830             m02 = -M02 / M00;
2831             m12 = -M12 / M11;
2832             break;
2833         case (APPLY_SCALE):
2834             M00 = m00;
2835             M11 = m11;
2836             if (M00 == 0.0 || M11 == 0.0) {
2837                 throw new NoninvertibleTransformException("Determinant is 0");
2838             }
2839             m00 = 1.0 / M00;
2840             // m10 = 0.0;
2841             // m01 = 0.0;
2842             m11 = 1.0 / M11;
2843             // m02 = 0.0;
2844             // m12 = 0.0;
2845             break;
2846         case (APPLY_TRANSLATE):
2847             // m00 = 1.0;
2848             // m10 = 0.0;
2849             // m01 = 0.0;
2850             // m11 = 1.0;
2851             m02 = -m02;
2852             m12 = -m12;
2853             break;
2854         case (APPLY_IDENTITY):
2855             // m00 = 1.0;
2856             // m10 = 0.0;
2857             // m01 = 0.0;
2858             // m11 = 1.0;
2859             // m02 = 0.0;
2860             // m12 = 0.0;
2861             break;
2862         }
2863     }
2864 
2865     /**
2866      * Transforms the specified {@code ptSrc} and stores the result
2867      * in {@code ptDst}.
2868      * If {@code ptDst} is {@code null}, a new {@link Point2D}
2869      * object is allocated and then the result of the transformation is
2870      * stored in this object.
2871      * In either case, {@code ptDst}, which contains the
2872      * transformed point, is returned for convenience.
2873      * If {@code ptSrc} and {@code ptDst} are the same
2874      * object, the input point is correctly overwritten with
2875      * the transformed point.
2876      * @param ptSrc the specified {@code Point2D} to be transformed
2877      * @param ptDst the specified {@code Point2D} that stores the
2878      * result of transforming {@code ptSrc}
2879      * @return the {@code ptDst} after transforming
2880      * {@code ptSrc} and storing the result in {@code ptDst}.
2881      * @since 1.2
2882      */
2883     public Point2D transform(Point2D ptSrc, Point2D ptDst) {
2884         if (ptDst == null) {
2885             if (ptSrc instanceof Point2D.Double) {
2886                 ptDst = new Point2D.Double();
2887             } else {
2888                 ptDst = new Point2D.Float();
2889             }
2890         }
2891         // Copy source coords into local variables in case src == dst
2892         double x = ptSrc.getX();
2893         double y = ptSrc.getY();
2894         switch (state) {
2895         default:
2896             stateError();
2897             /* NOTREACHED */
2898             return null;
2899         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2900             ptDst.setLocation(x * m00 + y * m01 + m02,
2901                               x * m10 + y * m11 + m12);
2902             return ptDst;
2903         case (APPLY_SHEAR | APPLY_SCALE):
2904             ptDst.setLocation(x * m00 + y * m01, x * m10 + y * m11);
2905             return ptDst;
2906         case (APPLY_SHEAR | APPLY_TRANSLATE):
2907             ptDst.setLocation(y * m01 + m02, x * m10 + m12);
2908             return ptDst;
2909         case (APPLY_SHEAR):
2910             ptDst.setLocation(y * m01, x * m10);
2911             return ptDst;
2912         case (APPLY_SCALE | APPLY_TRANSLATE):
2913             ptDst.setLocation(x * m00 + m02, y * m11 + m12);
2914             return ptDst;
2915         case (APPLY_SCALE):
2916             ptDst.setLocation(x * m00, y * m11);
2917             return ptDst;
2918         case (APPLY_TRANSLATE):
2919             ptDst.setLocation(x + m02, y + m12);
2920             return ptDst;
2921         case (APPLY_IDENTITY):
2922             ptDst.setLocation(x, y);
2923             return ptDst;
2924         }
2925 
2926         /* NOTREACHED */
2927     }
2928 
2929     /**
2930      * Transforms an array of point objects by this transform.
2931      * If any element of the {@code ptDst} array is
2932      * {@code null}, a new {@code Point2D} object is allocated
2933      * and stored into that element before storing the results of the
2934      * transformation.
2935      * <p>
2936      * Note that this method does not take any precautions to
2937      * avoid problems caused by storing results into {@code Point2D}
2938      * objects that will be used as the source for calculations
2939      * further down the source array.
2940      * This method does guarantee that if a specified {@code Point2D}
2941      * object is both the source and destination for the same single point
2942      * transform operation then the results will not be stored until
2943      * the calculations are complete to avoid storing the results on
2944      * top of the operands.
2945      * If, however, the destination {@code Point2D} object for one
2946      * operation is the same object as the source {@code Point2D}
2947      * object for another operation further down the source array then
2948      * the original coordinates in that point are overwritten before
2949      * they can be converted.
2950      * @param ptSrc the array containing the source point objects
2951      * @param ptDst the array into which the transform point objects are
2952      * returned
2953      * @param srcOff the offset to the first point object to be
2954      * transformed in the source array
2955      * @param dstOff the offset to the location of the first
2956      * transformed point object that is stored in the destination array
2957      * @param numPts the number of point objects to be transformed
2958      * @since 1.2
2959      */
2960     public void transform(Point2D[] ptSrc, int srcOff,
2961                           Point2D[] ptDst, int dstOff,
2962                           int numPts) {
2963         int state = this.state;
2964         while (--numPts >= 0) {
2965             // Copy source coords into local variables in case src == dst
2966             Point2D src = ptSrc[srcOff++];
2967             double x = src.getX();
2968             double y = src.getY();
2969             Point2D dst = ptDst[dstOff++];
2970             if (dst == null) {
2971                 if (src instanceof Point2D.Double) {
2972                     dst = new Point2D.Double();
2973                 } else {
2974                     dst = new Point2D.Float();
2975                 }
2976                 ptDst[dstOff - 1] = dst;
2977             }
2978             switch (state) {
2979             default:
2980                 stateError();
2981                 /* NOTREACHED */
2982                 return;
2983             case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
2984                 dst.setLocation(x * m00 + y * m01 + m02,
2985                                 x * m10 + y * m11 + m12);
2986                 break;
2987             case (APPLY_SHEAR | APPLY_SCALE):
2988                 dst.setLocation(x * m00 + y * m01, x * m10 + y * m11);
2989                 break;
2990             case (APPLY_SHEAR | APPLY_TRANSLATE):
2991                 dst.setLocation(y * m01 + m02, x * m10 + m12);
2992                 break;
2993             case (APPLY_SHEAR):
2994                 dst.setLocation(y * m01, x * m10);
2995                 break;
2996             case (APPLY_SCALE | APPLY_TRANSLATE):
2997                 dst.setLocation(x * m00 + m02, y * m11 + m12);
2998                 break;
2999             case (APPLY_SCALE):
3000                 dst.setLocation(x * m00, y * m11);
3001                 break;
3002             case (APPLY_TRANSLATE):
3003                 dst.setLocation(x + m02, y + m12);
3004                 break;
3005             case (APPLY_IDENTITY):
3006                 dst.setLocation(x, y);
3007                 break;
3008             }
3009         }
3010 
3011         /* NOTREACHED */
3012     }
3013 
3014     /**
3015      * Transforms an array of floating point coordinates by this transform.
3016      * The two coordinate array sections can be exactly the same or
3017      * can be overlapping sections of the same array without affecting the
3018      * validity of the results.
3019      * This method ensures that no source coordinates are overwritten by a
3020      * previous operation before they can be transformed.
3021      * The coordinates are stored in the arrays starting at the specified
3022      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3023      * @param srcPts the array containing the source point coordinates.
3024      * Each point is stored as a pair of x,&nbsp;y coordinates.
3025      * @param dstPts the array into which the transformed point coordinates
3026      * are returned.  Each point is stored as a pair of x,&nbsp;y
3027      * coordinates.
3028      * @param srcOff the offset to the first point to be transformed
3029      * in the source array
3030      * @param dstOff the offset to the location of the first
3031      * transformed point that is stored in the destination array
3032      * @param numPts the number of points to be transformed
3033      * @since 1.2
3034      */
3035     public void transform(float[] srcPts, int srcOff,
3036                           float[] dstPts, int dstOff,
3037                           int numPts) {
3038         double M00, M01, M02, M10, M11, M12;    // For caching
3039         if (dstPts == srcPts &&
3040             dstOff > srcOff && dstOff < srcOff + numPts * 2)
3041         {
3042             // If the arrays overlap partially with the destination higher
3043             // than the source and we transform the coordinates normally
3044             // we would overwrite some of the later source coordinates
3045             // with results of previous transformations.
3046             // To get around this we use arraycopy to copy the points
3047             // to their final destination with correct overwrite
3048             // handling and then transform them in place in the new
3049             // safer location.
3050             System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts * 2);
3051             // srcPts = dstPts;         // They are known to be equal.
3052             srcOff = dstOff;
3053         }
3054         switch (state) {
3055         default:
3056             stateError();
3057             /* NOTREACHED */
3058             return;
3059         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
3060             M00 = m00; M01 = m01; M02 = m02;
3061             M10 = m10; M11 = m11; M12 = m12;
3062             while (--numPts >= 0) {
3063                 double x = srcPts[srcOff++];
3064                 double y = srcPts[srcOff++];
3065                 dstPts[dstOff++] = (float) (M00 * x + M01 * y + M02);
3066                 dstPts[dstOff++] = (float) (M10 * x + M11 * y + M12);
3067             }
3068             return;
3069         case (APPLY_SHEAR | APPLY_SCALE):
3070             M00 = m00; M01 = m01;
3071             M10 = m10; M11 = m11;
3072             while (--numPts >= 0) {
3073                 double x = srcPts[srcOff++];
3074                 double y = srcPts[srcOff++];
3075                 dstPts[dstOff++] = (float) (M00 * x + M01 * y);
3076                 dstPts[dstOff++] = (float) (M10 * x + M11 * y);
3077             }
3078             return;
3079         case (APPLY_SHEAR | APPLY_TRANSLATE):
3080             M01 = m01; M02 = m02;
3081             M10 = m10; M12 = m12;
3082             while (--numPts >= 0) {
3083                 double x = srcPts[srcOff++];
3084                 dstPts[dstOff++] = (float) (M01 * srcPts[srcOff++] + M02);
3085                 dstPts[dstOff++] = (float) (M10 * x + M12);
3086             }
3087             return;
3088         case (APPLY_SHEAR):
3089             M01 = m01; M10 = m10;
3090             while (--numPts >= 0) {
3091                 double x = srcPts[srcOff++];
3092                 dstPts[dstOff++] = (float) (M01 * srcPts[srcOff++]);
3093                 dstPts[dstOff++] = (float) (M10 * x);
3094             }
3095             return;
3096         case (APPLY_SCALE | APPLY_TRANSLATE):
3097             M00 = m00; M02 = m02;
3098             M11 = m11; M12 = m12;
3099             while (--numPts >= 0) {
3100                 dstPts[dstOff++] = (float) (M00 * srcPts[srcOff++] + M02);
3101                 dstPts[dstOff++] = (float) (M11 * srcPts[srcOff++] + M12);
3102             }
3103             return;
3104         case (APPLY_SCALE):
3105             M00 = m00; M11 = m11;
3106             while (--numPts >= 0) {
3107                 dstPts[dstOff++] = (float) (M00 * srcPts[srcOff++]);
3108                 dstPts[dstOff++] = (float) (M11 * srcPts[srcOff++]);
3109             }
3110             return;
3111         case (APPLY_TRANSLATE):
3112             M02 = m02; M12 = m12;
3113             while (--numPts >= 0) {
3114                 dstPts[dstOff++] = (float) (srcPts[srcOff++] + M02);
3115                 dstPts[dstOff++] = (float) (srcPts[srcOff++] + M12);
3116             }
3117             return;
3118         case (APPLY_IDENTITY):
3119             if (srcPts != dstPts || srcOff != dstOff) {
3120                 System.arraycopy(srcPts, srcOff, dstPts, dstOff,
3121                                  numPts * 2);
3122             }
3123             return;
3124         }
3125 
3126         /* NOTREACHED */
3127     }
3128 
3129     /**
3130      * Transforms an array of double precision coordinates by this transform.
3131      * The two coordinate array sections can be exactly the same or
3132      * can be overlapping sections of the same array without affecting the
3133      * validity of the results.
3134      * This method ensures that no source coordinates are
3135      * overwritten by a previous operation before they can be transformed.
3136      * The coordinates are stored in the arrays starting at the indicated
3137      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3138      * @param srcPts the array containing the source point coordinates.
3139      * Each point is stored as a pair of x,&nbsp;y coordinates.
3140      * @param dstPts the array into which the transformed point
3141      * coordinates are returned.  Each point is stored as a pair of
3142      * x,&nbsp;y coordinates.
3143      * @param srcOff the offset to the first point to be transformed
3144      * in the source array
3145      * @param dstOff the offset to the location of the first
3146      * transformed point that is stored in the destination array
3147      * @param numPts the number of point objects to be transformed
3148      * @since 1.2
3149      */
3150     public void transform(double[] srcPts, int srcOff,
3151                           double[] dstPts, int dstOff,
3152                           int numPts) {
3153         double M00, M01, M02, M10, M11, M12;    // For caching
3154         if (dstPts == srcPts &&
3155             dstOff > srcOff && dstOff < srcOff + numPts * 2)
3156         {
3157             // If the arrays overlap partially with the destination higher
3158             // than the source and we transform the coordinates normally
3159             // we would overwrite some of the later source coordinates
3160             // with results of previous transformations.
3161             // To get around this we use arraycopy to copy the points
3162             // to their final destination with correct overwrite
3163             // handling and then transform them in place in the new
3164             // safer location.
3165             System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts * 2);
3166             // srcPts = dstPts;         // They are known to be equal.
3167             srcOff = dstOff;
3168         }
3169         switch (state) {
3170         default:
3171             stateError();
3172             /* NOTREACHED */
3173             return;
3174         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
3175             M00 = m00; M01 = m01; M02 = m02;
3176             M10 = m10; M11 = m11; M12 = m12;
3177             while (--numPts >= 0) {
3178                 double x = srcPts[srcOff++];
3179                 double y = srcPts[srcOff++];
3180                 dstPts[dstOff++] = M00 * x + M01 * y + M02;
3181                 dstPts[dstOff++] = M10 * x + M11 * y + M12;
3182             }
3183             return;
3184         case (APPLY_SHEAR | APPLY_SCALE):
3185             M00 = m00; M01 = m01;
3186             M10 = m10; M11 = m11;
3187             while (--numPts >= 0) {
3188                 double x = srcPts[srcOff++];
3189                 double y = srcPts[srcOff++];
3190                 dstPts[dstOff++] = M00 * x + M01 * y;
3191                 dstPts[dstOff++] = M10 * x + M11 * y;
3192             }
3193             return;
3194         case (APPLY_SHEAR | APPLY_TRANSLATE):
3195             M01 = m01; M02 = m02;
3196             M10 = m10; M12 = m12;
3197             while (--numPts >= 0) {
3198                 double x = srcPts[srcOff++];
3199                 dstPts[dstOff++] = M01 * srcPts[srcOff++] + M02;
3200                 dstPts[dstOff++] = M10 * x + M12;
3201             }
3202             return;
3203         case (APPLY_SHEAR):
3204             M01 = m01; M10 = m10;
3205             while (--numPts >= 0) {
3206                 double x = srcPts[srcOff++];
3207                 dstPts[dstOff++] = M01 * srcPts[srcOff++];
3208                 dstPts[dstOff++] = M10 * x;
3209             }
3210             return;
3211         case (APPLY_SCALE | APPLY_TRANSLATE):
3212             M00 = m00; M02 = m02;
3213             M11 = m11; M12 = m12;
3214             while (--numPts >= 0) {
3215                 dstPts[dstOff++] = M00 * srcPts[srcOff++] + M02;
3216                 dstPts[dstOff++] = M11 * srcPts[srcOff++] + M12;
3217             }
3218             return;
3219         case (APPLY_SCALE):
3220             M00 = m00; M11 = m11;
3221             while (--numPts >= 0) {
3222                 dstPts[dstOff++] = M00 * srcPts[srcOff++];
3223                 dstPts[dstOff++] = M11 * srcPts[srcOff++];
3224             }
3225             return;
3226         case (APPLY_TRANSLATE):
3227             M02 = m02; M12 = m12;
3228             while (--numPts >= 0) {
3229                 dstPts[dstOff++] = srcPts[srcOff++] + M02;
3230                 dstPts[dstOff++] = srcPts[srcOff++] + M12;
3231             }
3232             return;
3233         case (APPLY_IDENTITY):
3234             if (srcPts != dstPts || srcOff != dstOff) {
3235                 System.arraycopy(srcPts, srcOff, dstPts, dstOff,
3236                                  numPts * 2);
3237             }
3238             return;
3239         }
3240 
3241         /* NOTREACHED */
3242     }
3243 
3244     /**
3245      * Transforms an array of floating point coordinates by this transform
3246      * and stores the results into an array of doubles.
3247      * The coordinates are stored in the arrays starting at the specified
3248      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3249      * @param srcPts the array containing the source point coordinates.
3250      * Each point is stored as a pair of x,&nbsp;y coordinates.
3251      * @param dstPts the array into which the transformed point coordinates
3252      * are returned.  Each point is stored as a pair of x,&nbsp;y
3253      * coordinates.
3254      * @param srcOff the offset to the first point to be transformed
3255      * in the source array
3256      * @param dstOff the offset to the location of the first
3257      * transformed point that is stored in the destination array
3258      * @param numPts the number of points to be transformed
3259      * @since 1.2
3260      */
3261     public void transform(float[] srcPts, int srcOff,
3262                           double[] dstPts, int dstOff,
3263                           int numPts) {
3264         double M00, M01, M02, M10, M11, M12;    // For caching
3265         switch (state) {
3266         default:
3267             stateError();
3268             /* NOTREACHED */
3269             return;
3270         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
3271             M00 = m00; M01 = m01; M02 = m02;
3272             M10 = m10; M11 = m11; M12 = m12;
3273             while (--numPts >= 0) {
3274                 double x = srcPts[srcOff++];
3275                 double y = srcPts[srcOff++];
3276                 dstPts[dstOff++] = M00 * x + M01 * y + M02;
3277                 dstPts[dstOff++] = M10 * x + M11 * y + M12;
3278             }
3279             return;
3280         case (APPLY_SHEAR | APPLY_SCALE):
3281             M00 = m00; M01 = m01;
3282             M10 = m10; M11 = m11;
3283             while (--numPts >= 0) {
3284                 double x = srcPts[srcOff++];
3285                 double y = srcPts[srcOff++];
3286                 dstPts[dstOff++] = M00 * x + M01 * y;
3287                 dstPts[dstOff++] = M10 * x + M11 * y;
3288             }
3289             return;
3290         case (APPLY_SHEAR | APPLY_TRANSLATE):
3291             M01 = m01; M02 = m02;
3292             M10 = m10; M12 = m12;
3293             while (--numPts >= 0) {
3294                 double x = srcPts[srcOff++];
3295                 dstPts[dstOff++] = M01 * srcPts[srcOff++] + M02;
3296                 dstPts[dstOff++] = M10 * x + M12;
3297             }
3298             return;
3299         case (APPLY_SHEAR):
3300             M01 = m01; M10 = m10;
3301             while (--numPts >= 0) {
3302                 double x = srcPts[srcOff++];
3303                 dstPts[dstOff++] = M01 * srcPts[srcOff++];
3304                 dstPts[dstOff++] = M10 * x;
3305             }
3306             return;
3307         case (APPLY_SCALE | APPLY_TRANSLATE):
3308             M00 = m00; M02 = m02;
3309             M11 = m11; M12 = m12;
3310             while (--numPts >= 0) {
3311                 dstPts[dstOff++] = M00 * srcPts[srcOff++] + M02;
3312                 dstPts[dstOff++] = M11 * srcPts[srcOff++] + M12;
3313             }
3314             return;
3315         case (APPLY_SCALE):
3316             M00 = m00; M11 = m11;
3317             while (--numPts >= 0) {
3318                 dstPts[dstOff++] = M00 * srcPts[srcOff++];
3319                 dstPts[dstOff++] = M11 * srcPts[srcOff++];
3320             }
3321             return;
3322         case (APPLY_TRANSLATE):
3323             M02 = m02; M12 = m12;
3324             while (--numPts >= 0) {
3325                 dstPts[dstOff++] = srcPts[srcOff++] + M02;
3326                 dstPts[dstOff++] = srcPts[srcOff++] + M12;
3327             }
3328             return;
3329         case (APPLY_IDENTITY):
3330             while (--numPts >= 0) {
3331                 dstPts[dstOff++] = srcPts[srcOff++];
3332                 dstPts[dstOff++] = srcPts[srcOff++];
3333             }
3334             return;
3335         }
3336 
3337         /* NOTREACHED */
3338     }
3339 
3340     /**
3341      * Transforms an array of double precision coordinates by this transform
3342      * and stores the results into an array of floats.
3343      * The coordinates are stored in the arrays starting at the specified
3344      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3345      * @param srcPts the array containing the source point coordinates.
3346      * Each point is stored as a pair of x,&nbsp;y coordinates.
3347      * @param dstPts the array into which the transformed point
3348      * coordinates are returned.  Each point is stored as a pair of
3349      * x,&nbsp;y coordinates.
3350      * @param srcOff the offset to the first point to be transformed
3351      * in the source array
3352      * @param dstOff the offset to the location of the first
3353      * transformed point that is stored in the destination array
3354      * @param numPts the number of point objects to be transformed
3355      * @since 1.2
3356      */
3357     public void transform(double[] srcPts, int srcOff,
3358                           float[] dstPts, int dstOff,
3359                           int numPts) {
3360         double M00, M01, M02, M10, M11, M12;    // For caching
3361         switch (state) {
3362         default:
3363             stateError();
3364             /* NOTREACHED */
3365             return;
3366         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
3367             M00 = m00; M01 = m01; M02 = m02;
3368             M10 = m10; M11 = m11; M12 = m12;
3369             while (--numPts >= 0) {
3370                 double x = srcPts[srcOff++];
3371                 double y = srcPts[srcOff++];
3372                 dstPts[dstOff++] = (float) (M00 * x + M01 * y + M02);
3373                 dstPts[dstOff++] = (float) (M10 * x + M11 * y + M12);
3374             }
3375             return;
3376         case (APPLY_SHEAR | APPLY_SCALE):
3377             M00 = m00; M01 = m01;
3378             M10 = m10; M11 = m11;
3379             while (--numPts >= 0) {
3380                 double x = srcPts[srcOff++];
3381                 double y = srcPts[srcOff++];
3382                 dstPts[dstOff++] = (float) (M00 * x + M01 * y);
3383                 dstPts[dstOff++] = (float) (M10 * x + M11 * y);
3384             }
3385             return;
3386         case (APPLY_SHEAR | APPLY_TRANSLATE):
3387             M01 = m01; M02 = m02;
3388             M10 = m10; M12 = m12;
3389             while (--numPts >= 0) {
3390                 double x = srcPts[srcOff++];
3391                 dstPts[dstOff++] = (float) (M01 * srcPts[srcOff++] + M02);
3392                 dstPts[dstOff++] = (float) (M10 * x + M12);
3393             }
3394             return;
3395         case (APPLY_SHEAR):
3396             M01 = m01; M10 = m10;
3397             while (--numPts >= 0) {
3398                 double x = srcPts[srcOff++];
3399                 dstPts[dstOff++] = (float) (M01 * srcPts[srcOff++]);
3400                 dstPts[dstOff++] = (float) (M10 * x);
3401             }
3402             return;
3403         case (APPLY_SCALE | APPLY_TRANSLATE):
3404             M00 = m00; M02 = m02;
3405             M11 = m11; M12 = m12;
3406             while (--numPts >= 0) {
3407                 dstPts[dstOff++] = (float) (M00 * srcPts[srcOff++] + M02);
3408                 dstPts[dstOff++] = (float) (M11 * srcPts[srcOff++] + M12);
3409             }
3410             return;
3411         case (APPLY_SCALE):
3412             M00 = m00; M11 = m11;
3413             while (--numPts >= 0) {
3414                 dstPts[dstOff++] = (float) (M00 * srcPts[srcOff++]);
3415                 dstPts[dstOff++] = (float) (M11 * srcPts[srcOff++]);
3416             }
3417             return;
3418         case (APPLY_TRANSLATE):
3419             M02 = m02; M12 = m12;
3420             while (--numPts >= 0) {
3421                 dstPts[dstOff++] = (float) (srcPts[srcOff++] + M02);
3422                 dstPts[dstOff++] = (float) (srcPts[srcOff++] + M12);
3423             }
3424             return;
3425         case (APPLY_IDENTITY):
3426             while (--numPts >= 0) {
3427                 dstPts[dstOff++] = (float) (srcPts[srcOff++]);
3428                 dstPts[dstOff++] = (float) (srcPts[srcOff++]);
3429             }
3430             return;
3431         }
3432 
3433         /* NOTREACHED */
3434     }
3435 
3436     /**
3437      * Inverse transforms the specified {@code ptSrc} and stores the
3438      * result in {@code ptDst}.
3439      * If {@code ptDst} is {@code null}, a new
3440      * {@code Point2D} object is allocated and then the result of the
3441      * transform is stored in this object.
3442      * In either case, {@code ptDst}, which contains the transformed
3443      * point, is returned for convenience.
3444      * If {@code ptSrc} and {@code ptDst} are the same
3445      * object, the input point is correctly overwritten with the
3446      * transformed point.
3447      * @param ptSrc the point to be inverse transformed
3448      * @param ptDst the resulting transformed point
3449      * @return {@code ptDst}, which contains the result of the
3450      * inverse transform.
3451      * @exception NoninvertibleTransformException  if the matrix cannot be
3452      *                                         inverted.
3453      * @since 1.2
3454      */
3455     @SuppressWarnings("fallthrough")
3456     public Point2D inverseTransform(Point2D ptSrc, Point2D ptDst)
3457         throws NoninvertibleTransformException
3458     {
3459         if (ptDst == null) {
3460             if (ptSrc instanceof Point2D.Double) {
3461                 ptDst = new Point2D.Double();
3462             } else {
3463                 ptDst = new Point2D.Float();
3464             }
3465         }
3466         // Copy source coords into local variables in case src == dst
3467         double x = ptSrc.getX();
3468         double y = ptSrc.getY();
3469         switch (state) {
3470         default:
3471             stateError();
3472             /* NOTREACHED */
3473         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
3474             x -= m02;
3475             y -= m12;
3476             /* NOBREAK */
3477         case (APPLY_SHEAR | APPLY_SCALE):
3478             double det = m00 * m11 - m01 * m10;
3479             if (Math.abs(det) <= Double.MIN_VALUE) {
3480                 throw new NoninvertibleTransformException("Determinant is "+
3481                                                           det);
3482             }
3483             ptDst.setLocation((x * m11 - y * m01) / det,
3484                               (y * m00 - x * m10) / det);
3485             return ptDst;
3486         case (APPLY_SHEAR | APPLY_TRANSLATE):
3487             x -= m02;
3488             y -= m12;
3489             /* NOBREAK */
3490         case (APPLY_SHEAR):
3491             if (m01 == 0.0 || m10 == 0.0) {
3492                 throw new NoninvertibleTransformException("Determinant is 0");
3493             }
3494             ptDst.setLocation(y / m10, x / m01);
3495             return ptDst;
3496         case (APPLY_SCALE | APPLY_TRANSLATE):
3497             x -= m02;
3498             y -= m12;
3499             /* NOBREAK */
3500         case (APPLY_SCALE):
3501             if (m00 == 0.0 || m11 == 0.0) {
3502                 throw new NoninvertibleTransformException("Determinant is 0");
3503             }
3504             ptDst.setLocation(x / m00, y / m11);
3505             return ptDst;
3506         case (APPLY_TRANSLATE):
3507             ptDst.setLocation(x - m02, y - m12);
3508             return ptDst;
3509         case (APPLY_IDENTITY):
3510             ptDst.setLocation(x, y);
3511             return ptDst;
3512         }
3513 
3514         /* NOTREACHED */
3515     }
3516 
3517     /**
3518      * Inverse transforms an array of double precision coordinates by
3519      * this transform.
3520      * The two coordinate array sections can be exactly the same or
3521      * can be overlapping sections of the same array without affecting the
3522      * validity of the results.
3523      * This method ensures that no source coordinates are
3524      * overwritten by a previous operation before they can be transformed.
3525      * The coordinates are stored in the arrays starting at the specified
3526      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3527      * @param srcPts the array containing the source point coordinates.
3528      * Each point is stored as a pair of x,&nbsp;y coordinates.
3529      * @param dstPts the array into which the transformed point
3530      * coordinates are returned.  Each point is stored as a pair of
3531      * x,&nbsp;y coordinates.
3532      * @param srcOff the offset to the first point to be transformed
3533      * in the source array
3534      * @param dstOff the offset to the location of the first
3535      * transformed point that is stored in the destination array
3536      * @param numPts the number of point objects to be transformed
3537      * @exception NoninvertibleTransformException  if the matrix cannot be
3538      *                                         inverted.
3539      * @since 1.2
3540      */
3541     public void inverseTransform(double[] srcPts, int srcOff,
3542                                  double[] dstPts, int dstOff,
3543                                  int numPts)
3544         throws NoninvertibleTransformException
3545     {
3546         double M00, M01, M02, M10, M11, M12;    // For caching
3547         double det;
3548         if (dstPts == srcPts &&
3549             dstOff > srcOff && dstOff < srcOff + numPts * 2)
3550         {
3551             // If the arrays overlap partially with the destination higher
3552             // than the source and we transform the coordinates normally
3553             // we would overwrite some of the later source coordinates
3554             // with results of previous transformations.
3555             // To get around this we use arraycopy to copy the points
3556             // to their final destination with correct overwrite
3557             // handling and then transform them in place in the new
3558             // safer location.
3559             System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts * 2);
3560             // srcPts = dstPts;         // They are known to be equal.
3561             srcOff = dstOff;
3562         }
3563         switch (state) {
3564         default:
3565             stateError();
3566             /* NOTREACHED */
3567             return;
3568         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
3569             M00 = m00; M01 = m01; M02 = m02;
3570             M10 = m10; M11 = m11; M12 = m12;
3571             det = M00 * M11 - M01 * M10;
3572             if (Math.abs(det) <= Double.MIN_VALUE) {
3573                 throw new NoninvertibleTransformException("Determinant is "+
3574                                                           det);
3575             }
3576             while (--numPts >= 0) {
3577                 double x = srcPts[srcOff++] - M02;
3578                 double y = srcPts[srcOff++] - M12;
3579                 dstPts[dstOff++] = (x * M11 - y * M01) / det;
3580                 dstPts[dstOff++] = (y * M00 - x * M10) / det;
3581             }
3582             return;
3583         case (APPLY_SHEAR | APPLY_SCALE):
3584             M00 = m00; M01 = m01;
3585             M10 = m10; M11 = m11;
3586             det = M00 * M11 - M01 * M10;
3587             if (Math.abs(det) <= Double.MIN_VALUE) {
3588                 throw new NoninvertibleTransformException("Determinant is "+
3589                                                           det);
3590             }
3591             while (--numPts >= 0) {
3592                 double x = srcPts[srcOff++];
3593                 double y = srcPts[srcOff++];
3594                 dstPts[dstOff++] = (x * M11 - y * M01) / det;
3595                 dstPts[dstOff++] = (y * M00 - x * M10) / det;
3596             }
3597             return;
3598         case (APPLY_SHEAR | APPLY_TRANSLATE):
3599             M01 = m01; M02 = m02;
3600             M10 = m10; M12 = m12;
3601             if (M01 == 0.0 || M10 == 0.0) {
3602                 throw new NoninvertibleTransformException("Determinant is 0");
3603             }
3604             while (--numPts >= 0) {
3605                 double x = srcPts[srcOff++] - M02;
3606                 dstPts[dstOff++] = (srcPts[srcOff++] - M12) / M10;
3607                 dstPts[dstOff++] = x / M01;
3608             }
3609             return;
3610         case (APPLY_SHEAR):
3611             M01 = m01; M10 = m10;
3612             if (M01 == 0.0 || M10 == 0.0) {
3613                 throw new NoninvertibleTransformException("Determinant is 0");
3614             }
3615             while (--numPts >= 0) {
3616                 double x = srcPts[srcOff++];
3617                 dstPts[dstOff++] = srcPts[srcOff++] / M10;
3618                 dstPts[dstOff++] = x / M01;
3619             }
3620             return;
3621         case (APPLY_SCALE | APPLY_TRANSLATE):
3622             M00 = m00; M02 = m02;
3623             M11 = m11; M12 = m12;
3624             if (M00 == 0.0 || M11 == 0.0) {
3625                 throw new NoninvertibleTransformException("Determinant is 0");
3626             }
3627             while (--numPts >= 0) {
3628                 dstPts[dstOff++] = (srcPts[srcOff++] - M02) / M00;
3629                 dstPts[dstOff++] = (srcPts[srcOff++] - M12) / M11;
3630             }
3631             return;
3632         case (APPLY_SCALE):
3633             M00 = m00; M11 = m11;
3634             if (M00 == 0.0 || M11 == 0.0) {
3635                 throw new NoninvertibleTransformException("Determinant is 0");
3636             }
3637             while (--numPts >= 0) {
3638                 dstPts[dstOff++] = srcPts[srcOff++] / M00;
3639                 dstPts[dstOff++] = srcPts[srcOff++] / M11;
3640             }
3641             return;
3642         case (APPLY_TRANSLATE):
3643             M02 = m02; M12 = m12;
3644             while (--numPts >= 0) {
3645                 dstPts[dstOff++] = srcPts[srcOff++] - M02;
3646                 dstPts[dstOff++] = srcPts[srcOff++] - M12;
3647             }
3648             return;
3649         case (APPLY_IDENTITY):
3650             if (srcPts != dstPts || srcOff != dstOff) {
3651                 System.arraycopy(srcPts, srcOff, dstPts, dstOff,
3652                                  numPts * 2);
3653             }
3654             return;
3655         }
3656 
3657         /* NOTREACHED */
3658     }
3659 
3660     /**
3661      * Transforms the relative distance vector specified by
3662      * {@code ptSrc} and stores the result in {@code ptDst}.
3663      * A relative distance vector is transformed without applying the
3664      * translation components of the affine transformation matrix
3665      * using the following equations:
3666      * <pre>
3667      *  [  x' ]   [  m00  m01 (m02) ] [  x  ]   [ m00x + m01y ]
3668      *  [  y' ] = [  m10  m11 (m12) ] [  y  ] = [ m10x + m11y ]
3669      *  [ (1) ]   [  (0)  (0) ( 1 ) ] [ (1) ]   [     (1)     ]
3670      * </pre>
3671      * If {@code ptDst} is {@code null}, a new
3672      * {@code Point2D} object is allocated and then the result of the
3673      * transform is stored in this object.
3674      * In either case, {@code ptDst}, which contains the
3675      * transformed point, is returned for convenience.
3676      * If {@code ptSrc} and {@code ptDst} are the same object,
3677      * the input point is correctly overwritten with the transformed
3678      * point.
3679      * @param ptSrc the distance vector to be delta transformed
3680      * @param ptDst the resulting transformed distance vector
3681      * @return {@code ptDst}, which contains the result of the
3682      * transformation.
3683      * @since 1.2
3684      */
3685     public Point2D deltaTransform(Point2D ptSrc, Point2D ptDst) {
3686         if (ptDst == null) {
3687             if (ptSrc instanceof Point2D.Double) {
3688                 ptDst = new Point2D.Double();
3689             } else {
3690                 ptDst = new Point2D.Float();
3691             }
3692         }
3693         // Copy source coords into local variables in case src == dst
3694         double x = ptSrc.getX();
3695         double y = ptSrc.getY();
3696         switch (state) {
3697         default:
3698             stateError();
3699             /* NOTREACHED */
3700             return null;
3701         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
3702         case (APPLY_SHEAR | APPLY_SCALE):
3703             ptDst.setLocation(x * m00 + y * m01, x * m10 + y * m11);
3704             return ptDst;
3705         case (APPLY_SHEAR | APPLY_TRANSLATE):
3706         case (APPLY_SHEAR):
3707             ptDst.setLocation(y * m01, x * m10);
3708             return ptDst;
3709         case (APPLY_SCALE | APPLY_TRANSLATE):
3710         case (APPLY_SCALE):
3711             ptDst.setLocation(x * m00, y * m11);
3712             return ptDst;
3713         case (APPLY_TRANSLATE):
3714         case (APPLY_IDENTITY):
3715             ptDst.setLocation(x, y);
3716             return ptDst;
3717         }
3718 
3719         /* NOTREACHED */
3720     }
3721 
3722     /**
3723      * Transforms an array of relative distance vectors by this
3724      * transform.
3725      * A relative distance vector is transformed without applying the
3726      * translation components of the affine transformation matrix
3727      * using the following equations:
3728      * <pre>
3729      *  [  x' ]   [  m00  m01 (m02) ] [  x  ]   [ m00x + m01y ]
3730      *  [  y' ] = [  m10  m11 (m12) ] [  y  ] = [ m10x + m11y ]
3731      *  [ (1) ]   [  (0)  (0) ( 1 ) ] [ (1) ]   [     (1)     ]
3732      * </pre>
3733      * The two coordinate array sections can be exactly the same or
3734      * can be overlapping sections of the same array without affecting the
3735      * validity of the results.
3736      * This method ensures that no source coordinates are
3737      * overwritten by a previous operation before they can be transformed.
3738      * The coordinates are stored in the arrays starting at the indicated
3739      * offset in the order {@code [x0, y0, x1, y1, ..., xn, yn]}.
3740      * @param srcPts the array containing the source distance vectors.
3741      * Each vector is stored as a pair of relative x,&nbsp;y coordinates.
3742      * @param dstPts the array into which the transformed distance vectors
3743      * are returned.  Each vector is stored as a pair of relative
3744      * x,&nbsp;y coordinates.
3745      * @param srcOff the offset to the first vector to be transformed
3746      * in the source array
3747      * @param dstOff the offset to the location of the first
3748      * transformed vector that is stored in the destination array
3749      * @param numPts the number of vector coordinate pairs to be
3750      * transformed
3751      * @since 1.2
3752      */
3753     public void deltaTransform(double[] srcPts, int srcOff,
3754                                double[] dstPts, int dstOff,
3755                                int numPts) {
3756         double M00, M01, M10, M11;      // For caching
3757         if (dstPts == srcPts &&
3758             dstOff > srcOff && dstOff < srcOff + numPts * 2)
3759         {
3760             // If the arrays overlap partially with the destination higher
3761             // than the source and we transform the coordinates normally
3762             // we would overwrite some of the later source coordinates
3763             // with results of previous transformations.
3764             // To get around this we use arraycopy to copy the points
3765             // to their final destination with correct overwrite
3766             // handling and then transform them in place in the new
3767             // safer location.
3768             System.arraycopy(srcPts, srcOff, dstPts, dstOff, numPts * 2);
3769             // srcPts = dstPts;         // They are known to be equal.
3770             srcOff = dstOff;
3771         }
3772         switch (state) {
3773         default:
3774             stateError();
3775             /* NOTREACHED */
3776             return;
3777         case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
3778         case (APPLY_SHEAR | APPLY_SCALE):
3779             M00 = m00; M01 = m01;
3780             M10 = m10; M11 = m11;
3781             while (--numPts >= 0) {
3782                 double x = srcPts[srcOff++];
3783                 double y = srcPts[srcOff++];
3784                 dstPts[dstOff++] = x * M00 + y * M01;
3785                 dstPts[dstOff++] = x * M10 + y * M11;
3786             }
3787             return;
3788         case (APPLY_SHEAR | APPLY_TRANSLATE):
3789         case (APPLY_SHEAR):
3790             M01 = m01; M10 = m10;
3791             while (--numPts >= 0) {
3792                 double x = srcPts[srcOff++];
3793                 dstPts[dstOff++] = srcPts[srcOff++] * M01;
3794                 dstPts[dstOff++] = x * M10;
3795             }
3796             return;
3797         case (APPLY_SCALE | APPLY_TRANSLATE):
3798         case (APPLY_SCALE):
3799             M00 = m00; M11 = m11;
3800             while (--numPts >= 0) {
3801                 dstPts[dstOff++] = srcPts[srcOff++] * M00;
3802                 dstPts[dstOff++] = srcPts[srcOff++] * M11;
3803             }
3804             return;
3805         case (APPLY_TRANSLATE):
3806         case (APPLY_IDENTITY):
3807             if (srcPts != dstPts || srcOff != dstOff) {
3808                 System.arraycopy(srcPts, srcOff, dstPts, dstOff,
3809                                  numPts * 2);
3810             }
3811             return;
3812         }
3813 
3814         /* NOTREACHED */
3815     }
3816 
3817     /**
3818      * Returns a new {@link Shape} object defined by the geometry of the
3819      * specified {@code Shape} after it has been transformed by
3820      * this transform.
3821      * @param pSrc the specified {@code Shape} object to be
3822      * transformed by this transform.
3823      * @return a new {@code Shape} object that defines the geometry
3824      * of the transformed {@code Shape}, or null if {@code pSrc} is null.
3825      * @since 1.2
3826      */
3827     public Shape createTransformedShape(Shape pSrc) {
3828         if (pSrc == null) {
3829             return null;
3830         }
3831         return new Path2D.Double(pSrc, this);
3832     }
3833 
3834     // Round values to sane precision for printing
3835     // Note that Math.sin(Math.PI) has an error of about 10^-16
3836     private static double _matround(double matval) {
3837         return Math.rint(matval * 1E15) / 1E15;
3838     }
3839 
3840     /**
3841      * Returns a {@code String} that represents the value of this
3842      * {@link Object}.
3843      * @return a {@code String} representing the value of this
3844      * {@code Object}.
3845      * @since 1.2
3846      */
3847     public String toString() {
3848         return ("AffineTransform[["
3849                 + _matround(m00) + ", "
3850                 + _matround(m01) + ", "
3851                 + _matround(m02) + "], ["
3852                 + _matround(m10) + ", "
3853                 + _matround(m11) + ", "
3854                 + _matround(m12) + "]]");
3855     }
3856 
3857     /**
3858      * Returns {@code true} if this {@code AffineTransform} is
3859      * an identity transform.
3860      * @return {@code true} if this {@code AffineTransform} is
3861      * an identity transform; {@code false} otherwise.
3862      * @since 1.2
3863      */
3864     public boolean isIdentity() {
3865         return (state == APPLY_IDENTITY || (getType() == TYPE_IDENTITY));
3866     }
3867 
3868     /**
3869      * Returns a copy of this {@code AffineTransform} object.
3870      * @return an {@code Object} that is a copy of this
3871      * {@code AffineTransform} object.
3872      * @since 1.2
3873      */
3874     public Object clone() {
3875         try {
3876             return super.clone();
3877         } catch (CloneNotSupportedException e) {
3878             // this shouldn't happen, since we are Cloneable
3879             throw new InternalError(e);
3880         }
3881     }
3882 
3883     /**
3884      * Returns the hashcode for this transform.
3885      * @return      a hash code for this transform.
3886      * @since 1.2
3887      */
3888     public int hashCode() {
3889         long bits = Double.doubleToLongBits(m00);
3890         bits = bits * 31 + Double.doubleToLongBits(m01);
3891         bits = bits * 31 + Double.doubleToLongBits(m02);
3892         bits = bits * 31 + Double.doubleToLongBits(m10);
3893         bits = bits * 31 + Double.doubleToLongBits(m11);
3894         bits = bits * 31 + Double.doubleToLongBits(m12);
3895         return (((int) bits) ^ ((int) (bits >> 32)));
3896     }
3897 
3898     /**
3899      * Returns {@code true} if this {@code AffineTransform}
3900      * represents the same affine coordinate transform as the specified
3901      * argument.
3902      * @param obj the {@code Object} to test for equality with this
3903      * {@code AffineTransform}
3904      * @return {@code true} if {@code obj} equals this
3905      * {@code AffineTransform} object; {@code false} otherwise.
3906      * @since 1.2
3907      */
3908     public boolean equals(Object obj) {
3909         if (!(obj instanceof AffineTransform)) {
3910             return false;
3911         }
3912 
3913         AffineTransform a = (AffineTransform)obj;
3914 
3915         return ((m00 == a.m00) && (m01 == a.m01) && (m02 == a.m02) &&
3916                 (m10 == a.m10) && (m11 == a.m11) && (m12 == a.m12));
3917     }
3918 
3919     /* Serialization support.  A readObject method is neccessary because
3920      * the state field is part of the implementation of this particular
3921      * AffineTransform and not part of the public specification.  The
3922      * state variable's value needs to be recalculated on the fly by the
3923      * readObject method as it is in the 6-argument matrix constructor.
3924      */
3925 
3926     /*
3927      * JDK 1.2 serialVersionUID
3928      */
3929     private static final long serialVersionUID = 1330973210523860834L;
3930 
3931     private void writeObject(java.io.ObjectOutputStream s)
3932         throws java.lang.ClassNotFoundException, java.io.IOException
3933     {
3934         s.defaultWriteObject();
3935     }
3936 
3937     private void readObject(java.io.ObjectInputStream s)
3938         throws java.lang.ClassNotFoundException, java.io.IOException
3939     {
3940         s.defaultReadObject();
3941         updateState();
3942     }
3943 }