KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > geom > AffineTransform


1 /*
2  * @(#)AffineTransform.java 1.71 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.awt.geom;
9
10 import java.awt.Shape JavaDoc;
11
12 /**
13  * The <code>AffineTransform</code> class represents a 2D affine transform
14  * that performs a linear mapping from 2D coordinates to other 2D
15  * coordinates that preserves the "straightness" and
16  * "parallelness" of lines. Affine transformations can be constructed
17  * using sequences of translations, scales, flips, rotations, and shears.
18  * <p>
19  * Such a coordinate transformation can be represented by a 3 row by
20  * 3 column matrix with an implied last row of [ 0 0 1 ]. This matrix
21  * transforms source coordinates <code>(x,&nbsp;y)</code> into
22  * destination coordinates <code>(x',&nbsp;y')</code> by considering
23  * them to be a column vector and multiplying the coordinate vector
24  * by the matrix according to the following process:
25  * <pre>
26  * [ x'] [ m00 m01 m02 ] [ x ] [ m00x + m01y + m02 ]
27  * [ y'] = [ m10 m11 m12 ] [ y ] = [ m10x + m11y + m12 ]
28  * [ 1 ] [ 0 0 1 ] [ 1 ] [ 1 ]
29  * </pre>
30  *
31  * @version 1.71, 12/19/03
32  * @author Jim Graham
33  */

34 public class AffineTransform implements Cloneable JavaDoc, java.io.Serializable JavaDoc {
35     /*
36      * This constant is only useful for the cached type field.
37      * It indicates that the type has been decached and must be recalculated.
38      */

39     private static final int TYPE_UNKNOWN = -1;
40
41     /**
42      * This constant indicates that the transform defined by this object
43      * is an identity transform.
44      * An identity transform is one in which the output coordinates are
45      * always the same as the input coordinates.
46      * If this transform is anything other than the identity transform,
47      * the type will either be the constant GENERAL_TRANSFORM or a
48      * combination of the appropriate flag bits for the various coordinate
49      * conversions that this transform performs.
50      * @see #TYPE_TRANSLATION
51      * @see #TYPE_UNIFORM_SCALE
52      * @see #TYPE_GENERAL_SCALE
53      * @see #TYPE_FLIP
54      * @see #TYPE_QUADRANT_ROTATION
55      * @see #TYPE_GENERAL_ROTATION
56      * @see #TYPE_GENERAL_TRANSFORM
57      * @see #getType
58      */

59     public static final int TYPE_IDENTITY = 0;
60
61     /**
62      * This flag bit indicates that the transform defined by this object
63      * performs a translation in addition to the conversions indicated
64      * by other flag bits.
65      * A translation moves the coordinates by a constant amount in x
66      * and y without changing the length or angle of vectors.
67      * @see #TYPE_IDENTITY
68      * @see #TYPE_UNIFORM_SCALE
69      * @see #TYPE_GENERAL_SCALE
70      * @see #TYPE_FLIP
71      * @see #TYPE_QUADRANT_ROTATION
72      * @see #TYPE_GENERAL_ROTATION
73      * @see #TYPE_GENERAL_TRANSFORM
74      * @see #getType
75      */

76     public static final int TYPE_TRANSLATION = 1;
77
78     /**
79      * This flag bit indicates that the transform defined by this object
80      * performs a uniform scale in addition to the conversions indicated
81      * by other flag bits.
82      * A uniform scale multiplies the length of vectors by the same amount
83      * in both the x and y directions without changing the angle between
84      * vectors.
85      * This flag bit is mutually exclusive with the TYPE_GENERAL_SCALE flag.
86      * @see #TYPE_IDENTITY
87      * @see #TYPE_TRANSLATION
88      * @see #TYPE_GENERAL_SCALE
89      * @see #TYPE_FLIP
90      * @see #TYPE_QUADRANT_ROTATION
91      * @see #TYPE_GENERAL_ROTATION
92      * @see #TYPE_GENERAL_TRANSFORM
93      * @see #getType
94      */

95     public static final int TYPE_UNIFORM_SCALE = 2;
96
97     /**
98      * This flag bit indicates that the transform defined by this object
99      * performs a general scale in addition to the conversions indicated
100      * by other flag bits.
101      * A general scale multiplies the length of vectors by different
102      * amounts in the x and y directions without changing the angle
103      * between perpendicular vectors.
104      * This flag bit is mutually exclusive with the TYPE_UNIFORM_SCALE flag.
105      * @see #TYPE_IDENTITY
106      * @see #TYPE_TRANSLATION
107      * @see #TYPE_UNIFORM_SCALE
108      * @see #TYPE_FLIP
109      * @see #TYPE_QUADRANT_ROTATION
110      * @see #TYPE_GENERAL_ROTATION
111      * @see #TYPE_GENERAL_TRANSFORM
112      * @see #getType
113      */

114     public static final int TYPE_GENERAL_SCALE = 4;
115
116     /**
117      * This constant is a bit mask for any of the scale flag bits.
118      * @see #TYPE_UNIFORM_SCALE
119      * @see #TYPE_GENERAL_SCALE
120      */

121     public static final int TYPE_MASK_SCALE = (TYPE_UNIFORM_SCALE |
122                            TYPE_GENERAL_SCALE);
123
124     /**
125      * This flag bit indicates that the transform defined by this object
126      * performs a mirror image flip about some axis which changes the
127      * normally right handed coordinate system into a left handed
128      * system in addition to the conversions indicated by other flag bits.
129      * A right handed coordinate system is one where the positive X
130      * axis rotates counterclockwise to overlay the positive Y axis
131      * similar to the direction that the fingers on your right hand
132      * curl when you stare end on at your thumb.
133      * A left handed coordinate system is one where the positive X
134      * axis rotates clockwise to overlay the positive Y axis similar
135      * to the direction that the fingers on your left hand curl.
136      * There is no mathematical way to determine the angle of the
137      * original flipping or mirroring transformation since all angles
138      * of flip are identical given an appropriate adjusting rotation.
139      * @see #TYPE_IDENTITY
140      * @see #TYPE_TRANSLATION
141      * @see #TYPE_UNIFORM_SCALE
142      * @see #TYPE_GENERAL_SCALE
143      * @see #TYPE_QUADRANT_ROTATION
144      * @see #TYPE_GENERAL_ROTATION
145      * @see #TYPE_GENERAL_TRANSFORM
146      * @see #getType
147      */

148     public static final int TYPE_FLIP = 64;
149     /* NOTE: TYPE_FLIP was added after GENERAL_TRANSFORM was in public
150      * circulation and the flag bits could no longer be conveniently
151      * renumbered without introducing binary incompatibility in outside
152      * code.
153      */

154
155     /**
156      * This flag bit indicates that the transform defined by this object
157      * performs a quadrant rotation by some multiple of 90 degrees in
158      * addition to the conversions indicated by other flag bits.
159      * A rotation changes the angles of vectors by the same amount
160      * regardless of the original direction of the vector and without
161      * changing the length of the vector.
162      * This flag bit is mutually exclusive with the TYPE_GENERAL_ROTATION flag.
163      * @see #TYPE_IDENTITY
164      * @see #TYPE_TRANSLATION
165      * @see #TYPE_UNIFORM_SCALE
166      * @see #TYPE_GENERAL_SCALE
167      * @see #TYPE_FLIP
168      * @see #TYPE_GENERAL_ROTATION
169      * @see #TYPE_GENERAL_TRANSFORM
170      * @see #getType
171      */

172     public static final int TYPE_QUADRANT_ROTATION = 8;
173
174     /**
175      * This flag bit indicates that the transform defined by this object
176      * performs a rotation by an arbitrary angle in addition to the
177      * conversions indicated by other flag bits.
178      * A rotation changes the angles of vectors by the same amount
179      * regardless of the original direction of the vector and without
180      * changing the length of the vector.
181      * This flag bit is mutually exclusive with the
182      * TYPE_QUADRANT_ROTATION flag.
183      * @see #TYPE_IDENTITY
184      * @see #TYPE_TRANSLATION
185      * @see #TYPE_UNIFORM_SCALE
186      * @see #TYPE_GENERAL_SCALE
187      * @see #TYPE_FLIP
188      * @see #TYPE_QUADRANT_ROTATION
189      * @see #TYPE_GENERAL_TRANSFORM
190      * @see #getType
191      */

192     public static final int TYPE_GENERAL_ROTATION = 16;
193
194     /**
195      * This constant is a bit mask for any of the rotation flag bits.
196      * @see #TYPE_QUADRANT_ROTATION
197      * @see #TYPE_GENERAL_ROTATION
198      */

199     public static final int TYPE_MASK_ROTATION = (TYPE_QUADRANT_ROTATION |
200                           TYPE_GENERAL_ROTATION);
201
202     /**
203      * This constant indicates that the transform defined by this object
204      * performs an arbitrary conversion of the input coordinates.
205      * If this transform can be classified by any of the above constants,
206      * the type will either be the constant TYPE_IDENTITY or a
207      * combination of the appropriate flag bits for the various coordinate
208      * conversions that this transform performs.
209      * @see #TYPE_IDENTITY
210      * @see #TYPE_TRANSLATION
211      * @see #TYPE_UNIFORM_SCALE
212      * @see #TYPE_GENERAL_SCALE
213      * @see #TYPE_FLIP
214      * @see #TYPE_QUADRANT_ROTATION
215      * @see #TYPE_GENERAL_ROTATION
216      * @see #getType
217      */

218     public static final int TYPE_GENERAL_TRANSFORM = 32;
219
220     /**
221      * This constant is used for the internal state variable to indicate
222      * that no calculations need to be performed and that the source
223      * coordinates only need to be copied to their destinations to
224      * complete the transformation equation of this transform.
225      * @see #APPLY_TRANSLATE
226      * @see #APPLY_SCALE
227      * @see #APPLY_SHEAR
228      * @see #state
229      */

230     static final int APPLY_IDENTITY = 0;
231
232     /**
233      * This constant is used for the internal state variable to indicate
234      * that the translation components of the matrix (m02 and m12) need
235      * to be added to complete the transformation equation of this transform.
236      * @see #APPLY_IDENTITY
237      * @see #APPLY_SCALE
238      * @see #APPLY_SHEAR
239      * @see #state
240      */

241     static final int APPLY_TRANSLATE = 1;
242
243     /**
244      * This constant is used for the internal state variable to indicate
245      * that the scaling components of the matrix (m00 and m11) need
246      * to be factored in to complete the transformation equation of
247      * this transform. If the APPLY_SHEAR bit is also set then it
248      * indicates that the scaling components are not both 0.0. If the
249      * APPLY_SHEAR bit is not also set then it indicates that the
250      * scaling components are not both 1.0. If neither the APPLY_SHEAR
251      * nor the APPLY_SCALE bits are set then the scaling components
252      * are both 1.0, which means that the x and y components contribute
253      * to the transformed coordinate, but they are not multiplied by
254      * any scaling factor.
255      * @see #APPLY_IDENTITY
256      * @see #APPLY_TRANSLATE
257      * @see #APPLY_SHEAR
258      * @see #state
259      */

260     static final int APPLY_SCALE = 2;
261
262     /**
263      * This constant is used for the internal state variable to indicate
264      * that the shearing components of the matrix (m01 and m10) need
265      * to be factored in to complete the transformation equation of this
266      * transform. The presence of this bit in the state variable changes
267      * the interpretation of the APPLY_SCALE bit as indicated in its
268      * documentation.
269      * @see #APPLY_IDENTITY
270      * @see #APPLY_TRANSLATE
271      * @see #APPLY_SCALE
272      * @see #state
273      */

274     static final int APPLY_SHEAR = 4;
275
276     /*
277      * For methods which combine together the state of two separate
278      * transforms and dispatch based upon the combination, these constants
279      * specify how far to shift one of the states so that the two states
280      * are mutually non-interfering and provide constants for testing the
281      * bits of the shifted (HI) state. The methods in this class use
282      * the convention that the state of "this" transform is unshifted and
283      * the state of the "other" or "argument" transform is shifted (HI).
284      */

285     private static final int HI_SHIFT = 3;
286     private static final int HI_IDENTITY = APPLY_IDENTITY << HI_SHIFT;
287     private static final int HI_TRANSLATE = APPLY_TRANSLATE << HI_SHIFT;
288     private static final int HI_SCALE = APPLY_SCALE << HI_SHIFT;
289     private static final int HI_SHEAR = APPLY_SHEAR << HI_SHIFT;
290
291     /**
292      * The X coordinate scaling element of the 3x3
293      * affine transformation matrix.
294      *
295      * @serial
296      */

297     double m00;
298
299     /**
300      * The Y coordinate shearing element of the 3x3
301      * affine transformation matrix.
302      *
303      * @serial
304      */

305      double m10;
306
307     /**
308      * The X coordinate shearing element of the 3x3
309      * affine transformation matrix.
310      *
311      * @serial
312      */

313      double m01;
314
315     /**
316      * The Y coordinate scaling element of the 3x3
317      * affine transformation matrix.
318      *
319      * @serial
320      */

321      double m11;
322
323     /**
324      * The X coordinate of the translation element of the
325      * 3x3 affine transformation matrix.
326      *
327      * @serial
328      */

329      double m02;
330
331     /**
332      * The Y coordinate of the translation element of the
333      * 3x3 affine transformation matrix.
334      *
335      * @serial
336      */

337      double m12;
338
339     /**
340      * This field keeps track of which components of the matrix need to
341      * be applied when performing a transformation.
342      * @see #APPLY_IDENTITY
343      * @see #APPLY_TRANSLATE
344      * @see #APPLY_SCALE
345      * @see #APPLY_SHEAR
346      */

347     transient int state;
348
349     /**
350      * This field caches the current transformation type of the matrix.
351      * @see #TYPE_IDENTITY
352      * @see #TYPE_TRANSLATION
353      * @see #TYPE_UNIFORM_SCALE
354      * @see #TYPE_GENERAL_SCALE
355      * @see #TYPE_FLIP
356      * @see #TYPE_QUADRANT_ROTATION
357      * @see #TYPE_GENERAL_ROTATION
358      * @see #TYPE_GENERAL_TRANSFORM
359      * @see #TYPE_UNKNOWN
360      * @see #getType
361      */

362     private transient int type;
363
364     private AffineTransform(double m00, double m10,
365                 double m01, double m11,
366                 double m02, double m12,
367                 int state) {
368     this.m00 = m00;
369     this.m10 = m10;
370     this.m01 = m01;
371     this.m11 = m11;
372     this.m02 = m02;
373     this.m12 = m12;
374     this.state = state;
375     this.type = TYPE_UNKNOWN;
376     }
377
378     /**
379      * Constructs a new <code>AffineTransform</code> representing the
380      * Identity transformation.
381      */

382     public AffineTransform() {
383     m00 = m11 = 1.0;
384     // m01 = m10 = m02 = m12 = 0.0; /* Not needed. */
385
// state = APPLY_IDENTITY; /* Not needed. */
386
// type = TYPE_IDENTITY; /* Not needed. */
387
}
388
389     /**
390      * Constructs a new <code>AffineTransform</code> that is a copy of
391      * the specified <code>AffineTransform</code> object.
392      * @param Tx the <code>AffineTransform</code> object to copy
393      */

394     public AffineTransform(AffineTransform JavaDoc Tx) {
395     this.m00 = Tx.m00;
396     this.m10 = Tx.m10;
397     this.m01 = Tx.m01;
398     this.m11 = Tx.m11;
399     this.m02 = Tx.m02;
400     this.m12 = Tx.m12;
401     this.state = Tx.state;
402     this.type = Tx.type;
403     }
404
405     /**
406      * Constructs a new <code>AffineTransform</code> from 6 floating point
407      * values representing the 6 specifiable entries of the 3x3
408      * transformation matrix.
409      * @param m00,&nbsp;m01,&nbsp;m02,&nbsp;m10,&nbsp;m11,&nbsp;m12 the
410      * 6 floating point values that compose the 3x3 transformation matrix
411      */

412     public AffineTransform(float m00, float m10,
413                float m01, float m11,
414                float m02, float m12) {
415     this.m00 = m00;
416     this.m10 = m10;
417     this.m01 = m01;
418     this.m11 = m11;
419     this.m02 = m02;
420     this.m12 = m12;
421     updateState();
422     }
423
424     /**
425      * Constructs a new <code>AffineTransform</code> from an array of
426      * floating point values representing either the 4 non-translation
427      * enries or the 6 specifiable entries of the 3x3 transformation
428      * matrix. The values are retrieved from the array as
429      * {&nbsp;m00&nbsp;m10&nbsp;m01&nbsp;m11&nbsp;[m02&nbsp;m12]}.
430      * @param flatmatrix the float array containing the values to be set
431      * in the new <code>AffineTransform</code> object. The length of the
432      * array is assumed to be at least 4. If the length of the array is
433      * less than 6, only the first 4 values are taken. If the length of
434      * the array is greater than 6, the first 6 values are taken.
435      */

436     public AffineTransform(float[] flatmatrix) {
437     m00 = flatmatrix[0];
438     m10 = flatmatrix[1];
439     m01 = flatmatrix[2];
440     m11 = flatmatrix[3];
441     if (flatmatrix.length > 5) {
442         m02 = flatmatrix[4];
443         m12 = flatmatrix[5];
444     }
445     updateState();
446     }
447
448     /**
449      * Constructs a new <code>AffineTransform</code> from 6 double
450      * precision values representing the 6 specifiable entries of the 3x3
451      * transformation matrix.
452      * @param m00,&nbsp;m01,&nbsp;m02,&nbsp;m10,&nbsp;m11,&nbsp;m12 the
453      * 6 floating point values that compose the 3x3 transformation matrix
454      */

455     public AffineTransform(double m00, double m10,
456                double m01, double m11,
457                double m02, double m12) {
458     this.m00 = m00;
459     this.m10 = m10;
460     this.m01 = m01;
461     this.m11 = m11;
462     this.m02 = m02;
463     this.m12 = m12;
464     updateState();
465     }
466
467     /**
468      * Constructs a new <code>AffineTransform</code> from an array of
469      * double precision values representing either the 4 non-translation
470      * entries or the 6 specifiable entries of the 3x3 transformation
471      * matrix. The values are retrieved from the array as
472      * {&nbsp;m00&nbsp;m10&nbsp;m01&nbsp;m11&nbsp;[m02&nbsp;m12]}.
473      * @param flatmatrix the double array containing the values to be set
474      * in the new <code>AffineTransform</code> object. The length of the
475      * array is assumed to be at least 4. If the length of the array is
476      * less than 6, only the first 4 values are taken. If the length of
477      * the array is greater than 6, the first 6 values are taken.
478      */

479     public AffineTransform(double[] flatmatrix) {
480     m00 = flatmatrix[0];
481     m10 = flatmatrix[1];
482     m01 = flatmatrix[2];
483     m11 = flatmatrix[3];
484     if (flatmatrix.length > 5) {
485         m02 = flatmatrix[4];
486         m12 = flatmatrix[5];
487     }
488     updateState();
489     }
490
491     /**
492      * Returns a transform representing a translation transformation.
493      * The matrix representing the returned transform is:
494      * <pre>
495      * [ 1 0 tx ]
496      * [ 0 1 ty ]
497      * [ 0 0 1 ]
498      * </pre>
499      * @param tx the distance by which coordinates are translated in the
500      * X axis direction
501      * @param ty the distance by which coordinates are translated in the
502      * Y axis direction
503      * @return an <code>AffineTransform</code> object that represents a
504      * translation transformation, created with the specified vector.
505      */

506     public static AffineTransform JavaDoc getTranslateInstance(double tx, double ty) {
507     AffineTransform JavaDoc Tx = new AffineTransform JavaDoc();
508     Tx.setToTranslation(tx, ty);
509     return Tx;
510     }
511
512     /**
513      * Returns a transform representing a rotation transformation.
514      * The matrix representing the returned transform is:
515      * <pre>
516      * [ cos(theta) -sin(theta) 0 ]
517      * [ sin(theta) cos(theta) 0 ]
518      * [ 0 0 1 ]
519      * </pre>
520      * Rotating with a positive angle theta rotates points on the positive
521      * x axis toward the positive y axis.
522      * @param theta the angle of rotation in radians
523      * @return an <code>AffineTransform</code> object that is a rotation
524      * transformation, created with the specified angle of rotation.
525      */

526     public static AffineTransform JavaDoc getRotateInstance(double theta) {
527     AffineTransform JavaDoc Tx = new AffineTransform JavaDoc();
528     Tx.setToRotation(theta);
529     return Tx;
530     }
531
532     /**
533      * Returns a transform that rotates coordinates around an anchor point.
534      * This operation is equivalent to translating the coordinates so
535      * that the anchor point is at the origin (S1), then rotating them
536      * about the new origin (S2), and finally translating so that the
537      * intermediate origin is restored to the coordinates of the original
538      * anchor point (S3).
539      * <p>
540      * This operation is equivalent to the following sequence of calls:
541      * <pre>
542      * AffineTransform Tx = new AffineTransform();
543      * Tx.setToTranslation(x, y); // S3: final translation
544      * Tx.rotate(theta); // S2: rotate around anchor
545      * Tx.translate(-x, -y); // S1: translate anchor to origin
546      * </pre>
547      * The matrix representing the returned transform is:
548      * <pre>
549      * [ cos(theta) -sin(theta) x-x*cos+y*sin ]
550      * [ sin(theta) cos(theta) y-x*sin-y*cos ]
551      * [ 0 0 1 ]
552      * </pre>
553      * Rotating with a positive angle theta rotates points on the positive
554      * x axis toward the positive y axis.
555      * @param theta the angle of rotation in radians
556      * @param x,&nbsp;y the coordinates of the anchor point of the
557      * rotation
558      * @return an <code>AffineTransform</code> object that rotates
559      * coordinates around the specified point by the specified angle of
560      * rotation.
561      */

562     public static AffineTransform JavaDoc getRotateInstance(double theta,
563                             double x, double y) {
564     AffineTransform JavaDoc Tx = new AffineTransform JavaDoc();
565     Tx.setToRotation(theta, x, y);
566     return Tx;
567     }
568
569     /**
570      * Returns a transform representing a scaling transformation.
571      * The matrix representing the returned transform is:
572      * <pre>
573      * [ sx 0 0 ]
574      * [ 0 sy 0 ]
575      * [ 0 0 1 ]
576      * </pre>
577      * @param sx the factor by which coordinates are scaled along the
578      * X axis direction
579      * @param sy the factor by which coordinates are scaled along the
580      * Y axis direction
581      * @return an <code>AffineTransform</code> object that scales
582      * coordinates by the specified factors.
583      */

584     public static AffineTransform JavaDoc getScaleInstance(double sx, double sy) {
585     AffineTransform JavaDoc Tx = new AffineTransform JavaDoc();
586     Tx.setToScale(sx, sy);
587     return Tx;
588     }
589
590     /**
591      * Returns a transform representing a shearing transformation.
592      * The matrix representing the returned transform is:
593      * <pre>
594      * [ 1 shx 0 ]
595      * [ shy 1 0 ]
596      * [ 0 0 1 ]
597      * </pre>
598      * @param shx the multiplier by which coordinates are shifted in the
599      * direction of the positive X axis as a factor of their Y coordinate
600      * @param shy the multiplier by which coordinates are shifted in the
601      * direction of the positive Y axis as a factor of their X coordinate
602      * @return an <code>AffineTransform</code> object that shears
603      * coordinates by the specified multipliers.
604      */

605     public static AffineTransform JavaDoc getShearInstance(double shx, double shy) {
606     AffineTransform JavaDoc Tx = new AffineTransform JavaDoc();
607     Tx.setToShear(shx, shy);
608     return Tx;
609     }
610
611     /**
612      * Retrieves the flag bits describing the conversion properties of
613      * this transform.
614      * The return value is either one of the constants TYPE_IDENTITY
615      * or TYPE_GENERAL_TRANSFORM, or a combination of the
616      * appriopriate flag bits.
617      * A valid combination of flag bits is an exclusive OR operation
618      * that can combine
619      * the TYPE_TRANSLATION flag bit
620      * in addition to either of the
621      * TYPE_UNIFORM_SCALE or TYPE_GENERAL_SCALE flag bits
622      * as well as either of the
623      * TYPE_QUADRANT_ROTATION or TYPE_GENERAL_ROTATION flag bits.
624      * @return the OR combination of any of the indicated flags that
625      * apply to this transform
626      * @see #TYPE_IDENTITY
627      * @see #TYPE_TRANSLATION
628      * @see #TYPE_UNIFORM_SCALE
629      * @see #TYPE_GENERAL_SCALE
630      * @see #TYPE_QUADRANT_ROTATION
631      * @see #TYPE_GENERAL_ROTATION
632      * @see #TYPE_GENERAL_TRANSFORM
633      */

634     public int getType() {
635     if (type == TYPE_UNKNOWN) {
636         calculateType();
637     }
638     return type;
639     }
640
641     /**
642      * This is the utility function to calculate the flag bits when
643      * they have not been cached.
644      * @see #getType
645      */

646     private void calculateType() {
647     int ret = TYPE_IDENTITY;
648     boolean sgn0, sgn1;
649     double M0, M1, M2, M3;
650     updateState();
651     switch (state) {
652     default:
653         stateError();
654         /* NOTREACHED */
655     case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
656         ret = TYPE_TRANSLATION;
657         /* NOBREAK */
658     case (APPLY_SHEAR | APPLY_SCALE):
659         if ((M0 = m00) * (M2 = m01) + (M3 = m10) * (M1 = m11) != 0) {
660         // Transformed unit vectors are not perpendicular...
661
this.type = TYPE_GENERAL_TRANSFORM;
662         return;
663         }
664         sgn0 = (M0 >= 0.0);
665         sgn1 = (M1 >= 0.0);
666         if (sgn0 == sgn1) {
667         // sgn(M0) == sgn(M1) therefore sgn(M2) == -sgn(M3)
668
// This is the "unflipped" (right-handed) state
669
if (M0 != M1 || M2 != -M3) {
670             ret |= (TYPE_GENERAL_ROTATION | TYPE_GENERAL_SCALE);
671         } else if (M0 * M1 - M2 * M3 != 1.0) {
672             ret |= (TYPE_GENERAL_ROTATION | TYPE_UNIFORM_SCALE);
673         } else {
674             ret |= TYPE_GENERAL_ROTATION;
675         }
676         } else {
677         // sgn(M0) == -sgn(M1) therefore sgn(M2) == sgn(M3)
678
// This is the "flipped" (left-handed) state
679
if (M0 != -M1 || M2 != M3) {
680             ret |= (TYPE_GENERAL_ROTATION |
681                 TYPE_FLIP |
682                 TYPE_GENERAL_SCALE);
683         } else if (M0 * M1 - M2 * M3 != 1.0) {
684             ret |= (TYPE_GENERAL_ROTATION |
685                 TYPE_FLIP |
686                 TYPE_UNIFORM_SCALE);
687         } else {
688             ret |= (TYPE_GENERAL_ROTATION | TYPE_FLIP);
689         }
690         }
691         break;
692     case (APPLY_SHEAR | APPLY_TRANSLATE):
693         ret = TYPE_TRANSLATION;
694         /* NOBREAK */
695     case (APPLY_SHEAR):
696         sgn0 = ((M0 = m01) >= 0.0);
697         sgn1 = ((M1 = m10) >= 0.0);
698         if (sgn0 != sgn1) {
699         // Different signs - simple 90 degree rotation
700
if (M0 != -M1) {
701             ret |= (TYPE_QUADRANT_ROTATION | TYPE_GENERAL_SCALE);
702         } else if (M0 != 1.0 && M0 != -1.0) {
703             ret |= (TYPE_QUADRANT_ROTATION | TYPE_UNIFORM_SCALE);
704         } else {
705             ret |= TYPE_QUADRANT_ROTATION;
706         }
707         } else {
708         // Same signs - 90 degree rotation plus an axis flip too
709
if (M0 == M1) {
710             ret |= (TYPE_QUADRANT_ROTATION |
711                 TYPE_FLIP |
712                 TYPE_UNIFORM_SCALE);
713         } else {
714             ret |= (TYPE_QUADRANT_ROTATION |
715                 TYPE_FLIP |
716                 TYPE_GENERAL_SCALE);
717         }
718         }
719         break;
720     case (APPLY_SCALE | APPLY_TRANSLATE):
721         ret = TYPE_TRANSLATION;
722         /* NOBREAK */
723     case (APPLY_SCALE):
724         sgn0 = ((M0 = m00) >= 0.0);
725         sgn1 = ((M1 = m11) >= 0.0);
726         if (sgn0 == sgn1) {
727         if (sgn0) {
728             // Both scaling factors non-negative - simple scale
729
// Note: APPLY_SCALE implies M0, M1 are not both 1
730
if (M0 == M1) {
731             ret |= TYPE_UNIFORM_SCALE;
732             } else {
733             ret |= TYPE_GENERAL_SCALE;
734             }
735         } else {
736             // Both scaling factors negative - 180 degree rotation
737
if (M0 != M1) {
738             ret |= (TYPE_QUADRANT_ROTATION | TYPE_GENERAL_SCALE);
739             } else if (M0 != -1.0) {
740             ret |= (TYPE_QUADRANT_ROTATION | TYPE_UNIFORM_SCALE);
741             } else {
742             ret |= TYPE_QUADRANT_ROTATION;
743             }
744         }
745         } else {
746         // Scaling factor signs different - flip about some axis
747
if (M0 == -M1) {
748             if (M0 == 1.0 || M0 == -1.0) {
749             ret |= TYPE_FLIP;
750             } else {
751             ret |= (TYPE_FLIP | TYPE_UNIFORM_SCALE);
752             }
753         } else {
754             ret |= (TYPE_FLIP | TYPE_GENERAL_SCALE);
755         }
756         }
757         break;
758     case (APPLY_TRANSLATE):
759         ret = TYPE_TRANSLATION;
760         break;
761     case (APPLY_IDENTITY):
762         break;
763     }
764     this.type = ret;
765     }
766
767     /**
768      * Returns the determinant of the matrix representation of the transform.
769      * The determinant is useful both to determine if the transform can
770      * be inverted and to get a single value representing the
771      * combined X and Y scaling of the transform.
772      * <p>
773      * If the determinant is non-zero, then this transform is
774      * invertible and the various methods that depend on the inverse
775      * transform do not need to throw a
776      * {@link NoninvertibleTransformException}.
777      * If the determinant is zero then this transform can not be
778      * inverted since the transform maps all input coordinates onto
779      * a line or a point.
780      * If the determinant is near enough to zero then inverse transform
781      * operations might not carry enough precision to produce meaningful
782      * results.
783      * <p>
784      * If this transform represents a uniform scale, as indicated by
785      * the <code>getType</code> method then the determinant also
786      * represents the square of the uniform scale factor by which all of
787      * the points are expanded from or contracted towards the origin.
788      * If this transform represents a non-uniform scale or more general
789      * transform then the determinant is not likely to represent a
790      * value useful for any purpose other than determining if inverse
791      * transforms are possible.
792      * <p>
793      * Mathematically, the determinant is calculated using the formula:
794      * <pre>
795      * | m00 m01 m02 |
796      * | m10 m11 m12 | = m00 * m11 - m01 * m10
797      * | 0 0 1 |
798      * </pre>
799      *
800      * @return the determinant of the matrix used to transform the
801      * coordinates.
802      * @see #getType
803      * @see #createInverse
804      * @see #inverseTransform
805      * @see #TYPE_UNIFORM_SCALE
806      */

807     public double getDeterminant() {
808     switch (state) {
809     default:
810         stateError();
811         /* NOTREACHED */
812     case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
813     case (APPLY_SHEAR | APPLY_SCALE):
814         return m00 * m11 - m01 * m10;
815     case (APPLY_SHEAR | APPLY_TRANSLATE):
816     case (APPLY_SHEAR):
817         return -(m01 * m10);
818     case (APPLY_SCALE | APPLY_TRANSLATE):
819     case (APPLY_SCALE):
820         return m00 * m11;
821     case (APPLY_TRANSLATE):
822     case (APPLY_IDENTITY):
823         return 1.0;
824     }
825     }
826
827     /**
828      * Manually recalculates the state of the transform when the matrix
829      * changes too much to predict the effects on the state.
830      * The following table specifies what the various settings of the
831      * state field say about the values of the corresponding matrix
832      * element fields.
833      * Note that the rules governing the SCALE fields are slightly
834      * different depending on whether the SHEAR flag is also set.
835      * <pre>
836      * SCALE SHEAR TRANSLATE
837      * m00/m11 m01/m10 m02/m12
838      *
839      * IDENTITY 1.0 0.0 0.0
840      * TRANSLATE (TR) 1.0 0.0 not both 0.0
841      * SCALE (SC) not both 1.0 0.0 0.0
842      * TR | SC not both 1.0 0.0 not both 0.0
843      * SHEAR (SH) 0.0 not both 0.0 0.0
844      * TR | SH 0.0 not both 0.0 not both 0.0
845      * SC | SH not both 0.0 not both 0.0 0.0
846      * TR | SC | SH not both 0.0 not both 0.0 not both 0.0
847      * </pre>
848      */

849     void updateState() {
850     if (m01 == 0.0 && m10 == 0.0) {
851         if (m00 == 1.0 && m11 == 1.0) {
852         if (m02 == 0.0 && m12 == 0.0) {
853             state = APPLY_IDENTITY;
854             type = TYPE_IDENTITY;
855         } else {
856             state = APPLY_TRANSLATE;
857             type = TYPE_TRANSLATION;
858         }
859         } else {
860         if (m02 == 0.0 && m12 == 0.0) {
861             state = APPLY_SCALE;
862             type = TYPE_UNKNOWN;
863         } else {
864             state = (APPLY_SCALE | APPLY_TRANSLATE);
865             type = TYPE_UNKNOWN;
866         }
867         }
868     } else {
869         if (m00 == 0.0 && m11 == 0.0) {
870         if (m02 == 0.0 && m12 == 0.0) {
871             state = APPLY_SHEAR;
872             type = TYPE_UNKNOWN;
873         } else {
874             state = (APPLY_SHEAR | APPLY_TRANSLATE);
875             type = TYPE_UNKNOWN;
876         }
877         } else {
878         if (m02 == 0.0 && m12 == 0.0) {
879             state = (APPLY_SHEAR | APPLY_SCALE);
880             type = TYPE_UNKNOWN;
881         } else {
882             state = (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE);
883             type = TYPE_UNKNOWN;
884         }
885         }
886     }
887     }
888
889     /*
890      * Convenience method used internally to throw exceptions when
891      * a case was forgotten in a switch statement.
892      */

893     private void stateError() {
894     throw new InternalError JavaDoc("missing case in transform state switch");
895     }
896     
897     /**
898      * Retrieves the 6 specifiable values in the 3x3 affine transformation
899      * matrix and places them into an array of double precisions values.
900      * The values are stored in the array as
901      * {&nbsp;m00&nbsp;m10&nbsp;m01&nbsp;m11&nbsp;m02&nbsp;m12&nbsp;}.
902      * An array of 4 doubles can also be specified, in which case only the
903      * first four elements representing the non-transform
904      * parts of the array are retrieved and the values are stored into
905      * the array as {&nbsp;m00&nbsp;m10&nbsp;m01&nbsp;m11&nbsp;}
906      * @param flatmatrix the double array used to store the returned
907      * values.
908      * @see #getScaleX
909      * @see #getScaleY
910      * @see #getShearX
911      * @see #getShearY
912      * @see #getTranslateX
913      * @see #getTranslateY
914      */

915     public void getMatrix(double[] flatmatrix) {
916     flatmatrix[0] = m00;
917     flatmatrix[1] = m10;
918     flatmatrix[2] = m01;
919     flatmatrix[3] = m11;
920     if (flatmatrix.length > 5) {
921         flatmatrix[4] = m02;
922         flatmatrix[5] = m12;
923     }
924     }
925
926     /**
927      * Returns the X coordinate scaling element (m00) of the 3x3
928      * affine transformation matrix.
929      * @return a double value that is the X coordinate of the scaling
930      * element of the affine transformation matrix.
931      * @see #getMatrix
932      */

933     public double getScaleX() {
934     return m00;
935     }
936
937     /**
938      * Returns the Y coordinate scaling element (m11) of the 3x3
939      * affine transformation matrix.
940      * @return a double value that is the Y coordinate of the scaling
941      * element of the affine transformation matrix.
942      * @see #getMatrix
943      */

944     public double getScaleY() {
945     return m11;
946     }
947
948     /**
949      * Returns the X coordinate shearing element (m01) of the 3x3
950      * affine transformation matrix.
951      * @return a double value that is the X coordinate of the shearing
952      * element of the affine transformation matrix.
953      * @see #getMatrix
954      */

955     public double getShearX() {
956     return m01;
957     }
958
959     /**
960      * Returns the Y coordinate shearing element (m10) of the 3x3
961      * affine transformation matrix.
962      * @return a double value that is the Y coordinate of the shearing
963      * element of the affine transformation matrix.
964      * @see #getMatrix
965      */

966     public double getShearY() {
967     return m10;
968     }
969
970     /**
971      * Returns the X coordinate of the translation element (m02) of the
972      * 3x3 affine transformation matrix.
973      * @return a double value that is the X coordinate of the translation
974      * element of the affine transformation matrix.
975      * @see #getMatrix
976      */

977     public double getTranslateX() {
978     return m02;
979     }
980
981     /**
982      * Returns the Y coordinate of the translation element (m12) of the
983      * 3x3 affine transformation matrix.
984      * @return a double value that is the Y coordinate of the translation
985      * element of the affine transformation matrix.
986      * @see #getMatrix
987      */

988     public double getTranslateY() {
989     return m12;
990     }
991
992     /**
993      * Concatenates this transform with a translation transformation.
994      * This is equivalent to calling concatenate(T), where T is an
995      * <code>AffineTransform</code> represented by the following matrix:
996      * <pre>
997      * [ 1 0 tx ]
998      * [ 0 1 ty ]
999      * [ 0 0 1 ]
1000     * </pre>
1001     * @param tx the distance by which coordinates are translated in the
1002     * X axis direction
1003     * @param ty the distance by which coordinates are translated in the
1004     * Y axis direction
1005     */

1006    public void translate(double tx, double ty) {
1007    switch (state) {
1008    default:
1009        stateError();
1010        /* NOTREACHED */
1011    case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
1012        m02 = tx * m00 + ty * m01 + m02;
1013        m12 = tx * m10 + ty * m11 + m12;
1014        if (m02 == 0.0 && m12 == 0.0) {
1015        state = APPLY_SHEAR | APPLY_SCALE;
1016        if (type != TYPE_UNKNOWN) {
1017            type -= TYPE_TRANSLATION;
1018        }
1019        }
1020        return;
1021    case (APPLY_SHEAR | APPLY_SCALE):
1022        m02 = tx * m00 + ty * m01;
1023        m12 = tx * m10 + ty * m11;
1024        if (m02 != 0.0 || m12 != 0.0) {
1025        state = APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE;
1026        type |= TYPE_TRANSLATION;
1027        }
1028        return;
1029    case (APPLY_SHEAR | APPLY_TRANSLATE):
1030  &