From b6825d69488fe56050b3826c45eacf5552a2fcdf Mon Sep 17 00:00:00 2001 From: Brian Birtles Date: Mon, 19 Jan 2009 22:14:16 +1300 Subject: [PATCH] Bug 468996. Implement SMIL animateTransform element. r+sr=roc --- content/smil/nsISMILType.h | 25 + content/smil/nsSMILAnimationFunction.cpp | 3 +- content/smil/nsSMILValue.cpp | 20 +- content/smil/nsSMILValue.h | 1 + content/svg/content/src/Makefile.in | 3 + .../src/nsSVGAnimateTransformElement.cpp | 146 ++++++ .../src/nsSVGAnimatedTransformList.cpp | 55 +-- .../content/src/nsSVGAnimatedTransformList.h | 46 ++ content/svg/content/src/nsSVGElement.cpp | 18 + .../svg/content/src/nsSVGElementFactory.cpp | 4 + content/svg/content/src/nsSVGSMILTransform.h | 110 +++++ content/svg/content/src/nsSVGTransform.cpp | 41 -- content/svg/content/src/nsSVGTransform.h | 48 ++ .../content/src/nsSVGTransformSMILAttr.cpp | 439 ++++++++++++++++++ .../svg/content/src/nsSVGTransformSMILAttr.h | 95 ++++ .../content/src/nsSVGTransformSMILType.cpp | 356 ++++++++++++++ .../svg/content/src/nsSVGTransformSMILType.h | 141 ++++++ dom/public/idl/svg/Makefile.in | 1 + .../svg/nsIDOMSVGAnimateTransformElement.idl | 41 ++ dom/public/nsDOMClassInfoID.h | 1 + dom/src/base/nsDOMClassInfo.cpp | 11 + layout/reftests/svg/smil/reftest.list | 3 + .../svg/smil/transform/additive-1-ref.svg | 42 ++ .../svg/smil/transform/additive-1.svg | 209 +++++++++ .../svg/smil/transform/paced-1-ref.svg | 31 ++ .../reftests/svg/smil/transform/paced-1.svg | 64 +++ .../reftests/svg/smil/transform/reftest.list | 12 + .../svg/smil/transform/rotate-angle-1.svg | 60 +++ .../svg/smil/transform/rotate-angle-2.svg | 60 +++ .../svg/smil/transform/rotate-angle-3.svg | 60 +++ .../svg/smil/transform/rotate-angle-4.svg | 79 ++++ .../svg/smil/transform/rotate-angle-5.svg | 86 ++++ .../svg/smil/transform/rotate-angle-ref.svg | 38 ++ .../svg/smil/transform/scale-1-ref.svg | 38 ++ .../reftests/svg/smil/transform/scale-1.svg | 108 +++++ .../svg/smil/transform/skew-1-ref.svg | 43 ++ layout/reftests/svg/smil/transform/skew-1.svg | 86 ++++ 37 files changed, 2528 insertions(+), 96 deletions(-) create mode 100644 content/svg/content/src/nsSVGAnimateTransformElement.cpp create mode 100644 content/svg/content/src/nsSVGSMILTransform.h create mode 100644 content/svg/content/src/nsSVGTransformSMILAttr.cpp create mode 100644 content/svg/content/src/nsSVGTransformSMILAttr.h create mode 100644 content/svg/content/src/nsSVGTransformSMILType.cpp create mode 100644 content/svg/content/src/nsSVGTransformSMILType.h create mode 100644 dom/public/idl/svg/nsIDOMSVGAnimateTransformElement.idl create mode 100644 layout/reftests/svg/smil/transform/additive-1-ref.svg create mode 100644 layout/reftests/svg/smil/transform/additive-1.svg create mode 100644 layout/reftests/svg/smil/transform/paced-1-ref.svg create mode 100644 layout/reftests/svg/smil/transform/paced-1.svg create mode 100644 layout/reftests/svg/smil/transform/reftest.list create mode 100644 layout/reftests/svg/smil/transform/rotate-angle-1.svg create mode 100644 layout/reftests/svg/smil/transform/rotate-angle-2.svg create mode 100644 layout/reftests/svg/smil/transform/rotate-angle-3.svg create mode 100644 layout/reftests/svg/smil/transform/rotate-angle-4.svg create mode 100644 layout/reftests/svg/smil/transform/rotate-angle-5.svg create mode 100644 layout/reftests/svg/smil/transform/rotate-angle-ref.svg create mode 100644 layout/reftests/svg/smil/transform/scale-1-ref.svg create mode 100644 layout/reftests/svg/smil/transform/scale-1.svg create mode 100644 layout/reftests/svg/smil/transform/skew-1-ref.svg create mode 100644 layout/reftests/svg/smil/transform/skew-1.svg diff --git a/content/smil/nsISMILType.h b/content/smil/nsISMILType.h index 6d0afde3abf..db985f60884 100644 --- a/content/smil/nsISMILType.h +++ b/content/smil/nsISMILType.h @@ -67,6 +67,7 @@ class nsSMILValue; // | | | | | // | -- Assign? | X | X | X | // | -- Add? | - | X? | X | +// | -- SandwichAdd? | - | -? | X | // | -- ComputeDistance? | - | - | X? | // | -- Interpolate? | - | X | X | // +---------------------+---------------+-------------+------------------+ @@ -144,6 +145,30 @@ public: const nsSMILValue& aValueToAdd, PRUint32 aCount) const = 0; + /** + * Adds aValueToAdd to the underlying value in the animation sandwich, aDest. + * + * For most types this operation is identical to a regular Add() but for some + * types (notably ) the operation differs. For + * Add() corresponds to simply adding together the + * transform parameters and is used when calculating cumulative values or + * by-animation values. On the other hand SandwichAdd() is used when adding to + * the underlying value and requires matrix post-multiplication. (This + * distinction is most clearly indicated by the SVGT1.2 test suite. It is not + * obvious within the SMIL specifications.) + * + * @param aDest The value to add to. + * @param aValueToAdd The value to add. + * @return NS_OK on success, an error code on failure. + * + * @pre aValueToAdd.mType == aDest.mType == this + */ + virtual nsresult SandwichAdd(nsSMILValue& aDest, + const nsSMILValue& aValueToAdd) const + { + return Add(aDest, aValueToAdd, 1); + } + /** * Calculates the 'distance' between two values. This is the distance used in * paced interpolation. diff --git a/content/smil/nsSMILAnimationFunction.cpp b/content/smil/nsSMILAnimationFunction.cpp index 44e26583e10..91d69fc4eee 100644 --- a/content/smil/nsSMILAnimationFunction.cpp +++ b/content/smil/nsSMILAnimationFunction.cpp @@ -292,8 +292,9 @@ nsSMILAnimationFunction::ComposeResult(const nsISMILAttr& aSMILAttr, } // If additive animation isn't required or isn't supported, set the value. - if (!IsAdditive() || NS_FAILED(aResult.Add(result))) + if (!IsAdditive() || NS_FAILED(aResult.SandwichAdd(result))) { aResult = result; + } } PRInt8 diff --git a/content/smil/nsSMILValue.cpp b/content/smil/nsSMILValue.cpp index d249ad5ebd2..b54a08144f5 100644 --- a/content/smil/nsSMILValue.cpp +++ b/content/smil/nsSMILValue.cpp @@ -88,18 +88,32 @@ nsSMILValue::Add(const nsSMILValue& aValueToAdd, PRUint32 aCount) if (aValueToAdd.IsNull()) return NS_OK; if (aValueToAdd.mType != mType) { - NS_WARNING("Trying to add incompatible types."); + NS_ERROR("Trying to add incompatible types."); return NS_ERROR_FAILURE; } return mType->Add(*this, aValueToAdd, aCount); } +nsresult +nsSMILValue::SandwichAdd(const nsSMILValue& aValueToAdd) +{ + if (aValueToAdd.IsNull()) + return NS_OK; + + if (aValueToAdd.mType != mType) { + NS_ERROR("Trying to add incompatible types."); + return NS_ERROR_FAILURE; + } + + return mType->SandwichAdd(*this, aValueToAdd); +} + nsresult nsSMILValue::ComputeDistance(const nsSMILValue& aTo, double& aDistance) const { if (aTo.mType != mType) { - NS_WARNING("Trying to calculate distance between incompatible types."); + NS_ERROR("Trying to calculate distance between incompatible types."); return NS_ERROR_FAILURE; } @@ -112,7 +126,7 @@ nsSMILValue::Interpolate(const nsSMILValue& aEndVal, nsSMILValue& aResult) const { if (aEndVal.mType != mType) { - NS_WARNING("Trying to interpolate between incompatible types."); + NS_ERROR("Trying to interpolate between incompatible types."); return NS_ERROR_FAILURE; } diff --git a/content/smil/nsSMILValue.h b/content/smil/nsSMILValue.h index 07ab10621d8..19a4f32aaac 100644 --- a/content/smil/nsSMILValue.h +++ b/content/smil/nsSMILValue.h @@ -62,6 +62,7 @@ public: } nsresult Add(const nsSMILValue& aValueToAdd, PRUint32 aCount = 1); + nsresult SandwichAdd(const nsSMILValue& aValueToAdd); nsresult ComputeDistance(const nsSMILValue& aTo, double& aDistance) const; nsresult Interpolate(const nsSMILValue& aEndVal, double aUnitDistance, diff --git a/content/svg/content/src/Makefile.in b/content/svg/content/src/Makefile.in index d9ca0ced107..9a60ca250bf 100644 --- a/content/svg/content/src/Makefile.in +++ b/content/svg/content/src/Makefile.in @@ -140,8 +140,11 @@ CPPSRCS = \ ifdef MOZ_SMIL CPPSRCS += nsSVGAnimateElement.cpp \ + nsSVGAnimateTransformElement.cpp \ nsSVGAnimationElement.cpp \ nsSVGSetElement.cpp \ + nsSVGTransformSMILType.cpp \ + nsSVGTransformSMILAttr.cpp \ $(NULL) endif diff --git a/content/svg/content/src/nsSVGAnimateTransformElement.cpp b/content/svg/content/src/nsSVGAnimateTransformElement.cpp new file mode 100644 index 00000000000..b00a7348e67 --- /dev/null +++ b/content/svg/content/src/nsSVGAnimateTransformElement.cpp @@ -0,0 +1,146 @@ +/* -*- 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 + * Chris Double + * Daniel Holbert + * + * 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 "nsIDOMSVGAnimateTransformElement.h" +#include "nsSVGEnum.h" +#include "nsIDOMSVGTransform.h" +#include "nsIDOMSVGTransformable.h" +#include "nsSVGAnimatedTransformList.h" +#include "nsSVGTransformSMILAttr.h" +#include "nsSMILAnimationFunction.h" + +typedef nsSVGAnimationElement nsSVGAnimateTransformElementBase; + +class nsSVGAnimateTransformElement : public nsSVGAnimateTransformElementBase, + public nsIDOMSVGAnimateTransformElement +{ +protected: + friend nsresult NS_NewSVGAnimateTransformElement(nsIContent **aResult, + nsINodeInfo *aNodeInfo); + nsSVGAnimateTransformElement(nsINodeInfo* aNodeInfo); + + nsSMILAnimationFunction mAnimationFunction; + +public: + // interfaces: + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIDOMSVGANIMATETRANSFORMELEMENT + + NS_FORWARD_NSIDOMNODE(nsSVGAnimateTransformElementBase::) + NS_FORWARD_NSIDOMELEMENT(nsSVGAnimateTransformElementBase::) + NS_FORWARD_NSIDOMSVGELEMENT(nsSVGAnimateTransformElementBase::) + NS_FORWARD_NSIDOMSVGANIMATIONELEMENT(nsSVGAnimateTransformElementBase::) + + // nsIDOMNode specializations + virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; + + // nsGenericElement specializations + PRBool ParseAttribute(PRInt32 aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult); + + // nsISMILAnimationElement + virtual nsSMILAnimationFunction& AnimationFunction(); +}; + +NS_IMPL_NS_NEW_SVG_ELEMENT(AnimateTransform) + +//---------------------------------------------------------------------- +// nsISupports methods + +NS_IMPL_ADDREF_INHERITED(nsSVGAnimateTransformElement,nsSVGAnimateTransformElementBase) +NS_IMPL_RELEASE_INHERITED(nsSVGAnimateTransformElement,nsSVGAnimateTransformElementBase) + +NS_INTERFACE_TABLE_HEAD(nsSVGAnimateTransformElement) + NS_NODE_INTERFACE_TABLE5(nsSVGAnimateTransformElement, nsIDOMNode, + nsIDOMElement, nsIDOMSVGElement, + nsIDOMSVGAnimationElement, + nsIDOMSVGAnimateTransformElement) + NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimateElement) +NS_INTERFACE_MAP_END_INHERITING(nsSVGAnimateTransformElementBase) + +//---------------------------------------------------------------------- +// Implementation + +nsSVGAnimateTransformElement::nsSVGAnimateTransformElement(nsINodeInfo *aNodeInfo) + : nsSVGAnimateTransformElementBase(aNodeInfo) +{ +} + +PRBool +nsSVGAnimateTransformElement::ParseAttribute(PRInt32 aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult) +{ + // 'type' is an -specific attribute, and we'll handle it + // specially. + if (aNamespaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::type) { + aResult.ParseAtom(aValue); + nsIAtom* atom = aResult.GetAtomValue(); + if (atom != nsGkAtoms::translate && + atom != nsGkAtoms::scale && + atom != nsGkAtoms::rotate && + atom != nsGkAtoms::skewX && + atom != nsGkAtoms::skewY) { + ReportAttributeParseFailure(GetOwnerDoc(), aAttribute, aValue); + } + return PR_TRUE; + } + + return nsSVGAnimateTransformElementBase::ParseAttribute(aNamespaceID, + aAttribute, aValue, + aResult); +} + +//---------------------------------------------------------------------- +// nsIDOMNode methods + +NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGAnimateTransformElement) + +//---------------------------------------------------------------------- +// nsISMILAnimationElement methods + +nsSMILAnimationFunction& +nsSVGAnimateTransformElement::AnimationFunction() +{ + return mAnimationFunction; +} diff --git a/content/svg/content/src/nsSVGAnimatedTransformList.cpp b/content/svg/content/src/nsSVGAnimatedTransformList.cpp index f16092cffa4..fb5f37479bf 100644 --- a/content/svg/content/src/nsSVGAnimatedTransformList.cpp +++ b/content/svg/content/src/nsSVGAnimatedTransformList.cpp @@ -38,62 +38,15 @@ #include "nsSVGAnimatedTransformList.h" #include "nsSVGTransformList.h" -#include "nsSVGValue.h" -#include "nsWeakReference.h" #include "nsContentUtils.h" -//////////////////////////////////////////////////////////////////////// -// nsSVGAnimatedTransformList - -class nsSVGAnimatedTransformList : public nsIDOMSVGAnimatedTransformList, - public nsSVGValue, - public nsISVGValueObserver -{ -protected: - friend nsresult - NS_NewSVGAnimatedTransformList(nsIDOMSVGAnimatedTransformList** result, - nsIDOMSVGTransformList* baseVal); - - nsSVGAnimatedTransformList(); - ~nsSVGAnimatedTransformList(); - void Init(nsIDOMSVGTransformList* baseVal); - -public: - // nsISupports interface: - NS_DECL_ISUPPORTS - - // nsIDOMSVGAnimatedTransformList interface: - NS_DECL_NSIDOMSVGANIMATEDTRANSFORMLIST - - // remainder of nsISVGValue interface: - NS_IMETHOD SetValueString(const nsAString& aValue); - NS_IMETHOD GetValueString(nsAString& aValue); - - // nsISVGValueObserver - NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable, - modificationType aModType); - NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable, - modificationType aModType); - - // nsISupportsWeakReference - // implementation inherited from nsSupportsWeakReference - -protected: - nsCOMPtr mBaseVal; -}; - - //---------------------------------------------------------------------- // Implementation -nsSVGAnimatedTransformList::nsSVGAnimatedTransformList() -{ -} - nsSVGAnimatedTransformList::~nsSVGAnimatedTransformList() { if (!mBaseVal) return; - nsCOMPtr val = do_QueryInterface(mBaseVal); + nsCOMPtr val = do_QueryInterface(mBaseVal); if (!val) return; val->RemoveObserver(this); } @@ -146,7 +99,7 @@ nsSVGAnimatedTransformList::GetValueString(nsAString& aValue) /* readonly attribute nsIDOMSVGTransformList baseVal; */ NS_IMETHODIMP -nsSVGAnimatedTransformList::GetBaseVal(nsIDOMSVGTransformList * *aBaseVal) +nsSVGAnimatedTransformList::GetBaseVal(nsIDOMSVGTransformList** aBaseVal) { *aBaseVal = mBaseVal; NS_ADDREF(*aBaseVal); @@ -155,9 +108,9 @@ nsSVGAnimatedTransformList::GetBaseVal(nsIDOMSVGTransformList * *aBaseVal) /* readonly attribute nsIDOMSVGTransformList animVal; */ NS_IMETHODIMP -nsSVGAnimatedTransformList::GetAnimVal(nsIDOMSVGTransformList * *aAnimVal) +nsSVGAnimatedTransformList::GetAnimVal(nsIDOMSVGTransformList** aAnimVal) { - *aAnimVal = mBaseVal; + *aAnimVal = mAnimVal ? mAnimVal : mBaseVal; NS_ADDREF(*aAnimVal); return NS_OK; } diff --git a/content/svg/content/src/nsSVGAnimatedTransformList.h b/content/svg/content/src/nsSVGAnimatedTransformList.h index d0a4fbddfa0..dac8e6d1c03 100644 --- a/content/svg/content/src/nsSVGAnimatedTransformList.h +++ b/content/svg/content/src/nsSVGAnimatedTransformList.h @@ -41,6 +41,52 @@ #include "nsIDOMSVGAnimTransformList.h" #include "nsIDOMSVGTransformList.h" +#include "nsSVGValue.h" + +//////////////////////////////////////////////////////////////////////// +// nsSVGAnimatedTransformList + +class nsSVGTransformSMILAttr; + +class nsSVGAnimatedTransformList : public nsIDOMSVGAnimatedTransformList, + public nsSVGValue, + public nsISVGValueObserver +{ +protected: + friend nsresult + NS_NewSVGAnimatedTransformList(nsIDOMSVGAnimatedTransformList** result, + nsIDOMSVGTransformList* baseVal); + + ~nsSVGAnimatedTransformList(); + void Init(nsIDOMSVGTransformList* baseVal); + +public: + // nsISupports interface: + NS_DECL_ISUPPORTS + + // nsIDOMSVGAnimatedTransformList interface: + NS_DECL_NSIDOMSVGANIMATEDTRANSFORMLIST + + // remainder of nsISVGValue interface: + NS_IMETHOD SetValueString(const nsAString& aValue); + NS_IMETHOD GetValueString(nsAString& aValue); + + // nsISVGValueObserver + NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable, + modificationType aModType); + NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable, + modificationType aModType); + + // nsISupportsWeakReference + // implementation inherited from nsSupportsWeakReference + +protected: + friend class nsSVGTransformSMILAttr; + + nsCOMPtr mBaseVal; + // XXX This should be read-only, i.e. its setters should throw + nsCOMPtr mAnimVal; +}; nsresult NS_NewSVGAnimatedTransformList(nsIDOMSVGAnimatedTransformList** result, diff --git a/content/svg/content/src/nsSVGElement.cpp b/content/svg/content/src/nsSVGElement.cpp index 0b54febc8db..867fb1b5055 100644 --- a/content/svg/content/src/nsSVGElement.cpp +++ b/content/svg/content/src/nsSVGElement.cpp @@ -91,6 +91,8 @@ #include "prdtoa.h" #include #ifdef MOZ_SMIL +#include "nsSVGTransformSMILAttr.h" +#include "nsSVGAnimatedTransformList.h" #include "nsIDOMSVGTransformable.h" #endif // MOZ_SMIL @@ -1650,6 +1652,22 @@ nsSVGElement::RecompileScriptEventListeners() nsISMILAttr* nsSVGElement::GetAnimatedAttr(const nsIAtom* aName) { + // Transforms: + if (aName == nsGkAtoms::transform) { + nsCOMPtr transformable( + do_QueryInterface(static_cast(this))); + if (!transformable) + return nsnull; + nsCOMPtr transformList; + nsresult rv = transformable->GetTransform(getter_AddRefs(transformList)); + NS_ENSURE_SUCCESS(rv, nsnull); + nsSVGAnimatedTransformList* list + = static_cast(transformList.get()); + NS_ENSURE_TRUE(list, nsnull); + + return new nsSVGTransformSMILAttr(list, this); + } + // Lengths: LengthAttributesInfo info = GetLengthInfo(); for (PRUint32 i = 0; i < info.mLengthCount; i++) { diff --git a/content/svg/content/src/nsSVGElementFactory.cpp b/content/svg/content/src/nsSVGElementFactory.cpp index 778c88e9153..d687188dd9e 100644 --- a/content/svg/content/src/nsSVGElementFactory.cpp +++ b/content/svg/content/src/nsSVGElementFactory.cpp @@ -165,6 +165,8 @@ NS_NewSVGFEDisplacementMapElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); nsresult NS_NewSVGAnimateElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); nsresult +NS_NewSVGAnimateTransformElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); +nsresult NS_NewSVGSetElement(nsIContent **aResult, nsINodeInfo *aNodeInfo); #endif // MOZ_SMIL @@ -299,6 +301,8 @@ NS_NewSVGElement(nsIContent** aResult, nsINodeInfo *aNodeInfo, #ifdef MOZ_SMIL if (name == nsGkAtoms::animate) return NS_NewSVGAnimateElement(aResult, aNodeInfo); + if (name == nsGkAtoms::animateTransform) + return NS_NewSVGAnimateTransformElement(aResult, aNodeInfo); if (name == nsGkAtoms::set) return NS_NewSVGSetElement(aResult, aNodeInfo); #endif // MOZ_SMIL diff --git a/content/svg/content/src/nsSVGSMILTransform.h b/content/svg/content/src/nsSVGSMILTransform.h new file mode 100644 index 00000000000..ef3530cf055 --- /dev/null +++ b/content/svg/content/src/nsSVGSMILTransform.h @@ -0,0 +1,110 @@ +/* -*- 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) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Brian Birtles + * + * 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_SVGSMILTRANSFORM_H_ +#define NS_SVGSMILTRANSFORM_H_ + +//////////////////////////////////////////////////////////////////////// +// nsSVGSMILTransform +// +// A pared-down representation of an SVG transform used in SMIL animation. We +// just store the most basic facts about the transform such that we can add the +// transform parameters together and later reconstruct a full SVG transform from +// this information. +// +// The meaning of the mParams array depends on the transform type as follows: +// +// Type | mParams[0], mParams[1], mParams[2], ... +// --------------------+----------------------------------------- +// TRANSFORM_TRANSLATE | tx, ty +// TRANSFORM_SCALE | sx, sy +// TRANSFORM_ROTATE | rotation-angle (in degrees), cx, cy +// TRANSFORM_SKEWX | skew-angle (in degrees) +// TRANSFORM_SKEWY | skew-angle (in degrees) +// TRANSFORM_MATRIX | a, b, c, d, e, f +// +// TRANSFORM_MATRIX is never generated by animation code (it is only produced +// when the user inserts one via the DOM) and often requires special handling +// when we do encounter it. Therefore many users of this class are only +// interested in the first three parameters and so we provide a special +// constructor for setting those parameters only. +class nsSVGSMILTransform +{ +public: + enum TransformType + { + TRANSFORM_TRANSLATE, + TRANSFORM_SCALE, + TRANSFORM_ROTATE, + TRANSFORM_SKEWX, + TRANSFORM_SKEWY, + TRANSFORM_MATRIX + }; + + nsSVGSMILTransform(TransformType aType) + : mTransformType(aType) + { + for (int i = 0; i < 6; ++i) { + mParams[i] = 0; + } + } + + nsSVGSMILTransform(TransformType aType, float (&aParams)[3]) + : mTransformType(aType) + { + for (int i = 0; i < 3; ++i) { + mParams[i] = aParams[i]; + } + for (int i = 3; i < 6; ++i) { + mParams[i] = 0; + } + } + + nsSVGSMILTransform(float (&aParams)[6]) + : mTransformType(TRANSFORM_MATRIX) + { + for (int i = 0; i < 6; ++i) { + mParams[i] = aParams[i]; + } + } + + TransformType mTransformType; + + float mParams[6]; +}; + +#endif // NS_SVGSMILTRANSFORM_H_ diff --git a/content/svg/content/src/nsSVGTransform.cpp b/content/svg/content/src/nsSVGTransform.cpp index f8f45cc4007..b4e217b69ba 100644 --- a/content/svg/content/src/nsSVGTransform.cpp +++ b/content/svg/content/src/nsSVGTransform.cpp @@ -39,54 +39,13 @@ #include "nsSVGTransform.h" #include "prdtoa.h" #include "nsSVGMatrix.h" -#include "nsSVGValue.h" #include "nsISVGValueUtils.h" -#include "nsISVGValueObserver.h" #include "nsWeakReference.h" #include "nsSVGMatrix.h" #include "nsTextFormatter.h" #include "nsContentUtils.h" #include "nsDOMError.h" - -//////////////////////////////////////////////////////////////////////// -// nsSVGTransform - -class nsSVGTransform : public nsIDOMSVGTransform, - public nsSVGValue, - public nsISVGValueObserver -{ -public: - static nsresult Create(nsIDOMSVGTransform** aResult); - -protected: - nsSVGTransform(); - ~nsSVGTransform(); - nsresult Init(); -public: - // nsISupports interface: - NS_DECL_ISUPPORTS - - // nsIDOMSVGTransform interface: - NS_DECL_NSIDOMSVGTRANSFORM - - // nsISVGValue interface: - NS_IMETHOD SetValueString(const nsAString& aValue); - NS_IMETHOD GetValueString(nsAString& aValue); - - // nsISVGValueObserver - NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable, - modificationType aModType); - NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable, - modificationType aModType); - -protected: - nsCOMPtr mMatrix; - float mAngle, mOriginX, mOriginY; - PRUint16 mType; -}; - - //---------------------------------------------------------------------- // Implementation diff --git a/content/svg/content/src/nsSVGTransform.h b/content/svg/content/src/nsSVGTransform.h index 6183b8e0675..23571cf42ba 100644 --- a/content/svg/content/src/nsSVGTransform.h +++ b/content/svg/content/src/nsSVGTransform.h @@ -40,6 +40,54 @@ #define __NS_SVGTRANSFORM_H__ #include "nsIDOMSVGTransform.h" +#include "nsSVGValue.h" +#include "nsISVGValueObserver.h" + +//////////////////////////////////////////////////////////////////////// +// nsSVGTransform + +class nsSVGTransform : public nsIDOMSVGTransform, + public nsSVGValue, + public nsISVGValueObserver +{ +public: + static nsresult Create(nsIDOMSVGTransform** aResult); + +protected: + nsSVGTransform(); + ~nsSVGTransform(); + nsresult Init(); +public: + // nsISupports interface: + NS_DECL_ISUPPORTS + + // nsIDOMSVGTransform interface: + NS_DECL_NSIDOMSVGTRANSFORM + + // nsISVGValue interface: + NS_IMETHOD SetValueString(const nsAString& aValue); + NS_IMETHOD GetValueString(nsAString& aValue); + + // nsISVGValueObserver + NS_IMETHOD WillModifySVGObservable(nsISVGValue* observable, + modificationType aModType); + NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable, + modificationType aModType); + +#ifdef MOZ_SMIL + // Additional methods needed for animation + void GetRotationOrigin(float& aOriginX, float& aOriginY) const + { + aOriginX = mOriginX; + aOriginY = mOriginY; + } +#endif // MOZ_SMIL + +protected: + nsCOMPtr mMatrix; + float mAngle, mOriginX, mOriginY; + PRUint16 mType; +}; nsresult NS_NewSVGTransform(nsIDOMSVGTransform** result); diff --git a/content/svg/content/src/nsSVGTransformSMILAttr.cpp b/content/svg/content/src/nsSVGTransformSMILAttr.cpp new file mode 100644 index 00000000000..0b26a3f00c1 --- /dev/null +++ b/content/svg/content/src/nsSVGTransformSMILAttr.cpp @@ -0,0 +1,439 @@ +/* -*- 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) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Brian Birtles + * + * 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 "nsSVGTransformSMILAttr.h" +#include "nsSVGTransformSMILType.h" +#include "nsSVGAnimatedTransformList.h" +#include "nsSVGTransformList.h" +#include "nsSVGTransform.h" +#include "nsIDOMSVGTransform.h" +#include "nsIDOMSVGMatrix.h" +#include "nsSVGMatrix.h" +#include "nsSMILValue.h" +#include "nsSMILNullType.h" +#include "nsISMILAnimationElement.h" +#include "nsSVGElement.h" +#include "nsISVGValue.h" +#include "prdtoa.h" + +nsISMILType* +nsSVGTransformSMILAttr::GetSMILType() const +{ + return &nsSVGTransformSMILType::sSingleton; +} + +nsresult +nsSVGTransformSMILAttr::ValueFromString(const nsAString& aStr, + const nsISMILAnimationElement* aSrcElement, + nsSMILValue& aValue) const +{ + NS_ENSURE_TRUE(aSrcElement, NS_ERROR_FAILURE); + NS_ASSERTION(aValue.IsNull(), + "aValue should have been cleared before calling ValueFromString."); + + nsSMILValue val(&nsSVGTransformSMILType::sSingleton); + if (val.IsNull()) + return NS_ERROR_FAILURE; + + const nsAttrValue* typeAttr = aSrcElement->GetAnimAttr(nsGkAtoms::type); + + const nsIAtom* transformType = typeAttr + ? typeAttr->GetAtomValue() + : nsGkAtoms::translate; + + nsresult rv = ParseValue(aStr, transformType, val); + if (NS_FAILED(rv)) + return rv; + + aValue = val; + + return NS_OK; +} + +nsSMILValue +nsSVGTransformSMILAttr::GetBaseValue() const +{ + nsSVGTransformSMILType *type = &nsSVGTransformSMILType::sSingleton; + nsSMILValue val(type); + if (val.IsNull()) + return val; + + nsIDOMSVGTransformList *list = mVal->mBaseVal.get(); + + PRUint32 numItems = 0; + list->GetNumberOfItems(&numItems); + for (PRUint32 i = 0; i < numItems; i++) { + nsCOMPtr transform; + nsresult rv = list->GetItem(i, getter_AddRefs(transform)); + if (NS_SUCCEEDED(rv) && transform) { + rv = AppendSVGTransformToSMILValue(transform.get(), val); + NS_ENSURE_SUCCESS(rv,nsSMILValue()); + } + } + + return val; +} + +nsresult +nsSVGTransformSMILAttr::SetAnimValue(const nsSMILValue& aValue) +{ + if (aValue.mType != &nsSVGTransformSMILType::sSingleton) { + NS_WARNING("Unexpected SMIL Type"); + return NS_ERROR_FAILURE; + } + + nsresult rv = NS_OK; + + // Create the anim value if necessary + mVal->WillModify(nsISVGValue::mod_other); + if (!mVal->mAnimVal) { + rv = nsSVGTransformList::Create(getter_AddRefs(mVal->mAnimVal)); + NS_ENSURE_SUCCESS(rv,rv); + } + + // Do a minimal update on the anim value and if anything fails, set the anim + // value to null so that calls to nsSVGAnimatedTransformList::GetAnimVal will + // return the base value instead. + rv = UpdateFromSMILValue(mVal->mAnimVal, aValue); + if (NS_FAILED(rv)) { + mVal->mAnimVal = nsnull; + } + NS_ENSURE_SUCCESS(rv,rv); + + mVal->DidModify(nsISVGValue::mod_other); + return NS_OK; +} + +//---------------------------------------------------------------------- +// Implementation helpers + +nsresult +nsSVGTransformSMILAttr::ParseValue(const nsAString& aSpec, + const nsIAtom* aTransformType, + nsSMILValue& aResult) const +{ + nsSVGTransformSMILType* type = &nsSVGTransformSMILType::sSingleton; + NS_ASSERTION( + type == static_cast(aResult.mType), + "Unexpected type for SMIL value result."); + + // Reset the result so we can just append to it + nsresult rv = type->Init(aResult); + NS_ENSURE_SUCCESS(rv,rv); + + float params[3] = { 0.f }; + PRInt32 numParsed = ParseParameterList(aSpec, params, 3); + nsSVGSMILTransform::TransformType transformType; + + if (aTransformType == nsGkAtoms::translate) { + // tx [ty=0] + if (numParsed != 1 && numParsed != 2) + return NS_ERROR_FAILURE; + transformType = nsSVGSMILTransform::TRANSFORM_TRANSLATE; + } else if (aTransformType == nsGkAtoms::scale) { + // sx [sy=sx] + if (numParsed != 1 && numParsed != 2) + return NS_ERROR_FAILURE; + if (numParsed == 1) { + params[1] = params[0]; + } + transformType = nsSVGSMILTransform::TRANSFORM_SCALE; + } else if (aTransformType == nsGkAtoms::rotate) { + // r [cx=0 cy=0] + if (numParsed != 1 && numParsed != 3) + return NS_ERROR_FAILURE; + transformType = nsSVGSMILTransform::TRANSFORM_ROTATE; + } else if (aTransformType == nsGkAtoms::skewX) { + // x-angle + if (numParsed != 1) + return NS_ERROR_FAILURE; + transformType = nsSVGSMILTransform::TRANSFORM_SKEWX; + } else if (aTransformType == nsGkAtoms::skewY) { + // y-angle + if (numParsed != 1) + return NS_ERROR_FAILURE; + transformType = nsSVGSMILTransform::TRANSFORM_SKEWY; + } else { + return NS_ERROR_FAILURE; + } + + return type->AppendTransform(nsSVGSMILTransform(transformType, params), + aResult); +} + +inline PRBool +nsSVGTransformSMILAttr::IsSpace(const char c) const +{ + return (c == 0x9 || c == 0xA || c == 0xD || c == 0x20); +} + +inline void +nsSVGTransformSMILAttr::SkipWsp(nsACString::const_iterator& aIter, + const nsACString::const_iterator& aIterEnd) const +{ + while (aIter != aIterEnd && IsSpace(*aIter)) + ++aIter; +} + +PRInt32 +nsSVGTransformSMILAttr::ParseParameterList(const nsAString& aSpec, + float* aVars, + PRInt32 aNVars) const +{ + NS_ConvertUTF16toUTF8 spec(aSpec); + + nsACString::const_iterator start, end; + spec.BeginReading(start); + spec.EndReading(end); + + SkipWsp(start, end); + + int numArgsFound = 0; + + while (start != end) { + char const *arg = start.get(); + char *argend; + float f = float(PR_strtod(arg, &argend)); + if (arg == argend || argend > end.get()) + return -1; + + if (numArgsFound < aNVars) { + aVars[numArgsFound] = f; + } + + start.advance(argend - arg); + numArgsFound++; + + SkipWsp(start, end); + if (*start == ',') { + ++start; + SkipWsp(start, end); + } + } + + return numArgsFound; +} + +nsresult +nsSVGTransformSMILAttr::AppendSVGTransformToSMILValue( + nsIDOMSVGTransform* aTransform, nsSMILValue& aValue) const +{ + nsSVGTransformSMILType* type = &nsSVGTransformSMILType::sSingleton; + + PRUint16 svgTransformType = nsIDOMSVGTransform::SVG_TRANSFORM_MATRIX; + aTransform->GetType(&svgTransformType); + + nsCOMPtr matrix; + nsresult rv = aTransform->GetMatrix(getter_AddRefs(matrix)); + if (NS_FAILED(rv) || !matrix) + return NS_ERROR_FAILURE; + + float params[3] = { 0.f }; + nsSVGSMILTransform::TransformType transformType; + + switch (svgTransformType) + { + case nsIDOMSVGTransform::SVG_TRANSFORM_TRANSLATE: + { + matrix->GetE(¶ms[0]); + matrix->GetF(¶ms[1]); + transformType = nsSVGSMILTransform::TRANSFORM_TRANSLATE; + } + break; + + case nsIDOMSVGTransform::SVG_TRANSFORM_SCALE: + { + matrix->GetA(¶ms[0]); + matrix->GetD(¶ms[1]); + transformType = nsSVGSMILTransform::TRANSFORM_SCALE; + } + break; + + case nsIDOMSVGTransform::SVG_TRANSFORM_ROTATE: + { + /* + * Unfortunately the SVG 1.1 DOM API for transforms doesn't allow us to + * query the center of rotation so we do some dirty casting to make up + * for it. + */ + nsSVGTransform* svgTransform = static_cast(aTransform); + svgTransform->GetAngle(¶ms[0]); + svgTransform->GetRotationOrigin(params[1], params[2]); + transformType = nsSVGSMILTransform::TRANSFORM_ROTATE; + } + break; + + case nsIDOMSVGTransform::SVG_TRANSFORM_SKEWX: + { + aTransform->GetAngle(¶ms[0]); + transformType = nsSVGSMILTransform::TRANSFORM_SKEWX; + } + break; + + case nsIDOMSVGTransform::SVG_TRANSFORM_SKEWY: + { + aTransform->GetAngle(¶ms[0]); + transformType = nsSVGSMILTransform::TRANSFORM_SKEWY; + } + break; + + case nsIDOMSVGTransform::SVG_TRANSFORM_MATRIX: + { + float mx[6]; + matrix->GetA(&mx[0]); + matrix->GetB(&mx[1]); + matrix->GetC(&mx[2]); + matrix->GetD(&mx[3]); + matrix->GetE(&mx[4]); + matrix->GetF(&mx[5]); + rv = type->AppendTransform(nsSVGSMILTransform(mx), aValue); + transformType = nsSVGSMILTransform::TRANSFORM_MATRIX; + } + break; + + case nsIDOMSVGTransform::SVG_TRANSFORM_UNKNOWN: + // If it's 'unknown', it's probably not initialised, so just skip it. + return NS_OK; + + default: + NS_WARNING("Trying to convert unrecognised SVG transform type."); + return NS_ERROR_FAILURE; + } + + if (transformType != nsSVGSMILTransform::TRANSFORM_MATRIX) { + rv = + type->AppendTransform(nsSVGSMILTransform(transformType, params), aValue); + } + + return rv; +} + +nsresult +nsSVGTransformSMILAttr::UpdateFromSMILValue( + nsIDOMSVGTransformList* aTransformList, const nsSMILValue& aValue) +{ + PRUint32 svgLength = -1; + aTransformList->GetNumberOfItems(&svgLength); + + nsSVGTransformSMILType* type = &nsSVGTransformSMILType::sSingleton; + PRUint32 smilLength = type->GetNumTransforms(aValue); + + nsresult rv = NS_OK; + + for (PRUint32 i = 0; i < smilLength; i++) { + nsCOMPtr transform; + if (i < svgLength) { + // Get the transform to update + rv = aTransformList->GetItem(i, getter_AddRefs(transform)); + NS_ENSURE_SUCCESS(rv,rv); + } else { + // Append another transform to the list + nsresult rv = NS_NewSVGTransform(getter_AddRefs(transform)); + NS_ENSURE_SUCCESS(rv,rv); + + nsCOMPtr result; + rv = aTransformList->AppendItem(transform, getter_AddRefs(result)); + NS_ENSURE_SUCCESS(rv,rv); + } + // Set the value + const nsSVGSMILTransform* smilTransform = type->GetTransformAt(i, aValue); + rv = GetSVGTransformFromSMILValue(*smilTransform, transform); + NS_ENSURE_SUCCESS(rv,rv); + } + + // Trim excess elements + while (svgLength > smilLength) { + nsCOMPtr removed; + rv = aTransformList->RemoveItem(--svgLength, getter_AddRefs(removed)); + NS_ENSURE_SUCCESS(rv,rv); + } + + return NS_OK; +} + +nsresult +nsSVGTransformSMILAttr::GetSVGTransformFromSMILValue( + const nsSVGSMILTransform& aSMILTransform, + nsIDOMSVGTransform* aSVGTransform) const +{ + nsresult rv = NS_ERROR_FAILURE; + + switch (aSMILTransform.mTransformType) + { + case nsSVGSMILTransform::TRANSFORM_TRANSLATE: + rv = aSVGTransform->SetTranslate(aSMILTransform.mParams[0], + aSMILTransform.mParams[1]); + break; + + case nsSVGSMILTransform::TRANSFORM_SCALE: + rv = aSVGTransform->SetScale(aSMILTransform.mParams[0], + aSMILTransform.mParams[1]); + break; + + case nsSVGSMILTransform::TRANSFORM_ROTATE: + rv = aSVGTransform->SetRotate(aSMILTransform.mParams[0], + aSMILTransform.mParams[1], + aSMILTransform.mParams[2]); + break; + + case nsSVGSMILTransform::TRANSFORM_SKEWX: + rv = aSVGTransform->SetSkewX(aSMILTransform.mParams[0]); + break; + + case nsSVGSMILTransform::TRANSFORM_SKEWY: + rv = aSVGTransform->SetSkewY(aSMILTransform.mParams[0]); + break; + + case nsSVGSMILTransform::TRANSFORM_MATRIX: + { + nsCOMPtr svgMatrix; + rv = NS_NewSVGMatrix(getter_AddRefs(svgMatrix), + aSMILTransform.mParams[0], + aSMILTransform.mParams[1], + aSMILTransform.mParams[2], + aSMILTransform.mParams[3], + aSMILTransform.mParams[4], + aSMILTransform.mParams[5]); + NS_ENSURE_SUCCESS(rv,rv); + NS_ENSURE_TRUE(svgMatrix,NS_ERROR_FAILURE); + rv = aSVGTransform->SetMatrix(svgMatrix); + } + break; + } + + return rv; +} diff --git a/content/svg/content/src/nsSVGTransformSMILAttr.h b/content/svg/content/src/nsSVGTransformSMILAttr.h new file mode 100644 index 00000000000..4dbf66cd9f1 --- /dev/null +++ b/content/svg/content/src/nsSVGTransformSMILAttr.h @@ -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 SVG project. + * + * 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): + * Brian Birtles + * + * 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_SVGTRANSFORMSMILATTR_H_ +#define NS_SVGTRANSFORMSMILATTR_H_ + +#include "nsISMILAttr.h" +#include "nsIAtom.h" +#include "nsString.h" + +class nsSVGElement; +class nsSVGAnimatedTransformList; +class nsISMILType; +class nsIDOMSVGTransform; +class nsIDOMSVGTransformList; +class nsSVGSMILTransform; + +class nsSVGTransformSMILAttr : public nsISMILAttr +{ +public: + nsSVGTransformSMILAttr(nsSVGAnimatedTransformList* aTransform, + nsSVGElement* aSVGElement) + : mVal(aTransform), + mSVGElement(aSVGElement) {} + + // nsISMILAttr methods + virtual nsISMILType* GetSMILType() const; + virtual nsresult ValueFromString(const nsAString& aStr, + const nsISMILAnimationElement* aSrcElement, + nsSMILValue& aValue) const; + virtual nsSMILValue GetBaseValue() const; + virtual nsresult SetAnimValue(const nsSMILValue& aValue); + +protected: + nsresult ParseValue(const nsAString& aSpec, + const nsIAtom* aTransformType, + nsSMILValue& aResult) const; + PRInt32 ParseParameterList(const nsAString& aSpec, float* aVars, + PRInt32 aNVars) const; + PRBool IsSpace(const char c) const; + void SkipWsp(nsACString::const_iterator& aIter, + const nsACString::const_iterator& aIterEnd) const; + nsresult AppendSVGTransformToSMILValue(nsIDOMSVGTransform* transform, + nsSMILValue& aValue) const; + nsresult UpdateFromSMILValue(nsIDOMSVGTransformList* aTransformList, + const nsSMILValue& aValue); + nsresult GetSVGTransformFromSMILValue( + const nsSVGSMILTransform& aSMILTransform, + nsIDOMSVGTransform* aSVGTransform) const; + already_AddRefed GetSVGTransformFromSMILValue( + const nsSMILValue& aValue) const; + +private: + // Raw pointers are OK here because this nsSVGTransformSMILAttr is both + // created & destroyed during a SMIL sample-step, during which time the DOM + // isn't modified. + nsSVGAnimatedTransformList* mVal; + nsSVGElement* mSVGElement; +}; + +#endif // NS_SVGTRANSFORMSMILATTR_H_ diff --git a/content/svg/content/src/nsSVGTransformSMILType.cpp b/content/svg/content/src/nsSVGTransformSMILType.cpp new file mode 100644 index 00000000000..959abc067f6 --- /dev/null +++ b/content/svg/content/src/nsSVGTransformSMILType.cpp @@ -0,0 +1,356 @@ +/* -*- 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) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Brian Birtles + * + * 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 "nsSVGTransformSMILType.h" +#include "nsSMILValue.h" +#include "nsCRT.h" +#include + +/*static*/ nsSVGTransformSMILType nsSVGTransformSMILType::sSingleton; + +//---------------------------------------------------------------------- +// nsISMILType implementation + +nsresult +nsSVGTransformSMILType::Init(nsSMILValue &aValue) const +{ + NS_PRECONDITION(aValue.mType == this || aValue.IsNull(), + "Unexpected value type"); + NS_ASSERTION(aValue.mType != this || aValue.mU.mPtr, + "Invalid nsSMILValue of SVG transform type: NULL data member."); + + if (aValue.mType != this || !aValue.mU.mPtr) { + // Different type, or no data member: allocate memory and set type + TransformArray* transforms = new TransformArray(1); + NS_ENSURE_TRUE(transforms, NS_ERROR_OUT_OF_MEMORY); + aValue.mU.mPtr = transforms; + aValue.mType = this; + } else { + // Same type, just set clear + TransformArray* transforms = static_cast(aValue.mU.mPtr); + transforms->Clear(); + } + + return NS_OK; +} + +void +nsSVGTransformSMILType::Destroy(nsSMILValue& aValue) const +{ + NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value type."); + TransformArray* params = static_cast(aValue.mU.mPtr); + delete params; + aValue.mU.mPtr = nsnull; + aValue.mType = &nsSMILNullType::sSingleton; +} + +nsresult +nsSVGTransformSMILType::Assign(nsSMILValue& aDest, + const nsSMILValue& aSrc) const +{ + NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types."); + NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value."); + + const TransformArray* srcTransforms = + static_cast(aSrc.mU.mPtr); + TransformArray* dstTransforms = static_cast(aDest.mU.mPtr); + + // Before we assign, ensure we have sufficient memory + PRBool result = dstTransforms->SetCapacity(srcTransforms->Length()); + NS_ENSURE_TRUE(result,NS_ERROR_OUT_OF_MEMORY); + + *dstTransforms = *srcTransforms; + + return NS_OK; +} + +nsresult +nsSVGTransformSMILType::Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd, + PRUint32 aCount) const +{ + NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL type."); + NS_PRECONDITION(aDest.mType == aValueToAdd.mType, "Incompatible SMIL types."); + + TransformArray& dstTransforms(*static_cast(aDest.mU.mPtr)); + const TransformArray& srcTransforms + (*static_cast(aValueToAdd.mU.mPtr)); + + // We're doing a simple add here (as opposed to a sandwich add below). + // We only do this when we're accumulating a repeat result or calculating + // a by-animation value. + // + // In either case we should have 1 transform in the source array. + NS_ASSERTION(srcTransforms.Length() == 1, + "Invalid source transform list to add."); + + // And we should have 0 or 1 transforms in the dest array. + // (We can have 0 transforms in the case of by-animation when we are + // calculating the by-value as "0 + by". Zero being represented by an + // nsSMILValue with an empty transform array.) + NS_ASSERTION(dstTransforms.Length() < 2, + "Invalid dest transform list to add to."); + + // Get the individual transforms to add + const nsSVGSMILTransform& srcTransform = srcTransforms[0]; + if (dstTransforms.IsEmpty()) { + nsSVGSMILTransform* result = dstTransforms.AppendElement( + nsSVGSMILTransform(srcTransform.mTransformType)); + NS_ENSURE_TRUE(result,NS_ERROR_OUT_OF_MEMORY); + } + nsSVGSMILTransform& dstTransform = dstTransforms[0]; + + // The types must be the same + NS_ASSERTION(srcTransform.mTransformType == dstTransform.mTransformType, + "Trying to perform simple add of different transform types."); + + // And it should be impossible that one of them is of matrix type + NS_ASSERTION( + srcTransform.mTransformType != nsSVGSMILTransform::TRANSFORM_MATRIX, + "Trying to perform simple add with matrix transform."); + + // Add the parameters + for (int i = 0; i <= 2; ++i) { + dstTransform.mParams[i] += srcTransform.mParams[i] * aCount; + } + + return NS_OK; +} + +nsresult +nsSVGTransformSMILType::SandwichAdd(nsSMILValue& aDest, + const nsSMILValue& aValueToAdd) const +{ + NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL type."); + NS_PRECONDITION(aDest.mType == aValueToAdd.mType, "Incompatible SMIL types."); + + // For a sandwich add means a matrix post-multiplication + // which just means to put the additional transform on the end of the array + + TransformArray& dstTransforms(*static_cast(aDest.mU.mPtr)); + const TransformArray& srcTransforms + (*static_cast(aValueToAdd.mU.mPtr)); + + // We're only expecting to be adding 1 src transform on to the list + NS_ASSERTION(srcTransforms.Length() == 1, + "Trying to do sandwich add of more than one value."); + + // Stick the src on the end of the array + const nsSVGSMILTransform& srcTransform = srcTransforms[0]; + nsSVGSMILTransform* result = dstTransforms.AppendElement(srcTransform); + NS_ENSURE_TRUE(result,NS_ERROR_OUT_OF_MEMORY); + + return NS_OK; +} + +nsresult +nsSVGTransformSMILType::ComputeDistance(const nsSMILValue& aFrom, + const nsSMILValue& aTo, + double& aDistance) const +{ + NS_PRECONDITION(aFrom.mType == aTo.mType, + "Can't compute difference between different SMIL types."); + NS_PRECONDITION(aFrom.mType == this, "Unexpected SMIL type."); + + const TransformArray* fromTransforms = + static_cast(aFrom.mU.mPtr); + const TransformArray* toTransforms = + static_cast(aTo.mU.mPtr); + + // ComputeDistance is only used for calculating distances between single + // values in a values array which necessarily have the same type + // + // So we should only have one transform in each array and they should be of + // the same type + NS_ASSERTION(fromTransforms->Length() == 1, + "Wrong number of elements in from value."); + NS_ASSERTION(toTransforms->Length() == 1, + "Wrong number of elements in to value."); + + const nsSVGSMILTransform& fromTransform = (*fromTransforms)[0]; + const nsSVGSMILTransform& toTransform = (*toTransforms)[0]; + NS_ASSERTION(fromTransform.mTransformType == toTransform.mTransformType, + "Incompatible transform types to calculate distance between."); + + switch (fromTransform.mTransformType) + { + // We adopt the SVGT1.2 notions of distance here + // See: http://www.w3.org/TR/SVGTiny12/animate.html#complexDistances + // (As discussed in bug #469040) + case nsSVGSMILTransform::TRANSFORM_TRANSLATE: + case nsSVGSMILTransform::TRANSFORM_SCALE: + { + const float& a_tx = fromTransform.mParams[0]; + const float& a_ty = fromTransform.mParams[1]; + const float& b_tx = toTransform.mParams[0]; + const float& b_ty = toTransform.mParams[1]; + aDistance = sqrt(pow(a_tx - b_tx, 2) + (pow(a_ty - b_ty, 2))); + } + break; + + case nsSVGSMILTransform::TRANSFORM_ROTATE: + case nsSVGSMILTransform::TRANSFORM_SKEWX: + case nsSVGSMILTransform::TRANSFORM_SKEWY: + { + const float& a = fromTransform.mParams[0]; + const float& b = toTransform.mParams[0]; + aDistance = fabs(a-b); + } + break; + + default: + NS_ERROR("Got bad transform types for calculating distances."); + aDistance = 1.0; + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + +nsresult +nsSVGTransformSMILType::Interpolate(const nsSMILValue& aStartVal, + const nsSMILValue& aEndVal, + double aUnitDistance, + nsSMILValue& aResult) const +{ + NS_PRECONDITION(aStartVal.mType == aEndVal.mType, + "Can't interpolate between different SMIL types."); + NS_PRECONDITION(aStartVal.mType == this, + "Unexpected type for interpolation."); + NS_PRECONDITION(aResult.mType == this, "Unexpected result type."); + + const TransformArray& startTransforms = + (*static_cast(aStartVal.mU.mPtr)); + const TransformArray& endTransforms + (*static_cast(aEndVal.mU.mPtr)); + + // We may have 0..n transforms in the start transform array (the base + // value) but we should only have 1 transform in the end transform array + NS_ASSERTION(endTransforms.Length() == 1, + "Invalid end-point for interpolating between transform values."); + + // The end point should never be a matrix transform + const nsSVGSMILTransform& endTransform = endTransforms[0]; + NS_ASSERTION( + endTransform.mTransformType != nsSVGSMILTransform::TRANSFORM_MATRIX, + "End point for interpolation should not be a matrix transform."); + + // If we have 0 or more than 1 transform in the start transform array then we + // just interpolate from 0, 0, 0 + // Likewise, even if there's only 1 transform in the start transform array + // then if the type of the start transform doesn't match the end then we + // can't interpolate and should just use 0, 0, 0 + static float identityParams[3] = { 0.f }; + const float* startParams = nsnull; + if (startTransforms.Length() == 1) { + const nsSVGSMILTransform& startTransform = startTransforms[0]; + if (startTransform.mTransformType == endTransform.mTransformType) { + startParams = startTransform.mParams; + } + } + if (!startParams) { + startParams = identityParams; + } + + const float* endParams = endTransform.mParams; + + // Interpolate between the params + float newParams[3]; + for (int i = 0; i <= 2; ++i) { + const float& a = startParams[i]; + const float& b = endParams[i]; + newParams[i] = a + (b - a) * aUnitDistance; + } + + // Make the result + nsSVGSMILTransform resultTransform(endTransform.mTransformType, newParams); + + // Clear the way for it in the result array + TransformArray& dstTransforms = + (*static_cast(aResult.mU.mPtr)); + dstTransforms.Clear(); + + // Assign the result + nsSVGSMILTransform* transform = dstTransforms.AppendElement(resultTransform); + NS_ENSURE_TRUE(transform,NS_ERROR_OUT_OF_MEMORY); + + return NS_OK; +} + +//---------------------------------------------------------------------- +// Transform array accessors + +PRUint32 +nsSVGTransformSMILType::GetNumTransforms(const nsSMILValue& aValue) const +{ + NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value."); + + const TransformArray& transforms = + *static_cast(aValue.mU.mPtr); + + return transforms.Length(); +} + +const nsSVGSMILTransform* +nsSVGTransformSMILType::GetTransformAt(PRUint32 aIndex, + const nsSMILValue& aValue) const +{ + NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value."); + + const TransformArray& transforms = + *static_cast(aValue.mU.mPtr); + + if (aIndex >= transforms.Length()) { + NS_ERROR("Attempting to access invalid transform."); + return nsnull; + } + + return &transforms[aIndex]; +} + +nsresult +nsSVGTransformSMILType::AppendTransform(const nsSVGSMILTransform& aTransform, + nsSMILValue& aValue) const +{ + NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value."); + + TransformArray& transforms = *static_cast(aValue.mU.mPtr); + + nsSVGSMILTransform* transform = transforms.AppendElement(aTransform); + NS_ENSURE_TRUE(transform,NS_ERROR_OUT_OF_MEMORY); + + return NS_OK; +} diff --git a/content/svg/content/src/nsSVGTransformSMILType.h b/content/svg/content/src/nsSVGTransformSMILType.h new file mode 100644 index 00000000000..277678b8268 --- /dev/null +++ b/content/svg/content/src/nsSVGTransformSMILType.h @@ -0,0 +1,141 @@ +/* -*- 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) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Brian Birtles + * + * 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_SVGTRANSFORMSMILTYPE_H_ +#define NS_SVGTRANSFORMSMILTYPE_H_ + +#include "nsISMILType.h" +#include "nsSVGSMILTransform.h" +#include "nsTArray.h" + +struct nsSMILValue; + +//////////////////////////////////////////////////////////////////////// +// nsSVGTransformSMILType +// +// Operations for animating an nsSVGTransformList. +// +// This class is confused somewhat by the fact that: +// (i) An element animates an SVGTransformList +// (ii) BUT only allows the user to specify animation values +// for an SVGTransform +// +// This may be rectified in a future edition of SVG but for now it means that +// the underlying value of an animation may be something of the form: +// +// rotate(90) scale(2) skewX(50) +// +// BUT the animation values can only ever be SINGLE transform operations such as +// +// rotate(90) +// +// (actually the syntax here is: +// element and so these values can only ever contain 0 or +// 1 TRANSFORM elements as the syntax doesn't allow more. (A "value" here is +// a single element in the values array such as "0 50 20" above.) +// +// Likewise ComputeDistance() only ever operates within the values specified on +// an element so similar conditions hold. +// +// However, SandwichAdd() combines with a base value which may contain 0..n +// transforms either because the base value of the attribute specifies a series +// of transforms, e.g. +// +// +// +// +// +// or because several animations target the same attribute and are additive and +// so are simply appended on to the transformation array, e.g. +// +// +// +// +// +// +// +// Similar conditions hold for Interpolate() which in cases such as to-animation +// may have use a start-value the base value of the target attribute (which as +// we have seen above can contain 0..n elements) whilst the end-value comes from +// the and so can only hold 1 transform. +// +class nsSVGTransformSMILType : public nsISMILType +{ +public: + // nsISMILType + virtual nsresult Init(nsSMILValue& aValue) const; + virtual void Destroy(nsSMILValue& aValue) const; + virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const; + virtual nsresult Add(nsSMILValue& aDest, + const nsSMILValue& aValueToAdd, + PRUint32 aCount) const; + virtual nsresult SandwichAdd(nsSMILValue& aDest, + const nsSMILValue& aValueToAdd) 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; + // Transform array accessors + PRUint32 GetNumTransforms(const nsSMILValue& aValue) const; + const nsSVGSMILTransform* GetTransformAt(PRUint32 aIndex, + const nsSMILValue& aValue) const; + nsresult AppendTransform(const nsSVGSMILTransform& aTransform, + nsSMILValue& aValue) const; + + static nsSVGTransformSMILType sSingleton; + +protected: + typedef nsTArray TransformArray; + +private: + nsSVGTransformSMILType() {} +}; + +#endif // NS_SVGTRANSFORMSMILTYPE_H_ diff --git a/dom/public/idl/svg/Makefile.in b/dom/public/idl/svg/Makefile.in index 62fe2d3c79e..313353fd05d 100644 --- a/dom/public/idl/svg/Makefile.in +++ b/dom/public/idl/svg/Makefile.in @@ -131,6 +131,7 @@ XPIDLSRCS = \ ifdef MOZ_SMIL XPIDLSRCS += \ nsIDOMSVGAnimateElement.idl \ + nsIDOMSVGAnimateTransformElement.idl \ nsIDOMSVGAnimationElement.idl \ nsIDOMSVGSetElement.idl \ $(NULL) diff --git a/dom/public/idl/svg/nsIDOMSVGAnimateTransformElement.idl b/dom/public/idl/svg/nsIDOMSVGAnimateTransformElement.idl new file mode 100644 index 00000000000..319b6b51495 --- /dev/null +++ b/dom/public/idl/svg/nsIDOMSVGAnimateTransformElement.idl @@ -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 + * + * 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(735e0f75-c6aa-4aee-bcd2-46426d6ac90c)] +interface nsIDOMSVGAnimateTransformElement : nsIDOMSVGAnimationElement {}; diff --git a/dom/public/nsDOMClassInfoID.h b/dom/public/nsDOMClassInfoID.h index c887389cd51..2354de3aeeb 100644 --- a/dom/public/nsDOMClassInfoID.h +++ b/dom/public/nsDOMClassInfoID.h @@ -245,6 +245,7 @@ enum nsDOMClassInfoID { eDOMClassInfo_SVGAElement_id, #ifdef MOZ_SMIL eDOMClassInfo_SVGAnimateElement_id, + eDOMClassInfo_SVGAnimateTransformElement_id, eDOMClassInfo_SVGSetElement_id, #endif // MOZ_SMIL eDOMClassInfo_SVGCircleElement_id, diff --git a/dom/src/base/nsDOMClassInfo.cpp b/dom/src/base/nsDOMClassInfo.cpp index f7bf63372a8..30111e78837 100644 --- a/dom/src/base/nsDOMClassInfo.cpp +++ b/dom/src/base/nsDOMClassInfo.cpp @@ -378,6 +378,7 @@ #include "nsIDOMSVGAnimatedString.h" #ifdef MOZ_SMIL #include "nsIDOMSVGAnimateElement.h" +#include "nsIDOMSVGAnimateTransformElement.h" #include "nsIDOMSVGSetElement.h" #include "nsIDOMSVGAnimationElement.h" #include "nsIDOMElementTimeControl.h" @@ -948,6 +949,8 @@ static nsDOMClassInfoData sClassInfoData[] = { #ifdef MOZ_SMIL NS_DEFINE_CLASSINFO_DATA(SVGAnimateElement, nsElementSH, ELEMENT_SCRIPTABLE_FLAGS) + NS_DEFINE_CLASSINFO_DATA(SVGAnimateTransformElement, nsElementSH, + ELEMENT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(SVGSetElement, nsElementSH, ELEMENT_SCRIPTABLE_FLAGS) #endif // MOZ_SMIL @@ -2771,6 +2774,14 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES DOM_CLASSINFO_MAP_END + DOM_CLASSINFO_MAP_BEGIN(SVGAnimateTransformElement, + nsIDOMSVGAnimateTransformElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimationElement) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAnimateTransformElement) + 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) diff --git a/layout/reftests/svg/smil/reftest.list b/layout/reftests/svg/smil/reftest.list index a660a346467..2d32d8b08c2 100644 --- a/layout/reftests/svg/smil/reftest.list +++ b/layout/reftests/svg/smil/reftest.list @@ -19,6 +19,9 @@ include sort/reftest.list # style tests include style/reftest.list +# animateTransform tests +include transform/reftest.list + # time-dependent tests # XXXdholbert Disabling this class of tests for now, because most of them # can & should be converted so they don't depend on specific timeout values. diff --git a/layout/reftests/svg/smil/transform/additive-1-ref.svg b/layout/reftests/svg/smil/transform/additive-1-ref.svg new file mode 100644 index 00000000000..1b5f9a5aad2 --- /dev/null +++ b/layout/reftests/svg/smil/transform/additive-1-ref.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/transform/additive-1.svg b/layout/reftests/svg/smil/transform/additive-1.svg new file mode 100644 index 00000000000..36281c6c81a --- /dev/null +++ b/layout/reftests/svg/smil/transform/additive-1.svg @@ -0,0 +1,209 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/transform/paced-1-ref.svg b/layout/reftests/svg/smil/transform/paced-1-ref.svg new file mode 100644 index 00000000000..ac843a13e4f --- /dev/null +++ b/layout/reftests/svg/smil/transform/paced-1-ref.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/transform/paced-1.svg b/layout/reftests/svg/smil/transform/paced-1.svg new file mode 100644 index 00000000000..b37aa59cd7f --- /dev/null +++ b/layout/reftests/svg/smil/transform/paced-1.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/transform/reftest.list b/layout/reftests/svg/smil/transform/reftest.list new file mode 100644 index 00000000000..def2b651432 --- /dev/null +++ b/layout/reftests/svg/smil/transform/reftest.list @@ -0,0 +1,12 @@ +# Tests related to SVG Animation (using SMIL), focusing on the animateTransform +# element. + +== rotate-angle-1.svg rotate-angle-ref.svg +== rotate-angle-2.svg rotate-angle-ref.svg +== rotate-angle-3.svg rotate-angle-ref.svg +== rotate-angle-4.svg rotate-angle-ref.svg +== rotate-angle-5.svg rotate-angle-ref.svg +== scale-1.svg scale-1-ref.svg +== skew-1.svg skew-1-ref.svg +== paced-1.svg paced-1-ref.svg +== additive-1.svg additive-1-ref.svg diff --git a/layout/reftests/svg/smil/transform/rotate-angle-1.svg b/layout/reftests/svg/smil/transform/rotate-angle-1.svg new file mode 100644 index 00000000000..6da30cf3a72 --- /dev/null +++ b/layout/reftests/svg/smil/transform/rotate-angle-1.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/transform/rotate-angle-2.svg b/layout/reftests/svg/smil/transform/rotate-angle-2.svg new file mode 100644 index 00000000000..211dbf71502 --- /dev/null +++ b/layout/reftests/svg/smil/transform/rotate-angle-2.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/transform/rotate-angle-3.svg b/layout/reftests/svg/smil/transform/rotate-angle-3.svg new file mode 100644 index 00000000000..23051cabfae --- /dev/null +++ b/layout/reftests/svg/smil/transform/rotate-angle-3.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/transform/rotate-angle-4.svg b/layout/reftests/svg/smil/transform/rotate-angle-4.svg new file mode 100644 index 00000000000..17a9d7da2f6 --- /dev/null +++ b/layout/reftests/svg/smil/transform/rotate-angle-4.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/transform/rotate-angle-5.svg b/layout/reftests/svg/smil/transform/rotate-angle-5.svg new file mode 100644 index 00000000000..e4a97ca074c --- /dev/null +++ b/layout/reftests/svg/smil/transform/rotate-angle-5.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/transform/rotate-angle-ref.svg b/layout/reftests/svg/smil/transform/rotate-angle-ref.svg new file mode 100644 index 00000000000..e69ce351ef7 --- /dev/null +++ b/layout/reftests/svg/smil/transform/rotate-angle-ref.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/transform/scale-1-ref.svg b/layout/reftests/svg/smil/transform/scale-1-ref.svg new file mode 100644 index 00000000000..0e725f475b1 --- /dev/null +++ b/layout/reftests/svg/smil/transform/scale-1-ref.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/transform/scale-1.svg b/layout/reftests/svg/smil/transform/scale-1.svg new file mode 100644 index 00000000000..81fa8eb60fb --- /dev/null +++ b/layout/reftests/svg/smil/transform/scale-1.svg @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/transform/skew-1-ref.svg b/layout/reftests/svg/smil/transform/skew-1-ref.svg new file mode 100644 index 00000000000..10c7ca8a38b --- /dev/null +++ b/layout/reftests/svg/smil/transform/skew-1-ref.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/smil/transform/skew-1.svg b/layout/reftests/svg/smil/transform/skew-1.svg new file mode 100644 index 00000000000..037010fc51b --- /dev/null +++ b/layout/reftests/svg/smil/transform/skew-1.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +