KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Copyright 2001-2004 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.Graphics2D JavaDoc;
21 import java.awt.Paint JavaDoc;
22 import java.awt.Shape JavaDoc;
23 import java.awt.geom.AffineTransform JavaDoc;
24 import java.awt.geom.Rectangle2D JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.LinkedList JavaDoc;
27 import java.util.List JavaDoc;
28
29 import org.apache.batik.dom.svg.SVGOMDocument;
30 import org.apache.batik.dom.util.XLinkSupport;
31 import org.apache.batik.ext.awt.image.ConcreteComponentTransferFunction;
32 import org.apache.batik.ext.awt.image.renderable.ComponentTransferRable8Bit;
33 import org.apache.batik.ext.awt.image.renderable.Filter;
34 import org.apache.batik.gvt.AbstractGraphicsNode;
35 import org.apache.batik.gvt.RootGraphicsNode;
36 import org.apache.batik.gvt.GraphicsNode;
37 import org.apache.batik.gvt.PatternPaint;
38 import org.apache.batik.util.ParsedURL;
39 import org.w3c.dom.Element JavaDoc;
40 import org.w3c.dom.Node JavaDoc;
41
42 /**
43  * Bridge class for the <pattern> element.
44  *
45  * @author <a HREF="mailto:tkormann@apache.org">Thierry Kormann</a>
46  * @version $Id: SVGPatternElementBridge.java,v 1.27 2004/08/18 07:12:35 vhardy Exp $
47  */

48 public class SVGPatternElementBridge extends AbstractSVGBridge
49     implements PaintBridge, ErrorConstants {
50
51     /**
52      * Constructs a new SVGPatternElementBridge.
53      */

54     public SVGPatternElementBridge() {}
55
56     /**
57      * Returns 'pattern'.
58      */

59     public String JavaDoc getLocalName() {
60         return SVG_PATTERN_TAG;
61     }
62
63     /**
64      * Creates a <tt>Paint</tt> according to the specified parameters.
65      *
66      * @param ctx the bridge context to use
67      * @param patternElement the pattern element that defines a Paint
68      * @param paintedElement the element referencing the paint
69      * @param paintedNode the graphics node on which the Paint will be applied
70      * @param opacity the opacity of the Paint to create
71      */

72     public Paint JavaDoc createPaint(BridgeContext ctx,
73                              Element JavaDoc patternElement,
74                              Element JavaDoc paintedElement,
75                              GraphicsNode paintedNode,
76                              float opacity) {
77
78
79         // extract pattern content
80
RootGraphicsNode patternContentNode;
81         patternContentNode = (RootGraphicsNode)
82             ctx.getElementData(patternElement);
83
84         if (patternContentNode == null) {
85             patternContentNode = extractPatternContent(patternElement, ctx);
86             ctx.setElementData(patternElement, patternContentNode);
87         }
88         if (patternContentNode == null) {
89             return null; // no content means no paint
90
}
91
92         // get pattern region using 'patternUnits'. Pattern region is
93
// in tile pace.
94
Rectangle2D JavaDoc patternRegion = SVGUtilities.convertPatternRegion
95             (patternElement, paintedElement, paintedNode, ctx);
96
97         String JavaDoc s;
98
99         // 'patternTransform' attribute - default is an Identity matrix
100
AffineTransform JavaDoc patternTransform;
101         s = SVGUtilities.getChainableAttributeNS
102             (patternElement, null, SVG_PATTERN_TRANSFORM_ATTRIBUTE, ctx);
103         if (s.length() != 0) {
104             patternTransform = SVGUtilities.convertTransform
105                 (patternElement, SVG_PATTERN_TRANSFORM_ATTRIBUTE, s);
106         } else {
107             patternTransform = new AffineTransform JavaDoc();
108         }
109
110         // 'overflow' on the pattern element
111
boolean overflowIsHidden = CSSUtilities.convertOverflow(patternElement);
112
113         // 'patternContentUnits' - default is userSpaceOnUse
114
short contentCoordSystem;
115         s = SVGUtilities.getChainableAttributeNS
116             (patternElement, null, SVG_PATTERN_CONTENT_UNITS_ATTRIBUTE, ctx);
117         if (s.length() == 0) {
118             contentCoordSystem = SVGUtilities.USER_SPACE_ON_USE;
119         } else {
120             contentCoordSystem = SVGUtilities.parseCoordinateSystem
121                 (patternElement, SVG_PATTERN_CONTENT_UNITS_ATTRIBUTE, s);
122         }
123
124         // Compute a transform according to viewBox, preserveAspectRatio
125
// and patternContentUnits and the pattern transform attribute.
126
//
127
// The stack of transforms is:
128
//
129
// +-------------------------------+
130
// | viewPortTranslation |
131
// +-------------------------------+
132
// | preserveAspectRatioTransform |
133
// +-------------------------------+
134
// + patternContentUnitsTransform |
135
// +-------------------------------+
136
//
137
// where:
138
// - viewPortTranslation is the transform that translate to
139
// the viewPort's origin.
140
// - preserveAspectRatioTransform is the transformed implied by the
141
// preserveAspectRatio attribute.
142
// - patternContentUnitsTransform is the transform implied by the
143
// patternContentUnits attribute.
144
//
145
// Note that there is an additional transform from the tiling
146
// space to the user space (patternTransform) that is passed
147
// separately to the PatternPaintContext.
148
//
149
AffineTransform JavaDoc patternContentTransform = new AffineTransform JavaDoc();
150
151         //
152
// Process viewPortTranslation
153
//
154
patternContentTransform.translate(patternRegion.getX(),
155                                           patternRegion.getY());
156
157         //
158
// Process preserveAspectRatioTransform
159
//
160

161         // 'viewBox' attribute
162
String JavaDoc viewBoxStr = SVGUtilities.getChainableAttributeNS
163             (patternElement, null, SVG_VIEW_BOX_ATTRIBUTE, ctx);
164
165         if (viewBoxStr.length() > 0) {
166             // There is a viewBox attribute. Then, take
167
// preserveAspectRatio into account.
168
String JavaDoc aspectRatioStr = SVGUtilities.getChainableAttributeNS
169                (patternElement, null, SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE, ctx);
170             float w = (float)patternRegion.getWidth();
171             float h = (float)patternRegion.getHeight();
172             AffineTransform JavaDoc preserveAspectRatioTransform
173                 = ViewBox.getPreserveAspectRatioTransform
174                 (patternElement, viewBoxStr, aspectRatioStr, w, h);
175
176             patternContentTransform.concatenate(preserveAspectRatioTransform);
177         } else {
178             //
179
// Process patternContentUnitsTransform
180
//
181
if (contentCoordSystem == SVGUtilities.OBJECT_BOUNDING_BOX){
182                 AffineTransform JavaDoc patternContentUnitsTransform
183                     = new AffineTransform JavaDoc();
184                 Rectangle2D JavaDoc objectBoundingBox =
185                     paintedNode.getGeometryBounds();
186                 patternContentUnitsTransform.translate
187                     (objectBoundingBox.getX(),
188                      objectBoundingBox.getY());
189
190                 patternContentUnitsTransform.scale
191                     (objectBoundingBox.getWidth(),
192                      objectBoundingBox.getHeight());
193
194                 patternContentTransform.concatenate
195                     (patternContentUnitsTransform);
196             }
197         }
198
199         //
200
// Apply transform
201
//
202
// RootGraphicsNode gn = new RootGraphicsNode();
203
// gn.getChildren().add(patternContentNode);
204
GraphicsNode gn = new PatternGraphicsNode(patternContentNode);
205         
206         gn.setTransform(patternContentTransform);
207         
208         // take the opacity into account. opacity is implemented by a Filter
209
if (opacity != 1) {
210             Filter filter = gn.getGraphicsNodeRable(true);
211             filter = new ComponentTransferRable8Bit
212                 (filter,
213                  ConcreteComponentTransferFunction.getLinearTransfer
214                  (opacity, 0), //alpha
215
ConcreteComponentTransferFunction.getIdentityTransfer(), //Red
216
ConcreteComponentTransferFunction.getIdentityTransfer(), //Grn
217
ConcreteComponentTransferFunction.getIdentityTransfer());//Blu
218
gn.setFilter(filter);
219         }
220
221         
222
223         return new PatternPaint(gn,
224                                 patternRegion,
225                                 !overflowIsHidden,
226                                 patternTransform);
227
228     }
229
230     /**
231      * Returns the content of the specified pattern element. The
232      * content of the pattern can be specified as children of the
233      * patternElement or children of one of its 'ancestor' (linked with
234      * the xlink:href attribute).
235      *
236      * @param patternElement the gradient element
237      * @param ctx the bridge context to use
238      */

239     protected static
240         RootGraphicsNode extractPatternContent(Element JavaDoc patternElement,
241                                                     BridgeContext ctx) {
242
243         List JavaDoc refs = new LinkedList JavaDoc();
244         for (;;) {
245             RootGraphicsNode content
246                 = extractLocalPatternContent(patternElement, ctx);
247             if (content != null) {
248                 return content; // pattern content found, exit
249
}
250             String JavaDoc uri = XLinkSupport.getXLinkHref(patternElement);
251             if (uri.length() == 0) {
252                 return null; // no xlink:href found, exit
253
}
254             // check if there is circular dependencies
255
SVGOMDocument doc =
256                 (SVGOMDocument)patternElement.getOwnerDocument();
257             ParsedURL purl = new ParsedURL(doc.getURL(), uri);
258             if (!purl.complete())
259                 throw new BridgeException(patternElement,
260                                           ERR_URI_MALFORMED,
261                                           new Object JavaDoc[] {uri});
262
263             if (contains(refs, purl)) {
264                 throw new BridgeException(patternElement,
265                                           ERR_XLINK_HREF_CIRCULAR_DEPENDENCIES,
266                                           new Object JavaDoc[] {uri});
267             }
268             refs.add(purl);
269             patternElement = ctx.getReferencedElement(patternElement, uri);
270         }
271     }
272
273     /**
274      * Returns the content of the specified pattern element or null if any.
275      *
276      * @param e the pattern element
277      * @param ctx the bridge context
278      */

279     protected static
280         RootGraphicsNode extractLocalPatternContent(Element JavaDoc e,
281                                                          BridgeContext ctx) {
282
283         GVTBuilder builder = ctx.getGVTBuilder();
284         RootGraphicsNode content = null;
285         for (Node n = e.getFirstChild(); n != null; n = n.getNextSibling()) {
286             // check if the Node is valid
287
if (n.getNodeType() != Node.ELEMENT_NODE) {
288                 continue;
289             }
290
291             GraphicsNode gn = builder.build(ctx, (Element JavaDoc)n);
292             // check if a GraphicsNode has been created
293
if (gn != null) {
294                 // lazy instantation of the grouping element.
295
if (content == null) {
296                     content = new RootGraphicsNode();
297                 }
298                 content.getChildren().add(gn);
299             }
300         }
301         return content;
302     }
303
304     /**
305      * Returns true if the specified list of ParsedURLs contains the
306      * specified url.
307      *
308      * @param urls the list of ParsedURLs
309      * @param key the url to search for */

310     private static boolean contains(List JavaDoc urls, ParsedURL key) {
311         Iterator JavaDoc iter = urls.iterator();
312         while (iter.hasNext()) {
313             if (key.equals(iter.next()))
314                 return true;
315         }
316         return false;
317     }
318
319     public static class PatternGraphicsNode extends AbstractGraphicsNode {
320         GraphicsNode pcn;
321         Rectangle2D JavaDoc pBounds;
322         Rectangle2D JavaDoc gBounds;
323         Rectangle2D JavaDoc sBounds;
324         Shape JavaDoc oShape;
325         public PatternGraphicsNode(GraphicsNode gn) {
326             this.pcn = gn;
327         }
328         public void primitivePaint(Graphics2D JavaDoc g2d) {
329             pcn.paint(g2d);
330         }
331         public Rectangle2D JavaDoc getPrimitiveBounds() {
332             if (pBounds != null) return pBounds;
333             pBounds = pcn.getTransformedBounds(IDENTITY);
334             return pBounds;
335         }
336         public Rectangle2D JavaDoc getGeometryBounds() {
337             if (gBounds != null) return gBounds;
338             gBounds = pcn.getTransformedGeometryBounds(IDENTITY);
339             return gBounds;
340         }
341         public Rectangle2D JavaDoc getSensitiveBounds() {
342             if (sBounds != null) return sBounds;
343             sBounds = pcn.getTransformedSensitiveBounds(IDENTITY);
344             return sBounds;
345         }
346         public Shape JavaDoc getOutline() {
347             if (oShape != null) return oShape;
348             oShape = pcn.getOutline();
349             AffineTransform JavaDoc tr = pcn.getTransform();
350             if (tr != null)
351                 oShape = tr.createTransformedShape(oShape);
352             return oShape;
353         }
354         protected void invalidateGeometryCache() {
355             pBounds = null;
356             gBounds = null;
357             sBounds = null;
358             oShape = null;
359             super.invalidateGeometryCache();
360         }
361
362     }
363
364 }
365
366
Popular Tags