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:31 UTC

[16/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/SVGAnimateTransformElementBridge.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGAnimateTransformElementBridge.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGAnimateTransformElementBridge.java
new file mode 100644
index 0000000..9b6e33a
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGAnimateTransformElementBridge.java
@@ -0,0 +1,286 @@
+/*
+
+   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.util.ArrayList;
+
+import org.apache.flex.forks.batik.anim.AbstractAnimation;
+import org.apache.flex.forks.batik.dom.anim.AnimationTarget;
+import org.apache.flex.forks.batik.anim.TransformAnimation;
+import org.apache.flex.forks.batik.anim.values.AnimatableValue;
+import org.apache.flex.forks.batik.anim.values.AnimatableTransformListValue;
+import org.apache.flex.forks.batik.dom.svg.SVGOMTransform;
+import org.apache.flex.forks.batik.util.SVGTypes;
+
+import org.w3c.dom.svg.SVGTransform;
+
+/**
+ * Bridge class for the 'animateTransform' animation element.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: SVGAnimateTransformElementBridge.java 496029 2007-01-14 04:00:34Z cam $
+ */
+public class SVGAnimateTransformElementBridge extends SVGAnimateElementBridge {
+
+    /**
+     * Returns 'animateTransform'.
+     */
+    public String getLocalName() {
+        return SVG_ANIMATE_TRANSFORM_TAG;
+    }
+
+    /**
+     * Returns a new instance of this bridge.
+     */
+    public Bridge getInstance() {
+        return new SVGAnimateTransformElementBridge();
+    }
+
+    /**
+     * Creates the animation object for the animation element.
+     */
+    protected AbstractAnimation createAnimation(AnimationTarget target) {
+        short type = parseType();
+        AnimatableValue from = null, to = null, by = null;
+        if (element.hasAttributeNS(null, SVG_FROM_ATTRIBUTE)) {
+            from = parseValue(element.getAttributeNS(null, SVG_FROM_ATTRIBUTE),
+                              type, target);
+        }
+        if (element.hasAttributeNS(null, SVG_TO_ATTRIBUTE)) {
+            to = parseValue(element.getAttributeNS(null, SVG_TO_ATTRIBUTE),
+                            type, target);
+        }
+        if (element.hasAttributeNS(null, SVG_BY_ATTRIBUTE)) {
+            by = parseValue(element.getAttributeNS(null, SVG_BY_ATTRIBUTE),
+                            type, target);
+        }
+        return new TransformAnimation(timedElement,
+                                      this,
+                                      parseCalcMode(),
+                                      parseKeyTimes(),
+                                      parseKeySplines(),
+                                      parseAdditive(),
+                                      parseAccumulate(),
+                                      parseValues(type, target),
+                                      from,
+                                      to,
+                                      by,
+                                      type);
+    }
+
+    /**
+     * Returns the parsed 'type' attribute from the animation element.
+     */
+    protected short parseType() {
+        String typeString = element.getAttributeNS(null, SVG_TYPE_ATTRIBUTE);
+        if (typeString.equals("translate")) {
+            return SVGTransform.SVG_TRANSFORM_TRANSLATE;
+        } else if (typeString.equals("scale")) {
+            return SVGTransform.SVG_TRANSFORM_SCALE;
+        } else if (typeString.equals("rotate")) {
+            return SVGTransform.SVG_TRANSFORM_ROTATE;
+        } else if (typeString.equals("skewX")) {
+            return SVGTransform.SVG_TRANSFORM_SKEWX;
+        } else if (typeString.equals("skewY")) {
+            return SVGTransform.SVG_TRANSFORM_SKEWY;
+        }
+        throw new BridgeException
+            (ctx, element, ErrorConstants.ERR_ATTRIBUTE_VALUE_MALFORMED,
+             new Object[] { SVG_TYPE_ATTRIBUTE, typeString });
+    }
+
+    /**
+     * Parses a transform value.
+     */
+    protected AnimatableValue parseValue(String s, short type,
+                                         AnimationTarget target) {
+        float val1, val2 = 0, val3 = 0;
+        int i = 0;
+        char c = ',';
+        int len = s.length();
+        while (i < len) {
+            c = s.charAt(i);
+            if (c == ' ' || c == ',') {
+                break;
+            }
+            i++;
+        }
+        val1 = Float.parseFloat(s.substring(0, i));
+        if (i < len) {
+            i++;
+        }
+        int count = 1;
+        if (i < len && c == ' ') {
+            while (i < len) {
+                c = s.charAt(i);
+                if (c != ' ') {
+                    break;
+                }
+                i++;
+            }
+            if (c == ',') {
+                i++;
+            }
+        }
+        while (i < len && s.charAt(i) == ' ') {
+            i++;
+        }
+        int j = i;
+        if (i < len
+                && type != SVGTransform.SVG_TRANSFORM_SKEWX
+                && type != SVGTransform.SVG_TRANSFORM_SKEWY) {
+            while (i < len) {
+                c = s.charAt(i);
+                if (c == ' ' || c == ',') {
+                    break;
+                }
+                i++;
+            }
+            val2 = Float.parseFloat(s.substring(j, i));
+            if (i < len) {
+                i++;
+            }
+            count++;
+            if (i < len && c == ' ') {
+                while (i < len) {
+                    c = s.charAt(i);
+                    if (c != ' ') {
+                        break;
+                    }
+                    i++;
+                }
+                if (c == ',') {
+                    i++;
+                }
+            }
+            while (i < len && s.charAt(i) == ' ') {
+                i++;
+            }
+            j = i;
+            if (i < len && type == SVGTransform.SVG_TRANSFORM_ROTATE) {
+                while (i < len) {
+                    c = s.charAt(i);
+                    if (c == ',' || c == ' ') {
+                        break;
+                    }
+                    i++;
+                }
+                val3 = Float.parseFloat(s.substring(j, i));
+                if (i < len) {
+                    i++;
+                }
+                count++;
+                while (i < len && s.charAt(i) == ' ') {
+                    i++;
+                }
+            }
+        }
+
+        if (i != len) {
+            return null;
+        }
+
+        SVGOMTransform t = new SVGOMTransform();
+        switch (type) {
+            case SVGTransform.SVG_TRANSFORM_TRANSLATE:
+                if (count == 2) {
+                    t.setTranslate(val1, val2);
+                } else {
+                    t.setTranslate(val1, 0f);
+                }
+                break;
+            case SVGTransform.SVG_TRANSFORM_SCALE:
+                if (count == 2) {
+                    t.setScale(val1, val2);
+                } else {
+                    t.setScale(val1, val1);
+                }
+                break;
+            case SVGTransform.SVG_TRANSFORM_ROTATE:
+                if (count == 3) {
+                    t.setRotate(val1, val2, val3);
+                } else {
+                    t.setRotate(val1, 0f, 0f);
+                }
+                break;
+            case SVGTransform.SVG_TRANSFORM_SKEWX:
+                t.setSkewX(val1);
+                break;
+            case SVGTransform.SVG_TRANSFORM_SKEWY:
+                t.setSkewY(val1);
+                break;
+        }
+        return new AnimatableTransformListValue(target, t);
+    }
+
+    /**
+     * Returns the parsed 'values' attribute from the animation element.
+     */
+    protected AnimatableValue[] parseValues(short type,
+                                            AnimationTarget target) {
+        String valuesString = element.getAttributeNS(null,
+                                                     SVG_VALUES_ATTRIBUTE);
+        int len = valuesString.length();
+        if (len == 0) {
+            return null;
+        }
+        ArrayList values = new ArrayList(7);
+        int i = 0, start = 0, end;
+        char c;
+outer:  while (i < len) {
+            while (valuesString.charAt(i) == ' ') {
+                i++;
+                if (i == len) {
+                    break outer;
+                }
+            }
+            start = i++;
+            if (i < len) {
+                c = valuesString.charAt(i);
+                while (c != ';') {
+                    i++;
+                    if (i == len) {
+                        break;
+                    }
+                    c = valuesString.charAt(i);
+                }
+            }
+            end = i++;
+            String valueString = valuesString.substring(start, end);
+            AnimatableValue value = parseValue(valueString, type, target);
+            if (value == null) {
+                throw new BridgeException
+                    (ctx, element, ErrorConstants.ERR_ATTRIBUTE_VALUE_MALFORMED,
+                     new Object[] { SVG_VALUES_ATTRIBUTE, valuesString });
+            }
+            values.add(value);
+        }
+        AnimatableValue[] ret = new AnimatableValue[values.size()];
+        return (AnimatableValue[]) values.toArray(ret);
+    }
+
+    /**
+     * Returns whether the animation element being handled by this bridge can
+     * animate attributes of the specified type.
+     * @param type one of the TYPE_ constants defined in {@link SVGTypes}.
+     */
+    protected boolean canAnimateType(int type) {
+        return type == SVGTypes.TYPE_TRANSFORM_LIST;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGAnimationElementBridge.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGAnimationElementBridge.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGAnimationElementBridge.java
new file mode 100644
index 0000000..c3766e0
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/bridge/SVGAnimationElementBridge.java
@@ -0,0 +1,655 @@
+/*
+
+   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.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+
+import java.util.Calendar;
+
+import org.apache.flex.forks.batik.anim.AbstractAnimation;
+import org.apache.flex.forks.batik.anim.AnimationEngine;
+import org.apache.flex.forks.batik.anim.timing.TimedElement;
+import org.apache.flex.forks.batik.anim.values.AnimatableValue;
+import org.apache.flex.forks.batik.css.engine.CSSEngineEvent;
+import org.apache.flex.forks.batik.dom.AbstractNode;
+import org.apache.flex.forks.batik.dom.anim.AnimatableElement;
+import org.apache.flex.forks.batik.dom.anim.AnimationTarget;
+import org.apache.flex.forks.batik.dom.anim.AnimationTargetListener;
+import org.apache.flex.forks.batik.dom.svg.AnimatedLiveAttributeValue;
+import org.apache.flex.forks.batik.dom.svg.SVGAnimationContext;
+import org.apache.flex.forks.batik.dom.svg.SVGOMElement;
+import org.apache.flex.forks.batik.dom.util.XLinkSupport;
+import org.apache.flex.forks.batik.util.SVGTypes;
+
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.events.EventTarget;
+import org.w3c.dom.events.MutationEvent;
+import org.w3c.dom.svg.SVGElement;
+
+/**
+ * An abstract base class for the SVG animation element bridges.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: SVGAnimationElementBridge.java 580684 2007-09-30 09:05:57Z cam $
+ */
+public abstract class SVGAnimationElementBridge extends AbstractSVGBridge
+        implements GenericBridge,
+                   BridgeUpdateHandler,
+                   SVGAnimationContext,
+                   AnimatableElement {
+
+    /**
+     * The animation element.
+     */
+    protected SVGOMElement element;
+
+    /**
+     * The BridgeContext to be used.
+     */
+    protected BridgeContext ctx;
+
+    /**
+     * The AnimationEngine that manages all of the animations in the document.
+     */
+    protected SVGAnimationEngine eng;
+
+    /**
+     * The TimedElement object that provides the timing for the animation.
+     */
+    protected TimedElement timedElement;
+
+    /**
+     * The animation object that provides the values for the animation.
+     */
+    protected AbstractAnimation animation;
+
+    /**
+     * The namespace URI of the attribute being animated.
+     */
+    protected String attributeNamespaceURI;
+
+    /**
+     * The local name of the attribute or the name of the property being
+     * animated.
+     */
+    protected String attributeLocalName;
+
+    /**
+     * The animation type.  Must be one of the <code>ANIM_TYPE_*</code>
+     * constants defined in {@link AnimationEngine}.
+     */
+    protected short animationType;
+
+    /**
+     * The target element of the animation.
+     */
+    protected SVGOMElement targetElement;
+
+    /**
+     * The AnimationTarget the provides a context to the animation engine.
+     */
+    protected AnimationTarget animationTarget;
+
+    /**
+     * Returns the TimedElement for the animation.
+     */
+    public TimedElement getTimedElement() {
+        return timedElement;
+    }
+
+    // AnimatableElement /////////////////////////////////////////////////////
+
+    /**
+     * Returns the underlying value of the animated attribute.  Used for
+     * composition of additive animations.  This should be overridden in
+     * descendant classes that are for 'other' animations.
+     */
+    public AnimatableValue getUnderlyingValue() {
+        if (animationType == AnimationEngine.ANIM_TYPE_XML) {
+            return animationTarget.getUnderlyingValue(attributeNamespaceURI,
+                                                      attributeLocalName);
+        } else {
+            return eng.getUnderlyingCSSValue(element,
+                                             animationTarget,
+                                             attributeLocalName);
+        }
+    }
+
+    // GenericBridge /////////////////////////////////////////////////////////
+
+    /**
+     * Handles this animation element.
+     *
+     * @param ctx the bridge context to use
+     * @param e the element being handled
+     */
+    public void handleElement(BridgeContext ctx, Element e) {
+        if (ctx.isDynamic() && BridgeContext.getSVGContext(e) == null) {
+            SVGAnimationElementBridge b =
+                (SVGAnimationElementBridge) getInstance();
+            b.element = (SVGOMElement) e;
+            b.ctx = ctx;
+            b.eng = ctx.getAnimationEngine();
+            b.element.setSVGContext(b);
+            if (b.eng.hasStarted()) {
+                b.initializeAnimation();
+                b.initializeTimedElement();
+            } else {
+                b.eng.addInitialBridge(b);
+            }
+        }
+    }
+
+    /**
+     * Parses the animation element's target attributes and adds it to the
+     * document's AnimationEngine.
+     */
+    protected void initializeAnimation() {
+        // Determine the target element.
+        String uri = XLinkSupport.getXLinkHref(element);
+        Node t;
+        if (uri.length() == 0) {
+            t = element.getParentNode();
+        } else {
+            t = ctx.getReferencedElement(element, uri);
+            if (t.getOwnerDocument() != element.getOwnerDocument()) {
+                throw new BridgeException
+                    (ctx, element, ErrorConstants.ERR_URI_BAD_TARGET,
+                     new Object[] { uri });
+            }
+        }
+        animationTarget = null;
+        if (t instanceof SVGOMElement) {
+            targetElement = (SVGOMElement) t;
+            animationTarget = targetElement;
+        }
+        if (animationTarget == null) {
+            throw new BridgeException
+                (ctx, element, ErrorConstants.ERR_URI_BAD_TARGET,
+                 new Object[] { uri });
+        }
+
+        // Get the attribute/property name.
+        String an = element.getAttributeNS(null, SVG_ATTRIBUTE_NAME_ATTRIBUTE);
+        int ci = an.indexOf(':');
+        if (ci == -1) {
+            if (element.hasProperty(an)) {
+                animationType = AnimationEngine.ANIM_TYPE_CSS;
+                attributeLocalName = an;
+            } else {
+                animationType = AnimationEngine.ANIM_TYPE_XML;
+                attributeLocalName = an;
+            }
+        } else {
+            animationType = AnimationEngine.ANIM_TYPE_XML;
+            String prefix = an.substring(0, ci);
+            attributeNamespaceURI = element.lookupNamespaceURI(prefix);
+            attributeLocalName = an.substring(ci + 1);
+        }
+        if (animationType == AnimationEngine.ANIM_TYPE_CSS
+                && !targetElement.isPropertyAnimatable(attributeLocalName)
+            || animationType == AnimationEngine.ANIM_TYPE_XML
+                && !targetElement.isAttributeAnimatable(attributeNamespaceURI,
+                                                        attributeLocalName)) {
+            throw new BridgeException
+                (ctx, element, "attribute.not.animatable",
+                 new Object[] { targetElement.getNodeName(), an });
+        }
+
+        // Check that the attribute/property is animatable with this
+        // animation element.
+        int type;
+        if (animationType == AnimationEngine.ANIM_TYPE_CSS) {
+            type = targetElement.getPropertyType(attributeLocalName);
+        } else {
+            type = targetElement.getAttributeType(attributeNamespaceURI,
+                                                  attributeLocalName);
+        }
+        if (!canAnimateType(type)) {
+            throw new BridgeException
+                (ctx, element, "type.not.animatable",
+                 new Object[] { targetElement.getNodeName(), an,
+                                element.getNodeName() });
+        }
+
+        // Add the animation.
+        timedElement = createTimedElement();
+        animation = createAnimation(animationTarget);
+        eng.addAnimation(animationTarget, animationType, attributeNamespaceURI,
+                         attributeLocalName, animation);
+    }
+
+    /**
+     * Returns whether the animation element being handled by this bridge can
+     * animate attributes of the specified type.
+     * @param type one of the TYPE_ constants defined in {@link SVGTypes}.
+     */
+    protected abstract boolean canAnimateType(int type);
+
+    /**
+     * Returns whether the specified {@link AnimatableValue} is of a type allowed
+     * by this animation.
+     */
+    protected boolean checkValueType(AnimatableValue v) {
+        return true;
+    }
+
+    /**
+     * Parses the animation element's timing attributes and initializes the
+     * {@link TimedElement} object.
+     */
+    protected void initializeTimedElement() {
+        initializeTimedElement(timedElement);
+        timedElement.initialize();
+    }
+
+    /**
+     * Creates a TimedElement for the animation element.
+     */
+    protected TimedElement createTimedElement() {
+        return new SVGTimedElement();
+    }
+
+    /**
+     * Creates the animation object for the animation element.
+     */
+    protected abstract AbstractAnimation createAnimation(AnimationTarget t);
+
+    /**
+     * Parses an attribute as an AnimatableValue.
+     */
+    protected AnimatableValue parseAnimatableValue(String an) {
+        if (!element.hasAttributeNS(null, an)) {
+            return null;
+        }
+        String s = element.getAttributeNS(null, an);
+        AnimatableValue val = eng.parseAnimatableValue
+            (element, animationTarget, attributeNamespaceURI,
+             attributeLocalName, animationType == AnimationEngine.ANIM_TYPE_CSS,
+             s);
+        if (!checkValueType(val)) {
+            throw new BridgeException
+                (ctx, element, ErrorConstants.ERR_ATTRIBUTE_VALUE_MALFORMED,
+                 new Object[] { an, s });
+        }
+        return val;
+    }
+
+    /**
+     * Initializes the timing attributes of the timed element.
+     */
+    protected void initializeTimedElement(TimedElement timedElement) {
+        timedElement.parseAttributes
+            (element.getAttributeNS(null, "begin"),
+             element.getAttributeNS(null, "dur"),
+             element.getAttributeNS(null, "end"),
+             element.getAttributeNS(null, "min"),
+             element.getAttributeNS(null, "max"),
+             element.getAttributeNS(null, "repeatCount"),
+             element.getAttributeNS(null, "repeatDur"),
+             element.getAttributeNS(null, "fill"),
+             element.getAttributeNS(null, "restart"));
+    }
+
+    // BridgeUpdateHandler ///////////////////////////////////////////////////
+
+    /**
+     * Invoked when an MutationEvent of type 'DOMAttrModified' is fired.
+     */
+    public void handleDOMAttrModifiedEvent(MutationEvent evt) {
+    }
+
+    /**
+     * Invoked when an MutationEvent of type 'DOMNodeInserted' is fired.
+     */
+    public void handleDOMNodeInsertedEvent(MutationEvent evt) {
+    }
+
+    /**
+     * Invoked when an MutationEvent of type 'DOMNodeRemoved' is fired.
+     */
+    public void handleDOMNodeRemovedEvent(MutationEvent evt) {
+        element.setSVGContext(null);
+        dispose();
+    }
+
+    /**
+     * Invoked when an MutationEvent of type 'DOMCharacterDataModified' 
+     * is fired.
+     */
+    public void handleDOMCharacterDataModified(MutationEvent evt) {
+    }
+
+    /**
+     * Invoked when an CSSEngineEvent is fired.
+     */
+    public void handleCSSEngineEvent(CSSEngineEvent evt) {
+    }
+
+    /**
+     * Invoked when the animated value of an animatable attribute has changed.
+     */
+    public void handleAnimatedAttributeChanged
+            (AnimatedLiveAttributeValue alav) {
+    }
+
+    /**
+     * Invoked when an 'other' animation value has changed.
+     */
+    public void handleOtherAnimationChanged(String type) {
+    }
+
+    /**
+     * Disposes this BridgeUpdateHandler and releases all resources.
+     */
+    public void dispose() {
+        if (element.getSVGContext() == null) {
+            // Only remove the animation if this is not part of a rebuild.
+            eng.removeAnimation(animation);
+            timedElement.deinitialize();
+            timedElement = null;
+            element = null;
+        }
+    }
+
+    // SVGContext ///////////////////////////////////////////////////////////
+
+    /**
+     * Returns the size of a px CSS unit in millimeters.
+     */
+    public float getPixelUnitToMillimeter() {
+        return ctx.getUserAgent().getPixelUnitToMillimeter();
+    }
+
+    /**
+     * Returns the size of a px CSS unit in millimeters.
+     * This will be removed after next release.
+     * @see #getPixelUnitToMillimeter()
+     */
+    public float getPixelToMM() {
+        return getPixelUnitToMillimeter();
+            
+    }
+
+    public Rectangle2D getBBox() { return null; }
+    public AffineTransform getScreenTransform() { 
+        return ctx.getUserAgent().getTransform();
+    }
+    public void setScreenTransform(AffineTransform at) { 
+        ctx.getUserAgent().setTransform(at);
+    }
+    public AffineTransform getCTM() { return null; }
+    public AffineTransform getGlobalTransform() { return null; }
+    public float getViewportWidth() {
+        return ctx.getBlockWidth(element);
+    }
+    public float getViewportHeight() {
+        return ctx.getBlockHeight(element);
+    }
+    public float getFontSize() { return 0; }
+    public float svgToUserSpace(float v, int type, int pcInterp) {
+        return 0;
+    }
+
+    /**
+     * Adds a listener for changes to the given attribute value.
+     */
+    public void addTargetListener(String pn, AnimationTargetListener l) {
+    }
+
+    /**
+     * Removes a listener for changes to the given attribute value.
+     */
+    public void removeTargetListener(String pn, AnimationTargetListener l) {
+    }
+
+    // SVGAnimationContext ///////////////////////////////////////////////////
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.svg.SVGAnimationElement#getTargetElement()}.
+     */
+    public SVGElement getTargetElement() {
+        return targetElement;
+    }
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.svg.SVGAnimationElement#getStartTime()}.
+     */
+    public float getStartTime() {
+        return timedElement.getCurrentBeginTime();
+    }
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.svg.SVGAnimationElement#getCurrentTime()}.
+     */
+    public float getCurrentTime() {
+        return timedElement.getLastSampleTime();
+    }
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.svg.SVGAnimationElement#getSimpleDuration()}.  With the
+     * difference that an indefinite simple duration is returned as
+     * {@link TimedElement#INDEFINITE}, rather than throwing an exception.
+     */
+    public float getSimpleDuration() {
+        return timedElement.getSimpleDur();
+    }
+
+    /**
+     * Returns the time that the document would seek to if this animation
+     * element were hyperlinked to, or <code>NaN</code> if there is no
+     * such begin time.
+     */
+    public float getHyperlinkBeginTime() {
+        return timedElement.getHyperlinkBeginTime();
+    }
+
+    // ElementTimeControl ////////////////////////////////////////////////////
+
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.smil.ElementTimeControl#beginElement()}.
+     */
+    public boolean beginElement() throws DOMException {
+        timedElement.beginElement();
+        return timedElement.canBegin();
+    }
+    
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.smil.ElementTimeControl#beginElementAt(float)}.
+     */
+    public boolean beginElementAt(float offset) throws DOMException {
+        timedElement.beginElement(offset);
+        // XXX Not right, but who knows if it is possible to begin
+        //     at some arbitrary point in the future.
+        return true;
+    }
+    
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.smil.ElementTimeControl#endElement()}.
+     */
+    public boolean endElement() throws DOMException {
+        timedElement.endElement();
+        return timedElement.canEnd();
+    }
+    
+    /**
+     * <b>DOM</b>: Implements {@link
+     * org.w3c.dom.smil.ElementTimeControl#endElementAt(float)}.
+     */
+    public boolean endElementAt(float offset) throws DOMException {
+        timedElement.endElement(offset);
+        // XXX Not right, but who knows if it is possible to begin
+        //     at some arbitrary point in the future.
+        return true;
+    }
+
+    /**
+     * Returns whether this is a constant animation (i.e., a 'set' animation).
+     */
+    protected boolean isConstantAnimation() {
+        return false;
+    }
+
+    /**
+     * A TimedElement class for SVG animation elements.
+     */
+    protected class SVGTimedElement extends TimedElement {
+
+        /**
+         * Returns the DOM element this timed element is for.
+         */
+        public Element getElement() {
+            return element;
+        }
+
+        /**
+         * Fires a TimeEvent of the given type on this element.
+         * @param eventType the type of TimeEvent ("beginEvent", "endEvent"
+         *                  or "repeatEvent").
+         * @param time the timestamp of the event object
+         */
+        protected void fireTimeEvent(String eventType, Calendar time,
+                                     int detail) {
+            AnimationSupport.fireTimeEvent(element, 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) {
+            eng.toActive(animation, 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) {
+            eng.toInactive(animation, isFrozen);
+        }
+
+        /**
+         * Invoked to indicate that this timed element has had its fill removed.
+         */
+        protected void removeFill() {
+            eng.removeFill(animation);
+        }
+
+        /**
+         * 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) {
+            eng.sampledAt(animation, simpleTime, simpleDur, 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) {
+            eng.sampledLastValue(animation, repeatIteration);
+        }
+
+        /**
+         * Returns the timed element with the given ID.
+         */
+        protected TimedElement getTimedElementById(String id) {
+            return AnimationSupport.getTimedElementById(id, element);
+        }
+
+        /**
+         * Returns the event target with the given ID.
+         */
+        protected EventTarget getEventTargetById(String id) {
+            return AnimationSupport.getEventTargetById(id, element);
+        }
+
+        /**
+         * Returns the event target that should be listened to for
+         * access key events.
+         */
+        protected EventTarget getRootEventTarget() {
+            return (EventTarget) element.getOwnerDocument();
+        }
+
+        /**
+         * 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 targetElement;
+        }
+
+        /**
+         * Returns whether this timed element comes before the given timed
+         * element in document order.
+         */
+        public boolean isBefore(TimedElement other) {
+            Element e = ((SVGTimedElement) other).getElement();
+            int pos = ((AbstractNode) element).compareDocumentPosition(e);
+            return (pos & AbstractNode.DOCUMENT_POSITION_PRECEDING) != 0;
+        }
+
+        /**
+         * Returns a string representation of this animation.
+         */
+        public String toString() {
+            if (element != null) {
+                String id = element.getAttributeNS(null, "id");
+                if (id.length() != 0) {
+                    return id;
+                }
+            }
+            return super.toString();
+        }
+
+        /**
+         * Returns whether this timed element is for a constant animation (i.e.,
+         * a 'set' animation.
+         */
+        protected boolean isConstantAnimation() {
+            return SVGAnimationElementBridge.this.isConstantAnimation();
+        }
+    }
+}