blob: 3c9d6abb9eaf6be39fd4a8ec43efec6d9fb155e3 [file] [log] [blame]
/*
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});
}
}
}
}