KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > bridge > AbstractSVGGradientElementBridge


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.bridge;
19
20 import java.awt.Color JavaDoc;
21 import java.awt.Paint JavaDoc;
22 import java.awt.geom.AffineTransform JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.LinkedList JavaDoc;
25 import java.util.List JavaDoc;
26
27 import org.apache.batik.dom.svg.SVGOMDocument;
28 import org.apache.batik.dom.util.XLinkSupport;
29 import org.apache.batik.ext.awt.MultipleGradientPaint;
30 import org.apache.batik.gvt.GraphicsNode;
31 import org.apache.batik.util.ParsedURL;
32 import org.w3c.dom.Element JavaDoc;
33 import org.w3c.dom.Node JavaDoc;
34
35 /**
36  * Bridge class for vending gradients.
37  *
38  * @author <a HREF="mailto:tkormann@apache.org">Thierry Kormann</a>
39  * @version $Id: AbstractSVGGradientElementBridge.java,v 1.12 2004/08/18 07:12:30 vhardy Exp $
40  */

41 public abstract class AbstractSVGGradientElementBridge extends AbstractSVGBridge
42     implements PaintBridge, ErrorConstants {
43
44     /**
45      * Constructs a new AbstractSVGGradientElementBridge.
46      */

47     protected AbstractSVGGradientElementBridge() {}
48
49     /**
50      * Creates a <tt>Paint</tt> according to the specified parameters.
51      *
52      * @param ctx the bridge context to use
53      * @param paintElement the element that defines a Paint
54      * @param paintedElement the element referencing the paint
55      * @param paintedNode the graphics node on which the Paint will be applied
56      * @param opacity the opacity of the Paint to create
57      */

58     public Paint JavaDoc createPaint(BridgeContext ctx,
59                              Element JavaDoc paintElement,
60                              Element JavaDoc paintedElement,
61                              GraphicsNode paintedNode,
62                              float opacity) {
63
64         String JavaDoc s;
65
66         // stop elements
67
List JavaDoc stops = extractStop(paintElement, opacity, ctx);
68         // if no stops are defined, painting is the same as 'none'
69
if (stops == null) {
70             return null;
71         }
72         int stopLength = stops.size();
73         // if one stops is defined, painting is the same as a single color
74
if (stopLength == 1) {
75             return ((Stop)stops.get(0)).color;
76         }
77         float [] offsets = new float[stopLength];
78         Color JavaDoc [] colors = new Color JavaDoc[stopLength];
79         Iterator JavaDoc iter = stops.iterator();
80         for (int i=0; iter.hasNext(); ++i) {
81             Stop stop = (Stop)iter.next();
82             offsets[i] = stop.offset;
83             colors[i] = stop.color;
84         }
85
86         // 'spreadMethod' attribute - default is pad
87
MultipleGradientPaint.CycleMethodEnum spreadMethod
88             = MultipleGradientPaint.NO_CYCLE;
89         s = SVGUtilities.getChainableAttributeNS
90             (paintElement, null, SVG_SPREAD_METHOD_ATTRIBUTE, ctx);
91         if (s.length() != 0) {
92             spreadMethod = convertSpreadMethod(paintElement, s);
93         }
94
95         // 'color-interpolation' CSS property
96
MultipleGradientPaint.ColorSpaceEnum colorSpace
97             = CSSUtilities.convertColorInterpolation(paintElement);
98
99         // 'gradientTransform' attribute - default is an Identity matrix
100
AffineTransform JavaDoc transform;
101         s = SVGUtilities.getChainableAttributeNS
102             (paintElement, null, SVG_GRADIENT_TRANSFORM_ATTRIBUTE, ctx);
103         if (s.length() != 0) {
104             transform = SVGUtilities.convertTransform
105                 (paintElement, SVG_GRADIENT_TRANSFORM_ATTRIBUTE, s);
106         } else {
107             transform = new AffineTransform JavaDoc();
108         }
109
110         Paint JavaDoc paint = buildGradient(paintElement,
111                                     paintedElement,
112                                     paintedNode,
113                                     spreadMethod,
114                                     colorSpace,
115                                     transform,
116                                     colors,
117                                     offsets,
118                                     ctx);
119         return paint;
120     }
121
122     /**
123      * Builds a concrete gradient according to the specified parameters.
124      *
125      * @param paintElement the element that defines a Paint
126      * @param paintedElement the element referencing the paint
127      * @param paintedNode the graphics node on which the Paint will be applied
128      * @param spreadMethod the spread method
129      * @param colorSpace the color space (sRGB | LinearRGB)
130      * @param transform the gradient transform
131      * @param colors the colors of the gradient
132      * @param offsets the offsets
133      * @param ctx the bridge context to use
134      */

135     protected abstract
136         Paint JavaDoc buildGradient(Element JavaDoc paintElement,
137                             Element JavaDoc paintedElement,
138                             GraphicsNode paintedNode,
139                             MultipleGradientPaint.CycleMethodEnum spreadMethod,
140                             MultipleGradientPaint.ColorSpaceEnum colorSpace,
141                             AffineTransform JavaDoc transform,
142                             Color JavaDoc [] colors,
143                             float [] offsets,
144                             BridgeContext ctx);
145
146     // convenient methods
147

148     /**
149      * Converts the spreadMethod attribute.
150      *
151      * @param paintElement the paint Element with a spreadMethod
152      * @param s the spread method
153      */

154     protected static MultipleGradientPaint.CycleMethodEnum convertSpreadMethod
155         (Element JavaDoc paintElement, String JavaDoc s) {
156         if (SVG_REPEAT_VALUE.equals(s)) {
157             return MultipleGradientPaint.REPEAT;
158         }
159         if (SVG_REFLECT_VALUE.equals(s)) {
160             return MultipleGradientPaint.REFLECT;
161         }
162         if (SVG_PAD_VALUE.equals(s)) {
163             return MultipleGradientPaint.NO_CYCLE;
164         }
165         throw new BridgeException
166             (paintElement, ERR_ATTRIBUTE_VALUE_MALFORMED,
167              new Object JavaDoc[] {SVG_SPREAD_METHOD_ATTRIBUTE, s});
168     }
169
170     /**
171      * Returns the stops elements of the specified gradient
172      * element. Stops can be children of the gradients or defined on
173      * one of its 'ancestor' (linked with the xlink:href attribute).
174      *
175      * @param paintElement the gradient element
176      * @param opacity the opacity
177      * @param ctx the bridge context to use
178      */

179     protected static List JavaDoc extractStop(Element JavaDoc paintElement,
180                                       float opacity,
181                                       BridgeContext ctx) {
182
183         List JavaDoc refs = new LinkedList JavaDoc();
184         for (;;) {
185             List JavaDoc stops = extractLocalStop(paintElement, opacity, ctx);
186             if (stops != null) {
187                 return stops; // stop elements found, exit
188
}
189             String JavaDoc uri = XLinkSupport.getXLinkHref(paintElement);
190             if (uri.length() == 0) {
191                 return null; // no xlink:href found, exit
192
}
193             // check if there is circular dependencies
194
SVGOMDocument doc = (SVGOMDocument)paintElement.getOwnerDocument();
195             ParsedURL purl = new ParsedURL(doc.getURL(), uri);
196             if (!purl.complete())
197                 throw new BridgeException(paintElement,
198                                           ERR_URI_MALFORMED,
199                                           new Object JavaDoc[] {uri});
200
201             if (contains(refs, purl)) {
202                 throw new BridgeException(paintElement,
203                                           ERR_XLINK_HREF_CIRCULAR_DEPENDENCIES,
204                                           new Object JavaDoc[] {uri});
205             }
206             refs.add(purl);
207             paintElement = ctx.getReferencedElement(paintElement, uri);
208         }
209     }
210
211     /**
212      * Returns a list of <tt>Stop</tt> elements, children of the
213      * specified paintElement can have or null if any.
214      *
215      * @param gradientElement the paint element
216      * @param opacity the opacity
217      * @param ctx the bridge context
218      */

219     protected static List JavaDoc extractLocalStop(Element JavaDoc gradientElement,
220                                            float opacity,
221                                            BridgeContext ctx) {
222         LinkedList JavaDoc stops = null;
223         Stop previous = null;
224         for (Node n = gradientElement.getFirstChild();
225              n != null;
226              n = n.getNextSibling()) {
227
228             if ((n.getNodeType() != Node.ELEMENT_NODE)) {
229                 continue;
230             }
231
232             Element JavaDoc e = (Element JavaDoc)n;
233             Bridge bridge = ctx.getBridge(e);
234             if (bridge == null || !(bridge instanceof SVGStopElementBridge)) {
235                 continue;
236             }
237             Stop stop = ((SVGStopElementBridge)bridge).createStop
238                 (ctx, gradientElement, e, opacity);
239             if (stops == null) {
240                 stops = new LinkedList JavaDoc();
241             }
242             if (previous != null) {
243                 if (stop.offset < previous.offset) {
244                     stop.offset = previous.offset;
245                 }
246             }
247             stops.add(stop);
248             previous = stop;
249         }
250         return stops;
251     }
252
253     /**
254      * Returns true if the specified list of URLs contains the specified url.
255      *
256      * @param urls the list of URLs
257      * @param key the url to search for
258      */

259     private static boolean contains(List JavaDoc urls, ParsedURL key) {
260         Iterator JavaDoc iter = urls.iterator();
261         while (iter.hasNext()) {
262             if (key.equals(iter.next()))
263                 return true;
264         }
265         return false;
266     }
267
268     /**
269      * This class represents a gradient &lt;stop> element.
270      */

271     public static class Stop {
272
273         /** The stop color. */
274         public Color JavaDoc color;
275         /** The stop offset. */
276         public float offset;
277
278         /**
279          * Constructs a new stop definition.
280          *
281          * @param color the stop color
282          * @param offset the stop offset
283          */

284         public Stop(Color JavaDoc color, float offset) {
285             this.color = color;
286             this.offset = offset;
287         }
288     }
289
290     /**
291      * Bridge class for the gradient &lt;stop> element.
292      */

293     public static class SVGStopElementBridge extends AbstractSVGBridge
294         implements Bridge {
295
296         /**
297          * Returns 'stop'.
298          */

299         public String JavaDoc getLocalName() {
300             return SVG_STOP_TAG;
301         }
302
303         /**
304          * Creates a <tt>Stop</tt> according to the specified parameters.
305          *
306          * @param ctx the bridge context to use
307          * @param gradientElement the gradient element
308          * @param stopElement the stop element
309          * @param opacity an additional opacity of the stop color
310          */

311         public Stop createStop(BridgeContext ctx,
312                                Element JavaDoc gradientElement,
313                                Element JavaDoc stopElement,
314                                float opacity) {
315
316             String JavaDoc s = stopElement.getAttributeNS(null, SVG_OFFSET_ATTRIBUTE);
317             if (s.length() == 0) {
318                 throw new BridgeException(stopElement, ERR_ATTRIBUTE_MISSING,
319                                           new Object JavaDoc[] {SVG_OFFSET_ATTRIBUTE});
320             }
321             float offset;
322             try {
323                 offset = SVGUtilities.convertRatio(s);
324             } catch (NumberFormatException JavaDoc ex) {
325                 throw new BridgeException
326                     (stopElement, ERR_ATTRIBUTE_VALUE_MALFORMED,
327                      new Object JavaDoc[] {SVG_OFFSET_ATTRIBUTE, s, ex});
328             }
329             Color JavaDoc color
330                 = CSSUtilities.convertStopColor(stopElement, opacity, ctx);
331
332             return new Stop(color, offset);
333         }
334     }
335 }
336
Popular Tags