vhardy      2003/07/09 10:37:16

  Modified:    sources/org/apache/batik/bridge SVGFeImageElementBridge.java
  Added:       samples/tests/spec/filters feImage2.svg
  Log:
  Resolved bug #8854 on feImage complete implementation. Added new regression test on 
feImage
  
  Revision  Changes    Path
  1.1                  xml-batik/samples/tests/spec/filters/feImage2.svg
  
  Index: feImage2.svg
  ===================================================================
  <?xml version="1.0" standalone="no"?>
  <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
  "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.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.                                                         -->
  <!-- ========================================================================= -->
  
  <!-- ========================================================================= -->
  <!-- Drill down test on feImage                                                -->
  <!--                                                                           -->
  <!-- @author [EMAIL PROTECTED]                                             -->
  <!-- @version $Id $  -->
  <!-- ========================================================================= -->
  
  <?xml-stylesheet type="text/css" href="../../resources/style/test.css" ?>
  
  <svg xmlns="http://www.w3.org/2000/svg"; xmlns:xlink="http://www.w3.org/1999/xlink"; 
id="body" width="450" height="500" viewBox="0 0 450 500">
  <title>feImage Test</title>
      
      <!-- ============================================================= -->
      <!-- Test content                                                  -->
      <!-- ============================================================= -->
      <g id="testContent">
  
          <text x="225" y="40" class="title">
              feImage Test
          </text>
          
          <defs>
  
              <symbol id="symbol" viewBox="0 0 1 1">
                  <circle cx="0.5" cy="0.5" r="0.5" fill="orange" />
              </symbol>
  
              <svg id="svg" viewBox="0 0 1 1">
                  <circle cx="0.5" cy="0.5" r="0.5" fill="crimson" />
              </svg>
  
              <g id="common">
                  <circle cx="20" cy="20" r="20" fill="gold" />
              </g>
  
              <g id="commonBB">
                  <circle cx="0.5" cy="0.5" r="0.5" fill="gold" />
              </g>
  
              <filter id="symbolFilter" filterUnits="userSpaceOnUse" x="40" y="40" 
width="40" height="40">
                  <feImage xlink:href="#symbol" result="image"/>
              </filter>
  
              <filter id="svgFilter" filterUnits="userSpaceOnUse" x="40" y="40" 
width="40" height="40">
                  <feImage xlink:href="#svg" result="image"/>
              </filter>
  
              <filter id="commonFilter" filterUnits="userSpaceOnUse" x="0" y="0" 
width="40" height="40">
                  <feImage xlink:href="#common" result="image"/>
              </filter>
  
              <filter id="symbolFilterBB" primitiveUnits="objectBoundingBox" 
                      filterUnits="userSpaceOnUse" x="40" y="40" width="40" 
height="40">
                  <feImage xlink:href="#symbol" result="image" x="1" y="1" width="1" 
height="1"/>
              </filter>
  
              <filter id="svgFilterBB" primitiveUnits="objectBoundingBox" 
                      filterUnits="userSpaceOnUse" x="40" y="40" width="40" 
height="40">
                  <feImage xlink:href="#svg" result="image" x="1" y="1" width="1" 
height="1"/>
              </filter>
  
              <filter id="commonFilterBB" primitiveUnits="objectBoundingBox" 
                      filterUnits="userSpaceOnUse" x="0" y="0" width="40" height="40">
                  <feImage xlink:href="#commonBB" result="image" x="0" y="0" width="1" 
height="1"/>
              </filter>
  
          </defs>
  
          <g transform="translate(0,50)">
              <g transform="translate(50, 50)">
                  <use id="useSymbol" xlink:href="#symbol" x="40" y="40" width="40" 
height="40" />
                  <text x="60" y="30" text-anchor="middle">&lt;symbol&gt;</text>
              </g>
  
              <g transform="translate(150, 50)">
                  <use id="useSvg" xlink:href="#svg" x="40" y="40" width="40" 
height="40" />
                  <text x="60" y="30" text-anchor="middle">&lt;svg&gt;</text>
              </g>
  
              <g transform="translate(250, 50)">
                  <use xlink:href="#common" x="40" y="40"/>
                  <text x="60" y="30" text-anchor="middle">&lt;g&gt;</text>
              </g>
          </g>
  
          <g transform="translate(0, 150)">
              <g transform="translate(50, 50)">
                  <g filter="url(#symbolFilter)" />
                  <text x="60" y="30" text-anchor="middle"><tspan x="60" 
y="15">feImage</tspan>
                                                           <tspan x="60" 
y="30">&lt;symbol&gt;</tspan></text>
              </g>
              <g transform="translate(150, 50)">
                  <g filter="url(#svgFilter)" />
                  <text x="60" y="30" text-anchor="middle"><tspan x="60" 
y="15">feImage</tspan>
                                                           <tspan x="60" 
y="30">&lt;svg&gt;</tspan></text>
              </g>
              <g transform="translate(250, 50)">
                  <g transform="translate(40, 40)" filter="url(#commonFilter)" />
                  <text x="60" y="30" text-anchor="middle"><tspan x="60" 
y="15">feImage</tspan>
                                                           <tspan x="60" 
y="30">&lt;g&gt;</tspan></text>
              </g>
          </g>
  
          <g transform="translate(0, 250)">
              <g transform="translate(50, 50)">
                  <g filter="url(#symbolFilterBB)">
                      <rect width="40" height="40" />
                  </g>
                  <text x="60" y="30" text-anchor="middle"><tspan x="60" 
y="15">feImage ObjBBox</tspan>
                                                           <tspan x="60" 
y="30">&lt;symbol&gt;</tspan></text>
              </g>
  
              <g transform="translate(150, 50)">
                  <g filter="url(#svgFilterBB)">
                      <rect width="40" height="40" />
                  </g>
                  <text x="60" y="30" text-anchor="middle"><tspan x="60" 
y="15">feImage ObjBBox</tspan>
                                                           <tspan x="60" 
y="30">&lt;svg&gt;</tspan></text>
              </g>
  
              <g transform="translate(250, 50)">
                  <g transform="translate(40, 40)" filter="url(#commonFilterBB)">
                      <rect width="40" height="40" />
                  </g>
                  <text x="60" y="30" text-anchor="middle"><tspan x="60" 
y="15">feImage ObjBBox</tspan>
                                                           <tspan x="60" 
y="30">&lt;g&gt;</tspan></text>
              </g>
  
          </g>
  
      </g>
  
      <!-- ============================================================= -->
      <!-- Batik sample mark                                             -->
      <!-- ============================================================= -->
      <use xlink:href="../../../batikLogo.svg#Batik_Tag_Box" />
      
  </svg>
  
  
  
  1.19      +84 -45    
xml-batik/sources/org/apache/batik/bridge/SVGFeImageElementBridge.java
  
  Index: SVGFeImageElementBridge.java
  ===================================================================
  RCS file: 
/home/cvs/xml-batik/sources/org/apache/batik/bridge/SVGFeImageElementBridge.java,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- SVGFeImageElementBridge.java      11 Apr 2003 13:54:47 -0000      1.18
  +++ SVGFeImageElementBridge.java      9 Jul 2003 17:37:16 -0000       1.19
  @@ -9,12 +9,14 @@
   package org.apache.batik.bridge;
   
   import java.awt.geom.AffineTransform;
  +import java.awt.geom.NoninvertibleTransformException;
   import java.awt.geom.Rectangle2D;
   import java.net.URL;
   import java.util.Map;
   
   import org.apache.batik.dom.svg.SVGOMDocument;
   import org.apache.batik.dom.util.XLinkSupport;
  +import org.apache.batik.util.XMLConstants;
   import org.apache.batik.ext.awt.image.PadMode;
   import org.apache.batik.ext.awt.image.renderable.AffineRable8Bit;
   import org.apache.batik.ext.awt.image.renderable.Filter;
  @@ -22,6 +24,7 @@
   import org.apache.batik.ext.awt.image.spi.ImageTagRegistry;
   import org.apache.batik.gvt.GraphicsNode;
   import org.apache.batik.util.ParsedURL;
  +import org.w3c.dom.Document;
   import org.w3c.dom.Element;
   import org.w3c.dom.Node;
   import org.w3c.dom.svg.SVGDocument;
  @@ -80,68 +83,104 @@
                                         new Object[] {"xlink:href"});
           }
   
  +        //
  +        // According the the SVG specification, feImage behaves like
  +        // <image> if it references an SVG document or a raster image
  +        // and it behaves like a <use> if it references a document
  +        // fragment.
  +        //
  +        // To provide this behavior, depending on whether the uri 
  +        // contains a fragment identifier, we create either an 
  +        // <image> or a <use> element and request the corresponding
  +        // bridges to build the corresponding GraphicsNode for us.
  +        // 
  +        // Then, we take care of the possible transformation needed 
  +        // from objectBoundingBox space to user space.
  +        //
  +        
  +        GraphicsNode gn = null;
  +        Document document = filterElement.getOwnerDocument();
  +        boolean isUse = (uriStr.indexOf("#") != -1);
  +        Element contentElement = null;
  +        if (isUse) {
  +            contentElement = document.createElementNS(SVG_NAMESPACE_URI,
  +                                                    SVG_USE_TAG);
  +        } else {
  +            contentElement = document.createElementNS(SVG_NAMESPACE_URI,
  +                                                    SVG_IMAGE_TAG);
  +        }
  +
  +        
  +        contentElement.setAttributeNS(XLinkSupport.XLINK_NAMESPACE_URI, 
XMLConstants.XLINK_PREFIX + 
  +                                    ":" + SVG_HREF_ATTRIBUTE,
  +                                    uriStr);
  +
  +        Element proxyElement = document.createElementNS(SVG_NAMESPACE_URI,
  +                                                        SVG_G_TAG);
  +        proxyElement.appendChild(contentElement);
  +
           // feImage's default region is that of the filter chain.
           Rectangle2D defaultRegion = filterRegion;
   
  +        // Compute the transform from object bounding box to user
  +        // space if needed.
  +        AffineTransform at = new AffineTransform();
  +
  +        // 'primitiveUnits' attribute - default is userSpaceOnUse
  +        short coordSystemType;
  +        Element filterDefElement = (Element)(filterElement.getParentNode());
  +        boolean isBBox = false;
  +        String s = SVGUtilities.getChainableAttributeNS
  +            (filterDefElement, null, SVG_PRIMITIVE_UNITS_ATTRIBUTE, ctx);
  +        if (s.length() == 0) {
  +            coordSystemType = SVGUtilities.USER_SPACE_ON_USE;
  +        } else {
  +                coordSystemType = SVGUtilities.parseCoordinateSystem
  +                    (filterDefElement, SVG_PRIMITIVE_UNITS_ATTRIBUTE, s);
  +        }
  +        
  +        if (coordSystemType == SVGUtilities.OBJECT_BOUNDING_BOX) {
  +            isBBox = true;
  +            at = SVGUtilities.toObjectBBox(at, filteredNode);
  +        }
  +        
           // get filter primitive chain region
  -        Rectangle2D primitiveRegion
  +        Rectangle2D primitiveRegionUserSpace
               = SVGUtilities.convertFilterPrimitiveRegion(filterElement,
                                                           filteredElement,
                                                           filteredNode,
                                                           defaultRegion,
                                                           filterRegion,
                                                           ctx);
  +        Rectangle2D primitiveRegion = primitiveRegionUserSpace;
   
  -        Filter filter = null;
  -        // try to load the image as an svg document
  -        SVGDocument svgDoc = (SVGDocument)filterElement.getOwnerDocument();
  -        ParsedURL purl;
  -        URL baseURL = ((SVGOMDocument)svgDoc).getURLObject();
  -        if (baseURL != null)
  -            purl = new ParsedURL(baseURL.toString(), uriStr);
  -        else
  -            purl = new ParsedURL(uriStr);
  -
  -        // try to load an SVG document
  -        DocumentLoader loader = ctx.getDocumentLoader();
  -        URIResolver resolver = new URIResolver(svgDoc, loader);
  -        boolean toBBoxNeeded = false;
  -        try {
  -            Element refElement = null;
  -            Node n = resolver.getNode(purl.toString(), filterElement);
  -            if (n.getNodeType() == n.DOCUMENT_NODE) {
  -                refElement = ((SVGDocument)n).getRootElement();
  -            } else if (n.getNodeType() == Node.ELEMENT_NODE) {
  -                refElement = (Element)n;
  -                toBBoxNeeded = true;
  -            } else {
  -                throw new BridgeException
  -                    (filterElement, ERR_URI_IMAGE_INVALID,
  -                     new Object[] {uriStr});
  +        if (isBBox) {
  +            try {
  +                AffineTransform ati = at.createInverse();
  +                primitiveRegion = 
ati.createTransformedShape(primitiveRegion).getBounds2D();
  +            } catch (NoninvertibleTransformException nite) {
  +                // Should never happen, seem above
  +                throw new Error();
               }
  -            filter = createSVGFeImage
  -                (ctx, primitiveRegion, refElement, toBBoxNeeded, filterElement, 
filteredNode);
  -        } catch (BridgeException ex) {
  -            throw ex;
  -        } catch (SecurityException ex) {
  -            throw new BridgeException(filterElement, ERR_URI_UNSECURE,
  -                                      new Object[] {uriStr});
  -        } catch (Exception ex) {/* Nothing to do */ }
  -
  -        if (filter == null) {
  -            // try to load the image as a raster image (JPG or PNG)
  -            filter = createRasterFeImage(ctx, primitiveRegion, purl);
           }
   
  -        if (filter == null) {
  -            throw new BridgeException(filterElement, ERR_URI_IMAGE_INVALID,
  -                                      new Object[] {"xlink:href", uriStr});
  -        }
  +        contentElement.setAttributeNS(null, SVG_X_ATTRIBUTE, "" + 
primitiveRegion.getX());
  +        contentElement.setAttributeNS(null, SVG_Y_ATTRIBUTE, "" + 
primitiveRegion.getY());
  +        contentElement.setAttributeNS(null, SVG_WIDTH_ATTRIBUTE, "" + 
primitiveRegion.getWidth());
  +        contentElement.setAttributeNS(null, SVG_HEIGHT_ATTRIBUTE, "" + 
primitiveRegion.getHeight());
  +        
  +        // System.err.println(">>>>>>>>>>>> primitiveRegion : " + primitiveRegion);
  +        // System.err.println(">>>>>>>>>>>> at              : " + at);
  +
  +        GraphicsNode node = ctx.getGVTBuilder().build(ctx, proxyElement);
  +        Filter filter = node.getGraphicsNodeRable(true);
  +        
  +        filter = new AffineRable8Bit(filter, at);
   
           // handle the 'color-interpolation-filters' property
           handleColorInterpolationFilters(filter, filterElement);
   
  -        filter = new PadRable8Bit(filter, primitiveRegion, PadMode.ZERO_PAD);
  +        filter = new PadRable8Bit(filter, primitiveRegionUserSpace, 
PadMode.ZERO_PAD);
   
           // update the filter Map
           updateFilterMap(filterElement, filter, filterMap);
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to