You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CTM.java 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * $Id$
  3. * Copyright (C) 2001-2002 The Apache Software Foundation. All rights reserved.
  4. * For details on use and redistribution please refer to the
  5. * LICENSE file included with these sources.
  6. */
  7. package org.apache.fop.area;
  8. import java.awt.geom.Rectangle2D;
  9. import java.awt.Rectangle;
  10. import java.io.Serializable;
  11. import org.apache.fop.fo.properties.WritingMode;
  12. /**
  13. * Describe a PDF or PostScript style coordinate transformation matrix (CTM).
  14. * The matrix encodes translations, scaling and rotations of the coordinate
  15. * system used to render pages.
  16. */
  17. public class CTM implements Serializable {
  18. private double a, b, c, d, e, f;
  19. private static CTM s_CTM_lrtb = new CTM(1, 0, 0, 1, 0, 0);
  20. private static CTM s_CTM_rltb = new CTM(-1, 0, 0, 1, 0, 0);
  21. private static CTM s_CTM_tbrl = new CTM(0, 1, -1, 0, 0, 0);
  22. /**
  23. * Create the identity matrix
  24. */
  25. public CTM() {
  26. a = 1;
  27. b = 0;
  28. c = 0;
  29. d = 1;
  30. e = 0;
  31. f = 0;
  32. }
  33. /**
  34. * Initialize a CTM from the passed arguments.
  35. */
  36. public CTM(double a, double b, double c, double d, double e, double f) {
  37. this.a = a;
  38. this.b = b;
  39. this.c = c;
  40. this.d = d;
  41. this.e = e;
  42. this.f = f;
  43. }
  44. /**
  45. * Initialize a CTM to the identity matrix with a translation
  46. * specified by x and y.
  47. */
  48. public CTM(double x, double y) {
  49. this.a = 1;
  50. this.b = 0;
  51. this.c = 0;
  52. this.d = 1;
  53. this.e = x;
  54. this.f = y;
  55. }
  56. protected CTM(CTM ctm) {
  57. this.a = ctm.a;
  58. this.b = ctm.b;
  59. this.c = ctm.c;
  60. this.d = ctm.d;
  61. this.e = ctm.e;
  62. this.f = ctm.f;
  63. }
  64. /**
  65. * Return a CTM which will transform coordinates for a particular writing-mode
  66. * into normalized first quandrant coordinates.
  67. * @param wm A writing mode constant from fo.properties.WritingMode, ie.
  68. * one of LR_TB, RL_TB, TB_RL.
  69. * @param ipd The inline-progression dimension of the reference area whose
  70. * CTM is being set..
  71. * @param bpd The block-progression dimension of the reference area whose
  72. * CTM is being set.
  73. */
  74. public static CTM getWMctm(int wm, int ipd, int bpd) {
  75. CTM wmctm;
  76. switch (wm) {
  77. case WritingMode.LR_TB:
  78. return new CTM(s_CTM_lrtb);
  79. case WritingMode.RL_TB:
  80. {
  81. wmctm = new CTM(s_CTM_rltb);
  82. wmctm.e = ipd;
  83. return wmctm;
  84. }
  85. //return s_CTM_rltb.translate(ipd, 0);
  86. case WritingMode.TB_RL: // CJK
  87. {
  88. wmctm = new CTM(s_CTM_tbrl);
  89. wmctm.e = bpd;
  90. return wmctm;
  91. }
  92. //return s_CTM_tbrl.translate(0, ipd);
  93. default:
  94. return null;
  95. }
  96. }
  97. /**
  98. * Multiply new passed CTM with this one and generate a new result CTM.
  99. * @param premult The CTM to multiply with this one. The new one will be
  100. * the first multiplicand.
  101. * @return CTM The result of multiplying premult * this.
  102. */
  103. public CTM multiply(CTM premult) {
  104. CTM rslt = new CTM ((premult.a * a) + (premult.b * c),
  105. (premult.a * b) + (premult.b * d),
  106. (premult.c * a) + (premult.d * c),
  107. (premult.c * b) + (premult.d * d),
  108. (premult.e * a) + (premult.f * c) + e,
  109. (premult.e * b) + (premult.f * d) + f);
  110. return rslt;
  111. }
  112. /**
  113. * Rotate this CTM by "angle" radians and return a new result CTM.
  114. * This is used to account for reference-orientation.
  115. * @param angle The angle in radians. Positive angles are measured counter-
  116. * clockwise.
  117. * @return CTM The result of rotating this CTM.
  118. */
  119. public CTM rotate(double angle) {
  120. double cos, sin;
  121. if (angle == 90.0) {
  122. cos = 0.0;
  123. sin = 1.0;
  124. } else if (angle == 270.0) {
  125. cos = 0.0;
  126. sin = -1.0;
  127. } else if (angle == 180.0) {
  128. cos = -1.0;
  129. sin = 0.0;
  130. } else {
  131. double rad = Math.toRadians(angle);
  132. cos = Math.cos(rad);
  133. sin = Math.sin(rad);
  134. }
  135. CTM rotate = new CTM(cos, -sin, sin, cos, 0, 0);
  136. return multiply(rotate);
  137. }
  138. /**
  139. * Translate this CTM by the passed x and y values and return a new result CTM.
  140. * @param x The amount to translate along the x axis.
  141. * @param y The amount to translate along the y axis.
  142. * @return CTM The result of translating this CTM.
  143. */
  144. public CTM translate(double x, double y) {
  145. CTM translate = new CTM(1, 0, 0, 1, x, y);
  146. return multiply(translate);
  147. }
  148. /**
  149. * Scale this CTM by the passed x and y values and return a new result CTM.
  150. * @param x The amount to scale along the x axis.
  151. * @param y The amount to scale along the y axis.
  152. * @return CTM The result of scaling this CTM.
  153. */
  154. public CTM scale(double x, double y) {
  155. CTM scale = new CTM(x, 0, 0, y, 0, 0);
  156. return multiply(scale);
  157. }
  158. /**
  159. * Transform a rectangle by the CTM to produce a rectangle in the transformed
  160. * coordinate system.
  161. * @param inRect The rectangle in the original coordinate system
  162. * @return Rectangle2D The rectangle in the transformed coordinate system.
  163. */
  164. public Rectangle2D transform(Rectangle2D inRect) {
  165. // Store as 2 sets of 2 points and transform those, then
  166. // recalculate the width and height
  167. int x1t = (int)(inRect.getX() * a + inRect.getY() * c + e);
  168. int y1t = (int)(inRect.getX() * b + inRect.getY() * d + f);
  169. int x2t = (int)((inRect.getX() + inRect.getWidth()) * a +
  170. (inRect.getY() + inRect.getHeight()) * c + e);
  171. int y2t = (int)((inRect.getX() + inRect.getWidth()) * b +
  172. (inRect.getY() + inRect.getHeight()) * d + f);
  173. // Normalize with x1 < x2
  174. if (x1t > x2t) {
  175. int tmp = x2t;
  176. x2t = x1t;
  177. x1t = tmp;
  178. }
  179. if (y1t > y2t) {
  180. int tmp = y2t;
  181. y2t = y1t;
  182. y1t = tmp;
  183. }
  184. return new Rectangle(x1t, y1t, x2t - x1t, y2t - y1t);
  185. }
  186. public String toString() {
  187. return "[" + a + " " + b + " " + c + " " + d + " " + e + " " +
  188. f + "]";
  189. }
  190. public double[] toArray() {
  191. return new double[]{a, b, c, d, e, f};
  192. }
  193. }