1.  Fixed regression with DOM updates to rect elements' rx and ry attributes.
2.  The xlink:href attribute of image elements is animatable.
3.  Fixed error in the SVGTransform.setSkew[XY] implementations.
4.  Fixed problem with animating preserveAspectRatios attributes.
5.  Extension elements now do not need to provide override style declarations.
6.  Fixed problem with animatable attributes on use elements.
7.  SVG 1.2 multiImage element uses unanimated attribute values properly
    (before it was throwing exceptions).
8.  Various Errors thrown are now IllegalArgumentExceptions.
9.  Fixed regression with 'a' elements that are children of text elements.
10. Avoided warnings about varargs methods in the Rhino debugger code in
    JSVGViewerFrame.
11. Changed the SVGConverter.ERROR_UNABLE_TO_CREATE_OUTPUT_DIR test so that
    it also fails to create the directory under Unix.
12. Introduced org.apache.batik.extension.GraphicsExtensionElement that provides
    support for SVG interfaces common to graphics elements (SVGTransformable,
    SVGLocatable, etc.).


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/batik/branches/anim@426885 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/build.xml b/build.xml
index 2852f8b..d7d54b9 100644
--- a/build.xml
+++ b/build.xml
@@ -337,7 +337,7 @@
     <echo message="debug ${debug}, optimize ${optimize}, deprecation ${deprecation}"/>
 
     <javac srcdir="${testsrc}" destdir="${dest}"  deprecation="${deprecation}" 
-           debug="${debug}" optimize="${optimize}" >
+           debug="${debug}" optimize="${optimize}" encoding="UTF-8">
       <classpath>
         <pathelement location="${dest}" />
         <path refid="libs-classpath"/>
@@ -362,7 +362,7 @@
     <echo message="debug ${debug}, optimize ${optimize}, deprecation ${deprecation}"/>
 
     <javac srcdir="${samples}/tests/resources/java/sources" destdir="${samples}/tests/resources/java/classes"  deprecation="${deprecation}" 
-           debug="${debug}" optimize="${optimize}" >
+           debug="${debug}" optimize="${optimize}" encoding="UTF-8">
       <classpath>
         <pathelement location="${dest}" />
         <pathelement location="${samples}/tests/resources/java/classes" />
@@ -372,7 +372,7 @@
     </javac>
 
     <javac srcdir="${testresources}" destdir="${testresources}/classes"  deprecation="${deprecation}" 
-           debug="${debug}" optimize="${optimize}" >
+           debug="${debug}" optimize="${optimize}" encoding="UTF-8">
       <classpath>
         <pathelement location="${dest}" />
         <pathelement location="${testresources}/classes" />
@@ -449,7 +449,7 @@
   <target name       ="compile"
           depends    ="init, compile-prepare">
     <javac destdir="${dest}" deprecation="${deprecation}" 
-           debug="${debug}" optimize="${optimize}">
+           debug="${debug}" optimize="${optimize}" encoding="UTF-8">
       <src path="${src}"/>
       <src path="${src-jdk}"/>
       <classpath refid="libs-classpath"/>
diff --git a/sources-1.4/org/apache/batik/ext/awt/image/codec/imageio/AbstractImageIORegistryEntry.java b/sources-1.4/org/apache/batik/ext/awt/image/codec/imageio/AbstractImageIORegistryEntry.java
index 264e3c3..8eea5f0 100755
--- a/sources-1.4/org/apache/batik/ext/awt/image/codec/imageio/AbstractImageIORegistryEntry.java
+++ b/sources-1.4/org/apache/batik/ext/awt/image/codec/imageio/AbstractImageIORegistryEntry.java
@@ -124,7 +124,7 @@
                                       reader.getWidth(imageIndex), 
                                       reader.getHeight(imageIndex)));
                         CachableRed cr;
-                        //Naïve approach probably wasting lots of memory
+                        //Naïve approach probably wasting lots of memory
                         //and ignoring the gamma correction done by PNGRed :-(
                         BufferedImage bi = reader.read(imageIndex);
                         cr = GraphicsUtil.wrap(bi);
diff --git a/sources/org/apache/batik/Version.java b/sources/org/apache/batik/Version.java
index bb44852..c432409 100755
--- a/sources/org/apache/batik/Version.java
+++ b/sources/org/apache/batik/Version.java
@@ -39,20 +39,20 @@
      *   <tr>
      *     <th>Source</th>
      *     <th>Version string</th>
-     *   <tr>
      *   </tr>
+     *   <tr>
      *     <td>Release version</td>
      *     <td><em>version</em></td>
-     *   <tr>
      *   </tr>
+     *   <tr>
      *     <td>Trunk</td>
      *     <td>SVN+<em>yyyymmdd</em></td>
-     *   <tr>
      *   </tr>
+     *   <tr>
      *     <td>Branch</td>
      *     <td><em>branch-name</em> branch; SVN+<em>yyyymmdd</em></td>
      *   </tr>
-     *   </tr>
+     *   <tr>
      *     <td>Unknown</td>
      *     <td>development version</td>
      *   </tr>
diff --git a/sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java b/sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java
index 787083b..7b63938 100755
--- a/sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java
+++ b/sources/org/apache/batik/apps/svgbrowser/JSVGViewerFrame.java
@@ -901,16 +901,17 @@
                 debuggerConstructor =
                     dc.getConstructor(new Class[] { String.class });
                 debuggerMethods = new Method[] {
-                    dc.getMethod("clearAllBreakpoints", null),
-                    dc.getMethod("go", null),
+                    dc.getMethod("clearAllBreakpoints", (Class[]) null),
+                    dc.getMethod("go", (Class[]) null),
                     dc.getMethod("setExitAction", new Class[] {Runnable.class}),
                     dc.getMethod("attachTo", new Class[] { cfc }),
-                    dc.getMethod("detach", null),
-                    dc.getMethod("dispose", null),
-                    dc.getMethod("getDebugFrame", null)
+                    dc.getMethod("detach", (Class[]) null),
+                    dc.getMethod("dispose", (Class[]) null),
+                    dc.getMethod("getDebugFrame", (Class[]) null)
                 };
                 getContextFactoryMethod =
-                    rhinoInterpreterClass.getMethod("getContextFactory", null);
+                    rhinoInterpreterClass.getMethod("getContextFactory",
+                                                    (Class[]) null);
                 debuggerClass = dc;
                 isPresent = true;
             } catch (ClassNotFoundException cnfe) {
@@ -1001,7 +1002,7 @@
         protected JFrame getDebugFrame() {
             try {
                 return (JFrame) debuggerMethods[GET_DEBUG_FRAME_METHOD].invoke
-                    (debuggerInstance, null);
+                    (debuggerInstance, (Object[]) null);
             } catch (InvocationTargetException ite) {
                 throw new RuntimeException(ite);
             } catch (IllegalAccessException iae) {
@@ -1042,7 +1043,8 @@
          */
         public void detach() {
             try {
-                debuggerMethods[DETACH_METHOD].invoke(debuggerInstance, null);
+                debuggerMethods[DETACH_METHOD].invoke(debuggerInstance,
+                                                      (Object[]) null);
             } catch (InvocationTargetException ite) {
                 throw new RuntimeException(ite);
             } catch (IllegalAccessException iae) {
@@ -1055,7 +1057,8 @@
          */
         public void go() {
             try {
-                debuggerMethods[GO_METHOD].invoke(debuggerInstance, null);
+                debuggerMethods[GO_METHOD].invoke(debuggerInstance,
+                                                  (Object[]) null);
             } catch (InvocationTargetException ite) {
                 throw new RuntimeException(ite);
             } catch (IllegalAccessException iae) {
@@ -1069,7 +1072,7 @@
         public void clearAllBreakpoints() {
             try {
                 debuggerMethods[CLEAR_ALL_BREAKPOINTS_METHOD].invoke
-                    (debuggerInstance, null);
+                    (debuggerInstance, (Object[]) null);
             } catch (InvocationTargetException ite) {
                 throw new RuntimeException(ite);
             } catch (IllegalAccessException iae) {
@@ -1082,7 +1085,8 @@
          */
         public void dispose() {
             try {
-                debuggerMethods[DISPOSE_METHOD].invoke(debuggerInstance, null);
+                debuggerMethods[DISPOSE_METHOD].invoke(debuggerInstance,
+                                                       (Object[]) null);
             } catch (InvocationTargetException ite) {
                 throw new RuntimeException(ite);
             } catch (IllegalAccessException iae) {
@@ -1096,7 +1100,8 @@
          */
         protected Object getContextFactory(Object rhinoInterpreter) {
             try {
-                return getContextFactoryMethod.invoke(rhinoInterpreter, null);
+                return getContextFactoryMethod.invoke(rhinoInterpreter,
+                                                      (Object[]) null);
             } catch (InvocationTargetException ite) {
                 throw new RuntimeException(ite);
             } catch (IllegalAccessException iae) {
diff --git a/sources/org/apache/batik/bridge/AbstractGraphicsNodeBridge.java b/sources/org/apache/batik/bridge/AbstractGraphicsNodeBridge.java
index 55d7d45..f2f6113 100644
--- a/sources/org/apache/batik/bridge/AbstractGraphicsNodeBridge.java
+++ b/sources/org/apache/batik/bridge/AbstractGraphicsNodeBridge.java
@@ -188,11 +188,7 @@
             }
             n.setTransform(at);
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(), ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
     }
 
@@ -321,8 +317,9 @@
     protected void disposeTree(Node node, boolean removeContext) {
         if (node instanceof SVGOMElement) {
             SVGOMElement elt = (SVGOMElement)node;
-            BridgeUpdateHandler h = (BridgeUpdateHandler)elt.getSVGContext();
-            if (h != null) {
+            SVGContext ctx = elt.getSVGContext();
+            if (ctx instanceof BridgeUpdateHandler) {
+                BridgeUpdateHandler h = (BridgeUpdateHandler) ctx;
                 if (removeContext) {
                     elt.setSVGContext(null);
                 }
diff --git a/sources/org/apache/batik/bridge/BridgeException.java b/sources/org/apache/batik/bridge/BridgeException.java
index bbf654d..2f9e4c0 100644
--- a/sources/org/apache/batik/bridge/BridgeException.java
+++ b/sources/org/apache/batik/bridge/BridgeException.java
@@ -17,7 +17,9 @@
  */
 package org.apache.batik.bridge;
 
+import org.apache.batik.dom.svg.LiveAttributeException;
 import org.apache.batik.gvt.GraphicsNode;
+
 import org.w3c.dom.Element;
 import org.w3c.dom.svg.SVGDocument;
 
@@ -50,6 +52,37 @@
     protected GraphicsNode node;
 
     /**
+     * Constructs a new <tt>BridgeException</tt> based on the specified
+     * <tt>LiveAttributeException</tt>.
+     *
+     * @param ctx the bridge context to use for determining the element's
+     *            source position
+     * @param ex the {@link LiveAttributeException}
+     */
+    public BridgeException(BridgeContext ctx, LiveAttributeException ex) {
+        switch (ex.getCode()) {
+            case LiveAttributeException.ERR_ATTRIBUTE_MISSING:
+                this.code = ErrorConstants.ERR_ATTRIBUTE_MISSING;
+                break;
+            case LiveAttributeException.ERR_ATTRIBUTE_MALFORMED:
+                this.code = ErrorConstants.ERR_ATTRIBUTE_VALUE_MALFORMED;
+                break;
+            case LiveAttributeException.ERR_ATTRIBUTE_NEGATIVE:
+                this.code = ErrorConstants.ERR_LENGTH_NEGATIVE;
+                break;
+            default:
+                throw new IllegalStateException
+                    ("Unknown LiveAttributeException error code "
+                     + ex.getCode());
+        }
+        this.e = ex.getElement();
+        this.params = new Object[] { ex.getAttributeName(), ex.getValue() };
+        if (e != null && ctx != null) {
+            this.line = ctx.getDocumentLoader().getLineNumber(e);
+        }
+    }
+
+    /**
      * Constructs a new <tt>BridgeException</tt> with the specified parameters.
      *
      * @param ctx the bridge context to use for determining the element's
diff --git a/sources/org/apache/batik/bridge/PaintServer.java b/sources/org/apache/batik/bridge/PaintServer.java
index b3de1ab..8b58435 100644
--- a/sources/org/apache/batik/bridge/PaintServer.java
+++ b/sources/org/apache/batik/bridge/PaintServer.java
@@ -262,7 +262,8 @@
                                        ctx);
 
             default:
-                throw new Error(); // can't be reached
+                throw new IllegalArgumentException
+                    ("Paint argument is not an appropriate CSS value");
             }
         } else { // List
             Value v = paintDef.item(0);
@@ -292,12 +293,14 @@
                                                   opacity, ctx);
                     }
                 default:
-                    throw new Error(); // can't be reached
+                    throw new IllegalArgumentException
+                        ("Paint argument is not an appropriate CSS value");
                 }
             }
             default:
                 // can't be reached
-                throw new Error("Unallowed Value: " + v.getPrimitiveType()); 
+                throw new IllegalArgumentException
+                    ("Paint argument is not an appropriate CSS value");
             }
         }
     }
@@ -562,7 +565,8 @@
         case 's':
             return BasicStroke.CAP_SQUARE;
         default:
-            throw new Error(); // can't be reached
+            throw new IllegalArgumentException
+                ("Linecap argument is not an appropriate CSS value");
         }
     }
 
@@ -581,7 +585,8 @@
         case 'b':
             return BasicStroke.JOIN_BEVEL;
         default:
-            throw new Error(); // can't be reached
+            throw new IllegalArgumentException
+                ("Linejoin argument is not an appropriate CSS value");
         }
     }
 
@@ -605,7 +610,8 @@
             f = (f > 255f) ? 255f : (f < 0f) ? 0f : f;
             return Math.round(f);
         default:
-            throw new Error(); // can't be reached
+            throw new IllegalArgumentException
+                ("Color component argument is not an appropriate CSS value");
         }
     }
 
diff --git a/sources/org/apache/batik/bridge/SVGCircleElementBridge.java b/sources/org/apache/batik/bridge/SVGCircleElementBridge.java
index be1408e..8c6ed7a 100644
--- a/sources/org/apache/batik/bridge/SVGCircleElementBridge.java
+++ b/sources/org/apache/batik/bridge/SVGCircleElementBridge.java
@@ -82,11 +82,7 @@
             float w = r * 2;
             shapeNode.setShape(new Ellipse2D.Float(x, y, w, w));
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(), ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
     }
 
diff --git a/sources/org/apache/batik/bridge/SVGEllipseElementBridge.java b/sources/org/apache/batik/bridge/SVGEllipseElementBridge.java
index 58fa80b..ec542bb 100644
--- a/sources/org/apache/batik/bridge/SVGEllipseElementBridge.java
+++ b/sources/org/apache/batik/bridge/SVGEllipseElementBridge.java
@@ -83,11 +83,7 @@
             shapeNode.setShape(new Ellipse2D.Float(cx - rx, cy - ry,
                                                    rx * 2, ry * 2));
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(), ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
     }
 
diff --git a/sources/org/apache/batik/bridge/SVGImageElementBridge.java b/sources/org/apache/batik/bridge/SVGImageElementBridge.java
index 5279432..81745cc 100644
--- a/sources/org/apache/batik/bridge/SVGImageElementBridge.java
+++ b/sources/org/apache/batik/bridge/SVGImageElementBridge.java
@@ -164,10 +164,11 @@
         // Build the URL.
         String baseURI = AbstractNode.getBaseURI(e);
         ParsedURL purl;
-        if (baseURI == null)
+        if (baseURI == null) {
             purl = new ParsedURL(uriStr);
-        else
+        } else {
             purl = new ParsedURL(baseURI, uriStr);
+        }
 
         return createImageGraphicsNode(ctx, e, purl);
     }
@@ -437,6 +438,7 @@
                     return;
                 } else if (ln.equals(SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE)) {
                     updateImageBounds();
+                    return;
                 }
             } else if (ns.equals(XLINK_NAMESPACE_URI)
                     && ln.equals(XLINK_HREF_ATTRIBUTE)) {
@@ -444,11 +446,7 @@
                 return;
             }
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(), ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
         super.handleAnimatedAttributeChanged(alav);
     }
@@ -457,7 +455,7 @@
         //retrieve the new bounds of the image tag
         Rectangle2D bounds = getImageBounds(ctx, e);
         GraphicsNode imageNode = ((ImageNode)node).getImage();
-        float [] vb = null;
+        float[] vb = null;
         if (imageNode instanceof RasterImageNode) {
             //Raster image
             Rectangle2D imgBounds = 
@@ -894,11 +892,7 @@
                 } catch (java.awt.geom.NoninvertibleTransformException ex) {}
             }
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(), ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
     }
 
@@ -964,11 +958,7 @@
 
             return new Rectangle2D.Float(x, y, w, h);
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(), ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
     }
 
diff --git a/sources/org/apache/batik/bridge/SVGLineElementBridge.java b/sources/org/apache/batik/bridge/SVGLineElementBridge.java
index e5c3d0f..fe70c46 100644
--- a/sources/org/apache/batik/bridge/SVGLineElementBridge.java
+++ b/sources/org/apache/batik/bridge/SVGLineElementBridge.java
@@ -107,11 +107,7 @@
 
             shapeNode.setShape(new Line2D.Float(x1, y1, x2, y2));
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(), ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
     }
 
diff --git a/sources/org/apache/batik/bridge/SVGPathElementBridge.java b/sources/org/apache/batik/bridge/SVGPathElementBridge.java
index 1df04df..c35ee6f 100644
--- a/sources/org/apache/batik/bridge/SVGPathElementBridge.java
+++ b/sources/org/apache/batik/bridge/SVGPathElementBridge.java
@@ -87,11 +87,7 @@
             app.setWindingRule(CSSUtilities.convertFillRule(e));
             SVGAnimatedPathDataSupport.handlePathSegList(p, app);
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(), ex.getValue() });
+            throw new BridgeException(ctx, ex);
         } finally {
             shapeNode.setShape(app.getShape());
         }
diff --git a/sources/org/apache/batik/bridge/SVGPolygonElementBridge.java b/sources/org/apache/batik/bridge/SVGPolygonElementBridge.java
index 0d94d6e..bcfc171 100644
--- a/sources/org/apache/batik/bridge/SVGPolygonElementBridge.java
+++ b/sources/org/apache/batik/bridge/SVGPolygonElementBridge.java
@@ -93,11 +93,7 @@
                 shapeNode.setShape(app.getShape());
             }
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(), ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
     }
 
diff --git a/sources/org/apache/batik/bridge/SVGPolylineElementBridge.java b/sources/org/apache/batik/bridge/SVGPolylineElementBridge.java
index c83927a..c136bab 100644
--- a/sources/org/apache/batik/bridge/SVGPolylineElementBridge.java
+++ b/sources/org/apache/batik/bridge/SVGPolylineElementBridge.java
@@ -93,11 +93,7 @@
                 shapeNode.setShape(app.getShape());
             }
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(), ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
     }
 
diff --git a/sources/org/apache/batik/bridge/SVGRectElementBridge.java b/sources/org/apache/batik/bridge/SVGRectElementBridge.java
index 54bc05a..2965aaf 100644
--- a/sources/org/apache/batik/bridge/SVGRectElementBridge.java
+++ b/sources/org/apache/batik/bridge/SVGRectElementBridge.java
@@ -88,7 +88,7 @@
                 rx = w / 2;
             }
 
-            // 'ry' attribute - default is ry
+            // 'ry' attribute - default is rx
             float ry = re.getRy().getAnimVal().getValue();
             if (ry > h / 2) {
                 ry = h / 2;
@@ -102,11 +102,7 @@
             }
             shapeNode.setShape(shape);
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(), ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
     }
 
diff --git a/sources/org/apache/batik/bridge/SVGSVGElementBridge.java b/sources/org/apache/batik/bridge/SVGSVGElementBridge.java
index f0ce5b2..52f2475 100644
--- a/sources/org/apache/batik/bridge/SVGSVGElementBridge.java
+++ b/sources/org/apache/batik/bridge/SVGSVGElementBridge.java
@@ -202,11 +202,7 @@
                                               actualHeight));
             return cgn;
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(), ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
     }
 
@@ -291,12 +287,7 @@
                 }
             }
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(),
-                                ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
         super.handleAnimatedAttributeChanged(alav);
     }
@@ -390,12 +381,7 @@
                 handleElementAdded(gn, e.getParentNode(), e);
             }
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(),
-                                ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
     }
 
diff --git a/sources/org/apache/batik/bridge/SVGTextElementBridge.java b/sources/org/apache/batik/bridge/SVGTextElementBridge.java
index 48d90ec..fabec00 100644
--- a/sources/org/apache/batik/bridge/SVGTextElementBridge.java
+++ b/sources/org/apache/batik/bridge/SVGTextElementBridge.java
@@ -239,11 +239,7 @@
 
             return new Point2D.Float(x, y);
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(), ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
     }
 
@@ -1239,8 +1235,15 @@
 
         int lastChar = getElementEndIndex(element);
 
+        // 'a' elements aren't SVGTextPositioningElements, so don't process
+        // their positioning attributes on them.
+        if (!(element instanceof SVGOMTextPositioningElement)) {
+            addChildGlyphPositionAttributes(as, element, ctx);
+            return;
+        }
+
         // get all of the glyph position attribute values
-        SVGOMTextPositioningElement te = (SVGOMTextPositioningElement) e;
+        SVGOMTextPositioningElement te = (SVGOMTextPositioningElement) element;
 
         try {
             SVGLengthList xs  = te.getX().getAnimVal();
@@ -1296,7 +1299,7 @@
                     (GVTAttributedCharacterIterator.TextAttribute.ROTATION,
                      rad, firstChar, lastChar + 1);
 
-            } else if (len > 1) {  // its a list
+            } else if (len > 1) {  // it's a list
                 // set each rotate value from the list
                 for (int i = 0; i < len && firstChar + i <= lastChar; i++) {
                     Float rad = new Float(Math.toRadians(rs.getItem(i).getValue()));
@@ -1308,11 +1311,7 @@
 
             addChildGlyphPositionAttributes(as, element, ctx);
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(), ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
     }
 
@@ -1463,7 +1462,12 @@
                                   Element element,
                                   TextPath textPath,
                                   Integer bidiLevel) {
-        SVGTextContentElement tce = (SVGTextContentElement) element;
+        SVGTextContentElement tce = null;
+        if (element instanceof SVGTextContentElement) {
+            // 'a' elements aren't SVGTextContentElements, so they shouldn't
+            // be checked for 'textLength' or 'lengthAdjust' attributes.
+            tce = (SVGTextContentElement) element;
+        }
 
         Map result = new HashMap();
         String s;
@@ -1685,6 +1689,10 @@
                        Boolean.TRUE);
         }
 
+        if (tce == null) {
+            return result;
+        }
+
         try {
             // textLength
             AbstractSVGAnimatedLength textLength =
@@ -1712,11 +1720,7 @@
                 }
             }
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(), ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
 
         return result;
diff --git a/sources/org/apache/batik/bridge/SVGUseElementBridge.java b/sources/org/apache/batik/bridge/SVGUseElementBridge.java
index 5a751ef..599469d 100755
--- a/sources/org/apache/batik/bridge/SVGUseElementBridge.java
+++ b/sources/org/apache/batik/bridge/SVGUseElementBridge.java
@@ -91,6 +91,7 @@
             return null;
 
         CompositeGraphicsNode gn = buildCompositeGraphicsNode(ctx, e, null);
+        associateSVGContext(ctx, e, gn);
 
         return gn;
     }
diff --git a/sources/org/apache/batik/bridge/SVGUtilities.java b/sources/org/apache/batik/bridge/SVGUtilities.java
index f1969e6..ef25882 100644
--- a/sources/org/apache/batik/bridge/SVGUtilities.java
+++ b/sources/org/apache/batik/bridge/SVGUtilities.java
@@ -319,7 +319,7 @@
                 (yStr, yAttr, uctx);
             break;
         default:
-            throw new Error(); // can't be reached
+            throw new IllegalArgumentException("Invalid unit type");
         }
         return new Point2D.Float(x, y);
     }
@@ -339,12 +339,12 @@
                                       UnitProcessor.Context uctx) {
         switch (unitsType) {
         case OBJECT_BOUNDING_BOX:
-            return  UnitProcessor.svgOtherLengthToObjectBoundingBox
+            return UnitProcessor.svgOtherLengthToObjectBoundingBox
                 (length, attr, uctx);
         case USER_SPACE_ON_USE:
             return UnitProcessor.svgOtherLengthToUserSpace(length, attr, uctx);
         default:
-            throw new Error(); // can't be reached
+            throw new IllegalArgumentException("Invalid unit type");
         }
     }
 
@@ -729,7 +729,7 @@
             }
             break;
         default:
-            throw new Error(); // can't be reached
+            throw new IllegalArgumentException("Invalid unit type");
         }
         
         region.setRect(region.getX() + dx,
diff --git a/sources/org/apache/batik/bridge/ViewBox.java b/sources/org/apache/batik/bridge/ViewBox.java
index 9ae0196..ddb5b7b 100644
--- a/sources/org/apache/batik/bridge/ViewBox.java
+++ b/sources/org/apache/batik/bridge/ViewBox.java
@@ -273,11 +273,7 @@
                 SVGPreserveAspectRatio.SVG_MEETORSLICE_MEET;
             return getPreserveAspectRatioTransform(vb, align, meet, w, h);
         } catch (LiveAttributeException ex) {
-            throw new BridgeException
-                (ctx, ex.getElement(),
-                 ex.isMissing() ? ERR_ATTRIBUTE_MISSING
-                                : ERR_ATTRIBUTE_VALUE_MALFORMED,
-                 new Object[] { ex.getAttributeName(), ex.getValue() });
+            throw new BridgeException(ctx, ex);
         }
     }
 
diff --git a/sources/org/apache/batik/bridge/svg12/SVGMultiImageElementBridge.java b/sources/org/apache/batik/bridge/svg12/SVGMultiImageElementBridge.java
index b3f15a2..aa04d71 100644
--- a/sources/org/apache/batik/bridge/svg12/SVGMultiImageElementBridge.java
+++ b/sources/org/apache/batik/bridge/svg12/SVGMultiImageElementBridge.java
@@ -34,6 +34,7 @@
 import org.apache.batik.bridge.CSSUtilities;
 import org.apache.batik.bridge.SVGImageElementBridge;
 import org.apache.batik.bridge.SVGUtilities;
+import org.apache.batik.bridge.UnitProcessor;
 import org.apache.batik.bridge.Viewport;
 import org.apache.batik.dom.AbstractNode;
 import org.apache.batik.dom.util.XLinkSupport;
@@ -249,6 +250,58 @@
         super.dispose();
     }
 
+    /**
+     * Returns the bounds of the specified image element.
+     *
+     * @param ctx the bridge context
+     * @param element the image element
+     */
+    protected static
+        Rectangle2D getImageBounds(BridgeContext ctx, Element element) {
+
+        UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, element);
+
+        // 'x' attribute - default is 0
+        String s = element.getAttributeNS(null, SVG_X_ATTRIBUTE);
+        float x = 0;
+        if (s.length() != 0) {
+            x = UnitProcessor.svgHorizontalCoordinateToUserSpace
+                (s, SVG_X_ATTRIBUTE, uctx);
+        }
+
+        // 'y' attribute - default is 0
+        s = element.getAttributeNS(null, SVG_Y_ATTRIBUTE);
+        float y = 0;
+        if (s.length() != 0) {
+            y = UnitProcessor.svgVerticalCoordinateToUserSpace
+                (s, SVG_Y_ATTRIBUTE, uctx);
+        }
+
+        // 'width' attribute - required
+        s = element.getAttributeNS(null, SVG_WIDTH_ATTRIBUTE);
+        float w;
+        if (s.length() == 0) {
+            throw new BridgeException(ctx, element, ERR_ATTRIBUTE_MISSING,
+                                      new Object[] {SVG_WIDTH_ATTRIBUTE});
+        } else {
+            w = UnitProcessor.svgHorizontalLengthToUserSpace
+                (s, SVG_WIDTH_ATTRIBUTE, uctx);
+        }
+
+        // 'height' attribute - required
+        s = element.getAttributeNS(null, SVG_HEIGHT_ATTRIBUTE);
+        float h;
+        if (s.length() == 0) {
+            throw new BridgeException(ctx, element, ERR_ATTRIBUTE_MISSING,
+                                      new Object[] {SVG_HEIGHT_ATTRIBUTE});
+        } else {
+            h = UnitProcessor.svgVerticalLengthToUserSpace
+                (s, SVG_HEIGHT_ATTRIBUTE, uctx);
+        }
+
+        return new Rectangle2D.Float(x, y, w, h);
+    }
+
     protected void addInfo(Element e, Collection elems, 
                            Collection minDim, Collection maxDim,
                            Rectangle2D bounds) {
diff --git a/sources/org/apache/batik/css/engine/CSSEngine.java b/sources/org/apache/batik/css/engine/CSSEngine.java
index f4d09fd..54333b0 100644
--- a/sources/org/apache/batik/css/engine/CSSEngine.java
+++ b/sources/org/apache/batik/css/engine/CSSEngine.java
@@ -847,17 +847,19 @@
             // Apply the override rules to the result.
             StyleDeclarationProvider p =
                 elt.getOverrideStyleDeclarationProvider();
-            StyleDeclaration over = p.getStyleDeclaration();
-            if (over != null) {
-                int ol = over.size();
-                for (int i = 0; i < ol; i++) {
-                    int idx = over.getIndex(i);
-                    Value value = over.getValue(i);
-                    boolean important = over.getPriority(i);
-                    if (!result.isImportant(idx) || important) {
-                        result.putValue(idx, value);
-                        result.putImportant(idx, important);
-                        result.putOrigin(idx, StyleMap.OVERRIDE_ORIGIN);
+            if (p != null) {
+                StyleDeclaration over = p.getStyleDeclaration();
+                if (over != null) {
+                    int ol = over.size();
+                    for (int i = 0; i < ol; i++) {
+                        int idx = over.getIndex(i);
+                        Value value = over.getValue(i);
+                        boolean important = over.getPriority(i);
+                        if (!result.isImportant(idx) || important) {
+                            result.putValue(idx, value);
+                            result.putImportant(idx, important);
+                            result.putOrigin(idx, StyleMap.OVERRIDE_ORIGIN);
+                        }
                     }
                 }
             }
diff --git a/sources/org/apache/batik/dom/svg/AbstractSVGAnimatedLength.java b/sources/org/apache/batik/dom/svg/AbstractSVGAnimatedLength.java
index 07683cf..9fef607 100644
--- a/sources/org/apache/batik/dom/svg/AbstractSVGAnimatedLength.java
+++ b/sources/org/apache/batik/dom/svg/AbstractSVGAnimatedLength.java
@@ -146,32 +146,27 @@
      * Called when an Attr node has been added.
      */
     public void attrAdded(Attr node, String newv) {
-        if (!changing && baseVal != null) {
-            baseVal.invalidate();
-        }
-        fireBaseAttributeListeners();
-        if (!hasAnimVal) {
-            fireAnimatedAttributeListeners();
-        }
+        attrChanged();
     }
 
     /**
      * Called when an Attr node has been modified.
      */
     public void attrModified(Attr node, String oldv, String newv) {
-        if (!changing && baseVal != null) {
-            baseVal.invalidate();
-        }
-        fireBaseAttributeListeners();
-        if (!hasAnimVal) {
-            fireAnimatedAttributeListeners();
-        }
+        attrChanged();
     }
 
     /**
      * Called when an Attr node has been removed.
      */
     public void attrRemoved(Attr node, String oldv) {
+        attrChanged();
+    }
+
+    /**
+     * Called when the attribute has changed in some way.
+     */
+    protected void attrChanged() {
         if (!changing && baseVal != null) {
             baseVal.invalidate();
         }
@@ -234,8 +229,9 @@
             if (attr == null) {
                 s = getDefaultValue();
                 if (s == null) {
-                    throw new LiveAttributeException(element, localName, true,
-                                                     null);
+                    throw new LiveAttributeException
+                        (element, localName,
+                         LiveAttributeException.ERR_ATTRIBUTE_MISSING, null);
                 }
             } else {
                 s = attr.getValue();
@@ -244,7 +240,9 @@
             parse(s);
 
             if (nonNegative && value < 0) {
-                throw new LiveAttributeException(element, localName, false, s);
+                throw new LiveAttributeException
+                    (element, localName,
+                     LiveAttributeException.ERR_ATTRIBUTE_NEGATIVE, s);
             }
 
             valid = true;
diff --git a/sources/org/apache/batik/dom/svg/AbstractSVGLength.java b/sources/org/apache/batik/dom/svg/AbstractSVGLength.java
index 68d1df2..493fd82 100644
--- a/sources/org/apache/batik/dom/svg/AbstractSVGLength.java
+++ b/sources/org/apache/batik/dom/svg/AbstractSVGLength.java
@@ -120,8 +120,14 @@
      */
     public float getValue() {
         revalidate();
-        return UnitProcessor.svgToUserSpace(value, unitType,
-                                            direction, context);
+        try {
+            return UnitProcessor.svgToUserSpace(value, unitType,
+                                                direction, context);
+        } catch (IllegalArgumentException ex) {
+            // XXX Should we throw an exception here when the length
+            //     type is unknown?
+            return 0f;
+        }
     }
 
     /**
diff --git a/sources/org/apache/batik/dom/svg/AbstractSVGTransform.java b/sources/org/apache/batik/dom/svg/AbstractSVGTransform.java
index 5c9b13d..f0e932f 100644
--- a/sources/org/apache/batik/dom/svg/AbstractSVGTransform.java
+++ b/sources/org/apache/batik/dom/svg/AbstractSVGTransform.java
@@ -166,8 +166,8 @@
     public void setSkewX(float angle) {
         type = SVG_TRANSFORM_SKEWX;
         affineTransform =
-            new AffineTransform(1.0, Math.tan(Math.toRadians(angle)), 0.0,
-                                1.0, 0.0, 0.0);
+            AffineTransform.getShearInstance(Math.tan(Math.toRadians(angle)),
+                                             0.0);
         this.angle = angle;
     }
 
@@ -176,9 +176,9 @@
      */
     public void setSkewY(float angle) {
         type = SVG_TRANSFORM_SKEWY;
-        this.angle = angle;
         affineTransform =
-            new AffineTransform(1.0, 0.0, Math.tan(Math.toRadians(angle)),
-                                1.0, 0.0, 0.0);
+            AffineTransform.getShearInstance(0.0,
+                                             Math.tan(Math.toRadians(angle)));
+        this.angle = angle;
     }
 }
diff --git a/sources/org/apache/batik/dom/svg/LiveAttributeException.java b/sources/org/apache/batik/dom/svg/LiveAttributeException.java
index 87e155b..e49e248 100644
--- a/sources/org/apache/batik/dom/svg/LiveAttributeException.java
+++ b/sources/org/apache/batik/dom/svg/LiveAttributeException.java
@@ -27,6 +27,11 @@
  */
 public class LiveAttributeException extends RuntimeException {
 
+    // Constants for the error code.
+    public static final short ERR_ATTRIBUTE_MISSING   = 0;
+    public static final short ERR_ATTRIBUTE_MALFORMED = 1;
+    public static final short ERR_ATTRIBUTE_NEGATIVE  = 2;
+
     /**
      * The element on which the error occured.
      */
@@ -38,9 +43,10 @@
     protected String attributeName;
 
     /**
-     * Whether the attribute was missing (true) or malformed (false).
+     * The reason for the exception.  This must be one of the ERR_* constants
+     * defined in this class.
      */
-    protected boolean missing;
+    protected short code;
 
     /**
      * The malformed attribute value.
@@ -54,13 +60,14 @@
      * @param e the element on which the error occured
      * @param an the attribute name
      * @param missing whether the attribute was missing or malformed
+     * @param code the error code
      * @param val the malformed attribute value
      */
-    public LiveAttributeException(Element e, String an, boolean missing,
+    public LiveAttributeException(Element e, String an, short code,
                                   String val) {
         this.e = e;
         this.attributeName = an;
-        this.missing = missing;
+        this.code = code;
         this.value = val;
     }
 
@@ -79,14 +86,14 @@
     }
 
     /**
-     * Returns whether the attribute was missing (true) or malformed (false).
+     * Returns the error code.
      */
-    public boolean isMissing() {
-        return missing;
+    public short getCode() {
+        return code;
     }
 
     /**
-     * Returns the malformed attribute value.
+     * Returns the problematic attribute value.
      */
     public String getValue() {
         return value;
diff --git a/sources/org/apache/batik/dom/svg/SVGOMAnimatedLengthList.java b/sources/org/apache/batik/dom/svg/SVGOMAnimatedLengthList.java
index ed1505b..c4eecf3 100644
--- a/sources/org/apache/batik/dom/svg/SVGOMAnimatedLengthList.java
+++ b/sources/org/apache/batik/dom/svg/SVGOMAnimatedLengthList.java
@@ -242,8 +242,9 @@
             String s = getValueAsString();
             boolean isEmpty = s != null && s.length() == 0;
             if (s == null || isEmpty && !emptyAllowed) {
-                throw new LiveAttributeException(element, localName, true,
-                                                 null);
+                throw new LiveAttributeException
+                    (element, localName,
+                     LiveAttributeException.ERR_ATTRIBUTE_MISSING, s);
             }
             if (isEmpty) {
                 itemList = new ArrayList(1);
@@ -260,8 +261,9 @@
                 } catch (ParseException e) {
                     itemList = new ArrayList(1);
                     valid = true;
-                    throw new LiveAttributeException(element, localName, false,
-                                                     s);
+                    throw new LiveAttributeException
+                        (element, localName,
+                         LiveAttributeException.ERR_ATTRIBUTE_MALFORMED, s);
                 }
             }
             valid = true;
diff --git a/sources/org/apache/batik/dom/svg/SVGOMAnimatedNumberList.java b/sources/org/apache/batik/dom/svg/SVGOMAnimatedNumberList.java
index 4d1e60e..8abbcb2 100755
--- a/sources/org/apache/batik/dom/svg/SVGOMAnimatedNumberList.java
+++ b/sources/org/apache/batik/dom/svg/SVGOMAnimatedNumberList.java
@@ -226,8 +226,9 @@
             String s = getValueAsString();
             boolean isEmpty = s != null && s.length() == 0;
             if (s == null || isEmpty && !emptyAllowed) {
-                throw new LiveAttributeException(element, localName, true,
-                                                 null);
+                throw new LiveAttributeException
+                    (element, localName,
+                     LiveAttributeException.ERR_ATTRIBUTE_MISSING, null);
             }
             if (isEmpty) {
                 itemList = new ArrayList(1);
@@ -244,8 +245,9 @@
                 } catch (ParseException e) {
                     itemList = new ArrayList(1);
                     valid = true;
-                    throw new LiveAttributeException(element, localName, false,
-                                                     s);
+                    throw new LiveAttributeException
+                        (element, localName,
+                         LiveAttributeException.ERR_ATTRIBUTE_MALFORMED, s);
                 }
             }
             valid = true;
diff --git a/sources/org/apache/batik/dom/svg/SVGOMAnimatedPathData.java b/sources/org/apache/batik/dom/svg/SVGOMAnimatedPathData.java
index a5360e4..c49e909 100644
--- a/sources/org/apache/batik/dom/svg/SVGOMAnimatedPathData.java
+++ b/sources/org/apache/batik/dom/svg/SVGOMAnimatedPathData.java
@@ -276,8 +276,9 @@
 
             String s = getValueAsString();
             if (s == null) {
-                throw new LiveAttributeException(element, localName, true,
-                                                 null);
+                throw new LiveAttributeException
+                    (element, localName,
+                     LiveAttributeException.ERR_ATTRIBUTE_MISSING, null);
             }
             try {
                 ListBuilder builder = new ListBuilder();
@@ -291,7 +292,9 @@
             } catch (ParseException e) {
                 itemList = new ArrayList(1);
                 valid = true;
-                throw new LiveAttributeException(element, localName, false, s);
+                throw new LiveAttributeException
+                    (element, localName,
+                     LiveAttributeException.ERR_ATTRIBUTE_MALFORMED, s);
             }
         }
     }
@@ -352,8 +355,9 @@
 
             String s = getValueAsString();
             if (s == null) {
-                throw new LiveAttributeException(element, localName, true,
-                                                 null);
+                throw new LiveAttributeException
+                    (element, localName,
+                     LiveAttributeException.ERR_ATTRIBUTE_MISSING, null);
             }
             try {
                 ListBuilder builder = new ListBuilder();
@@ -367,7 +371,9 @@
             } catch (ParseException e) {
                 itemList = new ArrayList(1);
                 valid = true;
-                throw new LiveAttributeException(element, localName, false, s);
+                throw new LiveAttributeException
+                    (element, localName,
+                     LiveAttributeException.ERR_ATTRIBUTE_MALFORMED, s);
             }
             valid = true;
         }
diff --git a/sources/org/apache/batik/dom/svg/SVGOMAnimatedPoints.java b/sources/org/apache/batik/dom/svg/SVGOMAnimatedPoints.java
index 69ec0ff..a05bab0 100644
--- a/sources/org/apache/batik/dom/svg/SVGOMAnimatedPoints.java
+++ b/sources/org/apache/batik/dom/svg/SVGOMAnimatedPoints.java
@@ -208,8 +208,9 @@
 
             String s = getValueAsString();
             if (s == null) {
-                throw new LiveAttributeException(element, localName, true,
-                                                 null);
+                throw new LiveAttributeException
+                    (element, localName,
+                     LiveAttributeException.ERR_ATTRIBUTE_MISSING, null);
             }
             try {
                 ListBuilder builder = new ListBuilder();
@@ -223,7 +224,9 @@
             } catch (ParseException e) {
                 itemList = new ArrayList(1);
                 valid = true;
-                throw new LiveAttributeException(element, localName, false, s);
+                throw new LiveAttributeException
+                    (element, localName,
+                     LiveAttributeException.ERR_ATTRIBUTE_MALFORMED, s);
             }
             valid = true;
         }
diff --git a/sources/org/apache/batik/dom/svg/SVGOMAnimatedPreserveAspectRatio.java b/sources/org/apache/batik/dom/svg/SVGOMAnimatedPreserveAspectRatio.java
index c5ab659..03066d0 100644
--- a/sources/org/apache/batik/dom/svg/SVGOMAnimatedPreserveAspectRatio.java
+++ b/sources/org/apache/batik/dom/svg/SVGOMAnimatedPreserveAspectRatio.java
@@ -141,7 +141,14 @@
      * #getBaseVal()}.
      */
     public class BaseSVGPARValue extends AbstractSVGPreserveAspectRatio {
-        
+
+        /**
+         * Creates a new BaseSVGPARValue.
+         */
+        public BaseSVGPARValue() {
+            invalidate();
+        }
+
         /**
          * Create a DOMException.
          */
diff --git a/sources/org/apache/batik/dom/svg/SVGOMAnimatedRect.java b/sources/org/apache/batik/dom/svg/SVGOMAnimatedRect.java
index 6f53887..30bfc5c 100644
--- a/sources/org/apache/batik/dom/svg/SVGOMAnimatedRect.java
+++ b/sources/org/apache/batik/dom/svg/SVGOMAnimatedRect.java
@@ -195,8 +195,10 @@
                     protected int count;
                     public void endNumberList() {
                         if (count != 4) {
-                            throw new LiveAttributeException(element, localName,
-                                                             false, s);
+                            throw new LiveAttributeException
+                                (element, localName,
+                                 LiveAttributeException.ERR_ATTRIBUTE_MALFORMED,
+                                 s);
                         }
                     }
                     public void numberValue(float v) throws ParseException {
@@ -204,8 +206,10 @@
                             numbers[count] = v;
                         }
                         if (v < 0 && (count == 2 || count == 3)) {
-                            throw new LiveAttributeException(element, localName,
-                                                             false, s);
+                            throw new LiveAttributeException
+                                (element, localName,
+                                 LiveAttributeException.ERR_ATTRIBUTE_MALFORMED,
+                                 s);
                         }
                         count++;
                     }
diff --git a/sources/org/apache/batik/dom/svg/SVGOMAnimatedTransformList.java b/sources/org/apache/batik/dom/svg/SVGOMAnimatedTransformList.java
index 8d3a62f..50760ce 100644
--- a/sources/org/apache/batik/dom/svg/SVGOMAnimatedTransformList.java
+++ b/sources/org/apache/batik/dom/svg/SVGOMAnimatedTransformList.java
@@ -221,8 +221,9 @@
 
             String s = getValueAsString();
             if (s == null) {
-                throw new LiveAttributeException(element, localName, true,
-                                                 null);
+                throw new LiveAttributeException
+                    (element, localName,
+                     LiveAttributeException.ERR_ATTRIBUTE_MISSING, null);
             }
             try {
                 ListBuilder builder = new ListBuilder();
@@ -236,7 +237,9 @@
             } catch (ParseException e) {
                 itemList = new ArrayList(1);
                 valid = true;
-                throw new LiveAttributeException(element, localName, false, s);
+                throw new LiveAttributeException
+                    (element, localName,
+                     LiveAttributeException.ERR_ATTRIBUTE_MALFORMED, s);
             }
             valid = true;
         }
diff --git a/sources/org/apache/batik/dom/svg/SVGOMImageElement.java b/sources/org/apache/batik/dom/svg/SVGOMImageElement.java
index 2b34c66..80223d7 100644
--- a/sources/org/apache/batik/dom/svg/SVGOMImageElement.java
+++ b/sources/org/apache/batik/dom/svg/SVGOMImageElement.java
@@ -103,7 +103,7 @@
      */
     public SVGAnimatedLength getWidth() {
         return getAnimatedLengthAttribute
-            (null, SVG_WIDTH_ATTRIBUTE, "",
+            (null, SVG_WIDTH_ATTRIBUTE, null,
              SVGOMAnimatedLength.HORIZONTAL_LENGTH, true);
     }
 
@@ -112,7 +112,7 @@
      */
     public SVGAnimatedLength getHeight() {
         return getAnimatedLengthAttribute
-            (null, SVG_HEIGHT_ATTRIBUTE, "",
+            (null, SVG_HEIGHT_ATTRIBUTE, null,
              SVGOMAnimatedLength.VERTICAL_LENGTH, true);
     }
 
@@ -213,6 +213,9 @@
                 updateLengthAttributeValue(getHeight(), val);
                 return;
             }
+        } else if (ns.equals(XLINK_NAMESPACE_URI)
+                && ln.equals(XLINK_HREF_ATTRIBUTE)) {
+            updateStringAttributeValue(getHref(), val);
         }
         super.updateAttributeValue(ns, ln, val);
     }
@@ -237,6 +240,9 @@
                 return getBaseValue
                     (getHeight(), PERCENTAGE_VIEWPORT_HEIGHT);
             }
+        } else if (ns.equals(XLINK_NAMESPACE_URI)
+                && ln.equals(XLINK_HREF_ATTRIBUTE)) {
+            return getBaseValue(getHref());
         }
         return super.getUnderlyingValue(ns, ln);
     }
diff --git a/sources/org/apache/batik/dom/svg/SVGOMRectElement.java b/sources/org/apache/batik/dom/svg/SVGOMRectElement.java
index e72fe81..5045d93 100644
--- a/sources/org/apache/batik/dom/svg/SVGOMRectElement.java
+++ b/sources/org/apache/batik/dom/svg/SVGOMRectElement.java
@@ -98,9 +98,10 @@
      * <b>DOM</b>: Implements {@link SVGRectElement#getRx()}.
      */
     public SVGAnimatedLength getRx() {
-        SVGAnimatedLength result =
-            (SVGAnimatedLength)getLiveAttributeValue(null, SVG_RX_ATTRIBUTE);
+        AbstractSVGAnimatedLength result = (AbstractSVGAnimatedLength)
+            getLiveAttributeValue(null, SVG_RX_ATTRIBUTE);
         if (result == null) {
+            SVGOMDocument doc = (SVGOMDocument) ownerDocument;
             result = new AbstractSVGAnimatedLength
                 (this, null, SVG_RX_ATTRIBUTE,
                  SVGOMAnimatedLength.HORIZONTAL_LENGTH, true) {
@@ -111,7 +112,17 @@
                         }
                         return attr.getValue();
                     }
+                    protected void attrChanged() {
+                        super.attrChanged();
+                        AbstractSVGAnimatedLength ry =
+                            (AbstractSVGAnimatedLength) getRy();
+                        if (isSpecified() && !ry.isSpecified()) {
+                            ry.attrChanged();
+                        }
+                    }
                 };
+            result.addAnimatedAttributeListener
+                (doc.getAnimatedAttributeListener());
             putLiveAttributeValue(null, SVG_RX_ATTRIBUTE,
                                   (LiveAttributeValue)result);
         }
@@ -122,9 +133,10 @@
      * <b>DOM</b>: Implements {@link SVGRectElement#getRy()}.
      */
     public SVGAnimatedLength getRy() {
-        SVGAnimatedLength result =
-            (SVGAnimatedLength)getLiveAttributeValue(null, SVG_RY_ATTRIBUTE);
+        AbstractSVGAnimatedLength result = (AbstractSVGAnimatedLength)
+            getLiveAttributeValue(null, SVG_RY_ATTRIBUTE);
         if (result == null) {
+            SVGOMDocument doc = (SVGOMDocument) ownerDocument;
             result = new AbstractSVGAnimatedLength
                 (this, null, SVG_RY_ATTRIBUTE,
                  SVGOMAnimatedLength.HORIZONTAL_LENGTH, true) {
@@ -135,7 +147,17 @@
                         }
                         return attr.getValue();
                     }
+                    protected void attrChanged() {
+                        super.attrChanged();
+                        AbstractSVGAnimatedLength rx =
+                            (AbstractSVGAnimatedLength) getRx();
+                        if (isSpecified() && !rx.isSpecified()) {
+                            rx.attrChanged();
+                        }
+                    }
                 };
+            result.addAnimatedAttributeListener
+                (doc.getAnimatedAttributeListener());
             putLiveAttributeValue(null, SVG_RY_ATTRIBUTE,
                                   (LiveAttributeValue)result);
         }
@@ -216,9 +238,19 @@
                 return;
             } else if (ln.equals(SVG_RX_ATTRIBUTE)) {
                 updateLengthAttributeValue(getRx(), val);
+                AbstractSVGAnimatedLength ry =
+                    (AbstractSVGAnimatedLength) getRy();
+                if (!ry.isSpecified()) {
+                    updateLengthAttributeValue(getRy(), val);
+                }
                 return;
             } else if (ln.equals(SVG_RY_ATTRIBUTE)) {
                 updateLengthAttributeValue(getRy(), val);
+                AbstractSVGAnimatedLength rx =
+                    (AbstractSVGAnimatedLength) getRx();
+                if (!rx.isSpecified()) {
+                    updateLengthAttributeValue(getRx(), val);
+                }
                 return;
             } else if (ln.equals(SVG_WIDTH_ATTRIBUTE)) {
                 updateLengthAttributeValue(getWidth(), val);
diff --git a/sources/org/apache/batik/dom/util/DOMUtilities.java b/sources/org/apache/batik/dom/util/DOMUtilities.java
index 29fd417..45ff525 100644
--- a/sources/org/apache/batik/dom/util/DOMUtilities.java
+++ b/sources/org/apache/batik/dom/util/DOMUtilities.java
@@ -129,10 +129,10 @@
                 if (sysID != null) 
                     w.write (" SYSTEM \"" + sysID + "\">");
             }
-        }
             break;
+        }
         default:
-            throw new Error("Internal error (" + n.getNodeType() + ")");
+            throw new IOException("Unknown DOM node type " + n.getNodeType());
         }
     }
 
diff --git a/sources/org/apache/batik/extension/GraphicsExtensionElement.java b/sources/org/apache/batik/extension/GraphicsExtensionElement.java
new file mode 100644
index 0000000..7224c0d
--- /dev/null
+++ b/sources/org/apache/batik/extension/GraphicsExtensionElement.java
@@ -0,0 +1,204 @@
+/*
+
+   Copyright 2006  The Apache Software Foundation
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+*/
+package org.apache.batik.extension;
+
+import org.apache.batik.dom.AbstractDocument;
+import org.apache.batik.dom.svg.SVGExternalResourcesRequiredSupport;
+import org.apache.batik.dom.svg.SVGLocatableSupport;
+import org.apache.batik.dom.svg.SVGTestsSupport;
+import org.apache.batik.dom.svg.SVGTransformableSupport;
+import org.apache.batik.dom.util.XMLSupport;
+
+import org.w3c.dom.svg.SVGAnimatedBoolean;
+import org.w3c.dom.svg.SVGAnimatedTransformList;
+import org.w3c.dom.svg.SVGElement;
+import org.w3c.dom.svg.SVGException;
+import org.w3c.dom.svg.SVGExternalResourcesRequired;
+import org.w3c.dom.svg.SVGLangSpace;
+import org.w3c.dom.svg.SVGLocatable;
+import org.w3c.dom.svg.SVGMatrix;
+import org.w3c.dom.svg.SVGRect;
+import org.w3c.dom.svg.SVGStringList;
+import org.w3c.dom.svg.SVGTests;
+import org.w3c.dom.svg.SVGTransformable;
+
+/**
+ * An abstract base class for graphical extension elements.  This class
+ * inherits {@link org.w3c.dom.svg.SVGStylable} functionality from {@link
+ * StylableExtensionElement} and implements {@link SVGLocatable},
+ * {@link SVGTransformable}, {@link SVGExternalResourcesRequired},
+ * {@link SVGLangSpace} and {@link SVGTests}.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id$
+ */
+public abstract class GraphicsExtensionElement
+        extends    StylableExtensionElement
+        implements SVGTransformable {
+
+    /**
+     * Creates a new GraphicsExtensionElement object.
+     */
+    protected GraphicsExtensionElement() {
+    }
+
+    /**
+     * Creates a new GraphicsExtensionElement object.
+     * @param name The element name, for validation purposes.
+     * @param owner The owner document.
+     */
+    protected GraphicsExtensionElement(String name, AbstractDocument owner) {
+        super(name, owner);
+    }
+
+    // SVGLocatable support /////////////////////////////////////////////
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.svg.SVGLocatable#getNearestViewportElement()}.
+     */
+    public SVGElement getNearestViewportElement() {
+        return SVGLocatableSupport.getNearestViewportElement(this);
+    }
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.svg.SVGLocatable#getFarthestViewportElement()}.
+     */
+    public SVGElement getFarthestViewportElement() {
+        return SVGLocatableSupport.getFarthestViewportElement(this);
+    }
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.svg.SVGLocatable#getBBox()}.
+     */
+    public SVGRect getBBox() {
+        return SVGLocatableSupport.getBBox(this);
+    }
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.svg.SVGLocatable#getCTM()}.
+     */
+    public SVGMatrix getCTM() {
+        return SVGLocatableSupport.getCTM(this);
+    }
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.svg.SVGLocatable#getScreenCTM()}.
+     */
+    public SVGMatrix getScreenCTM() {
+        return SVGLocatableSupport.getScreenCTM(this);
+    }
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.svg.SVGLocatable#getTransformToElement(SVGElement)}.
+     */
+    public SVGMatrix getTransformToElement(SVGElement element)
+        throws SVGException {
+        return SVGLocatableSupport.getTransformToElement(this, element);
+    }
+
+    // SVGTransformable support //////////////////////////////////////////////
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.svg.SVGTransformable#getTransform()}.
+     */
+    public SVGAnimatedTransformList getTransform() {
+        return SVGTransformableSupport.getTransform(this);
+    }
+
+    // SVGExternalResourcesRequired support /////////////////////////////
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.svg.SVGExternalResourcesRequired#getExternalResourcesRequired()}.
+     */
+    public SVGAnimatedBoolean getExternalResourcesRequired() {
+        return SVGExternalResourcesRequiredSupport.
+            getExternalResourcesRequired(this);
+    }
+
+    // SVGLangSpace support //////////////////////////////////////////////////
+
+    /**
+     * <b>DOM</b>: Returns the xml:lang attribute value.
+     */
+    public String getXMLlang() {
+        return XMLSupport.getXMLLang(this);
+    }
+
+    /**
+     * <b>DOM</b>: Sets the xml:lang attribute value.
+     */
+    public void setXMLlang(String lang) {
+        setAttributeNS(XML_NAMESPACE_URI, XML_LANG_QNAME, lang);
+    }
+
+    /**
+     * <b>DOM</b>: Returns the xml:space attribute value.
+     */
+    public String getXMLspace() {
+        return XMLSupport.getXMLSpace(this);
+    }
+
+    /**
+     * <b>DOM</b>: Sets the xml:space attribute value.
+     */
+    public void setXMLspace(String space) {
+        setAttributeNS(XML_NAMESPACE_URI, XML_SPACE_QNAME, space);
+    }
+
+    // SVGTests support ///////////////////////////////////////////////////
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.svg.SVGTests#getRequiredFeatures()}.
+     */
+    public SVGStringList getRequiredFeatures() {
+        return SVGTestsSupport.getRequiredFeatures(this);
+    }
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.svg.SVGTests#getRequiredExtensions()}.
+     */
+    public SVGStringList getRequiredExtensions() {
+        return SVGTestsSupport.getRequiredExtensions(this);
+    }
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.svg.SVGTests#getSystemLanguage()}.
+     */
+    public SVGStringList getSystemLanguage() {
+        return SVGTestsSupport.getSystemLanguage(this);
+    }
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.svg.SVGTests#hasExtension(String)}.
+     */
+    public boolean hasExtension(String extension) {
+        return SVGTestsSupport.hasExtension(this, extension);
+    }
+}
diff --git a/sources/org/apache/batik/extension/svg/BatikRegularPolygonElement.java b/sources/org/apache/batik/extension/svg/BatikRegularPolygonElement.java
index 466773f..ffd81b0 100644
--- a/sources/org/apache/batik/extension/svg/BatikRegularPolygonElement.java
+++ b/sources/org/apache/batik/extension/svg/BatikRegularPolygonElement.java
@@ -18,7 +18,7 @@
 package org.apache.batik.extension.svg;
 
 import org.apache.batik.dom.AbstractDocument;
-import org.apache.batik.extension.PrefixableStylableExtensionElement;
+import org.apache.batik.extension.GraphicsExtensionElement;
 import org.w3c.dom.Node;
 
 /**
@@ -28,7 +28,7 @@
  * @version $Id$
  */
 public class BatikRegularPolygonElement
-    extends    PrefixableStylableExtensionElement 
+    extends    GraphicsExtensionElement 
     implements BatikExtConstants {
 
     /**
diff --git a/sources/org/apache/batik/extension/svg/BatikStarElement.java b/sources/org/apache/batik/extension/svg/BatikStarElement.java
index 9d706c3..0cdb532 100644
--- a/sources/org/apache/batik/extension/svg/BatikStarElement.java
+++ b/sources/org/apache/batik/extension/svg/BatikStarElement.java
@@ -18,7 +18,7 @@
 package org.apache.batik.extension.svg;
 
 import org.apache.batik.dom.AbstractDocument;
-import org.apache.batik.extension.PrefixableStylableExtensionElement;
+import org.apache.batik.extension.GraphicsExtensionElement;
 import org.w3c.dom.Node;
 
 /**
@@ -28,7 +28,7 @@
  * @version $Id$
  */
 public class BatikStarElement
-    extends    PrefixableStylableExtensionElement 
+    extends    GraphicsExtensionElement 
     implements BatikExtConstants {
 
     /**
diff --git a/sources/org/apache/batik/extension/svg/ColorSwitchBridge.java b/sources/org/apache/batik/extension/svg/ColorSwitchBridge.java
index b6970d0..81e890d 100644
--- a/sources/org/apache/batik/extension/svg/ColorSwitchBridge.java
+++ b/sources/org/apache/batik/extension/svg/ColorSwitchBridge.java
@@ -30,16 +30,17 @@
 import org.w3c.dom.Node;
 
 /**
- * Bridge class for a regular polygon element.
+ * Bridge class for the "color switch" extension element.
  *
  * @author <a href="mailto:thomas.deweese@kodak.com">Thomas Deweese</a>
+ * @version $Id$
  */
 public class ColorSwitchBridge 
     extends AbstractSVGBridge
     implements PaintBridge, BatikExtConstants {
 
     /**
-     * Constructs a new bridge for the &lt;rect> element.
+     * Constructs a new bridge for the &lt;batik:colorSwitch> element.
      */
     public ColorSwitchBridge() { /* nothing */ }
 
@@ -51,7 +52,7 @@
     }
 
     /**
-     * Returns 'rect'.
+     * Returns 'colorSwitch'.
      */
     public String getLocalName() {
         return BATIK_EXT_COLOR_SWITCH_TAG;
diff --git a/sources/org/apache/batik/extension/svg/ColorSwitchElement.java b/sources/org/apache/batik/extension/svg/ColorSwitchElement.java
index adbb4bc..7ba0237 100644
--- a/sources/org/apache/batik/extension/svg/ColorSwitchElement.java
+++ b/sources/org/apache/batik/extension/svg/ColorSwitchElement.java
@@ -22,7 +22,7 @@
 import org.w3c.dom.Node;
 
 /**
- * This class implements a regular polygon extension to SVG
+ * This class implements a "color switch" extension to SVG.
  *
  * @author <a href="mailto:thomas.deweese@kodak.com">Thomas DeWeese</a>
  * @version $Id$
diff --git a/sources/org/apache/batik/extension/svg/FlowTextElement.java b/sources/org/apache/batik/extension/svg/FlowTextElement.java
index 0aba363..0c52148 100644
--- a/sources/org/apache/batik/extension/svg/FlowTextElement.java
+++ b/sources/org/apache/batik/extension/svg/FlowTextElement.java
@@ -18,7 +18,7 @@
 package org.apache.batik.extension.svg;
 
 import org.apache.batik.dom.AbstractDocument;
-import org.apache.batik.extension.PrefixableStylableExtensionElement;
+import org.apache.batik.extension.GraphicsExtensionElement;
 import org.w3c.dom.Node;
 
 /**
@@ -28,7 +28,7 @@
  * @version $Id$
  */
 public class FlowTextElement
-    extends    PrefixableStylableExtensionElement 
+    extends    GraphicsExtensionElement 
     implements BatikExtConstants {
 
     /**
diff --git a/sources/org/apache/batik/parser/UnitProcessor.java b/sources/org/apache/batik/parser/UnitProcessor.java
index 982b06c..0a7c1a8 100644
--- a/sources/org/apache/batik/parser/UnitProcessor.java
+++ b/sources/org/apache/batik/parser/UnitProcessor.java
@@ -106,7 +106,7 @@
             // in the objectBoundingBox coordinate system
             return svgToUserSpace(value, type, d, ctx);
         default:
-            throw new Error(); // can't be reached
+            throw new IllegalArgumentException("Length has unknown type");
         }
     }
 
@@ -169,7 +169,7 @@
         case SVGLength.SVG_LENGTHTYPE_PERCENTAGE:
             return percentagesToPixels(v, d, ctx);
         default:
-            throw new Error(); // can't be reached
+            throw new IllegalArgumentException("Length has unknown type");
         }
     }
 
@@ -207,7 +207,7 @@
         case SVGLength.SVG_LENGTHTYPE_PERCENTAGE:
             return pixelsToPercentages(v, d, ctx);
         default:
-            throw new Error(); // can't be reached
+            throw new IllegalArgumentException("Length has unknown type");
         }
     }
 
diff --git a/test-sources/org/apache/batik/apps/rasterizer/SVGConverterTest.java b/test-sources/org/apache/batik/apps/rasterizer/SVGConverterTest.java
index a14bfd6..4532510 100644
--- a/test-sources/org/apache/batik/apps/rasterizer/SVGConverterTest.java
+++ b/test-sources/org/apache/batik/apps/rasterizer/SVGConverterTest.java
@@ -377,7 +377,7 @@
                    
         t = new ConfigErrorTest(SVGConverter.ERROR_UNABLE_TO_CREATE_OUTPUT_DIR){
                 protected void configure(SVGConverter c){
-                    c.setDst(new File("ZYZ::/cannotCreate"));
+                    c.setDst(new File("ZYZ::/cannotCreate\000"));
                 }
             };
         addTest(t);