KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > area > CTM


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 /* $Id: CTM.java 426576 2006-07-28 15:44:37Z jeremias $ */
19
20 package org.apache.fop.area;
21
22 import java.awt.Rectangle JavaDoc;
23 import java.awt.geom.Rectangle2D JavaDoc;
24 import java.io.Serializable JavaDoc;
25
26 import org.apache.fop.datatypes.FODimension;
27 import org.apache.fop.fo.Constants;
28
29 /**
30  * Describe a PDF or PostScript style coordinate transformation matrix (CTM).
31  * The matrix encodes translations, scaling and rotations of the coordinate
32  * system used to render pages.
33  */

34 public class CTM implements Serializable JavaDoc {
35
36     private double a, b, c, d, e, f;
37
38     private static final CTM CTM_LRTB = new CTM(1, 0, 0, 1, 0, 0);
39     private static final CTM CTM_RLTB = new CTM(-1, 0, 0, 1, 0, 0);
40     private static final CTM CTM_TBRL = new CTM(0, 1, -1, 0, 0, 0);
41
42     /**
43      * Create the identity matrix
44      */

45     public CTM() {
46         a = 1;
47         b = 0;
48         c = 0;
49         d = 1;
50         e = 0;
51         f = 0;
52     }
53
54     /**
55      * Initialize a CTM from the passed arguments.
56      *
57      * @param a the x scale
58      * @param b the x shear
59      * @param c the y shear
60      * @param d the y scale
61      * @param e the x shift
62      * @param f the y shift
63      */

64     public CTM(double a, double b, double c, double d, double e, double f) {
65         this.a = a;
66         this.b = b;
67         this.c = c;
68         this.d = d;
69         this.e = e;
70         this.f = f;
71     }
72
73     /**
74      * Initialize a CTM to the identity matrix with a translation
75      * specified by x and y
76      *
77      * @param x the x shift
78      * @param y the y shift.
79      */

80     public CTM(double x, double y) {
81         this.a = 1;
82         this.b = 0;
83         this.c = 0;
84         this.d = 1;
85         this.e = x;
86         this.f = y;
87     }
88
89     /**
90      * Initialize a CTM with the values of another CTM.
91      *
92      * @param ctm another CTM
93      */

94     protected CTM(CTM ctm) {
95         this.a = ctm.a;
96         this.b = ctm.b;
97         this.c = ctm.c;
98         this.d = ctm.d;
99         this.e = ctm.e;
100         this.f = ctm.f;
101     }
102
103     /**
104      * Return a CTM which will transform coordinates for a particular writing-mode
105      * into normalized first quandrant coordinates.
106      * @param wm A writing mode constant from fo.properties.WritingMode, ie.
107      * one of LR_TB, RL_TB, TB_RL.
108      * @param ipd The inline-progression dimension of the reference area whose
109      * CTM is being set..
110      * @param bpd The block-progression dimension of the reference area whose
111      * CTM is being set.
112      * @return a new CTM with the required transform
113      */

114     public static CTM getWMctm(int wm, int ipd, int bpd) {
115         CTM wmctm;
116         switch (wm) {
117             case Constants.EN_LR_TB:
118                 return new CTM(CTM_LRTB);
119             case Constants.EN_RL_TB:
120                 wmctm = new CTM(CTM_RLTB);
121                 wmctm.e = ipd;
122                 return wmctm;
123                 //return CTM_RLTB.translate(ipd, 0);
124
case Constants.EN_TB_RL: // CJK
125
wmctm = new CTM(CTM_TBRL);
126                 wmctm.e = bpd;
127                 return wmctm;
128                 //return CTM_TBRL.translate(0, ipd);
129
default:
130                 return null;
131         }
132     }
133
134     /**
135      * Multiply new passed CTM with this one and generate a new result CTM.
136      * @param premult The CTM to multiply with this one. The new one will be
137      * the first multiplicand.
138      * @return CTM The result of multiplying premult * this.
139      */

140     public CTM multiply(CTM premult) {
141         CTM result = new CTM ((premult.a * a) + (premult.b * c),
142                               (premult.a * b) + (premult.b * d),
143                               (premult.c * a) + (premult.d * c),
144                               (premult.c * b) + (premult.d * d),
145                               (premult.e * a) + (premult.f * c) + e,
146                               (premult.e * b) + (premult.f * d) + f);
147         return result;
148     }
149
150     /**
151      * Rotate this CTM by "angle" radians and return a new result CTM.
152      * This is used to account for reference-orientation.
153      * @param angle The angle in radians. Positive angles are measured counter-
154      * clockwise.
155      * @return CTM The result of rotating this CTM.
156      */

157     public CTM rotate(double angle) {
158         double cos, sin;
159         if (angle == 90.0 || angle == -270.0) {
160             cos = 0.0;
161             sin = 1.0;
162         } else if (angle == 270.0 || angle == -90.0) {
163             cos = 0.0;
164             sin = -1.0;
165         } else if (angle == 180.0 || angle == -180.0) {
166             cos = -1.0;
167             sin = 0.0;
168         } else {
169             double rad = Math.toRadians(angle);
170             cos = Math.cos(rad);
171             sin = Math.sin(rad);
172         }
173         CTM rotate = new CTM(cos, -sin, sin, cos, 0, 0);
174         return multiply(rotate);
175     }
176
177     /**
178      * Translate this CTM by the passed x and y values and return a new result CTM.
179      * @param x The amount to translate along the x axis.
180      * @param y The amount to translate along the y axis.
181      * @return CTM The result of translating this CTM.
182      */

183     public CTM translate(double x, double y) {
184         CTM translate = new CTM(1, 0, 0, 1, x, y);
185         return multiply(translate);
186     }
187
188     /**
189      * Scale this CTM by the passed x and y values and return a new result CTM.
190      * @param x The amount to scale along the x axis.
191      * @param y The amount to scale along the y axis.
192      * @return CTM The result of scaling this CTM.
193      */

194     public CTM scale(double x, double y) {
195         CTM scale = new CTM(x, 0, 0, y, 0, 0);
196         return multiply(scale);
197     }
198
199     /**
200      * Transform a rectangle by the CTM to produce a rectangle in the transformed
201      * coordinate system.
202      * @param inRect The rectangle in the original coordinate system
203      * @return Rectangle2D The rectangle in the transformed coordinate system.
204      */

205     public Rectangle2D JavaDoc transform(Rectangle2D JavaDoc inRect) {
206         // Store as 2 sets of 2 points and transform those, then
207
// recalculate the width and height
208
int x1t = (int)(inRect.getX() * a + inRect.getY() * c + e);
209         int y1t = (int)(inRect.getX() * b + inRect.getY() * d + f);
210         int x2t = (int)((inRect.getX() + inRect.getWidth()) * a
211                         + (inRect.getY() + inRect.getHeight()) * c + e);
212         int y2t = (int)((inRect.getX() + inRect.getWidth()) * b
213                         + (inRect.getY() + inRect.getHeight()) * d + f);
214         // Normalize with x1 < x2
215
if (x1t > x2t) {
216             int tmp = x2t;
217             x2t = x1t;
218             x1t = tmp;
219         }
220         if (y1t > y2t) {
221             int tmp = y2t;
222             y2t = y1t;
223             y1t = tmp;
224         }
225         return new Rectangle JavaDoc(x1t, y1t, x2t - x1t, y2t - y1t);
226     }
227
228     /**
229      * Get string for this transform.
230      *
231      * @return a string with the transform values
232      */

233     public String JavaDoc toString() {
234         return "[" + a + " " + b + " " + c + " " + d + " " + e + " "
235                + f + "]";
236     }
237
238     /**
239      * Get an array containing the values of this transform.
240      * This creates and returns a new transform with the values in it.
241      *
242      * @return an array containing the transform values
243      */

244     public double[] toArray() {
245         return new double[]{a, b, c, d, e, f};
246     }
247
248     /**
249      * Construct a coordinate transformation matrix (CTM).
250      * @param absRefOrient absolute reference orientation
251      * @param writingMode the writing mode
252      * @param absVPrect absolute viewpoint rectangle
253      * @param reldims relative dimensions
254      * @return CTM the coordinate transformation matrix (CTM)
255      */

256     public static CTM getCTMandRelDims(int absRefOrient,
257                                        int writingMode,
258                                        Rectangle2D JavaDoc absVPrect,
259                                        FODimension reldims) {
260         int width, height;
261         // We will use the absolute reference-orientation to set up the CTM.
262
// The value here is relative to its ancestor reference area.
263
if (absRefOrient % 180 == 0) {
264             width = (int) absVPrect.getWidth();
265             height = (int) absVPrect.getHeight();
266         } else {
267             // invert width and height since top left are rotated by 90 (cl or ccl)
268
height = (int) absVPrect.getWidth();
269             width = (int) absVPrect.getHeight();
270         }
271         /* Set up the CTM for the content of this reference area.
272          * This will transform region content coordinates in
273          * writing-mode relative into absolute page-relative
274          * which will then be translated based on the position of
275          * the region viewport.
276          * (Note: scrolling between region vp and ref area when
277          * doing online content!)
278          */

279         CTM ctm = new CTM(absVPrect.getX(), absVPrect.getY());
280
281         // First transform for rotation
282
if (absRefOrient != 0) {
283             // Rotation implies translation to keep the drawing area in the
284
// first quadrant. Note: rotation is counter-clockwise
285
switch (absRefOrient) {
286                 case 90:
287                 case -270:
288                     ctm = ctm.translate(0, width); // width = absVPrect.height
289
break;
290                 case 180:
291                 case -180:
292                     ctm = ctm.translate(width, height);
293                     break;
294                 case 270:
295                 case -90:
296                     ctm = ctm.translate(height, 0); // height = absVPrect.width
297
break;
298                 default:
299                     throw new RuntimeException JavaDoc();
300             }
301             ctm = ctm.rotate(absRefOrient);
302         }
303         /* Since we've already put adjusted width and height values for the
304          * top and left positions implied by the reference-orientation, we
305          * can set ipd and bpd appropriately based on the writing mode.
306          */

307
308         if (writingMode == Constants.EN_LR_TB || writingMode == Constants.EN_RL_TB) {
309             reldims.ipd = width;
310             reldims.bpd = height;
311         } else {
312             reldims.ipd = height;
313             reldims.bpd = width;
314         }
315         // Set a rectangle to be the writing-mode relative version???
316
// Now transform for writing mode
317
return ctm.multiply(CTM.getWMctm(writingMode, reldims.ipd, reldims.bpd));
318     }
319
320 }
321
Popular Tags