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