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.Color;
022: import java.awt.Paint;
023: import java.awt.geom.Rectangle2D;
024: import java.util.Map;
025:
026: import org.apache.batik.ext.awt.image.PadMode;
027: import org.apache.batik.ext.awt.image.renderable.Filter;
028: import org.apache.batik.ext.awt.image.renderable.FilterAlphaRable;
029: import org.apache.batik.ext.awt.image.renderable.FilterColorInterpolation;
030: import org.apache.batik.ext.awt.image.renderable.FloodRable8Bit;
031: import org.apache.batik.ext.awt.image.renderable.PadRable8Bit;
032: import org.apache.batik.gvt.GraphicsNode;
033: import org.apache.batik.gvt.filter.BackgroundRable8Bit;
034: import org.w3c.dom.Element;
035:
036: /**
037: * The base bridge class for SVG filter primitives.
038: *
039: * @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
040: * @version $Id: AbstractSVGFilterPrimitiveElementBridge.java 501922 2007-01-31 17:47:47Z dvholten $
041: */
042: public abstract class AbstractSVGFilterPrimitiveElementBridge extends
043: AnimatableGenericSVGBridge implements FilterPrimitiveBridge,
044: ErrorConstants {
045:
046: /**
047: * Constructs a new bridge for a filter primitive element.
048: */
049: protected AbstractSVGFilterPrimitiveElementBridge() {
050: }
051:
052: /**
053: * Returns the input source of the specified filter primitive
054: * element defined by its 'in' attribute.
055: *
056: * @param filterElement the filter primitive element
057: * @param filteredElement the element on which the filter is referenced
058: * @param filteredNode the graphics node on which the filter is applied
059: * @param inputFilter the default input filter
060: * @param filterMap the map that containes the named filter primitives
061: * @param ctx the bridge context
062: */
063: protected static Filter getIn(Element filterElement,
064: Element filteredElement, GraphicsNode filteredNode,
065: Filter inputFilter, Map filterMap, BridgeContext ctx) {
066:
067: String s = filterElement.getAttributeNS(null, SVG_IN_ATTRIBUTE);
068: if (s.length() == 0) {
069: return inputFilter;
070: } else {
071: return getFilterSource(filterElement, s, filteredElement,
072: filteredNode, filterMap, ctx);
073: }
074: }
075:
076: /**
077: * Returns the input source of the specified filter primitive
078: * element defined by its 'in2' attribute. The 'in2' attribute is assumed
079: * to be required if the subclasses ask for it.
080: *
081: * @param filterElement the filter primitive element
082: * @param filteredElement the element on which the filter is referenced
083: * @param filteredNode the graphics node on which the filter is applied
084: * @param inputFilter the default input filter
085: * @param filterMap the map that containes the named filter primitives
086: * @param ctx the bridge context
087: */
088: protected static Filter getIn2(Element filterElement,
089: Element filteredElement, GraphicsNode filteredNode,
090: Filter inputFilter, Map filterMap, BridgeContext ctx) {
091:
092: String s = filterElement
093: .getAttributeNS(null, SVG_IN2_ATTRIBUTE);
094: if (s.length() == 0) {
095: throw new BridgeException(ctx, filterElement,
096: ERR_ATTRIBUTE_MISSING,
097: new Object[] { SVG_IN2_ATTRIBUTE });
098: }
099: return getFilterSource(filterElement, s, filteredElement,
100: filteredNode, filterMap, ctx);
101: }
102:
103: /**
104: * Updates the filterMap according to the specified parameters.
105: *
106: * @param filterElement the filter primitive element
107: * @param filter the filter that is part of the filter chain
108: * @param filterMap the filter map to update
109: */
110: protected static void updateFilterMap(Element filterElement,
111: Filter filter, Map filterMap) {
112:
113: String s = filterElement.getAttributeNS(null,
114: SVG_RESULT_ATTRIBUTE);
115: if ((s.length() != 0) && (s.trim().length() != 0)) {
116: filterMap.put(s, filter);
117: }
118: }
119:
120: /**
121: * Handles the 'color-interpolation-filters' CSS property.
122: *
123: * @param filter the filter
124: * @param filterElement the filter element
125: */
126: protected static void handleColorInterpolationFilters(
127: Filter filter, Element filterElement) {
128: if (filter instanceof FilterColorInterpolation) {
129: boolean isLinear = CSSUtilities
130: .convertColorInterpolationFilters(filterElement);
131: // System.out.println("IsLinear: " + isLinear +
132: // " Filter: " + filter);
133: ((FilterColorInterpolation) filter)
134: .setColorSpaceLinear(isLinear);
135: }
136: }
137:
138: /**
139: * Returns the filter source according to the specified parameters.
140: *
141: * @param filterElement the filter element
142: * @param s the input of the filter primitive
143: * @param filteredElement the filtered element
144: * @param filteredNode the filtered graphics node
145: * @param filterMap the filter map that contains named filter primitives
146: * @param ctx the bridge context
147: */
148: static Filter getFilterSource(Element filterElement, String s,
149: Element filteredElement, GraphicsNode filteredNode,
150: Map filterMap, BridgeContext ctx) {
151:
152: // SourceGraphic
153: Filter srcG = (Filter) filterMap.get(SVG_SOURCE_GRAPHIC_VALUE);
154: Rectangle2D filterRegion = srcG.getBounds2D();
155:
156: int length = s.length();
157: Filter source = null;
158: switch (length) {
159: case 13:
160: if (SVG_SOURCE_GRAPHIC_VALUE.equals(s)) {
161: // SourceGraphic
162: source = srcG;
163: }
164: break;
165: case 11:
166: if (s.charAt(1) == SVG_SOURCE_ALPHA_VALUE.charAt(1)) {
167: if (SVG_SOURCE_ALPHA_VALUE.equals(s)) {
168: // SourceAlpha
169: source = srcG;
170: source = new FilterAlphaRable(source);
171: }
172: } else if (SVG_STROKE_PAINT_VALUE.equals(s)) {
173: // StrokePaint
174: Paint paint = PaintServer.convertStrokePaint(
175: filteredElement, filteredNode, ctx);
176: // <!> FIXME: Should we create a transparent flood ???
177: source = new FloodRable8Bit(filterRegion, paint);
178: }
179: break;
180: case 15:
181: if (s.charAt(10) == SVG_BACKGROUND_IMAGE_VALUE.charAt(10)) {
182: if (SVG_BACKGROUND_IMAGE_VALUE.equals(s)) {
183: // BackgroundImage
184: source = new BackgroundRable8Bit(filteredNode);
185: source = new PadRable8Bit(source, filterRegion,
186: PadMode.ZERO_PAD);
187: }
188: } else if (SVG_BACKGROUND_ALPHA_VALUE.equals(s)) {
189: // BackgroundAlpha
190: source = new BackgroundRable8Bit(filteredNode);
191: source = new FilterAlphaRable(source);
192: source = new PadRable8Bit(source, filterRegion,
193: PadMode.ZERO_PAD);
194: }
195: break;
196: case 9:
197: if (SVG_FILL_PAINT_VALUE.equals(s)) {
198: // FillPaint
199: Paint paint = PaintServer.convertFillPaint(
200: filteredElement, filteredNode, ctx);
201: if (paint == null) {
202: paint = new Color(0, 0, 0, 0); // create a transparent flood
203: }
204: source = new FloodRable8Bit(filterRegion, paint);
205: }
206: break;
207: }
208: if (source == null) {
209: // <identifier>
210: source = (Filter) filterMap.get(s);
211: }
212: return source;
213: }
214:
215: /**
216: * This is a bit of a hack but we set the flood bounds to
217: * -floatmax/2 -> floatmax/2 (should cover the area ok).
218: */
219: static final Rectangle2D INFINITE_FILTER_REGION = new Rectangle2D.Float(
220: -Float.MAX_VALUE / 2, -Float.MAX_VALUE / 2,
221: Float.MAX_VALUE, Float.MAX_VALUE);
222:
223: /**
224: * Converts on the specified filter primitive element, the specified
225: * attribute that represents an integer and with the specified
226: * default value.
227: *
228: * @param filterElement the filter primitive element
229: * @param attrName the name of the attribute
230: * @param defaultValue the default value of the attribute
231: * @param ctx the BridgeContext to use for error information
232: */
233: protected static int convertInteger(Element filterElement,
234: String attrName, int defaultValue, BridgeContext ctx) {
235: String s = filterElement.getAttributeNS(null, attrName);
236: if (s.length() == 0) {
237: return defaultValue;
238: } else {
239: try {
240: return SVGUtilities.convertSVGInteger(s);
241: } catch (NumberFormatException nfEx) {
242: throw new BridgeException(ctx, filterElement, nfEx,
243: ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
244: attrName, s });
245: }
246: }
247: }
248:
249: /**
250: * Converts on the specified filter primitive element, the specified
251: * attribute that represents a float and with the specified
252: * default value.
253: *
254: * @param filterElement the filter primitive element
255: * @param attrName the name of the attribute
256: * @param defaultValue the default value of the attribute
257: * @param ctx the BridgeContext to use for error information
258: */
259: protected static float convertNumber(Element filterElement,
260: String attrName, float defaultValue, BridgeContext ctx) {
261:
262: String s = filterElement.getAttributeNS(null, attrName);
263: if (s.length() == 0) {
264: return defaultValue;
265: } else {
266: try {
267: return SVGUtilities.convertSVGNumber(s);
268: } catch (NumberFormatException nfEx) {
269: throw new BridgeException(ctx, filterElement, nfEx,
270: ERR_ATTRIBUTE_VALUE_MALFORMED, new Object[] {
271: attrName, s, nfEx });
272: }
273: }
274: }
275: }
|