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 vh...@apache.org on 2002/11/15 19:44:52 UTC

cvs commit: xml-batik/sources/org/apache/batik/bridge CSSUtilities.java CursorManager.java

vhardy      2002/11/15 10:44:52

  Modified:    samples/tests/spec/interactivity cursor4.svg
               sources/org/apache/batik/bridge CSSUtilities.java
                        CursorManager.java
  Log:
  No longers shows a broken image if an image referenced by a cursor
  cannot be retrieved. Instead, use the follow on <cursor> element
  or use the built-in cursor at the end of the list (thanks Thomas for
  pointing out the BROKEN_IMAGE property).
  
  Moved all of cursor code to CursorManager except the high-level
  conversion methods still available through CSSUtilities.
  
  
  
  
  
  Revision  Changes    Path
  1.2       +6 -5      xml-batik/samples/tests/spec/interactivity/cursor4.svg
  
  Index: cursor4.svg
  ===================================================================
  RCS file: /home/cvs/xml-batik/samples/tests/spec/interactivity/cursor4.svg,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- cursor4.svg	14 Nov 2002 14:57:25 -0000	1.1
  +++ cursor4.svg	15 Nov 2002 18:44:52 -0000	1.2
  @@ -15,7 +15,8 @@
   <!-- This test shows that JPEG, PNG and TIF formats are supported. It also     -->
   <!-- shows that SVG images are not supported for cursors and that BMP images   -->
   <!-- are not either. Unsupported image formats result in the same bahavior as  -->
  -<!-- 'broken images'. The cursor displays a broken image.                      -->
  +<!-- 'broken images'. The cursor falls back to the built in cursor specified   -->
  +<!-- at the end of the cursor list values.                                     -->
   <!--                                                                           -->
   <!-- @author vhardy@apache.org                                                 -->
   <!-- @version $Id$             -->
  @@ -103,7 +104,7 @@
   
       <g transform="translate(337.5, 394)" visibility="hidden" >
           <g id="refbrokenImage" visibility="visible">
  -            <text class="label" text-anchor="middle" y="40">Broken Image</text>
  +            <text class="label" text-anchor="middle" y="40">Broken Image<tspan dy="1.5em" x="0">defaults to crosshair</tspan></text>
               <use xlink:href="#brokenImage"  />
           </g>
           <g id="reftiffImage">
  @@ -119,11 +120,11 @@
               <use xlink:href="#jpegImage"  />
           </g>
           <g id="refunsupportedImage">
  -            <text class="label" text-anchor="middle" y="40">Unsupported Image (BMP)</text>
  +            <text class="label" text-anchor="middle" y="40">Unsupported Image (BMP)<tspan dy="1.5em" x="0">defaults to crosshair</tspan></text>
               <use xlink:href="#unsupportedImage"  />
           </g>
           <g id="refsvgImage">
  -            <text class="label" text-anchor="middle" y="40">SVG Image</text>
  +            <text class="label" text-anchor="middle" y="40">SVG Image<tspan dy="1.5em" x="0">defaults to crosshair</tspan></text>
               <use xlink:href="#svgImage"  />
           </g>
   
  
  
  
  1.40      +2 -138    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.39
  retrieving revision 1.40
  diff -u -r1.39 -r1.40
  --- CSSUtilities.java	14 Nov 2002 14:57:13 -0000	1.39
  +++ CSSUtilities.java	15 Nov 2002 18:44:52 -0000	1.40
  @@ -269,145 +269,9 @@
        */
       public static Cursor
           convertCursor(Element e, BridgeContext ctx) {
  -        Value cursorValue 
  -            = CSSUtilities.getComputedStyle(e, 
  -                                            SVGCSSEngine.CURSOR_INDEX);
  -        String cursorStr = SVGConstants.SVG_AUTO_VALUE;
  -        Cursor cursor = null;
  -        Element cursorElement = null;
  -
  -        if (cursorValue != null) {
  -            if (cursorValue.getCssValueType() ==  CSSValue.CSS_PRIMITIVE_VALUE
  -                &&
  -                cursorValue.getPrimitiveType() == CSSPrimitiveValue.CSS_IDENT) {
  -                // Single Value : should be one of the predefined cursors or 
  -                // 'inherit'
  -                cursorStr = cursorValue.getStringValue();
  -            } else if (cursorValue.getCssValueType() == CSSValue.CSS_VALUE_LIST) {
  -                ListValue l = (ListValue)cursorValue;
  -                int nValues = l.getLength();
  -                if (nValues == 1) {
  -                    cursorValue = l.item(nValues-1);
  -                    if (cursorValue.getPrimitiveType() == CSSPrimitiveValue.CSS_IDENT) {
  -                        cursorStr = cursorValue.getStringValue();
  -                    }
  -                } else {
  -                    //
  -                    // Look for the first cursor url we can handle.
  -                    // That would be a reference to a <cursor> element.
  -                    //
  -                    cursorElement = null;
  -                    for (int i=0; i<nValues-1; i++) {
  -                        cursorValue = l.item(i);
  -                        if (cursorValue.getPrimitiveType() == CSSPrimitiveValue.CSS_URI) {
  -                            String uri = cursorValue.getStringValue();
  -                            
  -                            // If the uri does not resolve to a cursor element,
  -                            // then, this is not a type of cursor uri we can handle:
  -                            // go to the next or default to logical cursor
  -                            try {
  -                                cursorElement = ctx.getReferencedElement(e, uri);
  -                            } catch (BridgeException be) {
  -                                // Be only silent if this is a case where the target
  -                                // could not be found. Do not catch other errors (e.g,
  -                                // malformed URIs)
  -                                if (!ERR_URI_BAD_TARGET.equals(be.getCode())) {
  -                                    throw be;
  -                                }
  -                            }
  -
  -                            if (cursorElement != null) {
  -                                // We go an element, check it is of type cursor
  -                                String cursorNS = cursorElement.getNamespaceURI();
  -                                if (SVGConstants.SVG_NAMESPACE_URI.equals(cursorNS)
  -                                    &&
  -                                    SVGConstants.SVG_CURSOR_TAG.equals(cursorElement.getNodeName())) {
  -                                    break;
  -                                }
  -                            }
  -                            cursorElement = null;
  -                        }
  -                    }
  -
  -                    if (cursorElement == null) {
  -                        if (nValues > 0) {
  -                            cursorValue = l.item(nValues-1);
  -                            if (cursorValue.getPrimitiveType() == CSSPrimitiveValue.CSS_IDENT) {
  -                                cursorStr = cursorValue.getStringValue();
  -                            }
  -                        }
  -                    }
  -                }
  -            }
  -        } 
  -        
  -        if (cursorElement != null) {
  -            return ctx.getCursorManager().convertSVGCursor(cursorElement);
  -        } 
  -        
  -        return convertBuiltInCursor(e, cursorStr);
  -    }
  -
  -
  -    public static final Cursor convertBuiltInCursor(Element e, String cursorStr) {
  -        Cursor cursor = null;
  -
  -        // The CSS engine guarantees an non null, non empty string
  -        // as the computed value for cursor. Therefore, the following
  -        // test is safe.
  -        if (cursorStr.charAt(0) == 'a') { 
  -            //
  -            // Handle 'auto' value.
  -            //
  -            // - <a> The following sets the cursor for <a> element enclosing
  -            //   text nodes. Setting the proper cursor (i.e., depending on the
  -            //   children's 'cursor' property, is handled in the SVGAElementBridge
  -            //   so as to avoid going up the tree on mouseover events (looking for
  -            //   an anchor ancestor.
  -            //
  -            // - <image> The following does not change the cursor if the 
  -            //   element's cursor property is set to 'auto'. Otherwise, it takes
  -            //   precedence over any child (in case of SVG content) cursor setting.
  -            //   This means that for images referencing SVG content, a cursor 
  -            //   property set to 'auto' on the <image> element will not override 
  -            //   the cursor settings inside the SVG image. Any other cursor property
  -            //   will take precedence.
  -            //
  -            // - <use> Same behavior as for <image> except that the behavior 
  -            //   is controlled from the <use> element bridge (SVGUseElementBridge).
  -            //
  -            // - <text>, <tref> and <tspan> : a cursor value of auto will cause the
  -            //   cursor to be set to a text cursor. Note that text content with an
  -            //   'auto' cursor and descendant of an anchor will have its cursor
  -            //   set to the anchor cursor through the SVGAElementBridge.
  -            //
  -            String nameSpaceURI = e.getNamespaceURI();
  -            String tag = e.getNodeName();
  -            if (SVGConstants.SVG_NAMESPACE_URI.equals(nameSpaceURI)) {
  -                if (SVGConstants.SVG_A_TAG.equals(tag)) {
  -                    cursor = CursorManager.ANCHOR_CURSOR;
  -                } else if (SVGConstants.SVG_TEXT_TAG.equals(tag) ||
  -                           SVGConstants.SVG_TSPAN_TAG.equals(tag) ||
  -                           SVGConstants.SVG_TREF_TAG.equals(tag) ) {
  -                    cursor = CursorManager.TEXT_CURSOR;
  -                } else if (SVGConstants.SVG_IMAGE_TAG.equals(tag)) {
  -                    // Do not change the cursor 
  -                    return null;
  -                } else {
  -                    cursor = CursorManager.DEFAULT_CURSOR;
  -                }
  -            } else {
  -                cursor = CursorManager.DEFAULT_CURSOR;
  -            }
  -        } else {
  -            // Specific, logical cursor
  -            cursor = CursorManager.getPredefinedCursor(cursorStr);
  -        }
  -        
  -        return cursor;
  +        return ctx.getCursorManager().convertCursor(e);
       }
   
  -       
       ////////////////////////////////////////////////////////////////////////
       // 'color-rendering', 'text-rendering', 'image-rendering',
       // 'shape-rendering'
  
  
  
  1.5       +191 -11   xml-batik/sources/org/apache/batik/bridge/CursorManager.java
  
  Index: CursorManager.java
  ===================================================================
  RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/CursorManager.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- CursorManager.java	14 Nov 2002 19:44:49 -0000	1.4
  +++ CursorManager.java	15 Nov 2002 18:44:52 -0000	1.5
  @@ -30,6 +30,11 @@
   import org.apache.batik.ext.awt.image.spi.ImageTagRegistry;
   import org.apache.batik.ext.awt.image.renderable.Filter;
   
  +import org.apache.batik.css.engine.SVGCSSEngine;
  +import org.apache.batik.css.engine.value.ListValue;
  +import org.apache.batik.css.engine.value.StringValue;
  +import org.apache.batik.css.engine.value.Value;
  +
   import org.apache.batik.dom.util.XLinkSupport;
   import org.apache.batik.dom.svg.XMLBaseSupport;
   import org.apache.batik.util.SVGConstants;
  @@ -37,6 +42,9 @@
   import org.apache.batik.util.SoftReferenceCache;
   
   import org.w3c.dom.Element;
  +import org.w3c.dom.css.CSSPrimitiveValue;
  +import org.w3c.dom.css.CSSValue;
  +
   
   /**
    * The CursorManager class is a helper class which preloads the cursors 
  @@ -45,7 +53,7 @@
    * @author <a href="mailto:vincent.hardy@sun.com">Vincent Hardy</a>
    * @version $Id$
    */
  -public class CursorManager implements SVGConstants {
  +public class CursorManager implements SVGConstants, ErrorConstants {
       /**
        * Maps SVG Cursor Values to Java Cursors
        */
  @@ -134,11 +142,168 @@
       public static Cursor getPredefinedCursor(String cursorName){
           return (Cursor)cursorMap.get(cursorName);
       }
  +
  +    /**
  +     * Returns the Cursor corresponding to the input element's cursor property
  +     *
  +     * @param e the element on which the cursor property is set
  +     */
  +    public Cursor convertCursor(Element e) {
  +        Value cursorValue 
  +            = CSSUtilities.getComputedStyle(e, 
  +                                            SVGCSSEngine.CURSOR_INDEX);
  +
  +        String cursorStr = SVGConstants.SVG_AUTO_VALUE;
  +
  +        if (cursorValue != null) {
  +            if (cursorValue.getCssValueType() ==  CSSValue.CSS_PRIMITIVE_VALUE
  +                &&
  +                cursorValue.getPrimitiveType() == CSSPrimitiveValue.CSS_IDENT) {
  +                // Single Value : should be one of the predefined cursors or 
  +                // 'inherit'
  +                cursorStr = cursorValue.getStringValue();
  +                return convertBuiltInCursor(e, cursorStr);
  +            } else if (cursorValue.getCssValueType() == CSSValue.CSS_VALUE_LIST) {
  +                ListValue l = (ListValue)cursorValue;
  +                int nValues = l.getLength();
  +                if (nValues == 1) {
  +                    cursorValue = l.item(nValues-1);
  +                    if (cursorValue.getPrimitiveType() == CSSPrimitiveValue.CSS_IDENT) {
  +                        cursorStr = cursorValue.getStringValue();
  +                        return convertBuiltInCursor(e, cursorStr);
  +                    }
  +                } else if (nValues > 1) {
  +                    //
  +                    // Look for the first cursor url we can handle.
  +                    // That would be a reference to a <cursor> element.
  +                    //
  +                    return convertSVGCursor(e, l);
  +                }
  +            }
  +        } 
  +        
  +        return convertBuiltInCursor(e, cursorStr);
  +    }
       
  +    public Cursor convertBuiltInCursor(Element e, String cursorStr) {
  +        Cursor cursor = null;
  +
  +        // The CSS engine guarantees an non null, non empty string
  +        // as the computed value for cursor. Therefore, the following
  +        // test is safe.
  +        if (cursorStr.charAt(0) == 'a') { 
  +            //
  +            // Handle 'auto' value.
  +            //
  +            // - <a> The following sets the cursor for <a> element enclosing
  +            //   text nodes. Setting the proper cursor (i.e., depending on the
  +            //   children's 'cursor' property, is handled in the SVGAElementBridge
  +            //   so as to avoid going up the tree on mouseover events (looking for
  +            //   an anchor ancestor.
  +            //
  +            // - <image> The following does not change the cursor if the 
  +            //   element's cursor property is set to 'auto'. Otherwise, it takes
  +            //   precedence over any child (in case of SVG content) cursor setting.
  +            //   This means that for images referencing SVG content, a cursor 
  +            //   property set to 'auto' on the <image> element will not override 
  +            //   the cursor settings inside the SVG image. Any other cursor property
  +            //   will take precedence.
  +            //
  +            // - <use> Same behavior as for <image> except that the behavior 
  +            //   is controlled from the <use> element bridge (SVGUseElementBridge).
  +            //
  +            // - <text>, <tref> and <tspan> : a cursor value of auto will cause the
  +            //   cursor to be set to a text cursor. Note that text content with an
  +            //   'auto' cursor and descendant of an anchor will have its cursor
  +            //   set to the anchor cursor through the SVGAElementBridge.
  +            //
  +            String nameSpaceURI = e.getNamespaceURI();
  +            String tag = e.getNodeName();
  +            if (SVGConstants.SVG_NAMESPACE_URI.equals(nameSpaceURI)) {
  +                if (SVGConstants.SVG_A_TAG.equals(tag)) {
  +                    cursor = CursorManager.ANCHOR_CURSOR;
  +                } else if (SVGConstants.SVG_TEXT_TAG.equals(tag) ||
  +                           SVGConstants.SVG_TSPAN_TAG.equals(tag) ||
  +                           SVGConstants.SVG_TREF_TAG.equals(tag) ) {
  +                    cursor = CursorManager.TEXT_CURSOR;
  +                } else if (SVGConstants.SVG_IMAGE_TAG.equals(tag)) {
  +                    // Do not change the cursor 
  +                    return null;
  +                } else {
  +                    cursor = CursorManager.DEFAULT_CURSOR;
  +                }
  +            } else {
  +                cursor = CursorManager.DEFAULT_CURSOR;
  +            }
  +        } else {
  +            // Specific, logical cursor
  +            cursor = CursorManager.getPredefinedCursor(cursorStr);
  +        }
  +        
  +        return cursor;
  +    }
  +
  +       
       /**
  -     * Returns a cursor for the given cursorElement
  +     * Returns a cursor for the given value list. Note that the 
  +     * code assumes that the input value has at least two entries.
  +     * So the caller should check that before calling the method.
  +     * For example, CSSUtilities.convertCursor performs that check.
  +     */
  +    public Cursor convertSVGCursor(Element e, ListValue l) {
  +        int nValues = l.getLength();
  +        Element cursorElement = null;
  +        for (int i=0; i<nValues-1; i++) {
  +            Value cursorValue = l.item(i);
  +            if (cursorValue.getPrimitiveType() == CSSPrimitiveValue.CSS_URI) {
  +                String uri = cursorValue.getStringValue();
  +                
  +                // If the uri does not resolve to a cursor element,
  +                // then, this is not a type of cursor uri we can handle:
  +                // go to the next or default to logical cursor
  +                try {
  +                    cursorElement = ctx.getReferencedElement(e, uri);
  +                } catch (BridgeException be) {
  +                    // Be only silent if this is a case where the target
  +                    // could not be found. Do not catch other errors (e.g,
  +                    // malformed URIs)
  +                    if (!ERR_URI_BAD_TARGET.equals(be.getCode())) {
  +                        throw be;
  +                    }
  +                }
  +                
  +                if (cursorElement != null) {
  +                    // We go an element, check it is of type cursor
  +                    String cursorNS = cursorElement.getNamespaceURI();
  +                    if (SVGConstants.SVG_NAMESPACE_URI.equals(cursorNS)
  +                        &&
  +                        SVGConstants.SVG_CURSOR_TAG.equals(cursorElement.getNodeName())) {
  +                        Cursor c = convertSVGCursorElement(cursorElement);
  +                        if (c != null) { 
  +                            return c;
  +                        }
  +                    }
  +                }
  +            }
  +        }
  +        
  +        // If we got to that point, it means that no cursorElement
  +        // produced a valid cursor, i.e., either a format we support
  +        // or a valid referenced image (no broken image).
  +        // Fallback on the built in cursor property.
  +        Value cursorValue = l.item(nValues-1);
  +        String cursorStr = SVGConstants.SVG_AUTO_VALUE;
  +        if (cursorValue.getPrimitiveType() == CSSPrimitiveValue.CSS_IDENT) {
  +            cursorStr = cursorValue.getStringValue();
  +        }
  +          
  +        return convertBuiltInCursor(e, cursorStr);
  +    }
  +
  +    /**
  +     * Returns a cursor for a given element
        */
  -    public Cursor convertSVGCursor(Element cursorElement) {
  +    public Cursor convertSVGCursorElement(Element cursorElement) {
           // One of the cursor url resolved to a <cursor> element
           // Try to handle its image.
           String uriStr = XLinkSupport.getXLinkHref(cursorElement);
  @@ -182,12 +347,23 @@
           ImageTagRegistry reg = ImageTagRegistry.getRegistry();
           Filter f = reg.readURL(purl);
   
  +
  +        //
  +        // Check if we got a broken image
  +        //
  +        if (f.getProperty
  +            (SVGBrokenLinkProvider.SVG_BROKEN_LINK_DOCUMENT_PROPERTY) != null) {
  +            cursorCache.clearCursor(desc);
  +            return null;
  +        } 
  +            
           //
           // Now, get the preferred cursor dimension
           //
           Rectangle preferredSize = f.getBounds2D().getBounds();
           if (preferredSize == null || preferredSize.width <=0
               || preferredSize.height <=0 ) {
  +            cursorCache.clearCursor(desc);
               return null;
           }
   
  @@ -215,14 +391,14 @@
                   rh = cursorSize.height;
               }
               
  -            RenderedImage img = f.createScaledRendering((int)Math.round(rw),
  -                                                        (int)Math.round(rh),
  -                                                        null);
  +            RenderedImage ri = f.createScaledRendering((int)Math.round(rw),
  +                                                       (int)Math.round(rh),
  +                                                       null);
               
  -            if (img instanceof Image) {
  -                bi = (Image)img;
  +            if (ri instanceof Image) {
  +                bi = (Image)ri;
               } else {
  -                bi = renderedImageToImage(img);
  +                bi = renderedImageToImage(ri);
               }
   
               // Apply the scale transform that is applied to the image
  @@ -252,7 +428,7 @@
           y = y > (cursorSize.height-1) ? cursorSize.height - 1: y;
   
           //
  -        // The cursor image is not into the bi image
  +        // The cursor image is now into the bi image
           //
           Cursor c = Toolkit.getDefaultToolkit()
               .createCustomCursor(bi, 
  @@ -349,6 +525,10 @@
           public void putCursor(CursorDescriptor desc, 
                                 Cursor cursor) {
               putImpl(desc, cursor);
  +        }
  +
  +        public void clearCursor(CursorDescriptor desc) {
  +            clearImpl(desc);
           }
       }
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: batik-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: batik-dev-help@xml.apache.org