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