001: /*
002: * Copyright (c) 2007, intarsys consulting GmbH
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * - Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * - Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * - Neither the name of intarsys nor the names of its contributors may be used
015: * to endorse or promote products derived from this software without specific
016: * prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
028: * POSSIBILITY OF SUCH DAMAGE.
029: */
030: package de.intarsys.pdf.cds;
031:
032: import java.awt.geom.AffineTransform;
033: import de.intarsys.pdf.cos.COSArray;
034: import de.intarsys.pdf.cos.COSFixed;
035: import de.intarsys.pdf.cos.COSNumber;
036:
037: /**
038: * The implementation of the pdf transformation matrix.
039: *
040: * <p>Each matrix is represented as an array.
041: * <pre>
042: * The transformation matrix:
043: *
044: * + +
045: * | a b 0 |
046: * | c d 0 |
047: * | e f 1 |
048: * + +
049: *
050: * is written as a COSArray in the form:
051: *
052: * [ a b c d e f ]
053: *
054: * The identity transformation has the form:
055: *
056: * [ 1 0 0 1 0 0 ]
057: * </pre>
058: * </p>
059: *
060: * <p>
061: * Coordinates could be transformed by a matrix.
062: * <pre>
063: * A coordinate transformation is defined as:
064: * + +
065: * | a b 0 |
066: * [ x' y' 1 ] = [ x y 1] * | c d 0 |
067: * | e f 1 |
068: * + +
069: *
070: * so that
071: *
072: * x' = x*a + y*c + e
073: * y' = x*b + y*d + f
074: * </pre>
075: * </p>
076: */
077: public class CDSMatrix extends CDSBase {
078: /** Static information needed for rotation: rotate 0 degress (identity matrix) */
079: static public float[] MATRIX_0 = new float[] { 1, 0, 0, 1, 0, 0 };
080:
081: /** Static information needed for rotation: rotate 90 degrees */
082: static public float[] MATRIX_90 = new float[] { 0, 1, -1, 0, 0, 0 };
083:
084: /** Static information needed for rotation: rotate 180 degrees */
085: static public float[] MATRIX_180 = new float[] { -1, 0, 0, -1, 0, 0 };
086:
087: /** Static information needed for rotation: rotate 270 degrees */
088: static public float[] MATRIX_270 = new float[] { 0, -1, 1, 0, 0, 0 };
089:
090: /**
091: * Create a {@link CDSMatrix} from an <code>array</code> holding the
092: * transformation parameters.
093: *
094: * @param array
095: * The base {@link COSArray}
096: *
097: * @return Create a {@link CDSMatrix} from <code>array</code>
098: */
099: static public CDSMatrix createFromCOS(COSArray array) {
100: if (array == null) {
101: return null;
102: }
103: CDSMatrix matrix = (CDSMatrix) array
104: .getAttribute(CDSMatrix.class);
105: if (matrix == null) {
106: matrix = new CDSMatrix(array);
107: array.setAttribute(CDSMatrix.class, matrix);
108: }
109: return matrix;
110: }
111:
112: private float a;
113:
114: private float b;
115:
116: private float c;
117:
118: private float d;
119:
120: private float e;
121:
122: private float f;
123:
124: /**
125: * CDSMatrix constructor.
126: * <p>
127: * Create a new identity matrix
128: */
129: public CDSMatrix() {
130: super (COSArray.createWith(1, 0, 0, 1, 0, 0));
131: a = 1;
132: b = 0;
133: c = 0;
134: d = 1;
135: e = 0;
136: f = 0;
137: }
138:
139: /**
140: * Create a CDSMatrix based on the array in the parameter.
141: * The array must have 6 elements.
142: *
143: * @param data
144: * The array defining the matrix.
145: */
146: public CDSMatrix(float[] data) {
147: super (COSArray.createWith(data[0], data[1], data[2], data[3],
148: data[4], data[5]));
149: a = data[0];
150: b = data[1];
151: c = data[2];
152: d = data[3];
153: e = data[4];
154: f = data[5];
155: }
156:
157: /**
158: * Create a CDSMatrix based on the array in the parameter.
159: *
160: * @param newM
161: * The array defining the matrix.
162: */
163: protected CDSMatrix(COSArray newM) {
164: super (newM);
165: a = getA();
166: b = getB();
167: c = getC();
168: d = getD();
169: e = getE();
170: f = getF();
171: }
172:
173: /*
174: * (non-Javadoc)
175: *
176: * @see de.intarsys.pdf.cos.COSBasedObject#invalidateCaches()
177: */
178: public void invalidateCaches() {
179: super .invalidateCaches();
180: a = getA();
181: b = getB();
182: c = getC();
183: d = getD();
184: e = getE();
185: f = getF();
186: }
187:
188: /**
189: * Set the matrix element "a".
190: *
191: * @param num
192: * The new matrix element "a".
193: */
194: public void setA(float num) {
195: cosGetArray().set(0, COSFixed.create(num));
196: }
197:
198: /**
199: * Return the matrix element "a".
200: *
201: * @return The matrix element "a".
202: */
203: public float getA() {
204: return ((COSNumber) cosGetArray().get(0)).floatValue();
205: }
206:
207: /**
208: * Set the matrix element "b".
209: *
210: * @param num
211: * The new matrix element "b".
212: */
213: public void setB(float num) {
214: cosGetArray().set(1, COSFixed.create(num));
215: }
216:
217: /**
218: * Return the matrix element "b".
219: *
220: * @return The matrix element "b".
221: */
222: public float getB() {
223: return ((COSNumber) cosGetArray().get(1)).floatValue();
224: }
225:
226: /**
227: * Set the matrix element "c".
228: *
229: * @param num
230: * The new matrix element "c".
231: */
232: public void setC(float num) {
233: cosGetArray().set(2, COSFixed.create(num));
234: }
235:
236: /**
237: * Return the matrix element "c".
238: *
239: * @return The matrix element "c".
240: */
241: public float getC() {
242: return ((COSNumber) cosGetArray().get(2)).floatValue();
243: }
244:
245: /**
246: * Set the matrix element "d".
247: *
248: * @param num
249: * The new matrix element "d".
250: */
251: public void setD(float num) {
252: cosGetArray().set(3, COSFixed.create(num));
253: }
254:
255: /**
256: * Return the matrix element "d".
257: *
258: * @return The matrix element "d".
259: */
260: public float getD() {
261: return ((COSNumber) cosGetArray().get(3)).floatValue();
262: }
263:
264: /**
265: * Set the matrix element "e".
266: *
267: * @param num
268: * The new matrix element "e".
269: */
270: public void setE(float num) {
271: cosGetArray().set(4, COSFixed.create(num));
272: }
273:
274: /**
275: * Return the matrix element "e".
276: *
277: * @return The matrix element "e".
278: */
279: public float getE() {
280: return ((COSNumber) cosGetArray().get(4)).floatValue();
281: }
282:
283: /**
284: * Set the matrix element "f".
285: *
286: * @param num
287: * The new matrix element "f".
288: */
289: public void setF(float num) {
290: cosGetArray().set(5, COSFixed.create(num));
291: }
292:
293: /**
294: * Return the matrix element "f".
295: *
296: * @return The matrix element "f".
297: */
298: public float getF() {
299: return ((COSNumber) cosGetArray().get(5)).floatValue();
300: }
301:
302: /**
303: * Set all matrix elements "a" - "f"
304: *
305: * @param a
306: * The new matrix element "a".
307: * @param b
308: * The new matrix element "b".
309: * @param c
310: * The new matrix element "c".
311: * @param d
312: * The new matrix element "d".
313: * @param e
314: * The new matrix element "e".
315: * @param f
316: * The new matrix element "f".
317: */
318: public void setTransformation(float a, float b, float c, float d,
319: float e, float f) {
320: cosGetArray().set(0, COSFixed.create(a));
321: cosGetArray().set(1, COSFixed.create(b));
322: cosGetArray().set(2, COSFixed.create(c));
323: cosGetArray().set(3, COSFixed.create(d));
324: cosGetArray().set(4, COSFixed.create(e));
325: cosGetArray().set(5, COSFixed.create(f));
326: }
327:
328: /**
329: * Set all matrix elements "a" - "f"
330: *
331: * @param data
332: * The array defining the new parameters
333: */
334: public void setTransformation(float[] data) {
335: cosGetArray().set(0, COSFixed.create(data[0]));
336: cosGetArray().set(1, COSFixed.create(data[1]));
337: cosGetArray().set(2, COSFixed.create(data[2]));
338: cosGetArray().set(3, COSFixed.create(data[3]));
339: cosGetArray().set(4, COSFixed.create(data[4]));
340: cosGetArray().set(5, COSFixed.create(data[5]));
341: }
342:
343: /**
344: * Set all matrix elements "a" - "f"
345: *
346: * @param transform
347: * The matrix defining the new parameters
348: */
349: public void setTransformation(AffineTransform transform) {
350: double[] data = new double[6];
351: transform.getMatrix(data);
352: cosGetArray().set(0, COSFixed.create(data[0]));
353: cosGetArray().set(1, COSFixed.create(data[1]));
354: cosGetArray().set(2, COSFixed.create(data[2]));
355: cosGetArray().set(3, COSFixed.create(data[3]));
356: cosGetArray().set(4, COSFixed.create(data[4]));
357: cosGetArray().set(5, COSFixed.create(data[5]));
358: }
359:
360: /**
361: * Create a copy of the receiver
362: *
363: * @return a new copy of the receiver
364: */
365: public CDSMatrix copy() {
366: CDSMatrix result = new CDSMatrix((COSArray) cosGetObject()
367: .copyShallow());
368: return result;
369: }
370:
371: /**
372: * Concatenate this transformation with a rotation transformation.
373: *
374: * @param angle
375: * Rotation angle in radians
376: */
377: public void rotate(float angle) {
378: AffineTransform transform = toTransform();
379: transform.rotate(angle);
380: setTransformation(transform);
381: }
382:
383: /**
384: * Concatenate this transformation with a scaling transformation.
385: *
386: * @param v
387: * The scale factor.
388: */
389: public void scale(float[] v) {
390: setA(getA() * v[0]);
391: setD(getD() * v[1]);
392: }
393:
394: /**
395: * Transform a vector <code>v</code> using this.
396: *
397: * @param v
398: * The vector that will be transformed.
399: *
400: * @return The transformed vector.
401: */
402: public float[] transform(float[] v) {
403: int len = v.length;
404: float[] result = new float[len];
405: int i = 0;
406: int iinc = 1;
407: while (iinc < len) {
408: result[i] = (a * v[i]) + (c * v[iinc]) + e;
409: result[iinc] = (b * v[i]) + (d * v[iinc]) + f;
410: i += 2;
411: iinc += 2;
412: }
413: return result;
414: }
415:
416: /**
417: * Concatenate this transformation with a translation transformation.
418: *
419: * @param v
420: * The transaltion definition
421: */
422: public void translate(float[] v) {
423: setE(getE() + v[0]);
424: setF(getF() + v[1]);
425: }
426:
427: /**
428: * Concatenate this transformation with a translation transformation.
429: *
430: * @param x
431: * The translation in x direction
432: * @param y
433: * The translation in y direction
434: */
435: public void translate(float x, float y) {
436: setE(getE() + x);
437: setF(getF() + y);
438: }
439:
440: /**
441: * Create an {@link AffineTransform} that corresponds to this.
442: *
443: * @return Create an {@link AffineTransform} that corresponds to this.
444: */
445: public AffineTransform toTransform() {
446: return new AffineTransform(a, b, c, d, e, f);
447: }
448: }
|