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