KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > svggen > SVGTransform


1 /*
2
3    Copyright 2001,2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    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 package org.apache.batik.svggen;
19
20 import java.util.Stack JavaDoc;
21
22 import org.apache.batik.ext.awt.g2d.GraphicContext;
23 import org.apache.batik.ext.awt.g2d.TransformStackElement;
24 import org.apache.batik.ext.awt.g2d.TransformType;
25
26 /**
27  * Utility class that converts a GraphicContext transform stack
28  * into an SVG transform attribute.
29  *
30  * @author <a HREF="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
31  * @author <a HREF="mailto:paul_evenblij@compuware.com">Paul Evenblij</a>
32  * @version $Id: SVGTransform.java,v 1.9 2004/08/18 07:15:09 vhardy Exp $
33  */

34 public class SVGTransform extends AbstractSVGConverter{
35     /**
36      * Ratio used to convert radians to degrees
37      */

38     private static double radiansToDegrees = 180.0 / Math.PI;
39
40     /**
41      * @param generatorContext used by converter to handle precision
42      * or to create elements.
43      */

44     public SVGTransform(SVGGeneratorContext generatorContext) {
45         super(generatorContext);
46     }
47
48     /**
49      * Converts part or all of the input GraphicContext into
50      * a set of attribute/value pairs and related definitions
51      *
52      * @param gc GraphicContext to be converted
53      * @return descriptor of the attributes required to represent
54      * some or all of the GraphicContext state, along
55      * with the related definitions
56      * @see org.apache.batik.svggen.SVGDescriptor
57      */

58     public SVGDescriptor toSVG(GraphicContext gc){
59         return new SVGTransformDescriptor(toSVGTransform(gc));
60     }
61
62     /**
63      * @param gc GraphicContext whose transform stack should be converted
64      * to SVG.
65      * @return the value of an SVG attribute equivalent to the input
66      * GraphicContext's transform stack.
67      */

68     public final String JavaDoc toSVGTransform(GraphicContext gc){
69         return toSVGTransform(gc.getTransformStack());
70     }
71
72     /**
73      * This method tries to collapse the transform stack into an SVG
74      * string as compact as possible while still conveying the semantic
75      * of the stack. Successive stack elements of the same kind (e.g., two
76      * successive transforms or scales) are collapsed into a single element.
77      *
78      * @param transformStack sequence of transform that should
79      * be converted to an SVG transform attribute equivalent
80      */

81     public final String JavaDoc toSVGTransform(TransformStackElement transformStack[]){
82         StringBuffer JavaDoc transformStackBuffer = new StringBuffer JavaDoc();
83         int nTransforms = transformStack.length;
84         //
85
// Append transforms in the presentation stack
86
//
87
Stack JavaDoc presentation = new Stack JavaDoc() {
88             /**
89              * Adapted push implementation
90              */

91             public Object JavaDoc push(Object JavaDoc o) {
92                 Object JavaDoc element;
93                 if(((TransformStackElement)o).isIdentity()) {
94                     // identity transform: don't push,
95
// and try to return top of stack
96
element = pop();
97                 } else {
98                     // non-identity: push,
99
// and return null
100
super.push(o);
101                     element = null;
102                 }
103                 return element;
104             }
105             
106             /**
107              * Adapted pop implementation
108              */

109             public Object JavaDoc pop() {
110                 Object JavaDoc element = null;
111                 if(!super.empty()) {
112                     element = super.pop();
113                 }
114                 return element;
115             }
116         };
117         boolean canConcatenate = false;
118         int i = 0, j = 0, next = 0;
119         TransformStackElement element = null;
120
121         // We keep a separate 'presentation' stack, which contains
122
// all concatenated elements. The top of this stack is the
123
// element we try to concatenate onto. If this element
124
// becomes an identity transform, we discard it and look at
125
// the element underneath it instead.
126
// The presentation stack is guaranteed not to contain
127
// identity transforms.
128

129         while(i < nTransforms) {
130
131             // If we do not have an element to concatenate onto,
132
// we grab one here.
133
next = i;
134             if(element == null) {
135                 element = (TransformStackElement) transformStack[i].clone();
136                 next++;
137             }
138
139             // try to concatenate as much as possible
140
canConcatenate = true;
141             for(j = next; j < nTransforms; j++) {
142                 canConcatenate = element.concatenate(transformStack[j]);
143                 if(!canConcatenate)
144                     break;
145             }
146             // loop variable assertion:
147
// If "i" does not increment during this iteration, it is guaranteed
148
// to do so in the next, since "i" can only keep the same value as a
149
// result of "element" having a non-null value on starting this
150
// iteration, which can only be the case if it was popped from the
151
// stack during the previous one. The stack does not contain
152
// identities, and since "i" has not grown, "element" has remained
153
// unchanged and will be pushed onto the stack again. "element" will
154
// then become null, so "i" will eventually increment.
155
i = j;
156  
157             // Get rid of identity transforms within the stack.
158
// If an identity is pushed, it is immediately removed, and
159
// the current top of stack will be returned to concatenate onto.
160
// Otherwise, null will be returned.
161
element = (TransformStackElement) presentation.push(element);
162         }
163
164         // Push back teh last element popped, if not null
165
if (element != null){
166             presentation.push(element);
167         }
168  
169         //
170
// Transform presentation stack to SVG
171
//
172
int nPresentations = presentation.size();
173         
174         for(i = 0; i < nPresentations; i++) {
175             transformStackBuffer.append(convertTransform((TransformStackElement) presentation.elementAt(i)));
176             transformStackBuffer.append(SPACE);
177         }
178
179         String JavaDoc transformValue = transformStackBuffer.toString().trim();
180         return transformValue;
181     }
182
183     /**
184      * Converts an AffineTransform to an SVG transform string
185      */

186     final String JavaDoc convertTransform(TransformStackElement transformElement){
187         StringBuffer JavaDoc transformString = new StringBuffer JavaDoc();
188         double transformParameters[] = transformElement.getTransformParameters();
189         switch(transformElement.getType().toInt()){
190         case TransformType.TRANSFORM_TRANSLATE:
191             if(!transformElement.isIdentity()) {
192                 transformString.append(TRANSFORM_TRANSLATE);
193                 transformString.append(OPEN_PARENTHESIS);
194                 transformString.append(doubleString(transformParameters[0]));
195                 transformString.append(COMMA);
196                 transformString.append(doubleString(transformParameters[1]));
197                 transformString.append(CLOSE_PARENTHESIS);
198             }
199             break;
200         case TransformType.TRANSFORM_ROTATE:
201             if(!transformElement.isIdentity()) {
202                 transformString.append(TRANSFORM_ROTATE);
203                 transformString.append(OPEN_PARENTHESIS);
204                 transformString.append(doubleString(radiansToDegrees*transformParameters[0]));
205                 transformString.append(CLOSE_PARENTHESIS);
206             }
207             break;
208         case TransformType.TRANSFORM_SCALE:
209             if(!transformElement.isIdentity()) {
210                 transformString.append(TRANSFORM_SCALE);
211                 transformString.append(OPEN_PARENTHESIS);
212                 transformString.append(doubleString(transformParameters[0]));
213                 transformString.append(COMMA);
214                 transformString.append(doubleString(transformParameters[1]));
215                 transformString.append(CLOSE_PARENTHESIS);
216             }
217             break;
218         case TransformType.TRANSFORM_SHEAR:
219             if(!transformElement.isIdentity()) {
220                 transformString.append(TRANSFORM_MATRIX);
221                 transformString.append(OPEN_PARENTHESIS);
222                 transformString.append(1);
223                 transformString.append(COMMA);
224                 transformString.append(doubleString(transformParameters[1]));
225                 transformString.append(COMMA);
226                 transformString.append(doubleString(transformParameters[0]));
227                 transformString.append(COMMA);
228                 transformString.append(1);
229                 transformString.append(COMMA);
230                 transformString.append(0);
231                 transformString.append(COMMA);
232                 transformString.append(0);
233                 transformString.append(CLOSE_PARENTHESIS);
234             }
235             break;
236         case TransformType.TRANSFORM_GENERAL:
237             if(!transformElement.isIdentity()) {
238                 transformString.append(TRANSFORM_MATRIX);
239                 transformString.append(OPEN_PARENTHESIS);
240                 transformString.append(doubleString(transformParameters[0]));
241                 transformString.append(COMMA);
242                 transformString.append(doubleString(transformParameters[1]));
243                 transformString.append(COMMA);
244                 transformString.append(doubleString(transformParameters[2]));
245                 transformString.append(COMMA);
246                 transformString.append(doubleString(transformParameters[3]));
247                 transformString.append(COMMA);
248                 transformString.append(doubleString(transformParameters[4]));
249                 transformString.append(COMMA);
250                 transformString.append(doubleString(transformParameters[5]));
251                 transformString.append(CLOSE_PARENTHESIS);
252             }
253             break;
254         default:
255             // This should never happen. If it does, there is a
256
// serious error.
257
throw new Error JavaDoc();
258         }
259
260         return transformString.toString();
261     }
262 }
263
Popular Tags