Index: /cvsroot/mozilla/content/smil/Makefile.in
===================================================================
RCS file: /cvsroot/mozilla/content/smil/Makefile.in
diff -N content/smil/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/Makefile.in	14 Sep 2005 10:44:00 -0000
@@ -0,0 +1,48 @@
+# 
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+DIRS		= public src
+
+include $(topsrcdir)/config/rules.mk
+
Index: /cvsroot/mozilla/content/smil/public/Makefile.in
===================================================================
RCS file: /cvsroot/mozilla/content/smil/public/Makefile.in
diff -N content/smil/public/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/public/Makefile.in	14 Sep 2005 10:44:01 -0000
@@ -0,0 +1,61 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH           = ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE		= content
+
+EXPORTS		= \
+    nsISMILAnimAttr.h \
+	nsISMILAnimElement.h \
+	nsISMILAnimVal.h \
+	nsISMILAnimationController.h \
+	nsISMILAnimationFunction.h \
+	nsISMILAnimationRegistry.h \
+	nsISMILComposable.h \
+	nsISMILTimeClient.h \
+	nsISMILTimeContainer.h \
+	nsISMILTimedElement.h \
+	$(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
Index: /cvsroot/mozilla/content/smil/public/nsISMILAnimAttr.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/public/nsISMILAnimAttr.h
diff -N content/smil/public/nsISMILAnimAttr.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/public/nsISMILAnimAttr.h	14 Sep 2005 10:44:01 -0000
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_ISMILANIMATTR_H__
+#define __NS_ISMILANIMATTR_H__
+
+#include "nsISupports.h"
+
+class nsISMILAnimVal;
+
+////////////////////////////////////////////////////////////////////////
+// nsISMILAnimAttr
+
+// {c487920a-7d12-40ff-bf3b-c39dd4797cff}
+#define NS_ISMILANIMATTR_IID \
+{ 0xc487920a, 0x7d12, 0x40ff, { 0xbf, 0x3b, 0xc3, 0x9d, 0xd4, 0x79, 0x7c, 0xff } }
+
+class nsISMILAnimAttr : public nsISupports
+{
+public:
+  NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISMILANIMATTR_IID)
+
+  virtual nsISMILAnimVal*       GetBaseValue()=0;
+  virtual nsresult              SetAnimValue(nsISMILAnimVal& aValue)=0;
+
+  /*
+   * Factory methods
+   *
+   * NOTE: By moving these to nsISMILAnimVal, we'd be able to remove the
+   * dependency on this interface by nsSMILAnimationFunction and be one step
+   * closer to removing this interface altogether.
+   */
+  virtual nsresult  Create(nsISMILAnimVal** aResult) const = 0;
+
+  virtual nsresult  CreateFromSpec(const nsAString& aSpec,
+                                   nsISMILAnimVal** aResult) const = 0;
+};
+
+#endif // __NS_ISMILANIMATTR_H__
+
Index: /cvsroot/mozilla/content/smil/public/nsISMILAnimElement.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/public/nsISMILAnimElement.h
diff -N content/smil/public/nsISMILAnimElement.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/public/nsISMILAnimElement.h	14 Sep 2005 10:44:01 -0000
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_ISMILANIMELEMENT__
+#define __NS_ISMILANIMELEMENT__
+
+#include "nsISupports.h"
+#include "nsISMILAnimAttr.h"
+
+////////////////////////////////////////////////////////////////////////
+// nsISMILAnimElement: interface of elements that have attributes
+// that can be animated.
+
+// {5DD94E10-FD8D-42FB-B054-8D29F771033A}
+#define NS_ISMILANIMELEMENT_IID \
+{ 0x5dd94e10, 0xfd8d, 0x42fb, { 0xb0, 0x54, 0x8d, 0x29, 0xf7, 0x71, 0x03, 0x3a } }
+
+class nsISMILAnimElement : public nsISupports
+{
+public:
+  NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISMILANIMELEMENT_IID)
+
+  virtual nsISMILAnimAttr*
+  GetAnimAttribute(PRInt32 aNamespaceID, nsIAtom* aName)=0;
+};
+
+#endif // __NS_ISMILANIMELEMENT__
+
Index: /cvsroot/mozilla/content/smil/public/nsISMILAnimVal.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/public/nsISMILAnimVal.h
diff -N content/smil/public/nsISMILAnimVal.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/public/nsISMILAnimVal.h	14 Sep 2005 10:44:01 -0000
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_ISMILANIMVAL_H__
+#define __NS_ISMILANIMVAL_H__
+
+#include "nsISupports.h"
+
+////////////////////////////////////////////////////////////////////////
+// nsISMILAnimVal
+
+// {01d2aae5-9de4-4e8f-a1e9-ae660ad27925}
+#define NS_ISMILANIMVAL_IID \
+{ 0x01d2aae5, 0x9de4, 0x4e8f, { 0xa1, 0xe9, 0xae, 0x66, 0x0a, 0xd2, 0x79, 0x25 } }
+
+class nsISMILAnimVal : public nsISupports
+{
+public:
+  NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISMILANIMVAL_IID)
+
+  /**
+   * Calculates the 'distance' between this value and another. This is the
+   * distance used in paced interpolation.
+   *
+   * @param   aTo       The end of the interval for which the distance should be
+   *                    calculated.
+   * @param   aDistance The result of the calculation.
+   * @return  True on success, or false if there is no notion of distance for
+   *          the underlying data type.
+   */
+  virtual bool      ComputeDistance(const nsISMILAnimVal& aTo,
+                                    PRFloat64& aDistance) const = 0;
+
+  /**
+   * Calculates an interpolates value between this value and the specified end
+   * value using the specified proportion.
+   *
+   * @param   aEndVal       The value defining the end of the interval of
+   *                        interpolation.
+   * @param   aUnitDistance A number between 0.0 and 1.0 (inclusive) defining
+   *                        the distance of the interpolated value in the
+   *                        interval.
+   * @param   aResult       The interpolated value.
+   *
+   * @result  NS_OK on success, NS_ERROR_FAILURE if this data type cannot be
+   *          interpolated or NS_ERROR_OUT_OF_MEMORY if insufficient memory was
+   *          available for storing the result.
+   */
+  virtual nsresult  Interpolate(const nsISMILAnimVal& aEndVal,
+                                float aUnitDistance,
+                                nsISMILAnimVal& aResult) = 0;
+
+  /**
+   * Add the given value to this value. This method facilitates additive and
+   * cumulative animation.
+   *
+   * This method will fail (return false) if the underlying datatype is not
+   * additive or was not specified using an additive syntax.
+   *
+   * See SVG 1.1, section 19.2.5. In particular,
+   *
+   * "If a given attribute or property can take values of keywords (which are
+   * not additive) or numeric values (which are additive), then additive
+   * animations are possible if the subsequent animation uses a numeric value
+   * even if the base animation uses a keyword value; however, if the subsequent
+   * animation uses a keyword value, additive animation is not possible."
+   *
+   * @param   aAddedVal   The value to add to this value.
+   * @return  True on success, false on failure.
+   */
+  virtual bool      Add(const nsISMILAnimVal& aAddedVal) = 0;
+
+  /**
+   * Assign this object the value of another. Think of this as the assignment
+   * operator.
+   *
+   * @param   aNewVal     The value to set.
+   * @return  True on success, false on failure such as when the underlying
+   *          type of the specified object differs.
+   */
+  virtual bool      Set(const nsISMILAnimVal& aNewVal) = 0;
+
+  /**
+   * Repeats this value or the specified value a number of times. This method
+   * will fail (return false) if the underlying data type is not additive.
+   *
+   * @param   aCount        The number of times to repeat the value.
+   * @param   aRepeatValue  The value to repeat. If this parameter is null the
+   *                        current value will be repeated.
+   * @return  True on success, false on failure.
+   */
+  virtual bool      Repeat(PRUint32 aCount,
+                           const nsISMILAnimVal* aRepeatValue = nsnull) = 0;
+};
+
+#endif // __NS_ISMILANIMVAL_H__
+
Index: /cvsroot/mozilla/content/smil/public/nsISMILAnimationController.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/public/nsISMILAnimationController.h
diff -N content/smil/public/nsISMILAnimationController.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/public/nsISMILAnimationController.h	14 Sep 2005 10:44:02 -0000
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_ISMILANIMATIONCONTROLLER_H__
+#define __NS_ISMILANIMATIONCONTROLLER_H__
+
+#include "nsIAnimationController.h"
+
+#define NS_ISMILANIMATIONCONTROLLER_IID \
+{ 0xd2c81398, 0x1f30, 0x4303, { 0xbe, 0xbe, 0xc5, 0x0c, 0x01, 0xfd, 0xd8, 0x85 } }
+
+class nsISMILTimeContainer;
+
+////////////////////////////////////////////////////////////////////////
+// nsISMILAnimationController: Animation controller
+
+class nsISMILAnimationController : public nsIAnimationController
+{
+public:
+  NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISMILANIMATIONCONTROLLER_IID)
+
+  // nsIAnimationController methods
+  virtual nsresult  Pause()=0;
+  virtual nsresult  Resume()=0;
+
+  // Eventually, this will probably be all nsISMILTimedElements so that it is
+  // possible to have hierarchies of containers (which will implement
+  // nsISMILTimedElement), and then these methods will be replaced with
+  // SetRootElement.
+  virtual nsresult  AddTimeContainer(nsISMILTimeContainer* aContainer)=0;
+  virtual nsresult  RemoveTimeContainer(nsISMILTimeContainer* aContainer)=0;
+};
+
+nsISMILAnimationController* NS_NewSMILAnimationController();
+
+#endif // __NS_ISMILANIMATIONCONTROLLER_H__
+
Index: /cvsroot/mozilla/content/smil/public/nsISMILAnimationFunction.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/public/nsISMILAnimationFunction.h
diff -N content/smil/public/nsISMILAnimationFunction.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/public/nsISMILAnimationFunction.h	14 Sep 2005 10:44:02 -0000
@@ -0,0 +1,104 @@
+
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_ISMILANIMFUNCTION_H__
+#define __NS_ISMILANIMFUNCTION_H__
+
+#include "nsISupports.h"
+
+class nsISMILAnimAttr;
+
+// {14eb1aab-e4ba-4c77-be89-195ef975c90d}
+#define NS_ISMILANIMFUNCTION_IID \
+{ 0x14eb1aab, 0xe4ba, 0x4c77, { 0xbe, 0x89, 0x19, 0x5e, 0xf9, 0x75, 0xc9, 0x0d } }
+
+/**
+ * Provides the animation function for an interpolating animation element. This
+ * includes the animation-related attributes. It is intended to be used by
+ * elements such as <animate>, <animateColor> and so on.
+ *
+ * It will likely be split into nsISMILInterpolatingAnimFunc and
+ * nsISMILSimpleAnimFunc when <set> is introduced. Extra parameters or perhaps
+ * a subclass will probably be needed to support <animateTransform>,
+ * <animateMotion> and the like.
+ */
+class nsISMILAnimationFunction : public nsISupports
+{
+public:
+  NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISMILANIMFUNCTION_IID)
+
+  virtual nsresult        Init(nsISMILAnimAttr& aAttribute)=0;
+  virtual PRBool          IsInitialised()=0;
+
+  /*
+   * Property setters
+   */
+  virtual nsresult        SetAccumulate(const nsAString& aAccumulate)=0;
+  virtual nsresult        SetAdditive(const nsAString& aAdditive)=0;
+  virtual nsresult        SetBy(const nsAString& aBy)=0;
+  virtual nsresult        SetCalcMode(const nsAString& aCalcMode)=0;
+  virtual nsresult        SetFrom(const nsAString& aFrom)=0;
+  virtual nsresult        SetKeyTimes(const nsAString& aKeyTimes)=0;
+  virtual nsresult        SetKeySplines(const nsAString& aKeySplines)=0;
+  virtual nsresult        SetTo(const nsAString& aTo)=0;
+  virtual nsresult        SetValues(const nsAString& aValues)=0;
+
+  /*
+   * Property unsetters
+   *
+   * Unsetters are used instead of simply passing an empty string to the setters
+   * as in some cases an empty string is an error whereas not specifying an
+   * attribute is not.
+   *
+   * Unsetters are used in preference to setting a default value so that this
+   * object is responsible for supplying default values and not all the
+   * different animation elements that use it.
+   */
+  virtual void            UnsetAdditive()=0;
+  virtual void            UnsetBy()=0;
+  virtual void            UnsetCalcMode()=0;
+  virtual void            UnsetAccumulate()=0;
+  virtual void            UnsetFrom()=0;
+  virtual void            UnsetKeyTimes()=0;
+  virtual void            UnsetKeySplines()=0;
+  virtual void            UnsetTo()=0;
+  virtual void            UnsetValues()=0;
+
+  virtual void            SetDocumentPosition(PRUint16 aDocPosition)=0;
+};
+
+nsISMILAnimationFunction* NS_NewSMILAnimationFunction();
+
+#endif //__NS_ISMILANIMFUNCTION_H__
+
Index: /cvsroot/mozilla/content/smil/public/nsISMILAnimationRegistry.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/public/nsISMILAnimationRegistry.h
diff -N content/smil/public/nsISMILAnimationRegistry.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/public/nsISMILAnimationRegistry.h	14 Sep 2005 10:44:02 -0000
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_ISMILANIMATIONREGISTRY_H__
+#define __NS_ISMILANIMATIONREGISTRY_H__
+
+#include "nsISupports.h"
+
+class nsISMILAnimationController;
+class nsISMILComposable;
+class nsISMILAnimAttr;
+class nsISMILTimedElement;
+
+#define NS_ISMILANIMATIONREGISTRY_IID \
+{ 0xdd3c7124, 0xcc1f, 0x447b, { 0xa1, 0x35, 0x4a, 0xd8, 0xfc, 0xd4, 0x9f, 0x31 } }
+
+////////////////////////////////////////////////////////////////////////
+// nsISMILAnimationRegistry: Entry point for SMIL animated documents
+
+class nsISMILAnimationRegistry : public nsISupports
+{
+public:
+  NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISMILANIMATIONREGISTRY_IID)
+
+  virtual nsresult  SetController(nsISMILAnimationController* aController)=0;
+  virtual void      Pause()=0;
+  virtual void      Unpause()=0;
+  virtual PRBool    IsPaused()=0;
+  virtual float     GetCurrentTime()=0;
+  virtual nsresult  SetCurrentTime(float aSeconds)=0;
+  virtual nsresult  RegisterComposable(nsISMILAnimAttr* aTargetAttr,
+                                       nsISMILComposable* aComposable)=0;
+  virtual nsresult  UnregisterComposable(nsISMILComposable* aComposable)=0;
+  virtual nsresult  RegisterTimedElement(nsISMILTimedElement* aElement)=0;
+  virtual nsresult  UnregisterTimedElement(nsISMILTimedElement* aElement)=0;
+};
+
+nsISMILAnimationRegistry* NS_NewSMILAnimationRegistry();
+
+#endif // __NS_ISMILANIMATIONREGISTRY_H__
+
Index: /cvsroot/mozilla/content/smil/public/nsISMILComposable.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/public/nsISMILComposable.h
diff -N content/smil/public/nsISMILComposable.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/public/nsISMILComposable.h	14 Sep 2005 10:44:02 -0000
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_ISMILCOMPOSABLE_H__
+#define __NS_ISMILCOMPOSABLE_H__
+
+#include "nsISupports.h"
+#include "nsWeakReference.h"
+
+class nsISMILAnimVal;
+
+////////////////////////////////////////////////////////////////////////
+// nsISMILComposable
+
+// {4b05aa22-712e-4a9e-8452-f7c4b2e507e7}
+#define NS_ISMILCOMPOSABLE_IID \
+{ 0x4b05aa22, 0x712e, 0x4a9e, { 0x84, 0x52, 0xf7, 0xc4, 0xb2, 0xe5, 0x07, 0xe7 } }
+
+class nsISMILComposable : public nsSupportsWeakReference
+{
+public:
+  NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISMILCOMPOSABLE_IID)
+
+  /**
+   * Combines the result of this animation function for the last sample with the
+   * specified value.
+   *
+   * @param aResult The value to compose with.
+   */
+  virtual void      ComposeResult(nsISMILAnimVal &aResult)=0;
+
+  /**
+   * Returns the relative priority of this animation to another. The priority is
+   * used for determining the position of the animation in the animation
+   * sandwich.
+   *
+   * @return  -1 if this animation has lower priority or 1 if this animation has
+   *          higher priority
+   *
+   * This method should never return 0.
+   */
+  virtual PRInt8    CompareTo(const nsISMILComposable& composable) const=0;
+
+  /*
+   * The following three methods are used in sorting.
+   */
+
+  /**
+   * Indicates if this animation is a 'to animation'. Such animations appear
+   * 'higher' in the animation sandwich than all other animations.
+   *
+   * @return  True if this animation is a to animation, false otherwise.
+   */
+  virtual PRBool    IsToAnimation() const=0;
+
+  /**
+   * Returns the begin time of this animation for the interval it is currently
+   * animating. For inactive animations this will be LL_MinInt but such
+   * animations should be filtered from compositing anyway.
+   *
+   * @return  A 64-bit integer representing the begin time of this animation.
+   */
+  virtual const PRInt64&  GetBeginTime() const=0;
+
+  /**
+   * Returns a unique (0-based) index indicating the position of this animation
+   * in the document. The first animation will have index 0 as so on. Positions
+   * are recalculated when the document structure is changed.
+   *
+   * @return  An unsigned integer representing this animation's position in the
+   *          document.
+   */
+  virtual PRUint16   GetDocumentPosition() const=0;
+
+  /*
+   * The following methods are provided so that the compositor can optimise its
+   * operations in the future by only composing those animation that will affect
+   * the final result.
+   */
+ 
+  /**
+   * Indicates if the animation is currently active. Inactive animations will
+   * not contribute to the composed result.
+   *
+   * @return  True if the animation active, false otherwise.
+   */
+  virtual PRBool    IsActive() const=0; 
+
+  /**
+   * Indicates if this animation will replace the passed in result rather than
+   * adding to it. Animations that replace the underlying value may be called
+   * without first calling lower priority animations.
+   *
+   * @return  True if the animation will replace, false if it will add or
+   *          otherwise build on the passed in value.
+   */
+  virtual PRBool    WillReplace() const=0;
+};
+
+#endif // __NS_ISMILCOMPOSABLE_H__
+
Index: /cvsroot/mozilla/content/smil/public/nsISMILTimeClient.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/public/nsISMILTimeClient.h
diff -N content/smil/public/nsISMILTimeClient.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/public/nsISMILTimeClient.h	14 Sep 2005 10:44:02 -0000
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_ISMILTIMECLIENT_H__
+#define __NS_ISMILTIMECLIENT_H__
+
+#include "nsISupports.h"
+
+class nsSMILTimeValue;
+
+////////////////////////////////////////////////////////////////////////
+// nsISMILTimeClient
+
+// {196f66f4-e6f6-420b-a337-da42a2efccde}
+#define NS_ISMILTIMECLIENT_IID \
+{ 0x196f66f4, 0xe6f6, 0x420b, { 0xa3, 0x37, 0xda, 0x42, 0xa2, 0xef, 0xcc, 0xde } }
+
+class nsISMILTimeClient : public nsISupports
+{
+public:
+  NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISMILTIMECLIENT_IID)
+
+  virtual void      SampleAt(const PRInt64& aSimpleTime,
+                             const nsSMILTimeValue& aSimpleDuration,
+                             const PRUint32& aRepeatIteration)=0;
+
+  virtual void      SampleLastValue(const PRUint32& aRepeatIteration)=0;
+
+  virtual void      ToActive(const PRInt64& aBeginTime)=0;
+
+  virtual void      ToInactive()=0;
+};
+
+#endif // __NS_ISMILTIMECLIENT_H__
Index: /cvsroot/mozilla/content/smil/public/nsISMILTimeContainer.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/public/nsISMILTimeContainer.h
diff -N content/smil/public/nsISMILTimeContainer.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/public/nsISMILTimeContainer.h	14 Sep 2005 10:44:03 -0000
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_ISMILTIMECONTAINER_H__
+#define __NS_ISMILTIMECONTAINER_H__
+
+#include "nsISupports.h"
+#include "nsISMILTimedElement.h"
+
+////////////////////////////////////////////////////////////////////////
+// nsISMILTimeContainer: Time container
+
+// {46b51a7b-d857-45f1-9c7d-4d0d12719238}
+#define NS_ISMILTIMECONTAINER_IID \
+{ 0x46b51a7b, 0xd857, 0x45f1, { 0x9c, 0x7d, 0x4d, 0x0d, 0x12, 0x71, 0x92, 0x38 } }
+
+// When implementing SMIL 2.0 time containers, this would inherit from
+// nsISMILTimedElement, amongst other changes
+class nsISMILTimeContainer : public nsISupports
+{
+public:
+  NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISMILTIMECONTAINER_IID)
+
+  virtual nsresult  Pause()=0;
+  virtual nsresult  Resume()=0;
+
+  // We may later change this to SampleAt and maintain separate host document
+  // and document fragment times. This would allow more advanced time
+  // manipulations for documents with several animated SVG document fragments.
+  virtual void      Sample()=0;
+
+  virtual nsresult  AddTimedElement(nsISMILTimedElement* aElement)=0;
+  virtual nsresult  RemoveTimedElement(nsISMILTimedElement* aElement)=0;
+};
+
+#endif // __NS_ISMILTIMECONTAINER_H__
+
Index: /cvsroot/mozilla/content/smil/public/nsISMILTimedElement.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/public/nsISMILTimedElement.h
diff -N content/smil/public/nsISMILTimedElement.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/public/nsISMILTimedElement.h	14 Sep 2005 10:44:03 -0000
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_ISMILTIMEDELEMENT_H__
+#define __NS_ISMILTIMEDELEMENT_H__
+
+#include "nsWeakReference.h"
+
+class nsISMILTimeClient;
+class nsSMILTimeValue;
+class nsSMILInstanceTime;
+
+////////////////////////////////////////////////////////////////////////
+// nsISMILTimedElement
+
+// {c5f60446-5c1a-4f3b-8ce3-646199ac97f2}
+#define NS_ISMILTIMEDELEMENT_IID \
+{ 0xc5f60446, 0x5c1a, 0x4f3b, { 0x8c, 0xe3, 0x64, 0x61, 0x99, 0xac, 0x97, 0xf2 } }
+
+class nsISMILTimedElement : public nsSupportsWeakReference
+{
+public:
+  NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISMILTIMEDELEMENT_IID)
+
+  /**
+   * Adds an instance time object this this element's list of instance times.
+   * These instance times are used when creating intervals.
+   *
+   * This method is typically called by a nsSMILTimeValueSpec to register an
+   * instance time corresponding its specification.
+   *
+   * @param aInstanceTime   The time to add.
+   *
+   * @param aIsBegin        True if the time to be added represents a begin time
+   *                        or False if it represents an end time.
+   */
+  virtual void      AddInstanceTime(nsSMILInstanceTime* aInstanceTime,
+                                    PRBool aIsBegin)=0;
+
+  /**
+   * Sets the object that will be called by this timed element each time it is
+   * sampled.
+   *
+   * In Schmitz's model it is possible to associate several time clients with
+   * a timed element but for now we only allow one.
+   *
+   * @param aClient   The time client to associate. Any previous time client
+   *                  will be disassociated and no longer sampled. Setting this
+   *                  to NULL will simply disassociate the previous client, if
+   *                  any.
+   */
+  virtual void      SetTimeClient(nsISMILTimeClient* aClient)=0;
+
+  /**
+   * Samples the object at the given document time. Timing intervals are updated
+   * and if this element is active at the given time the associated time client
+   * to be sampled with the appropriate simple time.
+   *
+   * @param aDocumentTime The document time at which to sample.
+   */
+  virtual void      SampleAt(const PRInt64& aDocumentTime)=0;
+
+  /*
+   * Property setters
+   */
+  virtual nsresult  SetBeginSpec(const nsAString& aBeginSpec)=0;
+  virtual nsresult  SetEndSpec(const nsAString& aEndSpec)=0;
+  virtual nsresult  SetSimpleDuration(const nsAString& aDurSpec)=0;
+  virtual nsresult  SetMin(const nsAString& aMinSpec)=0;
+  virtual nsresult  SetMax(const nsAString& aMaxSpec)=0;
+  virtual nsresult  SetRestart(const nsAString& aRestartSpec)=0;
+  virtual nsresult  SetRepeatCount(const nsAString& aRepeatCountSpec)=0;
+  virtual nsresult  SetRepeatDur(const nsAString& aRepeatDurSpec)=0;
+  virtual nsresult  SetFillMode(const nsAString& aFillModeSpec)=0;
+
+  /*
+   * Property unsetters
+   *
+   * Unsetters are used instead of simply passing an empty string to the setters
+   * as in some cases an empty string is an error whereas not specifying an
+   * attribute is not.
+   *
+   * Unsetters are used in preference to setting a default value so that this
+   * object is responsible for supplying default values and not all the
+   * different animation elements that use it.
+   */
+  virtual void      UnsetBeginSpec()=0;
+  virtual void      UnsetEndSpec()=0;
+  virtual void      UnsetSimpleDuration()=0;
+  virtual void      UnsetMin()=0;
+  virtual void      UnsetMax()=0;
+  virtual void      UnsetRestart()=0;
+  virtual void      UnsetRepeatCount()=0;
+  virtual void      UnsetRepeatDur()=0;
+  virtual void      UnsetFillMode()=0;
+};
+
+nsISMILTimedElement* NS_NewSMILTimedElement();
+
+#endif // __NS_ISMILTIMEDELEMENT_H__
+
Index: /cvsroot/mozilla/content/smil/src/Makefile.in
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/Makefile.in
diff -N content/smil/src/Makefile.in
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/Makefile.in	14 Sep 2005 10:44:03 -0000
@@ -0,0 +1,83 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE		= content
+LIBRARY_NAME	= gkconsmil_s
+LIBXUL_LIBRARY	= 1
+
+REQUIRES	= xpcom \
+		  string \
+		  js \
+		  layout \
+		  content \
+		  necko \
+		  xpconnect \
+		  docshell \
+		  webshell \
+		  imglib2 \
+		  unicharutil \
+		  locale \
+		  $(NULL)
+
+CPPSRCS		= \
+	nsSMILAnimationController.cpp \
+	nsSMILAnimationFunction.cpp \
+	nsSMILAnimationRegistry.cpp \
+	nsSMILCompositor.cpp \
+	nsSMILInstanceTime.cpp \
+	nsSMILInterval.cpp \
+	nsSMILTimedDocumentRoot.cpp \
+	nsSMILTimedElement.cpp \
+	nsSMILTimeValue.cpp \
+	nsSMILTimeValueSpec.cpp \
+		$(NULL)
+
+include $(topsrcdir)/config/config.mk
+
+# we don't want the shared lib, but we want to force the creation of a static lib.
+FORCE_STATIC_LIB = 1
+
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -D_IMPL_NS_LAYOUT
Index: /cvsroot/mozilla/content/smil/src/nsSMILAnimationController.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILAnimationController.cpp
diff -N content/smil/src/nsSMILAnimationController.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILAnimationController.cpp	14 Sep 2005 10:44:04 -0000
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISMILAnimationController.h"
+#include "nsComponentManagerUtils.h"
+#include "nsWeakReference.h"
+#include "nsITimer.h"
+#include "nsISMILTimeContainer.h"
+#include "nsCOMArray.h"
+#include "nsISimpleEnumerator.h"
+#include "nsArrayEnumerator.h"
+
+class nsSMILAnimationController : public nsISMILAnimationController,
+                                  public nsSupportsWeakReference,
+                                  public nsITimerCallback
+{
+public:
+  virtual ~nsSMILAnimationController();
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSITIMERCALLBACK
+
+  // nsISMILAnimationController
+  virtual nsresult  Pause();
+  virtual nsresult  Resume();
+  virtual nsresult  AddTimeContainer(nsISMILTimeContainer* aContainer);
+  virtual nsresult  RemoveTimeContainer(nsISMILTimeContainer* aContainer);
+
+protected:
+  friend nsISMILAnimationController* NS_NewSMILAnimationController();
+
+  nsresult          Init();
+  nsresult          StartTimer();
+  nsresult          StopTimer();
+  void              SampleChildren();
+
+  nsCOMPtr<nsITimer>            mTimer;
+  nsCOMArray<nsIWeakReference>  mTimeContainers;
+};
+
+////////////////////////////////////////////////////////////////////////
+// nsSMILAnimationController implementation
+
+//----------------------------------------------------------------------
+// ctors, dtors, factory methods
+
+nsSMILAnimationController::~nsSMILAnimationController()
+{
+  if (mTimer)
+    mTimer->Cancel();
+}
+
+nsISMILAnimationController* NS_NewSMILAnimationController()
+{
+  nsSMILAnimationController* animationController = 
+    new nsSMILAnimationController();
+
+  if (animationController)
+  {
+    nsresult rv = animationController->Init();
+    if (NS_FAILED(rv))
+    {
+      delete animationController;
+      animationController = nsnull;
+    }
+  }
+
+  return animationController;
+}
+
+
+//----------------------------------------------------------------------
+// nsISupports methods:
+
+NS_IMPL_ISUPPORTS3(nsSMILAnimationController,
+                   nsISMILAnimationController,
+                   nsIAnimationController,
+                   nsISupportsWeakReference);
+
+//----------------------------------------------------------------------
+// nsITimerCallback methods
+
+NS_IMETHODIMP
+nsSMILAnimationController::Notify(nsITimer *timer)
+{
+  NS_ASSERTION(mTimer == timer,
+               "nsSMILAnimationController::Notify called with incorrect timer");
+
+  SampleChildren();
+
+  return NS_OK;
+}
+
+
+//----------------------------------------------------------------------
+// nsISMILAnimationController methods:
+
+nsresult
+nsSMILAnimationController::Pause()
+{
+  // TODO[2]: (for now this just involves calling pause on all the children)
+  NS_NOTYETIMPLEMENTED("nsSMILAnimationController::Pause");
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+nsSMILAnimationController::Resume()
+{
+  // TODO[2]: (for now this just involves calling resume on all the children)
+  NS_NOTYETIMPLEMENTED("nsSMILAnimationController::Resume");
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+nsSMILAnimationController::AddTimeContainer(nsISMILTimeContainer* aContainer)
+{
+  if (!aContainer)
+    return NS_ERROR_NULL_POINTER;
+
+  nsresult rv;
+  nsCOMPtr<nsIWeakReference> weakRef(
+      getter_AddRefs(do_GetWeakReference(aContainer, &rv)) );
+
+  if (NS_SUCCEEDED(rv))
+    rv = (mTimeContainers.AppendObject(weakRef)) ? NS_OK : NS_ERROR_FAILURE;
+
+  if (NS_SUCCEEDED(rv) && mTimeContainers.Count() == 1)
+    rv = StartTimer();
+
+  return rv;
+}
+
+nsresult
+nsSMILAnimationController::RemoveTimeContainer(nsISMILTimeContainer* aContainer)
+{
+  if (!aContainer)
+    return NS_ERROR_NULL_POINTER;
+
+  nsresult rv;
+  nsCOMPtr<nsIWeakReference> weakRef(
+      getter_AddRefs(do_GetWeakReference(aContainer, &rv)) );
+
+  if (NS_SUCCEEDED(rv))
+    rv = (mTimeContainers.RemoveObject(weakRef)) ? NS_OK : NS_ERROR_FAILURE;
+
+  if (NS_SUCCEEDED(rv) && mTimeContainers.Count() == 0)
+    rv = StopTimer();
+
+  return rv;
+}
+
+//----------------------------------------------------------------------
+// Implementation helpers:
+
+nsresult
+nsSMILAnimationController::Init()
+{
+  mTimer = do_CreateInstance("@mozilla.org/timer;1");
+  return (mTimer) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+nsresult
+nsSMILAnimationController::StartTimer()
+{
+  NS_ASSERTION(mTimer, "NULL timer!");
+
+  // TODO[2]: Remove magic number and make timer self-tuning
+  return mTimer->InitWithCallback(NS_STATIC_CAST(nsITimerCallback*, this),
+                                  25, nsITimer::TYPE_REPEATING_SLACK);
+}
+
+nsresult
+nsSMILAnimationController::StopTimer()
+{
+  NS_ASSERTION(mTimer, "NULL timer!");
+
+  return mTimer->Cancel();
+}
+
+void
+nsSMILAnimationController::SampleChildren()
+{
+  // Creating a new enumerator each sample provides thread-safety but I'm not
+  // sure what the cost is
+
+  nsCOMPtr<nsISimpleEnumerator> enumerator;
+  nsresult rv = 
+    NS_NewArrayEnumerator(getter_AddRefs(enumerator), mTimeContainers);
+  NS_ENSURE_SUCCESS(rv,);
+
+  PRBool more = PR_FALSE;
+  nsCOMPtr<nsISMILTimeContainer> container;
+  nsCOMPtr<nsIWeakReference> weakRef;
+
+  while (NS_SUCCEEDED(enumerator->HasMoreElements(&more)) && more)
+  {
+    if (NS_FAILED(enumerator->GetNext(getter_AddRefs(weakRef))) || !weakRef)
+      break;
+
+    container = do_QueryReferent(weakRef);
+
+    if (container)
+      container->Sample();
+  }
+  
+  /* Non-thread safe version
+  PRUint32 i = mTimeContainers.Count();
+  while (i > 0)
+  {
+    --i;
+    nsCOMPtr<nsISMILTimeContainer> 
+      container( do_QueryReferent(mTimeContainers[i]) );
+    // The above could be replaced with mTimeContainers.SafeObjectAt(i) to
+    // provide a little more safety
+
+    if (container)
+      container->Sample();
+    else
+      mTimeContainers.RemoveObjectAt(i);
+  }
+  */
+}
+
Index: /cvsroot/mozilla/content/smil/src/nsSMILAnimationFunction.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILAnimationFunction.cpp
diff -N content/smil/src/nsSMILAnimationFunction.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILAnimationFunction.cpp	14 Sep 2005 10:44:05 -0000
@@ -0,0 +1,731 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISMILAnimationFunction.h"
+#include "nsISMILComposable.h"
+#include "nsISMILTimeClient.h"
+#include "nsSMILTimeValue.h"
+#include "nsISMILAnimVal.h"
+#include "nsISMILAnimAttr.h"
+#include "nsCOMPtr.h"
+#include "nsCOMArray.h"
+#include "nsReadableUtils.h"
+#include "nsString.h"
+#include "nsCRT.h"
+#include <math.h>
+
+//----------------------------------------------------------------------
+// nsSMILAnimationFunction
+
+class nsSMILAnimationFunction : public nsISMILAnimationFunction,
+                                public nsISMILComposable,
+                                public nsISMILTimeClient
+{
+public:
+  nsSMILAnimationFunction();
+
+  NS_DECL_ISUPPORTS
+
+  // nsISMILAnimationFunction
+  virtual nsresult        Init(nsISMILAnimAttr& aAttribute);
+  virtual PRBool          IsInitialised();
+
+  virtual nsresult        SetAccumulate(const nsAString& aAccumulate);
+  virtual nsresult        SetAdditive(const nsAString& aAdditive);
+  virtual nsresult        SetBy(const nsAString& aBy);
+  virtual nsresult        SetCalcMode(const nsAString& aCalcMode);
+  virtual nsresult        SetFrom(const nsAString& aFrom);
+  virtual nsresult        SetKeyTimes(const nsAString& aKeyTimes);
+  virtual nsresult        SetKeySplines(const nsAString& aKeySplines);
+  virtual nsresult        SetTo(const nsAString& aTo);
+  virtual nsresult        SetValues(const nsAString& aValues);
+
+  virtual void            UnsetAdditive();
+  virtual void            UnsetBy();
+  virtual void            UnsetCalcMode();
+  virtual void            UnsetAccumulate();
+  virtual void            UnsetFrom();
+  virtual void            UnsetKeyTimes();
+  virtual void            UnsetKeySplines();
+  virtual void            UnsetTo();
+  virtual void            UnsetValues();
+
+  virtual void            SetDocumentPosition(PRUint16 aDocPosition);
+
+  // nsISMILTimeClient methods
+  virtual void            SampleAt(const PRInt64& aSimpleTime,
+                                   const nsSMILTimeValue& aSimpleDuration,
+                                   const PRUint32& aRepeatIteration);
+  virtual void            SampleLastValue(const PRUint32& aRepeatIteration);
+  virtual void            ToActive(const PRInt64& aBeginTime);
+  virtual void            ToInactive();
+
+  // nsISMILComposable methods
+  virtual void            ComposeResult(nsISMILAnimVal &aResult);
+  virtual PRInt8          CompareTo(const nsISMILComposable& composable) const;
+  virtual PRBool          IsToAnimation() const;
+  virtual const PRInt64&  GetBeginTime() const;
+  virtual PRUint16        GetDocumentPosition() const;
+  virtual PRBool          IsActive() const; 
+  virtual PRBool          WillReplace() const;
+
+protected:
+  // Implementation helpers
+  nsISMILAnimationFunction*     NS_NewSMILAnimationFunction();
+  virtual void                  FillValuesArray();
+  virtual PRBool                IsAdditive() const;
+
+  // Members
+  
+  /*
+   * The attribute being targeted. This is needed for parsing animation function
+   * values and creating temporary objects.
+   */
+  nsCOMPtr<nsISMILAnimAttr>     mAttribute;
+
+  /*
+   * There are a lot of member variables here. Most of these are keeping track
+   * of the state of various attributes so that as they are set and unset we
+   * know which ones to apply. This could be done more effectively in the
+   * element that owns this object (for example, by calling GetAttr) but we take
+   * care of it here as we expect many elements will reuse this logic.
+   */
+  PRBool                        mIsActive;
+
+  /*
+   * Animation function values.
+   */
+  nsCOMPtr<nsISMILAnimVal>      mFrom;
+  nsCOMPtr<nsISMILAnimVal>      mTo;
+  nsCOMPtr<nsISMILAnimVal>      mBy;
+  nsCOMArray<nsISMILAnimVal>    mValues;
+
+  /*
+   * When the values attribute isn't set explicitly, the mValues array is filled
+   * with an equivalent set of values based on the from, to and by attributes.
+   * This flag indicates if the values array is filled with values from an
+   * actual values attribute (in which case it is true) or if it has been filled
+   * with the values of from, to and by (in which case it is false).
+   */
+  PRBool                        mValuesIsSet;
+
+  enum nsSMILCalcMode
+  {
+    NS_SMIL_CALCMODE_LINEAR,
+    NS_SMIL_CALCMODE_DISCRETE,
+    NS_SMIL_CALCMODE_PACED,
+    NS_SMIL_CALCMODE_SPLINE
+  };
+  nsSMILCalcMode                mCalcMode;
+
+  PRBool                        mAdditive;
+
+  /*
+   * These are the parameters provided by the previous sample. Currently we
+   * perform lazy calculation. That is, we only calculate the result if and when
+   * instructed by the compositor. This allows us to apply the result directly
+   * to the animation value and allows the compositor to filter out functions
+   * that it determines will not contribute to the final result.
+   */
+  PRInt64                       mSimpleTime;
+  nsSMILTimeValue               mSimpleDuration;
+  PRUint32                      mRepeatIteration;
+  PRBool                        mLastValue;
+
+  PRInt64                       mBeginTime;
+  PRUint16                      mDocumentPosition;
+};
+
+//----------------------------------------------------------------------
+// Constructors etc.
+
+nsSMILAnimationFunction::nsSMILAnimationFunction()
+  : mValuesIsSet(PR_FALSE),
+    mCalcMode(NS_SMIL_CALCMODE_LINEAR),
+    mAdditive(PR_FALSE),
+    mIsActive(PR_FALSE),
+    mSimpleTime(-1),
+    mRepeatIteration(0),
+    mLastValue(PR_FALSE),
+    mBeginTime(LL_MinInt()),
+    mDocumentPosition(PR_UINT16_MAX)
+{
+}
+
+nsISMILAnimationFunction*
+NS_NewSMILAnimationFunction()
+{
+  return new nsSMILAnimationFunction();
+}
+
+//----------------------------------------------------------------------
+// nsISupports methods:
+
+NS_IMPL_ISUPPORTS4(nsSMILAnimationFunction,
+                   nsISMILAnimationFunction,
+                   nsISMILComposable,
+                   nsISMILTimeClient,
+                   nsISupportsWeakReference)
+
+//----------------------------------------------------------------------
+// nsISMILAnimationFunction methods:
+
+nsresult
+nsSMILAnimationFunction::Init(nsISMILAnimAttr& aAttribute)
+{
+  mAttribute = &aAttribute;
+  return NS_OK;
+}
+
+PRBool
+nsSMILAnimationFunction::IsInitialised()
+{
+  return (mAttribute != nsnull);
+}
+
+nsresult
+nsSMILAnimationFunction::SetAdditive(const nsAString& aAdditive)
+{
+  /*
+   * We could use nsSVGEnum here but I'd prefer to keep this module independent
+   * of SVG if possible. Besides, the enums are very simple.
+   */
+  nsresult rv = NS_ERROR_FAILURE;
+  mAdditive = PR_FALSE;
+  char* str = ToNewCString(aAdditive);
+  char* val = str;
+
+  while (*val && NS_IS_SPACE(*val))
+    ++val;
+
+  if (*val != 0) {
+    if (PL_strncmp(val, "sum", 3) == 0) {
+      mAdditive = PR_TRUE;
+      val += 3;
+      rv = NS_OK;
+    } else if (PL_strncmp(val, "replace", 7) == 0) {
+      val += 7;
+      rv = NS_OK;
+    }
+  }
+
+  if (NS_SUCCEEDED(rv)) {
+    while (*val && NS_IS_SPACE(*val))
+      ++val;
+    if (*val != 0) {
+      mAdditive = PR_FALSE;
+      rv = NS_ERROR_FAILURE;
+    }
+  }
+
+  nsMemory::Free(str);
+
+  return rv;
+}
+
+void
+nsSMILAnimationFunction::UnsetAdditive()
+{
+  mAdditive = PR_FALSE;
+}
+
+nsresult
+nsSMILAnimationFunction::SetBy(const nsAString& aBy)
+{
+  NS_ASSERTION(mAttribute, "Animation element not initialised.");
+
+  if (!mAttribute)
+    return NS_ERROR_FAILURE;
+
+  nsresult rv;
+  rv = mAttribute->CreateFromSpec(aBy, getter_AddRefs(mBy));
+
+  FillValuesArray();
+
+  return rv;
+}
+
+void
+nsSMILAnimationFunction::UnsetBy()
+{
+  mBy          = nsnull;
+  FillValuesArray();
+}
+
+nsresult
+nsSMILAnimationFunction::SetCalcMode(const nsAString& aCalcMode)
+{
+  // TODO[2]
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+void
+nsSMILAnimationFunction::UnsetCalcMode()
+{
+  // TODO[2]
+}
+
+nsresult
+nsSMILAnimationFunction::SetAccumulate(const nsAString& aAccumulate)
+{
+  // TODO[2]
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+void
+nsSMILAnimationFunction::UnsetAccumulate()
+{
+  // TODO[2]
+}
+
+
+nsresult
+nsSMILAnimationFunction::SetFrom(const nsAString& aFrom)
+{
+  NS_ASSERTION(mAttribute, "Animation element not initialised.");
+
+  if (!mAttribute)
+    return NS_ERROR_FAILURE;
+
+  nsresult rv;
+  rv = mAttribute->CreateFromSpec(aFrom, getter_AddRefs(mFrom));
+
+  FillValuesArray();
+
+  return rv;
+}
+
+void
+nsSMILAnimationFunction::UnsetFrom()
+{
+  mFrom          = nsnull;
+  FillValuesArray();
+}
+
+nsresult
+nsSMILAnimationFunction::SetKeySplines(const nsAString& aKeySplines)
+{
+  // TODO[2]
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+void
+nsSMILAnimationFunction::UnsetKeySplines()
+{
+  // TODO[2]
+}
+
+nsresult
+nsSMILAnimationFunction::SetKeyTimes(const nsAString& aKeyTimes)
+{
+  // TODO[2]
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+void
+nsSMILAnimationFunction::UnsetKeyTimes()
+{
+  // TODO[2]
+}
+
+nsresult
+nsSMILAnimationFunction::SetTo(const nsAString& aTo)
+{
+  NS_ASSERTION(mAttribute, "Animation element not initialised.");
+
+  if (!mAttribute)
+    return NS_ERROR_FAILURE;
+
+  nsresult rv;
+  rv = mAttribute->CreateFromSpec(aTo, getter_AddRefs(mTo));
+
+  FillValuesArray();
+
+  return rv;
+}
+
+void
+nsSMILAnimationFunction::UnsetTo()
+{
+  mTo          = nsnull;
+  FillValuesArray();
+}
+
+nsresult
+nsSMILAnimationFunction::SetValues(const nsAString& aValues)
+{
+  NS_ASSERTION(mAttribute, "Animation element not initialised.");
+
+  if (!mAttribute)
+    return NS_ERROR_FAILURE;
+
+  nsresult rv;
+  nsAString::const_iterator start;
+  nsAString::const_iterator end;
+  nsAString::const_iterator substr_end;
+  nsAString::const_iterator next;
+
+  aValues.BeginReading(start);
+  aValues.EndReading(end);
+
+  mValues.Clear();
+  mValuesIsSet = PR_FALSE;
+
+  while (start != end) {
+    rv = NS_ERROR_FAILURE;
+
+    while (*start && NS_IS_SPACE(*start))
+      ++start;
+
+    if (*start == '\0' || *start == ';')
+      break;
+
+    substr_end = start;
+
+    while (substr_end != end && *substr_end != ';')
+      ++substr_end;
+
+    next = substr_end;
+    if (*substr_end == ';') {
+      ++next;
+      if (next == end)
+        break;
+    }
+
+    do --substr_end; while (start != substr_end && NS_IS_SPACE(*substr_end));
+      ++substr_end;
+
+    nsCOMPtr<nsISMILAnimVal> newValue;
+    rv = mAttribute->CreateFromSpec(Substring(start, substr_end),
+                                    getter_AddRefs(newValue));
+
+    if (NS_FAILED(rv))
+      break;
+
+    mValues.AppendObject(newValue);
+
+    start = next;
+  }
+
+  if (NS_SUCCEEDED(rv))
+    mValuesIsSet = PR_TRUE;
+  else
+    mValues.Clear();
+
+  return rv;
+}
+
+void
+nsSMILAnimationFunction::UnsetValues()
+{
+  mValuesIsSet = PR_FALSE;
+  FillValuesArray();
+}
+
+void
+nsSMILAnimationFunction::SetDocumentPosition(PRUint16 aDocPosition)
+{
+  mDocumentPosition = aDocPosition;
+}
+
+//----------------------------------------------------------------------
+// nsISMILTimeClient methods
+
+void
+nsSMILAnimationFunction::SampleAt(const PRInt64& aSimpleTime,
+                                  const nsSMILTimeValue& aSimpleDuration,
+                                  const PRUint32& aRepeatIteration)
+{
+  mSimpleTime       = aSimpleTime;
+  mSimpleDuration   = aSimpleDuration;
+  mRepeatIteration  = aRepeatIteration;
+  mLastValue        = PR_FALSE;
+}
+
+void
+nsSMILAnimationFunction::SampleLastValue(const PRUint32& aRepeatIteration)
+{
+  mRepeatIteration  = aRepeatIteration;
+  mLastValue        = PR_TRUE;
+}
+
+void
+nsSMILAnimationFunction::ToActive(const PRInt64& aBeginTime)
+{
+  mBeginTime = aBeginTime;
+  mIsActive = PR_TRUE;
+}
+
+void
+nsSMILAnimationFunction::ToInactive()
+{
+  mIsActive = PR_FALSE;
+}
+
+//----------------------------------------------------------------------
+// nsISMILComposable methods
+
+void
+nsSMILAnimationFunction::ComposeResult(nsISMILAnimVal &aResult)
+{
+  /*
+   * This checks if mValues is empty so we don't need to check it again
+   */
+  if (!IsActive())
+    return;
+
+  NS_ENSURE_TRUE(mSimpleTime >= 0,);
+  NS_ENSURE_TRUE(mSimpleDuration.IsResolved() || 
+                 mSimpleDuration.IsIndefinite(), );
+  NS_ENSURE_TRUE(mAttribute,);
+  
+  nsCOMPtr<nsISMILAnimVal> result;
+  NS_ENSURE_SUCCESS(mAttribute->Create(getter_AddRefs(result)),);
+
+  if (mSimpleDuration.IsIndefinite() ||
+      (mValuesIsSet && mValues.Count() == 1)) {
+    nsISMILAnimVal* firstValue = mValues.SafeObjectAt(0);
+    NS_ENSURE_TRUE(firstValue,);
+    result->Set(*firstValue);
+  } else if (mLastValue) {
+    nsISMILAnimVal* lastValue = mValues.SafeObjectAt(mValues.Count() - 1);
+    NS_ENSURE_TRUE(lastValue,);
+    result->Repeat(mRepeatIteration, lastValue);
+  } else {
+    const PRInt64& dur   = mSimpleDuration.GetMillis();
+
+    if (LL_CMP(mSimpleTime, >=, dur) || !LL_GE_ZERO(mSimpleTime)) {
+      NS_ERROR("Animation sampled outside interval.");
+      return;
+    }
+    
+    double  fTime;
+    double  fDur;
+    double  simpleDistance;
+    double  intervalDistance;
+    PRInt32 index;
+    nsISMILAnimVal* from = nsnull;
+    nsISMILAnimVal* to   = nsnull;
+
+    LL_L2D(fTime, mSimpleTime);
+    LL_L2D(fDur, dur);
+
+    NS_ASSERTION(mValues.Count() >= 2 || IsToAnimation(),
+        "Unexpected number of values.");
+
+    simpleDistance = (fDur > 0.0) ? fTime / fDur : 0.0;
+
+    if (IsToAnimation()) {
+      from = &aResult;
+      to = mValues.SafeObjectAt(0);
+      intervalDistance = simpleDistance;
+    } else {
+      index = (PRInt32) floor(simpleDistance * (mValues.Count() - 1));
+
+      from = mValues.SafeObjectAt(index);
+      NS_ENSURE_TRUE(from,);
+
+      to = mValues.SafeObjectAt(index + 1);
+      NS_ENSURE_TRUE(to,);
+
+      intervalDistance = simpleDistance * (mValues.Count() - 1) - index;
+    }
+
+    nsresult rv = from->Interpolate(*to,
+                                    NS_STATIC_CAST(float, intervalDistance),
+                                    *result);
+    NS_ENSURE_SUCCESS(rv,);
+  }
+
+  /*
+   * If additive animation isn't required or fails, just set the value.
+   */
+  if (!IsAdditive() || !aResult.Add(*result))
+    aResult.Set(*result);
+}
+
+PRInt8
+nsSMILAnimationFunction::CompareTo(const nsISMILComposable& composable) const
+{
+  /*
+   * Inactive animations sort first
+   */
+  if (!IsActive())
+    return -1;
+
+  if (!composable.IsActive())
+    return 1;
+  
+  /*
+   * To animations sort last
+   */
+  if (!IsToAnimation() && composable.IsToAnimation())
+    return -1;
+
+  if (IsToAnimation() && !composable.IsToAnimation())
+    return 1;
+
+  /*
+   * We sort using the same rules if both animations are 'to animations' or both
+   * animations are not 'to animations'.
+   */
+  if (LL_NE(mBeginTime, composable.GetBeginTime()))
+    return LL_CMP(mBeginTime, >, composable.GetBeginTime()) ? 1 : -1;
+
+  // XXX When syncbase timing is implemented, we next need to sort based on
+  // dependencies
+
+  /*
+   * Animations that appear later in the document sort after those earlier in
+   * the document
+   */
+  /*
+   * Disabled for now until we implement the document traversal
+  NS_ASSERTION(mDocumentPosition != composable.GetDocumentPosition(),
+      "Two animations cannot have the same document position!");
+   */
+
+  return (mDocumentPosition <= composable.GetDocumentPosition()) ? -1 : 1;
+}
+
+PRBool
+nsSMILAnimationFunction::IsToAnimation() const
+{
+  return (!mValuesIsSet && mTo && !mFrom);
+}
+
+const PRInt64&
+nsSMILAnimationFunction::GetBeginTime() const
+{
+  return mBeginTime;
+}
+
+PRUint16
+nsSMILAnimationFunction::GetDocumentPosition() const
+{
+  return mDocumentPosition;
+}
+
+PRBool
+nsSMILAnimationFunction::IsActive() const
+{
+  /*
+   * Even if an animation should be active, if its attributes are set
+   * incorrectly, it will have no effect and should be considered by the
+   * compositor to be inactive.
+   */
+  return (mIsActive && mValues.Count() > 0);
+}
+
+
+PRBool
+nsSMILAnimationFunction::WillReplace() const
+{
+  return !IsAdditive();
+}
+
+//----------------------------------------------------------------------
+// Implementation helpers
+
+/*
+ * SMILANIM specifies the following rules for animation function values:
+ *
+ * (1) if values is set, it overrides everything
+ * (2) for from/to/by animation at least to or by must be specified, from on its
+ *     own (or nothing) is an error--which we will ignore
+ * (3) if both by and to are specified only to will be used, by will be ignored
+ * (4) if by is specified without from (by animation), forces additive behaviour
+ * (5) if to is specified without from (to animation), special care needs to be
+ *     taken when compositing animation as such animations are composited last.
+ *
+ * This helper method applies these rules to fill in the values list and to set
+ * some internal state.
+ */
+void
+nsSMILAnimationFunction::FillValuesArray()
+{
+  if (!mValuesIsSet) {
+    mValues.Clear();
+
+    if (mTo) {
+      if (mFrom) {
+        mValues.AppendObject(mFrom);
+        mValues.AppendObject(mTo);
+      } else {
+        mValues.AppendObject(mTo);
+      }
+    } else if (mBy) {
+      if (mFrom) {
+        /*
+         * Set values to 'from; from + to'
+         */
+        mValues.AppendObject(mFrom);
+        nsCOMPtr<nsISMILAnimVal> to;
+        if (NS_SUCCEEDED(mAttribute->Create(getter_AddRefs(to)))) {
+          to->Set(*mFrom);
+          to->Add(*mBy);
+          mValues.AppendObject(to);
+        } else {
+          mValues.Clear();
+        }
+      } else {
+        /*
+         * Set values to '0; by'
+         */
+        nsCOMPtr<nsISMILAnimVal> from;
+        if (NS_SUCCEEDED(mAttribute->Create(getter_AddRefs(from)))) {
+          mValues.AppendObject(from);
+          mValues.AppendObject(mBy);
+        } else {
+          mValues.Clear();
+        }
+      }
+    }
+    /* else, do nothing, mValues has been cleared already. */
+  }
+}
+
+inline PRBool
+nsSMILAnimationFunction::IsAdditive() const
+{
+  /*
+   * Animation is additive if:
+   *
+   * (1) additive = "sum" (mAdditive == true), or
+   * (2) it is 'by animation' (by is set, from and values are not)
+   *
+   * Although animation is not additive if it is 'to animation'
+   */
+  return (!IsToAnimation() && (mAdditive || (!mValuesIsSet && mBy && !mFrom)));
+}
+
Index: /cvsroot/mozilla/content/smil/src/nsSMILAnimationRegistry.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILAnimationRegistry.cpp
diff -N content/smil/src/nsSMILAnimationRegistry.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILAnimationRegistry.cpp	14 Sep 2005 10:44:06 -0000
@@ -0,0 +1,273 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSMILAnimationRegistry.h"
+#include "nsISMILAnimationController.h"
+#include "nsISMILAnimAttr.h"
+#include "nsSMILTimedDocumentRoot.h"
+#include "nsISMILComposable.h"
+
+////////////////////////////////////////////////////////////////////////
+// nsSMILAnimationRegistry implementation
+
+struct CompositorEntry
+{
+  nsISMILAnimAttr*  key;
+  nsSMILCompositor  compositor;
+};
+
+//----------------------------------------------------------------------
+// ctors, dtors, factory methods
+
+nsSMILAnimationRegistry::nsSMILAnimationRegistry()
+{
+}
+
+nsSMILAnimationRegistry::~nsSMILAnimationRegistry()
+{
+  if (mController && mTimedDocumentRoot)
+    mController->RemoveTimeContainer(mTimedDocumentRoot);
+
+  CompositorEntry*    entry;
+  PRInt32             count = mCompositors.Count();
+
+  for (PRInt32 i = 0; i < count; ++i)
+  {
+    entry = NS_STATIC_CAST(CompositorEntry*, mCompositors[i]);
+    mCompositors.ReplaceElementAt(nsnull, i);
+    delete entry;
+  }
+
+  mCompositors.Clear();
+}
+
+nsISMILAnimationRegistry*
+NS_NewSMILAnimationRegistry()
+{
+  nsSMILAnimationRegistry* animationRegistry = new nsSMILAnimationRegistry();
+
+  if (animationRegistry)
+  {
+    nsresult rv = animationRegistry->Init();
+    if (NS_FAILED(rv))
+    {
+      delete animationRegistry;
+      animationRegistry = nsnull;
+    }
+  }
+
+  return animationRegistry;
+}
+
+nsresult
+nsSMILAnimationRegistry::Init()
+{
+  mTimedDocumentRoot = new nsSMILTimedDocumentRoot(this);
+  NS_ENSURE_TRUE(mTimedDocumentRoot, NS_ERROR_OUT_OF_MEMORY);
+
+  return NS_OK;
+}
+
+//----------------------------------------------------------------------
+// nsISupports methods:
+
+NS_IMPL_ISUPPORTS1(nsSMILAnimationRegistry,
+                   nsISMILAnimationRegistry);
+
+//----------------------------------------------------------------------
+// nsISMILAnimationRegistry methods:
+
+nsresult
+nsSMILAnimationRegistry::SetController(nsISMILAnimationController* aController)
+{
+  nsresult rv = NS_OK;
+
+  if (mController)
+  {
+    rv = mController->RemoveTimeContainer(mTimedDocumentRoot);
+    NS_ENSURE_SUCCESS(rv,rv);
+  }
+
+  mController = aController;
+
+  if (mController && mTimedDocumentRoot)
+    rv = mController->AddTimeContainer(mTimedDocumentRoot);
+
+  return rv;
+}
+
+void
+nsSMILAnimationRegistry::Pause()
+{
+  // TODO[3]
+}
+
+void
+nsSMILAnimationRegistry::Unpause()
+{
+  // TODO[3]
+}
+
+PRBool
+nsSMILAnimationRegistry::IsPaused()
+{
+  // TODO[3]
+  return false;
+}
+
+float
+nsSMILAnimationRegistry::GetCurrentTime()
+{
+  return 0.0f;
+}
+
+nsresult
+nsSMILAnimationRegistry::SetCurrentTime(float aSeconds)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+nsSMILAnimationRegistry::RegisterComposable(nsISMILAnimAttr* aTargetAttr,
+                                            nsISMILComposable* aComposable)
+{
+  NS_ENSURE_ARG_POINTER(aTargetAttr);
+  NS_ENSURE_ARG_POINTER(aComposable);
+
+  nsSMILCompositor*   compositor = nsnull;
+  CompositorEntry*    entry;
+
+  /*
+   * Iterate in reverse as if a compositor already exists for this attribute it
+   * is most likely to be the most recently added entry.
+   */
+  for (PRInt32 i = mCompositors.Count() - 1; i >= 0 && !compositor; --i)
+  {
+    entry = (CompositorEntry*)mCompositors[i];
+    if (entry && entry->key == aTargetAttr)
+      compositor = &entry->compositor;
+  }
+
+  if (!compositor)
+  {
+    entry = new CompositorEntry();
+    NS_ENSURE_TRUE(entry,NS_ERROR_OUT_OF_MEMORY);
+
+    nsresult rv = entry->compositor.Init(aTargetAttr);
+    NS_ENSURE_SUCCESS(rv,rv);
+
+    entry->key = aTargetAttr;
+    if (!mCompositors.AppendElement(entry))
+    {
+      delete entry;
+      return NS_ERROR_FAILURE;
+    }
+
+    compositor = &entry->compositor;
+  }
+
+  return compositor->AddComposable(aComposable);
+}
+
+nsresult
+nsSMILAnimationRegistry::UnregisterComposable(nsISMILComposable* aComposable)
+{
+  NS_ENSURE_ARG_POINTER(aComposable);
+
+  PRBool              found = PR_FALSE;
+  nsresult            result = NS_OK;
+  nsresult            rv = NS_ERROR_FAILURE;
+  nsSMILCompositor*   compositor = nsnull;
+  CompositorEntry*    entry;
+  PRInt32             count = mCompositors.Count();
+
+  for (PRInt32 i = 0; i < count; ++i)
+  {
+    entry = (CompositorEntry*)mCompositors[i];
+    if (entry)
+    {
+      rv = entry->compositor.RemoveComposable(aComposable);
+
+      /*
+       * This rather complicated error handling just ensures that we report the
+       * first error that occurs, or a generic error if the item wasn't found.
+       */
+      if (NS_SUCCEEDED(result))
+        result = rv;
+      found = PR_TRUE;
+    }
+
+    /*
+     * Even if the entry now no longer has any compositors we don't bother
+     * deleting it. After all, it may be re-used again later.
+     */
+  }
+
+  return (found) ? rv : NS_ERROR_FAILURE;
+}
+
+nsresult
+nsSMILAnimationRegistry::RegisterTimedElement(nsISMILTimedElement *aElement)
+{
+  return (mTimedDocumentRoot) ? mTimedDocumentRoot->AddTimedElement(aElement)
+                              : NS_ERROR_FAILURE;
+}
+
+nsresult
+nsSMILAnimationRegistry::UnregisterTimedElement(nsISMILTimedElement *aElement)
+{
+  return (mTimedDocumentRoot) ? mTimedDocumentRoot->RemoveTimedElement(aElement)
+                              : NS_ERROR_FAILURE;
+}
+
+void
+nsSMILAnimationRegistry::StartSample()
+{
+  // TODO[2]: Suspend redraw
+}
+
+void
+nsSMILAnimationRegistry::EndSample()
+{
+  CompositorEntry*    entry;
+  PRInt32             count = mCompositors.Count();
+
+  for (PRInt32 i = 0; i < count; ++i)
+  {
+    entry = NS_STATIC_CAST(CompositorEntry*, mCompositors[i]);
+    entry->compositor.ComposeSample();
+  }
+
+  // TODO[2]: Unsuspend redraw
+}
+
Index: /cvsroot/mozilla/content/smil/src/nsSMILAnimationRegistry.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILAnimationRegistry.h
diff -N content/smil/src/nsSMILAnimationRegistry.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILAnimationRegistry.h	14 Sep 2005 10:44:06 -0000
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_SMILANIMATIONREGISTRY_H__
+#define __NS_SMILANIMATIONREGISTRY_H__
+
+#include "nsISMILAnimationRegistry.h"
+#include "nsSMILCompositor.h"
+#include "nsVoidArray.h"
+#include "nsAutoPtr.h"
+
+class nsSMILTimedDocumentRoot;
+class nsISMILAnimAttr;
+class nsISMILAnimationController;
+class nsISMILComposable;
+
+class nsSMILAnimationRegistry : public nsISMILAnimationRegistry
+{
+public:
+  nsSMILAnimationRegistry();
+  ~nsSMILAnimationRegistry();
+
+  NS_DECL_ISUPPORTS
+
+  virtual void      StartSample();
+  virtual void      EndSample();
+
+  // nsISMILAnimationRegistry
+  virtual nsresult  SetController(nsISMILAnimationController* aController);
+  virtual void      Pause();
+  virtual void      Unpause();
+  virtual PRBool    IsPaused();
+  virtual float     GetCurrentTime();
+  virtual nsresult  SetCurrentTime(float aSeconds);
+  virtual nsresult  RegisterComposable(nsISMILAnimAttr *aTargetAttr,
+                                       nsISMILComposable *aComposable);
+  virtual nsresult  UnregisterComposable(nsISMILComposable *aComposable);
+  virtual nsresult  RegisterTimedElement(nsISMILTimedElement *aElement);
+  virtual nsresult  UnregisterTimedElement(nsISMILTimedElement *aElement);
+
+protected:
+  friend nsISMILAnimationRegistry* NS_NewSMILAnimationRegistry();
+
+  nsresult          Init();
+
+  nsVoidArray                           mCompositors;
+  nsRefPtr<nsSMILTimedDocumentRoot>     mTimedDocumentRoot;
+  nsCOMPtr<nsISMILAnimationController>  mController;
+};
+
+#endif // __NS_SMILANIMATIONREGISTRY_H__
+
Index: /cvsroot/mozilla/content/smil/src/nsSMILCompositor.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILCompositor.cpp
diff -N content/smil/src/nsSMILCompositor.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILCompositor.cpp	14 Sep 2005 10:44:08 -0000
@@ -0,0 +1,168 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSMILCompositor.h"
+#include "nsISMILComposable.h"
+#include "nsISimpleEnumerator.h"
+#include "nsArrayEnumerator.h"
+#include "nsISMILAnimAttr.h"
+#include "nsISMILAnimVal.h"
+
+////////////////////////////////////////////////////////////////////////
+// nsSMILCompositor implementation
+
+nsresult
+nsSMILCompositor::Init(nsISMILAnimAttr* aTargetAttribute)
+{
+  NS_ENSURE_ARG_POINTER(aTargetAttribute);
+
+  nsresult rv;
+  mTargetAttribute = do_GetWeakReference(aTargetAttribute, &rv);
+  if (NS_FAILED(rv))
+  {
+    mTargetAttribute = nsnull;
+    return rv;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+nsSMILCompositor::AddComposable(nsISMILComposable* aComposable)
+{
+  NS_ENSURE_ARG_POINTER(aComposable);
+
+  nsresult rv;
+  nsCOMPtr<nsIWeakReference> weakRef(
+      getter_AddRefs(do_GetWeakReference(aComposable, &rv)) );
+
+  if (NS_SUCCEEDED(rv))
+    rv = (mChildren.AppendObject(weakRef)) ? NS_OK : NS_ERROR_FAILURE;
+
+  return rv;
+}
+
+nsresult
+nsSMILCompositor::RemoveComposable(nsISMILComposable* aComposable)
+{
+  NS_ENSURE_ARG_POINTER(aComposable);
+
+  nsresult rv;
+  nsCOMPtr<nsIWeakReference> weakRef(
+      getter_AddRefs(do_GetWeakReference(aComposable, &rv)) );
+
+  if (NS_SUCCEEDED(rv))
+    rv = (mChildren.RemoveObject(weakRef)) ? NS_OK : NS_ERROR_FAILURE;
+
+  return rv;
+}
+
+void
+nsSMILCompositor::ComposeSample()
+{
+  NS_ASSERTION(mTargetAttribute, "Target attribute not set on compositor.");
+
+  if (!mTargetAttribute)
+    return;
+
+  nsCOMPtr<nsISMILAnimAttr> targetAttribute( 
+      do_QueryReferent(mTargetAttribute) );
+
+  if (!targetAttribute)
+    return;
+
+  nsCOMPtr<nsISMILAnimVal> result( CopyBaseValue(targetAttribute) );
+  if (!result)
+    return;
+
+  mChildren.Sort(SortCompositors, nsnull);
+
+  nsCOMPtr<nsISimpleEnumerator> enumerator;
+  nsresult rv = 
+    NS_NewArrayEnumerator(getter_AddRefs(enumerator), mChildren);
+  NS_ENSURE_SUCCESS(rv,);
+
+  PRBool more = PR_FALSE;
+  nsCOMPtr<nsISMILComposable> composable;
+  nsCOMPtr<nsIWeakReference> weakRef;
+
+  while (NS_SUCCEEDED(enumerator->HasMoreElements(&more)) && more)
+  {
+    if (NS_FAILED(enumerator->GetNext(getter_AddRefs(weakRef))) || !weakRef)
+      break;
+
+    composable = do_QueryReferent(weakRef);
+
+    if (composable)
+    {
+      composable->ComposeResult(*result);
+    }
+  }
+  
+  // We can't just call Set on the animated value itself, because the observers
+  // of the animated object as a whole need to be updated too.
+  targetAttribute->SetAnimValue(*result);
+}
+
+//----------------------------------------------------------------------
+// Implementation helpers
+
+PR_CALLBACK int
+nsSMILCompositor::SortCompositors(nsIWeakReference *aRef1,
+                                  nsIWeakReference *aRef2,
+                                  void* aData)      
+{
+  nsCOMPtr<nsISMILComposable> a = do_QueryReferent(aRef1);
+  nsCOMPtr<nsISMILComposable> b = do_QueryReferent(aRef2);
+
+  return (a && b) ? a->CompareTo(*b) : -1;
+}
+
+nsISMILAnimVal*
+nsSMILCompositor::CopyBaseValue(nsISMILAnimAttr* aTargetAttribute)
+{
+  nsISMILAnimVal* baseValueCopy;
+
+  nsCOMPtr<nsISMILAnimVal> baseVal( aTargetAttribute->GetBaseValue() );
+  if (!baseVal)
+    return nsnull;
+
+  aTargetAttribute->Create(&baseValueCopy);
+  if (!baseValueCopy)
+    return nsnull;
+
+  baseValueCopy->Set(*baseVal);
+
+  return baseValueCopy;
+}
+
Index: /cvsroot/mozilla/content/smil/src/nsSMILCompositor.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILCompositor.h
diff -N content/smil/src/nsSMILCompositor.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILCompositor.h	14 Sep 2005 10:44:08 -0000
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_SMILCOMPOSITOR_H__
+#define __NS_SMILCOMPOSITOR_H__
+
+#include "nsCOMArray.h"
+#include "nsWeakReference.h"
+
+////////////////////////////////////////////////////////////////////////
+// nsSMILCompositor: Collection of animation compositors
+
+class nsISMILComposable;
+class nsISMILAnimAttr;
+class nsISMILAnimVal;
+
+class nsSMILCompositor
+{
+public:
+  nsresult  Init(nsISMILAnimAttr* aTargetAttribute);
+
+  nsresult  AddComposable(nsISMILComposable* aComposable);
+  nsresult  RemoveComposable(nsISMILComposable* aComposable);
+  void      ComposeSample();
+
+protected:
+  PR_STATIC_CALLBACK(int) SortCompositors(nsIWeakReference* aRef1,
+                                          nsIWeakReference* aRef2,
+                                          void* aData);
+
+  nsISMILAnimVal* CopyBaseValue(nsISMILAnimAttr* aTargetAttribute);
+
+  nsCOMArray<nsIWeakReference>   mChildren;
+  nsWeakPtr                      mTargetAttribute;
+};
+
+#endif // __NS_SMILCOMPOSITOR_H__
+
Index: /cvsroot/mozilla/content/smil/src/nsSMILInstanceTime.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILInstanceTime.cpp
diff -N content/smil/src/nsSMILInstanceTime.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILInstanceTime.cpp	14 Sep 2005 10:44:08 -0000
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSMILInstanceTime.h"
+#include "nsSMILTimeValueSpec.h"
+#include "nsSMILTimeValue.h"
+
+//----------------------------------------------------------------------
+// Implementation
+
+nsSMILInstanceTime::nsSMILInstanceTime (const nsSMILTimeValue &aTime,
+                                        nsSMILTimeValueSpec *aCreator,
+                                        PRBool aClearOnReset /*=false*/)
+  : mTime(aTime), // Copy the time
+    mClearOnReset(aClearOnReset)
+{
+  if (aCreator)
+    mCreator = do_GetWeakReference(aCreator);
+}
+
+//----------------------------------------------------------------------
+// nsSMILInstanceTime
+
Index: /cvsroot/mozilla/content/smil/src/nsSMILInstanceTime.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILInstanceTime.h
diff -N content/smil/src/nsSMILInstanceTime.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILInstanceTime.h	14 Sep 2005 10:44:08 -0000
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_SMILINSTANCETIME_H__
+#define __NS_SMILINSTANCETIME_H__
+
+#include "nsSMILTimeValue.h"
+#include "nsWeakReference.h"
+
+class nsSMILTimeValueSpec;
+
+////////////////////////////////////////////////////////////////////////
+// nsSMILInstanceTime
+
+class nsSMILInstanceTime
+{
+public:
+  nsSMILInstanceTime (const nsSMILTimeValue &aTime,
+                      nsSMILTimeValueSpec *aCreator,
+                      PRBool aClearOnReset = false);
+
+  const nsSMILTimeValue&  Time() const { return mTime; }
+
+  PRBool                  ClearOnReset() const { return mClearOnReset; }
+
+  // dependent update
+  
+  nsrefcnt    AddRef() { return ++mRefCnt; }
+  nsrefcnt    Release();
+
+protected:
+  nsSMILTimeValue     mTime;
+  nsWeakPtr           mCreator;
+
+  /**
+   * Should this instance time be removed when the owning timed element is rest.
+   * True for events and DOM calls.
+   */
+  PRBool              mClearOnReset;
+
+  /*
+   * This will only be used for for identifying the instance times associated
+   * with a deleting interval. We will never de-reference this pointer, but only
+   * use it for pointer comparisons. Therefore it's not necessary for instances
+   * of nsSMILInterval to be reference-counted.
+   *
+   * nsSMILInterval   *mTimebase
+   */
+
+  nsAutoRefCnt        mRefCnt;
+};
+
+inline nsrefcnt
+nsSMILInstanceTime::Release()
+{
+  if (--mRefCnt == 0)
+  {
+    delete this;
+    return 0;
+  }
+
+  return mRefCnt;
+}
+
+#endif // __NS_SMILINSTANCETIME_H__
+
Index: /cvsroot/mozilla/content/smil/src/nsSMILInterval.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILInterval.cpp
diff -N content/smil/src/nsSMILInterval.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILInterval.cpp	14 Sep 2005 10:44:09 -0000
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSMILInterval.h"
+
+nsSMILInterval::nsSMILInterval(const nsSMILTimeValue& aBegin,
+                               const nsSMILTimeValue& aEnd)
+: mBegin(aBegin),
+  mEnd(aEnd)
+{
+}
+
+//----------------------------------------------------------------------
+// Implementation
+
+PRBool
+nsSMILInterval::Recalc(const nsVoidArray& aBeginTimes,
+                       const nsVoidArray& aEndTimes,
+                       PRBool aHasEnds,
+                       const nsSMILTimeValue& min,
+                       const nsSMILTimeValue& max)
+{
+  // TODO[2]
+  return PR_TRUE;
+}
+
Index: /cvsroot/mozilla/content/smil/src/nsSMILInterval.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILInterval.h
diff -N content/smil/src/nsSMILInterval.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILInterval.h	14 Sep 2005 10:44:09 -0000
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_SMILINTERVAL_H__
+#define __NS_SMILINTERVAL_H__
+
+#include "nsSMILTimeValue.h"
+
+////////////////////////////////////////////////////////////////////////
+// nsSMILInterval class
+
+class nsVoidArray;
+
+class nsSMILInterval
+{
+public:
+  nsSMILInterval() {}
+
+  nsSMILInterval(const nsSMILTimeValue& aBegin,
+                 const nsSMILTimeValue& aEnd);
+
+  const nsSMILTimeValue& Begin() { return mBegin; }
+  const nsSMILTimeValue& End() { return mEnd; }
+
+  PRBool Recalc(const nsVoidArray& aBeginTimes,
+                const nsVoidArray& aEndTimes,
+                PRBool aHasEnds,
+                const nsSMILTimeValue& min,
+                const nsSMILTimeValue& max);
+
+protected:
+  nsSMILTimeValue   mBegin;
+  nsSMILTimeValue   mEnd;
+};
+
+#endif // __NS_SMILINTERVAL_H__
Index: /cvsroot/mozilla/content/smil/src/nsSMILTimeValue.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILTimeValue.cpp
diff -N content/smil/src/nsSMILTimeValue.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILTimeValue.cpp	14 Sep 2005 10:44:09 -0000
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSMILTimeValue.h"
+#include "nsDebug.h"
+
+PRInt64 nsSMILTimeValue::mUnresolvedSeconds = LL_MaxInt();
+
+//----------------------------------------------------------------------
+// Implementation
+
+// Default constructor creates an unresolved time
+nsSMILTimeValue::nsSMILTimeValue()
+  : mMilliseconds(LL_MaxInt()),
+    mIndefinite(PR_FALSE),
+    mResolved(PR_FALSE)
+{}
+
+//----------------------------------------------------------------------
+// nsSMILTimeValue methods:
+
+// TODO[3]: Profile and move the most accessed methods inline
+
+PRBool
+nsSMILTimeValue::IsIndefinite() const
+{
+  return mIndefinite;
+}
+
+void
+nsSMILTimeValue::SetIndefinite()
+{
+  mResolved = PR_FALSE;
+  mIndefinite = PR_TRUE;
+  mMilliseconds = LL_MaxInt();
+}
+
+PRBool
+nsSMILTimeValue::IsResolved() const
+{
+  return mResolved;
+}
+
+void
+nsSMILTimeValue::SetUnresolved()
+{
+  mResolved = PR_FALSE;
+  mIndefinite = PR_FALSE;
+  mMilliseconds = LL_MaxInt();
+}
+
+const PRInt64&
+nsSMILTimeValue::GetMillis() const
+{
+  NS_ASSERTION(mResolved, "GetMillis() called for unresolved time.");
+
+  if (!mResolved)
+      return mUnresolvedSeconds;
+
+  return mMilliseconds;
+}
+
+void
+nsSMILTimeValue::SetMillis(const PRInt64& aMillis)
+{
+  mResolved = PR_TRUE;
+  mIndefinite = PR_FALSE;
+  mMilliseconds = aMillis;
+}
+
+PRInt8
+nsSMILTimeValue::CompareTo(const nsSMILTimeValue& aCompare) const
+{
+  PRInt8 result;
+
+  if (mResolved)
+  {
+    result = (aCompare.mResolved)
+           ? CmpLL(mMilliseconds, aCompare.mMilliseconds)
+           : -1;
+  }
+  else if (mIndefinite)
+  {
+    if (aCompare.mResolved)
+      result = 1;
+    else if (aCompare.mIndefinite)
+      result = 0;
+    else
+      result = -1;
+  }
+  else
+  {
+    result = (aCompare.mResolved || aCompare.mIndefinite) ? 1 : 0;
+  }
+
+  return result;
+}
+
+PR_CALLBACK int
+nsSMILTimeValue::ComparisonCallback(const void *aElement1,
+                                    const void *aElement2,
+                                    void* aData)      
+{
+  return NS_STATIC_CAST(const nsSMILTimeValue*, aElement1)->CompareTo
+       (*NS_STATIC_CAST(const nsSMILTimeValue*, aElement2));
+}
+
Index: /cvsroot/mozilla/content/smil/src/nsSMILTimeValue.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILTimeValue.h
diff -N content/smil/src/nsSMILTimeValue.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILTimeValue.h	14 Sep 2005 10:44:09 -0000
@@ -0,0 +1,115 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_SMILTIMEVALUE_H__
+#define __NS_SMILTIMEVALUE_H__
+
+#include "prtypes.h"
+#include "prlong.h"
+
+/*
+ * nsSMILTimeValue class
+ *
+ * This class considers three orthogonal cases:
+ *
+ * 1) The time is resolved and has a millisecond value
+ * 2) The time is indefinite
+ * 3) The time in unresolved
+ *
+ * There is considerable chance for confusion with regards to the indefinite
+ * state. Is it resolved? We adopt the convention that it is NOT resolved (but
+ * nor is it unresolved). This simplifies implementation as you can then write:
+ *
+ * if (time.IsResolved())
+ *    x = time.GetMillis()
+ *
+ * instead of:
+ *
+ * if (time.IsResolved() && !time.IsIndefinite())
+ *    x = time.GetMillis()
+ *
+ * Testing if a time is unresolved becomes more complicated but this is tested
+ * much less often.
+ *
+ * In summary:
+ *
+ * State         |  GetMillis   |   IsResolved       |  IsIndefinite
+ * --------------+--------------------+--------------------+-------------------
+ * Resolved      |  The millisecond   |  PR_TRUE           |  PR_FALSE
+ *               |  time              |                    |
+ * --------------+--------------------+--------------------+-------------------
+ * Indefinite    |  LL_MaxInt         |  PR_FALSE          |  PR_TRUE
+ * --------------+--------------------+--------------------+-------------------
+ * Unresolved    |  LL_MaxInt         |  PR_FALSE          |  PR_FALSE
+ *
+ */
+
+class nsSMILTimeValue
+{
+public:
+  // Creates an unresolved time value
+  nsSMILTimeValue();
+
+  PRBool            IsIndefinite() const;
+  void              SetIndefinite();
+
+  PRBool            IsResolved() const;
+  void              SetUnresolved();
+
+  const PRInt64&    GetMillis() const;
+  void              SetMillis(const PRInt64& aMillis);
+
+  PRInt8            CompareTo(const nsSMILTimeValue& aCompare) const;
+
+  PR_STATIC_CALLBACK(int) ComparisonCallback(const void *aElement1,
+                                             const void *aElement2,
+                                             void* aData);
+
+private:
+  PRInt8            CmpLL(const PRInt64& a, const PRInt64& b) const;
+
+  static PRInt64    mUnresolvedSeconds;
+
+  PRInt64           mMilliseconds;
+  PRBool            mIndefinite;
+  PRBool            mResolved;
+};
+
+// A signed comparison of two signed 64-bit integers
+inline PRInt8
+nsSMILTimeValue::CmpLL(const PRInt64& a, const PRInt64& b) const
+{
+  return (LL_EQ(a, b)) ? 0 : (LL_CMP(a, >, b)) ? 1 : -1;
+}
+
+#endif // __NS_SMILTIMEVALUE_H__
Index: /cvsroot/mozilla/content/smil/src/nsSMILTimeValueSpec.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILTimeValueSpec.cpp
diff -N content/smil/src/nsSMILTimeValueSpec.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILTimeValueSpec.cpp	14 Sep 2005 10:44:10 -0000
@@ -0,0 +1,443 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSMILTimeValueSpec.h"
+#include "nsSMILTimeValue.h"
+#include "nsSMILInstanceTime.h"
+#include "nsAutoPtr.h"
+#include "nsCRT.h"
+#include "prdtoa.h"
+
+const PRUint32 nsSMILTimeValueSpec::MSEC_PER_SEC   = 1000;
+const PRUint32 nsSMILTimeValueSpec::MSEC_PER_MIN   = 1000 * 60;
+const PRUint32 nsSMILTimeValueSpec::MSEC_PER_HOUR  = 1000 * 60 * 60;
+
+//----------------------------------------------------------------------
+// Implementation
+
+// We can't return a raw pointer here because we call SetSpec, which calls
+// getWeakReference on the newly created value spec which will cause it to be
+// destroyed unless it is addref'ed first.
+
+nsresult NS_NewSMILTimeValueSpec(nsISMILTimedElement* aOwner,
+                                 PRBool aIsBegin,
+                                 const nsAString& aStringSpec,
+                                 nsSMILTimeValueSpec** aResult)
+{
+  if (nsnull == aResult) return NS_ERROR_NULL_POINTER;
+
+  *aResult = nsnull;
+
+  nsSMILTimeValueSpec* valueSpec = new nsSMILTimeValueSpec(aOwner, aIsBegin);
+
+  if (!valueSpec) return NS_ERROR_OUT_OF_MEMORY;
+  NS_ADDREF(valueSpec);
+
+  nsresult rv = valueSpec->SetSpec(aStringSpec);
+
+  if (NS_FAILED(rv))
+  {
+    NS_RELEASE(valueSpec);
+    return rv;
+  }
+
+  *aResult = valueSpec;
+
+  return NS_OK;
+}
+
+nsSMILTimeValueSpec::nsSMILTimeValueSpec(nsISMILTimedElement* aOwner,
+                                         PRBool aIsBegin)
+  : mIsBegin(aIsBegin),
+    mOffset() // initalises to zero
+{
+  if (aOwner)
+    mOwner = do_GetWeakReference(aOwner);
+}
+
+//----------------------------------------------------------------------
+// nsISupports
+
+NS_IMPL_ISUPPORTS2(nsSMILTimeValueSpec,
+                   nsSMILTimeValueSpec,
+                   nsISupportsWeakReference)
+
+//----------------------------------------------------------------------
+// nsSMILTimeValueSpec
+
+nsresult
+nsSMILTimeValueSpec::SetSpec(const nsAString& aStringSpec)
+{
+  // TODO[2]: Parse other specifiers
+  nsSMILTimeValue clockTime;
+  nsresult rv = ParseClockValue(aStringSpec,
+                                &clockTime,
+                                true,  // allow + or -
+                                true); // allow 'indefinite'
+
+  if (NS_FAILED(rv) || (!clockTime.IsResolved() && !clockTime.IsIndefinite()))
+    return NS_ERROR_FAILURE;
+  
+  if (clockTime.IsResolved())
+    mOffset = clockTime.GetMillis();
+  
+  if (mOwner)
+  {
+    nsRefPtr<nsSMILInstanceTime> instance = 
+      new nsSMILInstanceTime(clockTime, this);
+
+    nsCOMPtr<nsISMILTimedElement> owner = do_QueryReferent(mOwner);
+    if (owner)
+      owner->AddInstanceTime(instance, mIsBegin);
+    else
+      rv = NS_ERROR_FAILURE;
+  }
+
+  return rv;
+}
+
+// This method can actually parse more than a clock value as defined in the
+// SMIL Animation specification. It can also parse:
+//  - the + or - before an offset
+//  - the special value "indefinite"
+//  - the special value "media"
+//
+// Because the value "media" cannot be represented as part of an nsSMILTimeValue
+// and has different meanings depending on where it is used, it is passed out as
+// a separate parameter (which can be set to null if the media attribute is not
+// allowed).
+//
+// aResult may be NULL, e.g. to check if the string is a valid clock value
+nsresult
+nsSMILTimeValueSpec::ParseClockValue(const nsAString& aStringSpec,
+                                     nsSMILTimeValue* aResult, 
+                                     PRBool aAllowSign,       // = false
+                                     PRBool aAllowIndefinite, // = false
+                                     PRBool aAllowMedia,      // = false
+                                     PRBool* aIsMedia)        // = nsnull
+{
+  PRInt64 offset = LL_Zero();
+  PRFloat64 component = 0.0l;
+
+  PRInt8 sign = 0;
+  PRUint8 colonCount = 0;
+
+  PRBool started = PR_FALSE;
+  PRBool isValid = PR_TRUE;
+
+  PRInt32 metricMultiplicand = MSEC_PER_SEC;
+
+  PRBool numIsReal = PR_FALSE;
+  PRBool prevNumCouldBeMin = PR_FALSE;
+  PRBool numCouldBeMin = PR_FALSE;
+  PRBool numCouldBeSec = PR_FALSE;
+  PRBool isIndefinite = PR_FALSE;
+
+  char* spec; 
+  char* str = spec = ToNewCString(aStringSpec);
+
+  if (aIsMedia)
+    *aIsMedia = PR_FALSE;
+
+  while (*str)
+  {
+    if (IsSpace(*str))
+    {
+      if (started)
+      {
+        ++str;
+        break;
+      }
+      // else, we haven't started yet, ignore initial whitespace
+    }
+    else if (aAllowSign && (*str == '+' || *str == '-'))
+    {
+      if (sign != 0)
+      {
+        // sign has already been set
+        isValid = PR_FALSE;
+        break;
+      }
+
+      if (started)
+      {
+        // sign appears in the middle of the string
+        isValid = PR_FALSE;
+        break;
+      }
+
+      sign = (*str == '+') ? 1 : -1;
+    }
+    // The NS_IS_DIGIT etc. macros are not locale-specific
+    else if (NS_IS_DIGIT(*str))
+    {
+      char *end;
+
+      prevNumCouldBeMin = numCouldBeMin;
+
+      if (!GetClockComponent(str, &end, component, numIsReal, numCouldBeMin,
+                             numCouldBeSec))
+      {
+        isValid = PR_FALSE;
+        break;
+      }
+
+      started = PR_TRUE;
+      str = end - 1;
+    }
+    else if (*str == ':')
+    {
+      ++colonCount;
+
+      // Neither minutes nor hours can be reals
+      if (numIsReal)
+      {
+        isValid = PR_FALSE;
+        break;
+      }
+
+      // Clock value can't start with a ':'
+      if (!started)
+      {
+        isValid = PR_FALSE;
+        break;
+      }
+
+      // Can't have more than two colons
+      if (colonCount > 2)
+      {
+        isValid = PR_FALSE;
+        break;
+      }
+
+      // Multiply the offset by 60 and add the last accumulated component
+      PRInt64 component64;
+      LL_D2L(component64, component);
+      LL_MUL(offset, offset, LL_INIT(0,60));
+      LL_ADD(offset, offset, component64);
+
+      component = 0.0l;
+    }
+    else if (NS_IS_ALPHA(*str))
+    {
+      if (colonCount > 0)
+      {
+        isValid = PR_FALSE;
+        break;
+      }
+
+      char* end;
+      if (PL_strstr(str, "indefinite") == str && aAllowIndefinite)
+      {
+        // We set a separate flag because we don't know what the state of the
+        // passed in time value is and we shouldn't change it in the case of a
+        // bad input string (so we can't initialise it to 0ms for example).
+        isIndefinite = PR_TRUE;
+        if (aResult)
+          aResult->SetIndefinite();
+        end = str + PL_strlen("indefinite");
+      }
+      else if (PL_strstr(str, "media") == str && aAllowMedia)
+      {
+        if (aIsMedia)
+          *aIsMedia = PR_TRUE;
+        end = str + PL_strlen("media");
+      }
+      else if (!GetMetricMultiplicand(str, &end, metricMultiplicand))
+      {
+        isValid = PR_FALSE;
+        break;
+      }
+
+      str = end;
+
+      // Nothing must come after the string except whitespace
+      break;
+    }
+    else
+    {
+      isValid = PR_FALSE;
+      break;
+    }
+
+    ++str;
+  }
+
+  if (!started) isValid = PR_FALSE;
+
+  // Process remainder of string (if any) to ensure it is only trailing
+  // whitespace (embedded whitespace is not allowed)
+  while (*str && isValid)
+  {
+    if (!IsSpace(*str)) isValid = PR_FALSE;
+    ++str;
+  }
+
+  nsMemory::Free(spec);
+
+  // No more processing required if the value was "indefinite" or "media".
+  if (isIndefinite || (aIsMedia && *aIsMedia))
+    return NS_OK;
+
+  // If there is more than one colon then the previous component must be a
+  // correctly formatted minute (i.e. two digits between 00 and 59) and the
+  // latest component must be a correctly formatted second (i.e. two digits
+  // before the .)
+  if (colonCount > 0 && (!prevNumCouldBeMin || !numCouldBeSec))
+    isValid = PR_FALSE;
+
+  if (isValid)
+  {
+    // Tack on the last component
+    if (colonCount > 0)
+    {
+      LL_MUL(offset, offset, LL_INIT(0,60));
+      LL_MUL(offset, offset, LL_INIT(0,1000));
+      component *= 1000;
+      // rounding
+      component = (component >= 0) ? component + 0.5l : component - 0.5l;
+      PRInt64 component64;
+      LL_D2L(component64, component);
+      LL_ADD(offset, offset, component64);
+    }
+    else
+    {
+      component *= metricMultiplicand;
+      // rounding
+      component = (component >= 0) ? component + 0.5l : component - 0.5l;
+      LL_D2L(offset, component);
+    }
+
+    if (aResult)
+    {
+      PRInt64 millis = offset;
+
+      if (sign == -1)
+        LL_NEG(millis, offset);
+
+      aResult->SetMillis(millis);
+    }
+  }
+
+  return (isValid) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+// NS_IS_SPACE relies on isspace which may return true for \xB and \xC but
+// SMILANIM does not consider these characters to be whitespace.
+inline PRBool
+nsSMILTimeValueSpec::IsSpace(const char c)
+{
+  return (c == 0x9 || c == 0xA || c == 0xD || c == 0x20);
+}
+
+inline PRBool
+nsSMILTimeValueSpec::GetClockComponent(const char* aSrc,
+                                       char** aEnd,
+                                       PRFloat64& aResult,
+                                       PRBool& aIsReal,
+                                       PRBool& aCouldBeMin,
+                                       PRBool& aCouldBeSec)
+{
+  char *rest;
+  PRFloat64 value = PR_strtod(aSrc, &rest);
+
+  // Check a number was found
+  if (rest == aSrc)
+    return PR_FALSE;
+
+  // Check it's not expressed in exponential form
+  PRBool isExp = (PL_strnpbrk(aSrc, "eE", rest - aSrc) != nsnull);
+  if (isExp)
+    return PR_FALSE;
+
+  // Don't allow real numbers of the form "23."
+  if (*(rest - 1) == '.')
+    return PR_FALSE;
+
+  // Number looks good
+  aResult = value;
+  *aEnd = rest;
+
+  // Set some flags so we can check this number is valid once we know
+  // whether it's an hour, minute string etc.
+  aIsReal = (PL_strnchr(aSrc, '.', rest - aSrc) != nsnull);
+  aCouldBeMin = (value < 60.0l && ((rest - aSrc) == 2));
+  aCouldBeSec = (value < 60.0l ||
+      (value == 60.0l && aSrc[0] == '5')); // Take care of rounding error
+  aCouldBeSec &= (PL_strlen(aSrc) >= 2 &&
+      (aSrc[2] == '\0' || aSrc[2] == '.' || IsSpace(aSrc[2])));
+
+  return PR_TRUE;
+}
+
+inline PRBool
+nsSMILTimeValueSpec::GetMetricMultiplicand(char* aSrc,
+                                           char** aEnd,
+                                           PRInt32& multiplicand)
+{
+  nsresult result = PR_TRUE;
+  
+  switch (*aSrc)
+  {
+    case 'h':
+      *aEnd = aSrc + 1;
+      multiplicand = MSEC_PER_HOUR;
+      break;
+    case 'm':
+      if (aSrc[1] == 'i' && aSrc[2] == 'n')
+      {
+        *aEnd = aSrc + 3;
+        multiplicand = MSEC_PER_MIN;
+      }
+      else if (aSrc[1] == 's')
+      {
+        *aEnd = aSrc + 2;
+        multiplicand = 1;
+      }
+      else
+      {
+        result = PR_FALSE;
+      }
+      break;
+    case 's':
+      *aEnd = aSrc + 1;
+      multiplicand = MSEC_PER_SEC;
+      break;
+    default:
+      result = PR_FALSE;
+      break;
+  }
+
+  return result;
+}
+
Index: /cvsroot/mozilla/content/smil/src/nsSMILTimeValueSpec.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILTimeValueSpec.h
diff -N content/smil/src/nsSMILTimeValueSpec.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILTimeValueSpec.h	14 Sep 2005 10:44:10 -0000
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_SMILTIMEVALUESPEC_H__
+#define __NS_SMILTIMEVALUESPEC_H__
+
+#include "nsISupports.h"
+#include "nsString.h"
+#include "nsWeakReference.h"
+#include "nsISMILTimedElement.h"
+
+class nsSMILTimeValue;
+
+////////////////////////////////////////////////////////////////////////
+// nsSMILTimeValueSpec class
+
+// {39d2f376-6bda-42c0-8510-a93b24828a80}
+#define NS_SMILTIMEVALUESPEC_IID \
+{ 0x39d2f376, 0x6bda, 0x42c0, { 0x85, 0x10, 0xa9, 0x3b, 0x24, 0x82, 0x8a, 0x80 } }
+
+class nsSMILTimeValueSpec : public nsSupportsWeakReference
+{
+public:
+  NS_DEFINE_STATIC_IID_ACCESSOR(NS_SMILTIMEVALUESPEC_IID)
+  NS_DECL_ISUPPORTS
+
+  // Common parsing methods
+  static nsresult   ParseClockValue(const nsAString& aStringSpec,
+                                    nsSMILTimeValue* aResult, 
+                                    PRBool aAllowSign = false,
+                                    PRBool aAllowIndefinite = false,
+                                    PRBool aAllowMedia = false,
+                                    PRBool* aIsMedia = nsnull);
+
+protected:
+  nsSMILTimeValueSpec(nsISMILTimedElement* aOwner, PRBool aIsBegin);
+
+  friend nsresult NS_NewSMILTimeValueSpec(nsISMILTimedElement* aOwner,
+                                          PRBool aIsBegin,
+                                          const nsAString& aStringSpec,
+                                          nsSMILTimeValueSpec** aResult);
+
+  nsresult        SetSpec(const nsAString& aStringSpec);
+
+  static inline PRBool  IsSpace(const char c);
+  static inline PRBool  GetClockComponent(const char* aSrc,
+                                          char** aEnd,
+                                          PRFloat64& aResult,
+                                          PRBool& aIsReal,
+                                          PRBool& aCouldBeMin,
+                                          PRBool& aCouldBeSec);
+  static inline PRBool  GetMetricMultiplicand(char* aSrc,
+                                              char** aEnd,
+                                              PRInt32& multiplicand);
+
+
+  static const PRUint32 MSEC_PER_SEC;
+  static const PRUint32 MSEC_PER_MIN;
+  static const PRUint32 MSEC_PER_HOUR;
+
+  nsWeakPtr mOwner;
+  PRBool    mIsBegin;
+  PRInt64   mOffset;
+};
+
+////////////////////////////////////////////////////////////////////////
+// Factory methods
+
+nsresult NS_NewSMILTimeValueSpec(nsISMILTimedElement* aOwner,
+                                PRBool aIsBegin,
+                                const nsAString& aStringSpec,
+                                nsSMILTimeValueSpec** aResult);
+
+#endif // __NS_SMILTIMEVALUESPEC_H__
Index: /cvsroot/mozilla/content/smil/src/nsSMILTimedDocumentRoot.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILTimedDocumentRoot.cpp
diff -N content/smil/src/nsSMILTimedDocumentRoot.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILTimedDocumentRoot.cpp	14 Sep 2005 10:44:11 -0000
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSMILTimedDocumentRoot.h"
+#include "nsSMILTimeValue.h"
+
+////////////////////////////////////////////////////////////////////////
+// nsSMILTimedDocumentRoot implementation
+
+nsSMILTimedDocumentRoot::nsSMILTimedDocumentRoot(
+    nsSMILAnimationRegistry* registry)
+:
+  mStartTime(),
+  mAccumulatedOffset(),
+  mAnimationRegistry(registry)
+{
+}
+
+//----------------------------------------------------------------------
+// nsISupports methods:
+
+NS_IMPL_ISUPPORTS2(nsSMILTimedDocumentRoot,
+                   nsISMILTimeContainer,
+                   nsISupportsWeakReference);
+
+//----------------------------------------------------------------------
+// nsSMILTimedDocumentRoot methods
+
+nsSMILTimeValue
+nsSMILTimedDocumentRoot::WallclockToDocumentTime(nsISMILTimeValueSpec*
+                                                   aWallclockSpec)
+{
+  // TODO[2]
+  return nsSMILTimeValue();
+}
+
+nsresult
+nsSMILTimedDocumentRoot::SeekToTime(PRInt64 aSeekTo)
+{
+  // TODO[3]
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+//----------------------------------------------------------------------
+// nsISMILTimeContainer methods
+
+nsresult
+nsSMILTimedDocumentRoot::Pause()
+{
+  // TODO[2]
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+nsSMILTimedDocumentRoot::Resume()
+{
+  // TODO[2]
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+void
+nsSMILTimedDocumentRoot::Sample()
+{
+  /*
+   * It's probably more correct to use PRIntervalNow but I'm not sure if it
+   * will have sufficient range and it's unsigned.
+   */
+  PRInt64 now;
+  LL_DIV(now, PR_Now(), PR_USEC_PER_MSEC);
+
+  /*
+   * If this is the first time, record the document begin time
+   */
+  if (LL_IS_ZERO(mStartTime))
+    mStartTime = now;
+  
+  PRInt64 instant;
+  LL_SUB(instant, now, mStartTime);
+
+  if (mAnimationRegistry)
+    mAnimationRegistry->StartSample();
+
+  SampleChildren(instant);
+
+  if (mAnimationRegistry)
+    mAnimationRegistry->EndSample();
+}
+
+nsresult
+nsSMILTimedDocumentRoot::AddTimedElement(nsISMILTimedElement* aElement)
+{
+  if (!aElement)
+    return NS_ERROR_NULL_POINTER;
+
+  nsresult rv;
+  nsCOMPtr<nsIWeakReference> weakRef(
+      getter_AddRefs(do_GetWeakReference(aElement, &rv)) );
+
+  if (NS_SUCCEEDED(rv))
+    rv = (mTimedElements.AppendObject(weakRef)) ? NS_OK : NS_ERROR_FAILURE;
+
+  // TODO[1]: If the object already exists, don't freak out, it may have been
+  // removed from the tree and re-added between samples (objects are removed
+  // during each sample)
+
+  return rv;
+}
+
+nsresult
+nsSMILTimedDocumentRoot::RemoveTimedElement(nsISMILTimedElement* aElement)
+{
+  // TODO[2]
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+//----------------------------------------------------------------------
+// Implementation helpers:
+
+void
+nsSMILTimedDocumentRoot::SampleChildren(PRInt64 aDocumentTime)
+{
+  // TODO[f]: Replace with something thread-safe--probably a subclassed
+  // enumerator
+  PRUint32 i = mTimedElements.Count();
+  while (i > 0)
+  {
+    --i;
+    nsCOMPtr<nsISMILTimedElement> 
+      element( do_QueryReferent(mTimedElements[i]) );
+
+    if (element)
+      element->SampleAt(aDocumentTime);
+    else
+      mTimedElements.RemoveObjectAt(i);
+  }
+}
+
Index: /cvsroot/mozilla/content/smil/src/nsSMILTimedDocumentRoot.h
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILTimedDocumentRoot.h
diff -N content/smil/src/nsSMILTimedDocumentRoot.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILTimedDocumentRoot.h	14 Sep 2005 10:44:11 -0000
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_SMILTIMEDDOCUMENTROOT_H__
+#define __NS_SMILTIMEDDOCUMENTROOT_H__
+
+#include "nsISupports.h"
+#include "nsISMILTimeContainer.h"
+#include "nsSMILAnimationRegistry.h"
+#include "nsWeakReference.h"
+#include "nsCOMArray.h"
+
+class nsISMILTimeValueSpec;
+class nsISMILTimedElement;
+class nsSMILTimeValue;
+
+////////////////////////////////////////////////////////////////////////
+// nsSMILTimedDocumentRoot: Timed document root
+
+class nsSMILTimedDocumentRoot : public nsISMILTimeContainer,
+                                public nsSupportsWeakReference
+{
+public:
+  nsSMILTimedDocumentRoot(nsSMILAnimationRegistry* registry);
+
+  NS_DECL_ISUPPORTS
+
+  nsSMILTimeValue   WallclockToDocumentTime(nsISMILTimeValueSpec*
+                                              aWallclockSpec);
+  nsresult          SeekToTime(PRInt64 aSeekTo);
+
+  // nsISMILTimeContainer
+  virtual nsresult  Pause();
+  virtual nsresult  Resume();
+  virtual void      Sample();
+  virtual nsresult  AddTimedElement(nsISMILTimedElement* aElement);
+  virtual nsresult  RemoveTimedElement(nsISMILTimedElement* aElement);
+
+protected:
+  void              SampleChildren(PRInt64 aDocumentTime);
+
+  PRInt64                       mStartTime;
+  PRInt64                       mAccumulatedOffset;
+  nsCOMArray<nsIWeakReference>  mTimedElements;
+  nsSMILAnimationRegistry*      mAnimationRegistry;
+};
+
+#endif // __NS_SMILTIMEDDOCUMENTROOT_H__
+
Index: /cvsroot/mozilla/content/smil/src/nsSMILTimedElement.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/smil/src/nsSMILTimedElement.cpp
diff -N content/smil/src/nsSMILTimedElement.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/smil/src/nsSMILTimedElement.cpp	14 Sep 2005 10:44:13 -0000
@@ -0,0 +1,913 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISMILTimedElement.h"
+#include "nsSMILTimeValue.h"
+#include "nsSMILTimeValueSpec.h"
+#include "nsSMILInstanceTime.h"
+#include "nsSMILInterval.h"
+#include "nsISMILTimeClient.h"
+#include "nsCOMArray.h"
+#include "nsReadableUtils.h"
+#include "nsAutoPtr.h"
+#include "prdtoa.h"
+#include "plstr.h"
+
+//----------------------------------------------------------------------
+// Class declaration
+
+class nsSMILTimedElement : public nsISMILTimedElement
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  /*
+   * nsISMILTimedElement
+   */
+  virtual void      AddInstanceTime(nsSMILInstanceTime* aInstanceTime,
+                                    PRBool aIsBegin);
+  virtual void      SetTimeClient(nsISMILTimeClient* aClient);
+  virtual void      SampleAt(const PRInt64& aDocumentTime);
+
+  virtual nsresult  SetBeginSpec(const nsAString& aBeginSpec);
+  virtual nsresult  SetEndSpec(const nsAString& aEndSpec);
+  virtual nsresult  SetSimpleDuration(const nsAString& aDurSpec);
+  virtual nsresult  SetMin(const nsAString& aMinSpec);
+  virtual nsresult  SetMax(const nsAString& aMaxSpec);
+  virtual nsresult  SetRestart(const nsAString& aRestartSpec);
+  virtual nsresult  SetRepeatCount(const nsAString& aRepeatCountSpec);
+  virtual nsresult  SetRepeatDur(const nsAString& aRepeatDurSpec);
+  virtual nsresult  SetFillMode(const nsAString& aFillModeSpec);
+
+  virtual void      UnsetBeginSpec();
+  virtual void      UnsetEndSpec();
+  virtual void      UnsetSimpleDuration();
+  virtual void      UnsetMin();
+  virtual void      UnsetMax();
+  virtual void      UnsetRestart();
+  virtual void      UnsetRepeatCount();
+  virtual void      UnsetRepeatDur();
+  virtual void      UnsetFillMode();
+
+protected:
+  nsSMILTimedElement();
+  virtual ~nsSMILTimedElement();
+
+  friend nsISMILTimedElement* NS_NewSMILTimedElement();
+
+  /*
+   * Implementation helpers
+   */
+
+  /*
+   * This may eventually be pushed to the public interface in order to support
+   * repeating time containers. For now we just use it when we need to
+   * re-initialise internally, such as when because a new begin specification is
+   * set.
+   */
+  void            Reset();
+
+  nsresult        SetBeginOrEndSpec(const nsAString& aSpec, PRBool aIsBegin);
+
+  /**
+   * Calculates the first acceptable interval for this element.
+   *
+   * @see SMILANIM 3.6.8
+   */
+  nsresult        GetNextInterval(const nsSMILTimeValue& aBeginAfter,
+                                  PRBool aFirstInstance,
+                                  nsSMILInterval& aResult);
+
+  PRBool          GetNextGreater(const nsVoidArray& aList,
+                                 const nsSMILTimeValue& aBase,
+                                 PRInt32& aPosition,
+                                 nsSMILTimeValue& aResult);
+
+  nsSMILTimeValue CalcActiveEnd(const nsSMILTimeValue& aBegin,
+                                const nsSMILTimeValue& aEnd);
+
+  PRInt64         ActiveTimeToSimpleTime(const PRInt64& aActiveTime,
+                                         PRUint32& aRepeatIteration);
+
+  PRInt64         MinLL(const PRInt64& a, const PRInt64& b);
+
+  /*
+   * Members
+   */
+  nsCOMArray<nsSMILTimeValueSpec> mBeginSpecs;
+  nsCOMArray<nsSMILTimeValueSpec> mEndSpecs;
+
+  /*
+   * We need to distinguish between attempting to set the begin spec and failing
+   * (in which case the mBeginSpecs array will be empty) and not attempting to
+   * set the begin spec at all. In the first case, we should act as if the begin
+   * was indefinite, and in the second, we should act as if begin was 0s.
+   */
+  PRBool                          mBeginSpecSet;
+
+  nsSMILTimeValue                 mSimpleDur;
+
+  /**
+   * The number of iterations of the animation function. We use an
+   * nsSMILTimeValue type where:
+   *
+   * milliseconds = the number of iterations * 1000,
+   * indefinite = repeating indefinitely, until the document ends, and
+   * unresolved = the attribute is not set, therefore no repeating.
+   */
+  nsSMILTimeValue                 mRepeatCount;
+  nsSMILTimeValue                 mRepeatDur;
+
+  nsSMILTimeValue                 mMin;
+  nsSMILTimeValue                 mMax;
+
+  enum nsSMILRestartMode
+  {
+    NS_SMIL_RESTART_ALWAYS,
+    NS_SMIL_RESTART_NEVER,
+    NS_SMIL_RESTART_WHENNOTACTIVE
+  };
+  nsSMILRestartMode               mRestartMode;
+
+  enum nsSMILFillMode
+  {
+    NS_SMIL_FILL_REMOVE,
+    NS_SMIL_FILL_FREEZE
+  };
+  nsSMILFillMode                  mFillMode;
+
+  PRBool                          mEndHasEventConditions;
+
+  // nsRefArray would be really nice here
+  nsVoidArray                     mBeginInstances;
+  nsVoidArray                     mEndInstances;
+
+  nsCOMPtr<nsISMILTimeClient>     mClient;
+  nsSMILInterval                  mCurrentInterval;
+
+  /**
+   * The state of the element in its life-cycle. These states are based on the
+   * element life-cycle described in SMILANIM 3.6.8
+   */
+  enum nsSMILElementState
+  {
+    NS_SMIL_STATE_STARTUP,
+    NS_SMIL_STATE_WAITING,
+    NS_SMIL_STATE_ACTIVE,
+    NS_SMIL_STATE_POST_ACTIVE
+  };
+
+  nsSMILElementState              mElementState;
+};
+
+//----------------------------------------------------------------------
+// Implementation
+
+nsISMILTimedElement* NS_NewSMILTimedElement()
+{
+  return new nsSMILTimedElement();
+}
+
+nsSMILTimedElement::nsSMILTimedElement() : mBeginSpecs(),
+                                           mEndSpecs(),
+                                           mBeginSpecSet(PR_FALSE),
+                                           mRestartMode(NS_SMIL_RESTART_ALWAYS),
+                                           mFillMode(NS_SMIL_FILL_REMOVE),
+                                           mEndHasEventConditions(PR_FALSE),
+                                           mElementState(NS_SMIL_STATE_STARTUP)
+{
+  mSimpleDur.SetIndefinite();
+}
+
+nsSMILTimedElement::~nsSMILTimedElement()
+{
+  PRInt32 i;
+  PRInt32 count = mBeginInstances.Count();
+
+  for (i = 0; i < count; ++i)
+    NS_STATIC_CAST(nsSMILInstanceTime*, mBeginInstances[i])->Release();
+
+  count = mEndInstances.Count();
+
+  for (i = 0; i < count; ++i)
+    NS_STATIC_CAST(nsSMILInstanceTime*, mEndInstances[i])->Release();
+}
+
+//----------------------------------------------------------------------
+// nsISupports
+
+NS_IMPL_ISUPPORTS2(nsSMILTimedElement,
+                   nsISMILTimedElement,
+                   nsISupportsWeakReference)
+
+//----------------------------------------------------------------------
+// nsISMILTimedElement
+
+void
+nsSMILTimedElement::AddInstanceTime(nsSMILInstanceTime* aInstanceTime,
+                                    PRBool aIsBegin)
+{
+  NS_ASSERTION(aInstanceTime, "NULL instance time");
+
+  if (aIsBegin)
+  {
+    NS_ADDREF(aInstanceTime);
+    mBeginInstances.AppendElement(aInstanceTime);
+  }
+  else
+  {
+    NS_ADDREF(aInstanceTime);
+    mEndInstances.AppendElement(aInstanceTime);
+  }
+}
+
+void
+nsSMILTimedElement::SetTimeClient(nsISMILTimeClient* aClient)
+{
+  /*
+   * No need to check for NULL. A NULL parameter simply means to remove the
+   * previous client which we do by setting to NULL anyway.
+   */
+  mClient = aClient;
+}
+
+void
+nsSMILTimedElement::SampleAt(const PRInt64& aDocumentTime)
+{
+  PRBool          stateChanged;
+  nsSMILTimeValue docTime;
+  docTime.SetMillis(aDocumentTime);
+
+  do
+  {
+    stateChanged = false;
+
+    switch (mElementState)
+    {
+    case NS_SMIL_STATE_STARTUP:
+      {
+        nsSMILTimeValue beginAfter;
+        beginAfter.SetMillis(LL_MININT);
+
+        mElementState = 
+          (NS_SUCCEEDED(GetNextInterval(beginAfter, true, mCurrentInterval)))
+          ? NS_SMIL_STATE_WAITING
+          : NS_SMIL_STATE_POST_ACTIVE;
+        stateChanged = true;
+      }
+      break;
+
+    case NS_SMIL_STATE_WAITING:
+      {
+        if (mCurrentInterval.Begin().CompareTo(docTime) < 1)
+        {
+          mElementState = NS_SMIL_STATE_ACTIVE;
+          if (mClient)
+            mClient->ToActive(mCurrentInterval.Begin().GetMillis());
+          stateChanged = true;
+        }
+      }
+      break;
+
+    case NS_SMIL_STATE_ACTIVE:
+      {
+        if (mCurrentInterval.End().CompareTo(docTime) < 1)
+        {
+          mElementState = 
+            (NS_SUCCEEDED(GetNextInterval(mCurrentInterval.End(),
+                                          false,
+                                          mCurrentInterval)))
+            ? NS_SMIL_STATE_WAITING
+            : NS_SMIL_STATE_POST_ACTIVE;
+          if (mClient)
+            mClient->ToInactive();
+          stateChanged = true;
+        }
+        else
+        {
+          PRInt64 beginTime = mCurrentInterval.Begin().GetMillis();
+
+          PRInt64 activeTime;
+          LL_SUB(activeTime, aDocumentTime, beginTime);
+
+          if (mClient)
+          {
+            PRUint32 repeatIteration;
+            PRInt64  simpleTime = ActiveTimeToSimpleTime(activeTime,
+                                                         repeatIteration);
+            mClient->SampleAt(simpleTime, mSimpleDur, repeatIteration);
+          }
+        }
+      }
+      break;
+
+    case NS_SMIL_STATE_POST_ACTIVE:
+      // TODO: Sample the last value?
+      break;
+    }
+  } while (stateChanged);
+}
+
+nsresult
+nsSMILTimedElement::SetBeginSpec(const nsAString& aBeginSpec)
+{
+  mBeginSpecSet = PR_TRUE;
+  return SetBeginOrEndSpec(aBeginSpec, PR_TRUE);
+}
+
+void
+nsSMILTimedElement::UnsetBeginSpec()
+{
+  mBeginSpecs.Clear();
+  mBeginInstances.Clear();
+  mBeginSpecSet = PR_FALSE;
+  Reset();
+}
+
+nsresult
+nsSMILTimedElement::SetEndSpec(const nsAString& aEndSpec)
+{
+  /*
+   * When implementing events etc., don't forget to ensure
+   * mEndEventHasEndConditions is set if the specification contains conditions
+   * that describe event-values, repeat-values or accessKey-values.
+   */
+  return SetBeginOrEndSpec(aEndSpec, PR_FALSE);
+}
+
+void
+nsSMILTimedElement::UnsetEndSpec()
+{
+  mEndSpecs.Clear();
+  mEndInstances.Clear();
+  Reset();
+}
+
+nsresult
+nsSMILTimedElement::SetSimpleDuration(const nsAString& aDurSpec)
+{
+  nsSMILTimeValue duration;
+  PRBool isMedia;
+  nsresult rv;
+  
+  rv = nsSMILTimeValueSpec::ParseClockValue(aDurSpec,
+                                            &duration,
+                                            false, // don't allow + or -
+                                            true,  // allow indefinite
+                                            true,  // allow media
+                                            &isMedia);
+
+  if (NS_FAILED(rv) || (!duration.IsResolved() && !duration.IsIndefinite()))
+    return NS_ERROR_FAILURE;
+  
+  if (duration.IsResolved() && LL_EQ(duration.GetMillis(), LL_Zero()))
+    return NS_ERROR_FAILURE;
+
+  /*
+   * SVG-specific: "For SVG's animation elements, if "media" is specified, the
+   * attribute will be ignored." (SVG 1.1, section 19.2.6)
+   */
+  if (isMedia)
+    duration.SetIndefinite();
+
+  mSimpleDur = duration;
+
+  return NS_OK;
+}
+
+void
+nsSMILTimedElement::UnsetSimpleDuration()
+{
+  mSimpleDur.SetIndefinite();
+  Reset();
+}
+
+nsresult
+nsSMILTimedElement::SetMin(const nsAString& aMinSpec)
+{
+  // TODO[2]
+  return NS_OK;
+}
+
+void
+nsSMILTimedElement::UnsetMin()
+{
+  // TODO[2]
+}
+
+nsresult
+nsSMILTimedElement::SetMax(const nsAString& aMaxSpec)
+{
+  // TODO[2]
+  return NS_OK;
+}
+
+void
+nsSMILTimedElement::UnsetMax()
+{
+  // TODO[2]
+}
+
+nsresult
+nsSMILTimedElement::SetRestart(const nsAString& aRestartSpec)
+{
+  // TODO[2]
+  return NS_OK;
+}
+
+void
+nsSMILTimedElement::UnsetRestart()
+{
+  // TODO[2]
+}
+
+nsresult
+nsSMILTimedElement::SetRepeatCount(const nsAString& aRepeatCountSpec)
+{
+  nsresult rv      = NS_OK;
+  char*    str     = ToNewCString(aRepeatCountSpec);
+  char*    number  = str;
+
+  nsSMILTimeValue newRepeatCount;
+
+  Reset();
+
+  while (*number && isspace(*number))
+    ++number;
+
+  if (*number)
+  {
+    if (PL_strstr(number, "indefinite") == number)
+    {
+      newRepeatCount.SetIndefinite();
+      number += PL_strlen("indefinite");
+    }
+    else
+    {
+      char      *rest;
+      PRFloat64 value = PR_strtod(number, &rest);
+
+      if (rest != number)
+      {
+        PRInt64 count;
+        value *= 1000;
+
+        LL_D2L(count, value);
+
+        newRepeatCount.SetMillis(count);
+
+        if (!LL_GE_ZERO(count) || LL_IS_ZERO(count))
+          rv = NS_ERROR_FAILURE;
+
+        number = rest;
+      }
+      else
+      {
+        rv = NS_ERROR_FAILURE;
+      }
+    }
+
+    /* Check the remainder is whitespace */
+    while (*number && isspace(*number))
+      number++;
+
+    if (*number != 0)
+      rv = NS_ERROR_FAILURE;
+  }
+  else
+  {
+    /* Empty spec */
+    rv = NS_ERROR_FAILURE;
+  }
+
+  if (NS_SUCCEEDED(rv))
+    mRepeatCount = newRepeatCount;
+  else
+    mRepeatCount.SetUnresolved();
+
+  nsMemory::Free(str);
+    
+  return rv;
+}
+
+void
+nsSMILTimedElement::UnsetRepeatCount()
+{
+  mRepeatCount.SetUnresolved();
+  Reset();
+}
+
+nsresult
+nsSMILTimedElement::SetRepeatDur(const nsAString& aRepeatDurSpec)
+{
+  nsresult        rv;
+  nsSMILTimeValue duration;
+
+  Reset();
+  
+  rv = nsSMILTimeValueSpec::ParseClockValue(aRepeatDurSpec,
+                                            &duration,
+                                            false,  // don't allow + or -
+                                            true);  // allow indefinite
+
+  if (NS_FAILED(rv) || (!duration.IsResolved() && !duration.IsIndefinite()))
+    return NS_ERROR_FAILURE;
+  
+  mRepeatDur = duration;
+
+  return NS_OK;
+}
+
+void
+nsSMILTimedElement::UnsetRepeatDur()
+{
+  mRepeatDur.SetUnresolved();
+  Reset();
+}
+
+nsresult
+nsSMILTimedElement::SetFillMode(const nsAString& aFillModeSpec)
+{
+  // TODO[2]
+  return NS_OK;
+}
+
+void
+nsSMILTimedElement::UnsetFillMode()
+{
+  // TODO[2]
+}
+
+//----------------------------------------------------------------------
+// Implementation helpers
+
+void
+nsSMILTimedElement::Reset()
+{
+  nsSMILInstanceTime* instance;
+  PRInt32             count = mBeginInstances.Count();
+
+  for (PRInt32 i = 0; i < count; ++i)
+  {
+    instance = NS_STATIC_CAST(nsSMILInstanceTime*, mBeginInstances[i]);
+    if (instance->ClearOnReset())
+      mBeginInstances.RemoveElementAt(i);
+  }
+
+  count = mEndInstances.Count();
+
+  for (PRInt32 i = 0; i < count; ++i)
+  {
+    instance = NS_STATIC_CAST(nsSMILInstanceTime*, mEndInstances[i]);
+    if (instance->ClearOnReset())
+      mEndInstances.RemoveElementAt(i);
+  }
+
+  nsSMILTimeValue unresolved;
+  mCurrentInterval = nsSMILInterval(unresolved, unresolved);
+  mElementState    = NS_SMIL_STATE_STARTUP;
+
+  // TODO[2] Clear old intervals
+}
+
+nsresult
+nsSMILTimedElement::SetBeginOrEndSpec(const nsAString& aSpec,
+                                      PRBool aIsBegin)
+{
+  nsresult rv = NS_ERROR_FAILURE;
+
+  nsRefPtr<nsSMILTimeValueSpec>    spec;
+  nsCOMArray<nsSMILTimeValueSpec>& timeSpecsList = (aIsBegin)
+                                                 ? mBeginSpecs
+                                                 : mEndSpecs;
+  nsVoidArray&                     instancesList = (aIsBegin)
+                                                 ? mBeginInstances
+                                                 : mEndInstances;
+
+  timeSpecsList.Clear();
+  instancesList.Clear();
+  Reset();
+
+  PRInt32 start;
+  PRInt32 end = -1;
+  PRInt32 length;
+
+  do
+  {
+    start        = end + 1;
+    end          = aSpec.FindChar(';', start);
+    length       = (end == -1) ? -1 : end - start;
+
+    rv = NS_NewSMILTimeValueSpec(this, aIsBegin,
+      Substring(aSpec, start, length), getter_AddRefs(spec));
+
+    if (NS_SUCCEEDED(rv))
+    {
+      timeSpecsList.AppendObject(spec);
+    }
+    else
+    {
+      // TODO[3]: Appropriate error handling
+    }
+  } while (end != -1);
+
+  return rv;
+}
+
+/*
+ * This method is based on the pseudocode given in the SMILANIM spec.
+ *
+ * See:
+ * http://www.w3.org/TR/2001/REC-smil-animation-20010904/#Timing-BeginEnd-LC-Start
+ */
+nsresult
+nsSMILTimedElement::GetNextInterval(const nsSMILTimeValue& aBeginAfter,
+                                    PRBool aFirstInterval,
+                                    nsSMILInterval& aResult)
+{
+  static nsSMILTimeValue zeroTime;
+  zeroTime.SetMillis(LL_Zero());
+  
+  nsSMILTimeValue beginAfter = aBeginAfter;
+  nsSMILTimeValue tempBegin;
+  nsSMILTimeValue tempEnd;
+  PRInt32         beginPos = 0;
+  PRInt32         endPos = 0;
+
+  /*
+   * This is to handle the special case when a we are calculating the first
+   * interval and we have a non-0-duration interval immediately after
+   * a 0-duration in which case but we have to be careful not to re-use an end
+   * that has already been used in another interval. See the pseudocode in
+   * SMILANIM 3.6.8 for getFirstInterval.
+   */
+  PRInt32         endMaxPos = 0;
+
+  mBeginInstances.Sort(nsSMILTimeValue::ComparisonCallback, nsnull);
+  mEndInstances.Sort(nsSMILTimeValue::ComparisonCallback, nsnull);
+
+  while (true)
+  {
+    if (!mBeginSpecSet && beginAfter.CompareTo(zeroTime) < 1)
+    {
+      tempBegin.SetMillis(0);
+    }
+    else
+    {
+      PRBool beginFound = GetNextGreater(mBeginInstances, beginAfter,
+                                         beginPos, tempBegin);
+      if (!beginFound)
+        return NS_ERROR_FAILURE;
+    }
+
+    if (mEndSpecs.Count() == 0)
+    {
+      nsSMILTimeValue indefiniteEnd;
+      indefiniteEnd.SetIndefinite();
+
+      tempEnd = CalcActiveEnd(tempBegin, indefiniteEnd);
+    }
+    else
+    {
+      /* 
+       * Start searching from the beginning again.
+       */
+      endPos = 0;
+
+      PRBool endFound = GetNextGreater(mEndInstances, tempBegin,
+                                       endPos, tempEnd);
+
+      if
+      (
+        !aFirstInterval && tempEnd.CompareTo(aBeginAfter)==0
+        ||
+        (aFirstInterval && tempEnd.CompareTo(tempBegin)==0 && endPos<=endMaxPos)
+      )
+      {
+        endFound = GetNextGreater(mEndInstances, tempBegin, endPos, tempEnd);
+      }
+
+      endMaxPos = endPos;
+
+      if (!endFound)
+      {
+        if (mEndHasEventConditions || mEndInstances.Count() == 0)
+          tempEnd.SetUnresolved();
+        else
+          /* 
+           * This is a little counter-intuitive but according to SMILANIM, if
+           * all the end's are after the begin, we _don't_ just assume an
+           * infinite end, it's actually a bad interval. ASV however will just
+           * use an infinite end.
+           */
+          return NS_ERROR_FAILURE;
+      }
+
+      tempEnd = CalcActiveEnd(tempBegin, tempEnd);
+    }
+
+    if (tempEnd.CompareTo(zeroTime) == 1)
+    {
+      aResult = nsSMILInterval(tempBegin, tempEnd);
+      return NS_OK;
+    }
+    /*
+    TODO[2]
+    else if (restart == never)
+    {
+      return NS_ERROR_FAILURE;
+    }
+    */
+    else
+    {
+      beginAfter = tempEnd;
+    }
+  }
+  NS_NOTREACHED("Hmm... we really shouldn't be here");
+
+  return NS_ERROR_FAILURE;
+}
+
+PRBool
+nsSMILTimedElement::GetNextGreater(const nsVoidArray& aList,
+                                   const nsSMILTimeValue& aBase,
+                                   PRInt32 &aPosition,
+                                   nsSMILTimeValue& aResult)
+{
+    PRBool              found = PR_FALSE;
+    nsSMILInstanceTime* val;
+    PRInt32             count = aList.Count();
+
+    for (; aPosition < count && !found; ++aPosition)
+    {
+      val = NS_STATIC_CAST(nsSMILInstanceTime*, aList[aPosition]);
+      if (val->Time().CompareTo(aBase) > -1)
+      {
+        aResult = val->Time();
+        found = PR_TRUE;
+      }
+    }
+
+    return found;
+}
+
+inline PRInt64
+nsSMILTimedElement::MinLL(const PRInt64& a, const PRInt64& b)
+{
+  return (LL_CMP(a, <, b)) ? a : b;
+}
+
+/**
+ * @see SMILANIM 3.3.4
+ */
+nsSMILTimeValue
+nsSMILTimedElement::CalcActiveEnd(const nsSMILTimeValue& aBegin,
+                                  const nsSMILTimeValue& aEnd)
+{
+  nsSMILTimeValue result;
+
+  if (!aEnd.IsIndefinite() && !aEnd.IsResolved())
+  {
+    NS_ASSERTION(false, "Unresolved end time passed to CalcActiveEnd.");
+    result.SetIndefinite();
+    return result;
+  }
+
+  if (!mSimpleDur.IsIndefinite() && !mSimpleDur.IsResolved())
+  {
+    NS_ASSERTION(false, "Unresolved simple duration in CalcActiveEnd.");
+    result.SetIndefinite();
+    return result;
+  }
+
+  if (!aBegin.IsResolved() && !aBegin.IsIndefinite())
+  {
+    NS_ASSERTION(false, "Unresolved begin time passed to CalcActiveEnd.");
+    result.SetIndefinite();
+    return result;
+  }
+
+  if (mRepeatDur.IsIndefinite() || aBegin.IsIndefinite())
+  {
+    result.SetIndefinite();
+  }
+  else
+  {
+    if (mRepeatCount.IsResolved() && mRepeatDur.IsResolved())
+    {
+      if (mSimpleDur.IsResolved())
+      {
+        PRInt64 activeDur;
+        LL_MUL(activeDur, mRepeatCount.GetMillis(), mSimpleDur.GetMillis());
+        LL_DIV(activeDur, activeDur, 1000);
+        result.SetMillis(MinLL(activeDur, mRepeatDur.GetMillis()));
+      }
+      else
+      {
+        result = mRepeatDur;
+      }
+    }
+    else if (mRepeatCount.IsResolved() && mSimpleDur.IsResolved())
+    {
+      PRInt64 activeDur;
+      LL_MUL(activeDur, mRepeatCount.GetMillis(), mSimpleDur.GetMillis());
+      LL_DIV(activeDur, activeDur, 1000);
+      result.SetMillis(activeDur);
+    }
+    else if (mRepeatDur.IsResolved())
+    {
+      result = mRepeatDur;
+    }
+    else
+    {
+      if (mRepeatCount.IsIndefinite())
+      {
+        result.SetIndefinite();
+      }
+      else
+      {
+        result = mSimpleDur;
+      }
+    }
+  }
+
+  if (aEnd.IsResolved() && aBegin.IsResolved())
+  {
+    PRInt64 activeDur;
+    LL_SUB(activeDur, aEnd.GetMillis(), aBegin.GetMillis());
+
+    if (result.IsResolved())
+    {
+      result.SetMillis(MinLL(result.GetMillis(), activeDur));
+    }
+    else
+    {
+      result.SetMillis(activeDur);
+    }
+  }
+
+  if (result.IsResolved())
+  {
+    PRInt64 activeEnd;
+    LL_ADD(activeEnd, result.GetMillis(), aBegin.GetMillis());
+    result.SetMillis(activeEnd);
+  }
+
+  return result;
+}
+
+PRInt64
+nsSMILTimedElement::ActiveTimeToSimpleTime(const PRInt64& aActiveTime,
+                                           PRUint32& aRepeatIteration)
+{
+  PRInt64 result;
+
+  NS_ASSERTION(mSimpleDur.IsResolved() || mSimpleDur.IsIndefinite(),
+      "Trying to calculate active time with unresolved duration");
+
+  if (mSimpleDur.IsIndefinite() || LL_IS_ZERO(mSimpleDur.GetMillis()))
+  {
+    aRepeatIteration = 0;
+    result = aActiveTime;
+  }
+  else
+  {    
+    PRInt64 repeatResult;
+    LL_MOD(result, aActiveTime, mSimpleDur.GetMillis());
+    LL_DIV(repeatResult, aActiveTime, mSimpleDur.GetMillis());
+
+    LL_L2UI(aRepeatIteration, repeatResult);
+  }
+
+  return result;
+}
Index: /cvsroot/mozilla/content/svg/content/src/Makefile.in
===================================================================
RCS file: /cvsroot/mozilla/content/svg/content/src/Makefile.in,v
retrieving revision 1.38
diff -u -r1.38 Makefile.in
--- /cvsroot/mozilla/content/svg/content/src/Makefile.in	26 Aug 2005 02:49:49 -0000	1.38
+++ /cvsroot/mozilla/content/svg/content/src/Makefile.in	14 Sep 2005 10:44:17 -0000
@@ -136,6 +136,10 @@
 CPPSRCS += nsSVGForeignObjectElement.cpp
 endif
 
+ifdef MOZ_SMIL
+CPPSRCS += nsSVGAnimateElement.cpp
+endif
+
 include $(topsrcdir)/config/config.mk
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
@@ -178,3 +182,6 @@
 		$(NULL)
 
 DEFINES += -D_IMPL_NS_LAYOUT
+
+#CXXFLAGS	+= -P
+
Index: /cvsroot/mozilla/content/svg/content/src/nsISVGLength.h
===================================================================
RCS file: /cvsroot/mozilla/content/svg/content/src/nsISVGLength.h,v
retrieving revision 1.4
diff -u -r1.4 nsISVGLength.h
--- /cvsroot/mozilla/content/svg/content/src/nsISVGLength.h	5 Aug 2004 09:01:09 -0000	1.4
+++ /cvsroot/mozilla/content/svg/content/src/nsISVGLength.h	14 Sep 2005 10:44:17 -0000
@@ -42,6 +42,9 @@
 #include "nsIDOMSVGLength.h"
 
 class nsSVGCoordCtx;
+#ifdef MOZ_SMIL
+class nsISMILAnimVal;
+#endif // MOZ_SMIL
 
 ////////////////////////////////////////////////////////////////////////
 // nsISVGLength: private interface for svg lengths
@@ -55,7 +58,11 @@
 public:
   NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISVGLENGTH_IID)
 
-  NS_IMETHOD SetContext(nsSVGCoordCtx* ctx)=0;
+  NS_IMETHOD          SetContext(nsSVGCoordCtx* ctx)=0;
+#ifdef MOZ_SMIL
+  virtual nsresult    GetAnimValue(nsIDOMSVGLength** aResult)=0;
+  virtual nsresult    GetAnimVal(nsISMILAnimVal** aResult)=0;
+#endif // MOZ_SMIL
 };
 
 
Index: /cvsroot/mozilla/content/svg/content/src/nsISVGSVGElement.h
===================================================================
RCS file: /cvsroot/mozilla/content/svg/content/src/nsISVGSVGElement.h,v
retrieving revision 1.6
diff -u -r1.6 nsISVGSVGElement.h
--- /cvsroot/mozilla/content/svg/content/src/nsISVGSVGElement.h	25 Aug 2005 21:31:07 -0000	1.6
+++ /cvsroot/mozilla/content/svg/content/src/nsISVGSVGElement.h	14 Sep 2005 10:44:17 -0000
@@ -46,6 +46,9 @@
 class nsSVGCoordCtxProvider;
 class nsIDOMSVGNumber;
 class nsISVGEnum;
+#ifdef MOZ_SMIL
+class nsISMILAnimationRegistry;
+#endif
 
 ////////////////////////////////////////////////////////////////////////
 // nsISVGSVGElement: private interface implemented by <svg>-elements
@@ -89,6 +92,13 @@
   NS_IMETHOD_(float) GetPreviousScale()=0;
   NS_IMETHOD_(float) GetPreviousTranslate_x()=0;
   NS_IMETHOD_(float) GetPreviousTranslate_y()=0;
+  
+#ifdef MOZ_SMIL
+  /**
+   * Get the animation registry object for the outermost svg element.
+   */
+  NS_IMETHOD_(nsISMILAnimationRegistry*) GetAnimationRegistry()=0;
+#endif
 };
 
 #endif // __NS_ISVGSVGELEMENT__
Index: /cvsroot/mozilla/content/svg/content/src/nsSVGAnimateElement.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/svg/content/src/nsSVGAnimateElement.cpp
diff -N content/svg/content/src/nsSVGAnimateElement.cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/content/svg/content/src/nsSVGAnimateElement.cpp	14 Sep 2005 10:44:19 -0000
@@ -0,0 +1,623 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsSVGElement.h"
+#include "nsIDOMSVGAnimateElement.h"
+#include "nsSVGAtoms.h"
+#include "nsISVGSVGElement.h"
+#include "nsIBindingManager.h"
+#include "nsIDocument.h"
+#include "nsISMILTimedElement.h"
+#include "nsISMILAnimationFunction.h"
+#include "nsISMILAnimElement.h"
+#include "nsISMILAnimationRegistry.h"
+#include "nsISMILTimeClient.h"
+#include "nsISMILComposable.h"
+
+typedef nsSVGElement nsSVGAnimateElementBase;
+
+class nsSVGAnimateElement : public nsSVGAnimateElementBase,
+                            public nsIDOMSVGAnimateElement
+                              // : nsIDOMSVGAnimationElement
+{
+protected:
+  friend nsresult NS_NewSVGAnimateElement(nsIContent **aResult,
+                                          nsINodeInfo *aNodeInfo);
+  nsSVGAnimateElement(nsINodeInfo* aNodeInfo);
+  nsresult Init();
+
+public:
+  // interfaces:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSIDOMSVGANIMATEELEMENT
+  NS_DECL_NSIDOMSVGANIMATIONELEMENT
+
+  NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsSVGAnimateElementBase::)
+  NS_FORWARD_NSIDOMELEMENT(nsSVGAnimateElementBase::)
+  NS_FORWARD_NSIDOMSVGELEMENT(nsSVGAnimateElementBase::)
+
+  // nsISVGContent specializations
+  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                              nsIContent* aBindingParent,
+                              PRBool aCompileEventHandlers);
+  virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
+                              PRBool aNullParent = PR_TRUE);
+
+  // nsIContent specializations
+  virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+                           nsIAtom* aPrefix, const nsAString& aValue,
+                           PRBool aNotify);
+  virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
+                             PRBool aNotify);
+
+protected:
+  // Implementation helpers
+  nsISMILAnimationRegistry*         GetAnimationRegistry();
+  nsIContent*                       GetParentElement();
+  void                              UpdateTargetElement();
+  nsISMILAnimAttr*                  GetTargetAttribute();
+  void                              UpdateTargetAttribute();
+  void                              SetAnimationProperties();
+
+  nsWeakPtr                         mTargetElement;
+  nsRefPtr<nsISMILAnimationFunction> mAnimation;
+  nsCOMPtr<nsISMILTimedElement>     mTimedElement;
+};
+
+NS_IMPL_NS_NEW_SVG_ELEMENT(Animate)
+
+
+//----------------------------------------------------------------------
+// nsISupports methods
+
+NS_IMPL_ADDREF_INHERITED(nsSVGAnimateElement,nsSVGAnimateElementBase)
+NS_IMPL_RELEASE_INHERITED(nsSVGAnimateElement,nsSVGAnimateElementBase)
+
+NS_INTERFACE_MAP_BEGIN(nsSVGAnimateElement)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMElement)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGElement)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimationElement)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimateElement)
+  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimateElement)
+NS_INTERFACE_MAP_END_INHERITING(nsSVGAnimateElementBase)
+
+//----------------------------------------------------------------------
+// Implementation
+
+nsSVGAnimateElement::nsSVGAnimateElement(nsINodeInfo *aNodeInfo)
+  : nsSVGAnimateElementBase(aNodeInfo)
+{
+}
+
+nsresult
+nsSVGAnimateElement::Init()
+{
+  mTimedElement = NS_NewSMILTimedElement();
+  mAnimation =    NS_NewSMILAnimationFunction();
+
+  return (mTimedElement) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+//----------------------------------------------------------------------
+// nsIDOMSVGAnimationElement methods
+
+/* readonly attribute SVGElement targetElement; */
+NS_IMETHODIMP nsSVGAnimateElement::GetTargetElement(nsIDOMSVGElement * *aTarget)
+{
+  if (mTargetElement)
+  {
+    nsCOMPtr<nsIDOMSVGElement> weakref = do_QueryReferent(mTargetElement);
+    if (*aTarget)
+      NS_RELEASE(*aTarget);
+    NS_IF_ADDREF(*aTarget = weakref);
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsSVGAnimateElement::GetStartTime(float* retval)
+{
+  nsresult rv = NS_ERROR_FAILURE;
+
+  if (mTimedElement)
+  {
+    // TODO[3]: Fill this in
+    rv = NS_ERROR_NOT_IMPLEMENTED;
+  }
+
+  return rv;
+}
+
+NS_IMETHODIMP nsSVGAnimateElement::GetCurrentTime(float* retval)
+{
+  // TODO[3]: Query the time container
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsSVGAnimateElement::GetSimpleDuration(float* retval)
+{
+  // TODO[3]: Query the timed element
+  return NS_OK;
+}
+
+
+//----------------------------------------------------------------------
+// nsIDOMNode methods
+
+NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGAnimateElement)
+
+
+//----------------------------------------------------------------------
+// nsISVGContent methods
+
+nsresult nsSVGAnimateElement::BindToTree(nsIDocument* aDocument,
+                                         nsIContent* aParent,
+                                         nsIContent* aBindingParent,
+                                         PRBool aCompileEventHandlers)
+{
+  nsresult rv = nsSVGAnimateElementBase::BindToTree(aDocument, aParent,
+                                                    aBindingParent,
+                                                    aCompileEventHandlers);
+
+  if (NS_SUCCEEDED(rv))
+  {
+    UpdateTargetElement();
+
+    if (mTimedElement)
+    {
+
+      nsCOMPtr<nsISMILAnimationRegistry> registry = GetAnimationRegistry();
+      if (registry)
+        rv = registry->RegisterTimedElement(mTimedElement);
+    }
+  }
+
+  return rv;
+}
+
+void nsSVGAnimateElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
+{
+  if (mTimedElement)
+  {
+    nsCOMPtr<nsISMILAnimationRegistry> registry = GetAnimationRegistry();
+    if (registry)
+      registry->UnregisterTimedElement(mTimedElement);
+  }
+
+  nsSVGAnimateElementBase::UnbindFromTree(aDeep, aNullParent);
+
+  UpdateTargetElement();
+}
+
+//----------------------------------------------------------------------
+// nsIContent methods
+
+nsresult nsSVGAnimateElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+                                      nsIAtom* aPrefix, const nsAString& aValue,
+                                      PRBool aNotify)
+{
+  nsresult rv = nsSVGAnimateElementBase::SetAttr(aNameSpaceID, aName, aPrefix,
+                                                 aValue, aNotify);
+  
+  NS_ASSERTION(mTimedElement, "Unexpected NULL timed element.");
+
+  if (aName == nsSVGAtoms::attributeName && aNameSpaceID == kNameSpaceID_None)
+  {
+    UpdateTargetAttribute();
+    return rv;
+  }
+
+  if (mTimedElement && aNameSpaceID == kNameSpaceID_None)
+  {
+    if (aName == nsSVGAtoms::begin)
+    {
+      rv = mTimedElement->SetBeginSpec(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    else if (aName == nsSVGAtoms::dur)
+    {
+      rv = mTimedElement->SetSimpleDuration(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    else if (aName == nsSVGAtoms::end)
+    {
+      rv = mTimedElement->SetEndSpec(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    else if (aName == nsSVGAtoms::fill)
+    {
+      rv = mTimedElement->SetFillMode(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    else if (aName == nsSVGAtoms::max)
+    {
+      rv = mTimedElement->SetMax(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    else if (aName == nsSVGAtoms::min)
+    {
+      rv = mTimedElement->SetMin(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    else if (aName == nsSVGAtoms::repeatCount)
+    {
+      rv = mTimedElement->SetRepeatCount(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    else if (aName == nsSVGAtoms::repeatDur)
+    {
+      rv = mTimedElement->SetRepeatDur(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    else if (aName == nsSVGAtoms::restart)
+    {
+      rv = mTimedElement->SetRestart(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+
+    return rv;
+  }
+
+  /*
+   * When we support xlink href's we need to revise the namespace restriction
+   * here.
+   */
+  if (mAnimation && mAnimation->IsInitialised() &&
+      aNameSpaceID == kNameSpaceID_None)
+  {
+    if (aName == nsSVGAtoms::accumulate)
+    {
+      rv = mAnimation->SetAccumulate(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    else if (aName == nsSVGAtoms::additive)
+    {
+      rv = mAnimation->SetAdditive(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    else if (aName == nsSVGAtoms::by)
+    {
+      rv = mAnimation->SetBy(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    else if (aName == nsSVGAtoms::calcMode)
+    {
+      rv = mAnimation->SetCalcMode(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    else if (aName == nsSVGAtoms::from)
+    {
+      rv = mAnimation->SetFrom(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    else if (aName == nsSVGAtoms::keyTimes)
+    {
+      rv = mAnimation->SetKeyTimes(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    else if (aName == nsSVGAtoms::keySplines)
+    {
+      rv = mAnimation->SetKeySplines(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    else if (aName == nsSVGAtoms::to)
+    {
+      rv = mAnimation->SetTo(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    else if (aName == nsSVGAtoms::values)
+    {
+      rv = mAnimation->SetValues(aValue);
+      NS_ENSURE_SUCCESS(rv,rv);
+    }
+    return rv;
+  }
+
+  return rv;
+}
+
+nsresult nsSVGAnimateElement::UnsetAttr(PRInt32 aNameSpaceID,
+                                        nsIAtom* aAttribute, PRBool aNotify)
+{
+  nsresult rv = nsSVGAnimateElementBase::UnsetAttr(aNameSpaceID, aAttribute,
+                                                   aNotify);
+
+  if (aAttribute == nsSVGAtoms::attributeName &&
+      aNameSpaceID == kNameSpaceID_None)
+  {
+    UpdateTargetAttribute();
+  }
+  else if (mTimedElement && aNameSpaceID == kNameSpaceID_None)
+  {
+    if (aAttribute == nsSVGAtoms::begin)
+      mTimedElement->UnsetBeginSpec();
+    else if (aAttribute == nsSVGAtoms::dur)
+      mTimedElement->UnsetSimpleDuration();
+    else if (aAttribute == nsSVGAtoms::end)
+      mTimedElement->UnsetEndSpec();
+    else if (aAttribute == nsSVGAtoms::fill)
+      mTimedElement->UnsetFillMode();
+    else if (aAttribute == nsSVGAtoms::max)
+      mTimedElement->UnsetMax();
+    else if (aAttribute == nsSVGAtoms::min)
+      mTimedElement->UnsetMin();
+    else if (aAttribute == nsSVGAtoms::repeatCount)
+      mTimedElement->UnsetRepeatCount();
+    else if (aAttribute == nsSVGAtoms::repeatDur)
+      mTimedElement->UnsetRepeatDur();
+    else if (aAttribute == nsSVGAtoms::restart)
+      mTimedElement->UnsetRestart();
+  }
+  else if (mAnimation && mAnimation->IsInitialised() &&
+           aNameSpaceID == kNameSpaceID_None)
+  {
+    if (aAttribute == nsSVGAtoms::accumulate)
+      mAnimation->UnsetAccumulate();
+    else if (aAttribute == nsSVGAtoms::additive)
+      mAnimation->UnsetAdditive();
+    else if (aAttribute == nsSVGAtoms::by)
+      mAnimation->UnsetBy();
+    else if (aAttribute == nsSVGAtoms::calcMode)
+      mAnimation->UnsetCalcMode();
+    else if (aAttribute == nsSVGAtoms::from)
+      mAnimation->UnsetFrom();
+    else if (aAttribute == nsSVGAtoms::keyTimes)
+      mAnimation->UnsetKeyTimes();
+    else if (aAttribute == nsSVGAtoms::keySplines)
+      mAnimation->UnsetKeySplines();
+    else if (aAttribute == nsSVGAtoms::to)
+      mAnimation->UnsetTo();
+    else if (aAttribute == nsSVGAtoms::values)
+      mAnimation->UnsetValues();
+  }
+
+  return rv;
+}
+
+//----------------------------------------------------------------------
+// Implementation helpers
+
+nsISMILAnimationRegistry*
+nsSVGAnimateElement::GetAnimationRegistry()
+{
+  nsISMILAnimationRegistry*     result = nsnull;
+  nsCOMPtr<nsIDOMSVGSVGElement> ownerDOMSVG;
+
+  nsresult rv = GetOwnerSVGElement(getter_AddRefs(ownerDOMSVG));
+
+  if (NS_SUCCEEDED(rv) && ownerDOMSVG)
+  {
+    nsCOMPtr<nsISVGSVGElement> ownerSVG( do_QueryInterface(ownerDOMSVG, &rv) );
+
+    if (ownerSVG)
+      result = ownerSVG->GetAnimationRegistry();
+  }
+
+  return result;
+}
+
+nsIContent*
+nsSVGAnimateElement::GetParentElement()
+{
+  nsIContent*         result = nsnull;
+  nsIBindingManager*  bindingManager = nsnull;
+  nsIDocument*        ownerDoc = GetOwnerDoc();
+
+  if (ownerDoc)
+    bindingManager = ownerDoc->BindingManager();
+
+  if (bindingManager)
+    // we have a binding manager -- do we have an anonymous parent?
+    bindingManager->GetInsertionParent(this, &result);
+
+  if (!result)
+    // if we didn't find an anonymous parent, use the explicit one,
+    // whether it's null or not...
+    result = GetParent();
+
+  return result;
+}
+
+void
+nsSVGAnimateElement::UpdateTargetElement()
+{
+  // XXX Follow xlink:href attributes when provided
+  
+  nsCOMPtr<nsIContent> target = GetParentElement();
+
+  if (target)
+  {
+    nsWeakPtr targetElement = do_GetWeakReference(target);
+    if (targetElement && mTargetElement != targetElement)
+    {
+      mTargetElement = targetElement;
+      UpdateTargetAttribute();
+    }
+  }
+  else
+  {
+    mTargetElement = nsnull;
+    mAnimation = nsnull;
+  }
+}
+
+nsISMILAnimAttr*
+nsSVGAnimateElement::GetTargetAttribute()
+{
+  nsISMILAnimAttr* result = nsnull;
+
+  if (mTargetElement)
+  {
+    nsAutoString attributeName;
+
+    GetAttr(kNameSpaceID_None, nsSVGAtoms::attributeName, attributeName);
+
+    nsCOMPtr<nsIAtom> attributeAtom( do_GetAtom(attributeName) );
+    nsCOMPtr<nsISMILAnimElement> 
+      targetElement(do_QueryReferent(mTargetElement));
+
+    if (targetElement && attributeAtom)
+    {
+      result = 
+        targetElement->GetAnimAttribute(kNameSpaceID_None, attributeAtom);
+    }
+  }
+
+  return result;
+}
+
+void
+nsSVGAnimateElement::UpdateTargetAttribute()
+{
+  // XXX Implement XML vs CSS vs auto attribute types
+  nsresult rv;
+  
+  if (mTargetElement)
+  {
+    nsCOMPtr<nsISMILAnimAttr> targetAttribute = GetTargetAttribute();
+
+    if (targetAttribute)
+    {
+      if (!mAnimation)
+        mAnimation = NS_NewSMILAnimationFunction();
+      NS_ENSURE_TRUE(mAnimation,);
+
+      rv = mAnimation->Init(*targetAttribute);
+      NS_ENSURE_SUCCESS(rv,);
+
+      SetAnimationProperties();
+
+      nsCOMPtr<nsISMILTimeClient> timeClient( do_QueryInterface(mAnimation) );
+      NS_ENSURE_TRUE(timeClient,);
+      if (mTimedElement)
+        mTimedElement->SetTimeClient(timeClient);
+
+      nsCOMPtr<nsISMILAnimationRegistry> registry = GetAnimationRegistry();
+      NS_ENSURE_TRUE(registry,);
+
+      nsCOMPtr<nsISMILComposable> composable( do_QueryInterface(mAnimation) );
+      NS_ENSURE_TRUE(composable,);
+
+      registry->RegisterComposable(targetAttribute, composable);
+    }
+    else
+    {
+      // XXX Attribute doesn't exist or it isn't animatable, mark document
+      // in error
+      // (if necessary, we might re-arrange the GetTargetAttribute method so we
+      // can produce separate errors for when the element is not animatable and
+      // when the attribute can't be found or isn't animatable)
+    }
+  }
+  /* else: We may still be loading, ignore for now. This will be called again
+   * when our parent changes. */
+}
+
+/*
+ * After re-initialising an animation element with a new target attribute, it is
+ * necessary to reset all the properties for that element. That is because the
+ * animation element needs to know the type of the target attribute so it knows
+ * how to interpret the value specifications it is given as "from", "to" etc.
+ * parameters.
+ */
+void
+nsSVGAnimateElement::SetAnimationProperties()
+{
+  nsAutoString result;
+
+  NS_ASSERTION(mAnimation, "Animation not created");
+  NS_ASSERTION(mAnimation->IsInitialised(), "Animation not initialised");
+
+  if (mAnimation && mAnimation->IsInitialised())
+  {
+    if (HasAttr(kNameSpaceID_None, nsSVGAtoms::accumulate))
+    {
+      if (NS_SUCCEEDED(GetAttr(kNameSpaceID_None, nsSVGAtoms::accumulate,
+                               result)))
+        mAnimation->SetAccumulate(result);
+    }
+
+    if (HasAttr(kNameSpaceID_None, nsSVGAtoms::additive))
+    {
+      if (NS_SUCCEEDED(GetAttr(kNameSpaceID_None, nsSVGAtoms::additive,
+                               result)))
+        mAnimation->SetAdditive(result);
+    }
+
+    if (HasAttr(kNameSpaceID_None, nsSVGAtoms::by))
+    {
+      if (NS_SUCCEEDED(GetAttr(kNameSpaceID_None, nsSVGAtoms::by, result)))
+        mAnimation->SetBy(result);
+    }
+
+    if (HasAttr(kNameSpaceID_None, nsSVGAtoms::calcMode))
+    {
+      if (NS_SUCCEEDED(GetAttr(kNameSpaceID_None, nsSVGAtoms::calcMode,
+                               result)))
+        mAnimation->SetCalcMode(result);
+    }
+
+    if (HasAttr(kNameSpaceID_None, nsSVGAtoms::from))
+    {
+      if (NS_SUCCEEDED(GetAttr(kNameSpaceID_None, nsSVGAtoms::from, result)))
+        mAnimation->SetFrom(result);
+    }
+
+    if (HasAttr(kNameSpaceID_None, nsSVGAtoms::keyTimes))
+    {
+      if (NS_SUCCEEDED(GetAttr(kNameSpaceID_None, nsSVGAtoms::keyTimes,
+                               result)))
+        mAnimation->SetKeyTimes(result);
+    }
+
+    if (HasAttr(kNameSpaceID_None, nsSVGAtoms::keySplines))
+    {
+      if (NS_SUCCEEDED(GetAttr(kNameSpaceID_None, nsSVGAtoms::keySplines,
+                               result)))
+        mAnimation->SetKeySplines(result);
+    }
+
+    if (HasAttr(kNameSpaceID_None, nsSVGAtoms::to))
+    {
+      if (NS_SUCCEEDED(GetAttr(kNameSpaceID_None, nsSVGAtoms::to, result)))
+        mAnimation->SetTo(result);
+    }
+
+    if (HasAttr(kNameSpaceID_None, nsSVGAtoms::values))
+    {
+      if (NS_SUCCEEDED(GetAttr(kNameSpaceID_None, nsSVGAtoms::values, result)))
+        mAnimation->SetValues(result);
+    }
+  }
+}
+
Index: /cvsroot/mozilla/content/svg/content/src/nsSVGAnimatedLength.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/svg/content/src/nsSVGAnimatedLength.cpp,v
retrieving revision 1.8
diff -u -r1.8 nsSVGAnimatedLength.cpp
--- /cvsroot/mozilla/content/svg/content/src/nsSVGAnimatedLength.cpp	31 Jan 2005 19:45:10 -0000	1.8
+++ /cvsroot/mozilla/content/svg/content/src/nsSVGAnimatedLength.cpp	14 Sep 2005 10:44:19 -0000
@@ -41,6 +41,10 @@
 #include "nsSVGAnimatedLength.h"
 #include "nsSVGLength.h"
 #include "nsContentUtils.h"
+#ifdef MOZ_SMIL
+#include "nsISMILAnimVal.h"
+#include "nsISMILAnimAttr.h"
+#endif // MOZ_SMIL
 
 
 ////////////////////////////////////////////////////////////////////////
@@ -49,6 +53,9 @@
 class nsSVGAnimatedLength : public nsIDOMSVGAnimatedLength,
                             public nsSVGValue,
                             public nsISVGValueObserver,
+#ifdef MOZ_SMIL
+                            public nsISMILAnimAttr,
+#endif // MOZ_SMIL
                             public nsSupportsWeakReference
 {
 protected:
@@ -74,12 +81,24 @@
                                      modificationType aModType);
   NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
                                      modificationType aModType);
+
+#ifdef MOZ_SMIL
+  // nsISMILAnimAttr
+  virtual nsISMILAnimVal*       GetBaseValue();
+  virtual nsresult              SetAnimValue(nsISMILAnimVal& aValue);
+  virtual nsresult              Create(nsISMILAnimVal** aResult) const;
+  virtual nsresult              CreateFromSpec(const nsAString& aSpec,
+                                               nsISMILAnimVal** aResult) const;
+#endif // MOZ_SMIL
   
   // nsISupportsWeakReference
   // implementation inherited from nsSupportsWeakReference
   
 protected:
   nsCOMPtr<nsIDOMSVGLength> mBaseVal;
+#ifdef MOZ_SMIL
+  nsCOMPtr<nsIDOMSVGLength> mAnimVal;
+#endif // MOZ_SMIL
 };
 
 
@@ -102,8 +121,8 @@
 void
 nsSVGAnimatedLength::Init(nsIDOMSVGLength* baseVal)
 {
+  if (!baseVal) return;
   mBaseVal = baseVal;
-  if (!mBaseVal) return;
   nsCOMPtr<nsISVGValue> val = do_QueryInterface(mBaseVal);
   NS_ASSERTION(val, "baseval needs to implement nsISVGValue interface");
   if (!val) return;
@@ -122,6 +141,9 @@
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedLength)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver)
+#ifdef MOZ_SMIL
+  NS_INTERFACE_MAP_ENTRY(nsISMILAnimAttr)
+#endif // MOZ_SMIL
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedLength)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue)
 NS_INTERFACE_MAP_END
@@ -159,8 +181,22 @@
 NS_IMETHODIMP
 nsSVGAnimatedLength::GetAnimVal(nsIDOMSVGLength * *aAnimVal)
 {
+#ifndef MOZ_SMIL
   *aAnimVal = mBaseVal;
   NS_ADDREF(*aAnimVal);
+#else
+  nsresult rv = NS_OK;
+
+  if (!mAnimVal && mBaseVal)
+  {
+    nsCOMPtr<nsISVGLength> length( do_QueryInterface(mBaseVal) );
+    if (length)
+      rv = length->GetAnimValue(getter_AddRefs(mAnimVal));
+  }
+
+  NS_IF_ADDREF(*aAnimVal = mAnimVal);
+#endif // MOZ_SMIL
+
   return NS_OK;
 }
 
@@ -183,6 +219,83 @@
   return NS_OK;
 }
 
+#ifdef MOZ_SMIL
+//----------------------------------------------------------------------
+// nsISMILAnimAttr methods
+
+nsISMILAnimVal*
+nsSVGAnimatedLength::GetBaseValue()
+{
+  nsISMILAnimVal *result;
+  nsresult rv = mBaseVal->QueryInterface(NS_GET_IID(nsISMILAnimVal),
+                                         (void**)&result);
+  return result;
+}
+
+nsresult
+nsSVGAnimatedLength::SetAnimValue(nsISMILAnimVal& aValue)
+{
+  // TODO[1]: Check for equality before assigning
+  WillModify(mod_other);
+  nsCOMPtr<nsISMILAnimVal> animLength( do_QueryInterface(mAnimVal) );
+  animLength->Set(aValue);
+  DidModify(mod_other);
+
+  return NS_OK;
+}
+
+nsresult
+nsSVGAnimatedLength::Create(nsISMILAnimVal** aResult) const
+{
+  nsISVGLength* length = nsnull;
+  nsISMILAnimVal* result = nsnull;
+
+  nsresult rv = NS_NewSVGLength(&length);
+
+  if (NS_SUCCEEDED(rv) && length)
+    rv = length->GetAnimVal(&result);
+  else
+    result = nsnull;
+
+  NS_IF_RELEASE(length);
+
+  // GetAnimVal will add ref
+  *aResult = result;
+
+  return rv;
+}
+
+nsresult
+nsSVGAnimatedLength::CreateFromSpec(const nsAString& aSpec,
+                                    nsISMILAnimVal** aResult) const
+{
+  NS_ASSERTION(aResult, "NULL pointer provided for storing new value.");
+
+  if (!aResult)
+    return NS_ERROR_NULL_POINTER;
+  
+  *aResult = nsnull;
+  
+  // TODO[2] The syntax for numbers differs between XML attributes and CSS
+  // properties. Does the "attributeType" property affect this?
+
+  nsCOMPtr<nsISVGLength> length;
+
+  nsresult rv = NS_NewSVGLength(getter_AddRefs(length), aSpec);
+  NS_ENSURE_SUCCESS(rv,rv);
+
+  rv = length->ConvertToSpecifiedUnits(nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER);
+  NS_ENSURE_SUCCESS(rv,rv);
+
+  rv = length->GetAnimVal(aResult);
+  NS_ENSURE_SUCCESS(rv,rv);
+
+  // GetAnimVal will add ref
+
+  return rv;
+}
+#endif // MOZ_SMIL
+
 ////////////////////////////////////////////////////////////////////////
 // Exported creation functions
 
Index: /cvsroot/mozilla/content/svg/content/src/nsSVGAtomList.h
===================================================================
RCS file: /cvsroot/mozilla/content/svg/content/src/nsSVGAtomList.h,v
retrieving revision 1.24
diff -u -r1.24 nsSVGAtomList.h
--- /cvsroot/mozilla/content/svg/content/src/nsSVGAtomList.h	26 Aug 2005 02:49:49 -0000	1.24
+++ /cvsroot/mozilla/content/svg/content/src/nsSVGAtomList.h	14 Sep 2005 10:44:20 -0000
@@ -55,6 +55,9 @@
  ******/
 
 // tags
+#ifdef MOZ_SMIL
+SVG_ATOM(animate, "animate")
+#endif
 SVG_ATOM(circle, "circle")
 SVG_ATOM(clipPath, "clipPath")
 SVG_ATOM(defs, "defs")
@@ -207,6 +210,29 @@
 SVG_ATOM(y1, "y1")
 SVG_ATOM(y2, "y2")
 SVG_ATOM(zoomAndPan, "zoomAndPan")
+
+// SMIL properties (to be integrated with the others later)
+#ifdef MOZ_SMIL
+SVG_ATOM(accumulate, "accumulate")
+SVG_ATOM(additive, "additive")
+SVG_ATOM(attributeName, "attributeName")
+SVG_ATOM(attributeType, "attributeType")
+SVG_ATOM(begin, "begin")
+SVG_ATOM(by, "by")
+SVG_ATOM(calcMode, "calcMode")
+SVG_ATOM(dur, "dur")
+SVG_ATOM(end, "end")
+SVG_ATOM(from, "from")
+SVG_ATOM(keySplines, "keySplines")
+SVG_ATOM(keyTimes, "keyTimes")
+SVG_ATOM(max, "max")
+SVG_ATOM(min, "min")
+SVG_ATOM(repeatCount, "repeatCount")
+SVG_ATOM(repeatDur, "repeatDur")
+SVG_ATOM(restart, "restart")
+SVG_ATOM(to, "to")
+SVG_ATOM(values, "values")
+#endif
   
 // transformation keywords
 SVG_ATOM(matrix, "matrix")
Index: /cvsroot/mozilla/content/svg/content/src/nsSVGElement.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/svg/content/src/nsSVGElement.cpp,v
retrieving revision 1.80
diff -u -r1.80 nsSVGElement.cpp
--- /cvsroot/mozilla/content/svg/content/src/nsSVGElement.cpp	25 Aug 2005 21:31:07 -0000	1.80
+++ /cvsroot/mozilla/content/svg/content/src/nsSVGElement.cpp	14 Sep 2005 10:44:22 -0000
@@ -92,6 +92,9 @@
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver)
   NS_INTERFACE_MAP_ENTRY(nsISVGContent)
+#ifdef MOZ_SMIL
+  NS_INTERFACE_MAP_ENTRY(nsISMILAnimElement)
+#endif // MOZ_SMIL
 // provided by nsGenericElement:
 //  NS_INTERFACE_MAP_ENTRY(nsIStyledContent)
 //  NS_INTERFACE_MAP_ENTRY(nsIContent)
@@ -213,7 +216,10 @@
       attrValue.SetTo(proxy);
     }
     else {
-      attrValue.SetTo(svg_value);
+      // We don't want to continue on and call SetAttrAndNotify, as
+      // the SVGValue has already done that for us.  Returning early
+      // is safe as no event attributes are also SVGValues.
+      return NS_OK;
     }
   }
   else if (aName == nsSVGAtoms::style && aNamespaceID == kNameSpaceID_None) {
@@ -872,3 +878,23 @@
 
   return aAttr;
 }
+
+#ifdef MOZ_SMIL
+//----------------------------------------------------------------------
+// nsISMILAnimElement methods
+
+// This should be overridden as necessary, e.g. to ensure some attributes are
+// not animatable
+
+nsISMILAnimAttr*
+nsSVGElement::GetAnimAttribute(PRInt32 aNamespaceID, nsIAtom* aName)
+{
+  nsCOMPtr<nsISMILAnimAttr> result;
+  nsCOMPtr<nsISVGValue> attr = GetMappedAttribute(aNamespaceID, aName);
+
+  if (attr != nsnull)
+    result = do_QueryInterface(attr);
+
+  return result;
+}
+#endif // MOZ_SMIL
Index: /cvsroot/mozilla/content/svg/content/src/nsSVGElement.h
===================================================================
RCS file: /cvsroot/mozilla/content/svg/content/src/nsSVGElement.h,v
retrieving revision 1.47
diff -u -r1.47 nsSVGElement.h
--- /cvsroot/mozilla/content/svg/content/src/nsSVGElement.h	25 Aug 2005 21:57:31 -0000	1.47
+++ /cvsroot/mozilla/content/svg/content/src/nsSVGElement.h	14 Sep 2005 10:44:22 -0000
@@ -53,10 +53,16 @@
 #include "nsWeakReference.h"
 #include "nsISVGContent.h"
 #include "nsICSSStyleRule.h"
+#ifdef MOZ_SMIL
+#include "nsISMILAnimElement.h"
+#endif // MOZ_SMIL
 
 class nsSVGElement : public nsGenericElement,    // :nsIXMLContent:nsIStyledContent:nsIContent
                      public nsISVGValueObserver, 
                      public nsSupportsWeakReference, // :nsISupportsWeakReference
+#ifdef MOZ_SMIL
+                     public nsISMILAnimElement,
+#endif // MOZ_SMIL
                      public nsISVGContent
 {
 protected:
@@ -122,6 +128,12 @@
 
   // nsISVGContent
   virtual void ParentChainChanged(); 
+
+#ifdef MOZ_SMIL
+  // nsISVGAnimationTarget
+  virtual nsISMILAnimAttr*
+  GetAnimAttribute(PRInt32 aNamespaceID, nsIAtom* aName);
+#endif // MOZ_SMIL
   
 protected:
   // Hooks for subclasses
Index: /cvsroot/mozilla/content/svg/content/src/nsSVGElementFactory.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/svg/content/src/nsSVGElementFactory.cpp,v
retrieving revision 1.26
diff -u -r1.26 nsSVGElementFactory.cpp
--- /cvsroot/mozilla/content/svg/content/src/nsSVGElementFactory.cpp	26 Aug 2005 02:49:49 -0000	1.26
+++ /cvsroot/mozilla/content/svg/content/src/nsSVGElementFactory.cpp	14 Sep 2005 10:44:23 -0000
@@ -100,6 +100,10 @@
 NS_NewSVGClipPathElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
 nsresult
 NS_NewSVGTextPathElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
+#ifdef MOZ_SMIL
+nsresult
+NS_NewSVGAnimateElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
+#endif // MOZ_SMIL
 
 static PRBool gSVGEnabled;
 static const char SVG_PREF_STR[] = "svg.enabled";
@@ -205,6 +209,10 @@
     return NS_NewSVGClipPathElement(aResult, aNodeInfo);
   if (name == nsSVGAtoms::textPath)
     return NS_NewSVGTextPathElement(aResult, aNodeInfo);
+#ifdef MOZ_SMIL
+  if (name == nsSVGAtoms::animate)
+    return NS_NewSVGAnimateElement(aResult, aNodeInfo);
+#endif // MOZ_SMIL
 
   // if we don't know what to create, just create a standard xml element:
   return NS_NewXMLElement(aResult, aNodeInfo);
Index: /cvsroot/mozilla/content/svg/content/src/nsSVGLength.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/svg/content/src/nsSVGLength.cpp,v
retrieving revision 1.21
diff -u -r1.21 nsSVGLength.cpp
--- /cvsroot/mozilla/content/svg/content/src/nsSVGLength.cpp	9 Aug 2005 13:53:00 -0000	1.21
+++ /cvsroot/mozilla/content/svg/content/src/nsSVGLength.cpp	14 Sep 2005 10:44:25 -0000
@@ -49,10 +49,18 @@
 #include "nsISVGValueUtils.h"
 #include "nsWeakReference.h"
 #include "nsContentUtils.h"
+#ifdef MOZ_SMIL
+#include "nsISMILAnimVal.h"
+#include "nsDOMError.h"
+#endif // MOZ_SMIL
 
 ////////////////////////////////////////////////////////////////////////
 // nsSVGLength class
 
+#ifdef MOZ_SMIL
+class nsSVGLength__Anim__;
+#endif // MOZ_SMIL
+
 class nsSVGLength : public nsISVGLength,
                     public nsSVGValue,
                     public nsISVGValueObserver,
@@ -79,6 +87,10 @@
 
   // nsISVGLength interface:
   NS_IMETHOD SetContext(nsSVGCoordCtx* context);
+#ifdef MOZ_SMIL
+  virtual nsresult      GetAnimValue(nsIDOMSVGLength** aResult);
+  virtual nsresult      GetAnimVal(nsISMILAnimVal** aResult);
+#endif // MOZ_SMIL
   
   // nsISVGValue interface:
   NS_IMETHOD SetValueString(const nsAString& aValue);
@@ -104,8 +116,59 @@
   float mValueInSpecifiedUnits;
   PRUint16 mSpecifiedUnitType;
   nsRefPtr<nsSVGCoordCtx> mContext;
+#ifdef MOZ_SMIL
+  nsWeakPtr               mAnimValue;
+#endif // MOZ_SMIL
 };
 
+#ifdef MOZ_SMIL
+class nsSVGLength__Anim__ : public nsISVGLength,
+                            public nsSVGValue,
+                            public nsISVGValueObserver,
+                            public nsISMILAnimVal,
+                            public nsSupportsWeakReference
+{
+public:
+  nsSVGLength__Anim__(nsSVGLength& aSource);
+
+  // nsISupports interface:
+  NS_DECL_ISUPPORTS
+
+  // nsIDOMSVGLength interface:
+  NS_DECL_NSIDOMSVGLENGTH
+  
+  // nsISMILAnimVal interface:
+  virtual bool      ComputeDistance(const nsISMILAnimVal& aTo,
+                                    PRFloat64& aDistance) const;
+  virtual nsresult  Interpolate(const nsISMILAnimVal& aEndValue,
+                                float aUnitDistance,
+                                nsISMILAnimVal& aResult);
+  virtual bool      Add(const nsISMILAnimVal& aAddedValue);
+  virtual bool      Set(const nsISMILAnimVal& aNewValue);
+  virtual bool      Repeat(PRUint32 aCount,
+                           const nsISMILAnimVal* aRepeatValue);
+
+  // nsISVGLength interface:
+  NS_IMETHOD SetContext(nsSVGCoordCtx* context);
+  virtual nsresult      GetAnimValue(nsIDOMSVGLength** aResult);
+  virtual nsresult      GetAnimVal(nsISMILAnimVal** aResult);
+
+  // nsISVGValue interface:
+  NS_IMETHOD SetValueString(const nsAString& aValue);
+  NS_IMETHOD GetValueString(nsAString& aValue);
+
+  // nsISVGValueObserver interface:
+  NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable,
+                                     modificationType aModType);
+  NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
+                                     modificationType aModType);
+
+protected:
+  float                 mCanonicalValue;
+  nsRefPtr<nsSVGLength> mBase;
+  PRPackedBool          mIsAnimated:1;
+};
+#endif // MOZ_SMIL
 
 //----------------------------------------------------------------------
 // Implementation
@@ -170,6 +233,9 @@
   NS_INTERFACE_MAP_ENTRY(nsISVGLength)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGLength)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+#ifdef MOZ_SMIL
+  NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISMILAnimVal, new nsSVGLength__Anim__(*this))
+#endif // MOZ_SMIL
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGLength)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue)
 NS_INTERFACE_MAP_END
@@ -529,6 +595,64 @@
   return NS_OK;
 }
 
+#ifdef MOZ_SMIL
+nsresult
+nsSVGLength::GetAnimValue(nsIDOMSVGLength** aResult)
+{
+  nsIDOMSVGLength* result = nsnull;
+  nsresult rv;
+
+  NS_ASSERTION(aResult, "Pointer for storing result is NULL.");
+
+  if (!aResult)
+    return NS_ERROR_NULL_POINTER;
+
+  if (!mAnimValue)
+  {
+    nsSVGLength__Anim__* animValue = new nsSVGLength__Anim__(*this);
+    if (!animValue)
+    {
+      rv = NS_ERROR_OUT_OF_MEMORY;
+    }
+    else
+    {
+      result = NS_STATIC_CAST(nsIDOMSVGLength*, animValue);
+      result->AddRef();
+      mAnimValue = 
+        do_GetWeakReference(NS_STATIC_CAST(nsIDOMSVGLength*, animValue));
+    }
+  }
+  else
+  {
+    CallQueryReferent(mAnimValue.get(), &result);
+  }
+
+  *aResult = result;
+
+  return rv;
+}
+
+nsresult
+nsSVGLength::GetAnimVal(nsISMILAnimVal** aResult)
+{
+  NS_ASSERTION(aResult, "NULL parameter passed for storing result");
+
+  if (!aResult)
+    return NS_ERROR_NULL_POINTER;
+
+  *aResult = nsnull;
+
+  nsIDOMSVGLength* length;
+  nsresult rv = GetAnimValue(&length);
+
+  if (NS_SUCCEEDED(rv) && length)
+    CallQueryInterface(length, aResult);
+
+  // GetAnimValue() will addref
+
+  return rv;
+}
+#endif // MOZ_SMIL
 
 //----------------------------------------------------------------------
 // Implementation helpers:
@@ -596,3 +720,352 @@
   }
 }
 
+#ifdef MOZ_SMIL
+//----------------------------------------------------------------------
+// nsSVGLength__Anim__
+
+nsSVGLength__Anim__::nsSVGLength__Anim__(nsSVGLength& aSource)
+  : mCanonicalValue(0.0f),
+    mBase(&aSource),
+    mIsAnimated(PR_FALSE)
+{
+}
+
+//----------------------------------------------------------------------
+// nsSVGLength__Anim__::nsISupports
+
+NS_IMPL_ADDREF(nsSVGLength__Anim__)
+NS_IMPL_RELEASE(nsSVGLength__Anim__)
+
+NS_INTERFACE_MAP_BEGIN(nsSVGLength__Anim__)
+  NS_INTERFACE_MAP_ENTRY(nsISVGValue)
+  NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver)
+  NS_INTERFACE_MAP_ENTRY(nsISVGLength)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMSVGLength)
+  NS_INTERFACE_MAP_ENTRY(nsISMILAnimVal)
+  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGLength)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue)
+NS_INTERFACE_MAP_END
+
+//----------------------------------------------------------------------
+// nsSVGLength__Anim__::nsIDOMSVGLength
+
+NS_IMETHODIMP
+nsSVGLength__Anim__::GetUnitType(PRUint16 *aUnitType)
+{
+  return mBase->GetUnitType(aUnitType);
+}
+
+NS_IMETHODIMP
+nsSVGLength__Anim__::GetValue(float *aValue)
+{
+  if (mIsAnimated)
+  {
+    *aValue = mCanonicalValue;
+    return NS_OK;
+  }
+  else
+  {
+    return mBase->GetValue(aValue);
+  }
+}
+
+NS_IMETHODIMP
+nsSVGLength__Anim__::SetValue(float aValue)
+{
+  if (mIsAnimated)
+  {
+    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+  }
+  else
+  {
+    WillModify();
+    return mBase->SetValue(aValue);
+    DidModify();
+  }
+}
+
+NS_IMETHODIMP
+nsSVGLength__Anim__::GetValueInSpecifiedUnits(float *aValueInSpecifiedUnits)
+{
+  if (mIsAnimated)
+    return NS_ERROR_NOT_IMPLEMENTED; // TODO
+  else
+    return mBase->GetValueInSpecifiedUnits(aValueInSpecifiedUnits);
+}
+
+NS_IMETHODIMP
+nsSVGLength__Anim__::SetValueInSpecifiedUnits(float aValueInSpecifiedUnits)
+{
+  if (mIsAnimated)
+  {
+    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+  }
+  else
+  {
+    WillModify();
+    return mBase->SetValueInSpecifiedUnits(aValueInSpecifiedUnits);
+    DidModify();
+  }
+}
+
+NS_IMETHODIMP
+nsSVGLength__Anim__::GetValueAsString(nsAString & aValueAsString)
+{
+  if (mIsAnimated)
+    return NS_ERROR_NOT_IMPLEMENTED; // TODO
+  else
+    return mBase->GetValueAsString(aValueAsString);
+}
+
+NS_IMETHODIMP
+nsSVGLength__Anim__::SetValueAsString(const nsAString & aValueAsString)
+{
+  if (mIsAnimated)
+  {
+    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+  }
+  else
+  {
+    WillModify();
+    return mBase->SetValueAsString(aValueAsString);
+    DidModify();
+  }
+}
+
+NS_IMETHODIMP
+nsSVGLength__Anim__::NewValueSpecifiedUnits(PRUint16 unitType, float valueInSpecifiedUnits)
+{
+  if (mIsAnimated)
+  {
+    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+  }
+  else
+  {
+    WillModify();
+    return mBase->NewValueSpecifiedUnits(unitType, valueInSpecifiedUnits);
+    DidModify();
+  }
+}
+
+NS_IMETHODIMP
+nsSVGLength__Anim__::ConvertToSpecifiedUnits(PRUint16 unitType)
+{
+  if (mIsAnimated)
+  {
+    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+  }
+  else
+  {
+    WillModify();
+    return mBase->ConvertToSpecifiedUnits(unitType);
+    DidModify();
+  }
+}
+
+NS_IMETHODIMP
+nsSVGLength__Anim__::GetTransformedValue(nsIDOMSVGMatrix *matrix,
+                                 float *_retval)
+{
+  if (mIsAnimated)
+    return NS_ERROR_NOT_IMPLEMENTED; // TODO
+  else
+    return mBase->GetTransformedValue(matrix, _retval);
+}
+
+//----------------------------------------------------------------------
+// nsSVGLength__Anim__::nsISMILAnimVal
+  
+bool
+nsSVGLength__Anim__::ComputeDistance(const nsISMILAnimVal& aTo,
+                                     PRFloat64& aDistance) const
+{
+  // XXX
+  aDistance = 0.0;
+  return false;
+}
+
+nsresult
+nsSVGLength__Anim__::Interpolate(const nsISMILAnimVal& aEndValue,
+                                 float aUnitDistance,
+                                 nsISMILAnimVal& aResult)
+{
+  /*
+   * We wouldn't have to cast away const-ness if GetValue was a const member.
+   */
+  nsSVGLength__Anim__* end = (nsSVGLength__Anim__*)&aEndValue;
+  if (!end)
+    return NS_ERROR_FAILURE;
+
+  nsSVGLength__Anim__* length = NS_STATIC_CAST(nsSVGLength__Anim__*, &aResult);
+  if (!length)
+    return NS_ERROR_FAILURE;
+
+  nsresult rv = NS_OK;
+
+  float startVal;
+  rv = GetValue(&startVal);
+  NS_ENSURE_SUCCESS(rv,rv);
+
+  float endVal;
+  rv = end->GetValue(&endVal);
+  NS_ENSURE_SUCCESS(rv,rv);
+
+  length->mCanonicalValue =
+    (startVal + (endVal - startVal) * aUnitDistance);
+  length->mIsAnimated = PR_TRUE;
+
+  return NS_OK;
+}
+
+bool
+nsSVGLength__Anim__::Add(const nsISMILAnimVal& aAddedValue)
+{
+  /*
+   * We wouldn't have to cast away const-ness if GetValue was a const member.
+   */
+  nsSVGLength__Anim__* add = (nsSVGLength__Anim__*)&aAddedValue;
+
+  if (!add)
+    return false;
+
+  float value;
+  add->GetValue(&value);
+
+  WillModify();
+  mCanonicalValue += value;
+  mIsAnimated = PR_TRUE;
+  DidModify();
+
+  return true;
+}
+
+bool
+nsSVGLength__Anim__::Repeat(PRUint32 aCount,
+                            const nsISMILAnimVal* aRepeatValue)
+{
+  float value = mCanonicalValue;
+
+  if (aRepeatValue)
+  {
+    /*
+     * We wouldn't have to cast away const-ness if GetValue was a const member.
+     */
+    nsSVGLength__Anim__* repeat = (nsSVGLength__Anim__*)&aRepeatValue;
+    if (!repeat)
+      return false;
+    repeat->GetValue(&value);
+  }
+
+  WillModify();
+  mCanonicalValue = value * aCount;
+  mIsAnimated = PR_TRUE;
+  DidModify();
+
+  return true;
+}
+
+bool
+nsSVGLength__Anim__::Set(const nsISMILAnimVal& aNewValue)
+{
+  nsSVGLength__Anim__* length = (nsSVGLength__Anim__*)&aNewValue;
+
+  if (!length)
+    return false;
+
+  WillModify();
+  length->GetValue(&mCanonicalValue);
+  mIsAnimated = PR_TRUE;
+  DidModify();
+  return true;
+}
+
+//----------------------------------------------------------------------
+// nsSVGLength__Anim__::nsISVGLength
+
+NS_IMETHODIMP
+nsSVGLength__Anim__::SetContext(nsSVGCoordCtx* context)
+{
+  WillModify();
+  nsresult rv = mBase->SetContext(context);
+  DidModify();
+  return rv;
+  // TODO[2]: Update stuff
+}
+
+nsresult
+nsSVGLength__Anim__::GetAnimValue(nsIDOMSVGLength** aResult)
+{
+  if (aResult)
+  {
+    NS_ADDREF(*aResult = this);
+    return NS_OK;
+  }
+  else
+  {
+    return NS_ERROR_NULL_POINTER;
+  }
+}
+
+nsresult
+nsSVGLength__Anim__::GetAnimVal(nsISMILAnimVal** aResult)
+{
+  if (aResult)
+  {
+    NS_ADDREF(*aResult = this);
+    return NS_OK;
+  }
+  else
+  {
+    return NS_ERROR_NULL_POINTER;
+  }
+}
+
+//----------------------------------------------------------------------
+// nsSVGLength__Anim__::nsISVGValue
+
+NS_IMETHODIMP
+nsSVGLength__Anim__::SetValueString(const nsAString& aValue)
+{
+  if (mIsAnimated)
+  {
+    return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
+  }
+  else
+  {
+    WillModify();
+    return mBase->SetValueString(aValue);
+    DidModify();
+  }
+}
+
+NS_IMETHODIMP
+nsSVGLength__Anim__::GetValueString(nsAString& aValue)
+{
+  if (mIsAnimated)
+    return NS_ERROR_NOT_IMPLEMENTED; // TODO
+  else
+    return mBase->GetValueString(aValue);
+}
+
+//----------------------------------------------------------------------
+// nsSVGLength__Anim__::nsISVGValueObserver
+
+NS_IMETHODIMP
+nsSVGLength__Anim__::WillModifySVGObservable(nsISVGValue* observable,
+                                     modificationType aModType)
+{
+  WillModify(aModType);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSVGLength__Anim__::DidModifySVGObservable(nsISVGValue* observable,
+                                    modificationType aModType)
+{
+  DidModify(aModType);
+  return NS_OK;
+}
+#endif // MOZ_SMIL
+
Index: /cvsroot/mozilla/content/svg/content/src/nsSVGSVGElement.cpp
===================================================================
RCS file: /cvsroot/mozilla/content/svg/content/src/nsSVGSVGElement.cpp,v
retrieving revision 1.53
diff -u -r1.53 nsSVGSVGElement.cpp
--- /cvsroot/mozilla/content/svg/content/src/nsSVGSVGElement.cpp	25 Aug 2005 21:31:07 -0000	1.53
+++ /cvsroot/mozilla/content/svg/content/src/nsSVGSVGElement.cpp	14 Sep 2005 10:44:28 -0000
@@ -69,6 +69,10 @@
 #include "nsSVGEnum.h"
 #include "nsISVGChildFrame.h"
 #include "nsGUIEvent.h"
+#ifdef MOZ_SMIL
+#include "nsISMILAnimationController.h"
+#include "nsISMILAnimationRegistry.h"
+#endif // MOZ_SMIL
 
 typedef nsSVGStylableElement nsSVGSVGElementBase;
 
@@ -110,6 +114,9 @@
   NS_IMETHOD_(float) GetPreviousTranslate_x();
   NS_IMETHOD_(float) GetPreviousTranslate_y();
   NS_IMETHOD_(float) GetPreviousScale();
+#ifdef MOZ_SMIL
+  NS_IMETHOD_(nsISMILAnimationRegistry*) GetAnimationRegistry();
+#endif // MOZ_SMIL
 
   // nsIStyledContent interface
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
@@ -123,9 +130,20 @@
 protected:
   // nsSVGElement overrides
   PRBool IsEventName(nsIAtom* aName);
+#ifdef MOZ_SMIL
+  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                              nsIContent* aBindingParent,
+                              PRBool aCompileEventHandlers);
+  virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
+                              PRBool aNullParent = PR_TRUE);
+#endif // MOZ_SMIL
 
   // implementation helpers:
   void GetScreenPosition(PRInt32 &x, PRInt32 &y);
+#ifdef MOZ_SMIL
+  nsISMILAnimationController* GetAnimationController(nsIDocument* aDocument,
+                                                     PRBool aCreate = PR_FALSE);
+#endif // MOZ_SMIL
   
   nsCOMPtr<nsIDOMSVGAnimatedLength> mWidth;
   nsCOMPtr<nsIDOMSVGAnimatedLength> mHeight;
@@ -146,6 +164,11 @@
   float                             mPreviousScale;
   PRBool                            mZooming;
 
+#ifdef MOZ_SMIL
+  // animation
+  nsCOMPtr<nsISMILAnimationRegistry>   mAnimationRegistry;
+#endif // MOZ_SMIL
+  
   PRInt32 mRedrawSuspendCount;
 };
 
@@ -1344,6 +1367,34 @@
   return mPreviousScale;
 }
 
+#ifdef MOZ_SMIL
+nsISMILAnimationRegistry*
+nsSVGSVGElement::GetAnimationRegistry()
+{
+  nsISMILAnimationRegistry* result = nsnull;
+
+  if (mAnimationRegistry)
+  {
+    result = mAnimationRegistry;
+  }
+  else
+  {
+    // We must not be the outermost SVG element, try to find it
+    nsCOMPtr<nsIDOMSVGSVGElement> outerSVGDOM;
+
+    nsresult rv = GetOwnerSVGElement(getter_AddRefs(outerSVGDOM));
+
+    if (NS_SUCCEEDED(rv) && outerSVGDOM)
+    {
+      nsCOMPtr<nsISVGSVGElement> outerSVG( do_QueryInterface(outerSVGDOM) );
+      result = outerSVG->GetAnimationRegistry();
+    }
+  }
+
+  return result;
+}
+#endif // MOZ_SMIL
+
 //----------------------------------------------------------------------
 // nsIStyledContent methods
 
@@ -1480,6 +1531,60 @@
          aName == nsSVGAtoms::onzoom;
 }
 
+#ifdef MOZ_SMIL
+nsresult
+nsSVGSVGElement::BindToTree(nsIDocument* aDocument,
+                            nsIContent* aParent,
+                            nsIContent* aBindingParent,
+                            PRBool aCompileEventHandlers)
+{
+  nsCOMPtr<nsIDOMSVGSVGElement> outerSVG;
+
+  GetOwnerSVGElement(getter_AddRefs(outerSVG));
+
+  PRBool outermost = (outerSVG == nsnull);
+
+  nsCOMPtr<nsISMILAnimationController> smilController = 
+    GetAnimationController(aDocument, PR_TRUE);
+  NS_ASSERTION(smilController, "Couldn't get animation controller");
+
+  if (!mAnimationRegistry && outermost)
+  {
+    // We are now the outermost SVG element
+    mAnimationRegistry = NS_NewSMILAnimationRegistry();
+    NS_ENSURE_TRUE(mAnimationRegistry, NS_ERROR_FAILURE);
+  }
+  else if (mAnimationRegistry && !outermost)
+  {
+    mAnimationRegistry = nsnull;
+  }
+
+  nsresult rv = nsSVGSVGElementBase::BindToTree(aDocument, aParent,
+                                                aBindingParent,
+                                                aCompileEventHandlers);
+  NS_ENSURE_SUCCESS(rv,rv);
+
+  // Eventually this will be done at the same time as the SVGLoad event but
+  // given that we don't currently support externalResourcesRequired,
+  // starting up the animation at this time is roughly the same
+  if (mAnimationRegistry && smilController)
+    rv = mAnimationRegistry->SetController(smilController);
+
+  return rv;
+}
+
+void
+nsSVGSVGElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
+{
+  if (mAnimationRegistry)
+  {
+    mAnimationRegistry->SetController(nsnull);
+  }
+
+  nsSVGSVGElementBase::UnbindFromTree(aDeep, aNullParent);
+}
+#endif // MOZ_SMIL
+
 //----------------------------------------------------------------------
 // implementation helpers
 void nsSVGSVGElement::GetScreenPosition(PRInt32 &x, PRInt32 &y)
@@ -1508,3 +1613,39 @@
     y = rect.y;
   }
 }
+
+#ifdef MOZ_SMIL
+nsISMILAnimationController*
+nsSVGSVGElement::GetAnimationController(nsIDocument* aDocument,
+                                        PRBool aCreate /* = PR_FALSE */)
+{
+  nsISMILAnimationController* result = nsnull;
+
+  nsIPresShell* presShell;
+  nsPresContext* context;
+
+  if ((aDocument)
+      &&
+      (presShell = aDocument->GetShellAt(0))
+      &&
+      (context = presShell->GetPresContext()))
+  {
+    nsIAnimationController* controller = context->GetAnimationController();
+    if (controller)
+    {
+      nsresult rv = CallQueryInterface(controller, &result);
+
+      if (NS_FAILED(rv))
+        result = nsnull;
+    }
+    else if (aCreate)
+    {
+      result = NS_NewSMILAnimationController();
+      context->SetAnimationController(result);
+    }
+  }
+
+  return result;
+}
+#endif // MOZ_SMIL
+
Index: /cvsroot/mozilla/content/Makefile.in
===================================================================
RCS file: /cvsroot/mozilla/content/Makefile.in,v
retrieving revision 1.10
diff -u -r1.10 Makefile.in
--- /cvsroot/mozilla/content/Makefile.in	18 Apr 2005 06:33:19 -0000	1.10
+++ /cvsroot/mozilla/content/Makefile.in	14 Sep 2005 10:44:31 -0000
@@ -53,6 +53,10 @@
 DIRS            += xtf
 endif
 
+ifdef MOZ_SMIL
+DIRS			+= smil
+endif
+
 DIRS           += events
 
 include $(topsrcdir)/config/rules.mk
Index: /cvsroot/mozilla/dom/public/nsIDOMClassInfo.h
===================================================================
RCS file: /cvsroot/mozilla/dom/public/nsIDOMClassInfo.h,v
retrieving revision 1.69
diff -u -r1.69 nsIDOMClassInfo.h
--- /cvsroot/mozilla/dom/public/nsIDOMClassInfo.h	26 Aug 2005 02:49:49 -0000	1.69
+++ /cvsroot/mozilla/dom/public/nsIDOMClassInfo.h	14 Sep 2005 10:44:34 -0000
@@ -248,6 +248,10 @@
   eDOMClassInfo_SVGDocument_id,
 
   // SVG element classes
+#ifdef MOZ_SMIL
+  eDOMClassInfo_SVGAnimateElement_id,
+  eDOMClassInfo_SVGAnimationElement_id,
+#endif // MOZ_SMIL
   eDOMClassInfo_SVGCircleElement_id,
   eDOMClassInfo_SVGClipPathElement_id,
   eDOMClassInfo_SVGDefsElement_id,
Index: /cvsroot/mozilla/dom/public/idl/svg/Makefile.in
===================================================================
RCS file: /cvsroot/mozilla/dom/public/idl/svg/Makefile.in,v
retrieving revision 1.20
diff -u -r1.20 Makefile.in
--- /cvsroot/mozilla/dom/public/idl/svg/Makefile.in	26 Aug 2005 02:49:50 -0000	1.20
+++ /cvsroot/mozilla/dom/public/idl/svg/Makefile.in	14 Sep 2005 10:44:35 -0000
@@ -117,4 +117,10 @@
 		nsIDOMSVGZoomEvent.idl \
 		$(NULL)
 
+ifdef MOZ_SMIL
+XPIDLSRCS += nsIDOMSVGAnimateElement.idl \
+			 nsIDOMSVGAnimationElement.idl \
+			 $(NULL)
+endif
+
 include $(topsrcdir)/config/rules.mk
Index: /cvsroot/mozilla/dom/public/idl/svg/nsIDOMSVGAnimateElement.idl
===================================================================
RCS file: /cvsroot/mozilla/dom/public/idl/svg/nsIDOMSVGAnimateElement.idl
diff -N dom/public/idl/svg/nsIDOMSVGAnimateElement.idl
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/dom/public/idl/svg/nsIDOMSVGAnimateElement.idl	14 Sep 2005 10:44:35 -0000
@@ -0,0 +1,43 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * The Initial Developer of the Original Code is
+ * Crocodile Clips Ltd..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIDOMSVGAnimationElement.idl"
+
+[scriptable, uuid(0c4297e8-68d0-471d-a933-64132ccc5b97)]
+interface nsIDOMSVGAnimateElement : nsIDOMSVGAnimationElement {};
+
Index: /cvsroot/mozilla/dom/public/idl/svg/nsIDOMSVGAnimationElement.idl
===================================================================
RCS file: /cvsroot/mozilla/dom/public/idl/svg/nsIDOMSVGAnimationElement.idl
diff -N dom/public/idl/svg/nsIDOMSVGAnimationElement.idl
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/dom/public/idl/svg/nsIDOMSVGAnimationElement.idl	14 Sep 2005 10:44:36 -0000
@@ -0,0 +1,63 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * The Initial Developer of the Original Code is
+ * Crocodile Clips Ltd..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIDOMSVGElement.idl"
+
+[scriptable, uuid(8f2ccf31-5544-4a9d-8927-ef35d242039e)]
+interface nsIDOMSVGAnimationElement
+  : nsIDOMSVGElement
+/*
+        The SVG DOM makes use of multiple interface inheritance.
+        Since XPCOM only supports single interface inheritance,
+        the best thing that we can do is to promise that whenever
+        an object implements _this_ interface it will also
+        implement the following interfaces. (We then have to QI to
+        hop between them.)
+        
+    nsIDOMSVGTests,
+    nsIDOMSVGExternalResourcesRequired,
+    smil::ElementTimeControl,
+    events::nsIDOMEventTarget
+*/
+{ 
+  readonly attribute nsIDOMSVGElement targetElement;
+  float getStartTime ( );
+  float getCurrentTime ( );
+  float getSimpleDuration ( );
+          // raises (nsIDOMDOMException)
+};
Index: /cvsroot/mozilla/dom/src/base/nsDOMClassInfo.cpp
===================================================================
RCS file: /cvsroot/mozilla/dom/src/base/nsDOMClassInfo.cpp,v
retrieving revision 1.307
diff -u -r1.307 nsDOMClassInfo.cpp
--- /cvsroot/mozilla/dom/src/base/nsDOMClassInfo.cpp	1 Sep 2005 23:02:54 -0000	1.307
+++ /cvsroot/mozilla/dom/src/base/nsDOMClassInfo.cpp	14 Sep 2005 10:44:57 -0000
@@ -328,6 +328,10 @@
 #include "nsIDOMSVGAnimPresAspRatio.h"
 #include "nsIDOMSVGAnimatedRect.h"
 #include "nsIDOMSVGAnimatedString.h"
+#ifdef MOZ_SMIL
+#include "nsIDOMSVGAnimateElement.h"
+#include "nsIDOMSVGAnimationElement.h"
+#endif // MOZ_SMIL
 #include "nsIDOMSVGAnimTransformList.h"
 #include "nsIDOMSVGCircleElement.h"
 #include "nsIDOMSVGClipPathElement.h"
@@ -854,6 +858,12 @@
                            DOCUMENT_SCRIPTABLE_FLAGS)
 
   // SVG element classes
+#ifdef MOZ_SMIL
+  NS_DEFINE_CLASSINFO_DATA(SVGAnimateElement, nsElementSH,
+                           ELEMENT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(SVGAnimationElement, nsElementSH,
+                           ELEMENT_SCRIPTABLE_FLAGS)
+#endif // MOZ_SMIL
   NS_DEFINE_CLASSINFO_DATA(SVGCircleElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(SVGClipPathElement, nsElementSH,
@@ -2393,6 +2403,19 @@
 
   // SVG element classes
 
+#ifdef MOZ_SMIL
+  DOM_CLASSINFO_MAP_BEGIN(SVGAnimateElement, nsIDOMSVGAnimateElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimateElement)
+    DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN(SVGAnimationElement, nsIDOMSVGAnimationElement)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement)
+    DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
+  DOM_CLASSINFO_MAP_END
+#endif // MOZ_SMIL
+
   DOM_CLASSINFO_MAP_BEGIN(SVGCircleElement, nsIDOMSVGCircleElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGCircleElement)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
Index: /cvsroot/mozilla/layout/base/Makefile.in
===================================================================
RCS file: /cvsroot/mozilla/layout/base/Makefile.in,v
retrieving revision 1.21
diff -u -r1.21 Makefile.in
--- /cvsroot/mozilla/layout/base/Makefile.in	4 May 2005 20:22:28 -0000	1.21
+++ /cvsroot/mozilla/layout/base/Makefile.in	14 Sep 2005 10:44:59 -0000
@@ -112,6 +112,10 @@
 		nsStyleConsts.h \
 		$(NULL)
 
+ifdef MOZ_SMIL
+EXPORTS		+= nsIAnimationController.h
+endif
+
 CPPSRCS		= \
 		nsBidiUtils.cpp \
 		nsCSSColorUtils.cpp \
Index: /cvsroot/mozilla/layout/base/nsIAnimationController.h
===================================================================
RCS file: /cvsroot/mozilla/layout/base/nsIAnimationController.h
diff -N layout/base/nsIAnimationController.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ /cvsroot/mozilla/layout/base/nsIAnimationController.h	14 Sep 2005 10:44:59 -0000
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * Contributor(s):
+ *   Brian Birtles <birtles@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_IANIMATIONCONTROLLER_H__
+#define __NS_IANIMATIONCONTROLLER_H__
+
+#include "nsISupports.h"
+
+////////////////////////////////////////////////////////////////////////
+// nsIAnimationController: Animation controller
+
+// {7aa203ea-e6e1-4cca-84af-a29f0eaedef5}
+#define NS_IANIMATIONCONTROLLER_IID \
+{ 0x7aa203ea, 0xe6e1, 0x4cca, { 0x84, 0xaf, 0xa2, 0x9f, 0x0e, 0xae, 0xde, 0xf5 } }
+
+class nsIAnimationController : public nsISupports
+{
+public:
+  NS_DEFINE_STATIC_IID_ACCESSOR(NS_IANIMATIONCONTROLLER_IID)
+
+  virtual nsresult  Pause()=0;
+  virtual nsresult  Resume()=0;
+};
+
+#endif // __NS_IANIMATIONCONTROLLER_H__
+
Index: /cvsroot/mozilla/layout/base/nsPresContext.cpp
===================================================================
RCS file: /cvsroot/mozilla/layout/base/nsPresContext.cpp,v
retrieving revision 3.290
diff -u -r3.290 nsPresContext.cpp
--- /cvsroot/mozilla/layout/base/nsPresContext.cpp	23 Aug 2005 23:52:16 -0000	3.290
+++ /cvsroot/mozilla/layout/base/nsPresContext.cpp	14 Sep 2005 10:45:02 -0000
@@ -267,6 +267,10 @@
   NS_IF_RELEASE(mDeviceContext);
   NS_IF_RELEASE(mLookAndFeel);
   NS_IF_RELEASE(mLangGroup);
+
+#ifdef MOZ_SMIL
+  NS_IF_RELEASE(mAnimationController);
+#endif
 }
 
 NS_IMPL_ISUPPORTS2(nsPresContext, nsPresContext, nsIObserver)
Index: /cvsroot/mozilla/layout/base/nsPresContext.h
===================================================================
RCS file: /cvsroot/mozilla/layout/base/nsPresContext.h,v
retrieving revision 3.152
diff -u -r3.152 nsPresContext.h
--- /cvsroot/mozilla/layout/base/nsPresContext.h	23 Aug 2005 23:52:16 -0000	3.152
+++ /cvsroot/mozilla/layout/base/nsPresContext.h	14 Sep 2005 10:45:04 -0000
@@ -56,6 +56,10 @@
 #include "nsCRT.h"
 #include "nsIPrintSettings.h"
 #include "nsPropertyTable.h"
+#ifdef MOZ_SMIL
+#include "nsIAnimationController.h"
+#endif
+
 #ifdef IBMBIDI
 class nsBidiPresUtils;
 #endif // IBMBIDI
@@ -626,6 +630,18 @@
    */
   const nscoord* GetBorderWidthTable() { return mBorderWidthTable; }
 
+#ifdef MOZ_SMIL
+  nsIAnimationController* GetAnimationController()
+  { return mAnimationController; }
+  void SetAnimationController(nsIAnimationController* aController)
+  {
+      NS_IF_ADDREF(aController);
+      nsIAnimationController* temp = mAnimationController;
+      mAnimationController = aController;
+      NS_IF_RELEASE(temp);
+  }
+#endif
+
 protected:
   NS_HIDDEN_(void) SetImgAnimations(nsIContent *aParent, PRUint16 aMode);
   NS_HIDDEN_(void) GetDocumentColorPreferences();
@@ -669,6 +685,10 @@
   nsBidiPresUtils*      mBidiUtils;
 #endif
 
+#ifdef MOZ_SMIL
+  nsIAnimationController* mAnimationController; // [STRONG]
+#endif
+
   nsCOMPtr<nsITheme> mTheme;
   nsCOMPtr<nsILanguageAtomService> mLangService;
   nsCOMPtr<nsIPrintSettings> mPrintSettings;
Index: /cvsroot/mozilla/layout/build/Makefile.in
===================================================================
RCS file: /cvsroot/mozilla/layout/build/Makefile.in,v
retrieving revision 1.128
diff -u -r1.128 Makefile.in
--- /cvsroot/mozilla/layout/build/Makefile.in	18 Aug 2005 12:31:30 -0000	1.128
+++ /cvsroot/mozilla/layout/build/Makefile.in	14 Sep 2005 10:45:06 -0000
@@ -188,6 +188,12 @@
 endif
 endif
 
+ifdef MOZ_SMIL
+SHARED_LIBRARY_LIBS += \
+				$(DIST)/lib/$(LIB_PREFIX)gkconsmil_s.$(LIB_SUFFIX) \
+				$(NULL)
+endif
+
 EXTRA_DSO_LDOPTS = \
 		$(LIBS_DIR) \
 		$(EXTRA_DSO_LIBS) \
Index: /cvsroot/mozilla/config/autoconf.mk.in
===================================================================
RCS file: /cvsroot/mozilla/config/autoconf.mk.in,v
retrieving revision 3.366
diff -u -r3.366 autoconf.mk.in
--- /cvsroot/mozilla/config/autoconf.mk.in	31 Aug 2005 22:15:30 -0000	3.366
+++ /cvsroot/mozilla/config/autoconf.mk.in	14 Sep 2005 10:45:08 -0000
@@ -197,6 +197,7 @@
 MOZ_LIBART_CFLAGS = @MOZ_LIBART_CFLAGS@
 MOZ_ENABLE_CANVAS = @MOZ_ENABLE_CANVAS@
 MOZ_CAIRO_CFLAGS = @MOZ_CAIRO_CFLAGS@
+MOZ_SMIL = @MOZ_SMIL@
 TX_EXE = @TX_EXE@
 
 # Mac's don't like / in a #include, so we include the libart
Index: /cvsroot/mozilla/allmakefiles.sh
===================================================================
RCS file: /cvsroot/mozilla/allmakefiles.sh,v
retrieving revision 1.585
diff -u -r1.585 allmakefiles.sh
--- /cvsroot/mozilla/allmakefiles.sh	31 Aug 2005 22:15:27 -0000	1.585
+++ /cvsroot/mozilla/allmakefiles.sh	14 Sep 2005 10:45:43 -0000
@@ -1340,6 +1340,15 @@
 "
 fi
 
+# smil
+if [ "$MOZ_SMIL" ]; then
+    MAKEFILES_content="$MAKEFILES_content
+	content/smil/Makefile
+	content/smil/public/Makefile
+	content/smil/src/Makefile
+"
+fi
+
 # xtf
 if [ "$MOZ_XTF" ]; then
     MAKEFILES_content="$MAKEFILES_content
Index: /cvsroot/mozilla/configure.in
===================================================================
RCS file: /cvsroot/mozilla/configure.in,v
retrieving revision 1.1524
diff -u -r1.1524 configure.in
--- /cvsroot/mozilla/configure.in	2 Sep 2005 02:59:01 -0000	1.1524
+++ /cvsroot/mozilla/configure.in	14 Sep 2005 10:46:03 -0000
@@ -5020,6 +5020,17 @@
 dnl fi
 
 dnl ========================================================
+dnl SMIL
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(smil,
+[  --enable-smil            Enable SMIL animation support],
+    MOZ_SMIL=1,
+    MOZ_SMIL= )
+if test -n "$MOZ_SMIL"; then
+  AC_DEFINE(MOZ_SMIL)
+fi
+
+dnl ========================================================
 dnl Transformiix
 dnl ========================================================
 
@@ -6633,6 +6644,7 @@
 AC_SUBST(MOZ_SVG_RENDERER_GDIPLUS)
 AC_SUBST(MOZ_SVG_RENDERER_LIBART)
 AC_SUBST(MOZ_SVG_RENDERER_CAIRO)
+AC_SUBST(MOZ_SMIL)
 AC_SUBST(TX_EXE)
 AC_SUBST(MOZ_JS_LIBS)
 AC_SUBST(MOZ_PSM)
