You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-dev@xmlgraphics.apache.org by de...@apache.org on 2001/01/05 16:49:21 UTC
cvs commit: xml-batik/sources/org/apache/batik/util/awt/svg SVGConvolveOp.java
deweese 01/01/05 07:49:21
Modified: resources/org/apache/batik/refimpl/bridge/resources
Messages.properties
sources/org/apache/batik/gvt/filter ConvolveMatrixRable.java
PadMode.java
sources/org/apache/batik/refimpl/bridge
SVGBridgeContext.java
sources/org/apache/batik/refimpl/gvt/filter
ConcreteBackgroundRable.java
ConcreteConvolveMatrixRable.java
ConcreteGaussianBlurRable.java PadRed.java
sources/org/apache/batik/util SVGConstants.java
sources/org/apache/batik/util/awt/svg SVGConvolveOp.java
Added: samples/tests feConvolveMatrix.svg
sources/org/apache/batik/refimpl/bridge
SVGFeConvolveMatrixElementBridge.java
Log:
* Added support for PadMode REPLICATE (AKA duplicate) in PadRed.java
* Fixed a bug in ConcreteBackgroundRable for the case where there
was no child of node with background-enable:true before the child
requesting the background.
* Fixed a few constants in SVGConstants.
* Switched FeConvolveMatrix on (new bridge, almost finished implementation).
Still needs to handle bias (hard), and preserveAlpha (tricky but not
too bad).
* Fixed a few documentation bugs in GaussianBlurRable
* Added Messages for feConvolveMatrix bridge
Revision Changes Path
1.22 +30 -1 xml-batik/resources/org/apache/batik/refimpl/bridge/resources/Messages.properties
Index: Messages.properties
===================================================================
RCS file: /home/cvs/xml-batik/resources/org/apache/batik/refimpl/bridge/resources/Messages.properties,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- Messages.properties 2000/11/29 16:00:38 1.21
+++ Messages.properties 2001/01/05 15:49:16 1.22
@@ -220,7 +220,36 @@
The attribute "in2" on <feComposite> is required
feComposite.operator.invalid = \
-The value "{0}" of the attribute "operator" is invalid
+The value "{0}" of the attribute "operator" on <feComposite> is invalid
+
+##### <feConvolveMatrix> #####
+
+feConvolveMatrix.order.notPosInt = \
+The attribute "order" on <feConvolveMatrix> must contain positive integers(s).
+
+feConvolveMatrix.kernelMatrix.tooMany = \
+The attribute "kernelMatrix" on <feConvolveMatrix> contains too many values.
+
+feConvolveMatrix.kernelMatrix.notEnough = \
+The attribute "kernelMatrix" on <feConvolveMatrix> contains too few values.
+
+feConvolveMatrix.divisor.zero = \
+The attribute "divisor" on <feConvolveMatrix> can not be zero.
+
+feConvolveMatrix.targetX.invalid = \
+The attribute "targetX" on <feConvolveMatrix> must lie within the kernel.
+
+feConvolveMatrix.targetY.invalid = \
+The attribute "targetY" on <feConvolveMatrix> must lie within the kernel.
+
+feConvolveMatrix.edgeMode.invalid = \
+The value "{0}" of the attribute "edgeMode" on <feConvolveMatrix> is invalid.
+
+feConvolveMatrix.kernelUnitLength.notPositive = \
+The attribute "kernelUnitLength" on <feConvolveMatrix> must contain positive number(s).
+
+feConvolveMatrix.preserveAlpha.invalid = \
+The value "{0}" of the attribute "preserveAlpha" on <feConvolveMatrix> is invalid.
##### <feDisplacementMap> #####
1.1 xml-batik/samples/tests/feConvolveMatrix.svg
Index: feConvolveMatrix.svg
===================================================================
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20000802//EN"
"http://www.w3.org/TR/2000/CR-SVG-20000802/DTD/svg-20000802.dtd">
<!-- ========================================================================= -->
<!-- Copyright (C) The Apache Software Foundation. All rights reserved. -->
<!-- -->
<!-- This software is published under the terms of the Apache Software License -->
<!-- version 1.1, a copy of which has been included with this distribution in -->
<!-- the LICENSE file. -->
<!-- ========================================================================= -->
<!-- ========================================================================= -->
<!-- Test description here -->
<!-- -->
<!-- @author deweese@kodak.com -->
<!-- @version $Id $ -->
<!-- ========================================================================= -->
<?xml-stylesheet type="text/css" href="test.css" ?>
<svg id="body" width="450" height="500" viewBox="0 0 450 500">
<title>feMerge Test</title>
<!-- ============================================================= -->
<!-- Test content -->
<!-- ============================================================= -->
<g id="testContent">
<text x="225" y="40" class="title">
feConvolveMatrix Text
</text>
<defs>
<filter id="conv-rep-tr" x="0" y="0" width="1" height="1">
<feConvolveMatrix order="11 11"
kernelMatrix="0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0"
edgeMode="duplicate" />
</filter>
<filter id="conv-centX" x="0" y="0" width="1" height="1">
<feConvolveMatrix order="11 11"
kernelMatrix="0 0 0 0 0 0 0 0 0 0 10
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0"
targetX="10"
edgeMode="duplicate" />
</filter>
<filter id="conv-centY" x="0" y="0" width="1" height="1">
<feConvolveMatrix order="11 11"
kernelMatrix="0 0 0 0 0 0 0 0 0 0 10
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0"
targetY="0"
edgeMode="duplicate" />
</filter>
<filter id="conv-rep-bl" x="0" y="0" width="1" height="1">
<feConvolveMatrix order="11 11"
kernelMatrix="0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0"
edgeMode="duplicate" />
</filter>
<filter id="conv-rep-br" x="0" y="0" width="1" height="1">
<feConvolveMatrix order="11 11"
kernelMatrix="0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1"
edgeMode="duplicate" />
</filter>
<filter id="conv-rep-tl" x="0" y="0" width="1" height="1">
<feConvolveMatrix order="11 11"
kernelMatrix="1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0"
edgeMode="duplicate" />
</filter>
<filter id="conv-none-tr" x="0" y="0" width="1" height="1">
<feConvolveMatrix order="11 11"
kernelMatrix="0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0"
edgeMode="none" />
</filter>
<filter id="conv-none-tl" x="0" y="0" width="1" height="1">
<feConvolveMatrix order="11 11"
kernelMatrix="1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0"
edgeMode="none" />
</filter>
<filter id="conv-none-bl" x="0" y="0" width="1" height="1">
<feConvolveMatrix order="11 11"
kernelMatrix="0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0"
kernelUnitLength="4"
edgeMode="none" />
</filter>
<linearGradient id="grad" y2="100%">
<stop offset="0%" style="stop-color:#FF0" />
<stop offset="100%" style="stop-color:#F00" />
</linearGradient>
<g id="content">
<rect x="15" y="15" width="90" height="90"
style="fill:url(#grad)" />
<circle id="Circle1" cx="40" cy="65" r="25"
style="fill:yellowGreen" />
<circle id="Circle2" cx="80" cy="55" r="25" style="fill:darkBlue" />
<rect id="Rect1" x="40" y="35" width="30" height="70"
rx="15" ry="15"
style="fill:dodgerBlue" />
<rect id="Rect2" x="60" y="15" width="30" height="70"
rx="10" ry="10"
style="fill:Green" />
</g>
</defs>
<g transform="translate(0 40)" class="legend">
<!-- ============================================== -->
<!-- Convolve_Matrix_1_* -->
<!-- ============================================== -->
<g transform="translate(0 20)" class="row1" >
<g transform="translate(20,0)" >
<g style="filter:url(#conv-rep-tr)">
<use xlink:href="#content" />
</g>
<text transform="translate(60, 130)"
x="0" y="0" style="text-anchor:middle">
1.1 Replicate Top & Right
</text>
</g>
<g transform="translate(160,0)" >
<g style="filter:url(#conv-centX)">
<use xlink:href="#content" />
</g>
<text transform="translate(60, 118)"
x="0" y="0" style="text-anchor:middle">
1.2 Replicate Top, targetX
</text>
</g>
<g transform="translate(300,0)" >
<g style="filter:url(#conv-centY)">
<use xlink:href="#content" />
</g>
<text transform="translate(60, 130)"
x="0" y="0" style="text-anchor:middle">
1.3 Replicate Right, targetY, norm
</text>
</g>
</g> <!-- end row1 -->
<!-- ============================================== -->
<!-- Convolve_Matrix_2_* -->
<!-- ============================================== -->
<g transform="translate(0 160)" class="row2" >
<g transform="translate(20,0)" >
<g style="filter:url(#conv-rep-bl)">
<use xlink:href="#content" />
</g>
<text transform="translate(60, 130)"
x="0" y="0" style="text-anchor:middle">
3.1 Rep Bottom & Left
</text>
</g>
<g transform="translate(160,0)" >
<g style="filter:url(#conv-rep-br)">
<use xlink:href="#content" />
</g>
<text transform="translate(60, 130)"
x="0" y="0" style="text-anchor:middle">
3.2 Rep Bottom & Right
</text>
</g>
<g transform="translate(300,0)" >
<g style="filter:url(#conv-rep-tl)">
<use xlink:href="#content" />
</g>
<text transform="translate(60, 130)"
x="0" y="0" style="text-anchor:middle">
3.3 Rep Top & Left
</text>
</g>
</g> <!-- end row2 -->
<!-- ============================================== -->
<!-- Convolve_Matrix_3_* -->
<!-- ============================================== -->
<g transform="translate(0 300)" class="row3" >
<g transform="translate(20,0)" >
<g style="filter:url(#conv-none-tr)">
<use xlink:href="#content" />
</g>
<text transform="translate(60, 130)"
x="0" y="0" style="text-anchor:middle">
3.1 None Top & Right
</text>
</g>
<g transform="translate(160,0)" >
<g style="filter:url(#conv-none-tl)">
<use xlink:href="#content" />
</g>
<text transform="translate(60, 130)"
x="0" y="0" style="text-anchor:middle">
3.2 None Top & Left
</text>
</g>
<g transform="translate(300,0)" >
<g style="filter:url(#conv-none-bl)">
<use xlink:href="#content" />
</g>
<text transform="translate(60, 130)"
x="0" y="0" style="text-anchor:middle">
3.3 None Bottom & Left
</text>
</g>
</g> <!-- end row3-->
</g> <!-- end legend -->
</g> <!-- end test content -->
<!-- ============================================================= -->
<!-- Batik sample mark -->
<!-- ============================================================= -->
<use xlink:href="../batikLogo.svg#Batik_Tag_Box" />
</svg>
1.2 +38 -1 xml-batik/sources/org/apache/batik/gvt/filter/ConvolveMatrixRable.java
Index: ConvolveMatrixRable.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/filter/ConvolveMatrixRable.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ConvolveMatrixRable.java 2000/12/11 13:44:21 1.1
+++ ConvolveMatrixRable.java 2001/01/05 15:49:17 1.2
@@ -9,12 +9,13 @@
package org.apache.batik.gvt.filter;
import java.awt.image.Kernel;
+import java.awt.Point;
/**
* Convolves an image with a convolution matrix.
*
* @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
- * @version $Id: ConvolveMatrixRable.java,v 1.1 2000/12/11 13:44:21 deweese Exp $
+ * @version $Id: ConvolveMatrixRable.java,v 1.2 2001/01/05 15:49:17 deweese Exp $
*/
public interface ConvolveMatrixRable extends Filter {
@@ -42,12 +43,24 @@
public void setKernel(Kernel k);
/**
+ * Returns the target point of the kernel (what pixel under the kernel
+ * should be set to the result of convolution).
+ */
+ public Point getTarget();
+
+ /**
+ * Sets the target point of the kernel (what pixel under the kernel
+ * should be set to the result of the convolution).
+ */
+ public void setTarget(Point pt);
+
+ /**
* Returns the shift value to apply to the result of convolution
*/
public double getBias();
/**
- * Returns the shift value to apply to the result of convolution
+ * Sets the shift value to apply to the result of convolution
*/
public void setBias(double bias);
@@ -60,4 +73,28 @@
* Sets the current edge handling mode.
*/
public void setEdgeMode(PadMode edgeMode);
+
+ /**
+ * Returns the [x,y] distance in user space between kernel values
+ */
+ public double [] getKernelUnitLength();
+
+ /**
+ * Sets the [x,y] distance in user space between kernel values
+ * If set to zero then one pixel in device space will be used.
+ */
+ public void setKernelUnitLength(double [] kernelUnitLength);
+
+ /**
+ * Returns false if the convolution should affect the Alpha channel
+ */
+ public boolean getPreserveAlpha();
+
+ /**
+ * Sets Alpha channel handling.
+ * A value of False indicates that the convolution should apply to
+ * the Alpha Channel
+ */
+ public void setPreserveAlpha(boolean preserveAlpha);
}
+
1.2 +9 -1 xml-batik/sources/org/apache/batik/gvt/filter/PadMode.java
Index: PadMode.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/filter/PadMode.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- PadMode.java 2000/10/10 18:40:11 1.1
+++ PadMode.java 2001/01/05 15:49:17 1.2
@@ -13,7 +13,7 @@
* the CompositeRable operation. (over, in, out, atop, xor, arith)
*
* @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
- * @version $Id: PadMode.java,v 1.1 2000/10/10 18:40:11 hillion Exp $
+ * @version $Id: PadMode.java,v 1.2 2001/01/05 15:49:17 deweese Exp $
*/
public final class PadMode implements java.io.Serializable {
/** Pad edges with zeros */
@@ -22,12 +22,18 @@
/** Pad edges by replicating edge pixels */
public static final int MODE_REPLICATE = 2;
+ /** Pad edges by wrapping around edge pixels */
+ public static final int MODE_WRAP = 3;
+
/** Pad edges with zeros */
public static final PadMode ZERO_PAD = new PadMode(MODE_ZERO_PAD);
/** Pad edges by replicating edge pixels */
public static final PadMode REPLICATE = new PadMode(MODE_REPLICATE);
+ /** Pad edges by replicating edge pixels */
+ public static final PadMode WRAP = new PadMode(MODE_WRAP);
+
/**
* Returns the mode of this pad mode.
*/
@@ -57,6 +63,8 @@
return ZERO_PAD;
case MODE_REPLICATE:
return REPLICATE;
+ case MODE_WRAP:
+ return WRAP;
default:
throw new Error("Unknown Pad Mode type");
}
1.26 +4 -1 xml-batik/sources/org/apache/batik/refimpl/bridge/SVGBridgeContext.java
Index: SVGBridgeContext.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/refimpl/bridge/SVGBridgeContext.java,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- SVGBridgeContext.java 2000/12/28 09:37:43 1.25
+++ SVGBridgeContext.java 2001/01/05 15:49:18 1.26
@@ -21,7 +21,7 @@
*
* @author <a href="mailto:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a>
* @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
- * @version $Id: SVGBridgeContext.java,v 1.25 2000/12/28 09:37:43 hillion Exp $
+ * @version $Id: SVGBridgeContext.java,v 1.26 2001/01/05 15:49:18 deweese Exp $
*/
public class SVGBridgeContext extends ConcreteBridgeContext
implements SVGConstants {
@@ -88,6 +88,9 @@
putBridge(SVG_NAMESPACE_URI, SVG_FE_COMPOSITE_TAG,
new SVGFeCompositeElementBridge());
+
+ putBridge(SVG_NAMESPACE_URI, SVG_FE_CONVOLVE_MATRIX_TAG,
+ new SVGFeConvolveMatrixElementBridge());
putBridge(SVG_NAMESPACE_URI, SVG_FE_DISPLACEMENT_MAP_TAG,
new SVGFeDisplacementMapElementBridge());
1.1 xml-batik/sources/org/apache/batik/refimpl/bridge/SVGFeConvolveMatrixElementBridge.java
Index: SVGFeConvolveMatrixElementBridge.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.batik.refimpl.bridge;
import java.awt.geom.Rectangle2D;
import java.awt.Point;
import java.awt.image.Kernel;
import java.util.StringTokenizer;
import java.util.Map;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.BridgeMutationEvent;
import org.apache.batik.bridge.FilterPrimitiveBridge;
import org.apache.batik.bridge.IllegalAttributeValueException;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.gvt.GraphicsNodeRenderContext;
import org.apache.batik.gvt.filter.Filter;
import org.apache.batik.gvt.filter.ConvolveMatrixRable;
import org.apache.batik.gvt.filter.PadMode;
import org.apache.batik.gvt.filter.PadRable;
import org.apache.batik.refimpl.bridge.resources.Messages;
import org.apache.batik.refimpl.gvt.filter.ConcreteConvolveMatrixRable;
import org.apache.batik.refimpl.gvt.filter.ConcretePadRable;
import org.apache.batik.util.SVGConstants;
import org.apache.batik.util.UnitProcessor;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.css.CSSStyleDeclaration;
/**
* This class bridges an SVG <tt>feConvolveMatrix</tt> element with a concrete
* <tt>ConvolveMatrixRable</tt>
*
* @author <a href="mailto:Thomas.DeWeese@Kodak.com">Thomas DeWeese</a>
* @version $Id: SVGFeConvolveMatrixElementBridge.java,v 1.1 2001/01/05 15:49:18 deweese Exp $
*/
public class SVGFeConvolveMatrixElementBridge implements FilterPrimitiveBridge,
SVGConstants {
/**
* Returns the <tt>Filter</tt> that implements the filter
* operation modeled by the input DOM element
*
* @param filteredNode the node to which the filter will be attached.
* @param bridgeContext the context to use.
* @param filterElement DOM element that represents a filter abstraction
* @param in the <tt>Filter</tt> that represents the current
* filter input if the filter chain.
* @param filterRegion the filter area defined for the filter chained
* the new node will be part of.
* @param filterMap a map where the mediator can map a name to the
* <tt>Filter</tt> it creates. Other <tt>FilterBridge</tt>s
* can then access a filter node from the filterMap if they
* know its name.
*/
public Filter create(GraphicsNode filteredNode,
BridgeContext bridgeContext,
Element filterElement,
Element filteredElement,
Filter in,
Rectangle2D filterRegion,
Map filterMap){
// Extract kernel Order (Size)
String attrStr;
attrStr = filterElement.getAttributeNS(null, SVG_ORDER_ATTRIBUTE);
Float orderPair[] = SVGUtilities.buildFloatPair(attrStr);
int orderX=0, orderY=0;
if (orderPair[0] != null) {
orderX = (int)orderPair[0].floatValue();
if (orderX != (int)orderPair[0].floatValue())
throw new IllegalAttributeValueException
(Messages.formatMessage
("feConvolveMatrix.order.notPosInt", null));
}
if (orderX <= 0)
throw new IllegalAttributeValueException
(Messages.formatMessage
("feConvolveMatrix.order.notPosInt", null));
if (orderPair[1] == null)
orderY = orderX;
else {
orderY = (int)orderPair[1].floatValue();
if (orderY != (int)orderPair[1].floatValue())
throw new IllegalAttributeValueException
(Messages.formatMessage
("feConvolveMatrix.order.notPosInt", null));
}
if (orderY <= 0)
throw new IllegalAttributeValueException
(Messages.formatMessage
("feConvolveMatrix.order.notPosInt", null));
float [] kernel = new float[orderX*orderY];
attrStr = filterElement.getAttributeNS
(null, SVG_KERNEL_MATRIX_ATTRIBUTE);
{
StringTokenizer st = new StringTokenizer(attrStr);
int i=0;
while (st.hasMoreTokens()) {
kernel[i++] = SVGUtilities.convertSVGNumber
(SVG_KERNEL_MATRIX_ATTRIBUTE, st.nextToken());
if (i == orderX*orderY) break;
}
if (st.hasMoreTokens())
throw new IllegalAttributeValueException
(Messages.formatMessage
("feConvolveMatrix.kernelMatrix.tooMany", null));
if (i != orderX*orderY)
throw new IllegalAttributeValueException
(Messages.formatMessage
("feConvolveMatrix.kernelMatrix.notEnough", null));
}
attrStr = filterElement.getAttributeNS(null, SVG_DIVISOR_ATTRIBUTE);
float divisor = 0;
if (attrStr.length() != 0) {
divisor = SVGUtilities.convertSVGNumber
(SVG_DIVISOR_ATTRIBUTE, attrStr);
} else {
// Default is sum of kernel values (if sum is zero then 1.0).
for (int i=0; i<kernel.length; i++)
divisor += kernel[i];
if (divisor == 0.0f) divisor = 1.0f;
}
if (divisor == 0.0f)
throw new IllegalAttributeValueException
(Messages.formatMessage
("feConvolveMatrix.divisor.zero", null));
attrStr = filterElement.getAttributeNS(null, SVG_BIAS_ATTRIBUTE);
float bias = 0.0f;
if (attrStr.length() != 0) {
bias = SVGUtilities.convertSVGNumber(SVG_BIAS_ATTRIBUTE, attrStr);
}
attrStr = filterElement.getAttributeNS(null, SVG_TARGET_X_ATTRIBUTE);
int targetX=orderX/2;
if (attrStr.length() != 0) {
targetX = SVGUtilities.convertSVGInteger
(SVG_TARGET_X_ATTRIBUTE, attrStr);
}
if ((targetX < 0) || (targetX >= orderX))
throw new IllegalAttributeValueException
(Messages.formatMessage
("feConvolveMatrix.targetX.invalid", null));
attrStr = filterElement.getAttributeNS(null, SVG_TARGET_Y_ATTRIBUTE);
int targetY=orderY/2;
if (attrStr.length() != 0) {
targetY = SVGUtilities.convertSVGInteger
(SVG_TARGET_Y_ATTRIBUTE, attrStr);
}
if ((targetY < 0) || (targetY >= orderY))
throw new IllegalAttributeValueException
(Messages.formatMessage
("feConvolveMatrix.targetY.invalid", null));
attrStr = filterElement.getAttributeNS(null, SVG_EDGE_MODE_ATTRIBUTE);
PadMode padMode = PadMode.REPLICATE;
if (attrStr.length() != 0) {
attrStr = attrStr.toLowerCase();
if (attrStr.equals(SVG_DUPLICATE_VALUE))
padMode = PadMode.REPLICATE;
else if (attrStr.equals(SVG_WRAP_VALUE))
padMode = PadMode.WRAP;
else if (attrStr.equals(SVG_NONE_VALUE))
padMode = PadMode.ZERO_PAD;
else
throw new IllegalAttributeValueException
(Messages.formatMessage
("feConvolveMatrix.edgeMode.invalid",
new Object[] { attrStr }));
}
attrStr = filterElement.getAttributeNS
(null, SVG_KERNEL_UNIT_LENGTH_ATTRIBUTE);
double [] kernelUnitLength = null;
if (attrStr.length() != 0) {
Float [] fp = SVGUtilities.buildFloatPair(attrStr);
kernelUnitLength = new double[2];
if (fp[0] != null)
kernelUnitLength[0] = fp[0].floatValue();
if (fp[1] != null)
kernelUnitLength[1] = fp[1].floatValue();
else
kernelUnitLength[1] = kernelUnitLength[0];
}
if (kernelUnitLength != null) {
if (kernelUnitLength[0] <= 0)
throw new IllegalAttributeValueException
(Messages.formatMessage
("feConvolveMatrix.kernelUnitLength.notPositive", null));
if (kernelUnitLength[1] <= 0)
throw new IllegalAttributeValueException
(Messages.formatMessage
("feConvolveMatrix.kernelUnitLength.notPositive", null));
}
attrStr = filterElement.getAttributeNS
(null, SVG_PRESERVE_ALPHA_ATTRIBUTE);
boolean preserveAlpha = false;
if (attrStr.length() != 0) {
attrStr = attrStr.toLowerCase();
if (attrStr.equals("false"))
preserveAlpha = false;
else if (attrStr.equals("true"))
preserveAlpha = true;
else
throw new IllegalAttributeValueException
(Messages.formatMessage
("feConvolveMatrix.preserveAlpha.invalid",
new Object[] { attrStr }));
}
// Get source
String inAttr = filterElement.getAttributeNS(null, SVG_IN_ATTRIBUTE);
in = CSSUtilities.getFilterSource(filteredNode,
inAttr,
bridgeContext,
filteredElement,
in,
filterMap);
if (in == null)
return null;
//
// The default region is the input source's region unless the
// source is SourceGraphics, in which case the default region
// is the filter chain's region
//
Filter sourceGraphics = (Filter)filterMap.get(VALUE_SOURCE_GRAPHIC);
Rectangle2D defaultRegion = in.getBounds2D();
if (in == sourceGraphics) {
defaultRegion = filterRegion;
}
CSSStyleDeclaration cssDecl
= bridgeContext.getViewCSS().getComputedStyle(filterElement, null);
UnitProcessor.Context uctx
= new DefaultUnitProcessorContext(bridgeContext, cssDecl);
GraphicsNodeRenderContext rc =
bridgeContext.getGraphicsNodeRenderContext();
Rectangle2D convolveArea
= SVGUtilities.convertFilterPrimitiveRegion(filterElement,
filteredElement,
defaultRegion,
filteredNode,
rc,
uctx);
PadRable pad;
pad = new ConcretePadRable(in, convolveArea, PadMode.ZERO_PAD);
// Build filter
ConvolveMatrixRable convolve;
convolve = new ConcreteConvolveMatrixRable(pad);
// Rotate the kernel 180 deg.
int len2 = kernel.length/2;
int len1 = kernel.length-1;
for (int i=0; i<len2; i++) {
float tmp = kernel[i];
kernel[i] = kernel[len1-i];
kernel[len1-i] = tmp;
}
for (int i=0; i<kernel.length; i++)
kernel[i] /= divisor;
convolve.setKernel(new Kernel(orderX, orderY, kernel));
convolve.setTarget(new Point(targetX, targetY));
convolve.setBias(bias);
convolve.setEdgeMode(padMode);
convolve.setKernelUnitLength(kernelUnitLength);
convolve.setPreserveAlpha(preserveAlpha);
// Get result attribute if any
String result = filterElement.getAttributeNS(null,ATTR_RESULT);
if((result != null) && (result.trim().length() > 0)){
filterMap.put(result, convolve);
}
return convolve;
}
/**
* Update the <tt>Filter</tt> object to reflect the current
* configuration in the <tt>Element</tt> that models the filter.
*/
public void update(BridgeMutationEvent evt) {
// <!> FIXME : TODO
}
}
1.6 +25 -8 xml-batik/sources/org/apache/batik/refimpl/gvt/filter/ConcreteBackgroundRable.java
Index: ConcreteBackgroundRable.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/refimpl/gvt/filter/ConcreteBackgroundRable.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ConcreteBackgroundRable.java 2000/12/19 17:56:45 1.5
+++ ConcreteBackgroundRable.java 2001/01/05 15:49:18 1.6
@@ -40,7 +40,7 @@
* createRendering methods.
*
* @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
- * @version $Id: ConcreteBackgroundRable.java,v 1.5 2000/12/19 17:56:45 billh Exp $
+ * @version $Id: ConcreteBackgroundRable.java,v 1.6 2001/01/05 15:49:18 deweese Exp $
*/
public class ConcreteBackgroundRable
extends AbstractRable {
@@ -237,6 +237,12 @@
public Filter getBackground(GraphicsNode gn,
GraphicsNode child,
GraphicsNodeRenderContext rc) {
+ if (gn == null) {
+ throw new IllegalArgumentException
+ ("BackgroundImage requested yet no parent has " +
+ "'enable-background:new'");
+ }
+
Rectangle2D r2d = null;
if (gn instanceof CompositeGraphicsNode) {
CompositeGraphicsNode cgn = (CompositeGraphicsNode)gn;
@@ -246,27 +252,39 @@
Vector srcs = new Vector();
if (r2d == null) {
Filter f = getBackground(gn.getParent(), gn, rc);
- if (f == null)
- return null;
- srcs.add(f);
+ if (f != null)
+ srcs.add(f);
}
+ GraphicsNodeRableFactory gnrf;
+ gnrf = rc.getGraphicsNodeRableFactory();
+
if (child != null) {
CompositeGraphicsNode cgn = (CompositeGraphicsNode)gn;
List children = cgn.getChildren();
Iterator i = children.iterator();
while (i.hasNext()) {
GraphicsNode childGN = (GraphicsNode)i.next();
+ // System.out.println("Parent: " + cgn +
+ // "\n Child: " + child +
+ // "\n ChildGN: " + childGN);
if (childGN == child)
break;
GraphicsNodeRable gnr;
- GraphicsNodeRableFactory gnrf;
- gnrf = rc.getGraphicsNodeRableFactory();
gnr = gnrf.createGraphicsNodeRable(childGN, rc);
gnr.setUsePrimitivePaint(false);
srcs.add(gnr);
}
}
+ /* If this is uncommented then children appear in background img.
+ else {
+ // System.out.println("Parent: " + gn);
+ GraphicsNodeRable gnr;
+ gnr = gnrf.createGraphicsNodeRable(gn);
+ srcs.add(gnr);
+ }
+ */
+
if (srcs.size() == 0)
return null;
@@ -328,12 +346,11 @@
Filter f = getBackground(node, null, gnrc);
if ( f == null)
return null;
-
// org.apache.batik.test.gvt.ImageDisplay.showImage
// ("PrePad", f.createRendering(renderContext));
Rectangle2D r2d = getBounds2D();
- f = new ConcretePadRable(f, r2d, PadMode.ZERO_PAD);
+ // f = new ConcretePadRable(f, r2d, PadMode.ZERO_PAD);
// System.out.println("Bounds: " + r2d);
RenderedImage ri = f.createRendering(renderContext);
1.2 +220 -4 xml-batik/sources/org/apache/batik/refimpl/gvt/filter/ConcreteConvolveMatrixRable.java
Index: ConcreteConvolveMatrixRable.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/refimpl/gvt/filter/ConcreteConvolveMatrixRable.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ConcreteConvolveMatrixRable.java 2000/12/11 13:44:22 1.1
+++ ConcreteConvolveMatrixRable.java 2001/01/05 15:49:19 1.2
@@ -8,19 +8,37 @@
package org.apache.batik.refimpl.gvt.filter;
+import java.awt.Point;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.AffineTransform;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.awt.image.ColorModel;
+import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
+import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderContext;
+import java.awt.image.WritableRaster;
import org.apache.batik.gvt.filter.PadMode;
import org.apache.batik.gvt.filter.ConvolveMatrixRable;
import org.apache.batik.gvt.filter.Filter;
+import org.apache.batik.gvt.filter.CachableRed;
/**
* Convolves an image with a convolution matrix.
*
+ * Known limitations:
+ * Does not support bias other than zero - pending 16bit pathway
+ * Does not support edgeMode="wrap" - pending Tile code.
+ *
* @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
- * @version $Id: ConcreteConvolveMatrixRable.java,v 1.1 2000/12/11 13:44:22 deweese Exp $
+ * @version $Id: ConcreteConvolveMatrixRable.java,v 1.2 2001/01/05 15:49:19 deweese Exp $
*/
public class ConcreteConvolveMatrixRable
extends AbstractRable
@@ -28,10 +46,14 @@
{
Kernel kernel;
- double bias;
+ Point target;
+ float bias;
PadMode edgeMode;
+ float [] kernelUnitLength = new float[2];
+
+ boolean preserveAlpha = false;;
- ConcreteConvolveMatrixRable(Filter source) {
+ public ConcreteConvolveMatrixRable(Filter source) {
super(source);
}
@@ -60,6 +82,14 @@
this.kernel = k;
}
+ public Point getTarget() {
+ return (Point)target.clone();
+ }
+
+ public void setTarget(Point pt) {
+ this.target = (Point)pt.clone();
+ }
+
/**
* Returns the shift value to apply to the result of convolution
*/
@@ -72,7 +102,7 @@
*/
public void setBias(double bias) {
touch();
- this.bias = bias;
+ this.bias = (float)bias;
}
/**
@@ -90,8 +120,194 @@
this.edgeMode = edgeMode;
}
+ /**
+ * Returns the [x,y] distance in user space between kernel values
+ */
+ public double [] getKernelUnitLength() {
+ if (kernelUnitLength == null)
+ return null;
+
+ double [] ret = new double[2];
+ ret[0] = kernelUnitLength[0];
+ ret[1] = kernelUnitLength[1];
+ return ret;
+ }
+
+ /**
+ * Sets the [x,y] distance in user space between kernel values
+ * If set to zero then device space will be used.
+ */
+ public void setKernelUnitLength(double [] kernelUnitLength) {
+ touch();
+ if (kernelUnitLength == null) {
+ this.kernelUnitLength = null;
+ return;
+ }
+
+ if (this.kernelUnitLength == null)
+ this.kernelUnitLength = new float[2];
+
+ this.kernelUnitLength[0] = (float)kernelUnitLength[0];
+ this.kernelUnitLength[1] = (float)kernelUnitLength[1];
+ }
+
+ /**
+ * Returns false if the convolution should affect the Alpha channel
+ */
+ public boolean getPreserveAlpha() {
+ return preserveAlpha;
+ }
+
+ /**
+ * Sets Alpha channel handling.
+ * A value of False indicates that the convolution should apply to
+ * the Alpha Channel
+ */
+ public void setPreserveAlpha(boolean preserveAlpha) {
+ touch();
+ this.preserveAlpha = preserveAlpha;
+ }
+
public RenderedImage createRendering(RenderContext rc) {
- return null;
+ // Just copy over the rendering hints.
+ RenderingHints rh = rc.getRenderingHints();
+ if (rh == null) rh = new RenderingHints(null);
+
+ // update the current affine transform
+ AffineTransform at = rc.getTransform();
+
+
+ // This splits out the scale and applies it
+ // prior to the Gaussian. Then after appying the gaussian
+ // it applies the shear (rotation) and translation components.
+ double sx = at.getScaleX();
+ double sy = at.getScaleY();
+
+ double shx = at.getShearX();
+ double shy = at.getShearY();
+
+ double tx = at.getTranslateX();
+ double ty = at.getTranslateY();
+
+ // The Scale is the "hypotonose" of the matrix vectors. This
+ // represents the complete scaling value from user to an
+ // intermediate space that is scaled similarly to device
+ // space.
+ double scaleX = Math.sqrt(sx*sx + shy*shy);
+ double scaleY = Math.sqrt(sy*sy + shx*shx);
+
+ // These values represent the scale factor to the intermediate
+ // coordinate system where we will apply our convolution.
+ if (kernelUnitLength != null) {
+ if (kernelUnitLength[0] > 0.0)
+ scaleX = 1/kernelUnitLength[0];
+
+ if (kernelUnitLength[1] > 0.0)
+ scaleY = 1/kernelUnitLength[1];
+ }
+
+ Shape aoi = rc.getAreaOfInterest();
+ if(aoi == null)
+ aoi = getBounds2D();
+
+ Rectangle2D r = aoi.getBounds2D();
+
+ int kw = kernel.getWidth();
+ int kh = kernel.getHeight();
+ int kx = target.x;
+ int ky = target.y;
+
+ // Grow the region in usr space.
+ {
+ double rx0 = r.getX() -(kx/scaleX);
+ double ry0 = r.getY() -(ky/scaleY);
+ double rx1 = rx0 + r.getWidth() + (kw-1)/scaleX;
+ double ry1 = ry0 + r.getHeight() + (kh-1)/scaleY;
+ r = new Rectangle2D.Double(Math.floor(rx0),
+ Math.floor(ry0),
+ Math.ceil (rx1-Math.floor(rx0)),
+ Math.ceil (ry1-Math.floor(ry0)));
+ }
+ // This will be the affine transform between our usr space and
+ // an intermediate space which is scaled according to
+ // kernelUnitLength and is axially aligned with our user
+ // space.
+ AffineTransform srcAt
+ = AffineTransform.getScaleInstance(scaleX, scaleY);
+
+ // Here we update the translate to account for the phase shift
+ // (if any) introduced by setting targetX, targetY in SVG.
+ tx += target.x - kernel.getXOrigin();
+ ty += target.y - kernel.getYOrigin();
+
+ // This is the affine transform between our intermediate
+ // coordinate space (where the convolution takes place) and
+ // the real device space, or null (if we don't need an
+ // intermediate space).
+
+ // The shear/rotation simply divides out the
+ // common scale factor in the matrix.
+ AffineTransform resAt = new AffineTransform(sx/scaleX, shy/scaleX,
+ shx/scaleY, sy/scaleY,
+ tx, ty);
+
+ RenderedImage ri;
+ ri = getSource().createRendering(new RenderContext(srcAt, r, rh));
+ if (ri == null)
+ return null;
+
+ CachableRed cr;
+ cr = ConcreteRenderedImageCachableRed.wrap(ri);
+
+ Shape devShape = srcAt.createTransformedShape(aoi);
+ r = devShape.getBounds2D();
+ r = new Rectangle2D.Double(Math.floor(r.getX()-kx),
+ Math.floor(r.getY()-ky),
+ Math.ceil (r.getX()+r.getWidth())-
+ Math.floor(r.getX())+(kw-1),
+ Math.ceil (r.getY()+r.getHeight())-
+ Math.floor(r.getY())+(kh-1));
+
+ if (!r.getBounds().equals(cr.getBounds())) {
+ if (edgeMode == PadMode.WRAP)
+ throw new IllegalArgumentException
+ ("edgeMode=\"wrap\" is not supported by ConvolveMatrix.");
+ cr = new PadRed(cr, r.getBounds(), edgeMode, rh);
+ }
+
+ if (bias != 0.0)
+ throw new IllegalArgumentException
+ ("Only bias equals zero is supported in ConvolveMatrix.");
+
+ BufferedImageOp op = new ConvolveOp(kernel,
+ ConvolveOp.EDGE_NO_OP,
+ rh);
+
+ ColorModel cm = cr.getColorModel();
+
+ // OK this is a bit of a cheat. We Pull the DataBuffer out of
+ // The read-only raster that getData gives us. And use it to
+ // build a WritableRaster. This avoids a copy of the data.
+ Raster rr = cr.getData();
+ Point pt = new Point(0,0);
+ WritableRaster wr = Raster.createWritableRaster(rr.getSampleModel(),
+ rr.getDataBuffer(),
+ pt);
+
+ BufferedImage srcBI;
+ srcBI = new BufferedImage(cm, wr, cm.isAlphaPremultiplied(), null);
+
+ BufferedImage destBI;
+ destBI = op.filter(srcBI, null);
+
+ cr = new ConcreteBufferedImageCachableRed(destBI,
+ (int)r.getX(),
+ (int)r.getY());
+ cr = new PadRed(cr, r.getBounds(), PadMode.ZERO_PAD, rh);
+ if (!resAt.isIdentity())
+ cr = new AffineRed(cr, resAt, null);
+
+ return cr;
}
}
1.9 +3 -3 xml-batik/sources/org/apache/batik/refimpl/gvt/filter/ConcreteGaussianBlurRable.java
Index: ConcreteGaussianBlurRable.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/refimpl/gvt/filter/ConcreteGaussianBlurRable.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- ConcreteGaussianBlurRable.java 2000/11/21 20:54:22 1.8
+++ ConcreteGaussianBlurRable.java 2001/01/05 15:49:19 1.9
@@ -33,7 +33,7 @@
* GaussianBlurRable implementation
*
* @author <a href="mailto:vincent.hardy@eng.sun.com>Vincent Hardy</a>
- * @version $Id: ConcreteGaussianBlurRable.java,v 1.8 2000/11/21 20:54:22 deweese Exp $
+ * @version $Id: ConcreteGaussianBlurRable.java,v 1.9 2001/01/05 15:49:19 deweese Exp $
*/
public class ConcreteGaussianBlurRable
extends AbstractRable
@@ -220,7 +220,7 @@
return null;
CachableRed cr;
- cr = new ConcreteRenderedImageCachableRed(ri);
+ cr = ConcreteRenderedImageCachableRed.wrap(ri);
Shape devShape = srcAt.createTransformedShape(aoi);
r = devShape.getBounds2D();
@@ -231,7 +231,7 @@
if (!r.getBounds().equals(cr.getBounds()))
cr = new PadRed(cr, r.getBounds(), PadMode.ZERO_PAD, rh);
- ColorModel cm = ri.getColorModel();
+ ColorModel cm = cr.getColorModel();
// OK this is a bit of a cheat. We Pull the DataBuffer out of
// The read-only raster that getData gives us. And use it to
1.4 +180 -2 xml-batik/sources/org/apache/batik/refimpl/gvt/filter/PadRed.java
Index: PadRed.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/refimpl/gvt/filter/PadRed.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- PadRed.java 2000/11/17 19:40:17 1.3
+++ PadRed.java 2001/01/05 15:49:19 1.4
@@ -29,11 +29,12 @@
* This is an implementation of a Pad operation as a RenderedImage.
*
* @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
- * @version $Id: PadRed.java,v 1.3 2000/11/17 19:40:17 deweese Exp $ */
+ * @version $Id: PadRed.java,v 1.4 2001/01/05 15:49:19 deweese Exp $ */
public class PadRed extends AbstractRed {
static final boolean DEBUG=false;
+ PadMode padMode;
RenderingHints hints;
/**
@@ -54,6 +55,8 @@
bounds.x, bounds.y,
null);
+ this.padMode = padMode;
+
if (DEBUG) {
System.out.println("Src: " + src + " Bounds: " + bounds +
" Off: " +
@@ -61,6 +64,7 @@
src.getTileGridYOffset());
}
this.hints = hints;
+
}
public WritableRaster copyData(WritableRaster wr) {
@@ -80,6 +84,18 @@
src.copyData(srcWR);
}
+ if (padMode == PadMode.ZERO_PAD) {
+ handleZero(wr);
+ } else if (padMode == PadMode.REPLICATE) {
+ handleReplicate(wr);
+ } else if (padMode == PadMode.WRAP) {
+ handleWrap(wr);
+ }
+
+ return wr;
+ }
+
+ protected void handleZero(WritableRaster wr) {
// NOTE: I'm ignoring the pad mode here. I really need
// to check what the mode is and pad out the edges
// of wr. For now I just zero them...
@@ -97,6 +113,11 @@
// Fully transparent black.
g2d.setColor(new Color(0,0,0,0));
+ // Get my source.
+ CachableRed src = (CachableRed)getSources().get(0);
+ Rectangle srcR = src.getBounds();
+ Rectangle wrR = wr.getBounds();
+
int x = wrR.x;
int y = wrR.y;
int width = wrR.width;
@@ -182,8 +203,165 @@
g2d.fillRect(x0, y, w, height);
width-=w;
}
+ }
- return wr;
+
+ protected void handleReplicate(WritableRaster wr) {
+ // Get my source.
+ CachableRed src = (CachableRed)getSources().get(0);
+ Rectangle srcR = src.getBounds();
+ Rectangle wrR = wr.getBounds();
+
+ int x = wrR.x;
+ int y = wrR.y;
+ int width = wrR.width;
+ int height = wrR.height;
+
+ Rectangle r = wrR.intersection(srcR);
+
+ // We split the edge drawing up into four parts.
+ //
+ // +-----------------------------+
+ // | 3 | 1 | 4 |
+ // | +---------------+ |
+ // / / / /
+ // / / src / /
+ // / / / /
+ // / / / /
+ // | +---------------+ |
+ // | | 2 | |
+ // +-----------------------------+
+ //
+
+ // Draw #1
+ if (y < srcR.y) {
+ int repW = r.width;
+ int repX = srcR.x;
+ int wrX = srcR.x;
+ int wrY = y;
+ if (x+width <= srcR.x) {
+ // we are off to the left of src. so set repX to the
+ // left most pixel...
+ repW = 1;
+ repX = srcR.x;
+ wrX = x+width-1;
+ } else if (x >= srcR.x+srcR.width) {
+ // we are off to the right of src, so set repX to
+ // the right most pixel
+ repW = 1;
+ repX = srcR.x+srcR.width-1;
+ wrX = x;
+ }
+
+ // This fills the top row of section 1 from src (we
+ // go to src instead of getting the data from wr because
+ // in some cases wr will be completely off the top of src
+ WritableRaster wr1 = wr.createWritableChild(wrX, wrY,
+ repW, 1,
+ repX, srcR.y, null);
+ src.copyData(wr1);
+ wrY++;
+
+ int endY = srcR.y;
+ if (y+height < endY) endY = y+height;
+
+ if (wrY < endY) {
+ int [] pixels = wr.getPixels(wrX, wrY-1,
+ repW, 1, (int [])null);
+ while (wrY < srcR.y) {
+ wr.setPixels(wrX, wrY, repW, 1, pixels);
+ wrY++;
+ }
+ }
+ }
+
+ // Draw #2
+ if ((y+height) > (srcR.y+srcR.height)) {
+ int repW = r.width;
+ int repX = srcR.x;
+ int repY = srcR.y+srcR.height-1;
+
+ int wrX = srcR.x;
+ int wrY = srcR.y+srcR.height;
+ if (wrY < y) wrY = y;
+
+ if (x+width <= srcR.x) {
+ // we are off to the left of src. so set repX to the
+ // left most pixel...
+ repW = 1;
+ repX = srcR.x;
+ wrX = x+width-1;
+ } else if (x >= srcR.x+srcR.width) {
+ // we are off to the right of src, so set repX to
+ // the right most pixel
+ repW = 1;
+ repX = srcR.x+srcR.width-1;
+ wrX = x;
+ }
+
+ // First we get the top row of pixels from src. (we
+ // go to src instead of getting the data from wr because
+ // in some cases wr will be completely off the bottom of src).
+ WritableRaster wr1 = wr.createWritableChild(wrX, wrY,
+ repW, 1,
+ repX, repY, null);
+ // This fills the top row of section 2 from src
+ src.copyData(wr1);
+ wrY++;
+
+ int endY = y+height;
+ if (wrY < endY) {
+ // This fills the rest of section 2 from the first line.
+ int [] pixels = wr.getPixels(wrX, wrY-1,
+ repW, 1, (int [])null);
+ while (wrY < endY) {
+ wr.setPixels(wrX, wrY, repW, 1, pixels);
+ wrY++;
+ }
+ }
+ }
+
+ // Draw #3
+ if (x < srcR.x) {
+ // We are garunteed that we have a column of pixels down
+ // the edge of 1 and src. We simply replicate this column
+ // out to the edges of 2.
+ int wrX = srcR.x;
+ if (x+width <= srcR.x) {
+ wrX = x+width-1;
+ }
+
+ int xLoc = x;
+ int [] pixels = wr.getPixels(wrX, y, 1, height, (int [])null);
+ while (xLoc < wrX) {
+ wr.setPixels(xLoc, y, 1, height, pixels);
+ xLoc++;
+ }
+ }
+
+ // Draw #4
+ if (x+width > srcR.x+srcR.width) {
+ // We are garunteed that we have a column of pixels down
+ // the edge of 1 and src. We simply replicate this column
+ // out to the edges of 3.
+ int wrX = srcR.x+srcR.width-1;
+ if (x >= srcR.x+srcR.width) {
+ wrX = x;
+ }
+
+ int xLoc = wrX+1;
+ int endX = x+width-1;
+ int [] pixels = wr.getPixels(wrX, y, 1, height, (int [])null);
+ while (xLoc < endX) {
+ wr.setPixels(xLoc, y, 1, height, pixels);
+ xLoc++;
+ }
+ }
+ }
+
+ protected void handleWrap(WritableRaster wr) {
+
+ handleZero(wr);
}
/**
1.36 +4 -3 xml-batik/sources/org/apache/batik/util/SVGConstants.java
Index: SVGConstants.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/util/SVGConstants.java,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -r1.35 -r1.36
--- SVGConstants.java 2000/12/28 09:37:51 1.35
+++ SVGConstants.java 2001/01/05 15:49:20 1.36
@@ -13,7 +13,7 @@
*
* @author <a href="vincent.hardy@eng.sun.com">Vincent Hardy</a>
* @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
- * @version $Id: SVGConstants.java,v 1.35 2000/12/28 09:37:51 hillion Exp $
+ * @version $Id: SVGConstants.java,v 1.36 2001/01/05 15:49:20 deweese Exp $
*/
public interface SVGConstants extends CSSConstants {
String SVG_PUBLIC_ID =
@@ -101,7 +101,7 @@
String SVG_DIVISOR_ATTRIBUTE = "divisor";
String SVG_DX_ATTRIBUTE = "dx";
String SVG_DY_ATTRIBUTE = "dy";
- String SVG_EDGE_MODE_ATTRIBUTE = "edgemode";
+ String SVG_EDGE_MODE_ATTRIBUTE = "edgeMode";
String SVG_ELEVATION_ATTRIBUTE = "elevation";
String SVG_ENABLE_BACKGROUND_ATTRIBUTE = CSS_ENABLE_BACKGROUND_PROPERTY;
String SVG_EXPONENT_ATTRIBUTE = "exponent";
@@ -133,6 +133,7 @@
String SVG_K3_ATTRIBUTE = "k3";
String SVG_K4_ATTRIBUTE = "k4";
String SVG_KERNEL_MATRIX_ATTRIBUTE = "kernelMatrix";
+ String SVG_KERNEL_UNIT_LENGTH_ATTRIBUTE = "kernelUnitLength";
String SVG_KERNEL_UNIT_LENGTH_X_ATTRIBUTE = "kernelUnitLengthX";
String SVG_KERNEL_UNIT_LENGTH_Y_ATTRIBUTE = "kernelUnitLengthY";
String ATTR_LIGHT_COLOR = "lightColor";
@@ -147,7 +148,7 @@
String SVG_OFFSET_ATTRIBUTE = "offset";
String ATTR_OPACITY = CSS_OPACITY_PROPERTY;
String SVG_OPERATOR_ATTRIBUTE = "operator";
- String ATTR_ORDER = "order";
+ String SVG_ORDER_ATTRIBUTE = "order";
String SVG_ORDER_X_ATTRIBUTE = "orderX";
String SVG_ORDER_Y_ATTRIBUTE = "orderY";
String ATTR_PATTERN_CONTENT_UNITS = "patternContentUnits";
1.5 +2 -2 xml-batik/sources/org/apache/batik/util/awt/svg/SVGConvolveOp.java
Index: SVGConvolveOp.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/util/awt/svg/SVGConvolveOp.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- SVGConvolveOp.java 2000/12/28 09:37:54 1.4
+++ SVGConvolveOp.java 2001/01/05 15:49:20 1.5
@@ -24,7 +24,7 @@
* an SVG filter descriptor.
*
* @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
- * @version $Id: SVGConvolveOp.java,v 1.4 2000/12/28 09:37:54 hillion Exp $
+ * @version $Id: SVGConvolveOp.java,v 1.5 2001/01/05 15:49:20 deweese Exp $
* @see org.apache.batik.util.awt.svg.SVGBufferedImageOp
*/
public class SVGConvolveOp extends AbstractSVGFilterConverter{
@@ -76,7 +76,7 @@
domFactory.createElement(SVG_FE_CONVOLVE_MATRIX_TAG);
// Convert the kernel size
- feConvolveMatrixDef.setAttribute(ATTR_ORDER,
+ feConvolveMatrixDef.setAttribute(SVG_ORDER_ATTRIBUTE,
kernel.getWidth() + SPACE +
kernel.getHeight());