Bug 468996. Implement SMIL animateTransform element. r+sr=roc
|
@ -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 <animateTransform>) the operation differs. For
|
||||
* <animateTransform> 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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -140,8 +140,11 @@ CPPSRCS = \
|
|||
|
||||
ifdef MOZ_SMIL
|
||||
CPPSRCS += nsSVGAnimateElement.cpp \
|
||||
nsSVGAnimateTransformElement.cpp \
|
||||
nsSVGAnimationElement.cpp \
|
||||
nsSVGSetElement.cpp \
|
||||
nsSVGTransformSMILType.cpp \
|
||||
nsSVGTransformSMILAttr.cpp \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
|
|
@ -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 <birtles@gmail.com>
|
||||
* Chris Double <chris.double@double.co.nz>
|
||||
* 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 "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 <animateTransform>-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;
|
||||
}
|
|
@ -38,58 +38,11 @@
|
|||
|
||||
#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<nsIDOMSVGTransformList> mBaseVal;
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Implementation
|
||||
|
||||
nsSVGAnimatedTransformList::nsSVGAnimatedTransformList()
|
||||
{
|
||||
}
|
||||
|
||||
nsSVGAnimatedTransformList::~nsSVGAnimatedTransformList()
|
||||
{
|
||||
if (!mBaseVal) return;
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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<nsIDOMSVGTransformList> mBaseVal;
|
||||
// XXX This should be read-only, i.e. its setters should throw
|
||||
nsCOMPtr<nsIDOMSVGTransformList> mAnimVal;
|
||||
};
|
||||
|
||||
nsresult
|
||||
NS_NewSVGAnimatedTransformList(nsIDOMSVGAnimatedTransformList** result,
|
||||
|
|
|
@ -91,6 +91,8 @@
|
|||
#include "prdtoa.h"
|
||||
#include <stdarg.h>
|
||||
#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<nsIDOMSVGTransformable> transformable(
|
||||
do_QueryInterface(static_cast<nsIContent*>(this)));
|
||||
if (!transformable)
|
||||
return nsnull;
|
||||
nsCOMPtr<nsIDOMSVGAnimatedTransformList> transformList;
|
||||
nsresult rv = transformable->GetTransform(getter_AddRefs(transformList));
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
nsSVGAnimatedTransformList* list
|
||||
= static_cast<nsSVGAnimatedTransformList*>(transformList.get());
|
||||
NS_ENSURE_TRUE(list, nsnull);
|
||||
|
||||
return new nsSVGTransformSMILAttr(list, this);
|
||||
}
|
||||
|
||||
// Lengths:
|
||||
LengthAttributesInfo info = GetLengthInfo();
|
||||
for (PRUint32 i = 0; i < info.mLengthCount; i++) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <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_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_
|
|
@ -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<nsIDOMSVGMatrix> mMatrix;
|
||||
float mAngle, mOriginX, mOriginY;
|
||||
PRUint16 mType;
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Implementation
|
||||
|
||||
|
|
|
@ -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<nsIDOMSVGMatrix> mMatrix;
|
||||
float mAngle, mOriginX, mOriginY;
|
||||
PRUint16 mType;
|
||||
};
|
||||
|
||||
nsresult
|
||||
NS_NewSVGTransform(nsIDOMSVGTransform** result);
|
||||
|
|
|
@ -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 <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 "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<nsIDOMSVGTransform> 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<nsSVGTransformSMILType const *>(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<nsIDOMSVGMatrix> 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<nsSVGTransform*>(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<nsIDOMSVGTransform> 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<nsIDOMSVGTransform> 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<nsIDOMSVGTransform> 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<nsIDOMSVGMatrix> 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;
|
||||
}
|
|
@ -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 <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_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<nsIDOMSVGTransform> 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_
|
|
@ -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 <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 "nsSVGTransformSMILType.h"
|
||||
#include "nsSMILValue.h"
|
||||
#include "nsCRT.h"
|
||||
#include <math.h>
|
||||
|
||||
/*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<TransformArray*>(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<TransformArray*>(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<const TransformArray*>(aSrc.mU.mPtr);
|
||||
TransformArray* dstTransforms = static_cast<TransformArray*>(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<TransformArray*>(aDest.mU.mPtr));
|
||||
const TransformArray& srcTransforms
|
||||
(*static_cast<const TransformArray*>(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 <animateTransform> 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<TransformArray*>(aDest.mU.mPtr));
|
||||
const TransformArray& srcTransforms
|
||||
(*static_cast<const TransformArray*>(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<const TransformArray*>(aFrom.mU.mPtr);
|
||||
const TransformArray* toTransforms =
|
||||
static_cast<const TransformArray*>(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<const TransformArray*>(aStartVal.mU.mPtr));
|
||||
const TransformArray& endTransforms
|
||||
(*static_cast<const TransformArray*>(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<TransformArray*>(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<const TransformArray*>(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<const TransformArray*>(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<TransformArray*>(aValue.mU.mPtr);
|
||||
|
||||
nsSVGSMILTransform* transform = transforms.AppendElement(aTransform);
|
||||
NS_ENSURE_TRUE(transform,NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return NS_OK;
|
||||
}
|
|
@ -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 <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_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 <animateTransform> element animates an SVGTransformList
|
||||
// (ii) BUT <animateTransform> 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:
|
||||
// <animateTransform type="rotate" from="0" to="90"...
|
||||
// OR maybe
|
||||
// <animateTransform type="rotate" values="0; 90; 30; 50"...
|
||||
// OR even (with a rotation centre)
|
||||
// <animateTransform type="rotate" values="0 50 20; 30 50 20; 70 0 0"...)
|
||||
//
|
||||
// This has many implications for the number of elements we expect in the
|
||||
// transform array supplied for each operation.
|
||||
//
|
||||
// For example, Add() only ever operates on the values specified on an
|
||||
// <animateTransform> 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 <animateTransform> 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.
|
||||
//
|
||||
// <circle transform="translate(30) rotate(50)"... >
|
||||
// <animateTransform.../>
|
||||
// </circle>
|
||||
//
|
||||
// or because several animations target the same attribute and are additive and
|
||||
// so are simply appended on to the transformation array, e.g.
|
||||
//
|
||||
// <circle transform="translate(30)"... >
|
||||
// <animateTransform type="rotate" additive="sum".../>
|
||||
// <animateTransform type="scale" additive="sum".../>
|
||||
// <animateTransform type="skewX" additive="sum".../>
|
||||
// </circle>
|
||||
//
|
||||
// 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 <animateTransform> 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<nsSVGSMILTransform> TransformArray;
|
||||
|
||||
private:
|
||||
nsSVGTransformSMILType() {}
|
||||
};
|
||||
|
||||
#endif // NS_SVGTRANSFORMSMILTYPE_H_
|
|
@ -131,6 +131,7 @@ XPIDLSRCS = \
|
|||
ifdef MOZ_SMIL
|
||||
XPIDLSRCS += \
|
||||
nsIDOMSVGAnimateElement.idl \
|
||||
nsIDOMSVGAnimateTransformElement.idl \
|
||||
nsIDOMSVGAnimationElement.idl \
|
||||
nsIDOMSVGSetElement.idl \
|
||||
$(NULL)
|
||||
|
|
|
@ -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(735e0f75-c6aa-4aee-bcd2-46426d6ac90c)]
|
||||
interface nsIDOMSVGAnimateTransformElement : nsIDOMSVGAnimationElement {};
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(50 50)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(150 50)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(250 50)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(50 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(150 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(250 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(50 250)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(150 250)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(250 250)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(50 350)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 1.3 KiB |
|
@ -0,0 +1,209 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
class="reftest-wait"
|
||||
onload="setupSnapshot(1.5)">
|
||||
<script type="text/ecmascript"><![CDATA[
|
||||
function setupSnapshot(timeInSeconds) {
|
||||
var svg = document.documentElement;
|
||||
svg.pauseAnimations();
|
||||
svg.setCurrentTime(timeInSeconds);
|
||||
// Use setTimeout to allow SMIL to update the animation before we check
|
||||
// the values and take a snapshot
|
||||
setTimeout('checkAnimVals()');
|
||||
}
|
||||
function checkAnimVals() {
|
||||
var svg = document.documentElement;
|
||||
var paths = svg.getElementsByTagName("path");
|
||||
for (var i = 0; i < paths.length; i++) {
|
||||
var path = paths[i];
|
||||
checkAnimVal(path, path.transform.animVal, i);
|
||||
}
|
||||
svg.removeAttribute("class");
|
||||
}
|
||||
function Transform(type, angle) {
|
||||
this.type = type;
|
||||
this.angle = angle;
|
||||
}
|
||||
function checkAnimVal(path, val, index) {
|
||||
var expected = [];
|
||||
switch (index) {
|
||||
case 0:
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, 90));
|
||||
break;
|
||||
|
||||
case 1:
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, 90));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, -90));
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, 180));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, 45));
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, 45));
|
||||
break;
|
||||
|
||||
case 4:
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_TRANSLATE, 0));
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, 90));
|
||||
break;
|
||||
|
||||
case 5:
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, -90));
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, 90));
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, 90));
|
||||
break;
|
||||
|
||||
case 6:
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_TRANSLATE, 0));
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, 45));
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, 45));
|
||||
break;
|
||||
|
||||
case 7:
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_SKEWX, 20));
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_TRANSLATE, 0));
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, 45));
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, 45));
|
||||
break;
|
||||
|
||||
case 8:
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_SKEWX, 20));
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_TRANSLATE, 0));
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, 45));
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_TRANSLATE, 0));
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_TRANSLATE, 0));
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, 45));
|
||||
break;
|
||||
|
||||
case 9:
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_ROTATE, 90));
|
||||
expected.push(new Transform(SVGTransform.SVG_TRANSFORM_TRANSLATE, 0));
|
||||
break;
|
||||
}
|
||||
|
||||
var ok = true;
|
||||
if (val.numberOfItems == expected.length) {
|
||||
for (var i = 0; i < val.numberOfItems; i++) {
|
||||
var transform = val.getItem(i);
|
||||
if (transform.type != expected[i].type ||
|
||||
transform.angle != expected[i].angle) {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
path.style.visibility = 'hidden';
|
||||
}
|
||||
}
|
||||
]]></script>
|
||||
<!-- not additive -->
|
||||
<g transform="translate(50 50)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(-90)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="90" dur="1s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- to-animation: special additive -->
|
||||
<g transform="translate(150 50)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(-90)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" to="90" dur="1s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- by-animation: special additive -->
|
||||
<g transform="translate(250 50)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(-90)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" by="180" dur="1s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- normal additive: same type -->
|
||||
<g transform="translate(50 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(45)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="45" dur="1s" fill="freeze"
|
||||
additive="sum"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- normal additive: different type -->
|
||||
<g transform="translate(100 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="translate(50)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="90" dur="1s" fill="freeze"
|
||||
additive="sum"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- stacked additive: same type -->
|
||||
<g transform="translate(250 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(-90)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="90" dur="1s" fill="freeze"
|
||||
additive="sum"/>
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="90" dur="1s" fill="freeze"
|
||||
additive="sum"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- stacked additive: different types #1 -->
|
||||
<g transform="translate(0 250)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="translate(50)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="45" dur="1s" fill="freeze"
|
||||
additive="sum"/>
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="45" dur="1s" fill="freeze"
|
||||
additive="sum"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- stacked additive: different types #2 -->
|
||||
<g transform="translate(100 250) skewX(-20)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="skewX(20) translate(50)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="45" dur="1s" fill="freeze"
|
||||
additive="sum"/>
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="45" dur="1s" fill="freeze"
|
||||
additive="sum"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- stacked additive: different types #3 -->
|
||||
<g transform="translate(200 250) skewX(-20)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="skewX(20) translate(50)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="45" dur="1s" fill="freeze"
|
||||
additive="sum"/>
|
||||
<animateTransform attributeName="transform"
|
||||
type="translate" from="0" to="30" dur="1s" fill="freeze"
|
||||
additive="sum"/>
|
||||
<animateTransform attributeName="transform"
|
||||
type="translate" from="0" to="-30" dur="1s" fill="freeze"
|
||||
additive="sum"/>
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="45" dur="1s" fill="freeze"
|
||||
additive="sum"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- base value with rotation around a centre -->
|
||||
<g transform="translate(-50 300)">
|
||||
<path d="M48 100h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90 50 50)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="translate" from="0 0" to="0 -50" dur="1s" fill="freeze"
|
||||
additive="sum"/>
|
||||
</path>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 7.6 KiB |
|
@ -0,0 +1,31 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<g id="smiley">
|
||||
<circle fill="yellow" stroke="black" stroke-width="2" cx="0" cy="0"
|
||||
r="40"/>
|
||||
<circle fill="white" stroke="black" stroke-width="1" cx="-14" cy="-14"
|
||||
r="14"/>
|
||||
<circle fill="white" stroke="black" stroke-width="1" cx="14" cy="-14"
|
||||
r="14"/>
|
||||
<circle cx="-10" cy="-14" r="4"/>
|
||||
<circle cx="10" cy="-14" r="4"/>
|
||||
<path d="m-11 14a13,13 0 0,0 22,0" fill="none" stroke="black"/>
|
||||
</g>
|
||||
</defs>
|
||||
<g transform="translate(50 50)">
|
||||
<use xlink:href="#smiley"/>
|
||||
</g>
|
||||
<g transform="translate(150 50)">
|
||||
<use xlink:href="#smiley"/>
|
||||
</g>
|
||||
<g transform="translate(250 50)">
|
||||
<use xlink:href="#smiley"/>
|
||||
</g>
|
||||
<g transform="translate(50 150)">
|
||||
<use xlink:href="#smiley"/>
|
||||
</g>
|
||||
<g transform="translate(150 150)">
|
||||
<use xlink:href="#smiley"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 946 B |
|
@ -0,0 +1,64 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="setTimeAndSnapshot(1, true)">
|
||||
<script xlink:href="../smil-util.js" type="text/javascript"/>
|
||||
<defs>
|
||||
<g id="smiley">
|
||||
<circle fill="yellow" stroke="black" stroke-width="2" cx="0" cy="0"
|
||||
r="40"/>
|
||||
<circle fill="white" stroke="black" stroke-width="1" cx="-14" cy="-14"
|
||||
r="14"/>
|
||||
<circle fill="white" stroke="black" stroke-width="1" cx="14" cy="-14"
|
||||
r="14"/>
|
||||
<circle cx="-10" cy="-14" r="4"/>
|
||||
<circle cx="10" cy="-14" r="4"/>
|
||||
<path d="m-11 14a13,13 0 0,0 22,0" fill="none" stroke="black"/>
|
||||
</g>
|
||||
</defs>
|
||||
<!-- translation -->
|
||||
<g transform="translate(0 50)">
|
||||
<use xlink:href="#smiley">
|
||||
<animateTransform attributeName="transform" attributeType="XML"
|
||||
type="translate" fill="freeze" dur="2s" calcMode="paced"
|
||||
values="-5 -10; 35 20; 95 -60"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- rotation -->
|
||||
<g transform="translate(150 50) rotate(-90)">
|
||||
<use xlink:href="#smiley">
|
||||
<animateTransform attributeName="transform" attributeType="XML"
|
||||
type="rotate" fill="freeze" dur="2s" calcMode="paced"
|
||||
values="20 10 10; 40 -15 25; 160 21 -35"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- skewY -->
|
||||
<g transform="translate(250 50) skewY(-30)">
|
||||
<use xlink:href="#smiley">
|
||||
<animateTransform attributeName="transform" attributeType="XML"
|
||||
type="skewY" fill="freeze" dur="2s" calcMode="paced"
|
||||
values="10; 40; 50"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- scale -->
|
||||
<g transform="translate(50 150) scale(0.5)">
|
||||
<use xlink:href="#smiley">
|
||||
<animateTransform attributeName="transform" attributeType="XML"
|
||||
type="scale" fill="freeze" dur="2s" calcMode="paced"
|
||||
values="-4 -2.5; 4 3.5; 8 0.5"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- to-animation
|
||||
|
||||
You can't have to-animation with a paced calcMode. This test should just
|
||||
produce regular to-animation without any assertions. This is a white-box
|
||||
test.
|
||||
-->
|
||||
<g transform="translate(100 150)">
|
||||
<use xlink:href="#smiley">
|
||||
<animateTransform attributeName="transform" attributeType="XML"
|
||||
type="translate" fill="freeze" dur="2s" calcMode="paced"
|
||||
to="100"/>
|
||||
</use>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 2.2 KiB |
|
@ -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
|
|
@ -0,0 +1,60 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="setTimeAndSnapshot(1, true)">
|
||||
<script xlink:href="../smil-util.js" type="text/javascript"/>
|
||||
<g transform="translate(50 50) rotate(90)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="0" dur="4s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(150 50)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="90" dur="1s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(250 50)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="180" dur="2s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(50 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="270" dur="3s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(150 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="360" dur="4s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(250 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="540" dur="6s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(50 250)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="3600" dur="40s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(150 250)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="-270" dur="1s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(250 250)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="-540" dur="2s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 2.3 KiB |
|
@ -0,0 +1,60 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="setTimeAndSnapshot(1, true)">
|
||||
<script xlink:href="../smil-util.js" type="text/javascript"/>
|
||||
<g transform="translate(44 0) rotate(90 6 50)">
|
||||
<path d="M4 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0 6 50" to="0 6 50" dur="4s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(144 0)">
|
||||
<path d="M4 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0,6,50" to="90 6 50" dur="1s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(244,0)">
|
||||
<path d="M4 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0 6 50" to="180,6,50" dur="2s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(44,100)">
|
||||
<path d="M4 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0,6,50" to="270,6,50" dur="3s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(144,100)">
|
||||
<path d="M4 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0 6 50" to="360 6 50" dur="4s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(244,100)">
|
||||
<path d="M4 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0 6 50" to="540 6 50" dur="6s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(44,200)">
|
||||
<path d="M4 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0 6 50" to="3600 6 50" dur="40s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(144,200)">
|
||||
<path d="M4 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0 6 50" to="-270 6 50" dur="1s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(244,200)">
|
||||
<path d="M4 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0 6 50" to="-540 6 50" dur="2s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 2.3 KiB |
|
@ -0,0 +1,60 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="setTimeAndSnapshot(1, true)">
|
||||
<script xlink:href="../smil-util.js" type="text/javascript"/>
|
||||
<g transform="translate(0 0) rotate(90 50 50)">
|
||||
<path d="M48 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0 0 50" to="0 200 50" dur="4s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(100 0)">
|
||||
<path d="M48 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0 0 50" to="90 50 50" dur="1s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(200 0)">
|
||||
<path d="M48 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0 0 50" to="180 100 50" dur="2s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(0 100)">
|
||||
<path d="M48 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0 0 50" to="270 150 50" dur="3s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(100 100)">
|
||||
<path d="M48 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0 0 50" to="360 200 50" dur="4s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(200 100)">
|
||||
<path d="M48 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0 0 50" to="540 300 50" dur="6s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(0 200)">
|
||||
<path d="M48 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0 0 50" to="3600 2000 50" dur="40s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(100 200)">
|
||||
<path d="M48 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0 0 50" to="-270 50 50" dur="1s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<g transform="translate(200 200)">
|
||||
<path d="M48 100h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0 0 50" to="-540 100 50" dur="2s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 2.4 KiB |
|
@ -0,0 +1,79 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="setTimeAndSnapshot(1, true)">
|
||||
<script xlink:href="../smil-util.js" type="text/javascript"/>
|
||||
<!-- no animation -->
|
||||
<g transform="translate(50 50) rotate(90)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"/>
|
||||
</g>
|
||||
<!-- accumulate: sum -->
|
||||
<g transform="translate(150 50)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="45" dur="0.5s" fill="freeze"
|
||||
repeatCount="4" accumulate="sum"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- accumulate: none -->
|
||||
<g transform="translate(250 50)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="270" dur="0.75s" fill="freeze"
|
||||
repeatCount="2"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- additive: replace -->
|
||||
<g transform="translate(50 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(-90)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="180" dur="2s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- additive: sum (adding to base value) -->
|
||||
<g transform="translate(150 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(-90)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="270" dur="1.5s" fill="freeze"
|
||||
additive="sum"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- additive: sum (adding to other animations) -->
|
||||
<g transform="translate(250 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="60" dur="2s" fill="freeze"/>
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="60" dur="2s" fill="freeze"
|
||||
additive="sum"/>
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="60" dur="2s" fill="freeze"
|
||||
additive="sum"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- to animation -->
|
||||
<g transform="translate(50 250)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(45)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" to="135" dur="2s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- by animation -->
|
||||
<g transform="translate(150 250)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(45)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" by="90" dur="2s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- values animation -->
|
||||
<g transform="translate(250 250)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" values="0; 135; 0" dur="1.5s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 2.9 KiB |
|
@ -0,0 +1,86 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="setTimeAndSnapshot(1, true)">
|
||||
<script xlink:href="../smil-util.js" type="text/javascript"/>
|
||||
<!-- Tests to-animation behaviour for a lot of undefined situations.
|
||||
SVG 1.1 doesn't define what should happen here but the behaviour we
|
||||
expect is based on other browsers. -->
|
||||
<!-- to animation: rotation from base value -90 to final value 180 -->
|
||||
<g transform="translate(50 50)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(-90)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" to="180" dur="1.5s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- to animation: rotation from base value -810 to final value 990 -->
|
||||
<g transform="translate(150 50)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(-810)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" to="990" dur="2s" fill="freeze"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- to animation: rotation from base value -180 to final value 90 but with
|
||||
other animations combined.
|
||||
|
||||
What happens here is that the rotation animation can't interpolate from
|
||||
the base value as it's not a rotation transformation, so instead it
|
||||
assumes an underlying zero matrix as the base value. (see next comment)
|
||||
-->
|
||||
<g transform="translate(250 50)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(-90) translate(0 50) scale(2)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" to="180" dur="2s" fill="freeze" additive="sum"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- to animation: rotate and scale
|
||||
|
||||
Here again the scale animation can't interpolate from its base value
|
||||
which is of a different type so it assumes a zero matrix NOT an identity
|
||||
matrix (this is what the SVG WG have decided in the SVGT1.2 Tiny test
|
||||
suite).
|
||||
-->
|
||||
<g transform="translate(50 150) rotate(90)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="scale(2)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" to="180" dur="1s" fill="freeze" additive="sum"/>
|
||||
<animateTransform attributeName="transform"
|
||||
type="scale" to="2" dur="2s" fill="freeze" additive="sum"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- to animation: translate and rotate
|
||||
|
||||
Likewise here we end up rotating from 0 to 180 because we can't
|
||||
interpolate from the underlying translation transformation.
|
||||
-->
|
||||
<g transform="translate(150 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(-90) translate(0 50) scale(2)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="translate" to="0" dur="1s" fill="freeze" additive="sum"/>
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" to="180" dur="2s" fill="freeze" additive="sum"/>
|
||||
</path>
|
||||
</g>
|
||||
<!-- The following are from the reference image -->
|
||||
<g transform="translate(250 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(50 250)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(150 250)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(250 250)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 3.5 KiB |
|
@ -0,0 +1,38 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(50 50)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(150 50)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(250 50)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(50 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(150 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(250 150)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(50 250)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(150 250)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
<g transform="translate(250 250)">
|
||||
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue"
|
||||
transform="rotate(90)"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 1.2 KiB |
|
@ -0,0 +1,38 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<linearGradient id="grad">
|
||||
<stop offset="5%" stop-color="#F66"/>
|
||||
<stop offset="95%" stop-color="#FF6"/>
|
||||
</linearGradient>
|
||||
<circle fill="url(#grad)" stroke="black" stroke-width="1" cx="0" cy="0"
|
||||
r="20" id="circle"/>
|
||||
</defs>
|
||||
<g transform="translate(50 50)">
|
||||
<use xlink:href="#circle" transform="scale(2)"/>
|
||||
</g>
|
||||
<g transform="translate(150 50)">
|
||||
<use xlink:href="#circle" transform="scale(2)"/>
|
||||
</g>
|
||||
<g transform="translate(250 50)">
|
||||
<use xlink:href="#circle" transform="scale(2)"/>
|
||||
</g>
|
||||
<g transform="translate(50 150)">
|
||||
<use xlink:href="#circle" transform="scale(2)"/>
|
||||
</g>
|
||||
<g transform="translate(150 150)">
|
||||
<use xlink:href="#circle" transform="scale(2)"/>
|
||||
</g>
|
||||
<g transform="translate(250 150)">
|
||||
<use xlink:href="#circle" transform="scale(2)"/>
|
||||
</g>
|
||||
<g transform="translate(50 250)">
|
||||
<use xlink:href="#circle" transform="scale(2)"/>
|
||||
</g>
|
||||
<g transform="translate(150 250)">
|
||||
<use xlink:href="#circle" transform="scale(2)"/>
|
||||
</g>
|
||||
<g transform="translate(250 250)">
|
||||
<use xlink:href="#circle" transform="scale(2)"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 1.2 KiB |
|
@ -0,0 +1,108 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="setTimeAndSnapshot(1, true)">
|
||||
<script xlink:href="../smil-util.js" type="text/javascript"/>
|
||||
<defs>
|
||||
<linearGradient id="grad">
|
||||
<stop offset="5%" stop-color="#F66"/>
|
||||
<stop offset="95%" stop-color="#FF6"/>
|
||||
</linearGradient>
|
||||
<circle fill="url(#grad)" stroke="black" stroke-width="1" cx="0" cy="0"
|
||||
r="20" id="circle"/>
|
||||
</defs>
|
||||
<!-- to animation
|
||||
|
||||
This should interpolate from 0 (not 1) to 4 to match the behaviour
|
||||
required by the SVGT1.2 test suite and Opera's behaviour.
|
||||
-->
|
||||
<g transform="translate(50 50)">
|
||||
<use xlink:href="#circle">
|
||||
<animateTransform attributeName="transform"
|
||||
type="scale" to="4" dur="2s" fill="freeze"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- from-to animation -->
|
||||
<g transform="translate(150 50)">
|
||||
<use xlink:href="#circle">
|
||||
<animateTransform attributeName="transform"
|
||||
type="scale" from="-5" to="9" dur="2s" fill="freeze"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- negative to-animation
|
||||
|
||||
Should go from 0 to -4 over 2s, therefore at t=1s, the scale factor
|
||||
should be -2, so we add a rotation animation to correct the gradient
|
||||
-->
|
||||
<g transform="translate(250 50)">
|
||||
<use xlink:href="#circle">
|
||||
<animateTransform attributeName="transform"
|
||||
type="scale" to="-4" dur="2s" fill="freeze"/>
|
||||
<animateTransform attributeName="transform"
|
||||
type="rotate" from="0" to="360" dur="2s" fill="freeze" additive="sum"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- by animation
|
||||
|
||||
The behaviour at this point is not clear. The definition of by-animation
|
||||
is:
|
||||
|
||||
"simple animation in which the animation function is defined to offset
|
||||
the underlying value for the attribute, using a delta that varies over
|
||||
the course of the simple duration, starting from a delta of 0 and ending
|
||||
with the delta specified with the by attribute." (SMILANIM 3.2.2)
|
||||
|
||||
Therefore it might seem like by-animation of by="1" means to ADD to the
|
||||
underlying scale factor. Furthermore, the underlying scale factor when
|
||||
not otherwise specified might seemt to be 1, but the SVG WG have decided
|
||||
it's 0. This is inconsistent with the definition of addition for
|
||||
animateTransform (post-multiplication of matrices) but it is the
|
||||
behaviour required by SVGT1.2 test suite and used by Opera.
|
||||
|
||||
The following animation should go from 0 to 4, over 2s so at t=1s, the
|
||||
scale factor should be 2.
|
||||
-->
|
||||
<g transform="translate(50 150)">
|
||||
<use xlink:href="#circle">
|
||||
<animateTransform attributeName="transform"
|
||||
type="scale" by="4" dur="2s" fill="freeze"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- by animation #2 -->
|
||||
<g transform="translate(150 150)">
|
||||
<use xlink:href="#circle" transform="scale(4)">
|
||||
<animateTransform attributeName="transform"
|
||||
type="scale" by="1" dur="2s" fill="freeze" additive="sum"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- from-by animation -->
|
||||
<g transform="translate(250 150)">
|
||||
<use xlink:href="#circle">
|
||||
<animateTransform attributeName="transform"
|
||||
type="scale" from="2" by="0" dur="2s" fill="freeze"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- values animation -->
|
||||
<g transform="translate(50 250)">
|
||||
<use xlink:href="#circle">
|
||||
<animateTransform attributeName="transform"
|
||||
type="scale" values="0; 10; 2; 5; -1" dur="2s" fill="freeze"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- repetition -->
|
||||
<g transform="translate(150 250)">
|
||||
<use xlink:href="#circle">
|
||||
<animateTransform attributeName="transform" type="scale" from="0"
|
||||
to="0.6" dur="0.3s" repeatCount="4" accumulate="sum"
|
||||
fill="freeze"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- repeated to-animation (should NOT accumulate) -->
|
||||
<g transform="translate(250 250)">
|
||||
<use xlink:href="#circle">
|
||||
<animateTransform attributeName="transform" type="scale"
|
||||
to="6" dur="0.75" repeatCount="2" accumulate="sum"
|
||||
fill="freeze"/>
|
||||
</use>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 3.9 KiB |
|
@ -0,0 +1,43 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<g id="smiley">
|
||||
<circle fill="yellow" stroke="black" stroke-width="2" cx="0" cy="0"
|
||||
r="40"/>
|
||||
<circle fill="white" stroke="black" stroke-width="1" cx="-14" cy="-14"
|
||||
r="14"/>
|
||||
<circle fill="white" stroke="black" stroke-width="1" cx="14" cy="-14"
|
||||
r="14"/>
|
||||
<circle cx="-10" cy="-14" r="4"/>
|
||||
<circle cx="10" cy="-14" r="4"/>
|
||||
<path d="m-11 14a13,13 0 0,0 22,0" fill="none" stroke="black"/>
|
||||
</g>
|
||||
</defs>
|
||||
<g transform="translate(50 50)">
|
||||
<use xlink:href="#smiley" transform="skewX(30)"/>
|
||||
</g>
|
||||
<g transform="translate(150 50)">
|
||||
<use xlink:href="#smiley" transform="skewX(30)"/>
|
||||
</g>
|
||||
<g transform="translate(250 50)">
|
||||
<use xlink:href="#smiley" transform="skewX(30)"/>
|
||||
</g>
|
||||
<g transform="translate(50 150)">
|
||||
<use xlink:href="#smiley" transform="skewX(30)"/>
|
||||
</g>
|
||||
<g transform="translate(150 150)">
|
||||
<use xlink:href="#smiley" transform="skewX(30)"/>
|
||||
</g>
|
||||
<g transform="translate(250 150)">
|
||||
<use xlink:href="#smiley" transform="skewX(30)"/>
|
||||
</g>
|
||||
<g transform="translate(50 250)">
|
||||
<use xlink:href="#smiley" transform="skewX(30)"/>
|
||||
</g>
|
||||
<g transform="translate(150 250)">
|
||||
<use xlink:href="#smiley" transform="skewX(30)"/>
|
||||
</g>
|
||||
<g transform="translate(250 250)">
|
||||
<use xlink:href="#smiley" transform="skewX(30)"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 1.4 KiB |
|
@ -0,0 +1,86 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
class="reftest-wait"
|
||||
onload="setTimeAndSnapshot(1, true)">
|
||||
<script xlink:href="../smil-util.js" type="text/javascript"/>
|
||||
<defs>
|
||||
<g id="smiley">
|
||||
<circle fill="yellow" stroke="black" stroke-width="2" cx="0" cy="0"
|
||||
r="40"/>
|
||||
<circle fill="white" stroke="black" stroke-width="1" cx="-14" cy="-14"
|
||||
r="14"/>
|
||||
<circle fill="white" stroke="black" stroke-width="1" cx="14" cy="-14"
|
||||
r="14"/>
|
||||
<circle cx="-10" cy="-14" r="4"/>
|
||||
<circle cx="10" cy="-14" r="4"/>
|
||||
<path d="m-11 14a13,13 0 0,0 22,0" fill="none" stroke="black"/>
|
||||
</g>
|
||||
</defs>
|
||||
<!-- from-to animation -->
|
||||
<g transform="translate(50 50)">
|
||||
<use xlink:href="#smiley">
|
||||
<animateTransform attributeName="transform" attributeType="XML"
|
||||
type="skewX" fill="freeze" from="-30" to="90" dur="2s"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- from-by animation -->
|
||||
<g transform="translate(150 50)">
|
||||
<use xlink:href="#smiley">
|
||||
<animateTransform attributeName="transform" attributeType="XML"
|
||||
type="skewX" fill="freeze" from="60" by="-60" dur="2s"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- by animation -->
|
||||
<g transform="translate(250 50) skewX(-15)">
|
||||
<use xlink:href="#smiley" transform="skewX(15)">
|
||||
<animateTransform attributeName="transform" attributeType="XML"
|
||||
type="skewX" fill="freeze" by="60" dur="2s"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- to animation -->
|
||||
<g transform="translate(50 150)">
|
||||
<use xlink:href="#smiley" transform="skewX(15)">
|
||||
<animateTransform attributeName="transform" attributeType="XML"
|
||||
type="skewX" fill="freeze" to="45" dur="2s"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- values animation -->
|
||||
<g transform="translate(150 150)">
|
||||
<use xlink:href="#smiley">
|
||||
<animateTransform attributeName="transform" attributeType="XML"
|
||||
type="skewX" fill="freeze" values="10; 40; 20; 60" dur="2s"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- additive -->
|
||||
<g transform="translate(250 150)">
|
||||
<use xlink:href="#smiley" transform="skewY(-30)">
|
||||
<animateTransform attributeName="transform" attributeType="XML"
|
||||
type="skewY" fill="freeze" to="30" dur="2s"/>
|
||||
<animateTransform attributeName="transform" attributeType="XML"
|
||||
type="skewX" fill="freeze" from="-30" to="90" dur="2s" additive="sum"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- accumulate: none -->
|
||||
<g transform="translate(50 250)">
|
||||
<use xlink:href="#smiley">
|
||||
<animateTransform attributeName="transform" attributeType="XML"
|
||||
type="skewX" fill="freeze" from="20" to="50" dur="0.75s"
|
||||
repeatCount="3"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- accumulate: sum -->
|
||||
<g transform="translate(150 250)">
|
||||
<use xlink:href="#smiley">
|
||||
<animateTransform attributeName="transform" attributeType="XML"
|
||||
type="skewX" fill="freeze" from="0" to="22.5" dur="0.75"
|
||||
accumulate="sum" repeatCount="3"/>
|
||||
</use>
|
||||
</g>
|
||||
<!-- angles > 360 -->
|
||||
<g transform="translate(250 250)">
|
||||
<use xlink:href="#smiley">
|
||||
<animateTransform attributeName="transform" attributeType="XML"
|
||||
type="skewX" fill="freeze" from="-690" to="750" dur="2s"/>
|
||||
</use>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 3.1 KiB |