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/07/25 16:44:49 UTC
cvs commit: xml-batik/sources/org/apache/batik/gvt AbstractGraphicsNode.java
deweese 01/07/25 07:44:49
Modified: sources/org/apache/batik/bridge
AbstractSVGFilterPrimitiveElementBridge.java
CSSUtilities.java
sources/org/apache/batik/ext/awt/image/renderable
FilterResRable8Bit.java
sources/org/apache/batik/gvt AbstractGraphicsNode.java
Log:
1) No longer draws elements with opacity=0
2) FilterRes now implements the feMerge hack from the SVG spec
('SourceGraphic' bypasses the filterRes and is drawn directly to the
canvas).
PR: 1238
Revision Changes Path
1.4 +3 -1 xml-batik/sources/org/apache/batik/bridge/AbstractSVGFilterPrimitiveElementBridge.java
Index: AbstractSVGFilterPrimitiveElementBridge.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/AbstractSVGFilterPrimitiveElementBridge.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- AbstractSVGFilterPrimitiveElementBridge.java 2001/07/24 14:36:19 1.3
+++ AbstractSVGFilterPrimitiveElementBridge.java 2001/07/25 14:44:49 1.4
@@ -28,7 +28,7 @@
* The base bridge class for SVG filter primitives.
*
* @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
- * @version $Id: AbstractSVGFilterPrimitiveElementBridge.java,v 1.3 2001/07/24 14:36:19 tkormann Exp $
+ * @version $Id: AbstractSVGFilterPrimitiveElementBridge.java,v 1.4 2001/07/25 14:44:49 deweese Exp $
*/
public abstract class AbstractSVGFilterPrimitiveElementBridge
extends AbstractSVGBridge implements FilterPrimitiveBridge, ErrorConstants {
@@ -129,6 +129,8 @@
if (filter instanceof FilterColorInterpolation) {
boolean isLinear
= CSSUtilities.convertColorInterpolationFilters(filterElement);
+ // System.out.println("IsLinear: " + isLinear +
+ // " Filter: " + filter);
((FilterColorInterpolation)filter).setColorSpaceLinear(isLinear);
}
}
1.29 +6 -4 xml-batik/sources/org/apache/batik/bridge/CSSUtilities.java
Index: CSSUtilities.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/CSSUtilities.java,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -r1.28 -r1.29
--- CSSUtilities.java 2001/07/24 14:36:19 1.28
+++ CSSUtilities.java 2001/07/25 14:44:49 1.29
@@ -66,7 +66,7 @@
* concrete objects regarding to CSS properties.
*
* @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
- * @version $Id: CSSUtilities.java,v 1.28 2001/07/24 14:36:19 tkormann Exp $
+ * @version $Id: CSSUtilities.java,v 1.29 2001/07/25 14:44:49 deweese Exp $
*/
public abstract class CSSUtilities implements CSSConstants, ErrorConstants {
@@ -391,6 +391,9 @@
// 'opacity'
/////////////////////////////////////////////////////////////////////////
+ public final static Composite transparent =
+ AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0);
+
/**
* Returns a composite object that represents the 'opacity' of the
* specified element.
@@ -399,12 +402,11 @@
*/
public static Composite convertOpacity(Element e) {
CSSOMReadOnlyStyleDeclaration decl = getComputedStyle(e);
- CSSValue v =
- getComputedStyle(e).getPropertyCSSValueInternal
+ CSSValue v = decl.getPropertyCSSValueInternal
(CSS_OPACITY_PROPERTY);
float opacity = PaintServer.convertOpacity(v);
if (opacity <= 0f) {
- return null;
+ return transparent;
} else if (opacity >= 1f) {
return AlphaComposite.SrcOver;
} else {
1.7 +166 -3 xml-batik/sources/org/apache/batik/ext/awt/image/renderable/FilterResRable8Bit.java
Index: FilterResRable8Bit.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/ext/awt/image/renderable/FilterResRable8Bit.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- FilterResRable8Bit.java 2001/05/31 21:10:25 1.6
+++ FilterResRable8Bit.java 2001/07/25 14:44:49 1.7
@@ -10,28 +10,37 @@
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.Vector;
+import java.awt.Composite;
+import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
+
+import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderableImage;
import java.awt.image.renderable.RenderContext;
+import org.apache.batik.ext.awt.image.CompositeRule;
+import org.apache.batik.ext.awt.image.GraphicsUtil;
import org.apache.batik.ext.awt.image.rendered.AffineRed;
import org.apache.batik.ext.awt.image.rendered.TileCacheRed;
-import org.apache.batik.ext.awt.image.GraphicsUtil;
+import org.apache.batik.ext.awt.image.SVGComposite;
/**
* Interface for implementing filter resolution.
*
* @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
- * @version $Id: FilterResRable8Bit.java,v 1.6 2001/05/31 21:10:25 deweese Exp $
+ * @version $Id: FilterResRable8Bit.java,v 1.7 2001/07/25 14:44:49 deweese Exp $
*/
public class FilterResRable8Bit extends AbstractRable
- implements FilterResRable{
+ implements FilterResRable, PaintRable {
/**
* Filter resolution along the x-axis
@@ -48,6 +57,12 @@
}
+ public FilterResRable8Bit(Filter src, int filterResX, int filterResY) {
+ init(src, null);
+ setFilterResolutionX(filterResX);
+ setFilterResolutionY(filterResY);
+ }
+
/**
* Returns the source to be cropped.
*/
@@ -100,6 +115,154 @@
this.filterResolutionY = filterResolutionY;
}
+
+ /**
+ * This returns true if <tt>ri</tt> and all of <tt>ri</tt>'s
+ * sources implement the PaintRable interface. This is used to
+ * indicate that the chain has a good potential for bypassing the
+ * filterRes operation entirely.
+ *
+ * Ideally there would be a checkPaintRable method in PaintRable
+ * that could be used to get a definate answer about a filters
+ * ability to draw directly to a Graphics2D (this can sometimes
+ * 'fail' because of the way the Graphics2D is currently
+ * configured).
+ */
+ public boolean allPaintRable(RenderableImage ri) {
+ if (!(ri instanceof PaintRable))
+ return false;
+
+ Vector v = ri.getSources();
+ // No sources and we are PaintRable so the chain is PaintRable.
+ if (v == null) return true;
+
+ Iterator i = v.iterator();
+ while (i.hasNext()) {
+ RenderableImage nri = (RenderableImage)i.next();
+ // A source is not paintRable so we are not 100% paintRable.
+ if (!allPaintRable(nri)) return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * This function attempts to distribute the filterRes operation
+ * across src. Right now it knows about two operations, pad and
+ * composite. It's main target is the composite but often pad
+ * operations are sprinked in the chain so it needs to know about
+ * them. This list could be extended however if it gets much
+ * longer it should probably be rolled into a new 'helper interface'
+ * like PaintRable.
+ *
+ * NOTE: This is essentially a bad hack, but it is a hack that is
+ * recomended by the SVG specification so I do it.
+ */
+ public boolean distributeAcross(RenderableImage src, Graphics2D g2d) {
+ boolean ret;
+ if (src instanceof PadRable) {
+ PadRable pad = (PadRable)src;
+ Shape clip = g2d.getClip();
+ g2d.clip(pad.getPadRect());
+ ret = distributeAcross(pad.getSource(), g2d);
+ g2d.setClip(clip);
+ return ret;
+ }
+
+ if (src instanceof CompositeRable) {
+ CompositeRable comp = (CompositeRable)src;
+ if (comp.getCompositeRule() != CompositeRule.OVER)
+ return false;
+
+ if (false) {
+ // To check colorspaces or to not check colorspaces
+ // _that_ is the question...
+ ColorSpace crCS = comp.getOperationColorSpace();
+ ColorSpace g2dCS = GraphicsUtil.getDestinationColorSpace(g2d);
+ if ((g2dCS == null) || (g2dCS != crCS))
+ return false;
+ }
+
+ Vector v = comp.getSources();
+ if (v == null) return true;
+ ListIterator li = v.listIterator(v.size());
+ while (li.hasPrevious()) {
+ RenderableImage csrc = (RenderableImage)li.previous();
+ if (!allPaintRable(csrc)) {
+ li.next();
+ break;
+ }
+ }
+
+ if (!li.hasPrevious()) {
+ // All inputs are PaintRable so just draw directly to
+ // the graphics ignore filter res all togeather...
+ GraphicsUtil.drawImage(g2d, comp);
+ return true;
+ }
+
+ if (!li.hasNext())
+ // None of the trailing inputs are PaintRable so we don't
+ // distribute across this at all.
+ return false;
+
+ // Now we are in the case where some are paintRable and
+ // some aren't. In this case we create a new
+ // CompositeRable with the first ones, to which we apply
+ // ourselves (limiting the resolution), and after that
+ // we simply draw the remainder...
+ int idx = li.nextIndex(); // index of first PaintRable...
+ Filter f = new CompositeRable8Bit(v.subList(0, idx),
+ comp.getCompositeRule(),
+ comp.isColorSpaceLinear());
+ f = new FilterResRable8Bit(f, getFilterResolutionX(),
+ getFilterResolutionY());
+ GraphicsUtil.drawImage(g2d, f);
+ while (li.hasNext()) {
+ PaintRable pr = (PaintRable)li.next();
+ if (!pr.paintRable(g2d)) {
+ // Ugg it failed to paint so we need to filterRes it...
+ Filter prf = (Filter)pr;
+ prf = new FilterResRable8Bit(prf, getFilterResolutionX(),
+ getFilterResolutionY());
+ GraphicsUtil.drawImage(g2d, prf);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Should perform the equivilent action as
+ * createRendering followed by drawing the RenderedImage.
+ *
+ * @param g2d The Graphics2D to draw to.
+ * @return true if the paint call succeeded, false if
+ * for some reason the paint failed (in which
+ * case a createRendering should be used).
+ */
+ public boolean paintRable(Graphics2D g2d) {
+ // This is a bit of a hack to implement the suggestion of SVG
+ // specification that if the last operation in a filter chain
+ // is a SRC_OVER composite and the source is SourceGraphic it
+ // should be rendered directly to the canvas (by passing
+ // filterRes). We are actually much more aggressive in
+ // implementing this suggestion since we will bypass filterRes
+ // for all the trailing elements in a SRC_OVER composite that
+ // can be drawn directly to the canvas.
+
+ // System.out.println("Calling FilterResRable paintRable");
+
+ // This optimization only apply if we are using
+ // SrcOver. Otherwise things break...
+ Composite c = g2d.getComposite();
+ if (!SVGComposite.OVER.equals(c))
+ return false;
+
+ Filter src = getSource();
+ return distributeAcross(src, g2d);
+ }
/**
* Cached Rendered image at filterRes.
1.22 +8 -1 xml-batik/sources/org/apache/batik/gvt/AbstractGraphicsNode.java
Index: AbstractGraphicsNode.java
===================================================================
RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/AbstractGraphicsNode.java,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- AbstractGraphicsNode.java 2001/03/26 21:27:36 1.21
+++ AbstractGraphicsNode.java 2001/07/25 14:44:49 1.22
@@ -48,7 +48,7 @@
* @author <a href="mailto:Thierry.Kormann@sophia.inria.fr">Thierry Kormann</a>
* @author <a href="mailto:etissandier@ilog.fr">Emmanuel Tissandier</a>
* @author <a href="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
- * @version $Id: AbstractGraphicsNode.java,v 1.21 2001/03/26 21:27:36 deweese Exp $
+ * @version $Id: AbstractGraphicsNode.java,v 1.22 2001/07/25 14:44:49 deweese Exp $
*/
public abstract class AbstractGraphicsNode implements GraphicsNode, Cloneable {
@@ -325,6 +325,13 @@
// first, make sure we haven't been interrupted
if (Thread.currentThread().isInterrupted()) {
return;
+ }
+
+ if ((composite != null) &&
+ (composite instanceof AlphaComposite)) {
+ AlphaComposite ac = (AlphaComposite)composite;
+ if (ac.getAlpha() < 0.001)
+ return; // No point in drawing
}
//
---------------------------------------------------------------------
To unsubscribe, e-mail: batik-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-dev-help@xml.apache.org