1. /*
  2. * @(#)AffineTransform.java 1.60 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.awt.geom;
  8. import java.awt.Shape;
  9. /**
  10. * The <code>AffineTransform</code> class represents a 2D affine transform
  11. * that performs a linear mapping from 2D coordinates to other 2D
  12. * coordinates that preserves the "straightness" and
  13. * "parallelness" of lines. Affine transformations can be constructed
  14. * using sequences of translations, scales, flips, rotations, and shears.
  15. * <p>
  16. * Such a coordinate transformation can be represented by a 3 row by
  17. * 3 column matrix with an implied last row of [ 0 0 1 ]. This matrix
  18. * transforms source coordinates <code>(x, y)</code> into
  19. * destination coordinates <code>(x', y')</code> by considering
  20. * them to be a column vector and multiplying the coordinate vector
  21. * by the matrix according to the following process:
  22. * <pre>
  23. * [ x'] [ m00 m01 m02 ] [ x ] [ m00x + m01y + m02 ]
  24. * [ y'] = [ m10 m11 m12 ] [ y ] = [ m10x + m11y + m12 ]
  25. * [ 1 ] [ 0 0 1 ] [ 1 ] [ 1 ]
  26. * </pre>
  27. *
  28. * @version 10 Feb 1997
  29. * @author Jim Graham
  30. */
  31. public class AffineTransform implements Cloneable, java.io.Serializable {
  32. /**
  33. * This constant indicates that the transform defined by this object
  34. * is an identity transform.
  35. * An identity transform is one in which the output coordinates are
  36. * always the same as the input coordinates.
  37. * If this transform is anything other than the identity transform,
  38. * the type will either be the constant GENERAL_TRANSFORM or a
  39. * combination of the appropriate flag bits for the various coordinate
  40. * conversions that this transform performs.
  41. * @see #TYPE_TRANSLATION
  42. * @see #TYPE_UNIFORM_SCALE
  43. * @see #TYPE_GENERAL_SCALE
  44. * @see #TYPE_FLIP
  45. * @see #TYPE_QUADRANT_ROTATION
  46. * @see #TYPE_GENERAL_ROTATION
  47. * @see #TYPE_GENERAL_TRANSFORM
  48. * @see #getType
  49. */
  50. public static final int TYPE_IDENTITY = 0;
  51. /**
  52. * This flag bit indicates that the transform defined by this object
  53. * performs a translation in addition to the conversions indicated
  54. * by other flag bits.
  55. * A translation moves the coordinates by a constant amount in x
  56. * and y without changing the length or angle of vectors.
  57. * @see #TYPE_IDENTITY
  58. * @see #TYPE_UNIFORM_SCALE
  59. * @see #TYPE_GENERAL_SCALE
  60. * @see #TYPE_FLIP
  61. * @see #TYPE_QUADRANT_ROTATION
  62. * @see #TYPE_GENERAL_ROTATION
  63. * @see #TYPE_GENERAL_TRANSFORM
  64. * @see #getType
  65. */
  66. public static final int TYPE_TRANSLATION = 1;
  67. /**
  68. * This flag bit indicates that the transform defined by this object
  69. * performs a uniform scale in addition to the conversions indicated
  70. * by other flag bits.
  71. * A uniform scale multiplies the length of vectors by the same amount
  72. * in both the x and y directions without changing the angle between
  73. * vectors.
  74. * This flag bit is mutually exclusive with the TYPE_GENERAL_SCALE flag.
  75. * @see #TYPE_IDENTITY
  76. * @see #TYPE_TRANSLATION
  77. * @see #TYPE_GENERAL_SCALE
  78. * @see #TYPE_FLIP
  79. * @see #TYPE_QUADRANT_ROTATION
  80. * @see #TYPE_GENERAL_ROTATION
  81. * @see #TYPE_GENERAL_TRANSFORM
  82. * @see #getType
  83. */
  84. public static final int TYPE_UNIFORM_SCALE = 2;
  85. /**
  86. * This flag bit indicates that the transform defined by this object
  87. * performs a general scale in addition to the conversions indicated
  88. * by other flag bits.
  89. * A general scale multiplies the length of vectors by different
  90. * amounts in the x and y directions without changing the angle
  91. * between perpendicular vectors.
  92. * This flag bit is mutually exclusive with the TYPE_UNIFORM_SCALE flag.
  93. * @see #TYPE_IDENTITY
  94. * @see #TYPE_TRANSLATION
  95. * @see #TYPE_UNIFORM_SCALE
  96. * @see #TYPE_FLIP
  97. * @see #TYPE_QUADRANT_ROTATION
  98. * @see #TYPE_GENERAL_ROTATION
  99. * @see #TYPE_GENERAL_TRANSFORM
  100. * @see #getType
  101. */
  102. public static final int TYPE_GENERAL_SCALE = 4;
  103. /**
  104. * This constant is a bit mask for any of the scale flag bits.
  105. * @see #TYPE_UNIFORM_SCALE
  106. * @see #TYPE_GENERAL_SCALE
  107. */
  108. public static final int TYPE_MASK_SCALE = (TYPE_UNIFORM_SCALE |
  109. TYPE_GENERAL_SCALE);
  110. /**
  111. * This flag bit indicates that the transform defined by this object
  112. * performs a mirror image flip about some axis which changes the
  113. * normally right handed coordinate system into a left handed
  114. * system in addition to the conversions indicated by other flag bits.
  115. * A right handed coordinate system is one where the positive X
  116. * axis rotates counterclockwise to overlay the positive Y axis
  117. * similar to the direction that the fingers on your right hand
  118. * curl when you stare end on at your thumb.
  119. * A left handed coordinate system is one where the positive X
  120. * axis rotates clockwise to overlay the positive Y axis similar
  121. * to the direction that the fingers on your left hand curl.
  122. * There is no mathematical way to determine the angle of the
  123. * original flipping or mirroring transformation since all angles
  124. * of flip are identical given an appropriate adjusting rotation.
  125. * @see #TYPE_IDENTITY
  126. * @see #TYPE_TRANSLATION
  127. * @see #TYPE_UNIFORM_SCALE
  128. * @see #TYPE_GENERAL_SCALE
  129. * @see #TYPE_QUADRANT_ROTATION
  130. * @see #TYPE_GENERAL_ROTATION
  131. * @see #TYPE_GENERAL_TRANSFORM
  132. * @see #getType
  133. */
  134. public static final int TYPE_FLIP = 64;
  135. /* NOTE: TYPE_FLIP was added after GENERAL_TRANSFORM was in public
  136. * circulation and the flag bits could no longer be conveniently
  137. * renumbered without introducing binary incompatibility in outside
  138. * code.
  139. */
  140. /**
  141. * This flag bit indicates that the transform defined by this object
  142. * performs a quadrant rotation by some multiple of 90 degrees in
  143. * addition to the conversions indicated by other flag bits.
  144. * A rotation changes the angles of vectors by the same amount
  145. * regardless of the original direction of the vector and without
  146. * changing the length of the vector.
  147. * This flag bit is mutually exclusive with the TYPE_GENERAL_ROTATION flag.
  148. * @see #TYPE_IDENTITY
  149. * @see #TYPE_TRANSLATION
  150. * @see #TYPE_UNIFORM_SCALE
  151. * @see #TYPE_GENERAL_SCALE
  152. * @see #TYPE_FLIP
  153. * @see #TYPE_GENERAL_ROTATION
  154. * @see #TYPE_GENERAL_TRANSFORM
  155. * @see #getType
  156. */
  157. public static final int TYPE_QUADRANT_ROTATION = 8;
  158. /**
  159. * This flag bit indicates that the transform defined by this object
  160. * performs a rotation by an arbitrary angle in addition to the
  161. * conversions indicated by other flag bits.
  162. * A rotation changes the angles of vectors by the same amount
  163. * regardless of the original direction of the vector and without
  164. * changing the length of the vector.
  165. * This flag bit is mutually exclusive with the
  166. * TYPE_QUADRANT_ROTATION flag.
  167. * @see #TYPE_IDENTITY
  168. * @see #TYPE_TRANSLATION
  169. * @see #TYPE_UNIFORM_SCALE
  170. * @see #TYPE_GENERAL_SCALE
  171. * @see #TYPE_FLIP
  172. * @see #TYPE_QUADRANT_ROTATION
  173. * @see #TYPE_GENERAL_TRANSFORM
  174. * @see #getType
  175. */
  176. public static final int TYPE_GENERAL_ROTATION = 16;
  177. /**
  178. * This constant is a bit mask for any of the rotation flag bits.
  179. * @see #TYPE_QUADRANT_ROTATION
  180. * @see #TYPE_GENERAL_ROTATION
  181. */
  182. public static final int TYPE_MASK_ROTATION = (TYPE_QUADRANT_ROTATION |
  183. TYPE_GENERAL_ROTATION);
  184. /**
  185. * This constant indicates that the transform defined by this object
  186. * performs an arbitrary conversion of the input coordinates.
  187. * If this transform can be classified by any of the above constants,
  188. * the type will either be the constant TYPE_IDENTITY or a
  189. * combination of the appropriate flag bits for the various coordinate
  190. * conversions that this transform performs.
  191. * @see #TYPE_IDENTITY
  192. * @see #TYPE_TRANSLATION
  193. * @see #TYPE_UNIFORM_SCALE
  194. * @see #TYPE_GENERAL_SCALE
  195. * @see #TYPE_FLIP
  196. * @see #TYPE_QUADRANT_ROTATION
  197. * @see #TYPE_GENERAL_ROTATION
  198. * @see #getType
  199. */
  200. public static final int TYPE_GENERAL_TRANSFORM = 32;
  201. /**
  202. * This constant is used for the internal state variable to indicate
  203. * that no calculations need to be performed and that the source
  204. * coordinates only need to be copied to their destinations to
  205. * complete the transformation equation of this transform.
  206. * @see #APPLY_TRANSLATE
  207. * @see #APPLY_SCALE
  208. * @see #APPLY_SHEAR
  209. * @see #state
  210. */
  211. static final int APPLY_IDENTITY = 0;
  212. /**
  213. * This constant is used for the internal state variable to indicate
  214. * that the translation components of the matrix (m02 and m12) need
  215. * to be added to complete the transformation equation of this transform.
  216. * @see #APPLY_IDENTITY
  217. * @see #APPLY_SCALE
  218. * @see #APPLY_SHEAR
  219. * @see #state
  220. */
  221. static final int APPLY_TRANSLATE = 1;
  222. /**
  223. * This constant is used for the internal state variable to indicate
  224. * that the scaling components of the matrix (m00 and m11) need
  225. * to be factored in to complete the transformation equation of
  226. * this transform. If the APPLY_SHEAR bit is also set then it
  227. * indicates that the scaling components are not both 0.0. If the
  228. * APPLY_SHEAR bit is not also set then it indicates that the
  229. * scaling components are not both 1.0. If neither the APPLY_SHEAR
  230. * nor the APPLY_SCALE bits are set then the scaling components
  231. * are both 1.0, which means that the x and y components contribute
  232. * to the transformed coordinate, but they are not multiplied by
  233. * any scaling factor.
  234. * @see #APPLY_IDENTITY
  235. * @see #APPLY_TRANSLATE
  236. * @see #APPLY_SHEAR
  237. * @see #state
  238. */
  239. static final int APPLY_SCALE = 2;
  240. /**
  241. * This constant is used for the internal state variable to indicate
  242. * that the shearing components of the matrix (m01 and m10) need
  243. * to be factored in to complete the transformation equation of this
  244. * transform. The presence of this bit in the state variable changes
  245. * the interpretation of the APPLY_SCALE bit as indicated in its
  246. * documentation.
  247. * @see #APPLY_IDENTITY
  248. * @see #APPLY_TRANSLATE
  249. * @see #APPLY_SCALE
  250. * @see #state
  251. */
  252. static final int APPLY_SHEAR = 4;
  253. /*
  254. * For methods which combine together the state of two separate
  255. * transforms and dispatch based upon the combination, these constants
  256. * specify how far to shift one of the states so that the two states
  257. * are mutually non-interfering and provide constants for testing the
  258. * bits of the shifted (HI) state. The methods in this class use
  259. * the convention that the state of "this" transform is unshifted and
  260. * the state of the "other" or "argument" transform is shifted (HI).
  261. */
  262. private static final int HI_SHIFT = 3;
  263. private static final int HI_IDENTITY = APPLY_IDENTITY << HI_SHIFT;
  264. private static final int HI_TRANSLATE = APPLY_TRANSLATE << HI_SHIFT;
  265. private static final int HI_SCALE = APPLY_SCALE << HI_SHIFT;
  266. private static final int HI_SHEAR = APPLY_SHEAR << HI_SHIFT;
  267. /**
  268. * The X coordinate scaling element of the 3x3
  269. * affine transformation matrix.
  270. *
  271. * @serial
  272. */
  273. double m00;
  274. /**
  275. * The Y coordinate shearing element of the 3x3
  276. * affine transformation matrix.
  277. *
  278. * @serial
  279. */
  280. double m10;
  281. /**
  282. * The X coordinate shearing element of the 3x3
  283. * affine transformation matrix.
  284. *
  285. * @serial
  286. */
  287. double m01;
  288. /**
  289. * The Y coordinate scaling element of the 3x3
  290. * affine transformation matrix.
  291. *
  292. * @serial
  293. */
  294. double m11;
  295. /**
  296. * The X coordinate of the translation element of the
  297. * 3x3 affine transformation matrix.
  298. *
  299. * @serial
  300. */
  301. double m02;
  302. /**
  303. * The Y coordinate of the translation element of the
  304. * 3x3 affine transformation matrix.
  305. *
  306. * @serial
  307. */
  308. double m12;
  309. /**
  310. * This field keeps track of which components of the matrix need to
  311. * be applied when performing a transformation.
  312. * @see #APPLY_IDENTITY
  313. * @see #APPLY_TRANSLATE
  314. * @see #APPLY_SCALE
  315. * @see #APPLY_SHEAR
  316. */
  317. transient int state;
  318. private AffineTransform(double m00, double m10,
  319. double m01, double m11,
  320. double m02, double m12,
  321. int state) {
  322. this.m00 = m00;
  323. this.m10 = m10;
  324. this.m01 = m01;
  325. this.m11 = m11;
  326. this.m02 = m02;
  327. this.m12 = m12;
  328. this.state = state;
  329. }
  330. /**
  331. * Constructs a new <code>AffineTransform</code> representing the
  332. * Identity transformation.
  333. */
  334. public AffineTransform() {
  335. m00 = m11 = 1.0;
  336. // m01 = m10 = m02 = m12 = 0.0; /* Not needed. */
  337. // state = APPLY_IDENTITY; /* Not needed. */
  338. }
  339. /**
  340. * Constructs a new <code>AffineTransform</code> that is a copy of
  341. * the specified <code>AffineTransform</code> object.
  342. * @param Tx the <code>AffineTransform</code> object to copy
  343. */
  344. public AffineTransform(AffineTransform Tx) {
  345. this.m00 = Tx.m00;
  346. this.m10 = Tx.m10;
  347. this.m01 = Tx.m01;
  348. this.m11 = Tx.m11;
  349. this.m02 = Tx.m02;
  350. this.m12 = Tx.m12;
  351. this.state = Tx.state;
  352. }
  353. /**
  354. * Constructs a new <code>AffineTransform</code> from 6 floating point
  355. * values representing the 6 specifiable entries of the 3x3
  356. * transformation matrix.
  357. * @param m00, m01, m02, m10, m11, m12 the
  358. * 6 floating point values that compose the 3x3 transformation matrix
  359. */
  360. public AffineTransform(float m00, float m10,
  361. float m01, float m11,
  362. float m02, float m12) {
  363. this.m00 = m00;
  364. this.m10 = m10;
  365. this.m01 = m01;
  366. this.m11 = m11;
  367. this.m02 = m02;
  368. this.m12 = m12;
  369. updateState();
  370. }
  371. /**
  372. * Constructs a new <code>AffineTransform</code> from an array of
  373. * floating point values representing either the 4 non-translation
  374. * enries or the 6 specifiable entries of the 3x3 transformation
  375. * matrix. The values are retrieved from the array as
  376. * { m00 m10 m01 m11 [m02 m12]}.
  377. * @param flatmatrix the float array containing the values to be set
  378. * in the new <code>AffineTransform</code> object. The length of the
  379. * array is assumed to be at least 4. If the length of the array is
  380. * less than 6, only the first 4 values are taken. If the length of
  381. * the array is greater than 6, the first 6 values are taken.
  382. */
  383. public AffineTransform(float[] flatmatrix) {
  384. m00 = flatmatrix[0];
  385. m10 = flatmatrix[1];
  386. m01 = flatmatrix[2];
  387. m11 = flatmatrix[3];
  388. if (flatmatrix.length > 5) {
  389. m02 = flatmatrix[4];
  390. m12 = flatmatrix[5];
  391. }
  392. updateState();
  393. }
  394. /**
  395. * Constructs a new <code>AffineTransform</code> from 6 double
  396. * precision values representing the 6 specifiable entries of the 3x3
  397. * transformation matrix.
  398. * @param m00, m01, m02, m10, m11, m12 the
  399. * 6 floating point values that compose the 3x3 transformation matrix
  400. */
  401. public AffineTransform(double m00, double m10,
  402. double m01, double m11,
  403. double m02, double m12) {
  404. this.m00 = m00;
  405. this.m10 = m10;
  406. this.m01 = m01;
  407. this.m11 = m11;
  408. this.m02 = m02;
  409. this.m12 = m12;
  410. updateState();
  411. }
  412. /**
  413. * Constructs a new <code>AffineTransform</code> from an array of
  414. * double precision values representing either the 4 non-translation
  415. * entries or the 6 specifiable entries of the 3x3 transformation
  416. * matrix. The values are retrieved from the array as
  417. * { m00 m10 m01 m11 [m02 m12]}.
  418. * @param flatmatrix the double array containing the values to be set
  419. * in the new <code>AffineTransform</code> object. The length of the
  420. * array is assumed to be at least 4. If the length of the array is
  421. * less than 6, only the first 4 values are taken. If the length of
  422. * the array is greater than 6, the first 6 values are taken.
  423. */
  424. public AffineTransform(double[] flatmatrix) {
  425. m00 = flatmatrix[0];
  426. m10 = flatmatrix[1];
  427. m01 = flatmatrix[2];
  428. m11 = flatmatrix[3];
  429. if (flatmatrix.length > 5) {
  430. m02 = flatmatrix[4];
  431. m12 = flatmatrix[5];
  432. }
  433. updateState();
  434. }
  435. /**
  436. * Returns a transform representing a translation transformation.
  437. * The matrix representing the returned transform is:
  438. * <pre>
  439. * [ 1 0 tx ]
  440. * [ 0 1 ty ]
  441. * [ 0 0 1 ]
  442. * </pre>
  443. * @param tx the distance by which coordinates are translated in the
  444. * X axis direction
  445. * @param ty the distance by which coordinates are translated in the
  446. * Y axis direction
  447. * @return an <code>AffineTransform</code> object that represents a
  448. * translation transformation, created with the specified vector.
  449. */
  450. public static AffineTransform getTranslateInstance(double tx, double ty) {
  451. AffineTransform Tx = new AffineTransform();
  452. Tx.setToTranslation(tx, ty);
  453. return Tx;
  454. }
  455. /**
  456. * Returns a transform representing a rotation transformation.
  457. * The matrix representing the returned transform is:
  458. * <pre>
  459. * [ cos(theta) -sin(theta) 0 ]
  460. * [ sin(theta) cos(theta) 0 ]
  461. * [ 0 0 1 ]
  462. * </pre>
  463. * Rotating with a positive angle theta rotates points on the positive
  464. * x axis toward the positive y axis.
  465. * @param theta the angle of rotation in radians
  466. * @return an <code>AffineTransform</code> object that is a rotation
  467. * transformation, created with the specified angle of rotation.
  468. */
  469. public static AffineTransform getRotateInstance(double theta) {
  470. AffineTransform Tx = new AffineTransform();
  471. Tx.setToRotation(theta);
  472. return Tx;
  473. }
  474. /**
  475. * Returns a transform that rotates coordinates around an anchor point.
  476. * This operation is equivalent to translating the coordinates so
  477. * that the anchor point is at the origin (S1), then rotating them
  478. * about the new origin (S2), and finally translating so that the
  479. * intermediate origin is restored to the coordinates of the original
  480. * anchor point (S3).
  481. * <p>
  482. * This operation is equivalent to the following sequence of calls:
  483. * <pre>
  484. * AffineTransform Tx = new AffineTransform();
  485. * Tx.setToTranslation(x, y); // S3: final translation
  486. * Tx.rotate(theta); // S2: rotate around anchor
  487. * Tx.translate(-x, -y); // S1: translate anchor to origin
  488. * </pre>
  489. * The matrix representing the returned transform is:
  490. * <pre>
  491. * [ cos(theta) -sin(theta) x-x*cos+y*sin ]
  492. * [ sin(theta) cos(theta) y-x*sin-y*cos ]
  493. * [ 0 0 1 ]
  494. * </pre>
  495. * Rotating with a positive angle theta rotates points on the positive
  496. * x axis toward the positive y axis.
  497. * @param theta the angle of rotation in radians
  498. * @param x, y the coordinates of the anchor point of the
  499. * rotation
  500. * @return an <code>AffineTransform</code> object that rotates
  501. * coordinates around the specified point by the specified angle of
  502. * rotation.
  503. */
  504. public static AffineTransform getRotateInstance(double theta,
  505. double x, double y) {
  506. AffineTransform Tx = new AffineTransform();
  507. Tx.setToRotation(theta, x, y);
  508. return Tx;
  509. }
  510. /**
  511. * Returns a transform representing a scaling transformation.
  512. * The matrix representing the returned transform is:
  513. * <pre>
  514. * [ sx 0 0 ]
  515. * [ 0 sy 0 ]
  516. * [ 0 0 1 ]
  517. * </pre>
  518. * @param sx the factor by which coordinates are scaled along the
  519. * X axis direction
  520. * @param sy the factor by which coordinates are scaled along the
  521. * Y axis direction
  522. * @return an <code>AffineTransform</code> object that scales
  523. * coordinates by the specified factors.
  524. */
  525. public static AffineTransform getScaleInstance(double sx, double sy) {
  526. AffineTransform Tx = new AffineTransform();
  527. Tx.setToScale(sx, sy);
  528. return Tx;
  529. }
  530. /**
  531. * Returns a transform representing a shearing transformation.
  532. * The matrix representing the returned transform is:
  533. * <pre>
  534. * [ 1 shx 0 ]
  535. * [ shy 1 0 ]
  536. * [ 0 0 1 ]
  537. * </pre>
  538. * @param shx the multiplier by which coordinates are shifted in the
  539. * direction of the positive X axis as a factor of their Y coordinate
  540. * @param shy the multiplier by which coordinates are shifted in the
  541. * direction of the positive Y axis as a factor of their X coordinate
  542. * @return an <code>AffineTransform</code> object that shears
  543. * coordinates by the specified multipliers.
  544. */
  545. public static AffineTransform getShearInstance(double shx, double shy) {
  546. AffineTransform Tx = new AffineTransform();
  547. Tx.setToShear(shx, shy);
  548. return Tx;
  549. }
  550. /**
  551. * Retrieves the flag bits describing the conversion properties of
  552. * this transform.
  553. * The return value is either one of the constants TYPE_IDENTITY
  554. * or TYPE_GENERAL_TRANSFORM, or a combination of the
  555. * appriopriate flag bits.
  556. * A valid combination of flag bits is an exclusive OR operation
  557. * that can combine
  558. * the TYPE_TRANSLATION flag bit
  559. * in addition to either of the
  560. * TYPE_UNIFORM_SCALE or TYPE_GENERAL_SCALE flag bits
  561. * as well as either of the
  562. * TYPE_QUADRANT_ROTATION or TYPE_GENERAL_ROTATION flag bits.
  563. * @return the OR combination of any of the indicated flags that
  564. * apply to this transform
  565. * @see #TYPE_IDENTITY
  566. * @see #TYPE_TRANSLATION
  567. * @see #TYPE_UNIFORM_SCALE
  568. * @see #TYPE_GENERAL_SCALE
  569. * @see #TYPE_QUADRANT_ROTATION
  570. * @see #TYPE_GENERAL_ROTATION
  571. * @see #TYPE_GENERAL_TRANSFORM
  572. */
  573. public int getType() {
  574. int ret = TYPE_IDENTITY;
  575. boolean sgn0, sgn1;
  576. double M0, M1, M2, M3;
  577. switch (state) {
  578. default:
  579. stateError();
  580. /* NOTREACHED */
  581. case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  582. ret = TYPE_TRANSLATION;
  583. /* NOBREAK */
  584. case (APPLY_SHEAR | APPLY_SCALE):
  585. if ((M0 = m00) * (M2 = m01) + (M3 = m10) * (M1 = m11) != 0) {
  586. // Transformed unit vectors are not perpendicular...
  587. return TYPE_GENERAL_TRANSFORM;
  588. }
  589. sgn0 = (M0 >= 0.0);
  590. sgn1 = (M1 >= 0.0);
  591. if (sgn0 == sgn1) {
  592. // sgn(M0) == sgn(M1) therefore sgn(M2) == -sgn(M3)
  593. // This is the "unflipped" (right-handed) state
  594. if (M0 != M1 || M2 != -M3) {
  595. ret |= (TYPE_GENERAL_ROTATION | TYPE_GENERAL_SCALE);
  596. } else if (M0 * M1 - M2 * M3 != 1.0) {
  597. ret |= (TYPE_GENERAL_ROTATION | TYPE_UNIFORM_SCALE);
  598. } else {
  599. ret |= TYPE_GENERAL_ROTATION;
  600. }
  601. } else {
  602. // sgn(M0) == -sgn(M1) therefore sgn(M2) == sgn(M3)
  603. // This is the "flipped" (left-handed) state
  604. if (M0 != -M1 || M2 != M3) {
  605. ret |= (TYPE_GENERAL_ROTATION |
  606. TYPE_FLIP |
  607. TYPE_GENERAL_SCALE);
  608. } else if (M0 * M1 - M2 * M3 != 1.0) {
  609. ret |= (TYPE_GENERAL_ROTATION |
  610. TYPE_FLIP |
  611. TYPE_UNIFORM_SCALE);
  612. } else {
  613. ret |= (TYPE_GENERAL_ROTATION | TYPE_FLIP);
  614. }
  615. }
  616. break;
  617. case (APPLY_SHEAR | APPLY_TRANSLATE):
  618. ret = TYPE_TRANSLATION;
  619. /* NOBREAK */
  620. case (APPLY_SHEAR):
  621. sgn0 = ((M0 = m01) >= 0.0);
  622. sgn1 = ((M1 = m10) >= 0.0);
  623. if (sgn0 != sgn1) {
  624. // Different signs - simple 90 degree rotation
  625. if (M0 == -M1) {
  626. ret |= (TYPE_QUADRANT_ROTATION | TYPE_UNIFORM_SCALE);
  627. } else {
  628. ret |= (TYPE_QUADRANT_ROTATION | TYPE_GENERAL_SCALE);
  629. }
  630. } else {
  631. // Same signs - 90 degree rotation plus an axis flip too
  632. if (M0 == M1) {
  633. ret |= (TYPE_QUADRANT_ROTATION |
  634. TYPE_FLIP |
  635. TYPE_UNIFORM_SCALE);
  636. } else {
  637. ret |= (TYPE_QUADRANT_ROTATION |
  638. TYPE_FLIP |
  639. TYPE_GENERAL_SCALE);
  640. }
  641. }
  642. break;
  643. case (APPLY_SCALE | APPLY_TRANSLATE):
  644. ret = TYPE_TRANSLATION;
  645. /* NOBREAK */
  646. case (APPLY_SCALE):
  647. sgn0 = ((M0 = m00) >= 0.0);
  648. sgn1 = ((M1 = m11) >= 0.0);
  649. if (sgn0 == sgn1) {
  650. if (sgn0) {
  651. // Both scaling factors non-negative - simple scale
  652. if (M0 == M1) {
  653. ret |= TYPE_UNIFORM_SCALE;
  654. } else {
  655. ret |= TYPE_GENERAL_SCALE;
  656. }
  657. } else {
  658. // Both scaling factors negative - 180 degree rotation
  659. if (M0 == M1) {
  660. ret |= (TYPE_QUADRANT_ROTATION | TYPE_UNIFORM_SCALE);
  661. } else {
  662. ret |= (TYPE_QUADRANT_ROTATION | TYPE_GENERAL_SCALE);
  663. }
  664. }
  665. } else {
  666. // Scaling factor signs different - flip about some axis
  667. if (M0 == -M1) {
  668. if (M0 == 1.0 || M0 == -1.0) {
  669. ret |= TYPE_FLIP;
  670. } else {
  671. ret |= (TYPE_FLIP | TYPE_UNIFORM_SCALE);
  672. }
  673. } else {
  674. ret |= (TYPE_FLIP | TYPE_GENERAL_SCALE);
  675. }
  676. }
  677. break;
  678. case (APPLY_TRANSLATE):
  679. ret = TYPE_TRANSLATION;
  680. break;
  681. case (APPLY_IDENTITY):
  682. break;
  683. }
  684. return ret;
  685. }
  686. /**
  687. * Returns the determinant of the matrix representation of the transform.
  688. * The determinant is useful both to determine if the transform can
  689. * be inverted and to get a single value representing the
  690. * combined X and Y scaling of the transform.
  691. * <p>
  692. * If the determinant is non-zero, then this transform is
  693. * invertible and the various methods that depend on the inverse
  694. * transform do not need to throw a
  695. * {@link NoninvertibleTransformException}.
  696. * If the determinant is zero then this transform can not be
  697. * inverted since the transform maps all input coordinates onto
  698. * a line or a point.
  699. * If the determinant is near enough to zero then inverse transform
  700. * operations might not carry enough precision to produce meaningful
  701. * results.
  702. * <p>
  703. * If this transform represents a uniform scale, as indicated by
  704. * the <code>getType</code> method then the determinant also
  705. * represents the square of the uniform scale factor by which all of
  706. * the points are expanded from or contracted towards the origin.
  707. * If this transform represents a non-uniform scale or more general
  708. * transform then the determinant is not likely to represent a
  709. * value useful for any purpose other than determining if inverse
  710. * transforms are possible.
  711. * <p>
  712. * Mathematically, the determinant is calculated using the formula:
  713. * <pre>
  714. * | m00 m01 m02 |
  715. * | m10 m11 m12 | = m00 * m11 - m01 * m10
  716. * | 0 0 1 |
  717. * </pre>
  718. *
  719. * @return the determinant of the matrix used to transform the
  720. * coordinates.
  721. * @see #getType
  722. * @see #createInverse
  723. * @see #inverseTransform
  724. * @see #TYPE_UNIFORM_SCALE
  725. */
  726. public double getDeterminant() {
  727. switch (state) {
  728. default:
  729. stateError();
  730. /* NOTREACHED */
  731. case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  732. case (APPLY_SHEAR | APPLY_SCALE):
  733. return m00 * m11 - m01 * m10;
  734. case (APPLY_SHEAR | APPLY_TRANSLATE):
  735. case (APPLY_SHEAR):
  736. return -(m01 * m10);
  737. case (APPLY_SCALE | APPLY_TRANSLATE):
  738. case (APPLY_SCALE):
  739. return m00 * m11;
  740. case (APPLY_TRANSLATE):
  741. case (APPLY_IDENTITY):
  742. return 1.0;
  743. }
  744. }
  745. /**
  746. * Manually recalculates the state of the transform when the matrix
  747. * changes too much to predict the effects on the state.
  748. */
  749. void updateState() {
  750. if (m01 == 0.0 && m10 == 0.0) {
  751. if (m00 == 1.0 && m11 == 1.0) {
  752. if (m02 == 0.0 && m12 == 0.0) {
  753. state = APPLY_IDENTITY;
  754. } else {
  755. state = APPLY_TRANSLATE;
  756. }
  757. } else {
  758. if (m02 == 0.0 && m12 == 0.0) {
  759. state = APPLY_SCALE;
  760. } else {
  761. state = (APPLY_SCALE | APPLY_TRANSLATE);
  762. }
  763. }
  764. } else {
  765. if (m00 == 0.0 && m11 == 0.0) {
  766. if (m02 == 0.0 && m12 == 0.0) {
  767. state = APPLY_SHEAR;
  768. } else {
  769. state = (APPLY_SHEAR | APPLY_TRANSLATE);
  770. }
  771. } else {
  772. if (m02 == 0.0 && m12 == 0.0) {
  773. state = (APPLY_SHEAR | APPLY_SCALE);
  774. } else {
  775. state = (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE);
  776. }
  777. }
  778. }
  779. }
  780. /*
  781. * Convenience method used internally to throw exceptions when
  782. * a case was forgotten in a switch statement.
  783. */
  784. private void stateError() {
  785. throw new InternalError("missing case in transform state switch");
  786. }
  787. /**
  788. * Retrieves the 6 specifiable values in the 3x3 affine transformation
  789. * matrix and places them into an array of double precisions values.
  790. * The values are stored in the array as
  791. * { m00 m10 m01 m11 m02 m12 }.
  792. * An array of 4 doubles can also be specified, in which case only the
  793. * first four elements representing the non-transform
  794. * parts of the array are retrieved and the values are stored into
  795. * the array as { m00 m10 m01 m11 }
  796. * @param flatmatrix the double array used to store the returned
  797. * values.
  798. * @see #getScaleX
  799. * @see #getScaleY
  800. * @see #getShearX
  801. * @see #getShearY
  802. * @see #getTranslateX
  803. * @see #getTranslateY
  804. */
  805. public void getMatrix(double[] flatmatrix) {
  806. flatmatrix[0] = m00;
  807. flatmatrix[1] = m10;
  808. flatmatrix[2] = m01;
  809. flatmatrix[3] = m11;
  810. if (flatmatrix.length > 5) {
  811. flatmatrix[4] = m02;
  812. flatmatrix[5] = m12;
  813. }
  814. }
  815. /**
  816. * Returns the X coordinate scaling element (m00) of the 3x3
  817. * affine transformation matrix.
  818. * @return a double value that is the X coordinate of the scaling
  819. * element of the affine transformation matrix.
  820. * @see #getMatrix
  821. */
  822. public double getScaleX() {
  823. return m00;
  824. }
  825. /**
  826. * Returns the Y coordinate scaling element (m11) of the 3x3
  827. * affine transformation matrix.
  828. * @return a double value that is the Y coordinate of the scaling
  829. * element of the affine transformation matrix.
  830. * @see #getMatrix
  831. */
  832. public double getScaleY() {
  833. return m11;
  834. }
  835. /**
  836. * Returns the X coordinate shearing element (m01) of the 3x3
  837. * affine transformation matrix.
  838. * @return a double value that is the X coordinate of the shearing
  839. * element of the affine transformation matrix.
  840. * @see #getMatrix
  841. */
  842. public double getShearX() {
  843. return m01;
  844. }
  845. /**
  846. * Returns the Y coordinate shearing element (m10) of the 3x3
  847. * affine transformation matrix.
  848. * @return a double value that is the Y coordinate of the shearing
  849. * element of the affine transformation matrix.
  850. * @see #getMatrix
  851. */
  852. public double getShearY() {
  853. return m10;
  854. }
  855. /**
  856. * Returns the X coordinate of the translation element (m02) of the
  857. * 3x3 affine transformation matrix.
  858. * @return a double value that is the X coordinate of the translation
  859. * element of the affine transformation matrix.
  860. * @see #getMatrix
  861. */
  862. public double getTranslateX() {
  863. return m02;
  864. }
  865. /**
  866. * Returns the Y coordinate of the translation element (m12) of the
  867. * 3x3 affine transformation matrix.
  868. * @return a double value that is the Y coordinate of the translation
  869. * element of the affine transformation matrix.
  870. * @see #getMatrix
  871. */
  872. public double getTranslateY() {
  873. return m12;
  874. }
  875. /**
  876. * Concatenates this transform with a translation transformation.
  877. * This is equivalent to calling concatenate(T), where T is an
  878. * <code>AffineTransform</code> represented by the following matrix:
  879. * <pre>
  880. * [ 1 0 tx ]
  881. * [ 0 1 ty ]
  882. * [ 0 0 1 ]
  883. * </pre>
  884. * @param tx the distance by which coordinates are translated in the
  885. * X axis direction
  886. * @param ty the distance by which coordinates are translated in the
  887. * Y axis direction
  888. */
  889. public void translate(double tx, double ty) {
  890. switch (state) {
  891. default:
  892. stateError();
  893. /* NOTREACHED */
  894. case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  895. m02 = tx * m00 + ty * m01 + m02;
  896. m12 = tx * m10 + ty * m11 + m12;
  897. return;
  898. case (APPLY_SHEAR | APPLY_SCALE):
  899. m02 = tx * m00 + ty * m01;
  900. m12 = tx * m10 + ty * m11;
  901. state = APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE;
  902. return;
  903. case (APPLY_SHEAR | APPLY_TRANSLATE):
  904. m02 = ty * m01 + m02;
  905. m12 = tx * m10 + m12;
  906. return;
  907. case (APPLY_SHEAR):
  908. m02 = ty * m01;
  909. m12 = tx * m10;
  910. state = APPLY_SHEAR | APPLY_TRANSLATE;
  911. return;
  912. case (APPLY_SCALE | APPLY_TRANSLATE):
  913. m02 = tx * m00 + m02;
  914. m12 = ty * m11 + m12;
  915. return;
  916. case (APPLY_SCALE):
  917. m02 = tx * m00;
  918. m12 = ty * m11;
  919. state = APPLY_SCALE | APPLY_TRANSLATE;
  920. return;
  921. case (APPLY_TRANSLATE):
  922. m02 = tx + m02;
  923. m12 = ty + m12;
  924. return;
  925. case (APPLY_IDENTITY):
  926. m02 = tx;
  927. m12 = ty;
  928. state = APPLY_TRANSLATE;
  929. return;
  930. }
  931. }
  932. /**
  933. * Concatenates this transform with a rotation transformation.
  934. * This is equivalent to calling concatenate(R), where R is an
  935. * <code>AffineTransform</code> represented by the following matrix:
  936. * <pre>
  937. * [ cos(theta) -sin(theta) 0 ]
  938. * [ sin(theta) cos(theta) 0 ]
  939. * [ 0 0 1 ]
  940. * </pre>
  941. * Rotating with a positive angle theta rotates points on the positive
  942. * x axis toward the positive y axis.
  943. * @param theta the angle of rotation in radians
  944. */
  945. public void rotate(double theta) {
  946. double sin = Math.sin(theta);
  947. double cos = Math.cos(theta);
  948. if (Math.abs(sin) < 1E-15) {
  949. if (cos < 0.0) {
  950. m00 = -m00;
  951. m11 = -m11;
  952. int state = this.state;
  953. if ((state & (APPLY_SHEAR)) != 0) {
  954. // If there was a shear, then this rotation has no
  955. // effect on the state.
  956. m01 = -m01;
  957. m10 = -m10;
  958. } else {
  959. // No shear means the SCALE state may toggle when
  960. // m00 and m11 are negated.
  961. if (m00 == 1.0 && m11 == 1.0) {
  962. this.state = state & ~APPLY_SCALE;
  963. } else {
  964. this.state = state | APPLY_SCALE;
  965. }
  966. }
  967. }
  968. return;
  969. }
  970. if (Math.abs(cos) < 1E-15) {
  971. if (sin < 0.0) {
  972. double M0 = m00;
  973. m00 = -m01;
  974. m01 = M0;
  975. M0 = m10;
  976. m10 = -m11;
  977. m11 = M0;
  978. } else {
  979. double M0 = m00;
  980. m00 = m01;
  981. m01 = -M0;
  982. M0 = m10;
  983. m10 = m11;
  984. m11 = -M0;
  985. }
  986. state = rot90conversion[state];
  987. return;
  988. }
  989. double M0, M1;
  990. M0 = m00;
  991. M1 = m01;
  992. m00 = cos * M0 + sin * M1;
  993. m01 = -sin * M0 + cos * M1;
  994. M0 = m10;
  995. M1 = m11;
  996. m10 = cos * M0 + sin * M1;
  997. m11 = -sin * M0 + cos * M1;
  998. updateState();
  999. }
  1000. private static int rot90conversion[] = {
  1001. APPLY_SHEAR, APPLY_SHEAR | APPLY_TRANSLATE,
  1002. APPLY_SHEAR, APPLY_SHEAR | APPLY_TRANSLATE,
  1003. APPLY_SCALE, APPLY_SCALE | APPLY_TRANSLATE,
  1004. APPLY_SHEAR | APPLY_SCALE,
  1005. APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE,
  1006. };
  1007. /**
  1008. * Concatenates this transform with a transform that rotates
  1009. * coordinates around an anchor point.
  1010. * This operation is equivalent to translating the coordinates so
  1011. * that the anchor point is at the origin (S1), then rotating them
  1012. * about the new origin (S2), and finally translating so that the
  1013. * intermediate origin is restored to the coordinates of the original
  1014. * anchor point (S3).
  1015. * <p>
  1016. * This operation is equivalent to the following sequence of calls:
  1017. * <pre>
  1018. * translate(x, y); // S3: final translation
  1019. * rotate(theta); // S2: rotate around anchor
  1020. * translate(-x, -y); // S1: translate anchor to origin
  1021. * </pre>
  1022. * Rotating with a positive angle theta rotates points on the positive
  1023. * x axis toward the positive y axis.
  1024. * @param theta the angle of rotation in radians
  1025. * @param x, y the coordinates of the anchor point of the
  1026. * rotation
  1027. */
  1028. public void rotate(double theta, double x, double y) {
  1029. // REMIND: Simple for now - optimize later
  1030. translate(x, y);
  1031. rotate(theta);
  1032. translate(-x, -y);
  1033. }
  1034. /**
  1035. * Concatenates this transform with a scaling transformation.
  1036. * This is equivalent to calling concatenate(S), where S is an
  1037. * <code>AffineTransform</code> represented by the following matrix:
  1038. * <pre>
  1039. * [ sx 0 0 ]
  1040. * [ 0 sy 0 ]
  1041. * [ 0 0 1 ]
  1042. * </pre>
  1043. * @param sx the factor by which coordinates are scaled along the
  1044. * X axis direction
  1045. * @param sy the factor by which coordinates are scaled along the
  1046. * Y axis direction
  1047. */
  1048. public void scale(double sx, double sy) {
  1049. int state = this.state;
  1050. switch (state) {
  1051. default:
  1052. stateError();
  1053. /* NOTREACHED */
  1054. case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  1055. case (APPLY_SHEAR | APPLY_SCALE):
  1056. m00 *= sx;
  1057. m11 *= sy;
  1058. /* NOBREAK */
  1059. case (APPLY_SHEAR | APPLY_TRANSLATE):
  1060. case (APPLY_SHEAR):
  1061. m01 *= sy;
  1062. m10 *= sx;
  1063. return;
  1064. case (APPLY_SCALE | APPLY_TRANSLATE):
  1065. case (APPLY_SCALE):
  1066. m00 *= sx;
  1067. m11 *= sy;
  1068. return;
  1069. case (APPLY_TRANSLATE):
  1070. case (APPLY_IDENTITY):
  1071. m00 = sx;
  1072. m11 = sy;
  1073. this.state = state | APPLY_SCALE;
  1074. return;
  1075. }
  1076. }
  1077. /**
  1078. * Concatenates this transform with a shearing transformation.
  1079. * This is equivalent to calling concatenate(SH), where SH is an
  1080. * <code>AffineTransform</code> represented by the following matrix:
  1081. * <pre>
  1082. * [ 1 shx 0 ]
  1083. * [ shy 1 0 ]
  1084. * [ 0 0 1 ]
  1085. * </pre>
  1086. * @param shx the multiplier by which coordinates are shifted in the
  1087. * direction of the positive X axis as a factor of their Y coordinate
  1088. * @param shy the multiplier by which coordinates are shifted in the
  1089. * direction of the positive Y axis as a factor of their X coordinate
  1090. */
  1091. public void shear(double shx, double shy) {
  1092. int state = this.state;
  1093. switch (state) {
  1094. default:
  1095. stateError();
  1096. /* NOTREACHED */
  1097. case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  1098. case (APPLY_SHEAR | APPLY_SCALE):
  1099. double M0, M1;
  1100. M0 = m00;
  1101. M1 = m01;
  1102. m00 = M0 + M1 * shy;
  1103. m01 = M0 * shx + M1;
  1104. M0 = m10;
  1105. M1 = m11;
  1106. m10 = M0 + M1 * shy;
  1107. m11 = M0 * shx + M1;
  1108. return;
  1109. case (APPLY_SHEAR | APPLY_TRANSLATE):
  1110. case (APPLY_SHEAR):
  1111. m00 = m01 * shy;
  1112. m11 = m10 * shx;
  1113. this.state = state | APPLY_SCALE;
  1114. return;
  1115. case (APPLY_SCALE | APPLY_TRANSLATE):
  1116. case (APPLY_SCALE):
  1117. m01 = m00 * shx;
  1118. m10 = m11 * shy;
  1119. this.state = state | APPLY_SHEAR;
  1120. return;
  1121. case (APPLY_TRANSLATE):
  1122. case (APPLY_IDENTITY):
  1123. m01 = shx;
  1124. m10 = shy;
  1125. this.state = state | APPLY_SCALE | APPLY_SHEAR;
  1126. return;
  1127. }
  1128. }
  1129. /**
  1130. * Resets this transform to the Identity transform.
  1131. */
  1132. public void setToIdentity() {
  1133. m00 = m11 = 1.0;
  1134. m10 = m01 = m02 = m12 = 0.0;
  1135. state = APPLY_IDENTITY;
  1136. }
  1137. /**
  1138. * Sets this transform to a translation transformation.
  1139. * The matrix representing this transform becomes:
  1140. * <pre>
  1141. * [ 1 0 tx ]
  1142. * [ 0 1 ty ]
  1143. * [ 0 0 1 ]
  1144. * </pre>
  1145. * @param tx the distance by which coordinates are translated in the
  1146. * X axis direction
  1147. * @param ty the distance by which coordinates are translated in the
  1148. * Y axis direction
  1149. */
  1150. public void setToTranslation(double tx, double ty) {
  1151. m00 = 1.0;
  1152. m10 = 0.0;
  1153. m01 = 0.0;
  1154. m11 = 1.0;
  1155. m02 = tx;
  1156. m12 = ty;
  1157. state = APPLY_TRANSLATE;
  1158. }
  1159. /**
  1160. * Sets this transform to a rotation transformation.
  1161. * The matrix representing this transform becomes:
  1162. * <pre>
  1163. * [ cos(theta) -sin(theta) 0 ]
  1164. * [ sin(theta) cos(theta) 0 ]
  1165. * [ 0 0 1 ]
  1166. * </pre>
  1167. * Rotating with a positive angle theta rotates points on the positive
  1168. * x axis toward the positive y axis.
  1169. * @param theta the angle of rotation in radians
  1170. */
  1171. public void setToRotation(double theta) {
  1172. m02 = 0.0;
  1173. m12 = 0.0;
  1174. double sin = Math.sin(theta);
  1175. double cos = Math.cos(theta);
  1176. if (Math.abs(sin) < 1E-15) {
  1177. m01 = m10 = 0.0;
  1178. if (cos < 0) {
  1179. m00 = m11 = -1.0;
  1180. state = APPLY_SCALE;
  1181. } else {
  1182. m00 = m11 = 1.0;
  1183. state = APPLY_IDENTITY;
  1184. }
  1185. return;
  1186. }
  1187. if (Math.abs(cos) < 1E-15) {
  1188. m00 = m11 = 0.0;
  1189. if (sin < 0.0) {
  1190. m01 = 1.0;
  1191. m10 = -1.0;
  1192. } else {
  1193. m01 = -1.0;
  1194. m10 = 1.0;
  1195. }
  1196. state = APPLY_SHEAR;
  1197. return;
  1198. }
  1199. m00 = cos;
  1200. m01 = -sin;
  1201. m10 = sin;
  1202. m11 = cos;
  1203. state = APPLY_SHEAR | APPLY_SCALE;
  1204. return;
  1205. }
  1206. /**
  1207. * Sets this transform to a translated rotation transformation.
  1208. * This operation is equivalent to translating the coordinates so
  1209. * that the anchor point is at the origin (S1), then rotating them
  1210. * about the new origin (S2), and finally translating so that the
  1211. * intermediate origin is restored to the coordinates of the original
  1212. * anchor point (S3).
  1213. * <p>
  1214. * This operation is equivalent to the following sequence of calls:
  1215. * <pre>
  1216. * setToTranslation(x, y); // S3: final translation
  1217. * rotate(theta); // S2: rotate around anchor
  1218. * translate(-x, -y); // S1: translate anchor to origin
  1219. * </pre>
  1220. * The matrix representing this transform becomes:
  1221. * <pre>
  1222. * [ cos(theta) -sin(theta) x-x*cos+y*sin ]
  1223. * [ sin(theta) cos(theta) y-x*sin-y*cos ]
  1224. * [ 0 0 1 ]
  1225. * </pre>
  1226. * Rotating with a positive angle theta rotates points on the positive
  1227. * x axis toward the positive y axis.
  1228. * @param theta the angle of rotation in radians
  1229. * @param x, y the coordinates of the anchor point of the
  1230. * rotation
  1231. */
  1232. public void setToRotation(double theta, double x, double y) {
  1233. setToRotation(theta);
  1234. double sin = m10;
  1235. double oneMinusCos = 1.0 - m00;
  1236. m02 = x * oneMinusCos + y * sin;
  1237. m12 = y * oneMinusCos - x * sin;
  1238. state |= APPLY_TRANSLATE;
  1239. return;
  1240. }
  1241. /**
  1242. * Sets this transform to a scaling transformation.
  1243. * The matrix representing this transform becomes:
  1244. * <pre>
  1245. * [ sx 0 0 ]
  1246. * [ 0 sy 0 ]
  1247. * [ 0 0 1 ]
  1248. * </pre>
  1249. * @param sx the factor by which coordinates are scaled along the
  1250. * X axis direction
  1251. * @param sy the factor by which coordinates are scaled along the
  1252. * Y axis direction
  1253. */
  1254. public void setToScale(double sx, double sy) {
  1255. m00 = sx;
  1256. m10 = 0.0;
  1257. m01 = 0.0;
  1258. m11 = sy;
  1259. m02 = 0.0;
  1260. m12 = 0.0;
  1261. state = APPLY_SCALE;
  1262. }
  1263. /**
  1264. * Sets this transform to a shearing transformation.
  1265. * The matrix representing this transform becomes:
  1266. * <pre>
  1267. * [ 1 shx 0 ]
  1268. * [ shy 1 0 ]
  1269. * [ 0 0 1 ]
  1270. * </pre>
  1271. * @param shx the multiplier by which coordinates are shifted in the
  1272. * direction of the positive X axis as a factor of their Y coordinate
  1273. * @param shy the multiplier by which coordinates are shifted in the
  1274. * direction of the positive Y axis as a factor of their X coordinate
  1275. */
  1276. public void setToShear(double shx, double shy) {
  1277. m00 = 1.0;
  1278. m01 = shx;
  1279. m10 = shy;
  1280. m11 = 1.0;
  1281. m02 = 0.0;
  1282. m12 = 0.0;
  1283. state = APPLY_SHEAR | APPLY_SCALE;
  1284. }
  1285. /**
  1286. * Sets this transform to a copy of the transform in the specified
  1287. * <code>AffineTransform</code> object.
  1288. * @param Tx the <code>AffineTransform</code> object from which to
  1289. * copy the transform
  1290. */
  1291. public void setTransform(AffineTransform Tx) {
  1292. this.m00 = Tx.m00;
  1293. this.m10 = Tx.m10;
  1294. this.m01 = Tx.m01;
  1295. this.m11 = Tx.m11;
  1296. this.m02 = Tx.m02;
  1297. this.m12 = Tx.m12;
  1298. this.state = Tx.state;
  1299. }
  1300. /**
  1301. * Sets this transform to the matrix specified by the 6
  1302. * double precision values.
  1303. * @param m00, m01, m02, m10, m11, m12 the
  1304. * 6 floating point values that compose the 3x3 transformation matrix
  1305. */
  1306. public void setTransform(double m00, double m10,
  1307. double m01, double m11,
  1308. double m02, double m12) {
  1309. this.m00 = m00;
  1310. this.m10 = m10;
  1311. this.m01 = m01;
  1312. this.m11 = m11;
  1313. this.m02 = m02;
  1314. this.m12 = m12;
  1315. updateState();
  1316. }
  1317. /**
  1318. * Concatenates an <code>AffineTransform</code> <code>Tx</code> to
  1319. * this <code>AffineTransform</code> Cx in the most commonly useful
  1320. * way to provide a new user space
  1321. * that is mapped to the former user space by <code>Tx</code>.
  1322. * Cx is updated to perform the combined transformation.
  1323. * Transforming a point p by the updated transform Cx' is
  1324. * equivalent to first transforming p by <code>Tx</code> and then
  1325. * transforming the result by the original transform Cx like this:
  1326. * Cx'(p) = Cx(Tx(p))
  1327. * In matrix notation, if this transform Cx is
  1328. * represented by the matrix [this] and <code>Tx</code> is represented
  1329. * by the matrix [Tx] then this method does the following:
  1330. * <pre>
  1331. * [this] = [this] x [Tx]
  1332. * </pre>
  1333. * @param Tx the <code>AffineTransform</code> object to be
  1334. * concatenated with this <code>AffineTransform</code> object.
  1335. * @see #preConcatenate
  1336. */
  1337. public void concatenate(AffineTransform Tx) {
  1338. double M0, M1;
  1339. double T00, T01, T10, T11;
  1340. double T02, T12;
  1341. int mystate = state;
  1342. int txstate = Tx.state;
  1343. switch ((txstate << HI_SHIFT) | mystate) {
  1344. /* ---------- Tx == IDENTITY cases ---------- */
  1345. case (HI_IDENTITY | APPLY_IDENTITY):
  1346. case (HI_IDENTITY | APPLY_TRANSLATE):
  1347. case (HI_IDENTITY | APPLY_SCALE):
  1348. case (HI_IDENTITY | APPLY_SCALE | APPLY_TRANSLATE):
  1349. case (HI_IDENTITY | APPLY_SHEAR):
  1350. case (HI_IDENTITY | APPLY_SHEAR | APPLY_TRANSLATE):
  1351. case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE):
  1352. case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  1353. return;
  1354. /* ---------- this == IDENTITY cases ---------- */
  1355. case (HI_SHEAR | HI_SCALE | HI_TRANSLATE | APPLY_IDENTITY):
  1356. m01 = Tx.m01;
  1357. m10 = Tx.m10;
  1358. /* NOBREAK */
  1359. case (HI_SCALE | HI_TRANSLATE | APPLY_IDENTITY):
  1360. m00 = Tx.m00;
  1361. m11 = Tx.m11;
  1362. /* NOBREAK */
  1363. case (HI_TRANSLATE | APPLY_IDENTITY):
  1364. m02 = Tx.m02;
  1365. m12 = Tx.m12;
  1366. state = txstate;
  1367. return;
  1368. case (HI_SHEAR | HI_SCALE | APPLY_IDENTITY):
  1369. m01 = Tx.m01;
  1370. m10 = Tx.m10;
  1371. /* NOBREAK */
  1372. case (HI_SCALE | APPLY_IDENTITY):
  1373. m00 = Tx.m00;
  1374. m11 = Tx.m11;
  1375. state = txstate;
  1376. return;
  1377. case (HI_SHEAR | HI_TRANSLATE | APPLY_IDENTITY):
  1378. m02 = Tx.m02;
  1379. m12 = Tx.m12;
  1380. /* NOBREAK */
  1381. case (HI_SHEAR | APPLY_IDENTITY):
  1382. m01 = Tx.m01;
  1383. m10 = Tx.m10;
  1384. m00 = m11 = 0.0;
  1385. state = txstate;
  1386. return;
  1387. /* ---------- Tx == TRANSLATE cases ---------- */
  1388. case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  1389. T02 = Tx.m02;
  1390. T12 = Tx.m12;
  1391. m02 = T02 * m00 + T12 * m01 + m02;
  1392. m12 = T02 * m10 + T12 * m11 + m12;
  1393. return;
  1394. case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE):
  1395. T02 = Tx.m02;
  1396. T12 = Tx.m12;
  1397. m02 = T02 * m00 + T12 * m01;
  1398. m12 = T02 * m10 + T12 * m11;
  1399. state = APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE;
  1400. return;
  1401. case (HI_TRANSLATE | APPLY_SHEAR | APPLY_TRANSLATE):
  1402. m02 = Tx.m12 * m01 + m02;
  1403. m12 = Tx.m02 * m10 + m12;
  1404. return;
  1405. case (HI_TRANSLATE | APPLY_SHEAR):
  1406. m02 = Tx.m12 * m01;
  1407. m12 = Tx.m02 * m10;
  1408. state = APPLY_SHEAR | APPLY_TRANSLATE;
  1409. return;
  1410. case (HI_TRANSLATE | APPLY_SCALE | APPLY_TRANSLATE):
  1411. m02 = Tx.m02 * m00 + m02;
  1412. m12 = Tx.m12 * m11 + m12;
  1413. return;
  1414. case (HI_TRANSLATE | APPLY_SCALE):
  1415. m02 = Tx.m02 * m00;
  1416. m12 = Tx.m12 * m11;
  1417. state = APPLY_SCALE | APPLY_TRANSLATE;
  1418. return;
  1419. case (HI_TRANSLATE | APPLY_TRANSLATE):
  1420. m02 = Tx.m02 + m02;
  1421. m12 = Tx.m12 + m12;
  1422. return;
  1423. /* ---------- Tx == SCALE cases ---------- */
  1424. case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  1425. case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE):
  1426. T00 = Tx.m00; T11 = Tx.m11;
  1427. m00 *= T00;
  1428. m11 *= T11;
  1429. m01 *= T11;
  1430. m10 *= T00;
  1431. return;
  1432. case (HI_SCALE | APPLY_SHEAR | APPLY_TRANSLATE):
  1433. case (HI_SCALE | APPLY_SHEAR):
  1434. m01 *= Tx.m11;
  1435. m10 *= Tx.m00;
  1436. return;
  1437. case (HI_SCALE | APPLY_SCALE | APPLY_TRANSLATE):
  1438. case (HI_SCALE | APPLY_SCALE):
  1439. m00 *= Tx.m00;
  1440. m11 *= Tx.m11;
  1441. return;
  1442. case (HI_SCALE | APPLY_TRANSLATE):
  1443. m00 = Tx.m00;
  1444. m11 = Tx.m11;
  1445. state = APPLY_SCALE | APPLY_TRANSLATE;
  1446. return;
  1447. /* ---------- Tx == SHEAR cases ---------- */
  1448. case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  1449. case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE):
  1450. T01 = Tx.m01; T10 = Tx.m10;
  1451. M0 = m00;
  1452. m00 = m01 * T10;
  1453. m01 = M0 * T01;
  1454. M0 = m10;
  1455. m10 = m11 * T10;
  1456. m11 = M0 * T01;
  1457. return;
  1458. case (HI_SHEAR | APPLY_SHEAR | APPLY_TRANSLATE):
  1459. case (HI_SHEAR | APPLY_SHEAR):
  1460. m00 = m01 * Tx.m10;
  1461. m01 = 0.0;
  1462. m11 = m10 * Tx.m01;
  1463. m10 = 0.0;
  1464. state = mystate ^ (APPLY_SHEAR | APPLY_SCALE);
  1465. return;
  1466. case (HI_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  1467. case (HI_SHEAR | APPLY_SCALE):
  1468. m01 = m00 * Tx.m01;
  1469. m00 = 0.0;
  1470. m10 = m11 * Tx.m10;
  1471. m11 = 0.0;
  1472. state = mystate ^ (APPLY_SHEAR | APPLY_SCALE);
  1473. return;
  1474. case (HI_SHEAR | APPLY_TRANSLATE):
  1475. m00 = 0.0;
  1476. m01 = Tx.m01;
  1477. m10 = Tx.m10;
  1478. m11 = 0.0;
  1479. state = APPLY_TRANSLATE | APPLY_SHEAR;
  1480. return;
  1481. }
  1482. // If Tx has more than one attribute, it is not worth optimizing
  1483. // all of those cases...
  1484. T00 = Tx.m00; T01 = Tx.m01; T02 = Tx.m02;
  1485. T10 = Tx.m10; T11 = Tx.m11; T12 = Tx.m12;
  1486. switch (mystate) {
  1487. default:
  1488. stateError();
  1489. /* NOTREACHED */
  1490. case (APPLY_SHEAR | APPLY_SCALE):
  1491. state = mystate | txstate;
  1492. case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  1493. M0 = m00;
  1494. M1 = m01;
  1495. m00 = T00 * M0 + T10 * M1;
  1496. m01 = T01 * M0 + T11 * M1;
  1497. m02 += T02 * M0 + T12 * M1;
  1498. M0 = m10;
  1499. M1 = m11;
  1500. m10 = T00 * M0 + T10 * M1;
  1501. m11 = T01 * M0 + T11 * M1;
  1502. m12 += T02 * M0 + T12 * M1;
  1503. return;
  1504. case (APPLY_SHEAR | APPLY_TRANSLATE):
  1505. case (APPLY_SHEAR):
  1506. M0 = m01;
  1507. m00 = T10 * M0;
  1508. m01 = T11 * M0;
  1509. m02 += T12 * M0;
  1510. M0 = m10;
  1511. m10 = T00 * M0;
  1512. m11 = T01 * M0;
  1513. m12 += T02 * M0;
  1514. break;
  1515. case (APPLY_SCALE | APPLY_TRANSLATE):
  1516. case (APPLY_SCALE):
  1517. M0 = m00;
  1518. m00 = T00 * M0;
  1519. m01 = T01 * M0;
  1520. m02 += T02 * M0;
  1521. M0 = m11;
  1522. m10 = T10 * M0;
  1523. m11 = T11 * M0;
  1524. m12 += T12 * M0;
  1525. break;
  1526. case (APPLY_TRANSLATE):
  1527. m00 = T00;
  1528. m01 = T01;
  1529. m02 += T02;
  1530. m10 = T10;
  1531. m11 = T11;
  1532. m12 += T12;
  1533. state = txstate | APPLY_TRANSLATE;
  1534. return;
  1535. }
  1536. updateState();
  1537. }
  1538. /**
  1539. * Concatenates an <code>AffineTransform</code> <code>Tx</code> to
  1540. * this <code>AffineTransform</code> Cx
  1541. * in a less commonly used way such that <code>Tx</code> modifies the
  1542. * coordinate transformation relative to the absolute pixel
  1543. * space rather than relative to the existing user space.
  1544. * Cx is updated to perform the combined transformation.
  1545. * Transforming a point p by the updated transform Cx' is
  1546. * equivalent to first transforming p by the original transform
  1547. * Cx and then transforming the result by
  1548. * <code>Tx</code> like this:
  1549. * Cx'(p) = Tx(Cx(p))
  1550. * In matrix notation, if this transform Cx
  1551. * is represented by the matrix [this] and <code>Tx</code> is
  1552. * represented by the matrix [Tx] then this method does the
  1553. * following:
  1554. * <pre>
  1555. * [this] = [Tx] x [this]
  1556. * </pre>
  1557. * @param Tx the <code>AffineTransform</code> object to be
  1558. * concatenated with this <code>AffineTransform</code> object.
  1559. * @see #concatenate
  1560. */
  1561. public void preConcatenate(AffineTransform Tx) {
  1562. double M0, M1;
  1563. double T00, T01, T10, T11;
  1564. double T02, T12;
  1565. int mystate = state;
  1566. int txstate = Tx.state;
  1567. switch ((txstate << HI_SHIFT) | mystate) {
  1568. case (HI_IDENTITY | APPLY_IDENTITY):
  1569. case (HI_IDENTITY | APPLY_TRANSLATE):
  1570. case (HI_IDENTITY | APPLY_SCALE):
  1571. case (HI_IDENTITY | APPLY_SCALE | APPLY_TRANSLATE):
  1572. case (HI_IDENTITY | APPLY_SHEAR):
  1573. case (HI_IDENTITY | APPLY_SHEAR | APPLY_TRANSLATE):
  1574. case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE):
  1575. case (HI_IDENTITY | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  1576. // Tx is IDENTITY...
  1577. return;
  1578. case (HI_TRANSLATE | APPLY_IDENTITY):
  1579. case (HI_TRANSLATE | APPLY_SCALE):
  1580. case (HI_TRANSLATE | APPLY_SHEAR):
  1581. case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE):
  1582. // Tx is TRANSLATE, this has no TRANSLATE
  1583. m02 = Tx.m02;
  1584. m12 = Tx.m12;
  1585. state = mystate | APPLY_TRANSLATE;
  1586. return;
  1587. case (HI_TRANSLATE | APPLY_TRANSLATE):
  1588. case (HI_TRANSLATE | APPLY_SCALE | APPLY_TRANSLATE):
  1589. case (HI_TRANSLATE | APPLY_SHEAR | APPLY_TRANSLATE):
  1590. case (HI_TRANSLATE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  1591. // Tx is TRANSLATE, this has one too
  1592. m02 = m02 + Tx.m02;
  1593. m12 = m12 + Tx.m12;
  1594. return;
  1595. case (HI_SCALE | APPLY_TRANSLATE):
  1596. case (HI_SCALE | APPLY_IDENTITY):
  1597. // Only these two existing states need a new state
  1598. state = mystate | APPLY_SCALE;
  1599. /* NOBREAK */
  1600. case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  1601. case (HI_SCALE | APPLY_SHEAR | APPLY_SCALE):
  1602. case (HI_SCALE | APPLY_SHEAR | APPLY_TRANSLATE):
  1603. case (HI_SCALE | APPLY_SHEAR):
  1604. case (HI_SCALE | APPLY_SCALE | APPLY_TRANSLATE):
  1605. case (HI_SCALE | APPLY_SCALE):
  1606. // Tx is SCALE, this is anything
  1607. T00 = Tx.m00;
  1608. T11 = Tx.m11;
  1609. if ((mystate & APPLY_SHEAR) != 0) {
  1610. m01 = m01 * T00;
  1611. m10 = m10 * T11;
  1612. if ((mystate & APPLY_SCALE) != 0) {
  1613. m00 = m00 * T00;
  1614. m11 = m11 * T11;
  1615. }
  1616. } else {
  1617. m00 = m00 * T00;
  1618. m11 = m11 * T11;
  1619. }
  1620. if ((mystate & APPLY_TRANSLATE) != 0) {
  1621. m02 = m02 * T00;
  1622. m12 = m12 * T11;
  1623. }
  1624. return;
  1625. case (HI_SHEAR | APPLY_SHEAR | APPLY_TRANSLATE):
  1626. case (HI_SHEAR | APPLY_SHEAR):
  1627. mystate = mystate | APPLY_SCALE;
  1628. /* NOBREAK */
  1629. case (HI_SHEAR | APPLY_TRANSLATE):
  1630. case (HI_SHEAR | APPLY_IDENTITY):
  1631. case (HI_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  1632. case (HI_SHEAR | APPLY_SCALE):
  1633. state = mystate ^ APPLY_SHEAR;
  1634. /* NOBREAK */
  1635. case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  1636. case (HI_SHEAR | APPLY_SHEAR | APPLY_SCALE):
  1637. // Tx is SHEAR, this is anything
  1638. T01 = Tx.m01;
  1639. T10 = Tx.m10;
  1640. M0 = m00;
  1641. m00 = m10 * T01;
  1642. m10 = M0 * T10;
  1643. M0 = m01;
  1644. m01 = m11 * T01;
  1645. m11 = M0 * T10;
  1646. M0 = m02;
  1647. m02 = m12 * T01;
  1648. m12 = M0 * T10;
  1649. return;
  1650. }
  1651. // If Tx has more than one attribute, it is not worth optimizing
  1652. // all of those cases...
  1653. T00 = Tx.m00; T01 = Tx.m01; T02 = Tx.m02;
  1654. T10 = Tx.m10; T11 = Tx.m11; T12 = Tx.m12;
  1655. switch (mystate) {
  1656. default:
  1657. stateError();
  1658. /* NOTREACHED */
  1659. case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  1660. M0 = m02;
  1661. M1 = m12;
  1662. T02 += M0 * T00 + M1 * T01;
  1663. T12 += M0 * T10 + M1 * T11;
  1664. /* NOBREAK */
  1665. case (APPLY_SHEAR | APPLY_SCALE):
  1666. m02 = T02;
  1667. m12 = T12;
  1668. M0 = m00;
  1669. M1 = m10;
  1670. m00 = M0 * T00 + M1 * T01;
  1671. m10 = M0 * T10 + M1 * T11;
  1672. M0 = m01;
  1673. M1 = m11;
  1674. m01 = M0 * T00 + M1 * T01;
  1675. m11 = M0 * T10 + M1 * T11;
  1676. break;
  1677. case (APPLY_SHEAR | APPLY_TRANSLATE):
  1678. M0 = m02;
  1679. M1 = m12;
  1680. T02 += M0 * T00 + M1 * T01;
  1681. T12 += M0 * T10 + M1 * T11;
  1682. /* NOBREAK */
  1683. case (APPLY_SHEAR):
  1684. m02 = T02;
  1685. m12 = T12;
  1686. M0 = m10;
  1687. m00 = M0 * T01;
  1688. m10 = M0 * T11;
  1689. M0 = m01;
  1690. m01 = M0 * T00;
  1691. m11 = M0 * T10;
  1692. break;
  1693. case (APPLY_SCALE | APPLY_TRANSLATE):
  1694. M0 = m02;
  1695. M1 = m12;
  1696. T02 += M0 * T00 + M1 * T01;
  1697. T12 += M0 * T10 + M1 * T11;
  1698. /* NOBREAK */
  1699. case (APPLY_SCALE):
  1700. m02 = T02;
  1701. m12 = T12;
  1702. M0 = m00;
  1703. m00 = M0 * T00;
  1704. m10 = M0 * T10;
  1705. M0 = m11;
  1706. m01 = M0 * T01;
  1707. m11 = M0 * T11;
  1708. break;
  1709. case (APPLY_TRANSLATE):
  1710. M0 = m02;
  1711. M1 = m12;
  1712. T02 += M0 * T00 + M1 * T01;
  1713. T12 += M0 * T10 + M1 * T11;
  1714. /* NOBREAK */
  1715. case (APPLY_IDENTITY):
  1716. m02 = T02;
  1717. m12 = T12;
  1718. m00 = T00;
  1719. m10 = T10;
  1720. m01 = T01;
  1721. m11 = T11;
  1722. state = mystate | txstate;
  1723. return;
  1724. }
  1725. updateState();
  1726. }
  1727. /**
  1728. * Returns an <code>AffineTransform</code> object representing the
  1729. * inverse transformation.
  1730. * The inverse transform Tx' of this transform Tx
  1731. * maps coordinates transformed by Tx back
  1732. * to their original coordinates.
  1733. * In other words, Tx'(Tx(p)) = p = Tx(Tx'(p)).
  1734. * <p>
  1735. * If this transform maps all coordinates onto a point or a line
  1736. * then it will not have an inverse, since coordinates that do
  1737. * not lie on the destination point or line will not have an inverse
  1738. * mapping.
  1739. * The <code>getDeterminant</code> method can be used to determine if this
  1740. * transform has no inverse, in which case an exception will be
  1741. * thrown if the <code>createInverse</code> method is called.
  1742. * @return a new <code>AffineTransform</code> object representing the
  1743. * inverse transformation.
  1744. * @see #getDeterminant
  1745. * @exception NoninvertibleTransformException
  1746. * if the matrix cannot be inverted.
  1747. */
  1748. public AffineTransform createInverse()
  1749. throws NoninvertibleTransformException
  1750. {
  1751. double det;
  1752. switch (state) {
  1753. default:
  1754. stateError();
  1755. /* NOTREACHED */
  1756. case (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE):
  1757. det = m00 * m11 - m01 * m10;
  1758. if (Math.abs(det) <= Double.MIN_VALUE) {
  1759. throw new NoninvertibleTransformException("Determinant is "+
  1760. det);
  1761. }
  1762. return new AffineTransform( m11 / det, -m10 / det,
  1763. -m01 / det, m00 / det,
  1764. (m01 * m12 - m11 * m02) / det,
  1765. (m10 * m02 - m00 * m12) / det,
  1766. (APPLY_SHEAR |
  1767. APPLY_SCALE |
  1768. APPLY_TRANSLATE));
  1769. case (APPLY_SHEAR | APPLY_SCALE):
  1770. det = m00 * m11 - m01 * m10;
  1771. if (Math.abs(det) <= Double.MIN_VALUE) {
  1772. throw new NoninvertibleTransformException("Determinant is "+
  1773. det);
  1774. }
  1775. return new AffineTransform( m11 / det, -m10 / det,
  1776. -m01 / det, m00 / det,
  1777. 0.0, 0.0,
  1778. (APPLY_SHEAR | APPLY_SCALE));
  1779. case (APPLY_SHEAR | APPLY_TRANSLATE):
  1780. if (m01 == 0.0 || m10 == 0.0) {
  1781. throw new NoninvertibleTransformException("Determinant is 0");
  1782. }
  1783. return new AffineTransform( 0.0, 1.0 / m01,
  1784. 1.0 / m10, 0.0,
  1785. -m12 / m10, -m02 / m01,
  1786. (APPLY_SHEAR | APPLY_TRANSLATE));
  1787. case (APPLY_SHEAR):
  1788. if (m01 == 0.0 || m10 == 0.0) {
  1789. throw new NoninvertibleTransformException("Determinant is 0");
  1790. }
  1791. return new AffineTransform(0.0, 1.0 / m01,
  1792. 1.0 / m10, 0.0,
  1793. 0.0, 0.0,
  1794. (APPLY_SHEAR));
  1795. case (APPLY_SCALE | APPLY_TRANSLATE):
  1796. if (m00 == 0.0 || m11 == 0.0) {
  1797. throw new NoninvertibleTransformException("Determinant is 0");
  1798. }
  1799. return new AffineTransform( 1.0 / m00, 0.0,
  1800. 0.0, 1.0 / m11,
  1801. -m02 / m00, -m12 / m11,
  1802. (APPLY_SCALE | APPLY_TRANSLATE));
  1803. case (APPLY_SCALE):
  1804. if (m00 == 0.0 || m11 == 0.0) {
  1805. throw new NoninvertibleTransformException("Determinant is 0");
  1806. }
  1807. return new AffineTransform(1.0 / m00, 0.0,
  1808. 0.0, 1.0 / m11,
  1809. 0.0, 0.0,
  1810. (APPLY_SCALE));
  1811. case (APPLY_TRANSLATE):
  1812. return new AffineTransform( 1.0, 0.0,
  1813. 0.0, 1.0,
  1814. -m02, -m12,
  1815. (APPLY_TRANSLATE));
  1816. case (APPLY_IDENTITY):
  1817. return new AffineTransform();
  1818. }
  1819. /* NOTREACHED */
  1820. }
  1821. /**
  1822. * Transforms the specified <code>ptSrc</code> and stores the result
  1823. * in <code>ptDst</code>.
  1824. * If <code>ptDst</code> is <code>null</code>, a new {@link Point2D}
  1825. * object is allocated and then the result of the transformation is
  1826. * stored in this object.
  1827. * In either case, <code>ptDst</code>, which contains the
  1828. * transformed point, is returned for convenience.
  1829. * If <code>ptSrc</code> and <code>ptDst</code> are the same
  1830. * object, the input point is correctly overwritten with
  1831. * the transformed point.<