| /* |
| |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| |
| */ |
| package org.apache.batik.bridge; |
| |
| import java.awt.Color; |
| import java.awt.Paint; |
| import java.awt.geom.Rectangle2D; |
| import java.util.Map; |
| |
| import org.apache.batik.ext.awt.image.PadMode; |
| import org.apache.batik.ext.awt.image.renderable.Filter; |
| import org.apache.batik.ext.awt.image.renderable.FilterAlphaRable; |
| import org.apache.batik.ext.awt.image.renderable.FilterColorInterpolation; |
| import org.apache.batik.ext.awt.image.renderable.FloodRable8Bit; |
| import org.apache.batik.ext.awt.image.renderable.PadRable8Bit; |
| import org.apache.batik.gvt.GraphicsNode; |
| import org.apache.batik.gvt.filter.BackgroundRable8Bit; |
| import org.w3c.dom.Element; |
| |
| /** |
| * The base bridge class for SVG filter primitives. |
| * |
| * @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a> |
| * @version $Id$ |
| */ |
| public abstract class AbstractSVGFilterPrimitiveElementBridge |
| extends AnimatableGenericSVGBridge |
| implements FilterPrimitiveBridge, ErrorConstants { |
| |
| /** |
| * Constructs a new bridge for a filter primitive element. |
| */ |
| protected AbstractSVGFilterPrimitiveElementBridge() {} |
| |
| /** |
| * Returns the input source of the specified filter primitive |
| * element defined by its 'in' attribute. |
| * |
| * @param filterElement the filter primitive element |
| * @param filteredElement the element on which the filter is referenced |
| * @param filteredNode the graphics node on which the filter is applied |
| * @param inputFilter the default input filter |
| * @param filterMap the map that containes the named filter primitives |
| * @param ctx the bridge context |
| */ |
| protected static Filter getIn(Element filterElement, |
| Element filteredElement, |
| GraphicsNode filteredNode, |
| Filter inputFilter, |
| Map filterMap, |
| BridgeContext ctx) { |
| |
| String s = filterElement.getAttributeNS(null, SVG_IN_ATTRIBUTE); |
| if (s.length() == 0) { |
| return inputFilter; |
| } else { |
| return getFilterSource(filterElement, |
| s, |
| filteredElement, |
| filteredNode, |
| filterMap, |
| ctx); |
| } |
| } |
| |
| /** |
| * Returns the input source of the specified filter primitive |
| * element defined by its 'in2' attribute. The 'in2' attribute is assumed |
| * to be required if the subclasses ask for it. |
| * |
| * @param filterElement the filter primitive element |
| * @param filteredElement the element on which the filter is referenced |
| * @param filteredNode the graphics node on which the filter is applied |
| * @param inputFilter the default input filter |
| * @param filterMap the map that containes the named filter primitives |
| * @param ctx the bridge context |
| */ |
| protected static Filter getIn2(Element filterElement, |
| Element filteredElement, |
| GraphicsNode filteredNode, |
| Filter inputFilter, |
| Map filterMap, |
| BridgeContext ctx) { |
| |
| String s = filterElement.getAttributeNS(null, SVG_IN2_ATTRIBUTE); |
| if (s.length() == 0) { |
| throw new BridgeException(ctx, filterElement, ERR_ATTRIBUTE_MISSING, |
| new Object [] {SVG_IN2_ATTRIBUTE}); |
| } |
| return getFilterSource(filterElement, |
| s, |
| filteredElement, |
| filteredNode, |
| filterMap, |
| ctx); |
| } |
| |
| /** |
| * Updates the filterMap according to the specified parameters. |
| * |
| * @param filterElement the filter primitive element |
| * @param filter the filter that is part of the filter chain |
| * @param filterMap the filter map to update |
| */ |
| protected static void updateFilterMap(Element filterElement, |
| Filter filter, |
| Map filterMap) { |
| |
| String s = filterElement.getAttributeNS(null, SVG_RESULT_ATTRIBUTE); |
| if ((s.length() != 0) && (s.trim().length() != 0)) { |
| filterMap.put(s, filter); |
| } |
| } |
| |
| /** |
| * Handles the 'color-interpolation-filters' CSS property. |
| * |
| * @param filter the filter |
| * @param filterElement the filter element |
| */ |
| protected static void handleColorInterpolationFilters(Filter filter, |
| Element filterElement) { |
| if (filter instanceof FilterColorInterpolation) { |
| boolean isLinear |
| = CSSUtilities.convertColorInterpolationFilters(filterElement); |
| // System.out.println("IsLinear: " + isLinear + |
| // " Filter: " + filter); |
| ((FilterColorInterpolation)filter).setColorSpaceLinear(isLinear); |
| } |
| } |
| |
| /** |
| * Returns the filter source according to the specified parameters. |
| * |
| * @param filterElement the filter element |
| * @param s the input of the filter primitive |
| * @param filteredElement the filtered element |
| * @param filteredNode the filtered graphics node |
| * @param filterMap the filter map that contains named filter primitives |
| * @param ctx the bridge context |
| */ |
| static Filter getFilterSource(Element filterElement, |
| String s, |
| Element filteredElement, |
| GraphicsNode filteredNode, |
| Map filterMap, |
| BridgeContext ctx) { |
| |
| // SourceGraphic |
| Filter srcG = (Filter)filterMap.get(SVG_SOURCE_GRAPHIC_VALUE); |
| Rectangle2D filterRegion = srcG.getBounds2D(); |
| |
| int length = s.length(); |
| Filter source = null; |
| switch (length) { |
| case 13: |
| if (SVG_SOURCE_GRAPHIC_VALUE.equals(s)) { |
| // SourceGraphic |
| source = srcG; |
| } |
| break; |
| case 11: |
| if (s.charAt(1) == SVG_SOURCE_ALPHA_VALUE.charAt(1)) { |
| if (SVG_SOURCE_ALPHA_VALUE.equals(s)) { |
| // SourceAlpha |
| source = srcG; |
| source = new FilterAlphaRable(source); |
| } |
| } else if (SVG_STROKE_PAINT_VALUE.equals(s)) { |
| // StrokePaint |
| Paint paint = PaintServer.convertStrokePaint |
| (filteredElement,filteredNode, ctx); |
| // <!> FIXME: Should we create a transparent flood ??? |
| source = new FloodRable8Bit(filterRegion, paint); |
| } |
| break; |
| case 15: |
| if (s.charAt(10) == SVG_BACKGROUND_IMAGE_VALUE.charAt(10)) { |
| if (SVG_BACKGROUND_IMAGE_VALUE.equals(s)) { |
| // BackgroundImage |
| source = new BackgroundRable8Bit(filteredNode); |
| source = new PadRable8Bit(source, filterRegion, |
| PadMode.ZERO_PAD); |
| } |
| } else if (SVG_BACKGROUND_ALPHA_VALUE.equals(s)) { |
| // BackgroundAlpha |
| source = new BackgroundRable8Bit(filteredNode); |
| source = new FilterAlphaRable(source); |
| source = new PadRable8Bit(source, filterRegion, |
| PadMode.ZERO_PAD); |
| } |
| break; |
| case 9: |
| if (SVG_FILL_PAINT_VALUE.equals(s)) { |
| // FillPaint |
| Paint paint = PaintServer.convertFillPaint |
| (filteredElement,filteredNode, ctx); |
| if (paint == null) { |
| paint = new Color(0, 0, 0, 0); // create a transparent flood |
| } |
| source = new FloodRable8Bit(filterRegion, paint); |
| } |
| break; |
| } |
| if (source == null) { |
| // <identifier> |
| source = (Filter)filterMap.get(s); |
| } |
| return source; |
| } |
| |
| /** |
| * This is a bit of a hack but we set the flood bounds to |
| * -floatmax/2 -> floatmax/2 (should cover the area ok). |
| */ |
| static final Rectangle2D INFINITE_FILTER_REGION |
| = new Rectangle2D.Float(-Float.MAX_VALUE/2, |
| -Float.MAX_VALUE/2, |
| Float.MAX_VALUE, |
| Float.MAX_VALUE); |
| |
| |
| |
| /** |
| * Converts on the specified filter primitive element, the specified |
| * attribute that represents an integer and with the specified |
| * default value. |
| * |
| * @param filterElement the filter primitive element |
| * @param attrName the name of the attribute |
| * @param defaultValue the default value of the attribute |
| * @param ctx the BridgeContext to use for error information |
| */ |
| protected static int convertInteger(Element filterElement, |
| String attrName, |
| int defaultValue, |
| BridgeContext ctx) { |
| String s = filterElement.getAttributeNS(null, attrName); |
| if (s.length() == 0) { |
| return defaultValue; |
| } else { |
| try { |
| return SVGUtilities.convertSVGInteger(s); |
| } catch (NumberFormatException nfEx ) { |
| throw new BridgeException |
| (ctx, filterElement, nfEx, ERR_ATTRIBUTE_VALUE_MALFORMED, |
| new Object[] {attrName, s}); |
| } |
| } |
| } |
| |
| /** |
| * Converts on the specified filter primitive element, the specified |
| * attribute that represents a float and with the specified |
| * default value. |
| * |
| * @param filterElement the filter primitive element |
| * @param attrName the name of the attribute |
| * @param defaultValue the default value of the attribute |
| * @param ctx the BridgeContext to use for error information |
| */ |
| protected static float convertNumber(Element filterElement, |
| String attrName, |
| float defaultValue, |
| BridgeContext ctx) { |
| |
| String s = filterElement.getAttributeNS(null, attrName); |
| if (s.length() == 0) { |
| return defaultValue; |
| } else { |
| try { |
| return SVGUtilities.convertSVGNumber(s); |
| } catch (NumberFormatException nfEx) { |
| throw new BridgeException |
| (ctx, filterElement, nfEx, ERR_ATTRIBUTE_VALUE_MALFORMED, |
| new Object[] {attrName, s, nfEx}); |
| } |
| } |
| } |
| } |