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

[29/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/anim/MotionAnimation.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/MotionAnimation.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/MotionAnimation.java
new file mode 100644
index 0000000..8d6a102
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/MotionAnimation.java
@@ -0,0 +1,331 @@
+/*
+
+   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.anim;
+
+import java.awt.geom.Point2D;
+
+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.AnimatableMotionPointValue;
+import org.apache.flex.forks.batik.anim.values.AnimatableValue;
+import org.apache.flex.forks.batik.dom.anim.AnimatableElement;
+import org.apache.flex.forks.batik.ext.awt.geom.Cubic;
+import org.apache.flex.forks.batik.ext.awt.geom.ExtendedGeneralPath;
+import org.apache.flex.forks.batik.ext.awt.geom.ExtendedPathIterator;
+import org.apache.flex.forks.batik.ext.awt.geom.PathLength;
+import org.apache.flex.forks.batik.util.SMILConstants;
+
+/**
+ * An animation class for 'animateMotion' animations.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: MotionAnimation.java 575201 2007-09-13 07:41:26Z cam $
+ */
+public class MotionAnimation extends InterpolatingAnimation {
+
+    /**
+     * The path that describes the motion.
+     */
+    protected ExtendedGeneralPath path;
+
+    /**
+     * The path length calculation object.
+     */
+    protected PathLength pathLength;
+
+    /**
+     * The points defining the distance along the path that the
+     * keyTimes apply.
+     */
+    protected float[] keyPoints;
+
+    /**
+     * Whether automatic rotation should be performed.
+     */
+    protected boolean rotateAuto;
+
+    /**
+     * Whether the automatic rotation should be reversed.
+     */
+    protected boolean rotateAutoReverse;
+
+    /**
+     * The angle of rotation (in radians) to use when automatic rotation is
+     * not being used.
+     */
+    protected float rotateAngle;
+
+    /**
+     * Creates a new MotionAnimation.
+     */
+    public MotionAnimation(TimedElement timedElement,
+                           AnimatableElement animatableElement,
+                           int calcMode,
+                           float[] keyTimes,
+                           float[] keySplines,
+                           boolean additive,
+                           boolean cumulative,
+                           AnimatableValue[] values,
+                           AnimatableValue from,
+                           AnimatableValue to,
+                           AnimatableValue by,
+                           ExtendedGeneralPath path,
+                           float[] keyPoints,
+                           boolean rotateAuto,
+                           boolean rotateAutoReverse,
+                           float rotateAngle,
+                           short rotateAngleUnit) {
+        super(timedElement, animatableElement, calcMode, keyTimes, keySplines,
+              additive, cumulative);
+        this.rotateAuto = rotateAuto;
+        this.rotateAutoReverse = rotateAutoReverse;
+        this.rotateAngle = AnimatableAngleValue.rad(rotateAngle, rotateAngleUnit);
+
+        if (path == null) {
+            path = new ExtendedGeneralPath();
+            if (values == null || values.length == 0) {
+                if (from != null) {
+                    AnimatableMotionPointValue fromPt = (AnimatableMotionPointValue) from;
+                    float x = fromPt.getX();
+                    float y = fromPt.getY();
+                    path.moveTo(x, y);
+                    if (to != null) {
+                        AnimatableMotionPointValue toPt = (AnimatableMotionPointValue) to;
+                        path.lineTo(toPt.getX(), toPt.getY());
+                    } else if (by != null) {
+                        AnimatableMotionPointValue byPt = (AnimatableMotionPointValue) by;
+                        path.lineTo(x + byPt.getX(), y + byPt.getY());
+                    } else {
+                        throw timedElement.createException
+                            ("values.to.by.path.missing",
+                             new Object[] { null });
+                    }
+                } else {
+                    if (to != null) {
+                        AnimatableMotionPointValue unPt = (AnimatableMotionPointValue)
+                            animatableElement.getUnderlyingValue();
+                        AnimatableMotionPointValue toPt = (AnimatableMotionPointValue) to;
+                        path.moveTo(unPt.getX(), unPt.getY());
+                        path.lineTo(toPt.getX(), toPt.getY());
+                        this.cumulative = false;
+                    } else if (by != null) {
+                        AnimatableMotionPointValue byPt = (AnimatableMotionPointValue) by;
+                        path.moveTo(0, 0);
+                        path.lineTo(byPt.getX(), byPt.getY());
+                        this.additive = true;
+                    } else {
+                        throw timedElement.createException
+                            ("values.to.by.path.missing",
+                             new Object[] { null });
+                    }
+                }
+            } else {
+                AnimatableMotionPointValue pt = (AnimatableMotionPointValue) values[0];
+                path.moveTo(pt.getX(), pt.getY());
+                for (int i = 1; i < values.length; i++) {
+                    pt = (AnimatableMotionPointValue) values[i];
+                    path.lineTo(pt.getX(), pt.getY());
+                }
+            }
+        }
+        this.path = path;
+        pathLength = new PathLength(path);
+        int segments = 0;
+        ExtendedPathIterator epi = path.getExtendedPathIterator();
+        while (!epi.isDone()) {
+            int type = epi.currentSegment();
+            if (type != ExtendedPathIterator.SEG_MOVETO) {
+                segments++;
+            }
+            epi.next();
+        }
+
+        int count = keyPoints == null ? segments + 1 : keyPoints.length;
+        float totalLength = pathLength.lengthOfPath();
+        if (this.keyTimes != null && calcMode != CALC_MODE_PACED) {
+            if (this.keyTimes.length != count) {
+                throw timedElement.createException
+                    ("attribute.malformed",
+                     new Object[] { null,
+                                    SMILConstants.SMIL_KEY_TIMES_ATTRIBUTE });
+            }
+        } else {
+            if (calcMode == CALC_MODE_LINEAR || calcMode == CALC_MODE_SPLINE) {
+                this.keyTimes = new float[count];
+                for (int i = 0; i < count; i++) {
+                    this.keyTimes[i] = (float) i / (count - 1);
+                }
+            } else if (calcMode == CALC_MODE_DISCRETE) {
+                this.keyTimes = new float[count];
+                for (int i = 0; i < count; i++) {
+                    this.keyTimes[i] = (float) i / count;
+                }
+            } else { // CALC_MODE_PACED
+                // This corrects the keyTimes to be paced, so from now on
+                // it can be considered the same as CALC_MODE_LINEAR.
+                epi = path.getExtendedPathIterator();
+                this.keyTimes = new float[count];
+                int j = 0;
+                for (int i = 0; i < count - 1; i++) {
+                    while (epi.currentSegment() ==
+                            ExtendedPathIterator.SEG_MOVETO) {
+                        j++;
+                        epi.next();
+                    }
+                    this.keyTimes[i] =
+                        pathLength.getLengthAtSegment(j) / totalLength;
+                    j++;
+                    epi.next();
+                }
+                this.keyTimes[count - 1] = 1f;
+            }
+        }
+
+        if (keyPoints != null) {
+            if (keyPoints.length != this.keyTimes.length) {
+                throw timedElement.createException
+                    ("attribute.malformed",
+                     new Object[] { null,
+                                    SMILConstants.SMIL_KEY_POINTS_ATTRIBUTE });
+            }
+        } else {
+            epi = path.getExtendedPathIterator();
+            keyPoints = new float[count];
+            int j = 0;
+            for (int i = 0; i < count - 1; i++) {
+                while (epi.currentSegment() ==
+                        ExtendedPathIterator.SEG_MOVETO) {
+                    j++;
+                    epi.next();
+                }
+                keyPoints[i] = pathLength.getLengthAtSegment(j) / totalLength;
+                j++;
+                epi.next();
+            }
+            keyPoints[count - 1] = 1f;
+        }
+        this.keyPoints = keyPoints;
+    }
+
+    /**
+     * Called when the element is sampled at the given unit time.  This updates
+     * the {@link #value} of the animation if active.
+     */
+    protected void sampledAtUnitTime(float unitTime, int repeatIteration) {
+        AnimatableValue value, accumulation;
+        float interpolation = 0;
+        if (unitTime != 1) {
+            int keyTimeIndex = 0;
+            while (keyTimeIndex < keyTimes.length - 1
+                    && unitTime >= keyTimes[keyTimeIndex + 1]) {
+                keyTimeIndex++;
+            }
+            if (keyTimeIndex == keyTimes.length - 1 && calcMode == CALC_MODE_DISCRETE) {
+                keyTimeIndex = keyTimes.length - 2;
+                interpolation = 1;
+            } else {
+                if (calcMode == CALC_MODE_LINEAR || calcMode == CALC_MODE_PACED
+                        || calcMode == CALC_MODE_SPLINE) {
+                    if (unitTime == 0) {
+                        interpolation = 0;
+                    } else {
+                        interpolation = (unitTime - keyTimes[keyTimeIndex])
+                            / (keyTimes[keyTimeIndex + 1] - keyTimes[keyTimeIndex]);
+                    }
+                    if (calcMode == CALC_MODE_SPLINE && unitTime != 0) {
+                        // XXX This could be done better, e.g. with
+                        //     Newton-Raphson.
+                        Cubic c = keySplineCubics[keyTimeIndex];
+                        float tolerance = 0.001f;
+                        float min = 0;
+                        float max = 1;
+                        Point2D.Double p;
+                        for (;;) {
+                            float t = (min + max) / 2;
+                            p = c.eval(t);
+                            double x = p.getX();
+                            if (Math.abs(x - interpolation) < tolerance) {
+                                break;
+                            }
+                            if (x < interpolation) {
+                                min = t;
+                            } else {
+                                max = t;
+                            }
+                        }
+                        interpolation = (float) p.getY();
+                    }
+                }
+            }
+            float point = keyPoints[keyTimeIndex];
+            if (interpolation != 0) {
+                point += interpolation *
+                    (keyPoints[keyTimeIndex + 1] - keyPoints[keyTimeIndex]);
+            }
+            point *= pathLength.lengthOfPath();
+            Point2D p = pathLength.pointAtLength(point);
+            float ang;
+            if (rotateAuto) {
+                ang = pathLength.angleAtLength(point);
+                if (rotateAutoReverse) {
+                    ang += Math.PI;
+                }
+            } else {
+                ang = rotateAngle;
+            }
+            value = new AnimatableMotionPointValue(null, (float) p.getX(),
+                                                   (float) p.getY(), ang);
+        } else {
+            Point2D p = pathLength.pointAtLength(pathLength.lengthOfPath());
+            float ang;
+            if (rotateAuto) {
+                ang = pathLength.angleAtLength(pathLength.lengthOfPath());
+                if (rotateAutoReverse) {
+                    ang += Math.PI;
+                }
+            } else {
+                ang = rotateAngle;
+            }
+            value = new AnimatableMotionPointValue(null, (float) p.getX(),
+                                                   (float) p.getY(), ang);
+        }
+        if (cumulative) {
+            Point2D p = pathLength.pointAtLength(pathLength.lengthOfPath());
+            float ang;
+            if (rotateAuto) {
+                ang = pathLength.angleAtLength(pathLength.lengthOfPath());
+                if (rotateAutoReverse) {
+                    ang += Math.PI;
+                }
+            } else {
+                ang = rotateAngle;
+            }
+            accumulation = new AnimatableMotionPointValue(null, (float) p.getX(),
+                                                          (float) p.getY(), ang);
+        } else {
+            accumulation = null;
+        }
+
+        this.value = value.interpolate(this.value, null, interpolation,
+                                       accumulation, repeatIteration);
+        if (this.value.hasChanged()) {
+            markDirty();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/SetAnimation.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/SetAnimation.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/SetAnimation.java
new file mode 100644
index 0000000..b83d8e4
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/SetAnimation.java
@@ -0,0 +1,68 @@
+/*
+
+   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.anim;
+
+import org.apache.flex.forks.batik.anim.values.AnimatableValue;
+import org.apache.flex.forks.batik.anim.timing.TimedElement;
+import org.apache.flex.forks.batik.dom.anim.AnimatableElement;
+
+/**
+ * An animation class for 'set' animations.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: SetAnimation.java 475477 2006-11-15 22:44:28Z cam $
+ */
+public class SetAnimation extends AbstractAnimation {
+
+    /**
+     * The set animation value.
+     */
+    protected AnimatableValue to;
+
+    /**
+     * Creates a new SetAnimation.
+     */
+    public SetAnimation(TimedElement timedElement,
+                        AnimatableElement animatableElement,
+                        AnimatableValue to) {
+        super(timedElement, animatableElement);
+        this.to = to;
+    }
+
+    /**
+     * Called when the element is sampled at the given time.
+     */
+    protected void sampledAt(float simpleTime, float simpleDur,
+                             int repeatIteration) {
+        if (value == null) {
+            value = to;
+            markDirty();
+        }
+    }
+
+    /**
+     * Called when the element is sampled for its "last" value.
+     */
+    protected void sampledLastValue(int repeatIteration) {
+        if (value == null) {
+            value = to;
+            markDirty();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/SimpleAnimation.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/SimpleAnimation.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/SimpleAnimation.java
new file mode 100644
index 0000000..84ac35e
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/SimpleAnimation.java
@@ -0,0 +1,221 @@
+/*
+
+   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.anim;
+
+import java.awt.geom.Point2D;
+
+import org.apache.flex.forks.batik.anim.timing.TimedElement;
+import org.apache.flex.forks.batik.anim.values.AnimatableValue;
+import org.apache.flex.forks.batik.dom.anim.AnimatableElement;
+import org.apache.flex.forks.batik.ext.awt.geom.Cubic;
+import org.apache.flex.forks.batik.util.SMILConstants;
+
+/**
+ * An animation class for 'animate' animations.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: SimpleAnimation.java 492528 2007-01-04 11:45:47Z cam $
+ */
+public class SimpleAnimation extends InterpolatingAnimation {
+
+    /**
+     * Values between which to interpolate.
+     */
+    protected AnimatableValue[] values;
+
+    /**
+     * Starting value of the animation.
+     */
+    protected AnimatableValue from;
+
+    /**
+     * Ending value of the animation.
+     */
+    protected AnimatableValue to;
+
+    /**
+     * Relative offset value for the animation.
+     */
+    protected AnimatableValue by;
+
+    /**
+     * Creates a new SimpleAnimation.
+     */
+    public SimpleAnimation(TimedElement timedElement,
+                           AnimatableElement animatableElement,
+                           int calcMode,
+                           float[] keyTimes,
+                           float[] keySplines,
+                           boolean additive,
+                           boolean cumulative,
+                           AnimatableValue[] values,
+                           AnimatableValue from,
+                           AnimatableValue to,
+                           AnimatableValue by) {
+        super(timedElement, animatableElement, calcMode, keyTimes, keySplines,
+              additive, cumulative);
+        this.from = from;
+        this.to = to;
+        this.by = by;
+
+        if (values == null) {
+            if (from != null) {
+                values = new AnimatableValue[2];
+                values[0] = from;
+                if (to != null) {
+                    values[1] = to;
+                } else if (by != null) {
+                    values[1] = from.interpolate(null, null, 0f, by, 1); 
+                } else {
+                    throw timedElement.createException
+                        ("values.to.by.missing", new Object[] { null });
+                }
+            } else {
+                if (to != null) {
+                    values = new AnimatableValue[2];
+                    values[0] = animatableElement.getUnderlyingValue();
+                    values[1] = to;
+                    this.cumulative = false;
+                    toAnimation = true;
+                } else if (by != null) {
+                    this.additive = true;
+                    values = new AnimatableValue[2];
+                    values[0] = by.getZeroValue();
+                    values[1] = by;
+                } else {
+                    throw timedElement.createException
+                        ("values.to.by.missing", new Object[] { null });
+                }
+            }
+        }
+        this.values = values;
+
+        if (this.keyTimes != null && calcMode != CALC_MODE_PACED) {
+            if (this.keyTimes.length != values.length) {
+                throw timedElement.createException
+                    ("attribute.malformed",
+                     new Object[] { null,
+                                    SMILConstants.SMIL_KEY_TIMES_ATTRIBUTE });
+            }
+        } else {
+            if (calcMode == CALC_MODE_LINEAR || calcMode == CALC_MODE_SPLINE
+                    || calcMode == CALC_MODE_PACED && !values[0].canPace()) {
+                int count = values.length == 1 ? 2 : values.length;
+                this.keyTimes = new float[count];
+                for (int i = 0; i < count; i++) {
+                    this.keyTimes[i] = (float) i / (count - 1);
+                }
+            } else if (calcMode == CALC_MODE_DISCRETE) {
+                int count = values.length;
+                this.keyTimes = new float[count];
+                for (int i = 0; i < count; i++) {
+                    this.keyTimes[i] = (float) i / count;
+                }
+            } else { // CALC_MODE_PACED
+                // This corrects the keyTimes to be paced, so from now on
+                // it can be considered the same as CALC_MODE_LINEAR.
+                int count = values.length;
+                float[] cumulativeDistances = new float[count];
+                cumulativeDistances[0] = 0;
+                for (int i = 1; i < count; i++) {
+                    cumulativeDistances[i] = cumulativeDistances[i - 1]
+                        + values[i - 1].distanceTo(values[i]);
+                }
+                float totalLength = cumulativeDistances[count - 1];
+                this.keyTimes = new float[count];
+                this.keyTimes[0] = 0;
+                for (int i = 1; i < count - 1; i++) {
+                    this.keyTimes[i] = cumulativeDistances[i] / totalLength;
+                }
+                this.keyTimes[count - 1] = 1;
+            }
+        }
+
+        if (calcMode == CALC_MODE_SPLINE
+                && keySplines.length != (this.keyTimes.length - 1) * 4) {
+            throw timedElement.createException
+                ("attribute.malformed",
+                 new Object[] { null,
+                                SMILConstants.SMIL_KEY_SPLINES_ATTRIBUTE });
+        }
+    }
+
+    /**
+     * Called when the element is sampled at the given unit time.  This updates
+     * the {@link #value} of the animation if active.
+     */
+    protected void sampledAtUnitTime(float unitTime, int repeatIteration) {
+        AnimatableValue value, accumulation, nextValue;
+        float interpolation = 0;
+        if (unitTime != 1) {
+            int keyTimeIndex = 0;
+            while (keyTimeIndex < keyTimes.length - 1
+                    && unitTime >= keyTimes[keyTimeIndex + 1]) {
+                keyTimeIndex++;
+            }
+            value = values[keyTimeIndex];
+            if (calcMode == CALC_MODE_LINEAR
+                    || calcMode == CALC_MODE_PACED
+                    || calcMode == CALC_MODE_SPLINE) {
+                nextValue = values[keyTimeIndex + 1];
+                interpolation = (unitTime - keyTimes[keyTimeIndex])
+                    / (keyTimes[keyTimeIndex + 1] - keyTimes[keyTimeIndex]);
+                if (calcMode == CALC_MODE_SPLINE && unitTime != 0) {
+                    // XXX This could be done better, e.g. with
+                    //     Newton-Raphson.
+                    Cubic c = keySplineCubics[keyTimeIndex];
+                    float tolerance = 0.001f;
+                    float min = 0;
+                    float max = 1;
+                    Point2D.Double p;
+                    for (;;) {
+                        float t = (min + max) / 2;
+                        p = c.eval(t);
+                        double x = p.getX();
+                        if (Math.abs(x - interpolation) < tolerance) {
+                            break;
+                        }
+                        if (x < interpolation) {
+                            min = t;
+                        } else {
+                            max = t;
+                        }
+                    }
+                    interpolation = (float) p.getY();
+                }
+            } else {
+                nextValue = null;
+            }
+        } else {
+            value = values[values.length - 1];
+            nextValue = null;
+        }
+        if (cumulative) {
+            accumulation = values[values.length - 1];
+        } else {
+            accumulation = null;
+        }
+
+        this.value = value.interpolate(this.value, nextValue, interpolation,
+                                       accumulation, repeatIteration);
+        if (this.value.hasChanged()) {
+            markDirty();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/TransformAnimation.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/TransformAnimation.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/TransformAnimation.java
new file mode 100644
index 0000000..2e386cf
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/TransformAnimation.java
@@ -0,0 +1,251 @@
+/*
+
+   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.anim;
+
+import org.apache.flex.forks.batik.anim.timing.TimedElement;
+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.anim.AnimatableElement;
+
+import org.w3c.dom.svg.SVGTransform;
+
+/**
+ * An animation class for 'animateTransform' animations.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: TransformAnimation.java 492528 2007-01-04 11:45:47Z cam $
+ */
+public class TransformAnimation extends SimpleAnimation {
+
+    /**
+     * The transform type.  This should take one of the constants defined
+     * in {@link org.w3c.dom.svg.SVGTransform}.
+     */
+    protected short type;
+
+    /**
+     * Time values to control the pacing of the second component of the
+     * animation.
+     */
+    protected float[] keyTimes2;
+
+    /**
+     * Time values to control the pacing of the third component of the
+     * animation.
+     */
+    protected float[] keyTimes3;
+
+    /**
+     * Creates a new TransformAnimation.
+     */
+    public TransformAnimation(TimedElement timedElement,
+                              AnimatableElement animatableElement,
+                              int calcMode,
+                              float[] keyTimes,
+                              float[] keySplines,
+                              boolean additive,
+                              boolean cumulative,
+                              AnimatableValue[] values,
+                              AnimatableValue from,
+                              AnimatableValue to,
+                              AnimatableValue by,
+                              short type) {
+        // pretend we didn't get a calcMode="paced", since we need specialised
+        // behaviour in sampledAtUnitTime.
+        super(timedElement, animatableElement,
+              calcMode == CALC_MODE_PACED ? CALC_MODE_LINEAR : calcMode,
+              calcMode == CALC_MODE_PACED ? null : keyTimes,
+              keySplines, additive, cumulative, values, from, to, by);
+        this.calcMode = calcMode;
+        this.type = type;
+
+        if (calcMode != CALC_MODE_PACED) {
+            return;
+        }
+
+        // Determine the equivalent keyTimes for the individual components
+        // of the transforms for CALC_MODE_PACED.
+        int count = this.values.length;
+        float[] cumulativeDistances1;
+        float[] cumulativeDistances2 = null;
+        float[] cumulativeDistances3 = null;
+        switch (type) {
+            case SVGTransform.SVG_TRANSFORM_ROTATE:
+                cumulativeDistances3 = new float[count];
+                cumulativeDistances3[0] = 0f;
+                // fall through
+            case SVGTransform.SVG_TRANSFORM_SCALE:
+            case SVGTransform.SVG_TRANSFORM_TRANSLATE:
+                cumulativeDistances2 = new float[count];
+                cumulativeDistances2[0] = 0f;
+                // fall through
+            default:
+                cumulativeDistances1 = new float[count];
+                cumulativeDistances1[0] = 0f;
+        }
+
+        for (int i = 1; i < this.values.length; i++) {
+            switch (type) {
+                case SVGTransform.SVG_TRANSFORM_ROTATE:
+                    cumulativeDistances3[i] =
+                        cumulativeDistances3[i - 1]
+                            + ((AnimatableTransformListValue)
+                                this.values[i - 1]).distanceTo3(this.values[i]);
+                    // fall through
+                case SVGTransform.SVG_TRANSFORM_SCALE:
+                case SVGTransform.SVG_TRANSFORM_TRANSLATE:
+                    cumulativeDistances2[i] =
+                        cumulativeDistances2[i - 1]
+                            + ((AnimatableTransformListValue)
+                                this.values[i - 1]).distanceTo2(this.values[i]);
+                    // fall through
+                default:
+                    cumulativeDistances1[i] =
+                        cumulativeDistances1[i - 1]
+                            + ((AnimatableTransformListValue)
+                                this.values[i - 1]).distanceTo1(this.values[i]);
+            }
+        }
+
+        switch (type) {
+            case SVGTransform.SVG_TRANSFORM_ROTATE:
+                float totalLength = cumulativeDistances3[count - 1];
+                keyTimes3 = new float[count];
+                keyTimes3[0] = 0f;
+                for (int i = 1; i < count - 1; i++) {
+                    keyTimes3[i] = cumulativeDistances3[i] / totalLength;
+                }
+                keyTimes3[count - 1] = 1f;
+                // fall through
+            case SVGTransform.SVG_TRANSFORM_SCALE:
+            case SVGTransform.SVG_TRANSFORM_TRANSLATE:
+                totalLength = cumulativeDistances2[count - 1];
+                keyTimes2 = new float[count];
+                keyTimes2[0] = 0f;
+                for (int i = 1; i < count - 1; i++) {
+                    keyTimes2[i] = cumulativeDistances2[i] / totalLength;
+                }
+                keyTimes2[count - 1] = 1f;
+                // fall through
+            default:
+                totalLength = cumulativeDistances1[count - 1];
+                this.keyTimes = new float[count];
+                this.keyTimes[0] = 0f;
+                for (int i = 1; i < count - 1; i++) {
+                    this.keyTimes[i] = cumulativeDistances1[i] / totalLength;
+                }
+                this.keyTimes[count - 1] = 1f;
+        }
+    }
+
+    /**
+     * Called when the element is sampled at the given unit time.  This updates
+     * the {@link #value} of the animation if active.
+     */
+    protected void sampledAtUnitTime(float unitTime, int repeatIteration) {
+        // Note that skews are handled by SimpleAnimation and not here, since
+        // they need just the one component of interpolation.
+        if (calcMode != CALC_MODE_PACED
+                || type == SVGTransform.SVG_TRANSFORM_SKEWX
+                || type == SVGTransform.SVG_TRANSFORM_SKEWY) {
+            super.sampledAtUnitTime(unitTime, repeatIteration);
+            return;
+        }
+
+        AnimatableTransformListValue
+            value1, value2, value3 = null, nextValue1, nextValue2,
+            nextValue3 = null, accumulation;
+        float interpolation1 = 0f, interpolation2 = 0f, interpolation3 = 0f;
+        if (unitTime != 1) {
+            switch (type) {
+                case SVGTransform.SVG_TRANSFORM_ROTATE:
+                    int keyTimeIndex = 0;
+                    while (keyTimeIndex < keyTimes3.length - 1
+                            && unitTime >= keyTimes3[keyTimeIndex + 1]) {
+                        keyTimeIndex++;
+                    }
+                    value3 = (AnimatableTransformListValue)
+                        this.values[keyTimeIndex];
+                    nextValue3 = (AnimatableTransformListValue)
+                        this.values[keyTimeIndex + 1];
+                    interpolation3 = (unitTime - keyTimes3[keyTimeIndex])
+                        / (keyTimes3[keyTimeIndex + 1] -
+                                keyTimes3[keyTimeIndex]);
+                    // fall through
+                default:
+                    keyTimeIndex = 0;
+                    while (keyTimeIndex < keyTimes2.length - 1
+                            && unitTime >= keyTimes2[keyTimeIndex + 1]) {
+                        keyTimeIndex++;
+                    }
+                    value2 = (AnimatableTransformListValue)
+                        this.values[keyTimeIndex];
+                    nextValue2 = (AnimatableTransformListValue)
+                        this.values[keyTimeIndex + 1];
+                    interpolation2 = (unitTime - keyTimes2[keyTimeIndex])
+                        / (keyTimes2[keyTimeIndex + 1] -
+                                keyTimes2[keyTimeIndex]);
+
+                    keyTimeIndex = 0;
+                    while (keyTimeIndex < keyTimes.length - 1
+                            && unitTime >= keyTimes[keyTimeIndex + 1]) {
+                        keyTimeIndex++;
+                    }
+                    value1 = (AnimatableTransformListValue)
+                        this.values[keyTimeIndex];
+                    nextValue1 = (AnimatableTransformListValue)
+                        this.values[keyTimeIndex + 1];
+                    interpolation1 = (unitTime - keyTimes[keyTimeIndex])
+                        / (keyTimes[keyTimeIndex + 1] -
+                                keyTimes[keyTimeIndex]);
+            }
+        } else {
+            value1 = value2 = value3 = (AnimatableTransformListValue)
+                this.values[this.values.length - 1];
+            nextValue1 = nextValue2 = nextValue3 = null;
+            interpolation1 = interpolation2 = interpolation3 = 1f;
+        }
+        if (cumulative) {
+            accumulation = (AnimatableTransformListValue)
+                this.values[this.values.length - 1];
+        } else {
+            accumulation = null;
+        }
+
+        switch (type) {
+            case SVGTransform.SVG_TRANSFORM_ROTATE:
+                this.value = AnimatableTransformListValue.interpolate
+                    ((AnimatableTransformListValue) this.value, value1, value2,
+                     value3, nextValue1, nextValue2, nextValue3, interpolation1,
+                     interpolation2, interpolation3, accumulation,
+                     repeatIteration);
+                break;
+            default:
+                this.value = AnimatableTransformListValue.interpolate
+                    ((AnimatableTransformListValue) this.value, value1, value2,
+                     nextValue1, nextValue2, interpolation1, interpolation2,
+                     accumulation, repeatIteration);
+                break;
+        }
+
+        if (this.value.hasChanged()) {
+            markDirty();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/AccesskeyTimingSpecifier.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/AccesskeyTimingSpecifier.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/AccesskeyTimingSpecifier.java
new file mode 100644
index 0000000..0f01f8c
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/AccesskeyTimingSpecifier.java
@@ -0,0 +1,149 @@
+/*
+
+   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.anim.timing;
+
+import org.apache.flex.forks.batik.dom.events.DOMKeyEvent;
+import org.apache.flex.forks.batik.dom.events.NodeEventTarget;
+import org.apache.flex.forks.batik.util.XMLConstants;
+
+import org.w3c.dom.events.Event;
+import org.w3c.dom.events.EventListener;
+import org.w3c.dom.events.EventTarget;
+import org.w3c.dom.events.KeyboardEvent;
+
+/**
+ * A class to handle SMIL access key timing specifiers.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: AccesskeyTimingSpecifier.java 580338 2007-09-28 13:13:46Z cam $
+ */
+public class AccesskeyTimingSpecifier
+        extends EventLikeTimingSpecifier
+        implements EventListener {
+
+    /**
+     * The accesskey.
+     */
+    protected char accesskey;
+
+    /**
+     * Whether this access key specifier uses SVG 1.2 syntax.
+     */
+    protected boolean isSVG12AccessKey;
+
+    /**
+     * The DOM 3 key name for SVG 1.2 access key specifiers.
+     */
+    protected String keyName;
+
+    /**
+     * Creates a new AccesskeyTimingSpecifier object using SVG 1.1
+     * or SMIL syntax.
+     */
+    public AccesskeyTimingSpecifier(TimedElement owner, boolean isBegin,
+                                    float offset, char accesskey) {
+        super(owner, isBegin, offset);
+        this.accesskey = accesskey;
+    }
+    
+    /**
+     * Creates a new AccesskeyTimingSpecifier object using SVG 1.2 syntax.
+     */
+    public AccesskeyTimingSpecifier(TimedElement owner, boolean isBegin,
+                                    float offset, String keyName) {
+        super(owner, isBegin, offset);
+        this.isSVG12AccessKey = true;
+        this.keyName = keyName;
+    }
+
+    /**
+     * Returns a string representation of this timing specifier.
+     */
+    public String toString() {
+        if (isSVG12AccessKey) {
+            return "accessKey(" + keyName + ")"
+                + (offset != 0 ? super.toString() : "");
+        }
+        return "accesskey(" + accesskey + ")"
+            + (offset != 0 ? super.toString() : "");
+    }
+
+    /**
+     * Initializes this timing specifier by adding the initial instance time
+     * to the owner's instance time list or setting up any event listeners.
+     */
+    public void initialize() {
+        if (isSVG12AccessKey) {
+            NodeEventTarget eventTarget =
+                (NodeEventTarget) owner.getRootEventTarget();
+            eventTarget.addEventListenerNS
+                (XMLConstants.XML_EVENTS_NAMESPACE_URI, "keydown",
+                 this, false, null);
+        } else {
+            EventTarget eventTarget = owner.getRootEventTarget();
+            eventTarget.addEventListener("keypress", this, false);
+        }
+    }
+
+    /**
+     * Deinitializes this timing specifier by removing any event listeners.
+     */
+    public void deinitialize() {
+        if (isSVG12AccessKey) {
+            NodeEventTarget eventTarget =
+                (NodeEventTarget) owner.getRootEventTarget();
+            eventTarget.removeEventListenerNS
+                (XMLConstants.XML_EVENTS_NAMESPACE_URI, "keydown",
+                 this, false);
+        } else {
+            EventTarget eventTarget = owner.getRootEventTarget();
+            eventTarget.removeEventListener("keypress", this, false);
+        }
+    }
+
+    // EventListener /////////////////////////////////////////////////////////
+
+    /**
+     * Handles key events fired by the eventbase element.
+     */
+    public void handleEvent(Event e) {
+        boolean matched;
+        if (e.getType().charAt(3) == 'p') {
+            // DOM 2 key draft keypress
+            DOMKeyEvent evt = (DOMKeyEvent) e;
+            matched = evt.getCharCode() == accesskey;
+        } else {
+            // DOM 3 keydown
+            KeyboardEvent evt = (KeyboardEvent) e;
+            matched = evt.getKeyIdentifier().equals(keyName);
+        }
+        if (matched) {
+            owner.eventOccurred(this, e);
+        }
+    }
+
+    /**
+     * Invoked to resolve an event-like timing specifier into an instance time.
+     */
+    public void resolve(Event e) {
+        float time = owner.getRoot().convertEpochTime(e.getTimeStamp());
+        InstanceTime instance = new InstanceTime(this, time + offset, true);
+        owner.addInstanceTime(instance, isBegin);
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/EventLikeTimingSpecifier.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/EventLikeTimingSpecifier.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/EventLikeTimingSpecifier.java
new file mode 100644
index 0000000..5b26251
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/EventLikeTimingSpecifier.java
@@ -0,0 +1,51 @@
+/*
+
+   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.anim.timing;
+
+import org.w3c.dom.events.Event;
+
+/**
+ * Abstract class from which all event-like timing specifier classes derive.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: EventLikeTimingSpecifier.java 475477 2006-11-15 22:44:28Z cam $
+ */
+public abstract class EventLikeTimingSpecifier extends OffsetTimingSpecifier {
+
+    /**
+     * Creates a new EventLikeTimingSpecifier object.
+     */
+    public EventLikeTimingSpecifier(TimedElement owner, boolean isBegin,
+                                    float offset) {
+        super(owner, isBegin, offset);
+    }
+
+    /**
+     * Returns whether this timing specifier is event-like (i.e., if it is
+     * an eventbase, accesskey or a repeat timing specifier).
+     */
+    public boolean isEventCondition() {
+        return true;
+    }
+
+    /**
+     * Invoked to resolve an event-like timing specifier into an instance time.
+     */
+    public abstract void resolve(Event e);
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/EventbaseTimingSpecifier.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/EventbaseTimingSpecifier.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/EventbaseTimingSpecifier.java
new file mode 100644
index 0000000..c34ee0f
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/EventbaseTimingSpecifier.java
@@ -0,0 +1,128 @@
+/*
+
+   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.anim.timing;
+
+import org.apache.flex.forks.batik.dom.events.NodeEventTarget;
+
+import org.w3c.dom.events.Event;
+import org.w3c.dom.events.EventListener;
+import org.w3c.dom.events.EventTarget;
+
+/**
+ * A class to handle eventbase SMIL timing specifiers.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: EventbaseTimingSpecifier.java 580338 2007-09-28 13:13:46Z cam $
+ */
+public class EventbaseTimingSpecifier
+        extends EventLikeTimingSpecifier
+        implements EventListener {
+
+    /**
+     * The ID of the eventbase element.
+     */
+    protected String eventbaseID;
+
+    /**
+     * The eventbase element.
+     */
+    protected TimedElement eventbase;
+
+    /**
+     * The eventbase element as an {@link EventTarget}.
+     */
+    protected EventTarget eventTarget;
+
+    /**
+     * The namespace URI of the event to sync to.
+     */
+    protected String eventNamespaceURI;
+
+    /**
+     * The type of the event to sync to.
+     */
+    protected String eventType;
+
+    /**
+     * The animation name of the event to sync to.
+     */
+    protected String eventName;
+
+    /**
+     * Creates a new EventbaseTimingSpecifier object.
+     */
+    public EventbaseTimingSpecifier(TimedElement owner, boolean isBegin,
+                                    float offset, String eventbaseID,
+                                    String eventName) {
+        super(owner, isBegin, offset);
+        this.eventbaseID = eventbaseID;
+        this.eventName = eventName;
+        TimedDocumentRoot root = owner.getRoot();
+        this.eventNamespaceURI = root.getEventNamespaceURI(eventName);
+        this.eventType = root.getEventType(eventName);
+        if (eventbaseID == null) {
+            this.eventTarget = owner.getAnimationEventTarget();
+        } else {
+            this.eventTarget = owner.getEventTargetById(eventbaseID);
+        }
+    }
+
+    /**
+     * Returns a string representation of this timing specifier.
+     */
+    public String toString() {
+        return (eventbaseID == null ? "" : eventbaseID + ".") + eventName
+            + (offset != 0 ? super.toString() : "");
+    }
+
+    /**
+     * Initializes this timing specifier by adding the initial instance time
+     * to the owner's instance time list or setting up any event listeners.
+     */
+    public void initialize() {
+        ((NodeEventTarget) eventTarget).addEventListenerNS
+            (eventNamespaceURI, eventType, this, false, null);
+    }
+
+    /**
+     * Deinitializes this timing specifier by removing any event listeners.
+     */
+    public void deinitialize() {
+        ((NodeEventTarget) eventTarget).removeEventListenerNS
+            (eventNamespaceURI, eventType, this, false);
+    }
+
+    // EventListener /////////////////////////////////////////////////////////
+
+    /**
+     * Handles an event fired on the eventbase element.
+     */
+    public void handleEvent(Event e) {
+        owner.eventOccurred(this, e);
+    }
+
+    /**
+     * Invoked to resolve an event-like timing specifier into an instance time.
+     */
+    public void resolve(Event e) {
+        float time = owner.getRoot().convertEpochTime(e.getTimeStamp());
+        InstanceTime instance = new InstanceTime(this, time + offset, true);
+        owner.addInstanceTime(instance, isBegin);
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/IndefiniteTimingSpecifier.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/IndefiniteTimingSpecifier.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/IndefiniteTimingSpecifier.java
new file mode 100644
index 0000000..2b11a06
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/IndefiniteTimingSpecifier.java
@@ -0,0 +1,64 @@
+/*
+
+   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.anim.timing;
+
+/**
+ * A class to handle the 'indefinite' SMIL timing specifier.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: IndefiniteTimingSpecifier.java 580338 2007-09-28 13:13:46Z cam $
+ */
+public class IndefiniteTimingSpecifier extends TimingSpecifier {
+
+    /**
+     * Creates a new IndefiniteTimingSpecifier object.
+     */
+    public IndefiniteTimingSpecifier(TimedElement owner, boolean isBegin) {
+        super(owner, isBegin);
+    }
+    
+    /**
+     * Returns a string representation of this timing specifier.
+     */
+    public String toString() {
+        return "indefinite";
+    }
+
+    /**
+     * Initializes this timing specifier by adding the initial instance time
+     * to the owner's instance time list or setting up any event listeners.
+     */
+    public void initialize() {
+        if (!isBegin) {
+            // Only end instance lists get an 'indefinite' instance time from
+            // an indefinite timing specifier.
+            InstanceTime instance =
+                new InstanceTime(this, TimedElement.INDEFINITE, false);
+            owner.addInstanceTime(instance, isBegin);
+        }
+    }
+
+    /**
+     * Returns whether this timing specifier is event-like (i.e., if it is
+     * an eventbase, accesskey or a repeat timing specifier).
+     */
+    public boolean isEventCondition() {
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/InstanceTime.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/InstanceTime.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/InstanceTime.java
new file mode 100644
index 0000000..b160381
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/InstanceTime.java
@@ -0,0 +1,117 @@
+/*
+
+   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.anim.timing;
+
+/**
+ * A class that represents an instance time created from a timing
+ * specification.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: InstanceTime.java 580338 2007-09-28 13:13:46Z cam $
+ */
+public class InstanceTime implements Comparable {
+
+    /**
+     * The time.
+     */
+    protected float time;
+
+    /**
+     * The {@link TimingSpecifier} that created this InstanceTime.
+     */
+    protected TimingSpecifier creator;
+
+    /**
+     * Whether this InstanceTime should be removed from an element's
+     * begin or end instance time lists upon reset.
+     */
+    protected boolean clearOnReset;
+
+    /**
+     * Creates a new InstanceTime.
+     * @param creator the TimingSpecifier that created this InstanceTime
+     * @param time the new time, in parent simple time
+     * @param clearOnReset whether this InstanceTime should be removed from
+     *                     an instance time list upon element reset
+     */
+    public InstanceTime(TimingSpecifier creator,
+                        float time,
+                        boolean clearOnReset) {
+        // Trace.enter(this, null, new Object[] { creator, new Float(time), timebase, new Boolean(clearOnReset) } ); try {
+        this.creator = creator;
+        // XXX Convert time from the creator's syncbase's
+        //     time system into this time system.  Not
+        //     strictly necessary in SVG.
+        this.time = time;
+        this.clearOnReset = clearOnReset;
+        // } finally { Trace.exit(); }
+    }
+
+    /**
+     * Returns whether the InstanceTime should be removed from the
+     * element's begin or end instance time list when it is reset.
+     */
+    public boolean getClearOnReset() {
+        return clearOnReset;
+    }
+
+    /**
+     * Returns the time of this instance time.
+     */
+    public float getTime() {
+        return time;
+    }
+
+    /**
+     * Called by the dependent Interval to indicate that its time
+     * has changed.
+     * @param newTime the new time, in parent simple time
+     */
+    float dependentUpdate(float newTime) {
+        // Trace.enter(this, "dependentUpdate", new Object[] { new Float(newTime) } ); try {
+        // XXX Convert time from the creator's syncbase's
+        //     time system into this time system.  Not
+        //     strictly necessary in SVG.
+        time = newTime;
+        if (creator != null) {
+            return creator.handleTimebaseUpdate(this, time);
+        }
+        return Float.POSITIVE_INFINITY;
+        // } finally { Trace.exit(); }
+    }
+
+    /**
+     * Returns a string representation of this InstanceTime.
+     */
+    public String toString() {
+        return Float.toString(time);
+    }
+
+    // Comparable ////////////////////////////////////////////////////////////
+
+    /**
+     * Compares this InstanceTime with another.
+     */
+    public int compareTo(Object o) {
+        InstanceTime it = (InstanceTime)o;
+        if (time == it.time) return 0;
+        if (time >  it.time) return 1;
+        return -1;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/Interval.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/Interval.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/Interval.java
new file mode 100644
index 0000000..3551947
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/Interval.java
@@ -0,0 +1,184 @@
+/*
+
+   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.anim.timing;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+/**
+ * A class that represents an interval for a timed element.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: Interval.java 492528 2007-01-04 11:45:47Z cam $
+ */
+public class Interval {
+
+    /**
+     * The begin time for the interval.
+     */
+    protected float begin;
+
+    /**
+     * The end time for the interval.
+     */
+    protected float end;
+
+    /**
+     * The InstanceTime that defined the begin time of the current interval.
+     */
+    protected InstanceTime beginInstanceTime;
+
+    /**
+     * The InstanceTime that defined the end time of the current interval.
+     */
+    protected InstanceTime endInstanceTime;
+
+    /**
+     * The list of {@link InstanceTime} objects that are dependent
+     * on the begin time of this Interval.
+     */
+    protected LinkedList beginDependents = new LinkedList();
+
+    /**
+     * The list of {@link InstanceTime} objects that are dependent
+     * on the end time of this Interval.
+     */
+    protected LinkedList endDependents = new LinkedList();
+
+    /**
+     * Creates a new Interval.
+     * @param begin the begin time of the Interval
+     * @param end the end time of the Interval
+     * @param beginInstanceTime the {@link InstanceTime} object that defined
+     *        the begin time of the Interval
+     * @param endInstanceTime the {@link InstanceTime} object that defined
+     *        the end time of the Interval
+     */
+    public Interval(float begin, float end, InstanceTime beginInstanceTime,
+                    InstanceTime endInstanceTime) {
+        // Trace.enter(this, null, new Object[] { new Float(begin), new Float(end), beginInstanceTime, endInstanceTime } ); try {
+        this.begin = begin;
+        this.end = end;
+        this.beginInstanceTime = beginInstanceTime;
+        this.endInstanceTime = endInstanceTime;
+        // } finally { Trace.exit(); }
+    }
+
+    /**
+     * Returns a string representation of this Interval.
+     */
+    public String toString() {
+        return TimedElement.toString(begin) + ".." + TimedElement.toString(end);
+    }
+
+    /**
+     * Returns the begin time of this interval.
+     */
+    public float getBegin() {
+        return begin;
+    }
+
+    /**
+     * Returns the end time of this interval.
+     */
+    public float getEnd() {
+        return end;
+    }
+
+    /**
+     * Returns the {@link InstanceTime} that defined the begin time of this
+     * interval.
+     */
+    public InstanceTime getBeginInstanceTime() {
+        return beginInstanceTime;
+    }
+
+    /**
+     * Returns the {@link InstanceTime} that defined the end time of this
+     * interval.
+     */
+    public InstanceTime getEndInstanceTime() {
+        return endInstanceTime;
+    }
+
+    /**
+     * Adds a dependent InstanceTime for this Interval.
+     */
+    void addDependent(InstanceTime dependent, boolean forBegin) {
+        // Trace.enter(this, "addDependent", new Object[] { dependent, new Boolean(forBegin) } ); try {
+        if (forBegin) {
+            beginDependents.add(dependent);
+        } else {
+            endDependents.add(dependent);
+        }
+        // } finally { Trace.exit(); }
+    }
+
+    /**
+     * Removes a dependent InstanceTime for this Interval.
+     */
+    void removeDependent(InstanceTime dependent, boolean forBegin) {
+        // Trace.enter(this, "removeDependent", new Object[] { dependent, new Boolean(forBegin) } ); try {
+        if (forBegin) {
+            beginDependents.remove(dependent);
+        } else {
+            endDependents.remove(dependent);
+        }
+        // } finally { Trace.exit(); }
+    }
+
+    /**
+     * Updates the begin time for this interval.
+     */
+    float setBegin(float begin) {
+        // Trace.enter(this, "setBegin", new Object[] { new Float(begin) } ); try {
+        float minTime = Float.POSITIVE_INFINITY;
+        this.begin = begin;
+        Iterator i = beginDependents.iterator();
+        while (i.hasNext()) {
+            InstanceTime it = (InstanceTime) i.next();
+            float t = it.dependentUpdate(begin);
+            if (t < minTime) {
+                minTime = t;
+            }
+        }
+        return minTime;
+        // } finally { Trace.exit(); }
+    }
+
+    /**
+     * Updates the end time for this interval.
+     */
+    float setEnd(float end, InstanceTime endInstanceTime) {
+        // Trace.enter(this, "setEnd", new Object[] { new Float(end) } ); try {
+        float minTime = Float.POSITIVE_INFINITY;
+        this.end = end;
+        this.endInstanceTime = endInstanceTime;
+        Iterator i = endDependents.iterator();
+        while (i.hasNext()) {
+            InstanceTime it = (InstanceTime) i.next();
+            float t = it.dependentUpdate(end);
+            if (t < minTime) {
+                minTime = t;
+            }
+        }
+        return minTime;
+        // } finally { Trace.exit(); }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/MediaMarkerTimingSpecifier.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/MediaMarkerTimingSpecifier.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/MediaMarkerTimingSpecifier.java
new file mode 100644
index 0000000..86b3be4
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/MediaMarkerTimingSpecifier.java
@@ -0,0 +1,75 @@
+/*
+
+   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.anim.timing;
+
+/**
+ * A class to handle media marker SMIL timing specifiers.  This class
+ * of timing specifier is currently unused.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: MediaMarkerTimingSpecifier.java 475477 2006-11-15 22:44:28Z cam $
+ */
+public class MediaMarkerTimingSpecifier extends TimingSpecifier {
+
+    /**
+     * The ID of the media element.
+     */
+    protected String syncbaseID;
+
+    /**
+     * The media element.
+     */
+    protected TimedElement mediaElement;
+
+    /**
+     * The media marker name.
+     */
+    protected String markerName;
+
+    /**
+     * The instance time.
+     */
+    protected InstanceTime instance;
+
+    /**
+     * Creates a new MediaMarkerTimingSpecifier object.
+     */
+    public MediaMarkerTimingSpecifier(TimedElement owner, boolean isBegin,
+                                      String syncbaseID, String markerName) {
+        super(owner, isBegin);
+        this.syncbaseID = syncbaseID;
+        this.markerName = markerName;
+        this.mediaElement = owner.getTimedElementById(syncbaseID);
+    }
+    
+    /**
+     * Returns a string representation of this timing specifier.
+     */
+    public String toString() {
+        return syncbaseID + ".marker(" + markerName + ")";
+    }
+
+    /**
+     * Returns whether this timing specifier is event-like (i.e., if it is
+     * an eventbase, accesskey or a repeat timing specifier).
+     */
+    public boolean isEventCondition() {
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/OffsetTimingSpecifier.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/OffsetTimingSpecifier.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/OffsetTimingSpecifier.java
new file mode 100644
index 0000000..cd12e7f
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/OffsetTimingSpecifier.java
@@ -0,0 +1,66 @@
+/*
+
+   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.anim.timing;
+
+/**
+ * A class to handle offset SMIL timing specifiers.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: OffsetTimingSpecifier.java 580338 2007-09-28 13:13:46Z cam $
+ */
+public class OffsetTimingSpecifier extends TimingSpecifier {
+
+    /**
+     * The offset value.
+     */
+    protected float offset;
+
+    /**
+     * Creates a new OffsetTimingSpecifier object.
+     */
+    public OffsetTimingSpecifier(TimedElement owner, boolean isBegin,
+                                 float offset) {
+        super(owner, isBegin);
+        this.offset = offset;
+    }
+    
+    /**
+     * Returns a string representation of this timing specifier.
+     */
+    public String toString() {
+        return (offset >= 0 ? "+" : "") + offset;
+    }
+
+    /**
+     * Initializes this timing specifier by adding the initial instance time
+     * to the owner's instance time list or setting up any event listeners.
+     */
+    public void initialize() {
+        InstanceTime instance = new InstanceTime(this, offset, false);
+        owner.addInstanceTime(instance, isBegin);
+    }
+
+    /**
+     * Returns whether this timing specifier is event-like (i.e., if it is
+     * an eventbase, accesskey or a repeat timing specifier).
+     */
+    public boolean isEventCondition() {
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/RepeatTimingSpecifier.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/RepeatTimingSpecifier.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/RepeatTimingSpecifier.java
new file mode 100644
index 0000000..65d0610
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/RepeatTimingSpecifier.java
@@ -0,0 +1,83 @@
+/*
+
+   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.anim.timing;
+
+import org.w3c.dom.events.Event;
+import org.w3c.dom.smil.TimeEvent;
+
+/**
+ * A class to handle repeat event SMIL timing specifiers.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: RepeatTimingSpecifier.java 475477 2006-11-15 22:44:28Z cam $
+ */
+public class RepeatTimingSpecifier extends EventbaseTimingSpecifier {
+
+    /**
+     * The repeat iteration.
+     */
+    protected int repeatIteration;
+
+    /**
+     * Whether a repeat iteration was specified.
+     */
+    protected boolean repeatIterationSpecified;
+
+    /**
+     * Creates a new RepeatTimingSpecifier object without a repeat iteration.
+     */
+    public RepeatTimingSpecifier(TimedElement owner, boolean isBegin,
+                                 float offset, String syncbaseID) {
+        super(owner, isBegin, offset, syncbaseID,
+              owner.getRoot().getRepeatEventName());
+    }
+
+    /**
+     * Creates a new RepeatTimingSpecifier object with a repeat iteration.
+     */
+    public RepeatTimingSpecifier(TimedElement owner, boolean isBegin,
+                                 float offset, String syncbaseID,
+                                 int repeatIteration) {
+        super(owner, isBegin, offset, syncbaseID,
+              owner.getRoot().getRepeatEventName());
+        this.repeatIteration = repeatIteration;
+        this.repeatIterationSpecified = true;
+    }
+    
+    /**
+     * Returns a string representation of this timing specifier.
+     */
+    public String toString() {
+        return (eventbaseID == null ? "" : eventbaseID + ".") + "repeat"
+            + (repeatIterationSpecified ? "(" + repeatIteration + ")" : "")
+            + (offset != 0 ? super.toString() : "");
+    }
+
+    // EventListener /////////////////////////////////////////////////////////
+
+    /**
+     * Handles an event fired on the eventbase element.
+     */
+    public void handleEvent(Event e) {
+        TimeEvent evt = (TimeEvent) e;
+        if (!repeatIterationSpecified || evt.getDetail() == repeatIteration) {
+            super.handleEvent(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/SyncbaseTimingSpecifier.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/SyncbaseTimingSpecifier.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/SyncbaseTimingSpecifier.java
new file mode 100644
index 0000000..b857ba8
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/SyncbaseTimingSpecifier.java
@@ -0,0 +1,136 @@
+/*
+
+   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.anim.timing;
+
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+
+/**
+ * A class to handle syncbase SMIL timing specifiers.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: SyncbaseTimingSpecifier.java 580338 2007-09-28 13:13:46Z cam $
+ */
+public class SyncbaseTimingSpecifier extends OffsetTimingSpecifier {
+
+    /**
+     * The ID of the syncbase element.
+     */
+    protected String syncbaseID;
+
+    /**
+     * The syncbase element.
+     */
+    protected TimedElement syncbaseElement;
+
+    /**
+     * Whether this specifier specifies a sync to the begin or the end
+     * of the syncbase element.
+     */
+    protected boolean syncBegin;
+
+    /**
+     * Map of {@link Interval}s to <!--a {@link WeakReference} to -->an
+     * {@link InstanceTime}.
+     */
+    protected HashMap instances = new HashMap();
+
+    /**
+     * Creates a new SyncbaseTimingSpecifier object.
+     */
+    public SyncbaseTimingSpecifier(TimedElement owner, boolean isBegin,
+                                   float offset, String syncbaseID,
+                                   boolean syncBegin) {
+        super(owner, isBegin, offset);
+        // Trace.enter(this, null, new Object[] { owner, new Boolean(isBegin), new Float(offset), syncbaseID, new Boolean(syncBegin) } ); try {
+        this.syncbaseID = syncbaseID;
+        this.syncBegin = syncBegin;
+        this.syncbaseElement = owner.getTimedElementById(syncbaseID);
+        syncbaseElement.addDependent(this, syncBegin);
+        // } finally { Trace.exit(); }
+    }
+
+    /**
+     * Returns a string representation of this timing specifier.
+     */
+    public String toString() {
+        return syncbaseID + "." + (syncBegin ? "begin" : "end")
+            + (offset != 0 ? super.toString() : "");
+    }
+
+    /**
+     * Initializes this timing specifier by adding the initial instance time
+     * to the owner's instance time list or setting up any event listeners.
+     */
+    public void initialize() {
+    }
+
+    /**
+     * Returns whether this timing specifier is event-like (i.e., if it is
+     * an eventbase, accesskey or a repeat timing specifier).
+     */
+    public boolean isEventCondition() {
+        return false;
+    }
+
+    /**
+     * Called by the timebase element when it creates a new Interval.
+     */
+    float newInterval(Interval interval) {
+        // Trace.enter(this, "newInterval", new Object[] { interval } ); try {
+        if (owner.hasPropagated) {
+            return Float.POSITIVE_INFINITY;
+        }
+        InstanceTime instance =
+            new InstanceTime(this, (syncBegin ? interval.getBegin()
+                                              : interval.getEnd()) + offset,
+                             true);
+        instances.put(interval, instance);
+        interval.addDependent(instance, syncBegin);
+        return owner.addInstanceTime(instance, isBegin);
+        // } finally { Trace.exit(); }
+    }
+
+    /**
+     * Called by the timebase element when it deletes an Interval.
+     */
+    float removeInterval(Interval interval) {
+        // Trace.enter(this, "removeInterval", new Object[] { interval } ); try {
+        if (owner.hasPropagated) {
+            return Float.POSITIVE_INFINITY;
+        }
+        InstanceTime instance = (InstanceTime) instances.get(interval);
+        interval.removeDependent(instance, syncBegin);
+        return owner.removeInstanceTime(instance, isBegin);
+        // } finally { Trace.exit(); }
+    }
+
+    /**
+     * Called by an {@link InstanceTime} created by this TimingSpecifier
+     * to indicate that its value has changed.
+     */
+    float handleTimebaseUpdate(InstanceTime instanceTime, float newTime) {
+        // Trace.enter(this, "handleTimebaseUpdate", new Object[] { instanceTime, new Float(newTime) } ); try {
+        if (owner.hasPropagated) {
+            return Float.POSITIVE_INFINITY;
+        }
+        return owner.instanceTimeChanged(instanceTime, isBegin);
+        // } finally { Trace.exit(); }
+    }
+}

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f690ea2f/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/TimeContainer.java
----------------------------------------------------------------------
diff --git a/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/TimeContainer.java b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/TimeContainer.java
new file mode 100644
index 0000000..96bcd73
--- /dev/null
+++ b/modules/thirdparty/batik/sources/org/apache/flex/forks/batik/anim/timing/TimeContainer.java
@@ -0,0 +1,147 @@
+/*
+
+   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.anim.timing;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * An abstract base class for time container elements.
+ *
+ * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
+ * @version $Id: TimeContainer.java 579456 2007-09-26 03:58:47Z cam $
+ */
+public abstract class TimeContainer extends TimedElement {
+
+    /**
+     * The child {@link TimedElement}s of this time container.
+     */
+    protected List children = new LinkedList();
+
+    /**
+     * Adds a {@link TimedElement} to this container.
+     */
+    public void addChild(TimedElement e) {
+        if (e == this) {
+            throw new IllegalArgumentException("recursive datastructure not allowed here!");
+        }
+        children.add(e);
+        e.parent = this;
+        setRoot(e, root);
+        root.fireElementAdded(e);
+        root.currentIntervalWillUpdate();
+    }
+
+    /**
+     * Recursively sets the {@link TimedDocumentRoot} of the given
+     * {@link TimedElement} and any of its descendants.
+     */
+    protected void setRoot(TimedElement e, TimedDocumentRoot root) {
+        e.root = root;
+        if (e instanceof TimeContainer) {
+            TimeContainer c = (TimeContainer) e;
+            Iterator it = c.children.iterator();
+            while (it.hasNext()) {
+                TimedElement te = (TimedElement)it.next();
+                setRoot(te, root);
+            }
+        }
+    }
+
+    /**
+     * Removes a {@link TimedElement} from this container.
+     */
+    public void removeChild(TimedElement e) {
+        children.remove(e);
+        e.parent = null;
+        setRoot(e, null);
+        root.fireElementRemoved(e);
+        root.currentIntervalWillUpdate();
+    }
+
+    /**
+     * Returns an array of the children of this container.
+     */
+    public TimedElement[] getChildren() {
+        return (TimedElement[]) children.toArray(new TimedElement[0]);
+    }
+
+    /**
+     * Calculates the local simple time.  Currently the hyperlinking parameter
+     * is ignored, so DOM timing events are fired during hyperlinking seeks.
+     * If we were following SMIL 2.1 rather than SMIL Animation, then these
+     * events would have to be surpressed.
+     *
+     * @return the number of seconds until this element becomes active again
+     *         if it currently is not, {@link Float#POSITIVE_INFINITY} if this
+     *         element will become active at some undetermined point in the
+     *         future (because of unresolved begin times, for example) or
+     *         will never become active again, or <code>0f</code> if the
+     *         element is currently active.
+     */
+    protected float sampleAt(float parentSimpleTime, boolean hyperlinking) {
+        super.sampleAt(parentSimpleTime, hyperlinking);
+        // Maybe check the return value of the previous statement.
+        return sampleChildren(parentSimpleTime, hyperlinking);
+    }
+
+    /**
+     * Samples all the child timed elements.
+     */
+    protected float sampleChildren(float parentSimpleTime,
+                                   boolean hyperlinking) {
+        float mint = Float.POSITIVE_INFINITY;
+        Iterator i = children.iterator();
+        while (i.hasNext()) {
+            TimedElement e = (TimedElement) i.next();
+            float t = e.sampleAt(parentSimpleTime, hyperlinking);
+            if (t < mint) {
+                mint = t;
+            }
+        }
+        return mint;
+    }
+
+    /**
+     * Resets this element.
+     */
+    protected void reset(boolean clearCurrentBegin) {
+        super.reset(clearCurrentBegin);
+        Iterator i = children.iterator();
+        while (i.hasNext()) {
+            TimedElement e = (TimedElement) i.next();
+            e.reset(clearCurrentBegin);
+        }
+    }
+
+    /**
+     * Returns whether this timed element is for a constant animation (i.e., a
+     * 'set' animation.
+     */
+    protected boolean isConstantAnimation() {
+        return false;
+    }
+
+    /**
+     * Returns the default begin time for the given child
+     * timed element.
+     */
+    public abstract float getDefaultBegin(TimedElement child);
+}