You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by jm...@apache.org on 2013/10/08 16:03:30 UTC

[15/62] [abbrv] [partial] Merged Apache Flex 4.9.0 release branch

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGAnimationEngine.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGAnimationEngine.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGAnimationEngine.java
new file mode 100644
index 0000000..dd0d3db
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGAnimationEngine.java
@@ -0,0 +1,1888 @@
+/*
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.flex.forks.batik.bridge;
+
+import java.awt.Color;
+import java.awt.Paint;
+import java.lang.ref.WeakReference;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Arrays;
+import java.util.Set;
+
+import org.apache.flex.forks.batik.anim.AnimationEngine;
+import org.apache.flex.forks.batik.anim.AnimationException;
+import org.apache.flex.forks.batik.dom.anim.AnimationTarget;
+import org.apache.flex.forks.batik.anim.timing.TimedDocumentRoot;
+import org.apache.flex.forks.batik.anim.timing.TimedElement;
+import org.apache.flex.forks.batik.anim.values.AnimatableAngleValue;
+import org.apache.flex.forks.batik.anim.values.AnimatableAngleOrIdentValue;
+import org.apache.flex.forks.batik.anim.values.AnimatableBooleanValue;
+import org.apache.flex.forks.batik.anim.values.AnimatableIntegerValue;
+import org.apache.flex.forks.batik.anim.values.AnimatableLengthValue;
+import org.apache.flex.forks.batik.anim.values.AnimatableLengthListValue;
+import org.apache.flex.forks.batik.anim.values.AnimatableLengthOrIdentValue;
+import org.apache.flex.forks.batik.anim.values.AnimatableNumberValue;
+import org.apache.flex.forks.batik.anim.values.AnimatableNumberListValue;
+import org.apache.flex.forks.batik.anim.values.AnimatableNumberOrPercentageValue;
+import org.apache.flex.forks.batik.anim.values.AnimatablePathDataValue;
+import org.apache.flex.forks.batik.anim.values.AnimatablePointListValue;
+import org.apache.flex.forks.batik.anim.values.AnimatablePreserveAspectRatioValue;
+import org.apache.flex.forks.batik.anim.values.AnimatableNumberOrIdentValue;
+import org.apache.flex.forks.batik.anim.values.AnimatableRectValue;
+import org.apache.flex.forks.batik.anim.values.AnimatableStringValue;
+import org.apache.flex.forks.batik.anim.values.AnimatableValue;
+import org.apache.flex.forks.batik.anim.values.AnimatableColorValue;
+import org.apache.flex.forks.batik.anim.values.AnimatablePaintValue;
+import org.apache.flex.forks.batik.css.engine.CSSEngine;
+import org.apache.flex.forks.batik.css.engine.CSSStylableElement;
+import org.apache.flex.forks.batik.css.engine.StyleMap;
+import org.apache.flex.forks.batik.css.engine.value.FloatValue;
+import org.apache.flex.forks.batik.css.engine.value.StringValue;
+import org.apache.flex.forks.batik.css.engine.value.Value;
+import org.apache.flex.forks.batik.css.engine.value.ValueManager;
+import org.apache.flex.forks.batik.dom.svg.SVGOMDocument;
+import org.apache.flex.forks.batik.dom.svg.SVGOMElement;
+import org.apache.flex.forks.batik.dom.svg.SVGStylableElement;
+import org.apache.flex.forks.batik.parser.DefaultPreserveAspectRatioHandler;
+import org.apache.flex.forks.batik.parser.FloatArrayProducer;
+import org.apache.flex.forks.batik.parser.DefaultLengthHandler;
+import org.apache.flex.forks.batik.parser.LengthArrayProducer;
+import org.apache.flex.forks.batik.parser.LengthHandler;
+import org.apache.flex.forks.batik.parser.LengthListParser;
+import org.apache.flex.forks.batik.parser.LengthParser;
+import org.apache.flex.forks.batik.parser.NumberListParser;
+import org.apache.flex.forks.batik.parser.PathArrayProducer;
+import org.apache.flex.forks.batik.parser.PathParser;
+import org.apache.flex.forks.batik.parser.PointsParser;
+import org.apache.flex.forks.batik.parser.ParseException;
+import org.apache.flex.forks.batik.parser.PreserveAspectRatioHandler;
+import org.apache.flex.forks.batik.parser.PreserveAspectRatioParser;
+import org.apache.flex.forks.batik.util.RunnableQueue;
+import org.apache.flex.forks.batik.util.SMILConstants;
+import org.apache.flex.forks.batik.util.XMLConstants;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.css.CSSPrimitiveValue;
+import org.w3c.dom.css.CSSStyleDeclaration;
+import org.w3c.dom.css.CSSValue;
+import org.w3c.dom.events.EventTarget;
+import org.w3c.dom.svg.SVGAngle;
+import org.w3c.dom.svg.SVGLength;
+import org.w3c.dom.svg.SVGPreserveAspectRatio;
+
+/**
+ * An AnimationEngine for SVG documents.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: SVGAnimationEngine.java 579854 2007-09-27 00:07:53Z cam $
+ */
+public class SVGAnimationEngine extends AnimationEngine {
+
+    /**
+     * The BridgeContext to use for value parsing.
+     */
+    protected BridgeContext ctx;
+
+    /**
+     * The CSSEngine used for CSS value parsing.
+     */
+    protected CSSEngine cssEngine;
+
+    /**
+     * Whether animation processing has started.  This affects whether
+     * animation element bridges add their animation on to the initial
+     * bridge list, or process them immediately.
+     */
+    protected boolean started;
+
+    /**
+     * The Runnable that ticks the document.
+     */
+    protected AnimationTickRunnable animationTickRunnable;
+
+    /**
+     * The factory for unparsed string values.
+     */
+    protected UncomputedAnimatableStringValueFactory
+        uncomputedAnimatableStringValueFactory =
+            new UncomputedAnimatableStringValueFactory();
+
+    /**
+     * The factory for length-or-ident values.
+     */
+    protected AnimatableLengthOrIdentFactory
+        animatableLengthOrIdentFactory = new AnimatableLengthOrIdentFactory();
+
+    /**
+     * The factory for number-or-ident values.
+     */
+    protected AnimatableNumberOrIdentFactory
+        animatableNumberOrIdentFactory =
+            new AnimatableNumberOrIdentFactory(false);
+
+    /**
+     * Factories for {@link AnimatableValue} parsing.
+     */
+    protected Factory[] factories = {
+        null, // TYPE_UNKNOWN
+        new AnimatableIntegerValueFactory(), // TYPE_INTEGER
+        new AnimatableNumberValueFactory(), // TYPE_NUMBER
+        new AnimatableLengthValueFactory(), // TYPE_LENGTH
+        null, // TYPE_NUMBER_OPTIONAL_NUMBER
+        new AnimatableAngleValueFactory(), // TYPE_ANGLE
+        new AnimatableColorValueFactory(), // TYPE_COLOR
+        new AnimatablePaintValueFactory(), // TYPE_PAINT
+        null, // TYPE_PERCENTAGE
+        null, // TYPE_TRANSFORM_LIST
+        uncomputedAnimatableStringValueFactory, // TYPE_URI
+        null, // TYPE_FREQUENCY
+        null, // TYPE_TIME
+        new AnimatableNumberListValueFactory(), // TYPE_NUMBER_LIST
+        new AnimatableLengthListValueFactory(), // TYPE_LENGTH_LIST
+        uncomputedAnimatableStringValueFactory, // TYPE_IDENT
+        uncomputedAnimatableStringValueFactory, // TYPE_CDATA
+        animatableLengthOrIdentFactory, // TYPE_LENGTH_OR_INHERIT
+        uncomputedAnimatableStringValueFactory, // TYPE_IDENT_LIST
+        uncomputedAnimatableStringValueFactory, // TYPE_CLIP_VALUE
+        uncomputedAnimatableStringValueFactory, // TYPE_URI_OR_IDENT
+        uncomputedAnimatableStringValueFactory, // TYPE_CURSOR_VALUE
+        new AnimatablePathDataFactory(), // TYPE_PATH_DATA
+        uncomputedAnimatableStringValueFactory, // TYPE_ENABLE_BACKGROUND_VALUE
+        null, // TYPE_TIME_VALUE_LIST
+        animatableNumberOrIdentFactory, // TYPE_NUMBER_OR_INHERIT
+        uncomputedAnimatableStringValueFactory, // TYPE_FONT_FAMILY_VALUE
+        null, // TYPE_FONT_FACE_FONT_SIZE_VALUE
+        new AnimatableNumberOrIdentFactory(true), // TYPE_FONT_WEIGHT_VALUE
+        new AnimatableAngleOrIdentFactory(), // TYPE_ANGLE_OR_IDENT
+        null, // TYPE_KEY_SPLINES_VALUE
+        new AnimatablePointListValueFactory(), // TYPE_POINTS_VALUE
+        new AnimatablePreserveAspectRatioValueFactory(), // TYPE_PRESERVE_ASPECT_RATIO_VALUE
+        null, // TYPE_URI_LIST
+        uncomputedAnimatableStringValueFactory, // TYPE_LENGTH_LIST_OR_IDENT
+        null, // TYPE_CHARACTER_OR_UNICODE_RANGE_LIST
+        null, // TYPE_UNICODE_RANGE_LIST
+        null, // TYPE_FONT_VALUE
+        null, // TYPE_FONT_DECSRIPTOR_SRC_VALUE
+        animatableLengthOrIdentFactory, // TYPE_FONT_SIZE_VALUE
+        animatableLengthOrIdentFactory, // TYPE_BASELINE_SHIFT_VALUE
+        animatableLengthOrIdentFactory, // TYPE_KERNING_VALUE
+        animatableLengthOrIdentFactory, // TYPE_SPACING_VALUE
+        animatableLengthOrIdentFactory, // TYPE_LINE_HEIGHT_VALUE
+        animatableNumberOrIdentFactory, // TYPE_FONT_SIZE_ADJUST_VALUE
+        null, // TYPE_LANG_VALUE
+        null, // TYPE_LANG_LIST_VALUE
+        new AnimatableNumberOrPercentageValueFactory(), // TYPE_NUMBER_OR_PERCENTAGE
+        null, // TYPE_TIMING_SPECIFIER_LIST
+        new AnimatableBooleanValueFactory(), // TYPE_BOOLEAN
+        new AnimatableRectValueFactory() // TYPE_RECT
+    };
+
+    /**
+     * Whether the document is an SVG 1.2 document.
+     */
+    protected boolean isSVG12;
+
+    /**
+     * List of bridges that will be initialized when the document is started.
+     */
+    protected LinkedList initialBridges = new LinkedList();
+
+    /**
+     * A StyleMap used by the {@link Factory}s when computing CSS values.
+     */
+    protected StyleMap dummyStyleMap;
+
+    /**
+     * The thread that ticks the animation engine.
+     */
+    protected AnimationThread animationThread;
+
+    /**
+     * The animation limiting mode.
+     */
+    protected int animationLimitingMode;
+
+    /**
+     * The amount of animation limiting.
+     */
+    protected float animationLimitingAmount;
+
+    /**
+     * Set of SMIL animation event names for SVG 1.1.
+     */
+    protected static final Set animationEventNames11 = new HashSet();
+
+    /**
+     * Set of SMIL animation event names for SVG 1.2.
+     */
+    protected static final Set animationEventNames12 = new HashSet();
+
+    static {
+        String[] eventNamesCommon = {
+            "click", "mousedown", "mouseup", "mouseover", "mousemove",
+            "mouseout", "beginEvent", "endEvent"
+        };
+        String[] eventNamesSVG11 = {
+            "DOMSubtreeModified", "DOMNodeInserted", "DOMNodeRemoved",
+            "DOMNodeRemovedFromDocument", "DOMNodeInsertedIntoDocument",
+            "DOMAttrModified", "DOMCharacterDataModified", "SVGLoad",
+            "SVGUnload", "SVGAbort", "SVGError", "SVGResize", "SVGScroll",
+            "repeatEvent"
+        };
+        String[] eventNamesSVG12 = {
+            "load", "resize", "scroll", "zoom"
+        };
+        for (int i = 0; i < eventNamesCommon.length; i++) {
+            animationEventNames11.add(eventNamesCommon[i]);
+            animationEventNames12.add(eventNamesCommon[i]);
+        }
+        for (int i = 0; i < eventNamesSVG11.length; i++) {
+            animationEventNames11.add(eventNamesSVG11[i]);
+        }
+        for (int i = 0; i < eventNamesSVG12.length; i++) {
+            animationEventNames12.add(eventNamesSVG12[i]);
+        }
+    }
+
+    /**
+     * Creates a new SVGAnimationEngine.
+     */
+    public SVGAnimationEngine(Document doc, BridgeContext ctx) {
+        super(doc);
+        this.ctx = ctx;
+        SVGOMDocument d = (SVGOMDocument) doc;
+        cssEngine = d.getCSSEngine();
+        dummyStyleMap = new StyleMap(cssEngine.getNumberOfProperties());
+        isSVG12 = d.isSVG12();
+    }
+
+    /**
+     * Disposes this animation engine.
+     */
+    public void dispose() {
+        synchronized (this) {
+            pause();
+            super.dispose();
+        }
+    }
+
+    /**
+     * Adds an animation element bridge to the list of bridges that
+     * require initializing when the document is started.
+     */
+    public void addInitialBridge(SVGAnimationElementBridge b) {
+        if (initialBridges != null) {
+            initialBridges.add(b);
+        }
+    }
+
+    /**
+     * Returns whether animation processing has begun.
+     */
+    public boolean hasStarted() {
+        return started;
+    }
+
+    /**
+     * Parses an AnimatableValue.
+     */
+    public AnimatableValue parseAnimatableValue(Element animElt,
+                                                AnimationTarget target,
+                                                String ns, String ln,
+                                                boolean isCSS,
+                                                String s) {
+        SVGOMElement elt = (SVGOMElement) target.getElement();
+        int type;
+        if (isCSS) {
+            type = elt.getPropertyType(ln);
+        } else {
+            type = elt.getAttributeType(ns, ln);
+        }
+        Factory factory = factories[type];
+        if (factory == null) {
+            String an = ns == null ? ln : '{' + ns + '}' + ln;
+            throw new BridgeException
+                (ctx, animElt, "attribute.not.animatable",
+                 new Object[] { target.getElement().getNodeName(), an });
+        }
+        return factories[type].createValue(target, ns, ln, isCSS, s);
+    }
+
+    /**
+     * Returns an AnimatableValue for the underlying value of a CSS property.
+     */
+    public AnimatableValue getUnderlyingCSSValue(Element animElt,
+                                                 AnimationTarget target,
+                                                 String pn) {
+        ValueManager[] vms = cssEngine.getValueManagers();
+        int idx = cssEngine.getPropertyIndex(pn);
+        if (idx != -1) {
+            int type = vms[idx].getPropertyType();
+            Factory factory = factories[type];
+            if (factory == null) {
+                throw new BridgeException
+                    (ctx, animElt, "attribute.not.animatable",
+                     new Object[] { target.getElement().getNodeName(), pn });
+            }
+            SVGStylableElement e = (SVGStylableElement) target.getElement();
+            CSSStyleDeclaration over = e.getOverrideStyle();
+            String oldValue = over.getPropertyValue(pn);
+            if (oldValue != null) {
+                over.removeProperty(pn);
+            }
+            Value v = cssEngine.getComputedStyle(e, null, idx);
+            if (oldValue != null && !oldValue.equals("")) {
+                over.setProperty(pn, oldValue, null);
+            }
+            return factories[type].createValue(target, pn, v);
+        }
+        // XXX Doesn't handle shorthands.
+        return null;
+    }
+
+    /**
+     * Pauses the animations.
+     */
+    public void pause() {
+        super.pause();
+        UpdateManager um = ctx.getUpdateManager();
+        if (um != null) {
+            um.getUpdateRunnableQueue().setIdleRunnable(null);
+        }
+    }
+
+    /**
+     * Pauses the animations.
+     */
+    public void unpause() {
+        super.unpause();
+        UpdateManager um = ctx.getUpdateManager();
+        if (um != null) {
+            um.getUpdateRunnableQueue().setIdleRunnable(animationTickRunnable);
+        }
+    }
+
+    /**
+     * Returns the current document time.
+     */
+    public float getCurrentTime() {
+        boolean p = pauseTime != 0;
+        unpause();
+        float t = timedDocumentRoot.getCurrentTime();
+        if (p) {
+            pause();
+        }
+        return t;
+    }
+
+    /**
+     * Sets the current document time.
+     */
+    public float setCurrentTime(float t) {
+        float ret = super.setCurrentTime(t);
+        if (animationTickRunnable != null) {
+            animationTickRunnable.resume();
+        }
+        return ret;
+    }
+
+    /**
+     * Creates a new returns a new TimedDocumentRoot object for the document.
+     */
+    protected TimedDocumentRoot createDocumentRoot() {
+        return new AnimationRoot();
+    }
+
+    /**
+     * Starts the animation engine.
+     */
+    public void start(long documentStartTime) {
+        if (started) {
+            return;
+        }
+        started = true;
+        try {
+            try {
+                Calendar cal = Calendar.getInstance();
+                cal.setTime(new Date(documentStartTime));
+                timedDocumentRoot.resetDocument(cal);
+                Object[] bridges = initialBridges.toArray();
+                initialBridges = null;
+                for (int i = 0; i < bridges.length; i++) {
+                    SVGAnimationElementBridge bridge =
+                        (SVGAnimationElementBridge) bridges[i];
+                    bridge.initializeAnimation();
+                }
+                for (int i = 0; i < bridges.length; i++) {
+                    SVGAnimationElementBridge bridge =
+                        (SVGAnimationElementBridge) bridges[i];
+                    bridge.initializeTimedElement();
+                }
+                // tick(0, false);
+                // animationThread = new AnimationThread();
+                // animationThread.start();
+                UpdateManager um = ctx.getUpdateManager();
+                if (um != null) {
+                    RunnableQueue q = um.getUpdateRunnableQueue();
+                    animationTickRunnable = new AnimationTickRunnable(q, this);
+                    q.setIdleRunnable(animationTickRunnable);
+                }
+            } catch (AnimationException ex) {
+                throw new BridgeException(ctx, ex.getElement().getElement(),
+                                          ex.getMessage());
+            }
+        } catch (Exception ex) {
+            if (ctx.getUserAgent() == null) {
+                ex.printStackTrace();
+            } else {
+                ctx.getUserAgent().displayError(ex);
+            }
+        }
+    }
+
+    /**
+     * Sets the animation limiting mode to "none".
+     */
+    public void setAnimationLimitingNone() {
+        animationLimitingMode = 0;
+    }
+
+    /**
+     * Sets the animation limiting mode to a percentage of CPU.
+     * @param pc the maximum percentage of CPU to use (0 &lt; pc ≤ 1)
+     */
+    public void setAnimationLimitingCPU(float pc) {
+        animationLimitingMode = 1;
+        animationLimitingAmount = pc;
+    }
+
+    /**
+     * Sets the animation limiting mode to a number of frames per second.
+     * @param fps the maximum number of frames per second (fps &gt; 0)
+     */
+    public void setAnimationLimitingFPS(float fps) {
+        animationLimitingMode = 2;
+        animationLimitingAmount = fps;
+    }
+
+    /**
+     * A class for the root time container.
+     */
+    protected class AnimationRoot extends TimedDocumentRoot {
+
+        /**
+         * Creates a new AnimationRoot object.
+         */
+        public AnimationRoot() {
+            super(!isSVG12, isSVG12);
+        }
+
+        /**
+         * Returns the namespace URI of the event that corresponds to the given
+         * animation event name.
+         */
+        protected String getEventNamespaceURI(String eventName) {
+            if (!isSVG12) {
+                return null;
+            }
+            if (eventName.equals("focusin")
+                    || eventName.equals("focusout")
+                    || eventName.equals("activate")
+                    || animationEventNames12.contains(eventName)) {
+                return XMLConstants.XML_EVENTS_NAMESPACE_URI;
+            }
+            return null;
+        }
+
+        /**
+         * Returns the type of the event that corresponds to the given
+         * animation event name.
+         */
+        protected String getEventType(String eventName) {
+            if (eventName.equals("focusin")) {
+                return "DOMFocusIn";
+            } else if (eventName.equals("focusout")) {
+                return "DOMFocusOut";
+            } else if (eventName.equals("activate")) {
+                return "DOMActivate";
+            }
+            if (isSVG12) {
+                if (animationEventNames12.contains(eventName)) {
+                    return eventName;
+                }
+            } else {
+                if (animationEventNames11.contains(eventName)) {
+                    return eventName;
+                }
+            }
+            return null;
+        }
+
+        /**
+         * Returns the name of the repeat event.
+         * @return "repeatEvent" for SVG
+         */
+        protected String getRepeatEventName() {
+            return SMILConstants.SMIL_REPEAT_EVENT_NAME;
+        }
+
+        /**
+         * Fires a TimeEvent of the given type on this element.
+         * @param eventType the type of TimeEvent ("beginEvent", "endEvent"
+         *                  or "repeatEvent"/"repeat").
+         * @param time the timestamp of the event object
+         */
+        protected void fireTimeEvent(String eventType, Calendar time,
+                                     int detail) {
+            AnimationSupport.fireTimeEvent
+                ((EventTarget) document, eventType, time, detail);
+        }
+
+        /**
+         * Invoked to indicate this timed element became active at the
+         * specified time.
+         * @param begin the time the element became active, in document simple time
+         */
+        protected void toActive(float begin) {
+        }
+
+        /**
+         * Invoked to indicate that this timed element became inactive.
+         * @param stillActive if true, indicates that the element is still
+         *                    actually active, but between the end of the
+         *                    computed repeat duration and the end of the
+         *                    interval
+         * @param isFrozen whether the element is frozen or not
+         */
+        protected void toInactive(boolean stillActive, boolean isFrozen) {
+        }
+
+        /**
+         * Invoked to indicate that this timed element has had its fill removed.
+         */
+        protected void removeFill() {
+        }
+
+        /**
+         * Invoked to indicate that this timed element has been sampled at the
+         * given time.
+         * @param simpleTime the sample time in local simple time
+         * @param simpleDur the simple duration of the element
+         * @param repeatIteration the repeat iteration during which the element
+         *                        was sampled
+         */
+        protected void sampledAt(float simpleTime, float simpleDur,
+                                 int repeatIteration) {
+        }
+
+        /**
+         * Invoked to indicate that this timed element has been sampled
+         * at the end of its active time, at an integer multiple of the
+         * simple duration.  This is the "last" value that will be used
+         * for filling, which cannot be sampled normally.
+         */
+        protected void sampledLastValue(int repeatIteration) {
+        }
+
+        /**
+         * Returns the timed element with the given ID.
+         */
+        protected TimedElement getTimedElementById(String id) {
+            return AnimationSupport.getTimedElementById(id, document);
+        }
+
+        /**
+         * Returns the event target with the given ID.
+         */
+        protected EventTarget getEventTargetById(String id) {
+            return AnimationSupport.getEventTargetById(id, document);
+        }
+
+        /**
+         * Returns the target of this animation as an {@link EventTarget}.  Used
+         * for eventbase timing specifiers where the element ID is omitted.
+         */
+        protected EventTarget getAnimationEventTarget() {
+            return null;
+        }
+
+        /**
+         * Returns the event target that should be listened to for
+         * access key events.
+         */
+        protected EventTarget getRootEventTarget() {
+            return (EventTarget) document;
+        }
+
+        /**
+         * Returns the DOM element that corresponds to this timed element, if
+         * such a DOM element exists.
+         */
+        public Element getElement() {
+            return null;
+        }
+
+        /**
+         * Returns whether this timed element comes before the given timed
+         * element in document order.
+         */
+        public boolean isBefore(TimedElement other) {
+            return false;
+        }
+
+        /**
+         * Invoked by timed elements in this document to indicate that the
+         * current interval will be re-evaluated at the next sample.
+         */
+        protected void currentIntervalWillUpdate() {
+            if (animationTickRunnable != null) {
+                animationTickRunnable.resume();
+            }
+        }
+    }
+
+    /**
+     * Idle runnable to tick the animation, that reads times from System.in.
+     */
+    protected static class DebugAnimationTickRunnable extends AnimationTickRunnable {
+
+        float t = 0f;
+
+        public DebugAnimationTickRunnable(RunnableQueue q, SVGAnimationEngine eng) {
+            super(q, eng);
+            waitTime = Long.MAX_VALUE;
+            new Thread() {
+                public void run() {
+                    java.io.BufferedReader r = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
+                    System.out.println("Enter times.");
+                    for (;;) {
+                        String s;
+                        try {
+                            s = r.readLine();
+                        } catch (java.io.IOException e) {
+                            s = null;
+                        }
+                        if (s == null) {
+                            System.exit(0);
+                        }
+                        t = Float.parseFloat(s);
+                        DebugAnimationTickRunnable.this.resume();
+                    }
+                }
+            }.start();
+        }
+
+        public void resume() {
+            waitTime = 0;
+            Object lock = q.getIteratorLock();
+            synchronized (lock) {
+                lock.notify();
+            }
+        }
+
+        public long getWaitTime() {
+            long wt = waitTime;
+            waitTime = Long.MAX_VALUE;
+            return wt;
+        }
+
+        public void run() {
+            SVGAnimationEngine eng = getAnimationEngine();
+            synchronized (eng) {
+                try {
+                    try {
+                        eng.tick(t, false);
+                    } catch (AnimationException ex) {
+                        throw new BridgeException
+                            (eng.ctx, ex.getElement().getElement(),
+                             ex.getMessage());
+                    }
+                } catch (Exception ex) {
+                    if (eng.ctx.getUserAgent() == null) {
+                        ex.printStackTrace();
+                    } else {
+                        eng.ctx.getUserAgent().displayError(ex);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Idle runnable to tick the animation.
+     */
+    protected static class AnimationTickRunnable
+            implements RunnableQueue.IdleRunnable {
+
+        /**
+         * Calendar instance used for passing current time values to the
+         * animation timing system.
+         */
+        protected Calendar time = Calendar.getInstance();
+
+//         /**
+//          * The current document time in seconds, truncated.
+//          */
+//         protected double second = -1.;
+
+//         /**
+//          * The number of frames that have been ticked so far this second.
+//          */
+//         protected int frames;
+
+        /**
+         * The number of milliseconds to wait until the next animation tick.
+         * This is returned by {@link #getWaitTime()}.
+         */
+        protected long waitTime;
+
+        /**
+         * The RunnableQueue in which this is the
+         * {@link RunnableQueue.IdleRunnable}.
+         */
+        protected RunnableQueue q;
+
+        /**
+         * The number of past tick times to keep, for computing the average
+         * time per tick.
+         */
+        private static final int NUM_TIMES = 8;
+
+        /**
+         * The past tick times.
+         */
+        protected long[] times = new long[NUM_TIMES];
+
+        /**
+         * The sum of the times in {@link #times}.
+         */
+        protected long sumTime;
+
+        /**
+         * The current index into {@link #times}.
+         */
+        protected int timeIndex;
+
+        /**
+         * A weak reference to the SVGAnimationEngine this AnimationTickRunnable
+         * is for.  We make this a WeakReference so that a ticking animation
+         * engine does not prevent from being GCed.
+         */
+        protected WeakReference engRef;
+
+        /**
+         * The maximum number of consecutive exceptions to allow before
+         * stopping the report of them.
+         */
+        protected static final int MAX_EXCEPTION_COUNT = 10;
+
+        /**
+         * The number of consecutive exceptions that have been thrown.  This is
+         * used to detect when exceptions are occurring every tick, and to stop
+         * reporting them when this happens.
+         */
+        protected int exceptionCount;
+
+        /**
+         * Creates a new AnimationTickRunnable.
+         */
+        public AnimationTickRunnable(RunnableQueue q, SVGAnimationEngine eng) {
+            this.q = q;
+            this.engRef = new WeakReference(eng);
+            // Initialize the past times to 100ms.
+            Arrays.fill(times, 100);
+            sumTime = 100 * NUM_TIMES;
+        }
+
+        /**
+         * Forces an animation update, if the {@link RunnableQueue} is
+         * currently waiting.
+         */
+        public void resume() {
+            waitTime = 0;
+            Object lock = q.getIteratorLock();
+            synchronized (lock) {
+                lock.notify();
+            }
+        }
+
+        /**
+         * Returns the system time that can be safely waited until before this
+         * {@link Runnable} is run again.
+         *
+         * @return time to wait until, <code>0</code> if no waiting can
+         *         be done, or {@link Long#MAX_VALUE} if the {@link Runnable}
+         *         should not be run again at this time
+         */
+        public long getWaitTime() {
+            return waitTime;
+        }
+
+        /**
+         * Performs one tick of the animation.
+         */
+        public void run() {
+            SVGAnimationEngine eng = getAnimationEngine();
+            synchronized (eng) {
+                int animationLimitingMode = eng.animationLimitingMode;
+                float animationLimitingAmount = eng.animationLimitingAmount;
+                try {
+                    try {
+                        long before = System.currentTimeMillis();
+                        time.setTime(new Date(before));
+                        float t = eng.timedDocumentRoot.convertWallclockTime(time);
+//                         if (Math.floor(t) > second) {
+//                             second = Math.floor(t);
+//                             System.err.println("fps: " + frames);
+//                             frames = 0;
+//                         }
+                        float t2 = eng.tick(t, false);
+                        long after = System.currentTimeMillis();
+                        long dur = after - before;
+                        if (dur == 0) {
+                            dur = 1;
+                        }
+                        sumTime -= times[timeIndex];
+                        sumTime += dur;
+                        times[timeIndex] = dur;
+                        timeIndex = (timeIndex + 1) % NUM_TIMES;
+
+                        if (t2 == Float.POSITIVE_INFINITY) {
+                            waitTime = Long.MAX_VALUE;
+                        } else {
+                            waitTime = before + (long) (t2 * 1000) - 1000;
+                            if (waitTime < after) {
+                                waitTime = after;
+                            }
+                            if (animationLimitingMode != 0) {
+                                float ave = (float) sumTime / NUM_TIMES;
+                                float delay;
+                                if (animationLimitingMode == 1) {
+                                    // %cpu
+                                    delay = ave / animationLimitingAmount - ave;
+                                } else {
+                                    // fps
+                                    delay = 1000f / animationLimitingAmount - ave;
+                                }
+                                long newWaitTime = after + (long) delay;
+                                if (newWaitTime > waitTime) {
+                                    waitTime = newWaitTime;
+                                }
+                            }
+                        }
+//                         frames++;
+                    } catch (AnimationException ex) {
+                        throw new BridgeException
+                            (eng.ctx, ex.getElement().getElement(),
+                             ex.getMessage());
+                    }
+                    exceptionCount = 0;
+                } catch (Exception ex) {
+                    if (++exceptionCount < MAX_EXCEPTION_COUNT) {
+                        if (eng.ctx.getUserAgent() == null) {
+                            ex.printStackTrace();
+                        } else {
+                            eng.ctx.getUserAgent().displayError(ex);
+                        }
+                    }
+                }
+
+                if (animationLimitingMode == 0) {
+                    // so we don't steal too much time from the Swing thread
+                    try {
+                        Thread.sleep(1);
+                    } catch (InterruptedException ie) {
+                    }
+                }
+            }
+        }
+
+        /**
+         * Returns the SVGAnimationEngine this AnimationTickRunnable is for.
+         */
+        protected SVGAnimationEngine getAnimationEngine() {
+            return (SVGAnimationEngine) engRef.get();
+        }
+    }
+
+    /**
+     * The thread that ticks the animation.
+     */
+    protected class AnimationThread extends Thread {
+
+        /**
+         * The current time.
+         */
+        protected Calendar time = Calendar.getInstance();
+
+        /**
+         * The RunnableQueue to perform the animation in.
+         */
+        protected RunnableQueue runnableQueue =
+            ctx.getUpdateManager().getUpdateRunnableQueue();
+
+        /**
+         * The animation ticker Runnable.
+         */
+        protected Ticker ticker = new Ticker();
+
+        /**
+         * Ticks the animation over as fast as possible.
+         */
+        public void run() {
+            if (true) {
+                for (;;) {
+                    time.setTime(new Date());
+                    ticker.t = timedDocumentRoot.convertWallclockTime(time);
+                    try {
+                        runnableQueue.invokeAndWait(ticker);
+                    } catch (InterruptedException e) {
+                        return;
+                    }
+                }
+            } else {
+                ticker.t = 1;
+                while (ticker.t < 10) {
+                    try {
+                        Thread.sleep(1000);
+                    } catch (InterruptedException ie) {
+                    }
+                    try {
+                        runnableQueue.invokeAndWait(ticker);
+                    } catch (InterruptedException e) {
+                        return;
+                    }
+                    ticker.t++;
+                }
+            }
+        }
+
+        /**
+         * A runnable that ticks the animation engine.
+         */
+        protected class Ticker implements Runnable {
+
+            /**
+             * The document time to tick at next.
+             */
+            protected float t;
+
+            /**
+             * Ticks the animation over.
+             */
+            public void run() {
+                tick(t, false);
+            }
+        }
+    }
+
+    // AnimatableValue factories
+
+    /**
+     * Interface for AnimatableValue factories.
+     */
+    protected interface Factory {
+
+        /**
+         * Creates a new AnimatableValue from a string.
+         */
+        AnimatableValue createValue(AnimationTarget target, String ns,
+                                    String ln, boolean isCSS, String s);
+
+        /**
+         * Creates a new AnimatableValue from a CSS {@link Value}.
+         */
+        AnimatableValue createValue(AnimationTarget target, String pn, Value v);
+    }
+
+    /**
+     * Factory class for AnimatableValues for CSS properties.
+     * XXX Shorthand properties are not supported.
+     */
+    protected abstract class CSSValueFactory implements Factory {
+
+        public AnimatableValue createValue(AnimationTarget target, String ns,
+                                           String ln, boolean isCSS, String s) {
+            // XXX Always parsing as a CSS value.
+            return createValue(target, ln, createCSSValue(target, ln, s));
+        }
+
+        public AnimatableValue createValue(AnimationTarget target, String pn,
+                                           Value v) {
+            CSSStylableElement elt = (CSSStylableElement) target.getElement();
+            v = computeValue(elt, pn, v);
+            return createAnimatableValue(target, pn, v);
+        }
+
+        /**
+         * Creates a new AnimatableValue from a CSS {@link Value}, after
+         * computation and inheritance.
+         */
+        protected abstract AnimatableValue createAnimatableValue
+            (AnimationTarget target, String pn, Value v);
+
+        /**
+         * Creates a new CSS {@link Value} from a string.
+         */
+        protected Value createCSSValue(AnimationTarget t, String pn, String s) {
+            CSSStylableElement elt = (CSSStylableElement) t.getElement();
+            Value v = cssEngine.parsePropertyValue(elt, pn, s);
+            return computeValue(elt, pn, v);
+        }
+
+        /**
+         * Computes a CSS {@link Value} and performance inheritance if the
+         * specified value is 'inherit'.
+         */
+        protected Value computeValue(CSSStylableElement elt, String pn,
+                                     Value v) {
+            ValueManager[] vms = cssEngine.getValueManagers();
+            int idx = cssEngine.getPropertyIndex(pn);
+            if (idx != -1) {
+                if (v.getCssValueType() == CSSValue.CSS_INHERIT) {
+                    elt = CSSEngine.getParentCSSStylableElement(elt);
+                    if (elt != null) {
+                        return cssEngine.getComputedStyle(elt, null, idx);
+                    }
+                    return vms[idx].getDefaultValue();
+                }
+                v = vms[idx].computeValue(elt, null, cssEngine, idx,
+                                          dummyStyleMap, v);
+            }
+            return v;
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatableBooleanValue}s.
+     */
+    protected class AnimatableBooleanValueFactory implements Factory {
+
+        /**
+         * Creates a new AnimatableValue from a string.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String ns,
+                                           String ln, boolean isCSS, String s) {
+            return new AnimatableBooleanValue(target, "true".equals(s));
+        }
+
+        /**
+         * Creates a new AnimatableValue from a CSS {@link Value}.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String pn,
+                                           Value v) {
+            return new AnimatableBooleanValue(target,
+                                              "true".equals(v.getCssText()));
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatableIntegerValue}s.
+     */
+    protected class AnimatableIntegerValueFactory implements Factory {
+
+        /**
+         * Creates a new AnimatableValue from a string.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String ns,
+                                           String ln, boolean isCSS, String s) {
+            return new AnimatableIntegerValue(target, Integer.parseInt(s));
+        }
+
+        /**
+         * Creates a new AnimatableValue from a CSS {@link Value}.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String pn,
+                                           Value v) {
+            return new AnimatableIntegerValue(target,
+                                              Math.round(v.getFloatValue()));
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatableNumberValue}s.
+     */
+    protected class AnimatableNumberValueFactory implements Factory {
+
+        /**
+         * Creates a new AnimatableValue from a string.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String ns,
+                                           String ln, boolean isCSS, String s) {
+            return new AnimatableNumberValue(target, Float.parseFloat(s));
+        }
+
+        /**
+         * Creates a new AnimatableValue from a CSS {@link Value}.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String pn,
+                                           Value v) {
+            return new AnimatableNumberValue(target, v.getFloatValue());
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatableNumberOrPercentageValue}s.
+     */
+    protected class AnimatableNumberOrPercentageValueFactory
+            implements Factory {
+
+        /**
+         * Creates a new AnimatableValue from a string.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String ns,
+                                           String ln, boolean isCSS, String s) {
+            float v;
+            boolean pc;
+            if (s.charAt(s.length() - 1) == '%') {
+                v = Float.parseFloat(s.substring(0, s.length() - 1));
+                pc = true;
+            } else {
+                v = Float.parseFloat(s);
+                pc = false;
+            }
+            return new AnimatableNumberOrPercentageValue(target, v, pc);
+        }
+
+        /**
+         * Creates a new AnimatableValue from a CSS {@link Value}.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String pn,
+                                           Value v) {
+            switch (v.getPrimitiveType()) {
+                case CSSPrimitiveValue.CSS_PERCENTAGE:
+                    return new AnimatableNumberOrPercentageValue
+                        (target, v.getFloatValue(), true);
+                case CSSPrimitiveValue.CSS_NUMBER:
+                    return new AnimatableNumberOrPercentageValue
+                        (target, v.getFloatValue());
+            }
+            // XXX Do something better than returning null.
+            return null;
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatablePreserveAspectRatioValue}s.
+     */
+    protected class AnimatablePreserveAspectRatioValueFactory implements Factory {
+
+        /**
+         * The parsed 'align' value.
+         */
+        protected short align;
+
+        /**
+         * The parsed 'meetOrSlice' value.
+         */
+        protected short meetOrSlice;
+
+        /**
+         * Parser for preserveAspectRatio values.
+         */
+        protected PreserveAspectRatioParser parser =
+            new PreserveAspectRatioParser();
+
+        /**
+         * Handler for the preserveAspectRatio parser.
+         */
+        protected DefaultPreserveAspectRatioHandler handler =
+            new DefaultPreserveAspectRatioHandler() {
+
+            /**
+             * Implements {@link
+             * PreserveAspectRatioHandler#startPreserveAspectRatio()}.
+             */
+            public void startPreserveAspectRatio() throws ParseException {
+                align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_UNKNOWN;
+                meetOrSlice = SVGPreserveAspectRatio.SVG_MEETORSLICE_UNKNOWN;
+            }
+
+            /**
+             * Implements {@link PreserveAspectRatioHandler#none()}.
+             */
+            public void none() throws ParseException {
+                align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_NONE;
+            }
+
+            /**
+             * Implements {@link PreserveAspectRatioHandler#xMaxYMax()}.
+             */
+            public void xMaxYMax() throws ParseException {
+                align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMAXYMAX;
+            }
+
+            /**
+             * Implements {@link PreserveAspectRatioHandler#xMaxYMid()}.
+             */
+            public void xMaxYMid() throws ParseException {
+                align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMAXYMID;
+            }
+
+            /**
+             * Implements {@link PreserveAspectRatioHandler#xMaxYMin()}.
+             */
+            public void xMaxYMin() throws ParseException {
+                align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMAXYMIN;
+            }
+
+            /**
+             * Implements {@link PreserveAspectRatioHandler#xMidYMax()}.
+             */
+            public void xMidYMax() throws ParseException {
+                align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMAX;
+            }
+
+            /**
+             * Implements {@link PreserveAspectRatioHandler#xMidYMid()}.
+             */
+            public void xMidYMid() throws ParseException {
+                align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMID;
+            }
+
+            /**
+             * Implements {@link PreserveAspectRatioHandler#xMidYMin()}.
+             */
+            public void xMidYMin() throws ParseException {
+                align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMIN;
+            }
+
+            /**
+             * Implements {@link PreserveAspectRatioHandler#xMinYMax()}.
+             */
+            public void xMinYMax() throws ParseException {
+                align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMAX;
+            }
+
+            /**
+             * Implements {@link PreserveAspectRatioHandler#xMinYMid()}.
+             */
+            public void xMinYMid() throws ParseException {
+                align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMID;
+            }
+
+            /**
+             * Implements {@link PreserveAspectRatioHandler#xMinYMin()}.
+             */
+            public void xMinYMin() throws ParseException {
+                align = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMINYMIN;
+            }
+
+            /**
+             * Implements {@link PreserveAspectRatioHandler#meet()}.
+             */
+            public void meet() throws ParseException {
+                meetOrSlice = SVGPreserveAspectRatio.SVG_MEETORSLICE_MEET;
+            }
+
+            /**
+             * Implements {@link PreserveAspectRatioHandler#slice()}.
+             */
+            public void slice() throws ParseException {
+                meetOrSlice = SVGPreserveAspectRatio.SVG_MEETORSLICE_SLICE;
+            }
+        };
+
+        /**
+         * Creates a new AnimatablePreserveAspectRatioValueFactory.
+         */
+        public AnimatablePreserveAspectRatioValueFactory() {
+            parser.setPreserveAspectRatioHandler(handler);
+        }
+
+        /**
+         * Creates a new AnimatableValue from a string.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String ns,
+                                           String ln, boolean isCSS, String s) {
+            try {
+                parser.parse(s);
+                return new AnimatablePreserveAspectRatioValue(target, align,
+                                                              meetOrSlice);
+            } catch (ParseException e) {
+                // XXX Do something better than returning null.
+                return null;
+            }
+        }
+
+        /**
+         * Creates a new AnimatableValue from a CSS {@link Value}.  Returns null
+         * since preserveAspectRatio values aren't used in CSS values.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String pn,
+                                           Value v) {
+            return null;
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatableLengthValue}s.
+     */
+    protected class AnimatableLengthValueFactory implements Factory {
+
+        /**
+         * The parsed length unit type.
+         */
+        protected short type;
+
+        /**
+         * The parsed length value.
+         */
+        protected float value;
+
+        /**
+         * Parser for lengths.
+         */
+        protected LengthParser parser = new LengthParser();
+
+        /**
+         * Handler for the length parser.
+         */
+        protected LengthHandler handler = new DefaultLengthHandler() {
+            public void startLength() throws ParseException {
+                type = SVGLength.SVG_LENGTHTYPE_NUMBER;
+            }
+            public void lengthValue(float v) throws ParseException {
+                value = v;
+            }
+            public void em() throws ParseException {
+                type = SVGLength.SVG_LENGTHTYPE_EMS;
+            }
+            public void ex() throws ParseException {
+                type = SVGLength.SVG_LENGTHTYPE_EXS;
+            }
+            public void in() throws ParseException {
+                type = SVGLength.SVG_LENGTHTYPE_IN;
+            }
+            public void cm() throws ParseException {
+                type = SVGLength.SVG_LENGTHTYPE_CM;
+            }
+            public void mm() throws ParseException {
+                type = SVGLength.SVG_LENGTHTYPE_MM;
+            }
+            public void pc() throws ParseException {
+                type = SVGLength.SVG_LENGTHTYPE_PC;
+            }
+            public void pt() throws ParseException {
+                type = SVGLength.SVG_LENGTHTYPE_PT;
+            }
+            public void px() throws ParseException {
+                type = SVGLength.SVG_LENGTHTYPE_PX;
+            }
+            public void percentage() throws ParseException {
+                type = SVGLength.SVG_LENGTHTYPE_PERCENTAGE;
+            }
+            public void endLength() throws ParseException {
+            }
+        };
+
+        /**
+         * Creates a new AnimatableLengthValueFactory.
+         */
+        public AnimatableLengthValueFactory() {
+            parser.setLengthHandler(handler);
+        }
+
+        /**
+         * Creates a new AnimatableValue from a string.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String ns,
+                                           String ln, boolean isCSS, String s) {
+            short pcInterp = target.getPercentageInterpretation(ns, ln, isCSS);
+            try {
+                parser.parse(s);
+                return new AnimatableLengthValue
+                    (target, type, value, pcInterp);
+            } catch (ParseException e) {
+                // XXX Do something better than returning null.
+                return null;
+            }
+        }
+
+        /**
+         * Creates a new AnimatableValue from a CSS {@link Value}.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String pn,
+                                           Value v) {
+            return new AnimatableIntegerValue(target,
+                                              Math.round(v.getFloatValue()));
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatableLengthListValue}s.
+     */
+    protected class AnimatableLengthListValueFactory implements Factory {
+
+        /**
+         * Parser for length lists.
+         */
+        protected LengthListParser parser = new LengthListParser();
+
+        /**
+         * The producer class that accumulates the lengths.
+         */
+        protected LengthArrayProducer producer = new LengthArrayProducer();
+
+        /**
+         * Creates a new AnimatableLengthListValueFactory.
+         */
+        public AnimatableLengthListValueFactory() {
+            parser.setLengthListHandler(producer);
+        }
+
+        /**
+         * Creates a new AnimatableValue from a string.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String ns,
+                                           String ln, boolean isCSS, String s) {
+            try {
+                short pcInterp = target.getPercentageInterpretation
+                    (ns, ln, isCSS);
+                parser.parse(s);
+                return new AnimatableLengthListValue
+                    (target, producer.getLengthTypeArray(),
+                     producer.getLengthValueArray(),
+                     pcInterp);
+            } catch (ParseException e) {
+                // XXX Do something better than returning null.
+                return null;
+            }
+        }
+
+        /**
+         * Creates a new AnimatableValue from a CSS {@link Value}.  Returns null
+         * since point lists aren't used in CSS values.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String pn,
+                                           Value v) {
+            return null;
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatableNumberListValue}s.
+     */
+    protected class AnimatableNumberListValueFactory implements Factory {
+
+        /**
+         * Parser for number lists.
+         */
+        protected NumberListParser parser = new NumberListParser();
+
+        /**
+         * The producer class that accumulates the numbers.
+         */
+        protected FloatArrayProducer producer = new FloatArrayProducer();
+
+        /**
+         * Creates a new AnimatableNumberListValueFactory.
+         */
+        public AnimatableNumberListValueFactory() {
+            parser.setNumberListHandler(producer);
+        }
+
+        /**
+         * Creates a new AnimatableValue from a string.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String ns,
+                                           String ln, boolean isCSS, String s) {
+            try {
+                parser.parse(s);
+                return new AnimatableNumberListValue(target,
+                                                     producer.getFloatArray());
+            } catch (ParseException e) {
+                // XXX Do something better than returning null.
+                return null;
+            }
+        }
+
+        /**
+         * Creates a new AnimatableValue from a CSS {@link Value}.  Returns null
+         * since number lists aren't used in CSS values.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String pn,
+                                           Value v) {
+            return null;
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatableNumberListValue}s.
+     */
+    protected class AnimatableRectValueFactory implements Factory {
+
+        /**
+         * Parser for number lists.
+         */
+        protected NumberListParser parser = new NumberListParser();
+
+        /**
+         * The producer class that accumulates the numbers.
+         */
+        protected FloatArrayProducer producer = new FloatArrayProducer();
+
+        /**
+         * Creates a new AnimatableNumberListValueFactory.
+         */
+        public AnimatableRectValueFactory() {
+            parser.setNumberListHandler(producer);
+        }
+
+        /**
+         * Creates a new AnimatableValue from a string.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String ns,
+                                           String ln, boolean isCSS, String s) {
+            try {
+                parser.parse(s);
+                float[] r = producer.getFloatArray();
+                if (r.length != 4) {
+                    // XXX Do something better than returning null.
+                    return null;
+                }
+                return new AnimatableRectValue(target, r[0], r[1], r[2], r[3]);
+            } catch (ParseException e) {
+                // XXX Do something better than returning null.
+                return null;
+            }
+        }
+
+        /**
+         * Creates a new AnimatableValue from a CSS {@link Value}.  Returns null
+         * since rects aren't used in CSS values.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String pn,
+                                           Value v) {
+            return null;
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatablePointListValue}s.
+     */
+    protected class AnimatablePointListValueFactory implements Factory {
+
+        /**
+         * Parser for point lists.
+         */
+        protected PointsParser parser = new PointsParser();
+
+        /**
+         * The producer class that accumulates the points.
+         */
+        protected FloatArrayProducer producer = new FloatArrayProducer();
+
+        /**
+         * Creates a new AnimatablePointListValueFactory.
+         */
+        public AnimatablePointListValueFactory() {
+            parser.setPointsHandler(producer);
+        }
+
+        /**
+         * Creates a new AnimatableValue from a string.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String ns,
+                                           String ln, boolean isCSS, String s) {
+            try {
+                parser.parse(s);
+                return new AnimatablePointListValue(target,
+                                                    producer.getFloatArray());
+            } catch (ParseException e) {
+                // XXX Do something better than returning null.
+                return null;
+            }
+        }
+
+        /**
+         * Creates a new AnimatableValue from a CSS {@link Value}.  Returns null
+         * since point lists aren't used in CSS values.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String pn,
+                                           Value v) {
+            return null;
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatablePathDataValue}s.
+     */
+    protected class AnimatablePathDataFactory implements Factory {
+
+        /**
+         * Parser for path data.
+         */
+        protected PathParser parser = new PathParser();
+
+        /**
+         * The producer class that accumulates the path segments.
+         */
+        protected PathArrayProducer producer = new PathArrayProducer();
+
+        /**
+         * Creates a new AnimatablePathDataFactory.
+         */
+        public AnimatablePathDataFactory() {
+            parser.setPathHandler(producer);
+        }
+
+        /**
+         * Creates a new AnimatableValue from a string.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String ns,
+                                           String ln, boolean isCSS, String s) {
+            try {
+                parser.parse(s);
+                return new AnimatablePathDataValue
+                    (target, producer.getPathCommands(),
+                     producer.getPathParameters());
+            } catch (ParseException e) {
+                // XXX Do something better than returning null.
+                return null;
+            }
+        }
+
+        /**
+         * Creates a new AnimatableValue from a CSS {@link Value}.  Returns null
+         * since point lists aren't used in CSS values.
+         */
+        public AnimatableValue createValue(AnimationTarget target, String pn,
+                                           Value v) {
+            return null;
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatableStringValue}s.
+     */
+    protected class UncomputedAnimatableStringValueFactory implements Factory {
+
+        public AnimatableValue createValue(AnimationTarget target, String ns,
+                                           String ln, boolean isCSS, String s) {
+            return new AnimatableStringValue(target, s);
+        }
+
+        public AnimatableValue createValue(AnimationTarget target, String pn,
+                                           Value v) {
+            return new AnimatableStringValue(target, v.getCssText());
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatableLengthOrIdentValue}s.
+     */
+    protected class AnimatableLengthOrIdentFactory extends CSSValueFactory {
+
+        protected AnimatableValue createAnimatableValue(AnimationTarget target,
+                                                        String pn, Value v) {
+            if (v instanceof StringValue) {
+                return new AnimatableLengthOrIdentValue(target,
+                                                        v.getStringValue());
+            }
+            short pcInterp = target.getPercentageInterpretation(null, pn, true);
+            FloatValue fv = (FloatValue) v;
+            return new AnimatableLengthOrIdentValue
+                (target, fv.getPrimitiveType(), fv.getFloatValue(), pcInterp);
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatableNumberOrIdentValue}s.
+     */
+    protected class AnimatableNumberOrIdentFactory extends CSSValueFactory {
+
+        /**
+         * Whether numbers are actually numeric keywords, as with the
+         * font-weight property.
+         */
+        protected boolean numericIdents;
+
+        public AnimatableNumberOrIdentFactory(boolean numericIdents) {
+            this.numericIdents = numericIdents;
+        }
+
+        protected AnimatableValue createAnimatableValue(AnimationTarget target,
+                                                        String pn, Value v) {
+            if (v instanceof StringValue) {
+                return new AnimatableNumberOrIdentValue(target,
+                                                        v.getStringValue());
+            }
+            FloatValue fv = (FloatValue) v;
+            return new AnimatableNumberOrIdentValue(target, fv.getFloatValue(),
+                                                    numericIdents);
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatableAngleValue}s.
+     */
+    protected class AnimatableAngleValueFactory extends CSSValueFactory {
+
+        protected AnimatableValue createAnimatableValue(AnimationTarget target,
+                                                        String pn, Value v) {
+            FloatValue fv = (FloatValue) v;
+            short unit;
+            switch (fv.getPrimitiveType()) {
+                case CSSPrimitiveValue.CSS_NUMBER:
+                case CSSPrimitiveValue.CSS_DEG:
+                    unit = SVGAngle.SVG_ANGLETYPE_DEG;
+                    break;
+                case CSSPrimitiveValue.CSS_RAD:
+                    unit = SVGAngle.SVG_ANGLETYPE_RAD;
+                    break;
+                case CSSPrimitiveValue.CSS_GRAD:
+                    unit = SVGAngle.SVG_ANGLETYPE_GRAD;
+                    break;
+                default:
+                    // XXX Do something better than returning null.
+                    return null;
+            }
+            return new AnimatableAngleValue(target, fv.getFloatValue(), unit);
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatableAngleOrIdentValue}s.
+     */
+    protected class AnimatableAngleOrIdentFactory extends CSSValueFactory {
+
+        protected AnimatableValue createAnimatableValue(AnimationTarget target,
+                                                        String pn, Value v) {
+            if (v instanceof StringValue) {
+                return new AnimatableAngleOrIdentValue(target,
+                                                       v.getStringValue());
+            }
+            FloatValue fv = (FloatValue) v;
+            short unit;
+            switch (fv.getPrimitiveType()) {
+                case CSSPrimitiveValue.CSS_NUMBER:
+                case CSSPrimitiveValue.CSS_DEG:
+                    unit = SVGAngle.SVG_ANGLETYPE_DEG;
+                    break;
+                case CSSPrimitiveValue.CSS_RAD:
+                    unit = SVGAngle.SVG_ANGLETYPE_RAD;
+                    break;
+                case CSSPrimitiveValue.CSS_GRAD:
+                    unit = SVGAngle.SVG_ANGLETYPE_GRAD;
+                    break;
+                default:
+                    // XXX Do something better than returning null.
+                    return null;
+            }
+            return new AnimatableAngleOrIdentValue(target, fv.getFloatValue(),
+                                                   unit);
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatableColorValue}s.
+     */
+    protected class AnimatableColorValueFactory extends CSSValueFactory {
+
+        protected AnimatableValue createAnimatableValue(AnimationTarget target,
+                                                        String pn, Value v) {
+            Paint p = PaintServer.convertPaint
+                (target.getElement(), null, v, 1.0f, ctx);
+            if (p instanceof Color) {
+                Color c = (Color) p;
+                return new AnimatableColorValue(target,
+                                                c.getRed() / 255f,
+                                                c.getGreen() / 255f,
+                                                c.getBlue() / 255f);
+            }
+            // XXX Indicate that the parsed value wasn't a Color?
+            return null;
+        }
+    }
+
+    /**
+     * Factory class for {@link AnimatablePaintValue}s.
+     */
+    protected class AnimatablePaintValueFactory extends CSSValueFactory {
+
+        /**
+         * Creates a new {@link AnimatablePaintValue} from a {@link Color}
+         * object.
+         */
+        protected AnimatablePaintValue createColorPaintValue(AnimationTarget t,
+                                                             Color c) {
+            return AnimatablePaintValue.createColorPaintValue
+                (t, c.getRed() / 255f, c.getGreen() / 255f, c.getBlue() / 255f);
+
+        }
+
+        protected AnimatableValue createAnimatableValue(AnimationTarget target,
+                                                        String pn, Value v) {
+            if (v.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+                switch (v.getPrimitiveType()) {
+                    case CSSPrimitiveValue.CSS_IDENT:
+                        return AnimatablePaintValue.createNonePaintValue(target);
+                    case CSSPrimitiveValue.CSS_RGBCOLOR: {
+                        Paint p = PaintServer.convertPaint
+                            (target.getElement(), null, v, 1.0f, ctx);
+                        return createColorPaintValue(target, (Color) p);
+                    }
+                    case CSSPrimitiveValue.CSS_URI:
+                        return AnimatablePaintValue.createURIPaintValue
+                            (target, v.getStringValue());
+                }
+            } else {
+                Value v1 = v.item(0);
+                switch (v1.getPrimitiveType()) {
+                    case CSSPrimitiveValue.CSS_RGBCOLOR: {
+                        Paint p = PaintServer.convertPaint
+                            (target.getElement(), null, v, 1.0f, ctx);
+                        return createColorPaintValue(target, (Color) p);
+                    }
+                    case CSSPrimitiveValue.CSS_URI: {
+                        Value v2 = v.item(1);
+                        switch (v2.getPrimitiveType()) {
+                            case CSSPrimitiveValue.CSS_IDENT:
+                                return AnimatablePaintValue.createURINonePaintValue
+                                    (target, v1.getStringValue());
+                            case CSSPrimitiveValue.CSS_RGBCOLOR: {
+                                Paint p = PaintServer.convertPaint
+                                    (target.getElement(), null, v.item(1), 1.0f, ctx);
+                                return createColorPaintValue(target, (Color) p);
+                            }
+                        }
+                    }
+                }
+            }
+            // XXX Indicate that the specified Value wasn't a Color?
+            return null;
+        }
+    }
+
+    /**
+     * Factory class for computed CSS {@link AnimatableStringValue}s.
+     */
+    protected class AnimatableStringValueFactory extends CSSValueFactory {
+
+        protected AnimatableValue createAnimatableValue(AnimationTarget target,
+                                                        String pn, Value v) {
+            return new AnimatableStringValue(target, v.getCssText());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGBridgeExtension.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGBridgeExtension.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGBridgeExtension.java
index 3d00998..b1683e3 100644
--- a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGBridgeExtension.java
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGBridgeExtension.java
@@ -1,10 +1,11 @@
 /*
 
-   Copyright 2001-2002,2004-2005  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
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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
 
@@ -26,6 +27,9 @@ import org.w3c.dom.Element;
 /**
  * This is a Service interface for classes that want to extend the
  * functionality of the Bridge, to support new tags in the rendering tree.
+ *
+ * @author <a href="mailto:thomas.deweese@kodak.com">Thomas DeWeese</a>
+ * @version $Id: SVGBridgeExtension.java 475477 2006-11-15 22:44:28Z cam $
  */
 public class SVGBridgeExtension implements BridgeExtension {
 
@@ -147,7 +151,11 @@ public class SVGBridgeExtension implements BridgeExtension {
         ctx.putBridge(new SVGTitleElementBridge());
         ctx.putBridge(new SVGUseElementBridge());
         ctx.putBridge(new SVGVKernElementBridge());
-
+        ctx.putBridge(new SVGSetElementBridge());
+        ctx.putBridge(new SVGAnimateElementBridge());
+        ctx.putBridge(new SVGAnimateColorElementBridge());
+        ctx.putBridge(new SVGAnimateTransformElementBridge());
+        ctx.putBridge(new SVGAnimateMotionElementBridge());
     }
 
     /**
@@ -165,7 +173,7 @@ public class SVGBridgeExtension implements BridgeExtension {
         String ln = e.getLocalName();
         if (ln.equals(SVGConstants.SVG_SCRIPT_TAG)
                 || ln.startsWith("animate")
-                || ln.equals("set")) {
+                || ln.equals(SVGConstants.SVG_SET_TAG)) {
             return true;
         }
         return false;

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGBrokenLinkProvider.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGBrokenLinkProvider.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGBrokenLinkProvider.java
index 27e1f94..1a1f318 100644
--- a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGBrokenLinkProvider.java
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGBrokenLinkProvider.java
@@ -1,10 +1,11 @@
 /*
 
-   Copyright 2001-2003  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
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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
 
@@ -17,53 +18,27 @@
  */
 package org.apache.flex.forks.batik.bridge;
 
-import java.net.URL;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.flex.forks.batik.dom.util.DOMUtilities;
 import org.apache.flex.forks.batik.ext.awt.image.renderable.Filter;
 import org.apache.flex.forks.batik.ext.awt.image.spi.DefaultBrokenLinkProvider;
-import org.apache.flex.forks.batik.gvt.GraphicsNode;
+import org.apache.flex.forks.batik.gvt.CompositeGraphicsNode;
 import org.apache.flex.forks.batik.gvt.filter.GraphicsNodeRable8Bit;
-import org.apache.flex.forks.batik.util.SVGConstants;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.flex.forks.dom.svg.SVGDocument;
+
 /**
  * This interface is to be used to provide alternate ways of 
  * generating a placeholder image when the ImageTagRegistry
  * fails to handle a given reference.
+ *
+ * @author <a href="mailto:thomas.deweese@kodak.com">Thomas DeWeese</a>
+ * @version $Id: SVGBrokenLinkProvider.java 475477 2006-11-15 22:44:28Z cam $
  */
 public class SVGBrokenLinkProvider 
     extends    DefaultBrokenLinkProvider 
     implements ErrorConstants {
 
-    public final static String SVG_BROKEN_LINK_DOCUMENT_PROPERTY = 
-        "org.apache.flex.forks.batik.bridge.BrokenLinkDocument";
-
-    UserAgent      userAgent;
-    DocumentLoader loader;
-    BridgeContext  ctx;
-    GraphicsNode   gvtRoot = null;
-    SVGDocument       svgDoc;
-    
     public SVGBrokenLinkProvider() {
-        userAgent = new UserAgentAdapter();
-        loader    = new DocumentLoader(userAgent);
-        ctx       = new BridgeContext(userAgent, loader);
-
-        Class cls = SVGBrokenLinkProvider.class;
-        URL blURL = cls.getResource("BrokenLink.svg");
-        if (blURL == null) return;
-
-        GVTBuilder builder = new GVTBuilder();
-        try {
-            svgDoc  = (SVGDocument)loader.loadDocument(blURL.toString());
-            gvtRoot = builder.build(ctx, svgDoc);
-        } catch (Exception ex) {
-            // t.printStackTrace();
-        }
     }
 
     /**
@@ -81,38 +56,11 @@ public class SVGBrokenLinkProvider
      *        the circumstances of the failure.  */
     public Filter getBrokenLinkImage(Object base, String code, 
                                      Object[] params) {
-        if (gvtRoot == null) 
-            return null;
-
         String message = formatMessage(base, code, params);
-        Document doc = getBrokenLinkDocument(message);
         Map props = new HashMap();
         props.put(BROKEN_LINK_PROPERTY, message);
-        props.put(SVG_BROKEN_LINK_DOCUMENT_PROPERTY, doc);
-        
-        return new GraphicsNodeRable8Bit(gvtRoot, props);
-    }
-
-    public SVGDocument getBrokenLinkDocument(Object base, 
-                                          String code, Object [] params) {
-        String message = formatMessage(base, code, params);
-        return getBrokenLinkDocument(message);
-    }
 
-    public SVGDocument getBrokenLinkDocument(String message) {
-        SVGDocument doc = (SVGDocument)DOMUtilities.deepCloneDocument
-            (svgDoc, svgDoc.getImplementation());
-        Element infoE = doc.getElementById("__More_About");
-        Element title = doc.createElementNS(SVGConstants.SVG_NAMESPACE_URI,
-                                            SVGConstants.SVG_TITLE_TAG);
-        title.appendChild(doc.createTextNode
-                          (Messages.formatMessage
-                           (MSG_BROKEN_LINK_TITLE, null)));
-        Element desc = doc.createElementNS(SVGConstants.SVG_NAMESPACE_URI,
-                                           SVGConstants.SVG_DESC_TAG);
-        desc.appendChild(doc.createTextNode(message));
-        infoE.insertBefore(desc, infoE.getFirstChild());
-        infoE.insertBefore(title, desc);
-        return doc;
+        CompositeGraphicsNode cgn = new CompositeGraphicsNode();
+        return new GraphicsNodeRable8Bit(cgn, props);
     }
 }

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGCircleElementBridge.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGCircleElementBridge.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGCircleElementBridge.java
index e620f1c..0193610 100644
--- a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGCircleElementBridge.java
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGCircleElementBridge.java
@@ -1,10 +1,11 @@
 /*
 
-   Copyright 2001-2003  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
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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
 
@@ -20,16 +21,20 @@ package org.apache.flex.forks.batik.bridge;
 import java.awt.geom.Ellipse2D;
 import java.awt.geom.Rectangle2D;
 
+import org.apache.flex.forks.batik.dom.svg.AbstractSVGAnimatedLength;
+import org.apache.flex.forks.batik.dom.svg.AnimatedLiveAttributeValue;
+import org.apache.flex.forks.batik.dom.svg.LiveAttributeException;
+import org.apache.flex.forks.batik.dom.svg.SVGOMCircleElement;
 import org.apache.flex.forks.batik.gvt.ShapeNode;
 import org.apache.flex.forks.batik.gvt.ShapePainter;
+
 import org.w3c.dom.Element;
-import org.w3c.dom.events.MutationEvent;
 
 /**
  * Bridge class for the &lt;circle> element.
  *
  * @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
- * @version $Id: SVGCircleElementBridge.java,v 1.15 2004/08/18 07:12:33 vhardy Exp $
+ * @version $Id: SVGCircleElementBridge.java 527382 2007-04-11 04:31:58Z cam $
  */
 public class SVGCircleElementBridge extends SVGShapeElementBridge {
 
@@ -62,57 +67,51 @@ public class SVGCircleElementBridge extends SVGShapeElementBridge {
     protected void buildShape(BridgeContext ctx,
                               Element e,
                               ShapeNode shapeNode) {
-        UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, e);
-        String s;
-
-        // 'cx' attribute - default is 0
-        s = e.getAttributeNS(null, SVG_CX_ATTRIBUTE);
-        float cx = 0;
-        if (s.length() != 0) {
-            cx = UnitProcessor.svgHorizontalCoordinateToUserSpace
-                (s, SVG_CX_ATTRIBUTE, uctx);
-        }
-
-        // 'cy' attribute - default is 0
-        s = e.getAttributeNS(null, SVG_CY_ATTRIBUTE);
-        float cy = 0;
-        if (s.length() != 0) {
-            cy = UnitProcessor.svgVerticalCoordinateToUserSpace
-                (s, SVG_CY_ATTRIBUTE, uctx);
-        }
-
-        // 'r' attribute - required
-        s = e.getAttributeNS(null, SVG_R_ATTRIBUTE);
-        float r;
-        if (s.length() != 0) {
-            r = UnitProcessor.svgOtherLengthToUserSpace
-                (s, SVG_R_ATTRIBUTE, uctx);
-        } else {
-            throw new BridgeException(e, ERR_ATTRIBUTE_MISSING,
-                                      new Object[] {SVG_R_ATTRIBUTE, s});
+        try {
+            SVGOMCircleElement ce = (SVGOMCircleElement) e;
+
+            // 'cx' attribute - default is 0
+            AbstractSVGAnimatedLength _cx =
+                (AbstractSVGAnimatedLength) ce.getCx();
+            float cx = _cx.getCheckedValue();
+
+            // 'cy' attribute - default is 0
+            AbstractSVGAnimatedLength _cy =
+                (AbstractSVGAnimatedLength) ce.getCy();
+            float cy = _cy.getCheckedValue();
+
+            // 'r' attribute - required
+            AbstractSVGAnimatedLength _r =
+                (AbstractSVGAnimatedLength) ce.getR();
+            float r = _r.getCheckedValue();
+
+            float x = cx - r;
+            float y = cy - r;
+            float w = r * 2;
+            shapeNode.setShape(new Ellipse2D.Float(x, y, w, w));
+        } catch (LiveAttributeException ex) {
+            throw new BridgeException(ctx, ex);
         }
-        float x = cx - r;
-        float y = cy - r;
-        float w = r * 2;
-        shapeNode.setShape(new Ellipse2D.Float(x, y, w, w));
     }
 
     // BridgeUpdateHandler implementation //////////////////////////////////
 
     /**
-     * Invoked when an MutationEvent of type 'DOMAttrModified' is fired.
+     * Invoked when the animated value of an animatable attribute has changed.
      */
-    public void handleDOMAttrModifiedEvent(MutationEvent evt) {
-        String attrName = evt.getAttrName();
-        if (attrName.equals(SVG_CX_ATTRIBUTE) ||
-            attrName.equals(SVG_CY_ATTRIBUTE) ||
-            attrName.equals(SVG_R_ATTRIBUTE)) {
-
-            buildShape(ctx, e, (ShapeNode)node);
-            handleGeometryChanged();
-        } else {
-            super.handleDOMAttrModifiedEvent(evt);
+    public void handleAnimatedAttributeChanged
+            (AnimatedLiveAttributeValue alav) {
+        if (alav.getNamespaceURI() == null) {
+            String ln = alav.getLocalName();
+            if (ln.equals(SVG_CX_ATTRIBUTE)
+                    || ln.equals(SVG_CY_ATTRIBUTE)
+                    || ln.equals(SVG_R_ATTRIBUTE)) {
+                buildShape(ctx, e, (ShapeNode)node);
+                handleGeometryChanged();
+                return;
+            }
         }
+        super.handleAnimatedAttributeChanged(alav);
     }
 
     protected ShapePainter createShapePainter(BridgeContext ctx,

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGClipPathElementBridge.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGClipPathElementBridge.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGClipPathElementBridge.java
index 06bc58f..4d77761 100644
--- a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGClipPathElementBridge.java
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGClipPathElementBridge.java
@@ -1,10 +1,11 @@
 /*
 
-   Copyright 2001-2004  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
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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
 
@@ -23,8 +24,7 @@ import java.awt.geom.AffineTransform;
 import java.awt.geom.Area;
 import java.awt.geom.GeneralPath;
 
-import org.apache.flex.forks.batik.css.engine.CSSImportNode;
-import org.apache.flex.forks.batik.dom.svg.SVGOMCSSImportedElementRoot;
+import org.apache.flex.forks.batik.dom.svg.SVGOMUseElement;
 import org.apache.flex.forks.batik.ext.awt.image.renderable.ClipRable;
 import org.apache.flex.forks.batik.ext.awt.image.renderable.ClipRable8Bit;
 import org.apache.flex.forks.batik.ext.awt.image.renderable.Filter;
@@ -37,10 +37,10 @@ import org.w3c.dom.Node;
  * Bridge class for the &lt;clipPath> element.
  *
  * @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
- * @version $Id: SVGClipPathElementBridge.java,v 1.23 2004/11/18 01:46:53 deweese Exp $
+ * @version $Id: SVGClipPathElementBridge.java 475477 2006-11-15 22:44:28Z cam $
  */
-public class SVGClipPathElementBridge extends AbstractSVGBridge
-    implements ClipBridge {
+public class SVGClipPathElementBridge extends AnimatableGenericSVGBridge
+        implements ClipBridge {
 
     /**
      * Constructs a new bridge for the &lt;clipPath> element.
@@ -74,7 +74,7 @@ public class SVGClipPathElementBridge extends AbstractSVGBridge
         s = clipElement.getAttributeNS(null, SVG_TRANSFORM_ATTRIBUTE);
         if (s.length() != 0) {
             Tx = SVGUtilities.convertTransform
-                (clipElement, SVG_TRANSFORM_ATTRIBUTE, s);
+                (clipElement, SVG_TRANSFORM_ATTRIBUTE, s, ctx);
         } else {
             Tx = new AffineTransform();
         }
@@ -86,7 +86,7 @@ public class SVGClipPathElementBridge extends AbstractSVGBridge
             coordSystemType = SVGUtilities.USER_SPACE_ON_USE;
         } else {
             coordSystemType = SVGUtilities.parseCoordinateSystem
-                (clipElement, SVG_CLIP_PATH_UNITS_ATTRIBUTE, s);
+                (clipElement, SVG_CLIP_PATH_UNITS_ATTRIBUTE, s, ctx);
         }
         // additional transform to move to objectBoundingBox coordinate system
         if (coordSystemType == SVGUtilities.OBJECT_BOUNDING_BOX) {
@@ -123,17 +123,13 @@ public class SVGClipPathElementBridge extends AbstractSVGBridge
             hasChildren = true;
 
             // if this is a 'use' element, get the actual shape used
-            if (child instanceof CSSImportNode) {
-                SVGOMCSSImportedElementRoot shadow =
-                    (SVGOMCSSImportedElementRoot)
-                    ((CSSImportNode) child).getCSSImportedElementRoot();
-                
-                if (shadow != null) {
-                    Node shadowChild = shadow.getFirstChild();
-                    if (shadowChild != null
-                            && shadowChild.getNodeType() == Node.ELEMENT_NODE) {
-                        child = (Element) shadowChild;
-                    }
+            if (child instanceof SVGOMUseElement) {
+                Node shadowChild
+                    = ((SVGOMUseElement) child).getCSSFirstChild();
+
+                if (shadowChild != null
+                        && shadowChild.getNodeType() == Node.ELEMENT_NODE) {
+                    child = (Element) shadowChild;
                 }
             }