Bug 216462: Add support for basic SVG animation (SMIL). Disabled in builds by default. r+sr=roc

This commit is contained in:
Brian Birtles 2009-01-14 20:38:07 -08:00
parent b28ea75f40
commit 0a47d48dae
208 changed files with 11119 additions and 20 deletions
browser/installer
config
configure.in
content
dom
layout

@ -342,6 +342,9 @@ bin/res/entityTables/*
; svg
bin/res/svg.css
bin/components/dom_svg.xpt
#ifdef MOZ_SMIL
bin/components/dom_smil.xpt
#endif
; [Personal Security Manager]
;

@ -337,6 +337,9 @@ bin\res\entityTables\*
; svg
bin\res\svg.css
bin\components\dom_svg.xpt
#ifdef MOZ_SMIL
bin\components\dom_smil.xpt
#endif
; [Personal Security Manager]
;

@ -229,6 +229,7 @@ MOZ_SVG = @MOZ_SVG@
MOZ_LIBART_CFLAGS = @MOZ_LIBART_CFLAGS@
MOZ_ENABLE_CANVAS = @MOZ_ENABLE_CANVAS@
MOZ_CAIRO_CFLAGS = @MOZ_CAIRO_CFLAGS@
MOZ_SMIL = @MOZ_SMIL@
MOZ_XSLT_STANDALONE = @MOZ_XSLT_STANDALONE@
MOZ_PREF_EXTENSIONS = @MOZ_PREF_EXTENSIONS@

@ -5759,6 +5759,17 @@ if test -n "$MOZ_SVG"; then
AC_DEFINE(MOZ_SVG)
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 Installer
dnl ========================================================
@ -7807,6 +7818,7 @@ AC_SUBST(MOZ_XTF)
AC_SUBST(MOZ_NO_INSPECTOR_APIS)
AC_SUBST(MOZ_PREF_EXTENSIONS)
AC_SUBST(MOZ_SVG)
AC_SUBST(MOZ_SMIL)
AC_SUBST(MOZ_XSLT_STANDALONE)
AC_SUBST(MOZ_JS_LIBS)
AC_SUBST(MOZ_PSM)

@ -59,6 +59,10 @@ ifdef MOZ_XTF
PARALLEL_DIRS += xtf
endif
ifdef MOZ_SMIL
PARALLEL_DIRS += smil
endif
ifdef MOZ_MATHML
PARALLEL_DIRS += mathml
endif

@ -121,7 +121,8 @@ NS_NewXULElement(nsIContent** aResult, nsINodeInfo* aNodeInfo);
#ifdef MOZ_SVG
nsresult
NS_NewSVGElement(nsIContent** aResult, nsINodeInfo* aNodeInfo);
NS_NewSVGElement(nsIContent** aResult, nsINodeInfo* aNodeInfo,
PRBool aFromParser);
#endif
nsresult

@ -59,6 +59,9 @@ class nsAttrValue;
class nsAttrName;
class nsTextFragment;
class nsIDocShell;
#ifdef MOZ_SMIL
class nsISMILAttr;
#endif // MOZ_SMIL
// IID for the nsIContent interface
#define NS_ICONTENT_IID \
@ -859,6 +862,16 @@ public:
*/
virtual void SaveSubtreeState() = 0;
#ifdef MOZ_SMIL
/*
* Returns a new nsISMILAttr that allows the caller to animate the given
* attribute on this element.
*
* The CALLER OWNS the result and is responsible for deleting it.
*/
virtual nsISMILAttr* GetAnimatedAttr(const nsIAtom* aName) = 0;
#endif // MOZ_SMIL
private:
/**
* Hook for implementing GetClasses. This is guaranteed to only be

@ -54,6 +54,9 @@
#include "nsNodeInfoManager.h"
#include "nsIStreamListener.h"
#include "nsIObserver.h"
#ifdef MOZ_SMIL
class nsSMILAnimationController;
#endif // MOZ_SMIL
class nsIContent;
class nsPresContext;
@ -1109,6 +1112,11 @@ public:
*/
PRBool IsShowing() { return mIsShowing; }
#ifdef MOZ_SMIL
// Getter for this document's SMIL Animation Controller
virtual nsSMILAnimationController* GetAnimationController() = 0;
#endif // MOZ_SMIL
protected:
~nsIDocument()
{

@ -171,6 +171,11 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID);
#include "mozAutoDocUpdate.h"
#ifdef MOZ_SMIL
#include "nsSMILAnimationController.h"
#include "imgIContainer.h"
#endif // MOZ_SMIL
#ifdef MOZ_LOGGING
// so we can get logging even in release builds
@ -1777,6 +1782,13 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mCatalogSheets)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mVisitednessChangedURIs)
#ifdef MOZ_SMIL
// Traverse animation components
if (tmp->mAnimationController) {
tmp->mAnimationController->Traverse(&cb);
}
#endif // MOZ_SMIL
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_PRESERVED_WRAPPER
if (tmp->mSubDocuments && tmp->mSubDocuments->ops) {
@ -5255,6 +5267,32 @@ nsDocument::EnumerateExternalResources(nsSubDocEnumFunc aCallback, void* aData)
mExternalResourceMap.EnumerateResources(aCallback, aData);
}
#ifdef MOZ_SMIL
nsSMILAnimationController*
nsDocument::GetAnimationController()
{
// We create the animation controller lazily because most documents won't want
// one and only SVG documents and the like will call this
if (mAnimationController)
return mAnimationController;
mAnimationController = NS_NewSMILAnimationController(this);
// If there's a presContext then check the animation mode and pause if
// necessary.
nsIPresShell *shell = GetPrimaryShell();
if (mAnimationController && shell) {
nsPresContext *context = shell->GetPresContext();
if (context &&
context->ImageAnimationMode() == imgIContainer::kDontAnimMode) {
mAnimationController->Pause(nsSMILTimeContainer::PAUSE_USERPREF);
}
}
return mAnimationController;
}
#endif // MOZ_SMIL
struct DirTable {
const char* mName;
PRUint8 mValue;
@ -7103,6 +7141,12 @@ nsDocument::OnPageShow(PRBool aPersisted)
// Set mIsShowing before firing events, in case those event handlers
// move us around.
mIsShowing = PR_TRUE;
#ifdef MOZ_SMIL
if (mAnimationController) {
mAnimationController->OnPageShow();
}
#endif
nsPageTransitionEvent event(PR_TRUE, NS_PAGE_SHOW, aPersisted);
DispatchEventToWindow(&event);
@ -7133,6 +7177,12 @@ nsDocument::OnPageHide(PRBool aPersisted)
// Set mIsShowing before firing events, in case those event handlers
// move us around.
mIsShowing = PR_FALSE;
#ifdef MOZ_SMIL
if (mAnimationController) {
mAnimationController->OnPageHide();
}
#endif
// Now send out a PageHide event.
nsPageTransitionEvent event(PR_TRUE, NS_PAGE_HIDE, aPersisted);

@ -134,6 +134,9 @@ class nsOnloadBlocker;
class nsUnblockOnloadEvent;
struct PLEvent;
class nsChildContentList;
#ifdef MOZ_SMIL
class nsSMILAnimationController;
#endif // MOZ_SMIL
PR_BEGIN_EXTERN_C
/* Note that these typedefs declare functions, not pointer to
@ -979,6 +982,10 @@ public:
virtual NS_HIDDEN_(void)
EnumerateExternalResources(nsSubDocEnumFunc aCallback, void* aData);
#ifdef MOZ_SMIL
nsSMILAnimationController* GetAnimationController();
#endif // MOZ_SMIL
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDocument, nsIDocument)
/**
@ -1270,6 +1277,10 @@ private:
nsRevocableEventPtr<nsRunnableMethod<nsDocument> > mPendingTitleChangeEvent;
nsExternalResourceMap mExternalResourceMap;
#ifdef MOZ_SMIL
nsAutoPtr<nsSMILAnimationController> mAnimationController;
#endif // MOZ_SMIL
};
#define NS_DOCUMENT_INTERFACE_TABLE_BEGIN(_class) \

@ -54,6 +54,10 @@
#include "nsCycleCollectionParticipant.h"
#include "nsContentUtils.h"
#ifdef MOZ_SMIL
#include "nsISMILAttr.h"
#endif // MOZ_SMIL
class nsIDOMAttr;
class nsIDOMEventListener;
class nsIDOMNodeList;
@ -217,6 +221,14 @@ public:
virtual void AppendTextTo(nsAString& aResult);
virtual void DestroyContent();
virtual void SaveSubtreeState();
#ifdef MOZ_SMIL
virtual nsISMILAttr* GetAnimatedAttr(const nsIAtom* /*aName*/)
{
return nsnull;
}
#endif // MOZ_SMIL
#ifdef DEBUG
virtual void List(FILE* out, PRInt32 aIndent) const;
virtual void DumpContent(FILE* out, PRInt32 aIndent, PRBool aDumpAll) const;

@ -1893,6 +1893,13 @@ nsGenericElement::InternalIsSupported(nsISupports* aObject,
}
}
#endif /* MOZ_SVG */
#ifdef MOZ_SMIL
else if (PL_strcasecmp(f, "TimeControl") == 0) {
if (aVersion.IsEmpty() || PL_strcmp(v, "1.0") == 0) {
*aReturn = PR_TRUE;
}
}
#endif /* MOZ_SMIL */
else {
nsCOMPtr<nsIDOMNSFeatureFactory> factory =
GetDOMFeatureFactory(aFeature, aVersion);

@ -65,6 +65,10 @@
#include "nsIDocument.h"
#include "nsIDOMNodeSelector.h"
#ifdef MOZ_SMIL
#include "nsISMILAttr.h"
#endif // MOZ_SMIL
class nsIDOMAttr;
class nsIDOMEventListener;
class nsIFrame;
@ -427,6 +431,13 @@ public:
virtual void DestroyContent();
virtual void SaveSubtreeState();
#ifdef MOZ_SMIL
virtual nsISMILAttr* GetAnimatedAttr(const nsIAtom* /*aName*/)
{
return nsnull;
}
#endif // MOZ_SMIL
#ifdef DEBUG
virtual void List(FILE* out, PRInt32 aIndent) const
{

@ -1257,6 +1257,25 @@ GK_ATOM(z, "z")
GK_ATOM(zoomAndPan, "zoomAndPan")
#endif
#ifdef MOZ_SMIL
GK_ATOM(accumulate, "accumulate")
GK_ATOM(additive, "additive")
GK_ATOM(attributeName, "attributeName")
GK_ATOM(attributeType, "attributeType")
GK_ATOM(begin, "begin")
GK_ATOM(by, "by")
GK_ATOM(calcMode, "calcMode")
GK_ATOM(css, "CSS")
GK_ATOM(dur, "dur")
GK_ATOM(keySplines, "keySplines")
GK_ATOM(keyTimes, "keyTimes")
GK_ATOM(repeatCount, "repeatCount")
GK_ATOM(repeatDur, "repeatDur")
GK_ATOM(restart, "restart")
GK_ATOM(to, "to")
GK_ATOM(XML, "XML")
#endif
#ifdef MOZ_MATHML
GK_ATOM(MOZcolumnalign, "-moz-math-columnalign")
GK_ATOM(MOZcolumnline, "-moz-math-columnline") // different from columnlines_

@ -243,7 +243,7 @@ NS_NewElement(nsIContent** aResult, PRInt32 aElementType,
#endif
#ifdef MOZ_SVG
if (aElementType == kNameSpaceID_SVG && NS_SVGEnabled()) {
return NS_NewSVGElement(aResult, aNodeInfo);
return NS_NewSVGElement(aResult, aNodeInfo, aFromParser);
}
#endif
if (aElementType == kNameSpaceID_XMLEvents) {

102
content/smil/Makefile.in Normal file

@ -0,0 +1,102 @@
#
# ***** 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 SMIL module.
#
# The Initial Developer of the Original Code is Brian Birtles.
# Portions created by the Initial Developer are Copyright (C) 2005
# 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 *****
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 \
layout \
widget \
gfx \
unicharutil \
dom \
js \
pref \
$(NULL)
CPPSRCS = \
nsSMILAnimationController.cpp \
nsSMILAnimationFunction.cpp \
nsSMILCompositor.cpp \
nsSMILFloatType.cpp \
nsSMILInstanceTime.cpp \
nsSMILKeySpline.cpp \
nsSMILNullType.cpp \
nsSMILParserUtils.cpp \
nsSMILRepeatCount.cpp \
nsSMILSetAnimationFunction.cpp \
nsSMILTimeContainer.cpp \
nsSMILTimedElement.cpp \
nsSMILTimeValue.cpp \
nsSMILTimeValueSpec.cpp \
nsSMILValue.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
ifdef ENABLE_TESTS
TOOL_DIRS += test
endif
EXPORTS = \
nsISMILAnimationElement.h \
nsISMILAttr.h \
nsSMILAnimationController.h \
nsSMILCompositorTable.h \
nsSMILTimeContainer.h \
nsSMILTypes.h \
$(NULL)
include $(topsrcdir)/config/rules.mk
INCLUDES += \
-I$(srcdir)/../base/src \
$(NULL)
DEFINES += -D_IMPL_NS_LAYOUT

@ -0,0 +1,153 @@
/* -*- 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.
*
* The Initial Developer of the Original Code is
* the Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Holbert <dholbert@mozilla.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_ISMILANIMATIONELEMENT_H_
#define NS_ISMILANIMATIONELEMENT_H_
#include "nsISupports.h"
#include "nsIContent.h"
class nsISMILAttr;
//////////////////////////////////////////////////////////////////////////////
// nsISMILAnimationElement: Interface for elements that control the animation of
// some property of another element, e.g. <animate>, <set>.
#define NS_ISMILANIMATIONELEMENT_IID \
{ 0x70ac6eed, 0x0dba, 0x4c11, { 0xa6, 0xc5, 0x15, 0x73, 0xbc, 0x2f, 0x1a, 0xd8 } }
class nsSMILAnimationFunction;
class nsSMILTimeContainer;
class nsSMILTimedElement;
enum nsSMILTargetAttrType {
eSMILTargetAttrType_auto,
eSMILTargetAttrType_CSS,
eSMILTargetAttrType_XML
};
class nsISMILAnimationElement : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISMILANIMATIONELEMENT_IID)
/*
* Returns this element as nsIContent.
*/
virtual const nsIContent& Content() const = 0;
/*
* Non-const version of Content()
*/
virtual nsIContent& Content() = 0;
/*
* Returns the source attribute as an nsAttrValue. The global namespace will
* be used.
*
* (The 'Anim' here and below is largely to avoid conflicts for subclasses
* that derive from nsGenericElement)
*
* @param aName the name of the attr
* @returns PR_TRUE if the attribute was set (even when set to empty string)
* PR_FALSE when not set.
*/
virtual const nsAttrValue* GetAnimAttr(nsIAtom* aName) const = 0;
/*
* Get the current value of an attribute as a string. The global namespace
* will be used.
*
* @param aName the name of the attr
* @param aResult the value (may legitimately be the empty string) [OUT]
* @returns PR_TRUE if the attribute was set (even when set to empty string)
* PR_FALSE when not set.
*/
PRBool GetAnimAttr(nsIAtom* aAttName, nsAString &aResult) const
{
return Content().GetAttr(kNameSpaceID_None, aAttName, aResult);
}
/*
* Check for the presence of an attribute in the global namespace.
*/
PRBool HasAnimAttr(nsIAtom* aAttName) const
{
return Content().HasAttr(kNameSpaceID_None, aAttName);
}
/*
* Returns the target (animated) element.
*/
virtual nsIContent* GetTargetElementContent() = 0;
/*
* Returns the name of the target (animated) attribute or property.
*/
virtual nsIAtom* GetTargetAttributeName() const = 0;
/*
* Returns the type of the target (animated) attribute or property.
*/
virtual nsSMILTargetAttrType GetTargetAttributeType() const = 0;
/*
* Returns the SMIL animation function associated with this animation element.
*
* The animation function is owned by the animation element.
*/
virtual nsSMILAnimationFunction& AnimationFunction() = 0;
/*
* Returns the SMIL timed element associated with this animation element.
*
* The timed element is owned by the animation element.
*/
virtual nsSMILTimedElement& TimedElement() = 0;
/*
* Returns the SMIL timed container root with which this animation element is
* associated (if any).
*/
virtual nsSMILTimeContainer* GetTimeContainer() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsISMILAnimationElement,
NS_ISMILANIMATIONELEMENT_IID)
#endif // NS_ISMILANIMATIONELEMENT_H_

@ -0,0 +1,99 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 ***** */
#ifndef NS_ISMILATTR_H_
#define NS_ISMILATTR_H_
#include "nsStringFwd.h"
class nsSMILValue;
class nsISMILType;
class nsISMILAnimationElement;
////////////////////////////////////////////////////////////////////////
// nsISMILAttr: A variable targeted by SMIL for animation and can therefore have
// an underlying (base) value and an animated value For example, an attribute of
// a particular SVG element.
//
// These objects only exist during the compositing phase of SMIL animation
// calculations. They have a single owner who is responsible for deleting the
// object.
class nsISMILAttr
{
public:
/**
* Creates a new nsSMILValue for this attribute from a string. The string is
* parsed in the context of this attribute so that context-dependent values
* such as em-based units can be resolved into a canonical form suitable for
* animation (including interpolation etc.).
*
* @param aStr A string defining the new value to be created.
* @param aSrcElement The source animation element. This may be needed to
* provided additional context data such as for
* animateTransform where the 'type' attribute is needed to
* parse the value.
* @param aValue Outparam for storing the parsed value.
* @return NS_OK on success or an error code if creation failed.
*/
virtual nsresult ValueFromString(const nsAString& aStr,
const nsISMILAnimationElement* aSrcElement,
nsSMILValue& aValue) const = 0;
/**
* Gets the underlying value of this attribute.
*
* @return an nsSMILValue object. returned_object.IsNull() will be true if an
* error occurred.
*/
virtual nsSMILValue GetBaseValue() const = 0;
/**
* Sets the presentation value of this attribute.
*
* @param aValue The value to set.
* @return NS_OK on success or an error code if setting failed.
*/
virtual nsresult SetAnimValue(const nsSMILValue& aValue) = 0;
/**
* Virtual destructor, to make sure subclasses can clean themselves up.
*/
virtual ~nsISMILAttr() {};
};
#endif // NS_ISMILATTR_H_

196
content/smil/nsISMILType.h Normal file

@ -0,0 +1,196 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert O'Callahan <roc+moz@cs.cmu.edu>
* 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_ISMILTYPE_H_
#define NS_ISMILTYPE_H_
#include "nscore.h"
class nsSMILValue;
//////////////////////////////////////////////////////////////////////////////
// nsISMILType: Interface for defining the basic operations needed for animating
// a particular kind of data (e.g. lengths, colors, transformation matrices).
//
// This interface is never used directly but always through an nsSMILValue that
// bundles together a pointer to a concrete implementation of this interface and
// the data upon which it should operate.
//
// We keep the data and type separate rather than just providing different
// subclasses of nsSMILValue as this allows nsSMILValues to be allocated on the
// stack and directly assigned to one another provided performance benefits for
// the animation code.
//
// Note that different types have different capabilities. Roughly speaking there
// are probably three main types:
//
// +---------------------+---------------+-------------+------------------+
// | CATEGORY: | DISCRETE | LINEAR | ADDITIVE |
// +---------------------+---------------+-------------+------------------+
// | Example: | strings, | path data? | lengths, |
// | | color k/words?| | RGB color values |
// | | | | |
// | -- Assign? | X | X | X |
// | -- Add? | - | X? | X |
// | -- ComputeDistance? | - | - | X? |
// | -- Interpolate? | - | X | X |
// +---------------------+---------------+-------------+------------------+
//
class nsISMILType
{
public:
/**
* Initialises aValue and sets it to some identity value such that adding
* aValue to another value of the same type has no effect.
*
* @pre (aValue.mType == this && aValue.mU is valid)
* || aValue.mType == null-type
* @post aValue.mType == this || NS_FAILED(rv)
*/
virtual nsresult Init(nsSMILValue& aValue) const = 0;
/**
* Destroys any data associated with a value of this type.
*
* @pre aValue.mType == this
* @post aValue.IsNull()
*/
virtual void Destroy(nsSMILValue& aValue) const = 0;
/**
* Assign this object the value of another. Think of this as the assignment
* operator.
*
* @param aDest The left-hand side of the assignment.
* @param aSrc The right-hand side of the assignment.
* @return NS_OK on success, an error code on failure such as when the
* underlying type of the specified object differs.
*
* @pre aDest.mType == aSrc.mType == this
*/
virtual nsresult Assign(nsSMILValue& aDest,
const nsSMILValue& aSrc) const = 0;
/**
* Adds two values.
*
* The count parameter facilitates repetition.
*
* By equation,
*
* aDest += aValueToAdd * aCount
*
* Therefore, if aCount == 0, aDest will be unaltered.
*
* This method will fail if this data type is not additive or the value 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."
*
* If this method fails (e.g. because the data type is not additive), aDest
* will be unaltered.
*
* @param aDest The value to add to.
* @param aValueToAdd The value to add.
* @param aCount The number of times to add aValueToAdd.
* @return NS_OK on success, an error code on failure.
*
* @pre aValueToAdd.mType == aDest.mType == this
*/
virtual nsresult Add(nsSMILValue& aDest,
const nsSMILValue& aValueToAdd,
PRUint32 aCount) const = 0;
/**
* Calculates the 'distance' between two values. This is the distance used in
* paced interpolation.
*
* @param aFrom The start of the interval for which the distance should
* be calculated.
* @param aTo The end of the interval for which the distance should be
* calculated.
* @param aDistance The result of the calculation.
* @return NS_OK on success, or an appropriate error code if there is no
* notion of distance for the underlying data type or the distance
* could not be calculated.
*
* @pre aFrom.mType == aTo.mType == this
*/
virtual nsresult ComputeDistance(const nsSMILValue& aFrom,
const nsSMILValue& aTo,
double& aDistance) const = 0;
/**
* Calculates an interpolated value between two values using the specified
* proportion.
*
* @param aStartVal The value defining the start of the interval of
* interpolation.
* @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.
*
* @pre aStartVal.mType == aEndVal.mType == aResult.mType == this
*/
virtual nsresult Interpolate(const nsSMILValue& aStartVal,
const nsSMILValue& aEndVal,
double aUnitDistance,
nsSMILValue& aResult) const = 0;
/*
* Virtual destructor: Nothing to do here, but subclasses
* may need it.
*/
virtual ~nsISMILType() {};
};
#endif // NS_ISMILTYPE_H_

@ -0,0 +1,511 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Birtles <birtles@gmail.com>
* Daniel Holbert <dholbert@mozilla.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 "nsSMILAnimationController.h"
#include "nsSMILCompositor.h"
#include "nsComponentManagerUtils.h"
#include "nsITimer.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsISMILAnimationElement.h"
#include "nsIDOMSVGAnimationElement.h"
#include "nsSMILTimedElement.h"
//----------------------------------------------------------------------
// nsSMILAnimationController implementation
// In my testing the minimum needed for smooth animation is 36 frames per
// second which seems like a lot (Flash traditionally uses 14fps).
//
// Redrawing is synchronous. This is deliberate so that later we can tune the
// timer based on how long the callback takes. To achieve 36fps we'd need 28ms
// between frames. For now we set the timer interval to be a little less than
// this (to allow for the render itself) and then let performance decay as the
// image gets more complicated and render times increase.
//
const PRUint32 nsSMILAnimationController::kTimerInterval = 22;
//----------------------------------------------------------------------
// ctors, dtors, factory methods
nsSMILAnimationController::nsSMILAnimationController()
: mDocument(nsnull)
{
mAnimationElementTable.Init();
mChildContainerTable.Init();
}
nsSMILAnimationController::~nsSMILAnimationController()
{
if (mTimer) {
mTimer->Cancel();
mTimer = nsnull;
}
if (mForceSampleEvent) {
mForceSampleEvent->Expire();
mForceSampleEvent = nsnull;
}
NS_ASSERTION(mAnimationElementTable.Count() == 0,
"Animation controller shouldn't be tracking any animation"
" elements when it dies.");
}
nsSMILAnimationController* NS_NewSMILAnimationController(nsIDocument* aDoc)
{
nsSMILAnimationController* animationController =
new nsSMILAnimationController();
NS_ENSURE_TRUE(animationController, nsnull);
nsresult rv = animationController->Init(aDoc);
if (NS_FAILED(rv)) {
delete animationController;
animationController = nsnull;
}
return animationController;
}
nsresult
nsSMILAnimationController::Init(nsIDocument* aDoc)
{
NS_ENSURE_ARG_POINTER(aDoc);
mTimer = do_CreateInstance("@mozilla.org/timer;1");
NS_ENSURE_TRUE(mTimer, NS_ERROR_OUT_OF_MEMORY);
// Keep track of document, so we can traverse its set of animation elements
mDocument = aDoc;
Begin();
return NS_OK;
}
//----------------------------------------------------------------------
// nsSMILTimeContainer methods:
void
nsSMILAnimationController::Pause(PRUint32 aType)
{
nsSMILTimeContainer::Pause(aType);
if (mPauseState) {
StopTimer();
}
}
void
nsSMILAnimationController::Resume(PRUint32 aType)
{
PRBool wasPaused = (mPauseState != 0);
nsSMILTimeContainer::Resume(aType);
if (wasPaused && !mPauseState) {
StartTimer();
}
}
nsSMILTime
nsSMILAnimationController::GetParentTime() const
{
// Our parent time is wallclock time
return PR_Now() / PR_USEC_PER_MSEC;
}
//----------------------------------------------------------------------
// Animation element registration methods:
void
nsSMILAnimationController::RegisterAnimationElement(
nsISMILAnimationElement* aAnimationElement)
{
mAnimationElementTable.PutEntry(aAnimationElement);
}
void
nsSMILAnimationController::UnregisterAnimationElement(
nsISMILAnimationElement* aAnimationElement)
{
mAnimationElementTable.RemoveEntry(aAnimationElement);
}
//----------------------------------------------------------------------
// nsSMILAnimationController methods:
nsresult
nsSMILAnimationController::OnForceSample()
{
// Make sure this was a queued call
NS_ENSURE_TRUE(mForceSampleEvent, NS_ERROR_FAILURE);
nsresult rv = NS_OK;
if (!mPauseState) {
// Stop timer-controlled samples first, to avoid race conditions.
rv = StopTimer();
if (NS_SUCCEEDED(rv)) {
// StartTimer does a synchronous sample before it starts the timer.
// This is the sample that we're "forcing" here.
rv = StartTimer();
}
}
mForceSampleEvent = nsnull;
return rv;
}
void
nsSMILAnimationController::FireForceSampleEvent()
{
if (!mForceSampleEvent) {
mForceSampleEvent = new ForceSampleEvent(*this);
if (NS_FAILED(NS_DispatchToCurrentThread(mForceSampleEvent))) {
NS_WARNING("Failed to dispatch force sample event");
mForceSampleEvent = nsnull;
}
}
}
//----------------------------------------------------------------------
// Page show/hide
void
nsSMILAnimationController::OnPageShow()
{
Resume(nsSMILTimeContainer::PAUSE_PAGEHIDE);
}
void
nsSMILAnimationController::OnPageHide()
{
Pause(nsSMILTimeContainer::PAUSE_PAGEHIDE);
}
//----------------------------------------------------------------------
// Cycle-collection support
void
nsSMILAnimationController::Traverse(
nsCycleCollectionTraversalCallback* aCallback)
{
// Traverse last compositor table
if (mLastCompositorTable) {
mLastCompositorTable->EnumerateEntries(CompositorTableEntryTraverse,
aCallback);
}
}
/*static*/ PR_CALLBACK PLDHashOperator
nsSMILAnimationController::CompositorTableEntryTraverse(
nsSMILCompositor* aCompositor,
void* aArg)
{
nsCycleCollectionTraversalCallback* cb =
static_cast<nsCycleCollectionTraversalCallback*>(aArg);
aCompositor->Traverse(cb);
return PL_DHASH_NEXT;
}
void
nsSMILAnimationController::Unlink()
{
mLastCompositorTable = nsnull;
}
//----------------------------------------------------------------------
// Timer-related implementation helpers
/*static*/ void
nsSMILAnimationController::Notify(nsITimer* timer, void* aClosure)
{
nsSMILAnimationController* controller = (nsSMILAnimationController*)aClosure;
NS_ASSERTION(controller->mTimer == timer,
"nsSMILAnimationController::Notify called with incorrect timer");
controller->Sample();
}
nsresult
nsSMILAnimationController::StartTimer()
{
NS_ENSURE_TRUE(mTimer, NS_ERROR_FAILURE);
NS_ASSERTION(mPauseState == 0, "Starting timer but controller is paused.");
// Run the first sample manually
Sample();
//
// XXX Make this self-tuning. Sounds like control theory to me and not
// something I'm familiar with.
//
return mTimer->InitWithFuncCallback(nsSMILAnimationController::Notify,
this,
kTimerInterval,
nsITimer::TYPE_REPEATING_SLACK);
}
nsresult
nsSMILAnimationController::StopTimer()
{
NS_ENSURE_TRUE(mTimer, NS_ERROR_FAILURE);
return mTimer->Cancel();
}
//----------------------------------------------------------------------
// Sample-related methods and callbacks
void
nsSMILAnimationController::DoSample()
{
// STEP 1: Sample the child time containers
//
// When we sample the child time containers they will simply record the sample
// time in document time.
TimeContainerHashtable activeContainers;
activeContainers.Init(mChildContainerTable.Count());
mChildContainerTable.EnumerateEntries(SampleTimeContainers,
&activeContainers);
// STEP 2: (i) Sample the timed elements AND
// (ii) Create a table of compositors
//
// (i) Here we sample the timed elements (fetched from the
// nsISMILAnimationElements) which determine from the active time if the
// element is active and what it's simple time etc. is. This information is
// then passed to its time client (nsSMILAnimationFunction).
//
// (ii) During the same loop we also build up a table that contains one
// compositor for each animated attribute and which maps animated elements to
// the corresponding compositor for their target attribute.
//
// Note that this compositor table needs to be allocated on the heap so we can
// store it until the next sample. This lets us find out which elements were
// animated in sample 'n-1' but not in sample 'n' (and hence need to have
// their animation effects removed in sample 'n').
//
// Parts (i) and (ii) are not functionally related but we combine them here to
// save iterating over the animation elements twice.
// Create the compositor table
nsAutoPtr<nsSMILCompositorTable>
currentCompositorTable(new nsSMILCompositorTable());
if (!currentCompositorTable)
return;
currentCompositorTable->Init(0);
SampleAnimationParams params = { &activeContainers, currentCompositorTable };
nsresult rv = mAnimationElementTable.EnumerateEntries(SampleAnimation,
&params);
if (NS_FAILED(rv)) {
NS_WARNING("SampleAnimationParams failed");
}
activeContainers.Clear();
// STEP 3: Remove animation effects from any no-longer-animated elems/attrs
if (mLastCompositorTable) {
// XXX Remove animation effects from no-longer-animated elements
// * For each compositor in current sample's hash table:
// - Remove entry from *prev sample's* hash table
// * For any entries still remaining in prev sample's hash table:
// - Remove animation from that entry's attribute.
// (For nsSVGLength2, set anim val = base val. For CSS attribs,
// just clear the relevant chunk of OverrideStyle)
}
// STEP 4: Compose currently-animated attributes.
nsSMILCompositor::ComposeAttributes(*currentCompositorTable);
// Update last compositor table
mLastCompositorTable = currentCompositorTable.forget();
}
/*static*/ PR_CALLBACK PLDHashOperator
nsSMILAnimationController::SampleTimeContainers(TimeContainerPtrKey* aKey,
void* aData)
{
NS_ENSURE_TRUE(aKey, PL_DHASH_NEXT);
NS_ENSURE_TRUE(aKey->GetKey(), PL_DHASH_NEXT);
NS_ENSURE_TRUE(aData, PL_DHASH_NEXT);
TimeContainerHashtable* activeContainers
= static_cast<TimeContainerHashtable*>(aData);
nsSMILTimeContainer* container = aKey->GetKey();
if (container->NeedsSample()) {
container->Sample();
activeContainers->PutEntry(container);
}
return PL_DHASH_NEXT;
}
/*static*/ PR_CALLBACK PLDHashOperator
nsSMILAnimationController::SampleAnimation(AnimationElementPtrKey* aKey,
void* aData)
{
NS_ENSURE_TRUE(aKey, PL_DHASH_NEXT);
NS_ENSURE_TRUE(aKey->GetKey(), PL_DHASH_NEXT);
NS_ENSURE_TRUE(aData, PL_DHASH_NEXT);
nsISMILAnimationElement* animElem = aKey->GetKey();
SampleAnimationParams* params = static_cast<SampleAnimationParams*>(aData);
SampleTimedElement(animElem, params->mActiveContainers);
AddAnimationToCompositorTable(animElem, params->mCompositorTable);
return PL_DHASH_NEXT;
}
/*static*/ void
nsSMILAnimationController::SampleTimedElement(
nsISMILAnimationElement* aElement, TimeContainerHashtable* aActiveContainers)
{
nsSMILTimeContainer* timeContainer = aElement->GetTimeContainer();
if (!timeContainer)
return;
// We'd like to call timeContainer->NeedsSample() here and skip all timed
// elements that belong to paused time containers that don't need a sample,
// but that doesn't work because we've already called Sample() on all the time
// containers so the paused ones don't need a sample any more and they'll
// return false.
//
// Instead we build up a hashmap of active time containers during the previous
// step (SampleTimeContainers) and then test here if the container for this
// timed element is in the list.
if (!aActiveContainers->GetEntry(timeContainer))
return;
nsSMILTime containerTime = timeContainer->GetCurrentTime();
aElement->TimedElement().SampleAt(containerTime);
}
/*static*/ void
nsSMILAnimationController::AddAnimationToCompositorTable(
nsISMILAnimationElement* aElement, nsSMILCompositorTable* aCompositorTable)
{
// Add a compositor to the hash table if there's not already one there
nsSMILCompositorKey key;
if (!GetCompositorKeyForAnimation(aElement, key))
// Something's wrong/missing about animation's target; skip this animation
return;
nsSMILCompositor* result = aCompositorTable->PutEntry(key);
// Add this animationElement's animation function to the compositor's list of
// animation functions.
result->AddAnimationFunction(&aElement->AnimationFunction());
}
// Helper function that, given a nsISMILAnimationElement, looks up its target
// element & target attribute and returns a newly-constructed nsSMILCompositor
// for this target.
/*static*/ PRBool
nsSMILAnimationController::GetCompositorKeyForAnimation(
nsISMILAnimationElement* aAnimElem, nsSMILCompositorKey& aResult)
{
// Look up target (animated) element
nsIContent* targetElem = aAnimElem->GetTargetElementContent();
if (!targetElem)
// Animation has no target elem -- skip it.
return PR_FALSE;
// Look up target (animated) attribute
//
// XXXdholbert As mentioned in SMILANIM section 3.1, attributeName may
// have an XMLNS prefix to indicate the XML namespace. Need to parse
// that somewhere.
nsIAtom* attributeName = aAnimElem->GetTargetAttributeName();
if (!attributeName)
// Animation has no target attr -- skip it.
return PR_FALSE;
// Look up target (animated) attribute-type
nsSMILTargetAttrType attributeType = aAnimElem->GetTargetAttributeType();
// Check if an 'auto' attributeType refers to a CSS property or XML attribute.
// Note that SMIL requires we search for CSS properties first. So if they
// overlap, 'auto' = 'CSS'. (SMILANIM 3.1)
//
// XXX This doesn't really work for CSS properties that aren't mapped
// attributes
if (attributeType == eSMILTargetAttrType_auto) {
attributeType = (targetElem->IsAttributeMapped(attributeName))
? eSMILTargetAttrType_CSS
: eSMILTargetAttrType_XML;
}
PRBool isCSS = (attributeType == eSMILTargetAttrType_CSS);
// Construct the key
aResult.mElement = targetElem;
aResult.mAttributeName = attributeName;
aResult.mIsCSS = isCSS;
return PR_TRUE;
}
//----------------------------------------------------------------------
// Add/remove child time containers
nsresult
nsSMILAnimationController::AddChild(nsSMILTimeContainer& aChild)
{
TimeContainerPtrKey* key = mChildContainerTable.PutEntry(&aChild);
NS_ENSURE_TRUE(key,NS_ERROR_OUT_OF_MEMORY);
if (!mPauseState && mChildContainerTable.Count() == 1) {
StartTimer();
}
return NS_OK;
}
void
nsSMILAnimationController::RemoveChild(nsSMILTimeContainer& aChild)
{
mChildContainerTable.RemoveEntry(&aChild);
if (!mPauseState && mChildContainerTable.Count() == 0) {
StopTimer();
}
}

@ -0,0 +1,179 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Birtles <birtles@gmail.com>
* Daniel Holbert <dholbert@mozilla.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_SMILANIMATIONCONTROLLER_H_
#define NS_SMILANIMATIONCONTROLLER_H_
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsTArray.h"
#include "nsITimer.h"
#include "nsTHashtable.h"
#include "nsHashKeys.h"
#include "nsThreadUtils.h" // for nsRunnable
#include "nsSMILTimeContainer.h"
#include "nsSMILCompositorTable.h"
class nsISMILAnimationElement;
class nsIDocument;
//----------------------------------------------------------------------
// nsSMILAnimationController
//
// The animation controller maintains the animation timer and determines the
// sample times and sample rate for all SMIL animations in a document. There is
// at most one animation controller per nsDocument so that frame-rate tuning can
// be performed at a document-level.
//
// The animation controller can contain many child time containers (timed
// document root objects) which may correspond to SVG document fragments within
// a compound document. These time containers can be paused individually or
// here, at the document level.
//
class nsSMILAnimationController : public nsSMILTimeContainer
{
public:
nsSMILAnimationController();
~nsSMILAnimationController();
// nsSMILContainer
virtual void Pause(PRUint32 aType);
virtual void Resume(PRUint32 aType);
virtual nsSMILTime GetParentTime() const;
// Methods for registering and enumerating animation elements
void RegisterAnimationElement(nsISMILAnimationElement* aAnimationElement);
void UnregisterAnimationElement(nsISMILAnimationElement* aAnimationElement);
// Methods for forcing synchronous samples
nsresult OnForceSample();
void FireForceSampleEvent();
// Methods for handling page transitions
void OnPageShow();
void OnPageHide();
// Methods for supporting cycle-collection
void Traverse(nsCycleCollectionTraversalCallback* aCallback);
void Unlink();
protected:
// Typedefs
typedef nsPtrHashKey<nsSMILTimeContainer> TimeContainerPtrKey;
typedef nsTHashtable<TimeContainerPtrKey> TimeContainerHashtable;
typedef nsPtrHashKey<nsISMILAnimationElement> AnimationElementPtrKey;
typedef nsTHashtable<AnimationElementPtrKey> AnimationElementHashtable;
// Types
class ForceSampleEvent : public nsRunnable {
public:
ForceSampleEvent(nsSMILAnimationController &aAnimationController)
: mAnimationController(&aAnimationController) { }
NS_IMETHOD Run() {
if (!mAnimationController)
return NS_OK;
return mAnimationController->OnForceSample();
}
void Expire() { mAnimationController = nsnull; }
private:
nsSMILAnimationController* mAnimationController;
};
struct SampleAnimationParams
{
TimeContainerHashtable* mActiveContainers;
nsSMILCompositorTable* mCompositorTable;
};
// Factory methods
friend nsSMILAnimationController*
NS_NewSMILAnimationController(nsIDocument* aDoc);
nsresult Init(nsIDocument* aDoc);
// Cycle-collection implementation helpers
PR_STATIC_CALLBACK(PLDHashOperator) CompositorTableEntryTraverse(
nsSMILCompositor* aCompositor, void* aArg);
// Timer-related implementation helpers
static void Notify(nsITimer* aTimer, void* aClosure);
nsresult StartTimer();
nsresult StopTimer();
// Sample-related callbacks and implementation helpers
virtual void DoSample();
PR_STATIC_CALLBACK(PLDHashOperator) SampleTimeContainers(
TimeContainerPtrKey* aKey, void* aData);
PR_STATIC_CALLBACK(PLDHashOperator) SampleAnimation(
AnimationElementPtrKey* aKey, void* aData);
PR_STATIC_CALLBACK(PLDHashOperator) AddAnimationToCompositorTable(
AnimationElementPtrKey* aKey, void* aData);
static void SampleTimedElement(nsISMILAnimationElement* aElement,
TimeContainerHashtable* aActiveContainers);
static void AddAnimationToCompositorTable(
nsISMILAnimationElement* aElement, nsSMILCompositorTable* aCompositorTable);
static PRBool GetCompositorKeyForAnimation(nsISMILAnimationElement* aAnimElem,
nsSMILCompositorKey& aResult);
// Methods for adding/removing time containers
virtual nsresult AddChild(nsSMILTimeContainer& aChild);
virtual void RemoveChild(nsSMILTimeContainer& aChild);
// Members
static const PRUint32 kTimerInterval;
nsCOMPtr<nsITimer> mTimer;
AnimationElementHashtable mAnimationElementTable;
TimeContainerHashtable mChildContainerTable;
nsRefPtr<ForceSampleEvent> mForceSampleEvent;
// Store raw ptr to mDocument. It owns the controller, so controller
// shouldn't outlive it
nsIDocument* mDocument;
// Contains compositors used in our last sample. We keep this around
// so we can detect when an element/attribute used to be animated,
// but isn't anymore for some reason. (e.g. if its <animate> element is
// removed or retargeted)
nsAutoPtr<nsSMILCompositorTable> mLastCompositorTable;
};
nsSMILAnimationController* NS_NewSMILAnimationController(nsIDocument *doc);
#endif // NS_SMILANIMATIONCONTROLLER_H_

File diff suppressed because it is too large Load Diff

@ -0,0 +1,364 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Birtles <birtles@gmail.com>
* Daniel Holbert <dholbert@mozilla.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_SMILANIMATIONFUNCTION_H_
#define NS_SMILANIMATIONFUNCTION_H_
#include "nsISMILAttr.h"
#include "nsGkAtoms.h"
#include "nsString.h"
#include "nsSMILTimeValue.h"
#include "nsSMILKeySpline.h"
#include "nsSMILValue.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
#include "nsAttrValue.h"
#include "nsSMILTypes.h"
class nsISMILAnimationElement;
//----------------------------------------------------------------------
// nsSMILAnimationFunction
//
// The animation function calculates animation values. It it is provided with
// time parameters (sample time, repeat iteration etc.) and it uses this to
// build an appropriate animation value by performing interpolation and
// addition operations.
//
// It is responsible for implementing the animation parameters of an animation
// element (e.g. from, by, to, values, calcMode, additive, accumulate, keyTimes,
// keySplines)
//
class nsSMILAnimationFunction
{
public:
nsSMILAnimationFunction();
/*
* Sets the owning animation element which this class uses to query attribute
* values and compare document positions.
*/
void SetAnimationElement(nsISMILAnimationElement* aAnimationElement);
/*
* Sets animation-specific attributes (or marks them dirty, in the case
* of from/to/by/values).
*
* @param aAttribute The attribute being set
* @param aValue The updated value of the attribute.
* @param aResult The nsAttrValue object that may be used for storing the
* parsed result.
* @param aParseResult Outparam used for reporting parse errors. Will be set
* to NS_OK if everything succeeds.
* @returns PR_TRUE if aAttribute is a recognized animation-related
* attribute; PR_FALSE otherwise.
*/
virtual PRBool SetAttr(nsIAtom* aAttribute, const nsAString& aValue,
nsAttrValue& aResult, nsresult* aParseResult = nsnull);
/*
* Unsets the given attribute.
*
* @returns PR_TRUE if aAttribute is a recognized animation-related
* attribute; PR_FALSE otherwise.
*/
virtual PRBool UnsetAttr(nsIAtom* aAttribute);
/**
* Indicate a new sample has occurred.
*
* @param aSampleTime The sample time for this timed element expressed in
* simple time.
* @param aSimpleDuration The simple duration for this timed element.
* @param aRepeatIteration The repeat iteration for this sample. The first
* iteration has a value of 0.
*/
void SampleAt(nsSMILTime aSampleTime,
const nsSMILTimeValue& aSimpleDuration,
PRUint32 aRepeatIteration);
/**
* Indicate to sample using the last value defined for the animation function.
* This value is not normally sampled due to the end-point exclusive timing
* model but only occurs when the fill mode is "freeze" and the active
* duration is an even multiple of the simple duration.
*
* @param aRepeatIteration The repeat iteration for this sample. The first
* iteration has a value of 0.
*/
void SampleLastValue(PRUint32 aRepeatIteration);
/**
* Indicate that this animation is now active. This is used to instruct the
* animation function that it should now add its result to the animation
* sandwich. The begin time is also provided for proper prioritization of
* animation functions, and for this reason, this method must be called
* before either of the Sample methods.
*
* @param aBeginTime The begin time for the newly active interval.
*/
void Activate(nsSMILTime aBeginTime);
/**
* Indicate that this animation is no longer active. This is used to instruct
* the animation function that it should no longer add its result to the
* animation sandwich.
*
* @param aIsFrozen True if this animation should continue to contribute to
* the animation sandwich using the most recent sample
* parameters.
*/
void Inactivate(PRBool aIsFrozen);
/**
* Combines the result of this animation function for the last sample with the
* specified value.
*
* @param aSMILAttr This animation's target attribute. Used here for
* doing attribute-specific parsing of from/to/by/values.
*
* @param aResult The value to compose with.
*/
void ComposeResult(const nsISMILAttr& aSMILAttr, nsSMILValue& aResult);
/**
* Returns the relative priority of this animation to another. The priority is
* used for determining the position of the animation in the animation
* sandwich -- higher priority animations are applied on top of lower
* priority animations.
*
* @return -1 if this animation has lower priority or 1 if this animation has
* higher priority
*
* This method should never return any other value, including 0.
*/
PRInt8 CompareTo(const nsSMILAnimationFunction* aOther) const;
/*
* The following methods are provided so that the compositor can optimize its
* operations 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.
*/
PRBool IsActive() const
{
/*
* - Frozen animations should be considered active for the purposes of
* compositing.
* - This function does not assume that our nsSMILValues (by/from/to/values)
* have already been parsed.
*/
return (mIsActive || mIsFrozen);
}
/**
* 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.
*/
PRBool WillReplace() const;
/**
* Indicates if the parameters for this animation have changed since the last
* time it was composited. This allows rendering to be performed only when
* necessary, particularly when no animations are active.
*
* Note that the caller is responsible for determining if the animation target
* has changed.
*
* @return True if the animation parameters have changed, false otherwise.
*/
PRBool HasChanged() const;
// Comparator utility class, used for sorting nsSMILAnimationFunctions
class Comparator {
public:
PRBool Equals(const nsSMILAnimationFunction* aElem1,
const nsSMILAnimationFunction* aElem2) const {
return (aElem1->CompareTo(aElem2) == 0);
}
PRBool LessThan(const nsSMILAnimationFunction* aElem1,
const nsSMILAnimationFunction* aElem2) const {
return (aElem1->CompareTo(aElem2) < 0);
}
};
protected:
// Typedefs
typedef nsTArray<nsSMILValue> nsSMILValueArray;
// Types
enum nsSMILCalcMode
{
CALC_LINEAR,
CALC_DISCRETE,
CALC_PACED,
CALC_SPLINE
};
// Used for sorting nsSMILAnimationFunctions
nsSMILTime GetBeginTime() const { return mBeginTime; }
// Property getters
PRBool GetAccumulate() const;
PRBool GetAdditive() const;
virtual nsSMILCalcMode GetCalcMode() const;
// Property setters
nsresult SetAccumulate(const nsAString& aAccumulate, nsAttrValue& aResult);
nsresult SetAdditive(const nsAString& aAdditive, nsAttrValue& aResult);
nsresult SetCalcMode(const nsAString& aCalcMode, nsAttrValue& aResult);
nsresult SetKeyTimes(const nsAString& aKeyTimes, nsAttrValue& aResult);
nsresult SetKeySplines(const nsAString& aKeySplines, nsAttrValue& aResult);
// Property un-setters
void UnsetAccumulate();
void UnsetAdditive();
void UnsetCalcMode();
void UnsetKeyTimes();
void UnsetKeySplines();
// Helpers
nsresult InterpolateResult(const nsSMILValueArray& aValues,
nsSMILValue& aResult,
nsSMILValue& aBaseValue);
nsresult AccumulateResult(const nsSMILValueArray& aValues,
nsSMILValue& aResult);
nsresult ComputePacedPosition(const nsSMILValueArray& aValues,
double aSimpleProgress,
double& aIntervalProgress,
const nsSMILValue*& aFrom,
const nsSMILValue*& aTo);
double ComputePacedTotalDistance(const nsSMILValueArray& aValues) const;
void ScaleSimpleProgress(double& aProgress);
void ScaleIntervalProgress(double& aProgress, PRUint32 aIntervalIndex,
PRUint32 aNumIntervals);
// Convenience attribute getters -- use these instead of querying
// mAnimationElement as these may need to be overridden by subclasses
virtual PRBool HasAttr(nsIAtom* aAttName) const;
virtual const nsAttrValue* GetAttr(nsIAtom* aAttName) const;
virtual PRBool GetAttr(nsIAtom* aAttName,
nsAString& aResult) const;
PRBool ParseAttr(nsIAtom* aAttName, const nsISMILAttr& aSMILAttr,
nsSMILValue& aResult) const;
nsresult GetValues(const nsISMILAttr& aSMILAttr,
nsSMILValueArray& aResult);
void UpdateValuesArray();
PRBool IsToAnimation() const;
PRBool IsAdditive() const;
void CheckKeyTimes(PRUint32 aNumValues);
void CheckKeySplines(PRUint32 aNumValues);
// Members
// -------
static nsAttrValue::EnumTable sAdditiveTable[];
static nsAttrValue::EnumTable sCalcModeTable[];
static nsAttrValue::EnumTable sAccumulateTable[];
nsTArray<double> mKeyTimes;
nsTArray<nsSMILKeySpline> mKeySplines;
PRPackedBool mIsActive;
PRPackedBool mIsFrozen;
// 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.
nsSMILTime mSampleTime; // sample time within simple dur
nsSMILTimeValue mSimpleDuration;
PRUint32 mRepeatIteration;
PRPackedBool mLastValue;
PRPackedBool mHasChanged;
nsSMILTime mBeginTime; // document time
// The owning animation element. This is used for sorting based on document
// position and for fetching attribute values stored in the element.
// Raw pointer is OK here, because this nsSMILAnimationFunction can't outlive
// its owning animation element.
nsISMILAnimationElement* mAnimationElement;
// Which attributes have been set but have had errors. This is not used for
// all attributes but only those which have specified error behaviour
// associated with them.
PRUint16 mErrorFlags;
// This is for the very specific case where we have a 'to' animation that is
// frozen part way through the simple duration and there are other active
// lower-priority animations targetting the same attribute. In this case
// SMILANIM 3.3.6 says:
//
// The value for F(t) when a to-animation is frozen (at the end of the
// simple duration) is just the to value. If a to-animation is frozen
// anywhere within the simple duration (e.g., using a repeatCount of "2.5"),
// the value for F(t) when the animation is frozen is the value computed for
// the end of the active duration. Even if other, lower priority animations
// are active while a to-animation is frozen, the value for F(t) does not
// change.
//
// To implement this properly we'd need to force a resample of all the lower
// priority animations at the active end of this animation--something which
// would introduce unwanted coupling between the timing and animation model.
// Instead we just save the value calculated when this animation is frozen (in
// which case this animation will be sampled at the active end and the lower
// priority animations should be sampled at a time pretty close to this,
// provided we have a reasonable frame rate and we aren't seeking).
//
// @see
// http://www.w3.org/TR/2001/REC-smil-animation-20010904/#FromToByAndAdditive
nsSMILValue mFrozenValue;
};
#endif // NS_SMILANIMATIONFUNCTION_H_

@ -0,0 +1,178 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is the Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Holbert <dholbert@mozilla.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 "nsHashKeys.h"
// nsSMILCompositorKey methods
inline PRBool
nsSMILCompositorKey::Equals(const nsSMILCompositorKey &aOther) const
{
return (aOther.mElement == mElement &&
aOther.mAttributeName == mAttributeName &&
aOther.mIsCSS == mIsCSS);
}
// PLDHashEntryHdr methods
PRBool
nsSMILCompositor::KeyEquals(KeyTypePointer aKey) const
{
return aKey && aKey->Equals(mKey);
}
/*static*/ PLDHashNumber
nsSMILCompositor::HashKey(KeyTypePointer aKey)
{
// Combine the 3 values into one numeric value, which will be hashed
const char *attrName = nsnull;
aKey->mAttributeName->GetUTF8String(&attrName);
return NS_PTR_TO_UINT32(aKey->mElement.get()) +
HashString(attrName) +
(aKey->mIsCSS ? 1 : 0);
}
// Cycle-collection support
void
nsSMILCompositor::Traverse(nsCycleCollectionTraversalCallback* aCallback)
{
if (!mKey.mElement)
return;
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCallback, "Compositor mKey.mElement");
aCallback->NoteXPCOMChild(mKey.mElement);
}
// Other methods
void
nsSMILCompositor::AddAnimationFunction(nsSMILAnimationFunction* aFunc)
{
if (aFunc) {
mAnimationFunctions.AppendElement(aFunc);
}
}
void
nsSMILCompositor::ComposeAttribute()
{
if (!mKey.mElement)
return;
// FIRST: Get the nsISMILAttr (to grab base value from, and to eventually
// give animated value to)
nsAutoPtr<nsISMILAttr> smilAttr;
if (mKey.mIsCSS) {
// XXX Look up style system for the CSS property. The set of CSS properties
// should be the same for all elements so we don't need to query the element
// itself.
} else {
smilAttr = mKey.mElement->GetAnimatedAttr(mKey.mAttributeName);
}
if (!smilAttr) {
// Target attribute not found
return;
}
// SECOND: Sort the animationFunctions, to prepare for compositing.
nsSMILAnimationFunction::Comparator comparator;
mAnimationFunctions.Sort(comparator);
// THIRD: Step backwards through animation functions to find out
// which ones we actually care about.
// PRBool changed = PR_FALSE; // XXXdholbert removing until we have
// HasChangedTarget
PRUint32 length = mAnimationFunctions.Length();
PRUint32 i;
for (i = length; i > 0; --i) {
nsSMILAnimationFunction* curAnimFunc = mAnimationFunctions[i-1];
// XXXdholbert we need to add another function
// nsSMILAnimationFunction::HasChangedTarget(elem, smilAttr, isCSS) that
// we call here (in addition to HasChanged(), because even if function
// value hasn't changed, its target might have.
// For this to work, the nsSMILAnimationFunction needs to cache its last
// elem/smilAttr/isCSS values, and then check them against the new values
// here.
/*
if (!changed && curAnimFunc->HasChanged()) {
changed = PR_TRUE;
}
*/
if (curAnimFunc->WillReplace()) {
--i;
break;
}
}
// NOTE: 'i' is now the index of the first animation function that we need
// to use in compositing.
// if (!changed) // XXXdholbert removing until we have HasChangedTarget
// return;
// FOURTH: Compose animation functions (starting with base value)
nsSMILValue resultValue = smilAttr->GetBaseValue();
if (resultValue.IsNull()) {
NS_WARNING("nsISMILAttr::GetBaseValue failed");
return;
}
for (; i < length; ++i) {
nsSMILAnimationFunction* curAnimFunc = mAnimationFunctions[i];
if (curAnimFunc) {
curAnimFunc->ComposeResult(*smilAttr, resultValue);
}
}
// FIFTH: Set the animated value to the final composited result.
nsresult rv = smilAttr->SetAnimValue(resultValue);
if (NS_FAILED(rv)) {
NS_WARNING("nsISMILAttr::SetAnimValue failed");
}
}
/*static*/ void
nsSMILCompositor::ComposeAttributes(nsSMILCompositorTable& aCompositorTable)
{
aCompositorTable.EnumerateEntries(DoComposeAttribute, nsnull);
}
/*static*/ PR_CALLBACK PLDHashOperator
nsSMILCompositor::DoComposeAttribute(nsSMILCompositor* aCompositor,
void* /*aData*/)
{
aCompositor->ComposeAttribute();
return PL_DHASH_NEXT;
}

@ -0,0 +1,122 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is the Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Holbert <dholbert@mozilla.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 "nsIContent.h"
#include "nsTHashtable.h"
#include "nsAutoPtr.h"
#include "nsString.h"
#include "nsSMILAnimationFunction.h"
#include "nsSMILCompositorTable.h"
#include "pldhash.h"
//----------------------------------------------------------------------
// nsSMILCompositorKey
//
// Hash Key: Animated Element, Attribute Name & Type (CSS vs. XML)
//
// NOTE: Need a nsRefPtr to the element, because nsSMILCompositors are kept
// around for 1 sample after they're used, and they need to make sure their
// target isn't deleted.
struct nsSMILCompositorKey
{
PRBool Equals(const nsSMILCompositorKey &aOther) const;
nsRefPtr<nsIContent> mElement;
nsRefPtr<nsIAtom> mAttributeName; // XXX need to consider namespaces here
PRPackedBool mIsCSS;
};
//----------------------------------------------------------------------
// nsSMILCompositor
//
// Performs the composition of the animation sandwich by combining the results
// of a series animation functions according to the rules of SMIL composition
// including prioritising animations.
class nsSMILCompositor : public PLDHashEntryHdr
{
public:
typedef const nsSMILCompositorKey& KeyType;
typedef const nsSMILCompositorKey* KeyTypePointer;
nsSMILCompositor(KeyTypePointer aKey) : mKey(*aKey) { }
nsSMILCompositor(const nsSMILCompositor& toCopy)
: mKey(toCopy.mKey),
mAnimationFunctions(toCopy.mAnimationFunctions)
{ }
~nsSMILCompositor() { }
// PLDHashEntryHdr methods
KeyType GetKey() const { return mKey; }
PRBool KeyEquals(KeyTypePointer aKey) const;
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
static PLDHashNumber HashKey(KeyTypePointer aKey);
enum { ALLOW_MEMMOVE = PR_FALSE };
// Adds the given animation function to this Compositor's list of functions
void AddAnimationFunction(nsSMILAnimationFunction* aFunc);
// Calls ComposeAttribute() on each nsSMILCompositor in the given hashset
static void ComposeAttributes(nsSMILCompositorTable& aCompositorTable);
// Cycle-collection support
void Traverse(nsCycleCollectionTraversalCallback* aCallback);
private:
// Composes the attribute's current value with the list of animation
// functions, and assigns the resulting value to this compositor's target
// attribute.
void ComposeAttribute();
// Static callback methods
PR_STATIC_CALLBACK(PLDHashOperator) DoComposeAttribute(
nsSMILCompositor* aCompositor, void *aData);
// The hash key (element, attribute name, isCSS)
nsSMILCompositorKey mKey;
// Hash Value: List of animation functions that animate the specified
// attribute
// ---------------------------------------------------------------
nsTArray<nsSMILAnimationFunction*> mAnimationFunctions;
};
#endif // NS_SMILCOMPOSITOR_H_

@ -0,0 +1,55 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is the Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Holbert <dholbert@mozilla.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_SMILCOMPOSITORTABLE_H_
#define NS_SMILCOMPOSITORTABLE_H_
#include "nsTHashtable.h"
//----------------------------------------------------------------------
// nsSMILCompositorTable : A hashmap of nsSMILCompositors
//
// This is just a forward-declaration because it is included in
// nsSMILAnimationController which is used in nsDocument. We don't want to
// expose all of nsSMILCompositor or otherwise any changes to it will mean the
// whole world will need to be rebuilt.
class nsSMILCompositor;
typedef nsTHashtable<nsSMILCompositor> nsSMILCompositorTable;
struct nsSMILCompositorKey;
#endif // NS_SMILCOMPOSITORTABLE_H_

@ -0,0 +1,118 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert O'Callahan <roc+moz@cs.cmu.edu>
* 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 "nsSMILFloatType.h"
#include "nsSMILValue.h"
#include "nsDebug.h"
#include <math.h>
/*static*/ nsSMILFloatType nsSMILFloatType::sSingleton;
nsresult
nsSMILFloatType::Init(nsSMILValue& aValue) const
{
NS_PRECONDITION(aValue.mType == this || aValue.IsNull(),
"Unexpected value type");
aValue.mU.mDouble = 0.0;
aValue.mType = this;
return NS_OK;
}
void
nsSMILFloatType::Destroy(nsSMILValue& aValue) const
{
NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value.");
aValue.mU.mDouble = 0.0;
aValue.mType = &nsSMILNullType::sSingleton;
}
nsresult
nsSMILFloatType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
{
NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types.");
NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value.");
aDest.mU.mDouble = aSrc.mU.mDouble;
return NS_OK;
}
nsresult
nsSMILFloatType::Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd,
PRUint32 aCount) const
{
NS_PRECONDITION(aValueToAdd.mType == aDest.mType,
"Trying to add invalid types");
NS_PRECONDITION(aValueToAdd.mType == this, "Unexpected source type");
aDest.mU.mDouble += aValueToAdd.mU.mDouble * aCount;
return NS_OK;
}
nsresult
nsSMILFloatType::ComputeDistance(const nsSMILValue& aFrom,
const nsSMILValue& aTo,
double& aDistance) const
{
NS_PRECONDITION(aFrom.mType == aTo.mType,"Trying to compare different types");
NS_PRECONDITION(aFrom.mType == this, "Unexpected source type");
const double &from = aFrom.mU.mDouble;
const double &to = aTo.mU.mDouble;
aDistance = fabs(to - from);
return NS_OK;
}
nsresult
nsSMILFloatType::Interpolate(const nsSMILValue& aStartVal,
const nsSMILValue& aEndVal,
double aUnitDistance,
nsSMILValue& aResult) const
{
NS_PRECONDITION(aStartVal.mType == aEndVal.mType,
"Trying to interpolate different types");
NS_PRECONDITION(aStartVal.mType == this,
"Unexpected types for interpolation.");
NS_PRECONDITION(aResult.mType == this, "Unexpected result type.");
const double &startVal = aStartVal.mU.mDouble;
const double &endVal = aEndVal.mU.mDouble;
aResult.mU.mDouble = (startVal + (endVal - startVal) * aUnitDistance);
return NS_OK;
}

@ -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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert O'Callahan <roc+moz@cs.cmu.edu>
* 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_SMILFLOATTYPE_H_
#define NS_SMILFLOATTYPE_H_
#include "nsISMILType.h"
class nsSMILFloatType : public nsISMILType
{
public:
virtual nsresult Init(nsSMILValue& aValue) const;
virtual void Destroy(nsSMILValue&) const;
virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const;
virtual nsresult Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd,
PRUint32 aCount) const;
virtual nsresult ComputeDistance(const nsSMILValue& aFrom,
const nsSMILValue& aTo,
double& aDistance) const;
virtual nsresult Interpolate(const nsSMILValue& aStartVal,
const nsSMILValue& aEndVal,
double aUnitDistance,
nsSMILValue& aResult) const;
static nsSMILFloatType sSingleton;
private:
nsSMILFloatType() {}
};
#endif // NS_SMILFLOATTYPE_H_

@ -0,0 +1,59 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 "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)
{
// XXX
}
nsSMILInstanceTime::~nsSMILInstanceTime()
{
// XXXdholbert When we add support for syncbase timing, we'll
// need to remove this nsSMILInstanceTime from its timebase
// here.
}

@ -0,0 +1,95 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 ***** */
#ifndef NS_SMILINSTANCETIME_H_
#define NS_SMILINSTANCETIME_H_
#include "nsISupports.h"
#include "nsSMILTimeValue.h"
#include "nsWeakReference.h"
#include "nsAutoPtr.h"
class nsSMILTimeValueSpec;
//----------------------------------------------------------------------
// nsSMILInstanceTime
//
// An instant in document simple time that may be used in creating a new
// interval
//
// For an overview of how this class is related to other SMIL time classes see
// the documentstation in nsSMILTimeValue.h
class nsSMILInstanceTime
{
public:
nsSMILInstanceTime(const nsSMILTimeValue& aTime,
nsSMILTimeValueSpec* aCreator,
PRBool aClearOnReset = PR_FALSE);
~nsSMILInstanceTime();
const nsSMILTimeValue& Time() const { return mTime; }
PRBool ClearOnReset() const { return mClearOnReset; }
// void DependentUpdate(const nsSMILTimeValue& aNewTime); -- NOT YET IMPL.
// Used by nsTArray::Sort
class Comparator {
public:
PRBool Equals(const nsSMILInstanceTime& aElem1,
const nsSMILInstanceTime& aElem2) const {
return (aElem1.Time().CompareTo(aElem2.Time()) == 0);
}
PRBool LessThan(const nsSMILInstanceTime& aElem1,
const nsSMILInstanceTime& aElem2) const {
return (aElem1.Time().CompareTo(aElem2.Time()) < 0);
}
};
protected:
nsSMILTimeValue mTime;
/**
* Indicates if this instance time should be removed when the owning timed
* element is reset. True for events and DOM calls.
*/
PRPackedBool mClearOnReset;
};
#endif // NS_SMILINSTANCETIME_H_

@ -0,0 +1,60 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 ***** */
#ifndef NS_SMILINTERVAL_H_
#define NS_SMILINTERVAL_H_
#include "nsSMILTimeValue.h"
//----------------------------------------------------------------------
// nsSMILInterval class
//
// This class is essentially a structure consisting of a begin and end time. It
// is used for representing the current interval and also for storing past
// intervals for the purpose of hyperlinking back in time.
//
// For an overview of how this class is related to other SMIL time classes see
// the documentstation in nsSMILTimeValue.h
class nsSMILInterval
{
public:
nsSMILTimeValue mBegin;
nsSMILTimeValue mEnd;
};
#endif // NS_SMILINTERVAL_H_

@ -0,0 +1,120 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 "nsSMILKeySpline.h"
#include <math.h>
#define NEWTON_ITERATIONS 4
const double nsSMILKeySpline::kSampleStepSize =
1.0 / double(kSplineTableSize - 1);
nsSMILKeySpline::nsSMILKeySpline(double aX1,
double aY1,
double aX2,
double aY2)
: mX1(aX1),
mY1(aY1),
mX2(aX2),
mY2(aY2)
{
if (mX1 != mY1 || mX2 != mY2)
CalcSampleValues();
}
double
nsSMILKeySpline::GetSplineValue(double aX) const
{
if (mX1 == mY1 && mX2 == mY2)
return aX;
return CalcBezier(GetTForX(aX), mY1, mY2);
}
void
nsSMILKeySpline::CalcSampleValues()
{
for (int i = 0; i < kSplineTableSize; ++i) {
mSampleValues[i] = CalcBezier(double(i) * kSampleStepSize, mX1, mX2);
}
}
/*static*/ double
nsSMILKeySpline::CalcBezier(double aT,
double aA1,
double aA2)
{
return A(aA1, aA2) * pow(aT,3) + B(aA1, aA2)*aT*aT + C(aA1) * aT;
}
/*static*/ double
nsSMILKeySpline::GetSlope(double aT,
double aA1,
double aA2)
{
double denom = (3.0 * A(aA1, aA2)*aT*aT + 2.0 * B(aA1, aA2) * aT + C(aA1));
return (denom == 0.0) ? 0.0 : 1.0 / denom;
}
double
nsSMILKeySpline::GetTForX(double aX) const
{
int i;
// Get an initial guess.
//
// Note: This is better than just taking x as our initial guess as cases such
// as where the control points are (1, 1), (0, 0) will take some 20 iterations
// to converge to a good accuracy. By taking an initial guess in this way we
// only need 3~4 iterations depending on the size of the table.
for (i = 0; i < kSplineTableSize - 2 && mSampleValues[i] < aX; ++i);
double currentT =
double(i) * kSampleStepSize + (aX - mSampleValues[i]) * kSampleStepSize;
// Refine with Newton-Raphson iteration
for (i = 0; i < NEWTON_ITERATIONS; ++i) {
double currentX = CalcBezier(currentT, mX1, mX2);
double currentSlope = GetSlope(currentT, mX1, mX2);
if (currentSlope == 0.0)
return currentT;
currentT -= (currentX - aX) * currentSlope;
}
return currentT;
}

@ -0,0 +1,107 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 ***** */
#ifndef NS_SMILKEYSPLINE_H_
#define NS_SMILKEYSPLINE_H_
#include "prtypes.h"
/**
* Utility class to provide scaling defined in a keySplines element.
*/
class nsSMILKeySpline
{
public:
/*
* Create a new key spline control point description.
*
* aX1, etc. are the x1, y1, x2, y2 cubic Bezier control points as defined by
* SMILANIM 3.2.3. They must each be in the range 0.0 <= x <= 1.0
*/
nsSMILKeySpline(double aX1, double aY1,
double aX2, double aY2);
/*
* Get the output (y) value for an input (x).
*
* x should be a floating-point number between 0 and 1 (inclusive).
*/
double GetSplineValue(double aX) const;
private:
void
CalcSampleValues();
static double
CalcBezier(double aT, double aA1, double aA2);
static double
GetSlope(double aT, double aA1, double aA2);
double
GetTForX(double aX) const;
static double
A(double aA1, double aA2)
{
return 1.0 - 3.0 * aA2 + 3.0 * aA1;
}
static double
B(double aA1, double aA2)
{
return 3.0 * aA2 - 6.0 * aA1;
}
static double
C(double aA1)
{
return 3.0 * aA1;
}
const double mX1;
const double mY1;
const double mX2;
const double mY2;
enum { kSplineTableSize = 11 };
double mSampleValues[kSplineTableSize];
static const double kSampleStepSize;
};
#endif // NS_SMILKEYSPLINE_H_

@ -0,0 +1,80 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert O'Callahan <roc+moz@cs.cmu.edu>
* 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 "nsSMILNullType.h"
#include "nsSMILValue.h"
#include "nsDebug.h"
/*static*/ nsSMILNullType nsSMILNullType::sSingleton;
nsresult
nsSMILNullType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
{
NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types.");
NS_PRECONDITION(aSrc.mType == this, "Unexpected source type");
aDest.mU = aSrc.mU;
aDest.mType = &sSingleton;
return NS_OK;
}
nsresult
nsSMILNullType::Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd,
PRUint32 aCount) const
{
NS_NOTREACHED("Adding NULL type.");
return NS_ERROR_FAILURE;
}
nsresult
nsSMILNullType::ComputeDistance(const nsSMILValue& aFrom,
const nsSMILValue& aTo,
double& aDistance) const
{
NS_NOTREACHED("Computing distance for NULL type.");
return NS_ERROR_FAILURE;
}
nsresult
nsSMILNullType::Interpolate(const nsSMILValue& aStartVal,
const nsSMILValue& aEndVal,
double aUnitDistance,
nsSMILValue& aResult) const
{
NS_NOTREACHED("Interpolating NULL type.");
return NS_ERROR_FAILURE;
}

@ -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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert O'Callahan <roc+moz@cs.cmu.edu>
* 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_SMILNULLTYPE_H_
#define NS_SMILNULLTYPE_H_
#include "nsISMILType.h"
class nsSMILNullType : public nsISMILType
{
public:
virtual nsresult Init(nsSMILValue& aValue) const { return NS_OK; }
virtual void Destroy(nsSMILValue& aValue) const {}
virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const;
// The remaining methods should never be called, so although they're very
// simple they don't need to be inline.
virtual nsresult Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd,
PRUint32 aCount) const;
virtual nsresult ComputeDistance(const nsSMILValue& aFrom,
const nsSMILValue& aTo,
double& aDistance) const;
virtual nsresult Interpolate(const nsSMILValue& aStartVal,
const nsSMILValue& aEndVal,
double aUnitDistance,
nsSMILValue& aResult) const;
static nsSMILNullType sSingleton;
};
#endif // NS_SMILNULLTYPE_H_

@ -0,0 +1,603 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 "nsSMILParserUtils.h"
#include "nsISMILAttr.h"
#include "nsSMILValue.h"
#include "nsSMILTimeValue.h"
#include "nsSMILTypes.h"
#include "nsSMILRepeatCount.h"
#include "nsString.h"
#include "prdtoa.h"
#include "nsCRT.h"
#include "nsCOMPtr.h"
#include "prlong.h"
const PRUint32 nsSMILParserUtils::MSEC_PER_SEC = 1000;
const PRUint32 nsSMILParserUtils::MSEC_PER_MIN = 1000 * 60;
const PRUint32 nsSMILParserUtils::MSEC_PER_HOUR = 1000 * 60 * 60;
//------------------------------------------------------------------------------
// Inlines
// 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
nsSMILParserUtils::IsSpace(const PRUnichar c)
{
return (c == 0x9 || c == 0xA || c == 0xD || c == 0x20);
}
inline void
nsSMILParserUtils::SkipWsp(nsACString::const_iterator& aIter,
const nsACString::const_iterator& aIterEnd)
{
while (aIter != aIterEnd && IsSpace(*aIter)) {
++aIter;
}
}
inline void
nsSMILParserUtils::SkipWsp(nsAString::const_iterator& aIter,
const nsAString::const_iterator& aIterEnd)
{
while (aIter != aIterEnd && IsSpace(*aIter)) {
++aIter;
}
}
inline double
nsSMILParserUtils::GetFloat(nsACString::const_iterator& aIter,
const nsACString::const_iterator& aIterEnd,
nsresult *aErrorCode)
{
char *end;
const char *start = aIter.get();
double value = PR_strtod(start, &end);
nsresult rv = NS_OK;
if (end == start || end > aIterEnd.get()) {
rv = NS_ERROR_FAILURE;
} else {
aIter.advance(end - start);
}
if (aErrorCode) {
*aErrorCode = rv;
}
return value;
}
inline PRBool
nsSMILParserUtils::ConsumeSubstring(nsACString::const_iterator& aIter,
const nsACString::const_iterator& aIterEnd,
const char *aSubstring)
{
size_t substrLen = PL_strlen(aSubstring);
typedef nsACString::const_iterator::difference_type diff_type;
if (aIterEnd.get() - aIter.get() < static_cast<diff_type>(substrLen))
return PR_FALSE;
PRBool result = PR_FALSE;
if (PL_strstr(aIter.get(), aSubstring) == aIter.get()) {
aIter.advance(substrLen);
result = PR_TRUE;
}
return result;
}
//------------------------------------------------------------------------------
// Implementation
nsresult
nsSMILParserUtils::ParseKeySplines(const nsAString& aSpec,
nsTArray<double>& aSplineArray)
{
nsresult rv = NS_OK;
NS_ConvertUTF16toUTF8 spec(aSpec);
nsACString::const_iterator start, end;
spec.BeginReading(start);
spec.EndReading(end);
SkipWsp(start, end);
int i = 0;
while (start != end)
{
double value = GetFloat(start, end, &rv);
if (NS_FAILED(rv))
break;
if (value > 1.0 || value < 0.0) {
rv = NS_ERROR_FAILURE;
break;
}
if (!aSplineArray.AppendElement(value)) {
rv = NS_ERROR_OUT_OF_MEMORY;
break;
}
++i;
SkipWsp(start, end);
if (start == end)
break;
if (i % 4) {
if (*start == ',') {
++start;
}
} else {
if (*start != ';') {
rv = NS_ERROR_FAILURE;
break;
}
++start;
}
SkipWsp(start, end);
}
if (i % 4) {
rv = NS_ERROR_FAILURE; // wrong number of points
}
return rv;
}
nsresult
nsSMILParserUtils::ParseKeyTimes(const nsAString& aSpec,
nsTArray<double>& aTimeArray)
{
nsresult rv = NS_OK;
NS_ConvertUTF16toUTF8 spec(aSpec);
nsACString::const_iterator start, end;
spec.BeginReading(start);
spec.EndReading(end);
SkipWsp(start, end);
double previousValue = -1.0;
while (start != end) {
double value = GetFloat(start, end, &rv);
if (NS_FAILED(rv))
break;
if (value > 1.0 || value < 0.0 || value < previousValue) {
rv = NS_ERROR_FAILURE;
break;
}
if (!aTimeArray.AppendElement(value)) {
rv = NS_ERROR_OUT_OF_MEMORY;
break;
}
previousValue = value;
SkipWsp(start, end);
if (start == end)
break;
if (*start++ != ';') {
rv = NS_ERROR_FAILURE;
break;
}
SkipWsp(start, end);
}
return rv;
}
nsresult
nsSMILParserUtils::ParseValues(const nsAString& aSpec,
const nsISMILAnimationElement* aSrcElement,
const nsISMILAttr& aAttribute,
nsTArray<nsSMILValue>& aValuesArray)
{
nsresult rv = NS_ERROR_FAILURE;
nsAString::const_iterator start;
nsAString::const_iterator end;
nsAString::const_iterator substr_end;
nsAString::const_iterator next;
aSpec.BeginReading(start);
aSpec.EndReading(end);
while (start != end) {
rv = NS_ERROR_FAILURE;
SkipWsp(start, end);
if (start == end || *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;
nsSMILValue newValue;
rv = aAttribute.ValueFromString(Substring(start, substr_end),
aSrcElement, newValue);
if (NS_FAILED(rv))
break;
if (!aValuesArray.AppendElement(newValue)) {
rv = NS_ERROR_OUT_OF_MEMORY;
break;
}
rv = NS_OK;
start = next;
}
return rv;
}
nsresult
nsSMILParserUtils::ParseRepeatCount(const nsAString& aSpec,
nsSMILRepeatCount& aResult)
{
nsresult rv = NS_OK;
NS_ConvertUTF16toUTF8 spec(aSpec);
nsACString::const_iterator start, end;
spec.BeginReading(start);
spec.EndReading(end);
SkipWsp(start, end);
if (start != end)
{
if (ConsumeSubstring(start, end, "indefinite")) {
aResult.SetIndefinite();
} else {
double value = GetFloat(start, end, &rv);
if (NS_SUCCEEDED(rv))
{
/* Repeat counts must be > 0 */
if (value <= 0.0) {
rv = NS_ERROR_FAILURE;
} else {
aResult = value;
}
}
}
/* Check for trailing junk */
SkipWsp(start, end);
if (start != end) {
rv = NS_ERROR_FAILURE;
}
} else {
/* Empty spec */
rv = NS_ERROR_FAILURE;
}
if (NS_FAILED(rv)) {
aResult.Unset();
}
return rv;
}
nsresult
nsSMILParserUtils::ParseClockValue(const nsAString& aSpec,
nsSMILTimeValue* aResult,
PRUint32 aFlags, // = 0
PRBool* aIsMedia) // = nsnull
{
nsSMILTime offset = 0L;
double component = 0.0;
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;
if (aIsMedia) {
*aIsMedia = PR_FALSE;
}
NS_ConvertUTF16toUTF8 spec(aSpec);
nsACString::const_iterator start, end;
spec.BeginReading(start);
spec.EndReading(end);
while (start != end) {
if (IsSpace(*start)) {
if (started) {
++start;
break;
}
// else, we haven't started yet, ignore initial whitespace
++start;
} else if ((aFlags & kClockValueAllowSign)
&& (*start == '+' || *start == '-')) {
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 = (*start == '+') ? 1 : -1;
++start;
// The NS_IS_DIGIT etc. macros are not locale-specific
} else if (NS_IS_DIGIT(*start)) {
prevNumCouldBeMin = numCouldBeMin;
if (!ParseClockComponent(start, end, component, numIsReal, numCouldBeMin,
numCouldBeSec)) {
isValid = PR_FALSE;
break;
}
started = PR_TRUE;
} else if (*start == ':') {
++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
offset = offset * 60 + PRInt64(component);
component = 0.0;
++start;
} else if (NS_IS_ALPHA(*start)) {
if (colonCount > 0) {
isValid = PR_FALSE;
break;
}
if ((aFlags & kClockValueAllowIndefinite)
&& ConsumeSubstring(start, end, "indefinite")) {
// 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();
}
} else if (aIsMedia && ConsumeSubstring(start, end, "media")) {
*aIsMedia = PR_TRUE;
} else if (!ParseMetricMultiplicand(start, end, metricMultiplicand)) {
isValid = PR_FALSE;
break;
}
// Nothing must come after the string except whitespace
break;
} else {
isValid = PR_FALSE;
break;
}
}
if (!started) {
isValid = PR_FALSE;
}
// Process remainder of string (if any) to ensure it is only trailing
// whitespace (embedded whitespace is not allowed)
SkipWsp(start, end);
if (start != end) {
isValid = PR_FALSE;
}
// 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) {
offset = offset * 60 * 1000;
component *= 1000;
// rounding
component = (component >= 0) ? component + 0.5 : component - 0.5;
offset += PRInt64(component);
} else {
component *= metricMultiplicand;
// rounding
component = (component >= 0) ? component + 0.5 : component - 0.5;
offset = PRInt64(component);
}
if (aResult) {
nsSMILTime millis = offset;
if (sign == -1) {
millis = -offset;
}
aResult->SetMillis(millis);
}
}
return (isValid) ? NS_OK : NS_ERROR_FAILURE;
}
PRBool
nsSMILParserUtils::ParseClockComponent(nsACString::const_iterator& aSpec,
const nsACString::const_iterator& aEnd,
double& aResult,
PRBool& aIsReal,
PRBool& aCouldBeMin,
PRBool& aCouldBeSec)
{
nsresult rv;
char const *begin = aSpec.get();
double value = GetFloat(aSpec, aEnd, &rv);
// Check a number was found
if (NS_FAILED(rv))
return PR_FALSE;
// Check it's not expressed in exponential form
size_t len = aSpec.get() - begin;
PRBool isExp = (PL_strnpbrk(begin, "eE", len) != nsnull);
if (isExp)
return PR_FALSE;
// Don't allow real numbers of the form "23."
if (*(aSpec.get() - 1) == '.')
return PR_FALSE;
// Number looks good
aResult = value;
// 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(begin, '.', len) != nsnull);
aCouldBeMin = (value < 60.0 && (len == 2));
aCouldBeSec = (value < 60.0 ||
(value == 60.0 && begin[0] == '5')); // Take care of rounding error
aCouldBeSec &= (len >= 2 &&
(begin[2] == '\0' || begin[2] == '.' || IsSpace(begin[2])));
return PR_TRUE;
}
inline PRBool
nsSMILParserUtils::ParseMetricMultiplicand(nsACString::const_iterator& aSpec,
const nsACString::const_iterator& aEnd,
PRInt32& multiplicand)
{
PRBool result = PR_FALSE;
size_t len = aEnd.get() - aSpec.get();
nsACString::const_iterator spec(aSpec);
if (len) {
switch (*spec++)
{
case 'h':
multiplicand = MSEC_PER_HOUR;
result = PR_TRUE;
break;
case 'm':
if (len >= 2) {
if (*spec == 's') {
++spec;
multiplicand = 1;
result = PR_TRUE;
} else if (len >= 3 && *spec++ == 'i' && *spec++ == 'n') {
multiplicand = MSEC_PER_MIN;
result = PR_TRUE;
}
}
break;
case 's':
multiplicand = MSEC_PER_SEC;
result = PR_TRUE;
break;
}
}
if (result) {
aSpec = spec;
}
return result;
}

@ -0,0 +1,136 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 ***** */
#ifndef NS_SMILPARSERUTILS_H_
#define NS_SMILPARSERUTILS_H_
#include "nscore.h"
#include "nsTArray.h"
#include "nsString.h"
class nsISMILAttr;
class nsISMILAnimationElement;
class nsSMILTimeValue;
class nsSMILValue;
class nsSMILRepeatCount;
/**
* Common parsing utilities for the SMIL module. There is little re-use here; it
* simply serves to simplify other classes by moving parsing outside and to aid
* unit testing.
*/
class nsSMILParserUtils
{
public:
static nsresult ParseKeySplines(const nsAString& aSpec,
nsTArray<double>& aSplineArray);
static nsresult ParseKeyTimes(const nsAString& aSpec,
nsTArray<double>& aTimesArray);
static nsresult ParseValues(const nsAString& aSpec,
const nsISMILAnimationElement* aSrcElement,
const nsISMILAttr& aAttribute,
nsTArray<nsSMILValue>& aValuesArray);
static nsresult ParseRepeatCount(const nsAString& aSpec,
nsSMILRepeatCount& aResult);
// Used with ParseClockValue. Allow + or - before a clock value.
static const PRInt8 kClockValueAllowSign = 1;
// Used with ParseClockValue. Allow "indefinite" in a clock value
static const PRInt8 kClockValueAllowIndefinite = 2;
/*
* 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 nsnull if the
* media attribute is not allowed).
*
* @param aSpec The string containing a clock value, e.g. "10s"
* @param aResult The parsed result. May be NULL (e.g. if this method is
* being called just to test if aSpec is a valid clock value).
* [OUT]
* @param aFlags A combination of the kClockValue* bit flags OR'ed together
* to define what additional syntax is allowed.
* @param aIsMedia Optional out parameter which, if not null, will be set to
* PR_TRUE if the value is the string "media", PR_FALSE
* otherwise. If it is null, the string "media" is not
* allowed.
*
* @return NS_OK if aSpec was successfully parsed as a valid clock value
* (according to aFlags), an error code otherwise.
*/
static nsresult ParseClockValue(const nsAString& aSpec,
nsSMILTimeValue* aResult,
PRUint32 aFlags = 0,
PRBool* aIsMedia = nsnull);
private:
static void SkipWsp(nsACString::const_iterator& aIter,
const nsACString::const_iterator& aIterEnd);
static void SkipWsp(nsAString::const_iterator& aIter,
const nsAString::const_iterator& aIterEnd);
static double GetFloat(nsACString::const_iterator& aIter,
const nsACString::const_iterator& aIterEnd,
nsresult *aErrorCode = nsnull);
static PRBool IsSpace(const PRUnichar c);
static PRBool ConsumeSubstring(nsACString::const_iterator& aIter,
const nsACString::const_iterator& aIterEnd,
const char *aSubstring);
static PRBool ParseClockComponent(nsACString::const_iterator& aSpec,
const nsACString::const_iterator& aEnd,
double& aResult,
PRBool& aIsReal,
PRBool& aCouldBeMin,
PRBool& aCouldBeSec);
static PRBool ParseMetricMultiplicand(nsACString::const_iterator& aSpec,
const nsACString::const_iterator& aEnd,
PRInt32& multiplicand);
static const PRUint32 MSEC_PER_SEC;
static const PRUint32 MSEC_PER_MIN;
static const PRUint32 MSEC_PER_HOUR;
};
#endif // NS_SMILPARSERUTILS_H_

@ -0,0 +1,41 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2009
* 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 "nsSMILRepeatCount.h"
/*static*/ const double nsSMILRepeatCount::kNotSet = -1.0;
/*static*/ const double nsSMILRepeatCount::kIndefinite = -2.0;

@ -0,0 +1,84 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2009
* 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 "prtypes.h"
#include "nsDebug.h"
#include <math.h>
//----------------------------------------------------------------------
// nsSMILRepeatCount
//
// A tri-state non-negative floating point number for representing the number of
// times an animation repeat, i.e. the SMIL repeatCount attribute.
//
// The three states are:
// 1. not-set
// 2. set (with non-negative, non-zero count value)
// 3. indefinite
//
class nsSMILRepeatCount
{
public:
nsSMILRepeatCount() : mCount(kNotSet) {}
nsSMILRepeatCount(double aCount) : mCount(kNotSet) { SetCount(aCount); }
operator double() const { return mCount; }
PRBool IsDefinite() const {
return mCount != kNotSet && mCount != kIndefinite;
}
PRBool IsIndefinite() const { return mCount == kIndefinite; }
PRBool IsSet() const { return mCount != kNotSet; }
nsSMILRepeatCount& operator=(double aCount)
{
SetCount(aCount);
return *this;
}
void SetCount(double aCount)
{
NS_ASSERTION(aCount > 0.0, "Negative or zero repeat count.");
mCount = aCount > 0.0 ? aCount : kNotSet;
}
void SetIndefinite() { mCount = kIndefinite; }
void Unset() { mCount = kNotSet; }
private:
static const double kNotSet;
static const double kIndefinite;
double mCount;
};

@ -0,0 +1,132 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2009
* 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 "nsSMILSetAnimationFunction.h"
inline PRBool
nsSMILSetAnimationFunction::IsDisallowedAttribute(
const nsIAtom* aAttribute) const
{
//
// A <set> element is similar to <animate> but lacks:
// AnimationValue.attrib(calcMode, values, keyTimes, keySplines, from, to,
// by) -- BUT has 'to'
// AnimationAddition.attrib(additive, accumulate)
//
if (aAttribute == nsGkAtoms::calcMode ||
aAttribute == nsGkAtoms::values ||
aAttribute == nsGkAtoms::keyTimes ||
aAttribute == nsGkAtoms::keySplines ||
aAttribute == nsGkAtoms::from ||
aAttribute == nsGkAtoms::by ||
aAttribute == nsGkAtoms::additive ||
aAttribute == nsGkAtoms::accumulate) {
return PR_TRUE;
}
return PR_FALSE;
}
PRBool
nsSMILSetAnimationFunction::SetAttr(nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult,
nsresult* aParseResult)
{
if (IsDisallowedAttribute(aAttribute)) {
aResult.SetTo(aValue);
if (aParseResult) {
// SMILANIM 4.2 says:
//
// The additive and accumulate attributes are not allowed, and will be
// ignored if specified.
//
// So at least for those two attributes we shouldn't report an error even
// if they're present. For now we'll also just silently ignore other
// attribute types too.
*aParseResult = NS_OK;
}
return PR_TRUE;
}
return nsSMILAnimationFunction::SetAttr(aAttribute, aValue,
aResult, aParseResult);
}
PRBool
nsSMILSetAnimationFunction::UnsetAttr(nsIAtom* aAttribute)
{
if (IsDisallowedAttribute(aAttribute)) {
return PR_TRUE;
}
return nsSMILAnimationFunction::UnsetAttr(aAttribute);
}
nsSMILAnimationFunction::nsSMILCalcMode
nsSMILSetAnimationFunction::GetCalcMode() const
{
return CALC_DISCRETE;
}
PRBool
nsSMILSetAnimationFunction::HasAttr(nsIAtom* aAttName) const
{
if (IsDisallowedAttribute(aAttName))
return PR_FALSE;
return nsSMILAnimationFunction::HasAttr(aAttName);
}
const nsAttrValue*
nsSMILSetAnimationFunction::GetAttr(nsIAtom* aAttName) const
{
if (IsDisallowedAttribute(aAttName))
return nsnull;
return nsSMILAnimationFunction::GetAttr(aAttName);
}
PRBool
nsSMILSetAnimationFunction::GetAttr(nsIAtom* aAttName,
nsAString& aResult) const
{
if (IsDisallowedAttribute(aAttName))
return nsnull;
return nsSMILAnimationFunction::GetAttr(aAttName, aResult);
}

@ -0,0 +1,87 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2009
* 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 ***** */
#ifndef NS_SMILSETANIMATIONFUNCTION_H_
#define NS_SMILSETANIMATIONFUNCTION_H_
#include "nsSMILAnimationFunction.h"
//----------------------------------------------------------------------
// nsSMILSetAnimationFunction
//
// Subclass of nsSMILAnimationFunction that limits the behaviour to that offered
// by a <set> element.
//
class nsSMILSetAnimationFunction : public nsSMILAnimationFunction
{
public:
/*
* Sets animation-specific attributes (or marks them dirty, in the case
* of from/to/by/values).
*
* @param aAttribute The attribute being set
* @param aValue The updated value of the attribute.
* @param aResult The nsAttrValue object that may be used for storing the
* parsed result.
* @param aParseResult Outparam used for reporting parse errors. Will be set
* to NS_OK if everything succeeds.
* @returns PR_TRUE if aAttribute is a recognized animation-related
* attribute; PR_FALSE otherwise.
*/
virtual PRBool SetAttr(nsIAtom* aAttribute, const nsAString& aValue,
nsAttrValue& aResult, nsresult* aParseResult = nsnull);
/*
* Unsets the given attribute.
*
* @returns PR_TRUE if aAttribute is a recognized animation-related
* attribute; PR_FALSE otherwise.
*/
virtual PRBool UnsetAttr(nsIAtom* aAttribute);
protected:
virtual nsSMILAnimationFunction::nsSMILCalcMode GetCalcMode() const;
virtual PRBool HasAttr(nsIAtom* aAttName) const;
virtual const nsAttrValue* GetAttr(nsIAtom* aAttName) const;
virtual PRBool GetAttr(nsIAtom* aAttName,
nsAString& aResult) const;
PRBool IsDisallowedAttribute(const nsIAtom* aAttribute) const;
};
#endif // NS_SMILSETANIMATIONFUNCTION_H_

@ -0,0 +1,177 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2009
* 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 "nsSMILTimeContainer.h"
nsSMILTimeContainer::nsSMILTimeContainer()
:
mParent(nsnull),
mCurrentTime(0L),
mParentOffset(0L),
mPauseStart(0L),
mNeedsPauseSample(PR_FALSE),
mPauseState(PAUSE_BEGIN)
{
}
nsSMILTimeContainer::~nsSMILTimeContainer()
{
if (mParent) {
mParent->RemoveChild(*this);
}
}
void
nsSMILTimeContainer::Begin()
{
Resume(PAUSE_BEGIN);
if (mPauseState) {
mNeedsPauseSample = PR_TRUE;
}
// This is a little bit complicated here. Ideally we'd just like to call
// Sample() and force an initial sample but this turns out to be a bad idea
// because this may mean that NeedsSample() no longer reports true and so when
// we come to the first real sample our parent will skip us over altogether.
// So we force the time to be updated and adopt the policy to never call
// Sample() ourselves but to always leave that to our parent or client.
UpdateCurrentTime();
}
void
nsSMILTimeContainer::Pause(PRUint32 aType)
{
if (!mPauseState && aType) {
mPauseStart = GetParentTime();
mNeedsPauseSample = PR_TRUE;
}
mPauseState |= aType;
}
void
nsSMILTimeContainer::Resume(PRUint32 aType)
{
if (!mPauseState)
return;
mPauseState &= ~aType;
if (!mPauseState) {
nsSMILTime extraOffset = GetParentTime() - mPauseStart;
mParentOffset += extraOffset;
}
}
nsSMILTime
nsSMILTimeContainer::GetCurrentTime() const
{
// The following behaviour is consistent with:
// http://www.w3.org/2003/01/REC-SVG11-20030114-errata
// #getCurrentTime_setCurrentTime_undefined_before_document_timeline_begin
// which says that if GetCurrentTime is called before the document timeline
// has begun we should just return 0.
if (IsPausedByType(PAUSE_BEGIN))
return 0L;
return mCurrentTime;
}
void
nsSMILTimeContainer::SetCurrentTime(nsSMILTime aSeekTo)
{
// The following behaviour is consistent with:
// http://www.w3.org/2003/01/REC-SVG11-20030114-errata
// #getCurrentTime_setCurrentTime_undefined_before_document_timeline_begin
// which says that if SetCurrentTime is called before the document timeline
// has begun we should still adjust the offset.
mParentOffset = GetParentTime() - aSeekTo;
if (mPauseState) {
mNeedsPauseSample = PR_TRUE;
}
// Force an update to the current time in case we get a call to GetCurrentTime
// before another call to Sample().
UpdateCurrentTime();
}
nsSMILTime
nsSMILTimeContainer::GetParentTime() const
{
if (mParent)
return mParent->GetCurrentTime();
return 0L;
}
void
nsSMILTimeContainer::Sample()
{
if (!NeedsSample())
return;
UpdateCurrentTime();
DoSample();
mNeedsPauseSample = PR_FALSE;
}
nsresult
nsSMILTimeContainer::SetParent(nsSMILTimeContainer* aParent)
{
if (mParent) {
mParent->RemoveChild(*this);
}
mParent = aParent;
nsresult rv = NS_OK;
if (mParent) {
rv = mParent->AddChild(*this);
}
return rv;
}
void
nsSMILTimeContainer::UpdateCurrentTime()
{
nsSMILTime now = mPauseState ? mPauseStart : GetParentTime();
mCurrentTime = now - mParentOffset;
}

@ -0,0 +1,194 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2009
* 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 ***** */
#ifndef NS_SMILTIMECONTAINER_H_
#define NS_SMILTIMECONTAINER_H_
#include "nscore.h"
#include "nsSMILTypes.h"
//----------------------------------------------------------------------
// nsSMILTimeContainer
//
// Common base class for a time base that can be paused, resumed, and sampled.
//
class nsSMILTimeContainer
{
public:
nsSMILTimeContainer();
virtual ~nsSMILTimeContainer();
/*
* Pause request types.
*/
enum {
PAUSE_BEGIN = 1,
PAUSE_SCRIPT = 2,
PAUSE_PAGEHIDE = 4,
PAUSE_USERPREF = 8
};
/*
* Cause the time container to records its begin time.
*/
void Begin();
/*
* Pause this time container
*
* @param aType The source of the pause request. Successive calls to Pause
* with the same aType will be ignored. The container will remain paused until
* each call to Pause of a given aType has been matched by at least one call
* to Resume with the same aType.
*/
virtual void Pause(PRUint32 aType);
/*
* Resume this time container
*
* param @aType The source of the resume request. Clears the pause flag for
* this particular type of pause request. When all pause flags have been
* cleared the time container will be resumed.
*/
virtual void Resume(PRUint32 aType);
/**
* Returns true if this time container is paused by the specified type.
* Note that the time container may also be paused by other types; this method
* does not test if aType is the exclusive pause source.
*
* @param @aType The pause source to test for.
* @return PR_TRUE if this container is paused by aType.
*/
PRBool IsPausedByType(PRUint32 aType) const { return mPauseState & aType; }
/*
* Return the time elapsed since this time container's begin time (expressed
* in parent time) minus any accumulated offset from pausing.
*/
nsSMILTime GetCurrentTime() const;
/*
* Seek the document timeline to the specified time.
*
* @param aSeekTo The time to seek to, expressed in this time container's time
* base (i.e. the same units as GetCurrentTime).
*/
void SetCurrentTime(nsSMILTime aSeekTo);
/*
* Return the current time for the parent time container if any.
*/
virtual nsSMILTime GetParentTime() const;
/*
* Updates the current time of this time container and calls DoSample to
* perform any sample-operations.
*/
void Sample();
/*
* Return if this time container should be sampled or can be skipped.
*
* This is most useful as an optimisation for skipping time containers that
* don't require a sample.
*/
PRBool NeedsSample() const { return !mPauseState || mNeedsPauseSample; }
/*
* Sets the parent time container.
*
* The callee still retains ownership of the time container.
*/
nsresult SetParent(nsSMILTimeContainer* aParent);
protected:
/*
* Per-sample operations to be performed whenever Sample() is called and
* NeedsSample() is true. Called after updating mCurrentTime;
*/
virtual void DoSample() { }
/*
* Adding and removing child containers is not implemented in the base class
* because not all subclasses need this.
*/
/*
* Adds a child time container.
*/
virtual nsresult AddChild(nsSMILTimeContainer& aChild)
{
return NS_ERROR_FAILURE;
}
/*
* Removes a child time container.
*/
virtual void RemoveChild(nsSMILTimeContainer& aChild) { }
/*
* Implementation helper to update the current time.
*/
void UpdateCurrentTime();
// The parent time container, if any
nsSMILTimeContainer* mParent;
// The current time established at the last call to Sample()
nsSMILTime mCurrentTime;
// The number of milliseconds for which the container has been paused
// (excluding the current pause interval if the container is currently
// paused).
//
// Current time = parent time - mParentOffset
//
nsSMILTime mParentOffset;
// The timestamp in milliseconds since the epoch (i.e. wallclock time) when
// the document was paused
nsSMILTime mPauseStart;
// Whether or not a pause sample is required
PRPackedBool mNeedsPauseSample;
// A bitfield of the pause state for all pause requests
PRUint32 mPauseState;
};
#endif // NS_SMILTIMECONTAINER_H_

@ -0,0 +1,116 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 "nsSMILTimeValue.h"
#include "nsDebug.h"
nsSMILTime nsSMILTimeValue::kUnresolvedSeconds = LL_MAXINT;
//----------------------------------------------------------------------
// Implementation
// Default constructor creates an unresolved time
nsSMILTimeValue::nsSMILTimeValue()
: mMilliseconds(LL_MAXINT),
mState(STATE_UNRESOLVED)
{
}
//----------------------------------------------------------------------
// nsSMILTimeValue methods:
inline PRInt8
nsSMILTimeValue::Cmp(PRInt64 aA, PRInt64 aB) const
{
return aA == aB ? 0 : (aA > aB ? 1 : -1);
}
void
nsSMILTimeValue::SetIndefinite()
{
mState = STATE_INDEFINITE;
mMilliseconds = LL_MAXINT;
}
void
nsSMILTimeValue::SetUnresolved()
{
mState = STATE_UNRESOLVED;
mMilliseconds = LL_MAXINT;
}
nsSMILTime
nsSMILTimeValue::GetMillis() const
{
NS_ASSERTION(mState == STATE_RESOLVED,
"GetMillis() called for unresolved time.");
if (mState != STATE_RESOLVED)
return kUnresolvedSeconds;
return mMilliseconds;
}
void
nsSMILTimeValue::SetMillis(nsSMILTime aMillis)
{
mState = STATE_RESOLVED;
mMilliseconds = aMillis;
}
PRInt8
nsSMILTimeValue::CompareTo(const nsSMILTimeValue& aOther) const
{
PRInt8 result;
if (mState == STATE_RESOLVED) {
result = (aOther.mState == STATE_RESOLVED)
? Cmp(mMilliseconds, aOther.mMilliseconds)
: -1;
} else if (mState == STATE_INDEFINITE) {
if (aOther.mState == STATE_RESOLVED)
result = 1;
else if (aOther.mState == STATE_INDEFINITE)
result = 0;
else
result = -1;
} else {
result = (aOther.mState != STATE_UNRESOLVED) ? 1 : 0;
}
return result;
}

@ -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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 ***** */
#ifndef NS_SMILTIMEVALUE_H_
#define NS_SMILTIMEVALUE_H_
#include "prtypes.h"
#include "prlong.h"
#include "nsSMILTypes.h"
/*----------------------------------------------------------------------
* nsSMILTimeValue class
*
* A tri-state time value.
*
* First a quick overview of the SMIL time data types:
*
* nsSMILTime -- a timestamp in milliseconds.
* nsSMILTimeValue -- (this class) a timestamp that can take the additional
* states 'indefinite' and 'unresolved'
* nsSMILInterval -- a pair of nsSMILTimeValues that defines a begin and an
* end point.
* nsSMILInstanceTime -- an nsSMILTimeValue used for constructing intervals. It
* contains additional fields to govern reset behavior.
* It also forms an anchor for establishing syncbase
* relationships.
* nsSMILTimeValueSpec -- a component of a begin or end attribute, such as the
* '5s' or 'a.end+2m' in begin="5s; a.end+2m". These
* objects produce nsSMILInstanceTimes and are also used
* in managing dependent relationships between
* animations.
*
* Objects of this class may be in one of three states:
*
* 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 { return mState == STATE_INDEFINITE; }
void SetIndefinite();
PRBool IsResolved() const { return mState == STATE_RESOLVED; }
void SetUnresolved();
nsSMILTime GetMillis() const;
void SetMillis(nsSMILTime aMillis);
PRInt8 CompareTo(const nsSMILTimeValue& aOther) const;
private:
PRInt8 Cmp(PRInt64 aA, PRInt64 aB) const;
static nsSMILTime kUnresolvedSeconds;
nsSMILTime mMilliseconds;
enum {
STATE_RESOLVED,
STATE_INDEFINITE,
STATE_UNRESOLVED
} mState;
};
#endif // NS_SMILTIMEVALUE_H_

@ -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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 "nsSMILTimeValueSpec.h"
#include "nsSMILTimeValue.h"
#include "nsSMILTimedElement.h"
#include "nsSMILInstanceTime.h"
#include "nsSMILParserUtils.h"
#include "nsString.h"
#include "nsAutoPtr.h"
//----------------------------------------------------------------------
// Implementation
already_AddRefed<nsSMILTimeValueSpec>
NS_NewSMILTimeValueSpec(nsSMILTimedElement* aOwner,
PRBool aIsBegin,
const nsAString& aStringSpec)
{
nsSMILTimeValueSpec* result = new nsSMILTimeValueSpec(aOwner, aIsBegin);
NS_ENSURE_TRUE(result, nsnull);
NS_ADDREF(result); // Need to addref as SetSpec calls getWeakReference
nsresult rv = result->SetSpec(aStringSpec);
if (NS_FAILED(rv)) {
NS_RELEASE(result);
return nsnull;
}
return result;
}
nsSMILTimeValueSpec::nsSMILTimeValueSpec(nsSMILTimedElement* aOwner,
PRBool aIsBegin)
: mOwner(aOwner),
mIsBegin(aIsBegin),
mOffset() // initalises to zero
{
}
//----------------------------------------------------------------------
// nsISupports
NS_IMPL_ISUPPORTS1(nsSMILTimeValueSpec,
nsISupports)
//----------------------------------------------------------------------
// nsSMILTimeValueSpec
nsresult
nsSMILTimeValueSpec::SetSpec(const nsAString& aStringSpec)
{
// XXX Need to parse other specifiers, not just offset type
nsSMILTimeValue clockTime;
nsresult rv = nsSMILParserUtils::ParseClockValue(aStringSpec, &clockTime,
nsSMILParserUtils::kClockValueAllowSign
| nsSMILParserUtils::kClockValueAllowIndefinite);
if (NS_FAILED(rv) || (!clockTime.IsResolved() && !clockTime.IsIndefinite()))
return NS_ERROR_FAILURE;
if (clockTime.IsResolved())
mOffset = clockTime.GetMillis();
if (mOwner) {
nsSMILInstanceTime instance(clockTime, this);
mOwner->AddInstanceTime(instance, mIsBegin);
}
return rv;
}

@ -0,0 +1,95 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 ***** */
#ifndef NS_SMILTIMEVALUESPEC_H_
#define NS_SMILTIMEVALUESPEC_H_
#include "nsISupports.h"
#include "nsCOMPtr.h"
#include "nsSMILTypes.h"
class nsAString;
class nsSMILTimeValue;
class nsSMILTimedElement;
//----------------------------------------------------------------------
// nsSMILTimeValueSpec class
//
// An individual element of a 'begin' or 'end' attribute, e.g. '5s', 'a.end'.
// This class handles the parsing of such specifications and performs the
// necessary event handling (for event, repeat, and accesskey specifications)
// and synchronisation (for syncbase specifications).
//
// For an overview of how this class is related to other SMIL time classes see
// the documentstation in nsSMILTimeValue.h
// {39d2f376-6bda-42c0-8510-a93b24828a80}
#define NS_SMILTIMEVALUESPEC_IID \
{ 0x39d2f376, 0x6bda, 0x42c0, { 0x85, 0x10, 0xa9, 0x3b, 0x24, 0x82, 0x8a, 0x80 } }
class nsSMILTimeValueSpec : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_SMILTIMEVALUESPEC_IID)
NS_DECL_ISUPPORTS
protected:
nsSMILTimeValueSpec(nsSMILTimedElement* aOwner, PRBool aIsBegin);
friend already_AddRefed<nsSMILTimeValueSpec>
NS_NewSMILTimeValueSpec(nsSMILTimedElement* aOwner,
PRBool aIsBegin,
const nsAString& aStringSpec);
nsresult SetSpec(const nsAString& aStringSpec);
nsSMILTimedElement* mOwner;
PRPackedBool mIsBegin;
nsSMILTime mOffset;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsSMILTimeValueSpec, NS_SMILTIMEVALUESPEC_IID)
////////////////////////////////////////////////////////////////////////
// Factory methods
already_AddRefed<nsSMILTimeValueSpec>
NS_NewSMILTimeValueSpec(nsSMILTimedElement* aOwner,
PRBool aIsBegin,
const nsAString& aStringSpec);
#endif // NS_SMILTIMEVALUESPEC_H_

File diff suppressed because it is too large Load Diff

@ -0,0 +1,298 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 ***** */
#ifndef NS_SMILTIMEDELEMENT_H_
#define NS_SMILTIMEDELEMENT_H_
#include "nsSMILInterval.h"
#include "nsSMILInstanceTime.h"
#include "nsSMILTimeValueSpec.h"
#include "nsSMILRepeatCount.h"
#include "nsSMILTypes.h"
#include "nsTArray.h"
#include "nsAutoPtr.h"
#include "nsAttrValue.h"
class nsSMILAnimationFunction;
class nsSMILTimeContainer;
class nsSMILTimeValue;
class nsIAtom;
//----------------------------------------------------------------------
// nsSMILTimedElement
class nsSMILTimedElement
{
public:
nsSMILTimedElement();
/**
* Methods for supporting the nsIDOMElementTimeControl interface.
*/
/*
* Adds a new begin instance time at the current document time (as defined by
* aContainer) plus or minus the specified offset.
*
* @param aOffsetSeconds A real number specifying the number of seconds to add
* to the current container time.
* @param aContainer The time container with which this timed element is
* associated and which should be used for determining the
* current time.
* @return NS_OK if the operation succeeeded, or an error code otherwise.
*/
PRBool BeginElementAt(double aOffsetSeconds,
const nsSMILTimeContainer* aContainer);
/*
* Adds a new end instance time at the current document time (as defined by
* aContainer) plus or minus the specified offset.
*
* @param aOffsetSeconds A real number specifying the number of seconds to add
* to the current container time.
* @param aContainer The time container with which this timed element is
* associated and which should be used for determining the
* current time.
* @return NS_OK if the operation succeeeded, or an error code otherwise.
*/
PRBool EndElementAt(double aOffsetSeconds,
const nsSMILTimeContainer* aContainer);
/**
* Adds an instance time object this element's list of instance times.
* These instance times are used when creating intervals.
*
* This method is typically called by an nsSMILTimeValueSpec.
*
* @param aInstanceTime The time to add, expressed in document time.
*
* @param aIsBegin True if the time to be added represents a begin time
* or false if it represents an end time.
*/
void AddInstanceTime(const nsSMILInstanceTime& aInstanceTime,
PRBool aIsBegin);
/**
* 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 nsnull will simply disassociate the previous client, if
* any.
*/
void SetTimeClient(nsSMILAnimationFunction* aClient);
/**
* 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
* will be sampled with the appropriate simple time.
*
* @param aDocumentTime The document time at which to sample.
*/
void SampleAt(nsSMILTime aDocumentTime);
/**
* Reset the element's internal state. As described in SMILANIM 3.3.7, all
* instance times associated with DOM calls, events, etc. are cleared.
*/
void Reset();
/**
* Restores the element to its initial state. As with Reset() this involves
* clearing certain instance times, however in addition to the Reset()
* behaviour this method also discards all previously constructed intervals,
* removes any previously applied fill effects, and resets the elements
* internal state. It is suitable for use, for example, when the begin or end
* attribute has been updated.
*/
void HardReset();
/**
* Attempts to set an attribute on this timed element.
*
* @param aAttribute The name of the attribute to set. The namespace of this
* attribute is not specified as it is checked by the host
* element. Only attributes in the namespace defined for
* SMIL attributes in the host language are passed to the
* timed element.
* @param aValue The attribute value.
* @param aResult The nsAttrValue object that may be used for storing the
* parsed result.
* @param[out] aParseResult The result of parsing the attribute. Will be set
* to NS_OK if parsing is successful.
*
* @return PR_TRUE if the given attribute is a timing attribute, PR_FALSE
* otherwise.
*/
PRBool SetAttr(nsIAtom* aAttribute, const nsAString& aValue,
nsAttrValue& aResult, nsresult* aParseResult = nsnull);
/**
* Attempts to unset an attribute on this timed element.
*
* @param aAttribute The name of the attribute to set. As with SetAttr the
* namespace of the attribute is not specified (see
* SetAttr).
*
* @return PR_TRUE if the given attribute is a timing attribute, PR_FALSE
* otherwise.
*/
PRBool UnsetAttr(nsIAtom* aAttribute);
protected:
//
// Implementation helpers
//
nsresult SetBeginSpec(const nsAString& aBeginSpec);
nsresult SetEndSpec(const nsAString& aEndSpec);
nsresult SetSimpleDuration(const nsAString& aDurSpec);
nsresult SetMin(const nsAString& aMinSpec);
nsresult SetMax(const nsAString& aMaxSpec);
nsresult SetRestart(const nsAString& aRestartSpec);
nsresult SetRepeatCount(const nsAString& aRepeatCountSpec);
nsresult SetRepeatDur(const nsAString& aRepeatDurSpec);
nsresult SetFillMode(const nsAString& aFillModeSpec);
void UnsetBeginSpec();
void UnsetEndSpec();
void UnsetSimpleDuration();
void UnsetMin();
void UnsetMax();
void UnsetRestart();
void UnsetRepeatCount();
void UnsetRepeatDur();
void UnsetFillMode();
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 GetNextGreaterOrEqual(
const nsTArray<nsSMILInstanceTime>& aList,
const nsSMILTimeValue& aBase,
PRInt32& aPosition,
nsSMILTimeValue& aResult);
nsSMILTimeValue CalcActiveEnd(const nsSMILTimeValue& aBegin,
const nsSMILTimeValue& aEnd);
nsSMILTimeValue GetRepeatDuration();
nsSMILTimeValue ApplyMinAndMax(const nsSMILTimeValue& aDuration);
nsSMILTime ActiveTimeToSimpleTime(nsSMILTime aActiveTime,
PRUint32& aRepeatIteration);
void CheckForEarlyEnd(const nsSMILTimeValue& aDocumentTime);
void UpdateCurrentInterval();
void SampleSimpleTime(nsSMILTime aActiveTime);
void SampleFillValue();
PRBool AddInstanceTimeFromCurrentTime(double aOffsetSeconds,
PRBool aIsBegin, const nsSMILTimeContainer* aContainer);
// Typedefs
typedef nsTArray<nsRefPtr<nsSMILTimeValueSpec> > SMILTimeValueSpecList;
//
// Members
//
SMILTimeValueSpecList mBeginSpecs;
SMILTimeValueSpecList mEndSpecs;
nsSMILTimeValue mSimpleDur;
nsSMILRepeatCount mRepeatCount;
nsSMILTimeValue mRepeatDur;
nsSMILTimeValue mMin;
nsSMILTimeValue mMax;
enum nsSMILFillMode
{
FILL_REMOVE,
FILL_FREEZE
};
nsSMILFillMode mFillMode;
static nsAttrValue::EnumTable sFillModeTable[];
enum nsSMILRestartMode
{
RESTART_ALWAYS,
RESTART_WHENNOTACTIVE,
RESTART_NEVER
};
nsSMILRestartMode mRestartMode;
static nsAttrValue::EnumTable sRestartModeTable[];
//
// 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.
//
PRPackedBool mBeginSpecSet;
PRPackedBool mEndHasEventConditions;
nsTArray<nsSMILInstanceTime> mBeginInstances;
nsTArray<nsSMILInstanceTime> mEndInstances;
nsSMILAnimationFunction* mClient;
nsSMILInterval mCurrentInterval;
nsTArray<nsSMILInterval> mOldIntervals;
/**
* 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
{
STATE_STARTUP,
STATE_WAITING,
STATE_ACTIVE,
STATE_POSTACTIVE
};
nsSMILElementState mElementState;
};
#endif // NS_SMILTIMEDELEMENT_H_

@ -0,0 +1,57 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2009
* 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 ***** */
#ifndef NS_SMILTYPES_H_
#define NS_SMILTYPES_H_
#include "prtypes.h"
// A timestamp in milliseconds
//
// A time may represent:
//
// simple time -- offset within the simple duration
// active time -- offset within the active duration
// document time -- offset since the document begin
// wallclock time -- "real" time -- offset since the epoch
//
// For an overview of how this class is related to other SMIL time classes see
// the documentstation in nsSMILTimeValue.h
//
typedef PRInt64 nsSMILTime;
#endif // NS_SMILTYPES_H_

@ -0,0 +1,130 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert O'Callahan <roc+moz@cs.cmu.edu>
* 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 "nsSMILValue.h"
#include "nsDebug.h"
nsSMILValue::nsSMILValue(const nsISMILType* aType)
: mU(),
mType(&nsSMILNullType::sSingleton)
{
if (!aType) return;
nsresult rv = aType->Init(*this);
NS_POSTCONDITION(mType == aType || (NS_FAILED(rv) && IsNull()),
"Post-condition of Init failed. nsSMILValue is invalid.");
}
nsSMILValue::nsSMILValue(const nsSMILValue& aVal)
:
mU(),
mType(&nsSMILNullType::sSingleton)
{
nsresult rv = aVal.mType->Init(*this);
NS_POSTCONDITION(mType == aVal.mType || (NS_FAILED(rv) && IsNull()),
"Post-condition of Init failed. nsSMILValue is invalid.");
if (NS_FAILED(rv)) return;
mType->Assign(*this, aVal);
}
const nsSMILValue&
nsSMILValue::operator=(const nsSMILValue& aVal)
{
if (&aVal == this)
return *this;
if (mType != aVal.mType) {
mType->Destroy(*this);
NS_POSTCONDITION(IsNull(), "nsSMILValue not null after destroying");
nsresult rv = aVal.mType->Init(*this);
NS_POSTCONDITION(mType == aVal.mType || (NS_FAILED(rv) && IsNull()),
"Post-condition of Init failed. nsSMILValue is invalid.");
if (NS_FAILED(rv)) return *this;
}
mType->Assign(*this, aVal);
return *this;
}
nsresult
nsSMILValue::Add(const nsSMILValue& aValueToAdd, PRUint32 aCount)
{
if (aValueToAdd.IsNull()) return NS_OK;
if (aValueToAdd.mType != mType) {
NS_WARNING("Trying to add incompatible types.");
return NS_ERROR_FAILURE;
}
return mType->Add(*this, aValueToAdd, aCount);
}
nsresult
nsSMILValue::ComputeDistance(const nsSMILValue& aTo, double& aDistance) const
{
if (aTo.mType != mType) {
NS_WARNING("Trying to calculate distance between incompatible types.");
return NS_ERROR_FAILURE;
}
return mType->ComputeDistance(*this, aTo, aDistance);
}
nsresult
nsSMILValue::Interpolate(const nsSMILValue& aEndVal,
double aUnitDistance,
nsSMILValue& aResult) const
{
if (aEndVal.mType != mType) {
NS_WARNING("Trying to interpolate between incompatible types.");
return NS_ERROR_FAILURE;
}
if (aResult.mType != mType) {
aResult.mType->Destroy(aResult);
NS_POSTCONDITION(aResult.IsNull(), "nsSMILValue not null after destroying");
nsresult rv = mType->Init(aResult);
NS_POSTCONDITION(aResult.mType == mType
|| (NS_FAILED(rv) && aResult.IsNull()),
"Post-condition of Init failed. nsSMILValue is invalid.");
if (NS_FAILED(rv)) return rv;
}
return mType->Interpolate(*this, aEndVal, aUnitDistance, aResult);
}

@ -0,0 +1,78 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert O'Callahan <roc+moz@cs.cmu.edu>
* 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_SMILVALUE_H_
#define NS_SMILVALUE_H_
#include "nsISMILType.h"
#include "nsSMILNullType.h"
class nsSMILValue
{
public:
nsSMILValue() : mU(), mType(&nsSMILNullType::sSingleton) { }
nsSMILValue(const nsISMILType* aType);
nsSMILValue(const nsSMILValue& aVal);
~nsSMILValue()
{
mType->Destroy(*this);
}
const nsSMILValue& operator=(const nsSMILValue& aVal);
PRBool IsNull() const
{
return (mType == &nsSMILNullType::sSingleton);
}
nsresult Add(const nsSMILValue& aValueToAdd, PRUint32 aCount = 1);
nsresult ComputeDistance(const nsSMILValue& aTo, double& aDistance) const;
nsresult Interpolate(const nsSMILValue& aEndVal,
double aUnitDistance,
nsSMILValue& aResult) const;
union {
PRInt64 mInt;
double mDouble;
void* mPtr;
} mU;
const nsISMILType* mType;
};
#endif // NS_SMILVALUE_H_

@ -0,0 +1,50 @@
# ***** 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 SMIL module.
#
# The Initial Developer of the Original Code is
# Mozilla Corporation.
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Daniel Holbert <dholbert@mozilla.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 *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = content/smil/test
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = test_smilRestart.xhtml \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)

@ -0,0 +1,105 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test for SMIL Restart Behavior </title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="120px" height="120px">
<!-- These 3 circles only differ in their animation's "restart" value -->
<circle cx="20" cy="20" r="15" fill="blue">
<animate attributeName="cx" from="20" to="100" begin="0s" dur="4s"
restart="always" id="always" attributeType="XML"/>
</circle>
<circle cx="20" cy="60" r="15" fill="blue">
<animate attributeName="cx" from="20" to="100" begin="0s" dur="4s"
restart="whenNotActive" id="whenNotActive" attributeType="XML"/>
</circle>
<circle cx="20" cy="100" r="15" fill="blue">
<animate attributeName="cx" from="20" to="100" begin="0s" dur="4s"
restart="never" id="never" attributeType="XML"/>
</circle>
</svg>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
<![CDATA[
/** Test for SMIL Restart Behavior **/
/* Global Variables */
var dur = 4.0; // this must match the "dur" attribute on animations above.
var svg = document.getElementById("svg");
SimpleTest.waitForExplicitFinish();
// main: just triggers the first link in the chain of function-calls
function main() {
checkInitialState();
}
// Attempt a "beginElement" call on the given element, and
// complain if we don't get the expected return value.
// 'time' is only provided for better diagnostic output.
function tryRestartElem(id, time, expectedRetVal) {
var elem = document.getElementById(id);
var retVal = elem.beginElement();
is(retVal, expectedRetVal,
"Error restarting animation '" + id +
"' at time = " + time + ": " +
"expected return value of " + expectedRetVal +
", but got " + retVal + ".");
}
function checkInitialState() {
svg.setCurrentTime(0.0);
setTimeout('doCheckInitialState(0.0)', 0);
}
function doCheckInitialState(time) {
tryRestartElem('always', time, true);
tryRestartElem('whenNotActive', time, false);
tryRestartElem('never', time, false);
checkHalfwayState();
}
function checkHalfwayState() {
svg.setCurrentTime(0.5 * dur);
setTimeout('doCheckHalfwayState(0.5 * dur)', 0);
}
function doCheckHalfwayState(time) {
tryRestartElem('always', time, true);
tryRestartElem('whenNotActive', time, false);
tryRestartElem('never', time, false);
checkEndingState();
}
function checkEndingState() {
svg.setCurrentTime(dur);
setTimeout('doCheckEndingState(dur)', 0);
}
function doCheckEndingState(time) {
tryRestartElem('always', time, true);
tryRestartElem('whenNotActive', time, true);
tryRestartElem('never', time, false);
checkAfterEndingState();
}
function checkAfterEndingState() {
svg.setCurrentTime(dur * 3);
setTimeout('doCheckAfterEndingState(dur * 3)', 0);
}
function doCheckAfterEndingState(time) {
tryRestartElem('always', time, true);
tryRestartElem('whenNotActive', time, true);
tryRestartElem('never', time, false);
SimpleTest.finish();
}
window.addEventListener("load", main, false);
]]>
</script>
</pre>
</body>
</html>

@ -21,6 +21,7 @@
#
# Contributor(s):
# Alex Fritze <alex.fritze@crocodile-clips.com>
# Chris Double <chris.double@double.co.nz>
#
# 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"),
@ -137,6 +138,13 @@ CPPSRCS = \
nsSVGValue.cpp \
$(NULL)
ifdef MOZ_SMIL
CPPSRCS += nsSVGAnimateElement.cpp \
nsSVGAnimationElement.cpp \
nsSVGSetElement.cpp \
$(NULL)
endif
include $(topsrcdir)/config/config.mk
# we don't want the shared lib, but we want to force the creation of a static lib.
@ -155,7 +163,6 @@ EXPORTS = \
nsSVGMatrix.h \
$(NULL)
include $(topsrcdir)/config/rules.mk
INCLUDES += \
@ -171,4 +178,10 @@ INCLUDES += \
-I$(topsrcdir)/content/xbl/src \
$(NULL)
ifdef MOZ_SMIL
INCLUDES += \
-I$(srcdir)/../../../smil \
$(NULL)
endif
DEFINES += -D_IMPL_NS_LAYOUT

@ -0,0 +1,106 @@
/* -*- 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.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 "nsSVGAnimationElement.h"
#include "nsIDOMSVGAnimateElement.h"
#include "nsSMILAnimationFunction.h"
typedef nsSVGAnimationElement nsSVGAnimateElementBase;
class nsSVGAnimateElement : public nsSVGAnimateElementBase,
public nsIDOMSVGAnimateElement
{
protected:
friend nsresult NS_NewSVGAnimateElement(nsIContent **aResult,
nsINodeInfo *aNodeInfo);
nsSVGAnimateElement(nsINodeInfo* aNodeInfo);
nsSMILAnimationFunction mAnimationFunction;
public:
// interfaces:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMSVGANIMATEELEMENT
NS_FORWARD_NSIDOMNODE(nsSVGAnimateElementBase::)
NS_FORWARD_NSIDOMELEMENT(nsSVGAnimateElementBase::)
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGAnimateElementBase::)
NS_FORWARD_NSIDOMSVGANIMATIONELEMENT(nsSVGAnimateElementBase::)
// nsIDOMNode
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
// nsISMILAnimationElement
virtual nsSMILAnimationFunction& AnimationFunction();
};
NS_IMPL_NS_NEW_SVG_ELEMENT(Animate)
//----------------------------------------------------------------------
// nsISupports methods
NS_IMPL_ADDREF_INHERITED(nsSVGAnimateElement,nsSVGAnimateElementBase)
NS_IMPL_RELEASE_INHERITED(nsSVGAnimateElement,nsSVGAnimateElementBase)
NS_INTERFACE_TABLE_HEAD(nsSVGAnimateElement)
NS_NODE_INTERFACE_TABLE5(nsSVGAnimateElement, nsIDOMNode, nsIDOMElement,
nsIDOMSVGElement, nsIDOMSVGAnimationElement,
nsIDOMSVGAnimateElement)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimateElement)
NS_INTERFACE_MAP_END_INHERITING(nsSVGAnimateElementBase)
//----------------------------------------------------------------------
// Implementation
nsSVGAnimateElement::nsSVGAnimateElement(nsINodeInfo *aNodeInfo)
: nsSVGAnimateElementBase(aNodeInfo)
{
}
//----------------------------------------------------------------------
// nsIDOMNode methods
NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGAnimateElement)
//----------------------------------------------------------------------
// nsISMILAnimationElement methods
nsSMILAnimationFunction&
nsSVGAnimateElement::AnimationFunction()
{
return mAnimationFunction;
}

@ -0,0 +1,404 @@
/* -*- 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.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Birtles <birtles@gmail.com>
* Chris Double <chris.double@double.co.nz>
*
* 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 "nsSVGAnimationElement.h"
#include "nsSVGSVGElement.h"
#include "nsSMILTimeContainer.h"
#include "nsSMILAnimationController.h"
#include "nsSMILAnimationFunction.h"
#include "nsISMILAttr.h"
#include "nsBindingManager.h"
//----------------------------------------------------------------------
// nsISupports methods
NS_IMPL_ADDREF_INHERITED(nsSVGAnimationElement, nsSVGAnimationElementBase)
NS_IMPL_RELEASE_INHERITED(nsSVGAnimationElement, nsSVGAnimationElementBase)
NS_INTERFACE_MAP_BEGIN(nsSVGAnimationElement)
NS_INTERFACE_MAP_ENTRY(nsISMILAnimationElement)
NS_INTERFACE_MAP_ENTRY(nsIDOMElementTimeControl)
NS_INTERFACE_MAP_END_INHERITING(nsSVGAnimationElementBase)
//----------------------------------------------------------------------
// Implementation
nsSVGAnimationElement::nsSVGAnimationElement(nsINodeInfo *aNodeInfo)
: nsSVGAnimationElementBase(aNodeInfo),
mTimedDocumentRoot(nsnull)
{
}
nsresult
nsSVGAnimationElement::Init()
{
nsresult rv = nsSVGAnimationElementBase::Init();
NS_ENSURE_SUCCESS(rv, rv);
AnimationFunction().SetAnimationElement(this);
mTimedElement.SetTimeClient(&AnimationFunction());
return NS_OK;
}
//----------------------------------------------------------------------
// nsISMILAnimationElement methods
const nsIContent&
nsSVGAnimationElement::Content() const
{
return *this;
}
nsIContent&
nsSVGAnimationElement::Content()
{
return *this;
}
const nsAttrValue*
nsSVGAnimationElement::GetAnimAttr(nsIAtom* aName) const
{
return mAttrsAndChildren.GetAttr(aName, kNameSpaceID_None);
}
nsIContent*
nsSVGAnimationElement::GetTargetElementContent()
{
if (HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)) {
// XXXdholbert: Use xlink:href attr to look up target element here.
// Note: Need to check for updated target element each sample, because
// the existing target's ID might've changed, or another element
// with the same ID might've been inserted earlier in the DOM tree.
NS_NOTYETIMPLEMENTED("nsSVGAnimationElement::GetTargetElementContent for "
"xlink:href-targeted animations");
return nsnull;
}
// No "xlink:href" attribute --> target is my parent.
return GetParentElement();
}
nsIAtom*
nsSVGAnimationElement::GetTargetAttributeName() const
{
const nsAttrValue* nameAttr
= mAttrsAndChildren.GetAttr(nsGkAtoms::attributeName);
if (!nameAttr)
return nsnull;
NS_ASSERTION(nameAttr->Type() == nsAttrValue::eAtom,
"attributeName should have been parsed as an atom");
return nameAttr->GetAtomValue();
}
nsSMILTargetAttrType
nsSVGAnimationElement::GetTargetAttributeType() const
{
nsIContent::AttrValuesArray typeValues[] = { &nsGkAtoms::css,
&nsGkAtoms::XML };
nsSMILTargetAttrType smilTypes[] = { eSMILTargetAttrType_CSS,
eSMILTargetAttrType_XML };
PRInt32 index = FindAttrValueIn(kNameSpaceID_None,
nsGkAtoms::attributeType,
typeValues,
eCaseMatters);
return (index >= 0) ? smilTypes[index] : eSMILTargetAttrType_auto;
}
nsSMILTimedElement&
nsSVGAnimationElement::TimedElement()
{
return mTimedElement;
}
//----------------------------------------------------------------------
// nsIDOMSVGAnimationElement methods
/* readonly attribute SVGElement targetElement; */
NS_IMETHODIMP
nsSVGAnimationElement::GetTargetElement(nsIDOMSVGElement** aTarget)
{
// We'll just call the other GetTargetElement method, and QI to the right type
nsIContent* targetContent = GetTargetElementContent();
nsCOMPtr<nsIDOMSVGElement> targetSVG = do_QueryInterface(targetContent);
NS_IF_ADDREF(*aTarget = targetSVG);
return NS_OK;
}
NS_IMETHODIMP
nsSVGAnimationElement::GetStartTime(float* retval)
{
// XXX
*retval = 0.f;
NS_NOTYETIMPLEMENTED("nsSVGAnimationElement::GetStartTime");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsSVGAnimationElement::GetCurrentTime(float* retval)
{
// XXX
*retval = 0.f;
NS_NOTYETIMPLEMENTED("nsSVGAnimationElement::GetCurrentTime");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsSVGAnimationElement::GetSimpleDuration(float* retval)
{
// XXX
*retval = 0.f;
NS_NOTYETIMPLEMENTED("nsSVGAnimationElement::GetSimpleDuration");
return NS_ERROR_NOT_IMPLEMENTED;
}
//----------------------------------------------------------------------
// nsIContent methods
nsresult
nsSVGAnimationElement::BindToTree(nsIDocument* aDocument,
nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsresult rv = nsSVGAnimationElementBase::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv,rv);
// XXXdholbert is ownerDOMSVG (as a check for SVG parent) still needed here?
nsCOMPtr<nsIDOMSVGSVGElement> ownerDOMSVG;
rv = GetOwnerSVGElement(getter_AddRefs(ownerDOMSVG));
if (NS_FAILED(rv) || !ownerDOMSVG)
// No use proceeding. We don't have an SVG parent (yet) so we won't be able
// to register ourselves etc. Maybe next time we'll have more luck.
// (This sort of situation will arise a lot when trees are being constructed
// piece by piece via script)
return NS_OK;
mTimedDocumentRoot = GetTimeContainer();
if (!mTimedDocumentRoot)
// Timed document root hasn't been created yet. This will be created when
// the SVG parent is bound. This happens when we create SVG trees entirely
// by script.
return NS_OK;
// Add myself to the animation controller's master set of animation elements.
if (aDocument) {
nsSMILAnimationController *controller = aDocument->GetAnimationController();
if (controller) {
controller->RegisterAnimationElement(this);
}
}
return NS_OK;
}
void
nsSVGAnimationElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
nsIDocument *doc = GetOwnerDoc();
if (doc) {
nsSMILAnimationController *controller = doc->GetAnimationController();
if (controller) {
controller->UnregisterAnimationElement(this);
}
}
if (mTimedDocumentRoot) {
mTimedDocumentRoot = nsnull;
}
nsSVGAnimationElementBase::UnbindFromTree(aDeep, aNullParent);
}
//----------------------------------------------------------------------
// nsIContent methods
PRBool
nsSVGAnimationElement::ParseAttribute(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aNamespaceID == kNameSpaceID_None) {
// Deal with target-related attributes here
if (aAttribute == nsGkAtoms::attributeName ||
aAttribute == nsGkAtoms::attributeType) {
aResult.ParseAtom(aValue);
return PR_TRUE;
}
nsresult rv = NS_ERROR_FAILURE;
// First let the animation function try to parse it...
PRBool foundMatch =
AnimationFunction().SetAttr(aAttribute, aValue, aResult, &rv);
// ... and if that didn't recognize the attribute, let the timed element
// try to parse it.
if (!foundMatch) {
foundMatch = mTimedElement.SetAttr(aAttribute, aValue, aResult, &rv);
}
if (foundMatch) {
if (NS_FAILED(rv)) {
ReportAttributeParseFailure(GetOwnerDoc(), aAttribute, aValue);
return PR_FALSE;
}
return PR_TRUE;
}
}
return nsSVGAnimationElementBase::ParseAttribute(aNamespaceID, aAttribute,
aValue, aResult);
}
nsresult
nsSVGAnimationElement::UnsetAttr(PRInt32 aNamespaceID,
nsIAtom* aAttribute, PRBool aNotify)
{
nsresult rv = nsSVGAnimationElementBase::UnsetAttr(aNamespaceID, aAttribute,
aNotify);
NS_ENSURE_SUCCESS(rv,rv);
if (aNamespaceID == kNameSpaceID_None) {
if (!AnimationFunction().UnsetAttr(aAttribute)) {
mTimedElement.UnsetAttr(aAttribute);
}
}
return NS_OK;
}
//----------------------------------------------------------------------
// Implementation helpers
nsSMILTimeContainer*
nsSVGAnimationElement::GetTimeContainer()
{
nsSMILTimeContainer *result = nsnull;
nsCOMPtr<nsIDOMSVGSVGElement> ownerDOMSVG;
nsresult rv = GetOwnerSVGElement(getter_AddRefs(ownerDOMSVG));
if (NS_SUCCEEDED(rv) && ownerDOMSVG) {
nsSVGSVGElement *ownerSVG =
static_cast<nsSVGSVGElement*>(ownerDOMSVG.get());
result = ownerSVG->GetTimedDocumentRoot();
}
return result;
}
nsIContent*
nsSVGAnimationElement::GetParentElement()
{
nsCOMPtr<nsIContent> result;
nsBindingManager* bindingManager = nsnull;
nsIDocument* ownerDoc = GetOwnerDoc();
if (ownerDoc)
bindingManager = ownerDoc->BindingManager();
if (bindingManager)
// we have a binding manager -- do we have an anonymous parent?
result = bindingManager->GetInsertionParent(this);
if (!result)
// if we didn't find an anonymous parent, use the explicit one,
// whether it's null or not...
result = GetParent();
return result;
}
// nsIDOMElementTimeControl
/* void beginElement (); */
NS_IMETHODIMP
nsSVGAnimationElement::BeginElement(void)
{
return BeginElementAt(0.f);
}
/* void beginElementAt (in float offset); */
NS_IMETHODIMP
nsSVGAnimationElement::BeginElementAt(float offset)
{
nsSVGSVGElement *ownerSVG = GetCtx();
if (!ownerSVG)
return NS_ERROR_FAILURE;
ownerSVG->RequestSample();
// We ignore the return code. The SMIL version of this interface has a void
// return type and no exception specification so there's no way to indicate
// that begin failed (e.g. because the element has restart="none").
mTimedElement.BeginElementAt(offset, mTimedDocumentRoot);
return NS_OK;
}
/* void endElement (); */
NS_IMETHODIMP
nsSVGAnimationElement::EndElement(void)
{
return EndElementAt(0.f);
}
/* void endElementAt (in float offset); */
NS_IMETHODIMP
nsSVGAnimationElement::EndElementAt(float offset)
{
nsSVGSVGElement *ownerSVG = GetCtx();
if (!ownerSVG)
return NS_ERROR_FAILURE;
ownerSVG->RequestSample();
// As with BeginElementAt, ignore the return code.
mTimedElement.EndElementAt(offset, mTimedDocumentRoot);
return NS_OK;
}

@ -0,0 +1,101 @@
/* -*- 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.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Birtles <birtles@gmail.com>
* Chris Double <chris.double@double.co.nz>
*
* 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_SVGANIMATIONELEMENT_H_
#define NS_SVGANIMATIONELEMENT_H_
#include "nsSVGElement.h"
#include "nsAutoPtr.h"
#include "nsIDOMSVGAnimationElement.h"
#include "nsIDOMElementTimeControl.h"
#include "nsISMILAnimationElement.h"
#include "nsSMILTimedElement.h"
class nsSMILTimeContainer;
typedef nsSVGElement nsSVGAnimationElementBase;
class nsSVGAnimationElement : public nsSVGAnimationElementBase,
public nsISMILAnimationElement,
public nsIDOMElementTimeControl
{
protected:
nsSVGAnimationElement(nsINodeInfo *aNodeInfo);
nsresult Init();
public:
// interfaces:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMSVGANIMATIONELEMENT
NS_DECL_NSIDOMELEMENTTIMECONTROL
// nsIContent specializations
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep, PRBool aNullParent);
// nsIContent specializations
virtual nsresult UnsetAttr(PRInt32 aNamespaceID, nsIAtom* aAttribute,
PRBool aNotify);
// nsGenericElement specializations
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
// nsISMILAnimationElement interface
virtual const nsIContent& Content() const;
virtual nsIContent& Content();
virtual const nsAttrValue* GetAnimAttr(nsIAtom* aName) const;
virtual nsIContent* GetTargetElementContent();
virtual nsIAtom* GetTargetAttributeName() const;
virtual nsSMILTargetAttrType GetTargetAttributeType() const;
virtual nsSMILTimedElement& TimedElement();
virtual nsSMILTimeContainer* GetTimeContainer();
protected:
// Implementation helpers
nsIContent* GetParentElement();
nsSMILTimedElement mTimedElement;
nsSMILTimeContainer* mTimedDocumentRoot;
};
#endif // NS_SVGANIMATIONELEMENT_H_

@ -87,8 +87,12 @@
#include "nsIDOMSVGAnimTransformList.h"
#include "nsIDOMSVGAnimatedRect.h"
#include "nsSVGRect.h"
#include "nsIFrame.h"
#include "prdtoa.h"
#include <stdarg.h>
#ifdef MOZ_SMIL
#include "nsIDOMSVGTransformable.h"
#endif // MOZ_SMIL
nsSVGEnumMapping nsSVGElement::sSVGUnitTypesMap[] = {
{&nsGkAtoms::userSpaceOnUse, nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE},
@ -1211,6 +1215,19 @@ nsSVGElement::DidChangeLength(PRUint8 aAttrEnum, PRBool aDoSetAttr)
newStr, PR_TRUE);
}
void
nsSVGElement::DidAnimateLength(PRUint8 aAttrEnum)
{
nsIFrame* frame = GetPrimaryFrame();
if (frame) {
LengthAttributesInfo info = GetLengthInfo();
frame->AttributeChanged(kNameSpaceID_None,
*info.mLengthInfo[aAttrEnum].mName,
nsIDOMMutationEvent::MODIFICATION);
}
}
void
nsSVGElement::GetAnimatedLengthValues(float *aFirst, ...)
{
@ -1620,3 +1637,19 @@ nsSVGElement::RecompileScriptEventListeners()
AddScriptEventListener(GetEventNameForAttr(attr), value, PR_TRUE);
}
}
#ifdef MOZ_SMIL
nsISMILAttr*
nsSVGElement::GetAnimatedAttr(const nsIAtom* aName)
{
// Lengths:
LengthAttributesInfo info = GetLengthInfo();
for (PRUint32 i = 0; i < info.mLengthCount; i++) {
if (aName == *info.mLengthInfo[i].mName) {
return info.mLengths[i].ToSMILAttr(this);
}
}
return nsnull;
}
#endif // MOZ_SMIL

@ -54,6 +54,11 @@
#include "nsWeakReference.h"
#include "nsICSSStyleRule.h"
#ifdef MOZ_SMIL
#include "nsISMILAttr.h"
#include "nsSMILAnimationController.h"
#endif
class nsSVGSVGElement;
class nsSVGLength2;
class nsSVGNumber2;
@ -142,10 +147,16 @@ public:
virtual void DidChangePreserveAspectRatio(PRBool aDoSetAttr);
virtual void DidChangeString(PRUint8 aAttrEnum, PRBool aDoSetAttr);
void DidAnimateLength(PRUint8 aAttrEnum);
void GetAnimatedLengthValues(float *aFirst, ...);
void GetAnimatedNumberValues(float *aFirst, ...);
void GetAnimatedIntegerValues(PRInt32 *aFirst, ...);
#ifdef MOZ_SMIL
virtual nsISMILAttr* GetAnimatedAttr(const nsIAtom* aName);
#endif
virtual void RecompileScriptEventListeners();
protected:
@ -155,6 +166,9 @@ protected:
const nsAString* aValue, PRBool aNotify);
virtual PRBool ParseAttribute(PRInt32 aNamespaceID, nsIAtom* aAttribute,
const nsAString& aValue, nsAttrValue& aResult);
static nsresult ReportAttributeParseFailure(nsIDocument* aDocument,
nsIAtom* aAttribute,
const nsAString& aValue);
// Hooks for subclasses
virtual PRBool IsEventName(nsIAtom* aName);
@ -329,10 +343,6 @@ private:
ParseIntegerOptionalInteger(const nsAString& aValue,
PRUint32 aIndex1, PRUint32 aIndex2);
static nsresult ReportAttributeParseFailure(nsIDocument* aDocument,
nsIAtom* aAttribute,
const nsAString& aValue);
void ResetOldStyleBaseType(nsISVGValue *svg_value);
nsCOMPtr<nsICSSStyleRule> mContentStyleRule;

@ -21,6 +21,7 @@
*
* Contributor(s):
* Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
* Chris Double <chris.double@double.co.nz>
*
* 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"),
@ -63,7 +64,8 @@ NS_NewSVGRectElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGGElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGSVGElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
NS_NewSVGSVGElement(nsIContent **aResult, nsINodeInfo *aNodeInfo,
PRBool aFromParser);
nsresult
NS_NewSVGForeignObjectElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
@ -159,8 +161,16 @@ NS_NewSVGFEImageElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGFEDisplacementMapElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
#ifdef MOZ_SMIL
nsresult
NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo)
NS_NewSVGAnimateElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
nsresult
NS_NewSVGSetElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
#endif // MOZ_SMIL
nsresult
NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo,
PRBool aFromParser)
{
NS_PRECONDITION(NS_SVGEnabled(),
"creating an SVG element while SVG disabled");
@ -189,7 +199,7 @@ NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo)
if (name == nsGkAtoms::rect)
return NS_NewSVGRectElement(aResult, aNodeInfo);
if (name == nsGkAtoms::svg)
return NS_NewSVGSVGElement(aResult, aNodeInfo);
return NS_NewSVGSVGElement(aResult, aNodeInfo, aFromParser);
if (name == nsGkAtoms::g)
return NS_NewSVGGElement(aResult, aNodeInfo);
if (name == nsGkAtoms::foreignObject)
@ -286,6 +296,12 @@ NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo)
return NS_NewSVGMaskElement(aResult, aNodeInfo);
if (name == nsGkAtoms::svgSwitch)
return NS_NewSVGSwitchElement(aResult, aNodeInfo);
#ifdef MOZ_SMIL
if (name == nsGkAtoms::animate)
return NS_NewSVGAnimateElement(aResult, aNodeInfo);
if (name == nsGkAtoms::set)
return NS_NewSVGSetElement(aResult, aNodeInfo);
#endif // MOZ_SMIL
// if we don't know what to create, just create a standard xml element:
return NS_NewXMLElement(aResult, aNodeInfo);

@ -42,6 +42,10 @@
#include "nsSVGSVGElement.h"
#include "nsIFrame.h"
#include "nsSVGIntegrationUtils.h"
#ifdef MOZ_SMIL
#include "nsSMILValue.h"
#include "nsSMILFloatType.h"
#endif // MOZ_SMIL
NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGLength2::DOMBaseVal, mSVGElement)
@ -408,6 +412,13 @@ nsSVGLength2::SetBaseValue(float aValue, nsSVGElement *aSVGElement)
aSVGElement->DidChangeLength(mAttrEnum, PR_TRUE);
}
void
nsSVGLength2::SetAnimValue(float aValue, nsSVGElement *aSVGElement)
{
mAnimVal = aValue * GetUnitScaleFactor(aSVGElement);
aSVGElement->DidAnimateLength(mAttrEnum);
}
nsresult
nsSVGLength2::ToDOMAnimatedLength(nsIDOMSVGAnimatedLength **aResult,
nsSVGElement *aSVGElement)
@ -419,3 +430,44 @@ nsSVGLength2::ToDOMAnimatedLength(nsIDOMSVGAnimatedLength **aResult,
NS_ADDREF(*aResult);
return NS_OK;
}
#ifdef MOZ_SMIL
nsISMILAttr*
nsSVGLength2::ToSMILAttr(nsSVGElement *aSVGElement)
{
return new SMILLength(this, aSVGElement);
}
nsresult
nsSVGLength2::SMILLength::ValueFromString(const nsAString& aStr,
const nsISMILAnimationElement* /*aSrcElement*/,
nsSMILValue& aValue) const
{
nsSVGLength2 tmp;
tmp.SetBaseValueString(aStr, mSVGElement, PR_FALSE);
nsSMILValue val(&nsSMILFloatType::sSingleton);
val.mU.mDouble = tmp.GetBaseValue(mSVGElement);
aValue = val;
return NS_OK;
}
nsSMILValue
nsSVGLength2::SMILLength::GetBaseValue() const
{
nsSMILValue val(&nsSMILFloatType::sSingleton);
val.mU.mDouble = mVal->GetBaseValue(mSVGElement);
return val;
}
nsresult
nsSVGLength2::SMILLength::SetAnimValue(const nsSMILValue& aValue)
{
NS_ASSERTION(aValue.mType == &nsSMILFloatType::sSingleton,
"Unexpected type to assign animated value");
if (aValue.mType == &nsSMILFloatType::sSingleton) {
mVal->SetAnimValue((float)aValue.mU.mDouble, mSVGElement);
}
return NS_OK;
}
#endif // MOZ_SMIL

@ -43,6 +43,12 @@
#include "nsSVGElement.h"
#include "nsDOMError.h"
#ifdef MOZ_SMIL
#include "nsISMILAttr.h"
class nsSMILValue;
class nsISMILType;
#endif // MOZ_SMIL
class nsIFrame;
class nsSVGLength2
@ -87,6 +93,10 @@ public:
nsresult ToDOMAnimatedLength(nsIDOMSVGAnimatedLength **aResult,
nsSVGElement* aSVGElement);
#ifdef MOZ_SMIL
// Returns a new nsISMILAttr object that the caller must delete
nsISMILAttr* ToSMILAttr(nsSVGElement* aSVGElement);
#endif // MOZ_SMIL
private:
@ -115,6 +125,7 @@ private:
float GetUnitScaleFactor(nsSVGSVGElement *aCtx) const;
void SetBaseValue(float aValue, nsSVGElement *aSVGElement);
void SetBaseValueInSpecifiedUnits(float aValue, nsSVGElement *aSVGElement);
void SetAnimValue(float aValue, nsSVGElement *aSVGElement);
void NewValueSpecifiedUnits(PRUint16 aUnitType, float aValue,
nsSVGElement *aSVGElement);
void ConvertToSpecifiedUnits(PRUint16 aUnitType, nsSVGElement *aSVGElement);
@ -215,6 +226,29 @@ private:
NS_IMETHOD GetAnimVal(nsIDOMSVGLength **aAnimVal)
{ return mVal->ToDOMAnimVal(aAnimVal, mSVGElement); }
};
#ifdef MOZ_SMIL
struct SMILLength : public nsISMILAttr
{
public:
SMILLength(nsSVGLength2* aVal, nsSVGElement *aSVGElement)
: mVal(aVal), mSVGElement(aSVGElement) {}
// These will stay alive because a nsISMILAttr only lives as long
// as the Compositing step, and DOM elements don't get a chance to
// die during that.
nsSVGLength2* mVal;
nsSVGElement* mSVGElement;
// nsISMILAttr methods
virtual nsresult ValueFromString(const nsAString& aStr,
const nsISMILAnimationElement* aSrcElement,
nsSMILValue &aValue) const;
virtual nsSMILValue GetBaseValue() const;
virtual nsresult SetAnimValue(const nsSMILValue& aValue);
};
#endif // MOZ_SMIL
};
#endif
#endif // __NS_SVGLENGTH2_H__

@ -22,6 +22,7 @@
* Contributor(s):
* Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
* Jonathan Watt <jonathan.watt@strath.ac.uk>
* Chris Double <chris.double@double.co.nz>
*
* 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"),
@ -63,6 +64,17 @@
#include "nsSVGUtils.h"
#include "nsSVGSVGElement.h"
#ifdef MOZ_SMIL
#include "nsEventDispatcher.h"
#include "nsSMILTimeContainer.h"
#include "nsSMILAnimationController.h"
#include "nsSMILTypes.h"
#include "nsIContentIterator.h"
nsresult NS_NewContentIterator(nsIContentIterator** aInstancePtrResult);
#endif // MOZ_SMIL
nsSVGElement::LengthInfo nsSVGSVGElement::sLengthInfo[4] =
{
{ &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, nsSVGUtils::X },
@ -85,7 +97,28 @@ nsSVGElement::EnumInfo nsSVGSVGElement::sEnumInfo[1] =
}
};
NS_IMPL_NS_NEW_SVG_ELEMENT(SVG)
// From NS_IMPL_NS_NEW_SVG_ELEMENT but with aFromParser
nsresult
NS_NewSVGSVGElement(nsIContent **aResult, nsINodeInfo *aNodeInfo,
PRBool aFromParser)
{
nsSVGSVGElement *it = new nsSVGSVGElement(aNodeInfo, aFromParser);
if (!it)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(it);
nsresult rv = it->Init();
if (NS_FAILED(rv)) {
NS_RELEASE(it);
return rv;
}
*aResult = it;
return rv;
}
//----------------------------------------------------------------------
// nsISupports methods
@ -104,7 +137,7 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGSVGElementBase)
//----------------------------------------------------------------------
// Implementation
nsSVGSVGElement::nsSVGSVGElement(nsINodeInfo* aNodeInfo)
nsSVGSVGElement::nsSVGSVGElement(nsINodeInfo* aNodeInfo, PRBool aFromParser)
: nsSVGSVGElementBase(aNodeInfo),
mCoordCtx(nsnull),
mViewportWidth(0),
@ -115,6 +148,9 @@ nsSVGSVGElement::nsSVGSVGElement(nsINodeInfo* aNodeInfo)
mPreviousScale(0),
mRedrawSuspendCount(0),
mDispatchEvent(PR_FALSE)
#ifdef MOZ_SMIL
,mStartAnimationOnBindToTree(!aFromParser)
#endif // MOZ_SMIL
{
}
@ -169,8 +205,26 @@ nsSVGSVGElement::Init()
//----------------------------------------------------------------------
// nsIDOMNode methods
// From NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGSVGElement)
nsresult
nsSVGSVGElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
{
*aResult = nsnull;
NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGSVGElement)
nsSVGSVGElement *it = new nsSVGSVGElement(aNodeInfo, PR_FALSE);
if (!it) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<nsINode> kungFuDeathGrip = it;
nsresult rv = it->Init();
rv |= CopyInnerTo(it);
if (NS_SUCCEEDED(rv)) {
kungFuDeathGrip.swap(*aResult);
}
return rv;
}
//----------------------------------------------------------------------
@ -428,32 +482,65 @@ nsSVGSVGElement::ForceRedraw()
NS_IMETHODIMP
nsSVGSVGElement::PauseAnimations()
{
#ifdef MOZ_SMIL
if (mTimedDocumentRoot) {
mTimedDocumentRoot->Pause(nsSMILTimeContainer::PAUSE_SCRIPT);
}
// else we're not the outermost <svg> or not bound to a tree, so silently fail
return NS_OK;
#else
NS_NOTYETIMPLEMENTED("nsSVGSVGElement::PauseAnimations");
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
/* void unpauseAnimations (); */
NS_IMETHODIMP
nsSVGSVGElement::UnpauseAnimations()
{
#ifdef MOZ_SMIL
if (mTimedDocumentRoot) {
mTimedDocumentRoot->Resume(nsSMILTimeContainer::PAUSE_SCRIPT);
}
// else we're not the outermost <svg> or not bound to a tree, so silently fail
return NS_OK;
#else
NS_NOTYETIMPLEMENTED("nsSVGSVGElement::UnpauseAnimations");
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
/* boolean animationsPaused (); */
NS_IMETHODIMP
nsSVGSVGElement::AnimationsPaused(PRBool *_retval)
{
#ifdef MOZ_SMIL
nsSMILTimeContainer* root = GetTimedDocumentRoot();
*_retval = root && root->IsPausedByType(nsSMILTimeContainer::PAUSE_SCRIPT);
return NS_OK;
#else
NS_NOTYETIMPLEMENTED("nsSVGSVGElement::AnimationsPaused");
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
/* float getCurrentTime (); */
NS_IMETHODIMP
nsSVGSVGElement::GetCurrentTime(float *_retval)
{
#ifdef MOZ_SMIL
nsSMILTimeContainer* root = GetTimedDocumentRoot();
if (root) {
double fCurrentTimeMs = double(root->GetCurrentTime());
*_retval = (float)(fCurrentTimeMs / PR_MSEC_PER_SEC);
} else {
*_retval = 0.f;
}
return NS_OK;
#else
NS_NOTYETIMPLEMENTED("nsSVGSVGElement::GetCurrentTime");
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
/* void setCurrentTime (in float seconds); */
@ -461,8 +548,21 @@ NS_IMETHODIMP
nsSVGSVGElement::SetCurrentTime(float seconds)
{
NS_ENSURE_FINITE(seconds, NS_ERROR_ILLEGAL_VALUE);
#ifdef MOZ_SMIL
if (mTimedDocumentRoot) {
double fMilliseconds = double(seconds) * PR_MSEC_PER_SEC;
// Round to nearest whole number before converting, to avoid precision
// errors
nsSMILTime lMilliseconds = PRInt64(NS_round(fMilliseconds));
mTimedDocumentRoot->SetCurrentTime(lMilliseconds);
RequestSample();
} // else we're not the outermost <svg> or not bound to a tree, so silently
// fail
return NS_OK;
#else
NS_NOTYETIMPLEMENTED("nsSVGSVGElement::SetCurrentTime");
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
/* nsIDOMNodeList getIntersectionList (in nsIDOMSVGRect rect, in nsIDOMSVGElement referenceElement); */
@ -1052,6 +1152,43 @@ nsSVGSVGElement::GetPreviousScale()
return mPreviousScale;
}
#ifdef MOZ_SMIL
nsSMILTimeContainer*
nsSVGSVGElement::GetTimedDocumentRoot()
{
nsSMILTimeContainer *result = nsnull;
if (mTimedDocumentRoot) {
result = mTimedDocumentRoot;
} 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) {
nsSVGSVGElement *outerSVG =
static_cast<nsSVGSVGElement*>(outerSVGDOM.get());
result = outerSVG->GetTimedDocumentRoot();
}
}
return result;
}
void
nsSVGSVGElement::RequestSample()
{
nsIDocument* doc = GetCurrentDoc();
if (doc) {
nsSMILAnimationController* smilController = doc->GetAnimationController();
if (smilController) {
smilController->FireForceSampleEvent();
}
}
}
#endif // MOZ_SMIL
//----------------------------------------------------------------------
// nsIContent methods
@ -1106,6 +1243,22 @@ nsSVGSVGElement::UnsetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
return NS_OK;
}
//----------------------------------------------------------------------
// nsIContent methods:
#ifdef MOZ_SMIL
nsresult
nsSVGSVGElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
{
if (aVisitor.mEvent->message == NS_SVG_LOAD) {
if (mTimedDocumentRoot) {
mTimedDocumentRoot->Begin();
}
}
return nsSVGSVGElementBase::PreHandleEvent(aVisitor);
}
#endif // MOZ_SMIL
//----------------------------------------------------------------------
// nsISVGValueObserver methods:
@ -1244,6 +1397,57 @@ nsSVGSVGElement::GetViewboxToViewportTransform(nsIDOMSVGMatrix **_retval)
return NS_OK;
}
#ifdef MOZ_SMIL
nsresult
nsSVGSVGElement::BindToTree(nsIDocument* aDocument,
nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
PRBool outermost = WillBeOutermostSVG(aParent, aBindingParent);
if (!mTimedDocumentRoot && outermost) {
// We will now be the outermost SVG element
mTimedDocumentRoot = new nsSMILTimeContainer();
NS_ENSURE_TRUE(mTimedDocumentRoot, NS_ERROR_OUT_OF_MEMORY);
} else if (!outermost) {
mTimedDocumentRoot = nsnull;
mStartAnimationOnBindToTree = PR_TRUE;
}
nsresult rv = nsSVGSVGElementBase::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv,rv);
if (mTimedDocumentRoot) {
if (aDocument) {
nsSMILAnimationController* smilController =
aDocument->GetAnimationController();
if (smilController) {
rv = mTimedDocumentRoot->SetParent(smilController);
}
}
if (mStartAnimationOnBindToTree) {
mTimedDocumentRoot->Begin();
}
}
return rv;
}
void
nsSVGSVGElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
if (mTimedDocumentRoot) {
mTimedDocumentRoot->SetParent(nsnull);
}
nsSVGSVGElementBase::UnbindFromTree(aDeep, aNullParent);
}
#endif // MOZ_SMIL
//----------------------------------------------------------------------
// implementation helpers
@ -1284,6 +1488,29 @@ void nsSVGSVGElement::GetOffsetToAncestor(nsIContent* ancestor,
}
}
#ifdef MOZ_SMIL
PRBool
nsSVGSVGElement::WillBeOutermostSVG(nsIContent* aParent,
nsIContent* aBindingParent) const
{
nsIContent* parent = aBindingParent ? aBindingParent : aParent;
while (parent && parent->GetNameSpaceID() == kNameSpaceID_SVG) {
nsIAtom* tag = parent->Tag();
if (tag == nsGkAtoms::foreignObject) {
// SVG in a foreignObject must have its own <svg> (nsSVGOuterSVGFrame).
return PR_FALSE;
}
if (tag == nsGkAtoms::svg) {
return PR_FALSE;
}
parent = parent->GetParent();
}
return PR_TRUE;
}
#endif // MOZ_SMIL
void
nsSVGSVGElement::InvalidateTransformNotifyFrame()
{

@ -50,6 +50,10 @@
#include "nsSVGEnum.h"
#include "nsSVGPreserveAspectRatio.h"
#ifdef MOZ_SMIL
class nsSMILTimeContainer;
#endif // MOZ_SMIL
#define QI_AND_CAST_TO_NSSVGSVGELEMENT(base) \
(nsCOMPtr<nsIDOMSVGSVGElement>(do_QueryInterface(base)) ? \
static_cast<nsSVGSVGElement*>(base.get()) : nsnull)
@ -80,8 +84,9 @@ class nsSVGSVGElement : public nsSVGSVGElementBase,
protected:
friend nsresult NS_NewSVGSVGElement(nsIContent **aResult,
nsINodeInfo *aNodeInfo);
nsSVGSVGElement(nsINodeInfo* aNodeInfo);
nsINodeInfo *aNodeInfo,
PRBool aFromParser);
nsSVGSVGElement(nsINodeInfo* aNodeInfo, PRBool aFromParser);
virtual ~nsSVGSVGElement();
nsresult Init();
@ -130,8 +135,16 @@ public:
NS_IMETHOD_(float) GetPreviousTranslate_y();
NS_IMETHOD_(float) GetPreviousScale();
#ifdef MOZ_SMIL
nsSMILTimeContainer* GetTimedDocumentRoot();
void RequestSample();
#endif // MOZ_SMIL
// nsIContent interface
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
#ifdef MOZ_SMIL
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
#endif // MOZ_SMIL
virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString* aValue, PRBool aNotify);
@ -172,8 +185,16 @@ 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, PRBool aNullParent);
#endif // MOZ_SMIL
// implementation helpers:
void GetOffsetToAncestor(nsIContent* ancestor, float &x, float &y);
PRBool IsRoot() {
NS_ASSERTION((IsInDoc() && !GetParent()) ==
(GetOwnerDoc() && (GetOwnerDoc()->GetRootContent() == this)),
@ -181,6 +202,20 @@ protected:
return IsInDoc() && !GetParent();
}
#ifdef MOZ_SMIL
/*
* While binding to the tree we need to determine if we will be the outermost
* <svg> element _before_ the children are bound (as they want to know what
* timed document root to register with) and therefore _before_ our parent is
* set (both actions are performed by nsGenericElement::BindToTree) so we
* can't use GetOwnerSVGElement() as it relies on GetParent(). This code is
* basically a simplified version of GetOwnerSVGElement that uses the parent
* parameters passed in instead.
*/
PRBool WillBeOutermostSVG(nsIContent* aParent,
nsIContent* aBindingParent) const;
#endif // MOZ_SMIL
// invalidate viewbox -> viewport xform & inform frames
void InvalidateTransformNotifyFrame();
@ -216,6 +251,12 @@ protected:
float mCoordCtxMmPerPx;
#ifdef MOZ_SMIL
// The time container for animations within this SVG document fragment. Set
// for all outermost <svg> elements (not nested <svg> elements).
nsAutoPtr<nsSMILTimeContainer> mTimedDocumentRoot;
#endif // MOZ_SMIL
// zoom and pan
// IMPORTANT: only RecordCurrentScaleTranslate should change the "mPreviousX"
// members below - see the comment in RecordCurrentScaleTranslate
@ -226,6 +267,14 @@ protected:
float mPreviousScale;
PRInt32 mRedrawSuspendCount;
PRPackedBool mDispatchEvent;
#ifdef MOZ_SMIL
// For outermost <svg> elements created from parsing, animation is started by
// the onload event in accordance with the SVG spec, but for <svg> elements
// created by script or promoted from inner <svg> to outermost <svg> we need
// to manually kick off animation when they are bound to the tree.
PRPackedBool mStartAnimationOnBindToTree;
#endif // MOZ_SMIL
};
#endif

@ -0,0 +1,107 @@
/* -*- 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.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Brian Birtles <birtles@gmail.com>
* Chris Double <chris.double@double.co.nz>
*
* 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 "nsSVGAnimationElement.h"
#include "nsIDOMSVGSetElement.h"
#include "nsSMILSetAnimationFunction.h"
typedef nsSVGAnimationElement nsSVGSetElementBase;
class nsSVGSetElement : public nsSVGSetElementBase,
public nsIDOMSVGSetElement
{
protected:
friend nsresult NS_NewSVGSetElement(nsIContent **aResult,
nsINodeInfo *aNodeInfo);
nsSVGSetElement(nsINodeInfo* aNodeInfo);
nsSMILSetAnimationFunction mAnimationFunction;
public:
// interfaces:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMSVGSETELEMENT
NS_FORWARD_NSIDOMNODE(nsSVGSetElementBase::)
NS_FORWARD_NSIDOMELEMENT(nsSVGSetElementBase::)
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGSetElementBase::)
NS_FORWARD_NSIDOMSVGANIMATIONELEMENT(nsSVGSetElementBase::)
// nsIDOMNode
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
// nsISMILAnimationElement
virtual nsSMILAnimationFunction& AnimationFunction();
};
NS_IMPL_NS_NEW_SVG_ELEMENT(Set)
//----------------------------------------------------------------------
// nsISupports methods
NS_IMPL_ADDREF_INHERITED(nsSVGSetElement,nsSVGSetElementBase)
NS_IMPL_RELEASE_INHERITED(nsSVGSetElement,nsSVGSetElementBase)
NS_INTERFACE_TABLE_HEAD(nsSVGSetElement)
NS_NODE_INTERFACE_TABLE5(nsSVGSetElement, nsIDOMNode, nsIDOMElement,
nsIDOMSVGElement, nsIDOMSVGAnimationElement,
nsIDOMSVGSetElement)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGSetElement)
NS_INTERFACE_MAP_END_INHERITING(nsSVGSetElementBase)
//----------------------------------------------------------------------
// Implementation
nsSVGSetElement::nsSVGSetElement(nsINodeInfo *aNodeInfo)
: nsSVGSetElementBase(aNodeInfo)
{
}
//----------------------------------------------------------------------
// nsIDOMNode methods
NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGSetElement)
//----------------------------------------------------------------------
// nsISMILAnimationElement methods
nsSMILAnimationFunction&
nsSVGSetElement::AnimationFunction()
{
return mAnimationFunction;
}

@ -326,7 +326,7 @@ nsSVGUseElement::CreateAnonymousContent()
return nsnull;
nsCOMPtr<nsIContent> svgNode;
NS_NewSVGSVGElement(getter_AddRefs(svgNode), nodeInfo);
NS_NewSVGSVGElement(getter_AddRefs(svgNode), nodeInfo, PR_FALSE);
if (!svgNode)
return nsnull;

@ -55,7 +55,8 @@ class nsINodeInfo;
{ 0x80, 0x3f, 0xeb, 0x90, 0xfe, 0xe0, 0x7a, 0xe9 } }
nsresult
NS_NewSVGSVGElement(nsIContent **aResult, nsINodeInfo *aNodeInfo);
NS_NewSVGSVGElement(nsIContent **aResult, nsINodeInfo *aNodeInfo,
PRBool aFromParser);
typedef nsSVGGraphicElement nsSVGUseElementBase;

@ -1179,7 +1179,11 @@ nsXMLContentSink::HandleEndElement(const PRUnichar *aName,
#ifdef MOZ_SVG
if (mDocument &&
content->GetNameSpaceID() == kNameSpaceID_SVG &&
content->HasAttr(kNameSpaceID_None, nsGkAtoms::onload)) {
(
#ifdef MOZ_SMIL
content->Tag() == nsGkAtoms::svg ||
#endif
content->HasAttr(kNameSpaceID_None, nsGkAtoms::onload))) {
FlushTags();
nsEvent event(PR_TRUE, NS_SVG_LOAD);

@ -67,5 +67,9 @@ ifdef MOZ_SVG
DIRS += svg
endif
ifdef MOZ_SMIL
DIRS += smil
endif
include $(topsrcdir)/config/rules.mk

@ -0,0 +1,53 @@
#!nmake
#
# ***** 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 SMIL module.
#
# The Initial Developer of the Original Code is Brian Birtles.
# Portions created by the Initial Developer are Copyright (C) 2005
# 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 *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = dom
XPIDL_MODULE = dom_smil
XPIDLSRCS = \
nsIDOMElementTimeControl.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

@ -0,0 +1,59 @@
/* -*- 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 SMIL module.
*
* The Initial Developer of the Original Code is Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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"
/*
* The definitions of this interface in SMIL Animation and SVG 1.1 differ in the
* return type and semantics.
*
* A proposed SVG errata item at:
*
* http://www.w3.org/2003/01/REC-SVG11-20030114-errata#elementtimecontrol-interface
*
* addresses this suggesting the interface definition from SMIL 3 be adopted
* which is what we use here.
*/
[scriptable, uuid(276a6678-7844-4d5e-8dfe-938c46089b84)]
interface nsIDOMElementTimeControl : nsISupports
{
void beginElement();
void beginElementAt(in float offset);
void endElement();
void endElementAt(in float offset);
};

@ -21,6 +21,7 @@
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Chris Double <chris.double@double.co.nz>
#
# 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"),
@ -127,4 +128,12 @@ XPIDLSRCS = \
nsIDOMSVGZoomEvent.idl \
$(NULL)
ifdef MOZ_SMIL
XPIDLSRCS += \
nsIDOMSVGAnimateElement.idl \
nsIDOMSVGAnimationElement.idl \
nsIDOMSVGSetElement.idl \
$(NULL)
endif
include $(topsrcdir)/config/rules.mk

@ -0,0 +1,41 @@
/* -*- 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 Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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 {};

@ -0,0 +1,62 @@
/* -*- 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 Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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::nsIDOMElementTimeControl,
events::nsIDOMEventTarget
*/
{
readonly attribute nsIDOMSVGElement targetElement;
float getStartTime();
float getCurrentTime();
float getSimpleDuration();
// raises (nsIDOMDOMException)
};

@ -0,0 +1,41 @@
/* -*- 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 Brian Birtles.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Chris Double <chris.double@double.co.nz>
*
* 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(b6c27cdc-4d8b-4343-8ccb-3b68adb1052a)]
interface nsIDOMSVGSetElement : nsIDOMSVGAnimationElement {};

@ -243,6 +243,10 @@ enum nsDOMClassInfoID {
// SVG element classes
eDOMClassInfo_SVGAElement_id,
#ifdef MOZ_SMIL
eDOMClassInfo_SVGAnimateElement_id,
eDOMClassInfo_SVGSetElement_id,
#endif // MOZ_SMIL
eDOMClassInfo_SVGCircleElement_id,
eDOMClassInfo_SVGClipPathElement_id,
eDOMClassInfo_SVGDefsElement_id,

@ -376,6 +376,12 @@
#include "nsIDOMSVGAnimPresAspRatio.h"
#include "nsIDOMSVGAnimatedRect.h"
#include "nsIDOMSVGAnimatedString.h"
#ifdef MOZ_SMIL
#include "nsIDOMSVGAnimateElement.h"
#include "nsIDOMSVGSetElement.h"
#include "nsIDOMSVGAnimationElement.h"
#include "nsIDOMElementTimeControl.h"
#endif // MOZ_SMIL
#include "nsIDOMSVGAnimTransformList.h"
#include "nsIDOMSVGCircleElement.h"
#include "nsIDOMSVGClipPathElement.h"
@ -939,6 +945,12 @@ static nsDOMClassInfoData sClassInfoData[] = {
// SVG element classes
NS_DEFINE_CLASSINFO_DATA(SVGAElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
#ifdef MOZ_SMIL
NS_DEFINE_CLASSINFO_DATA(SVGAnimateElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGSetElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
#endif // MOZ_SMIL
NS_DEFINE_CLASSINFO_DATA(SVGCircleElement, nsElementSH,
ELEMENT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(SVGClipPathElement, nsElementSH,
@ -2751,6 +2763,23 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
#ifdef MOZ_SMIL
DOM_CLASSINFO_MAP_BEGIN(SVGAnimateElement, nsIDOMSVGAnimateElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimateElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementTimeControl)
DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(SVGSetElement,
nsIDOMSVGSetElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGSetElement)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementTimeControl)
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

@ -90,6 +90,10 @@
#include "nsFontFaceLoader.h"
#include "nsIEventListenerManager.h"
#ifdef MOZ_SMIL
#include "nsSMILAnimationController.h"
#endif // MOZ_SMIL
#ifdef IBMBIDI
#include "nsBidiPresUtils.h"
#endif // IBMBIDI
@ -1079,6 +1083,30 @@ void nsPresContext::SetImgAnimations(nsIContent *aParent, PRUint16 aMode)
}
}
#ifdef MOZ_SMIL
void
nsPresContext::SetSMILAnimations(nsIDocument *aDoc, PRUint16 aNewMode,
PRUint16 aOldMode)
{
nsSMILAnimationController *controller = aDoc->GetAnimationController();
if (controller) {
switch (aNewMode)
{
case imgIContainer::kNormalAnimMode:
case imgIContainer::kLoopOnceAnimMode:
if (aOldMode == imgIContainer::kDontAnimMode)
controller->Resume(nsSMILTimeContainer::PAUSE_USERPREF);
break;
case imgIContainer::kDontAnimMode:
if (aOldMode != imgIContainer::kDontAnimMode)
controller->Pause(nsSMILTimeContainer::PAUSE_USERPREF);
break;
}
}
}
#endif // MOZ_SMIL
void
nsPresContext::SetImageAnimationModeInternal(PRUint16 aMode)
{
@ -1103,6 +1131,10 @@ nsPresContext::SetImageAnimationModeInternal(PRUint16 aMode)
if (rootContent) {
SetImgAnimations(rootContent, aMode);
}
#ifdef MOZ_SMIL
SetSMILAnimations(doc, aMode, mImageAnimationMode);
#endif // MOZ_SMIL
}
}

@ -788,6 +788,10 @@ protected:
NS_HIDDEN_(void) SysColorChangedInternal();
NS_HIDDEN_(void) SetImgAnimations(nsIContent *aParent, PRUint16 aMode);
#ifdef MOZ_SMIL
NS_HIDDEN_(void) SetSMILAnimations(nsIDocument *aDoc, PRUint16 aNewMode,
PRUint16 aOldMode);
#endif // MOZ_SMIL
NS_HIDDEN_(void) GetDocumentColorPreferences();
NS_HIDDEN_(void) PreferenceChanged(const char* aPrefName);

@ -214,6 +214,12 @@ SHARED_LIBRARY_LIBS += \
$(NULL)
endif
ifdef MOZ_SMIL
SHARED_LIBRARY_LIBS += \
$(DEPTH)/content/smil/$(LIB_PREFIX)gkconsmil_s.$(LIB_SUFFIX) \
$(NULL)
endif
ifdef MOZ_PLAINTEXT_EDITOR_ONLY
DEFINES += -DMOZILLA_PLAINTEXT_EDITOR_ONLY
else

@ -7,6 +7,10 @@ include sizing/reftest.list
include filters/reftest.list
# smil / animation tests
# disabled because SMIL is not built by default
# include smil/reftest.list
# Mozilla only tests (i.e. those containing XUL/XBL/etc.)
include moz-only/reftest.list

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="setTimeAndSnapshot(2.5, false)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<rect x="15" y="15" width="200" height="20" fill="blue">
<animate attributeName="height" calcMode="discrete"
additive="replace" accumulate="sum"
from="20" to="100" repeatCount="2"
begin="0s" dur="1s" fill="freeze"/>
</rect>
</svg>

After

(image error) Size: 501 B

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="setTimeAndSnapshot(2.5, false)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<rect x="15" y="15" width="200" height="20" fill="blue">
<animate attributeName="height" calcMode="discrete"
additive="sum" accumulate="none"
from="20" to="180"
begin="0s" dur="2s" fill="freeze"/>
</rect>
</svg>

After

(image error) Size: 481 B

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="setTimeAndSnapshot(2.5, false)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<rect x="15" y="15" width="200" height="20" fill="blue">
<animate attributeName="height" calcMode="discrete"
additive="sum" accumulate="sum"
from="20" to="90" repeatCount="2"
begin="0s" dur="1s" fill="freeze"/>
</rect>
</svg>

After

(image error) Size: 495 B

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="setTimeAndSnapshot(2.5, false)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<rect x="15" y="15" width="200" height="50" fill="blue">
<animate attributeName="height" calcMode="discrete"
values="100; 200; 50" begin="0s" dur="5s" fill="freeze"/>
</rect>
</svg>

After

(image error) Size: 425 B

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="setTimeAndSnapshot(2.5, false)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<rect x="15" y="15" width="200" height="200" fill="rgb(255,0,0)">
<animateColor attributeName="fill" from="rgb(255,0,0)" to="rgb(0,0,255)"
begin="0s" dur="2s" fill="freeze"/>
</rect>
</svg>

After

(image error) Size: 437 B

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="setTimeAndSnapshot(2.5, false)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<rect x="15" y="15" width="200" height="200" fill="blue" fill-opacity="0">
<animate attributeName="fill-opacity"
from="0" to="1" begin="0s" dur="2s" fill="freeze"/>
</rect>
</svg>

After

(image error) Size: 422 B

@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="setTimeAndSnapshot(2, false)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<rect x="15" y="15" width="200" height="50" fill="blue">
<animate attributeName="height"
from="50" to="200" begin="0s" dur="2s" fill="freeze"/>
</rect>
</svg>

After

(image error) Size: 400 B

@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="setTimeAndSnapshot(2.5, false)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<rect x="15" y="15" width="200" height="50" fill="blue">
<animate attributeName="height"
from="50" to="200" begin="0s" dur="2s" fill="freeze"/>
</rect>
</svg>

After

(image error) Size: 402 B

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg">
<rect x="15" y="15" width="200" height="115" fill="blue"/>
</svg>

After

(image error) Size: 109 B

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="setTimeAndSnapshot(0.3, true)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<rect x="15" y="15" width="200" height="50" fill="blue">
<animate attributeName="height"
from="100" to="200" begin="0s" dur="2s" fill="freeze"/>
</rect>
</svg>

After

(image error) Size: 401 B

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg">
<rect x="15" y="15" width="200" height="125" fill="blue"/>
</svg>

After

(image error) Size: 109 B

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="setTimeAndSnapshot(0.5, true)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<rect x="15" y="15" width="200" height="50" fill="blue">
<animate attributeName="height"
from="100" to="200" begin="0s" dur="2s" fill="freeze"/>
</rect>
</svg>

After

(image error) Size: 401 B

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg">
<rect x="15" y="15" width="200" height="160" fill="blue"/>
</svg>

After

(image error) Size: 109 B

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="setTimeAndSnapshot(1.2, true)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<rect x="15" y="15" width="200" height="50" fill="blue">
<animate attributeName="height"
from="100" to="200" begin="0s" dur="2s" fill="freeze"/>
</rect>
</svg>

After

(image error) Size: 401 B

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg">
<rect x="15" y="15" width="200" height="170" fill="blue"/>
</svg>

After

(image error) Size: 109 B

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="setTimeAndSnapshot(1.4, true)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<rect x="15" y="15" width="200" height="50" fill="blue">
<animate attributeName="height"
from="100" to="200" begin="0s" dur="2s" fill="freeze"/>
</rect>
</svg>

After

(image error) Size: 401 B

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg">
<rect x="15" y="15" width="200" height="190" fill="blue"/>
</svg>

After

(image error) Size: 109 B

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
class="reftest-wait"
onload="setTimeAndSnapshot(1.8, true)">
<script xlink:href="smil-util.js" type="text/javascript"/>
<rect x="15" y="15" width="200" height="50" fill="blue">
<animate attributeName="height"
from="100" to="200" begin="0s" dur="2s" fill="freeze"/>
</rect>
</svg>

After

(image error) Size: 401 B

Some files were not shown because too many files have changed in this diff Show More