KickJava   Java API By Example, From Geeks To Geeks.

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


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.geom.AffineTransform JavaDoc;
21 import java.awt.geom.NoninvertibleTransformException JavaDoc;
22 import java.awt.geom.Rectangle2D JavaDoc;
23 import java.util.Map JavaDoc;
24
25 import org.apache.batik.dom.util.XLinkSupport;
26 import org.apache.batik.util.XMLConstants;
27 import org.apache.batik.ext.awt.image.PadMode;
28 import org.apache.batik.ext.awt.image.renderable.AffineRable8Bit;
29 import org.apache.batik.ext.awt.image.renderable.Filter;
30 import org.apache.batik.ext.awt.image.renderable.PadRable8Bit;
31 import org.apache.batik.ext.awt.image.spi.ImageTagRegistry;
32 import org.apache.batik.gvt.GraphicsNode;
33 import org.apache.batik.util.ParsedURL;
34 import org.w3c.dom.Document JavaDoc;
35 import org.w3c.dom.Element JavaDoc;
36
37 /**
38  * Bridge class for the <feImage> element.
39  *
40  * @author <a HREF="mailto:tkormann@apache.org">Thierry Kormann</a>
41  * @version $Id: SVGFeImageElementBridge.java,v 1.23 2005/03/27 08:58:30 cam Exp $
42  */

43 public class SVGFeImageElementBridge
44     extends AbstractSVGFilterPrimitiveElementBridge {
45
46     /**
47      * Constructs a new bridge for the &lt;feImage> element.
48      */

49     public SVGFeImageElementBridge() {}
50
51     /**
52      * Returns 'feImage'.
53      */

54     public String JavaDoc getLocalName() {
55         return SVG_FE_IMAGE_TAG;
56     }
57
58     /**
59      * Creates a <tt>Filter</tt> primitive according to the specified
60      * parameters.
61      *
62      * @param ctx the bridge context to use
63      * @param filterElement the element that defines a filter
64      * @param filteredElement the element that references the filter
65      * @param filteredNode the graphics node to filter
66      *
67      * @param inputFilter the <tt>Filter</tt> that represents the current
68      * filter input if the filter chain.
69      * @param filterRegion the filter area defined for the filter chain
70      * the new node will be part of.
71      * @param filterMap a map where the mediator can map a name to the
72      * <tt>Filter</tt> it creates. Other <tt>FilterBridge</tt>s
73      * can then access a filter node from the filterMap if they
74      * know its name.
75      */

76     public Filter createFilter(BridgeContext ctx,
77                                Element JavaDoc filterElement,
78                                Element JavaDoc filteredElement,
79                                GraphicsNode filteredNode,
80                                Filter inputFilter,
81                                Rectangle2D JavaDoc filterRegion,
82                                Map JavaDoc filterMap) {
83
84         // 'xlink:href' attribute
85
String JavaDoc uriStr = XLinkSupport.getXLinkHref(filterElement);
86         if (uriStr.length() == 0) {
87             throw new BridgeException(filterElement, ERR_ATTRIBUTE_MISSING,
88                                       new Object JavaDoc[] {"xlink:href"});
89         }
90
91         //
92
// According the the SVG specification, feImage behaves like
93
// <image> if it references an SVG document or a raster image
94
// and it behaves like a <use> if it references a document
95
// fragment.
96
//
97
// To provide this behavior, depending on whether the uri
98
// contains a fragment identifier, we create either an
99
// <image> or a <use> element and request the corresponding
100
// bridges to build the corresponding GraphicsNode for us.
101
//
102
// Then, we take care of the possible transformation needed
103
// from objectBoundingBox space to user space.
104
//
105

106         Document JavaDoc document = filterElement.getOwnerDocument();
107         boolean isUse = (uriStr.indexOf("#") != -1);
108         Element JavaDoc contentElement = null;
109         if (isUse) {
110             contentElement = document.createElementNS(SVG_NAMESPACE_URI,
111                                                     SVG_USE_TAG);
112         } else {
113             contentElement = document.createElementNS(SVG_NAMESPACE_URI,
114                                                     SVG_IMAGE_TAG);
115         }
116
117         
118         contentElement.setAttributeNS(XLinkSupport.XLINK_NAMESPACE_URI, XMLConstants.XLINK_PREFIX +
119                                     ":" + SVG_HREF_ATTRIBUTE,
120                                     uriStr);
121
122         Element JavaDoc proxyElement = document.createElementNS(SVG_NAMESPACE_URI,
123                                                         SVG_G_TAG);
124         proxyElement.appendChild(contentElement);
125
126         // feImage's default region is that of the filter chain.
127
Rectangle2D JavaDoc defaultRegion = filterRegion;
128
129         // Compute the transform from object bounding box to user
130
// space if needed.
131
AffineTransform JavaDoc at = new AffineTransform JavaDoc();
132
133         // 'primitiveUnits' attribute - default is userSpaceOnUse
134
short coordSystemType;
135         Element JavaDoc filterDefElement = (Element JavaDoc)(filterElement.getParentNode());
136         boolean isBBox = false;
137         String JavaDoc s = SVGUtilities.getChainableAttributeNS
138             (filterDefElement, null, SVG_PRIMITIVE_UNITS_ATTRIBUTE, ctx);
139         if (s.length() == 0) {
140             coordSystemType = SVGUtilities.USER_SPACE_ON_USE;
141         } else {
142                 coordSystemType = SVGUtilities.parseCoordinateSystem
143                     (filterDefElement, SVG_PRIMITIVE_UNITS_ATTRIBUTE, s);
144         }
145         
146         if (coordSystemType == SVGUtilities.OBJECT_BOUNDING_BOX) {
147             isBBox = true;
148             at = SVGUtilities.toObjectBBox(at, filteredNode);
149         }
150         
151         // get filter primitive chain region
152
Rectangle2D JavaDoc primitiveRegionUserSpace
153             = SVGUtilities.convertFilterPrimitiveRegion(filterElement,
154                                                         filteredElement,
155                                                         filteredNode,
156                                                         defaultRegion,
157                                                         filterRegion,
158                                                         ctx);
159         Rectangle2D JavaDoc primitiveRegion = primitiveRegionUserSpace;
160
161         if (isBBox) {
162             try {
163                 AffineTransform JavaDoc ati = at.createInverse();
164                 primitiveRegion = ati.createTransformedShape(primitiveRegion).getBounds2D();
165             } catch (NoninvertibleTransformException JavaDoc nite) {
166                 // Should never happen, seem above
167
throw new Error JavaDoc();
168             }
169         }
170
171         contentElement.setAttributeNS(null, SVG_X_ATTRIBUTE, "" + primitiveRegion.getX());
172         contentElement.setAttributeNS(null, SVG_Y_ATTRIBUTE, "" + primitiveRegion.getY());
173         contentElement.setAttributeNS(null, SVG_WIDTH_ATTRIBUTE, "" + primitiveRegion.getWidth());
174         contentElement.setAttributeNS(null, SVG_HEIGHT_ATTRIBUTE, "" + primitiveRegion.getHeight());
175         
176         // System.err.println(">>>>>>>>>>>> primitiveRegion : " + primitiveRegion);
177
// System.err.println(">>>>>>>>>>>> at : " + at);
178

179         GraphicsNode node = ctx.getGVTBuilder().build(ctx, proxyElement);
180         Filter filter = node.getGraphicsNodeRable(true);
181         
182         filter = new AffineRable8Bit(filter, at);
183
184         // handle the 'color-interpolation-filters' property
185
handleColorInterpolationFilters(filter, filterElement);
186
187         filter = new PadRable8Bit(filter, primitiveRegionUserSpace, PadMode.ZERO_PAD);
188
189         // update the filter Map
190
updateFilterMap(filterElement, filter, filterMap);
191
192         return filter;
193     }
194
195     /**
196      * Returns a Filter that represents a svg document or element as an image.
197      *
198      * @param ctx the bridge context
199      * @param primitiveRegion the primitive region
200      * @param refElement the referenced element
201      * @param toBBoxNeeded true if there is a need to transform to ObjectBoundingBox
202      * space
203      * @param filterElement parent filter element
204      * @param filteredNode node to which the filter applies
205      */

206     protected static Filter createSVGFeImage(BridgeContext ctx,
207                                              Rectangle2D JavaDoc primitiveRegion,
208                                              Element JavaDoc refElement,
209                                              boolean toBBoxNeeded,
210                                              Element JavaDoc filterElement,
211                                              GraphicsNode filteredNode) {
212
213         //
214
// <!> FIX ME
215
// Unresolved issue on the feImage behavior when referencing an
216
// image (PNG, JPEG or SVG image).
217
// VH & TK, 03/08/2002
218
// Furthermore, for feImage referencing doc fragment, should act
219
// like a <use>, i.e., CSS cascading and the whole zing bang.
220
//
221
GraphicsNode node = ctx.getGVTBuilder().build(ctx, refElement);
222         Filter filter = node.getGraphicsNodeRable(true);
223
224         AffineTransform JavaDoc at = new AffineTransform JavaDoc();
225
226         if (toBBoxNeeded){
227             // 'primitiveUnits' attribute - default is userSpaceOnUse
228
short coordSystemType;
229             Element JavaDoc filterDefElement = (Element JavaDoc)(filterElement.getParentNode());
230             String JavaDoc s = SVGUtilities.getChainableAttributeNS
231                 (filterDefElement, null, SVG_PRIMITIVE_UNITS_ATTRIBUTE, ctx);
232             if (s.length() == 0) {
233                 coordSystemType = SVGUtilities.USER_SPACE_ON_USE;
234             } else {
235                 coordSystemType = SVGUtilities.parseCoordinateSystem
236                     (filterDefElement, SVG_PRIMITIVE_UNITS_ATTRIBUTE, s);
237             }
238             
239             if (coordSystemType == SVGUtilities.OBJECT_BOUNDING_BOX) {
240                 at = SVGUtilities.toObjectBBox(at, filteredNode);
241             }
242
243             Rectangle2D JavaDoc bounds = filteredNode.getGeometryBounds();
244             at.preConcatenate(AffineTransform.getTranslateInstance
245                               (primitiveRegion.getX() - bounds.getX(),
246                                primitiveRegion.getY() - bounds.getY()));
247             
248         } else {
249             
250             // Need to translate the image to the x, y coordinate to
251
// have the same behavior as the <use> element
252
at.translate(primitiveRegion.getX(), primitiveRegion.getY());
253         }
254
255         return new AffineRable8Bit(filter, at);
256     }
257
258     /**
259      * Returns a Filter that represents an raster image (JPG or PNG).
260      *
261      * @param ctx the bridge context
262      * @param primitiveRegion the primitive region
263      * @param purl the url of the image
264      */

265     protected static Filter createRasterFeImage(BridgeContext ctx,
266                                                 Rectangle2D JavaDoc primitiveRegion,
267                                                 ParsedURL purl) {
268
269         // Need to fit the raster image to the filter region so that
270
// we have the same behavior as raster images in the <image> element.
271
Filter filter = ImageTagRegistry.getRegistry().readURL(purl);
272
273         Rectangle2D JavaDoc bounds = filter.getBounds2D();
274         AffineTransform JavaDoc scale = new AffineTransform JavaDoc();
275         scale.translate(primitiveRegion.getX(), primitiveRegion.getY());
276         scale.scale(primitiveRegion.getWidth()/(bounds.getWidth()-1),
277                     primitiveRegion.getHeight()/(bounds.getHeight()-1));
278         scale.translate(-bounds.getX(), -bounds.getY());
279
280         return new AffineRable8Bit(filter, scale);
281     }
282 }
283
Popular Tags