KickJava   Java API By Example, From Geeks To Geeks.

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


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.awt.Shape JavaDoc;
21 import java.awt.geom.GeneralPath JavaDoc;
22 import java.awt.geom.PathIterator JavaDoc;
23
24 import org.w3c.dom.Element JavaDoc;
25
26 /**
27  * Utility class that converts a Shape object into an SVG
28  * path element. Note that this class does not attempt to
29  * find out what type of object (e.g., whether the input
30  * Shape is a Rectangle or an Ellipse. This type of analysis
31  * is done by the SVGShape class).
32  * Note that this class assumes that the parent of the
33  * path element it generates defines the fill-rule as
34  * nonzero. This is not the SVG default value. However,
35  * because it is the GeneralPath's default, it is preferable
36  * to have this attribute specified once to set the default
37  * (in the parent element, e.g., a group) and then only in
38  * the rare instance where the winding rule is different
39  * than the default. Otherwise, the attribute would have
40  * to be specified in the majority of path elements.
41  *
42  * @author <a HREF="mailto:cjolif@ilog.fr">Christophe Jolif</a>
43  * @author <a HREF="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
44  * @version $Id: SVGPath.java,v 1.16 2004/10/30 16:54:53 deweese Exp $
45  */

46 public class SVGPath extends SVGGraphicObjectConverter {
47     /**
48      * @param generatorContext used to build Elements
49      */

50     public SVGPath(SVGGeneratorContext generatorContext) {
51         super(generatorContext);
52     }
53
54     /**
55      * @param path the Shape that should be converted to an SVG path
56      * element.
57      * @return a path Element.
58      */

59     public Element JavaDoc toSVG(Shape JavaDoc path) {
60         // Create the path element and process its
61
// d attribute.
62
String JavaDoc dAttr = toSVGPathData(path, generatorContext);
63         if (dAttr==null || dAttr.length() == 0){
64             // be careful not to append null to the DOM tree
65
// because it will crash
66
return null;
67         }
68
69         Element JavaDoc svgPath = generatorContext.domFactory.createElementNS
70             (SVG_NAMESPACE_URI, SVG_PATH_TAG);
71         svgPath.setAttributeNS(null, SVG_D_ATTRIBUTE, dAttr);
72
73         // Set winding rule if different than SVG's default
74
if (path.getPathIterator(null).getWindingRule() == GeneralPath.WIND_EVEN_ODD)
75             svgPath.setAttributeNS(null, SVG_FILL_RULE_ATTRIBUTE, SVG_EVEN_ODD_VALUE);
76
77         return svgPath;
78     }
79
80     /**
81      * @param path the GeneralPath to convert
82      * @return the value of the corresponding d attribute
83      */

84      public static String JavaDoc toSVGPathData(Shape JavaDoc path, SVGGeneratorContext gc) {
85         StringBuffer JavaDoc d = new StringBuffer JavaDoc("");
86         PathIterator JavaDoc pi = path.getPathIterator(null);
87         float seg[] = new float[6];
88         int segType = 0;
89         while (!pi.isDone()) {
90             segType = pi.currentSegment(seg);
91             switch(segType) {
92             case PathIterator.SEG_MOVETO:
93                 d.append(PATH_MOVE);
94                 appendPoint(d, seg[0], seg[1], gc);
95                 break;
96             case PathIterator.SEG_LINETO:
97                 d.append(PATH_LINE_TO);
98                 appendPoint(d, seg[0], seg[1], gc);
99                 break;
100             case PathIterator.SEG_CLOSE:
101                 d.append(PATH_CLOSE);
102                 break;
103             case PathIterator.SEG_QUADTO:
104                 d.append(PATH_QUAD_TO);
105                 appendPoint(d, seg[0], seg[1], gc);
106                 appendPoint(d, seg[2], seg[3], gc);
107                 break;
108             case PathIterator.SEG_CUBICTO:
109                 d.append(PATH_CUBIC_TO);
110                 appendPoint(d, seg[0], seg[1], gc);
111                 appendPoint(d, seg[2], seg[3], gc);
112                 appendPoint(d, seg[4], seg[5], gc);
113                 break;
114             default:
115                 throw new Error JavaDoc();
116             }
117             pi.next();
118         } // while !isDone
119

120         if (d.length() > 0)
121             return d.toString().trim();
122         else {
123             // This is a degenerate case: there was no initial moveTo
124
// in the path and no data at all. However, this happens
125
// in the Java 2D API (e.g., when clipping to a rectangle
126
// with negative height/width, the clip will be a GeneralPath
127
// with no data, which causes everything to be clipped)
128
// It is the responsibility of the users of SVGPath to detect
129
// instances where the converted element (see #toSVG above)
130
// returns null, which only happens for degenerate cases.
131
return "";
132         }
133     }
134
135     /**
136      * Appends a coordinate to the path data
137      */

138     private static void appendPoint(StringBuffer JavaDoc d, float x, float y, SVGGeneratorContext gc) {
139         d.append(gc.doubleString(x));
140         d.append(SPACE);
141         d.append(gc.doubleString(y));
142         d.append(SPACE);
143     }
144 }
145
Popular Tags