001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019: package org.apache.batik.bridge;
020:
021: import java.awt.geom.Rectangle2D;
022: import java.util.Iterator;
023: import java.util.LinkedList;
024: import java.util.List;
025: import java.util.Map;
026:
027: import org.apache.batik.ext.awt.image.CompositeRule;
028: import org.apache.batik.ext.awt.image.PadMode;
029: import org.apache.batik.ext.awt.image.renderable.CompositeRable8Bit;
030: import org.apache.batik.ext.awt.image.renderable.Filter;
031: import org.apache.batik.ext.awt.image.renderable.PadRable8Bit;
032: import org.apache.batik.gvt.GraphicsNode;
033: import org.w3c.dom.Element;
034: import org.w3c.dom.Node;
035:
036: /**
037: * Bridge class for the <feMerge> element.
038: *
039: * @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
040: * @version $Id: SVGFeMergeElementBridge.java 475477 2006-11-15 22:44:28Z cam $
041: */
042: public class SVGFeMergeElementBridge extends
043: AbstractSVGFilterPrimitiveElementBridge {
044:
045: /**
046: * Constructs a new bridge for the <feMerge> element.
047: */
048: public SVGFeMergeElementBridge() {
049: }
050:
051: /**
052: * Returns 'feMerge'.
053: */
054: public String getLocalName() {
055: return SVG_FE_MERGE_TAG;
056: }
057:
058: /**
059: * Creates a <tt>Filter</tt> primitive according to the specified
060: * parameters.
061: *
062: * @param ctx the bridge context to use
063: * @param filterElement the element that defines a filter
064: * @param filteredElement the element that references the filter
065: * @param filteredNode the graphics node to filter
066: * @param inputFilter the <tt>Filter</tt> that represents the current
067: * filter input if the filter chain.
068: * @param filterRegion the filter area defined for the filter chain
069: * the new node will be part of.
070: * @param filterMap a map where the mediator can map a name to the
071: * <tt>Filter</tt> it creates. Other <tt>FilterBridge</tt>s
072: * can then access a filter node from the filterMap if they
073: * know its name.
074: */
075: public Filter createFilter(BridgeContext ctx,
076: Element filterElement, Element filteredElement,
077: GraphicsNode filteredNode, Filter inputFilter,
078: Rectangle2D filterRegion, Map filterMap) {
079:
080: List srcs = extractFeMergeNode(filterElement, filteredElement,
081: filteredNode, inputFilter, filterMap, ctx);
082:
083: if (srcs == null) {
084: return null; // <!> FIXME: no subelement found, result unspecified
085: }
086:
087: if (srcs.size() == 0) {
088: return null; // <!> FIXME: no subelement found, result unspecified
089: }
090:
091: // the default region is the input sources regions union
092: Iterator iter = srcs.iterator();
093: Rectangle2D defaultRegion = (Rectangle2D) ((Filter) iter.next())
094: .getBounds2D().clone();
095:
096: while (iter.hasNext()) {
097: defaultRegion.add(((Filter) iter.next()).getBounds2D());
098: }
099:
100: // get filter primitive chain region
101: Rectangle2D primitiveRegion = SVGUtilities
102: .convertFilterPrimitiveRegion(filterElement,
103: filteredElement, filteredNode, defaultRegion,
104: filterRegion, ctx);
105:
106: Filter filter = new CompositeRable8Bit(srcs,
107: CompositeRule.OVER, true);
108:
109: // handle the 'color-interpolation-filters' property
110: handleColorInterpolationFilters(filter, filterElement);
111:
112: filter = new PadRable8Bit(filter, primitiveRegion,
113: PadMode.ZERO_PAD);
114:
115: // update the filter Map
116: updateFilterMap(filterElement, filter, filterMap);
117:
118: return filter;
119: }
120:
121: /**
122: * Returns a list of Filter objects that represents the feMergeNode of
123: * the specified feMerge filter element.
124: *
125: * @param filterElement the feMerge filter element
126: * @param filteredElement the filtered element
127: * @param filteredNode the filtered graphics node
128: * @param inputFilter the <tt>Filter</tt> that represents the current
129: * filter input if the filter chain.
130: * @param filterMap the filter map that contains named filter primitives
131: * @param ctx the bridge context
132: */
133: protected static List extractFeMergeNode(Element filterElement,
134: Element filteredElement, GraphicsNode filteredNode,
135: Filter inputFilter, Map filterMap, BridgeContext ctx) {
136:
137: List srcs = null;
138: for (Node n = filterElement.getFirstChild(); n != null; n = n
139: .getNextSibling()) {
140:
141: if (n.getNodeType() != Node.ELEMENT_NODE) {
142: continue;
143: }
144:
145: Element e = (Element) n;
146: Bridge bridge = ctx.getBridge(e);
147: if (bridge == null
148: || !(bridge instanceof SVGFeMergeNodeElementBridge)) {
149: continue;
150: }
151: Filter filter = ((SVGFeMergeNodeElementBridge) bridge)
152: .createFilter(ctx, e, filteredElement,
153: filteredNode, inputFilter, filterMap);
154: if (filter != null) {
155: if (srcs == null) {
156: srcs = new LinkedList();
157: }
158: srcs.add(filter);
159: }
160: }
161: return srcs;
162: }
163:
164: /**
165: * Bridge class for the <feMergeNode> element.
166: */
167: public static class SVGFeMergeNodeElementBridge extends
168: AnimatableGenericSVGBridge {
169:
170: /**
171: * Constructs a new bridge for the <feMergeNode> element.
172: */
173: public SVGFeMergeNodeElementBridge() {
174: }
175:
176: /**
177: * Returns 'feMergeNode'.
178: */
179: public String getLocalName() {
180: return SVG_FE_MERGE_NODE_TAG;
181: }
182:
183: /**
184: * Creates a <tt>Filter</tt> according to the specified parameters.
185: *
186: * @param ctx the bridge context to use
187: * @param filterElement the element that defines a filter
188: * @param filteredElement the element that references the filter
189: * @param filteredNode the graphics node to filter
190: * @param inputFilter the <tt>Filter</tt> that represents the current
191: * filter input if the filter chain.
192: * @param filterMap a map where the mediator can map a name to the
193: * <tt>Filter</tt> it creates. Other <tt>FilterBridge</tt>s
194: * can then access a filter node from the filterMap if they
195: * know its name.
196: */
197: public Filter createFilter(BridgeContext ctx,
198: Element filterElement, Element filteredElement,
199: GraphicsNode filteredNode, Filter inputFilter,
200: Map filterMap) {
201: return getIn(filterElement, filteredElement, filteredNode,
202: inputFilter, filterMap, ctx);
203: }
204: }
205: }
|