001: /*
002: *
003: *
004: * Portions Copyright 2000-2007 Sun Microsystems, Inc. All Rights
005: * Reserved. Use is subject to license terms.
006: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public License version
010: * 2 only, as published by the Free Software Foundation.
011: *
012: * This program is distributed in the hope that it will be useful, but
013: * WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * General Public License version 2 for more details (a copy is
016: * included at /legal/license.txt).
017: *
018: * You should have received a copy of the GNU General Public License
019: * version 2 along with this work; if not, write to the Free Software
020: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
021: * 02110-1301 USA
022: *
023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
024: * Clara, CA 95054 or visit www.sun.com if you need additional
025: * information or have any questions.
026: */
027:
028: /*****************************************************************************
029: * Copyright (C) The Apache Software Foundation. All rights reserved. *
030: * ------------------------------------------------------------------------- *
031: * This software is published under the terms of the Apache Software License *
032: * version 1.1, a copy of which has been included with this distribution in *
033: * the LICENSE file. *
034: *****************************************************************************/package com.sun.perseus.parser;
035:
036: import com.sun.perseus.platform.MathSupport;
037:
038: import com.sun.perseus.j2d.Transform;
039:
040: /**
041: * The <code>TransformListParser</code> class converts attributes
042: * conforming to the SVG
043: * <a href="http://www.w3.org/TR/SVG11/coords.html#TransformAttribute">
044: * transform</a>
045: * syntax into <code>AffineTransform</code> objects.
046: *
047: * @version $Id: TransformListParser.java,v 1.2 2006/04/21 06:40:42 st125089 Exp $
048: */
049: public class TransformListParser extends NumberParser {
050: /**
051: * Captures the transform built by this parser
052: */
053: private Transform transform;
054:
055: /**
056: * @param txfStr the string containing the set of transform commands
057: * @return An <code>AffineTransform</code> object corresponding to the
058: * input transform list.
059: */
060: public Transform parseTransformList(final String txfStr) {
061: setString(txfStr);
062:
063: transform = new Transform(1, 0, 0, 1, 0, 0);
064:
065: // Parse leading wsp*
066: current = read();
067: skipSpaces();
068:
069: // Now, iterate on 'transforms?'
070: loop2: for (;;) {
071: switch (current) {
072: case 'm':
073: parseMatrix();
074: break;
075: case 'r':
076: parseRotate();
077: break;
078: case 't':
079: parseTranslate();
080: break;
081: case 's':
082: current = read();
083: switch (current) {
084: case 'c':
085: parseScale();
086: break;
087: case 'k':
088: parseSkew();
089: break;
090: default:
091: throw new IllegalArgumentException();
092: }
093: break;
094: case -1:
095: break loop2;
096: default:
097: throw new IllegalArgumentException();
098: }
099: current = read();
100: skipCommaSpaces();
101: }
102:
103: return transform;
104: }
105:
106: /**
107: * Parses a matrix transform. 'm' is assumed to be the current character.
108: */
109: protected final void parseMatrix() {
110: current = read();
111:
112: // Parse 'atrix wsp? ( wsp?'
113: if (current != 'a') {
114: throw new IllegalArgumentException();
115: }
116: current = read();
117: if (current != 't') {
118: throw new IllegalArgumentException();
119: }
120: current = read();
121: if (current != 'r') {
122: throw new IllegalArgumentException();
123: }
124: current = read();
125: if (current != 'i') {
126: throw new IllegalArgumentException();
127: }
128: current = read();
129: if (current != 'x') {
130: throw new IllegalArgumentException();
131: }
132: current = read();
133: skipSpaces();
134: if (current != '(') {
135: throw new IllegalArgumentException();
136: }
137: current = read();
138: skipSpaces();
139:
140: float a = parseNumber();
141: skipCommaSpaces();
142: float b = parseNumber();
143: skipCommaSpaces();
144: float c = parseNumber();
145: skipCommaSpaces();
146: float d = parseNumber();
147: skipCommaSpaces();
148: float e = parseNumber();
149: skipCommaSpaces();
150: float f = parseNumber();
151:
152: skipSpaces();
153:
154: if (current != ')') {
155: throw new IllegalArgumentException("Expected ')' and got >"
156: + (char) current + "<");
157: }
158:
159: transform.mMultiply(new Transform(a, b, c, d, e, f));
160: }
161:
162: /**
163: * Parses a rotate transform. 'r' is assumed to be the current character.
164: */
165: protected final void parseRotate() {
166: current = read();
167:
168: // Parse 'otate wsp? ( wsp?'
169: if (current != 'o') {
170: throw new IllegalArgumentException();
171: }
172: current = read();
173: if (current != 't') {
174: throw new IllegalArgumentException();
175: }
176: current = read();
177: if (current != 'a') {
178: throw new IllegalArgumentException();
179: }
180: current = read();
181: if (current != 't') {
182: throw new IllegalArgumentException();
183: }
184: current = read();
185: if (current != 'e') {
186: throw new IllegalArgumentException();
187: }
188: current = read();
189: skipSpaces();
190:
191: if (current != '(') {
192: throw new IllegalArgumentException();
193: }
194: current = read();
195: skipSpaces();
196:
197: float theta = parseNumber();
198: skipSpaces();
199:
200: switch (current) {
201: case ')':
202: transform.mRotate(theta);
203: return;
204: case ',':
205: current = read();
206: skipSpaces();
207: default:
208: // nothing.
209: }
210:
211: float cx = parseNumber();
212: skipCommaSpaces();
213: float cy = parseNumber();
214:
215: skipSpaces();
216: if (current != ')') {
217: throw new IllegalArgumentException();
218: }
219:
220: transform.mTranslate(cx, cy);
221: transform.mRotate(theta);
222: transform.mTranslate(-cx, -cy);
223: }
224:
225: /**
226: * Parses a translate transform. 't' is assumed to be
227: * the current character.
228: */
229: protected final void parseTranslate() {
230: current = read();
231:
232: // Parse 'ranslate wsp? ( wsp?'
233: if (current != 'r') {
234: throw new IllegalArgumentException();
235: }
236: current = read();
237: if (current != 'a') {
238: throw new IllegalArgumentException();
239: }
240: current = read();
241: if (current != 'n') {
242: throw new IllegalArgumentException();
243: }
244: current = read();
245: if (current != 's') {
246: throw new IllegalArgumentException();
247: }
248: current = read();
249: if (current != 'l') {
250: throw new IllegalArgumentException();
251: }
252: current = read();
253: if (current != 'a') {
254: throw new IllegalArgumentException();
255: }
256: current = read();
257: if (current != 't') {
258: throw new IllegalArgumentException();
259: }
260: current = read();
261: if (current != 'e') {
262: throw new IllegalArgumentException();
263: }
264: current = read();
265: skipSpaces();
266: if (current != '(') {
267: throw new IllegalArgumentException();
268: }
269: current = read();
270: skipSpaces();
271:
272: float tx = parseNumber();
273: skipSpaces();
274:
275: switch (current) {
276: case ')':
277: transform.mTranslate(tx, 0);
278: return;
279: case ',':
280: current = read();
281: skipSpaces();
282: default:
283: // nothing
284: }
285:
286: float ty = parseNumber();
287:
288: skipSpaces();
289: if (current != ')') {
290: throw new IllegalArgumentException();
291: }
292:
293: transform.mTranslate(tx, ty);
294: }
295:
296: /**
297: * Parses a scale transform. 'c' is assumed to be the current character.
298: */
299: protected final void parseScale() {
300: current = read();
301:
302: // Parse 'ale wsp? ( wsp?'
303: if (current != 'a') {
304: throw new IllegalArgumentException();
305: }
306: current = read();
307: if (current != 'l') {
308: throw new IllegalArgumentException();
309: }
310: current = read();
311: if (current != 'e') {
312: throw new IllegalArgumentException();
313: }
314: current = read();
315: skipSpaces();
316: if (current != '(') {
317: throw new IllegalArgumentException();
318: }
319: current = read();
320: skipSpaces();
321:
322: float sx = parseNumber();
323: skipSpaces();
324:
325: switch (current) {
326: case ')':
327: transform.mScale(sx);
328: return;
329: case ',':
330: current = read();
331: skipSpaces();
332: default:
333: // nothing
334: }
335:
336: float sy = parseNumber();
337:
338: skipSpaces();
339: if (current != ')') {
340: throw new IllegalArgumentException();
341: }
342:
343: transform.mScale(sx, sy);
344: }
345:
346: /**
347: * Parses a skew transform. 'e' is assumed to be the current character.
348: */
349: protected final void parseSkew() {
350: current = read();
351:
352: // Parse 'ew[XY] wsp? ( wsp?'
353: if (current != 'e') {
354: throw new IllegalArgumentException();
355: }
356: current = read();
357: if (current != 'w') {
358: throw new IllegalArgumentException();
359: }
360: current = read();
361:
362: boolean skewX = false;
363: switch (current) {
364: case 'X':
365: skewX = true;
366: case 'Y':
367: break;
368: default:
369: throw new IllegalArgumentException();
370: }
371: current = read();
372: skipSpaces();
373: if (current != '(') {
374: throw new IllegalArgumentException();
375: }
376: current = read();
377: skipSpaces();
378:
379: float sk = parseNumber();
380:
381: skipSpaces();
382: if (current != ')') {
383: throw new IllegalArgumentException();
384: }
385:
386: float tan = MathSupport.tan(MathSupport.toRadians(sk));
387:
388: if (skewX) {
389: Transform shear = new Transform(1, 0, tan, 1, 0, 0);
390: transform.mMultiply(shear);
391: // transform.shear(tan, 0);
392: } else {
393: Transform shear = new Transform(1, tan, 0, 1, 0, 0);
394: transform.mMultiply(shear);
395: // transform.shear(0, tan);
396: }
397: }
398:
399: }
|