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:[EMAIL PROTECTED]">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:[EMAIL PROTECTED]">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:[EMAIL PROTECTED]">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:[EMAIL PROTECTED]">Thierry Kormann</a> * @author <a href="mailto:[EMAIL PROTECTED]">Emmanuel Tissandier</a> * @author <a href="mailto:[EMAIL PROTECTED]">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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]