Bug 602759 part 7 - Refactor nsSVGAnimatedTransformList into SVGAnimatedTransformList and DOMSVGAnimatedTransformList and incorporate nsSVGTransformSMILAttr; r=jwatt

--HG--
rename : content/svg/content/src/nsSVGAnimatedTransformList.cpp => content/svg/content/src/DOMSVGAnimatedTransformList.cpp
rename : content/svg/content/src/nsSVGAnimatedTransformList.h => content/svg/content/src/DOMSVGAnimatedTransformList.h
This commit is contained in:
Brian Birtles 2011-09-25 22:04:31 +01:00
parent 722c1262b1
commit bdc7e4ee3e
10 changed files with 846 additions and 821 deletions

View File

@ -0,0 +1,176 @@
/* -*- 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
* Crocodile Clips Ltd..
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
*
* 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 "DOMSVGAnimatedTransformList.h"
#include "DOMSVGTransformList.h"
#include "SVGAnimatedTransformList.h"
#include "nsSVGAttrTearoffTable.h"
namespace mozilla {
static
nsSVGAttrTearoffTable<SVGAnimatedTransformList,DOMSVGAnimatedTransformList>
sSVGAnimatedTransformListTearoffTable;
NS_SVG_VAL_IMPL_CYCLE_COLLECTION(DOMSVGAnimatedTransformList, mElement)
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGAnimatedTransformList)
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGAnimatedTransformList)
} // namespace mozilla
DOMCI_DATA(SVGAnimatedTransformList, mozilla::DOMSVGAnimatedTransformList)
namespace mozilla {
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGAnimatedTransformList)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedTransformList)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimatedTransformList)
NS_INTERFACE_MAP_END
//----------------------------------------------------------------------
// nsIDOMSVGAnimatedTransformList methods:
/* readonly attribute nsIDOMSVGTransformList baseVal; */
NS_IMETHODIMP
DOMSVGAnimatedTransformList::GetBaseVal(nsIDOMSVGTransformList** aBaseVal)
{
if (!mBaseVal) {
mBaseVal = new DOMSVGTransformList(this, InternalAList().GetBaseValue());
}
NS_ADDREF(*aBaseVal = mBaseVal);
return NS_OK;
}
/* readonly attribute nsIDOMSVGTransformList animVal; */
NS_IMETHODIMP
DOMSVGAnimatedTransformList::GetAnimVal(nsIDOMSVGTransformList** aAnimVal)
{
if (!mAnimVal) {
mAnimVal = new DOMSVGTransformList(this, InternalAList().GetAnimValue());
}
NS_ADDREF(*aAnimVal = mAnimVal);
return NS_OK;
}
/* static */ already_AddRefed<DOMSVGAnimatedTransformList>
DOMSVGAnimatedTransformList::GetDOMWrapper(SVGAnimatedTransformList *aList,
nsSVGElement *aElement)
{
DOMSVGAnimatedTransformList *wrapper =
sSVGAnimatedTransformListTearoffTable.GetTearoff(aList);
if (!wrapper) {
wrapper = new DOMSVGAnimatedTransformList(aElement);
sSVGAnimatedTransformListTearoffTable.AddTearoff(aList, wrapper);
}
NS_ADDREF(wrapper);
return wrapper;
}
/* static */ DOMSVGAnimatedTransformList*
DOMSVGAnimatedTransformList::GetDOMWrapperIfExists(
SVGAnimatedTransformList *aList)
{
return sSVGAnimatedTransformListTearoffTable.GetTearoff(aList);
}
DOMSVGAnimatedTransformList::~DOMSVGAnimatedTransformList()
{
// Script no longer has any references to us, to our base/animVal objects, or
// to any of their list items.
sSVGAnimatedTransformListTearoffTable.RemoveTearoff(&InternalAList());
}
void
DOMSVGAnimatedTransformList::InternalBaseValListWillChangeLengthTo(
PRUint32 aNewLength)
{
// When the number of items in our internal counterpart's baseVal changes,
// we MUST keep our baseVal in sync. If we don't, script will either see a
// list that is too short and be unable to access indexes that should be
// valid, or else, MUCH WORSE, script will see a list that is too long and be
// able to access "items" at indexes that are out of bounds (read/write to
// bad memory)!!
nsRefPtr<DOMSVGAnimatedTransformList> kungFuDeathGrip;
if (mBaseVal) {
if (aNewLength < mBaseVal->Length()) {
// InternalListLengthWillChange might clear last reference to |this|.
// Retain a temporary reference to keep from dying before returning.
kungFuDeathGrip = this;
}
mBaseVal->InternalListLengthWillChange(aNewLength);
}
// If our attribute is not animating, then our animVal mirrors our baseVal
// and we must sync its length too. (If our attribute is animating, then the
// SMIL engine takes care of calling InternalAnimValListWillChangeLengthTo()
// if necessary.)
if (!IsAnimating()) {
InternalAnimValListWillChangeLengthTo(aNewLength);
}
}
void
DOMSVGAnimatedTransformList::InternalAnimValListWillChangeLengthTo(
PRUint32 aNewLength)
{
if (mAnimVal) {
mAnimVal->InternalListLengthWillChange(aNewLength);
}
}
PRBool
DOMSVGAnimatedTransformList::IsAnimating() const
{
return InternalAList().IsAnimating();
}
SVGAnimatedTransformList&
DOMSVGAnimatedTransformList::InternalAList()
{
return *mElement->GetAnimatedTransformList();
}
const SVGAnimatedTransformList&
DOMSVGAnimatedTransformList::InternalAList() const
{
return *mElement->GetAnimatedTransformList();
}
} // namespace mozilla

View File

@ -0,0 +1,155 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SVG project.
*
* The Initial Developer of the Original Code is
* Crocodile Clips Ltd..
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
*
* 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 MOZILLA_DOMSVGANIMATEDTRANSFORMLIST_H__
#define MOZILLA_DOMSVGANIMATEDTRANSFORMLIST_H__
#include "nsIDOMSVGAnimTransformList.h"
#include "nsCycleCollectionParticipant.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
class nsSVGElement;
namespace mozilla {
class SVGAnimatedTransformList;
class SVGTransformList;
class DOMSVGTransformList;
/**
* Class DOMSVGAnimatedTransformList
*
* This class is used to create the DOM tearoff objects that wrap internal
* SVGAnimatedTransformList objects.
*
* See the architecture comment in DOMSVGAnimatedLengthList.h (that's
* LENGTH list). The comment for that class largly applies to this one too
* and will go a long way to helping you understand the architecture here.
*
* This class is strongly intertwined with DOMSVGTransformList and
* DOMSVGTransform.
* Our DOMSVGTransformList base and anim vals are friends and take care of
* nulling out our pointers to them when they die (making our pointers to them
* true weak refs).
*/
class DOMSVGAnimatedTransformList : public nsIDOMSVGAnimatedTransformList
{
friend class DOMSVGTransformList;
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGAnimatedTransformList)
NS_DECL_NSIDOMSVGANIMATEDTRANSFORMLIST
/**
* Factory method to create and return a DOMSVGAnimatedTransformList wrapper
* for a given internal SVGAnimatedTransformList object. The factory takes
* care of caching the object that it returns so that the same object can be
* returned for the given SVGAnimatedTransformList each time it is requested.
* The cached object is only removed from the cache when it is destroyed due
* to there being no more references to it or to any of its descendant
* objects. If that happens, any subsequent call requesting the DOM wrapper
* for the SVGAnimatedTransformList will naturally result in a new
* DOMSVGAnimatedTransformList being returned.
*/
static already_AddRefed<DOMSVGAnimatedTransformList>
GetDOMWrapper(SVGAnimatedTransformList *aList, nsSVGElement *aElement);
/**
* This method returns the DOMSVGAnimatedTransformList wrapper for an internal
* SVGAnimatedTransformList object if it currently has a wrapper. If it does
* not, then nsnull is returned.
*/
static DOMSVGAnimatedTransformList*
GetDOMWrapperIfExists(SVGAnimatedTransformList *aList);
/**
* Called by internal code to notify us when we need to sync the length of
* our baseVal DOM list with its internal list. This is called just prior to
* the length of the internal baseVal list being changed so that any DOM list
* items that need to be removed from the DOM list can first get their values
* from their internal counterpart.
*
* The only time this method could fail is on OOM when trying to increase the
* length of the DOM list. If that happens then this method simply clears the
* list and returns. Callers just proceed as normal, and we simply accept
* that the DOM list will be empty (until successfully set to a new value).
*/
void InternalBaseValListWillChangeLengthTo(PRUint32 aNewLength);
void InternalAnimValListWillChangeLengthTo(PRUint32 aNewLength);
/**
* Returns true if our attribute is animating (in which case our animVal is
* not simply a mirror of our baseVal).
*/
PRBool IsAnimating() const;
private:
/**
* Only our static GetDOMWrapper() factory method may create objects of our
* type.
*/
DOMSVGAnimatedTransformList(nsSVGElement *aElement)
: mBaseVal(nsnull)
, mAnimVal(nsnull)
, mElement(aElement)
{}
~DOMSVGAnimatedTransformList();
/// Get a reference to this DOM wrapper object's internal counterpart.
SVGAnimatedTransformList& InternalAList();
const SVGAnimatedTransformList& InternalAList() const;
// Weak refs to our DOMSVGTransformList baseVal/animVal objects. These objects
// are friends and take care of clearing these pointers when they die, making
// these true weak references.
DOMSVGTransformList *mBaseVal;
DOMSVGTransformList *mAnimVal;
// Strong ref to our element to keep it alive. We hold this not only for
// ourself, but also for our base/animVal and all of their items.
nsRefPtr<nsSVGElement> mElement;
};
} // namespace mozilla
#endif // MOZILLA_DOMSVGANIMATEDTRANSFORMLIST_H__

View File

@ -51,6 +51,7 @@ LIBXUL_LIBRARY = 1
CPPSRCS = \
DOMSVGAnimatedLengthList.cpp \
DOMSVGAnimatedNumberList.cpp \
DOMSVGAnimatedTransformList.cpp \
DOMSVGLength.cpp \
DOMSVGLengthList.cpp \
DOMSVGMatrix.cpp \
@ -67,7 +68,6 @@ CPPSRCS = \
nsSVGAElement.cpp \
nsSVGAltGlyphElement.cpp \
nsSVGAngle.cpp \
nsSVGAnimatedTransformList.cpp \
nsSVGBoolean.cpp \
nsSVGCircleElement.cpp \
nsSVGClass.cpp \
@ -129,6 +129,7 @@ CPPSRCS = \
SVGAnimatedPathSegList.cpp \
SVGAnimatedPointList.cpp \
SVGAnimatedPreserveAspectRatio.cpp \
SVGAnimatedTransformList.cpp \
SVGLength.cpp \
SVGLengthList.cpp \
SVGNumberList.cpp \
@ -147,7 +148,6 @@ CPPSRCS += nsSVGAnimateElement.cpp \
nsSVGMpathElement.cpp \
nsSVGSetElement.cpp \
nsSVGTransformSMILType.cpp \
nsSVGTransformSMILAttr.cpp \
SVGIntegerPairSMILType.cpp \
SVGLengthListSMILType.cpp \
SVGMotionSMILType.cpp \

View File

@ -0,0 +1,355 @@
/* -*- 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 Mozilla SVG Project code.
*
* The Initial Developer of the Original Code is the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either 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 "SVGAnimatedTransformList.h"
#include "DOMSVGAnimatedTransformList.h"
#ifdef MOZ_SMIL
#include "nsSMILValue.h"
#include "SVGTransform.h"
#include "SVGTransformListSMILType.h"
#include "nsSVGUtils.h"
#include "prdtoa.h"
#endif // MOZ_SMIL
namespace mozilla {
nsresult
SVGAnimatedTransformList::SetBaseValueString(const nsAString& aValue)
{
SVGTransformList newBaseValue;
nsresult rv = newBaseValue.SetValueFromString(aValue);
if (NS_FAILED(rv)) {
return rv;
}
DOMSVGAnimatedTransformList *domWrapper =
DOMSVGAnimatedTransformList::GetDOMWrapperIfExists(this);
if (domWrapper) {
// We must send this notification *before* changing mBaseVal! If the length
// of our baseVal is being reduced, our baseVal's DOM wrapper list may have
// to remove DOM items from itself, and any removed DOM items need to copy
// their internal counterpart values *before* we change them.
//
domWrapper->InternalBaseValListWillChangeLengthTo(newBaseValue.Length());
}
// We don't need to call DidChange* here - we're only called by
// nsSVGElement::ParseAttribute under nsGenericElement::SetAttr,
// which takes care of notifying.
rv = mBaseVal.CopyFrom(newBaseValue);
if (NS_FAILED(rv) && domWrapper) {
// Attempting to increase mBaseVal's length failed - reduce domWrapper
// back to the same length:
domWrapper->InternalBaseValListWillChangeLengthTo(mBaseVal.Length());
} else {
mIsAttrSet = PR_TRUE;
}
return rv;
}
void
SVGAnimatedTransformList::ClearBaseValue()
{
DOMSVGAnimatedTransformList *domWrapper =
DOMSVGAnimatedTransformList::GetDOMWrapperIfExists(this);
if (domWrapper) {
// We must send this notification *before* changing mBaseVal! (See above.)
domWrapper->InternalBaseValListWillChangeLengthTo(0);
}
mBaseVal.Clear();
mIsAttrSet = PR_FALSE;
// Caller notifies
}
nsresult
SVGAnimatedTransformList::SetAnimValue(const SVGTransformList& aValue,
nsSVGElement *aElement)
{
DOMSVGAnimatedTransformList *domWrapper =
DOMSVGAnimatedTransformList::GetDOMWrapperIfExists(this);
if (domWrapper) {
// A new animation may totally change the number of items in the animVal
// list, replacing what was essentially a mirror of the baseVal list, or
// else replacing and overriding an existing animation. When this happens
// we must try and keep our animVal's DOM wrapper in sync (see the comment
// in DOMSVGAnimatedTransformList::InternalBaseValListWillChangeLengthTo).
//
// It's not possible for us to reliably distinguish between calls to this
// method that are setting a new sample for an existing animation, and
// calls that are setting the first sample of an animation that will
// override an existing animation. Happily it's cheap to just blindly
// notify our animVal's DOM wrapper of its internal counterpart's new value
// each time this method is called, so that's what we do.
//
// Note that we must send this notification *before* setting or changing
// mAnimVal! (See the comment in SetBaseValueString above.)
//
domWrapper->InternalAnimValListWillChangeLengthTo(aValue.Length());
}
if (!mAnimVal) {
mAnimVal = new SVGTransformList();
}
nsresult rv = mAnimVal->CopyFrom(aValue);
if (NS_FAILED(rv)) {
// OOM. We clear the animation, and, importantly, ClearAnimValue() ensures
// that mAnimVal and its DOM wrapper (if any) will have the same length!
ClearAnimValue(aElement);
return rv;
}
aElement->DidAnimateTransformList();
return NS_OK;
}
void
SVGAnimatedTransformList::ClearAnimValue(nsSVGElement *aElement)
{
DOMSVGAnimatedTransformList *domWrapper =
DOMSVGAnimatedTransformList::GetDOMWrapperIfExists(this);
if (domWrapper) {
// When all animation ends, animVal simply mirrors baseVal, which may have
// a different number of items to the last active animated value. We must
// keep the length of our animVal's DOM wrapper list in sync, and again we
// must do that before touching mAnimVal. See comments above.
//
domWrapper->InternalAnimValListWillChangeLengthTo(mBaseVal.Length());
}
mAnimVal = nsnull;
aElement->DidAnimateTransformList();
}
PRBool
SVGAnimatedTransformList::IsExplicitlySet() const
{
// Like other methods of this name, we need to know when a transform value has
// been explicitly set.
//
// There are three ways an animated list can become set:
// 1) Markup -- we set mIsAttrSet to PR_TRUE on any successful call to
// SetBaseValueString and clear it on ClearBaseValue (as called by
// nsSVGElement::UnsetAttr or a failed nsSVGElement::ParseAttribute)
// 2) DOM call -- simply fetching the baseVal doesn't mean the transform value
// has been set. It is set if that baseVal has one or more transforms in
// the list.
// 3) Animation -- which will cause the mAnimVal member to be allocated
return mIsAttrSet || !mBaseVal.IsEmpty() || mAnimVal;
}
#ifdef MOZ_SMIL
nsISMILAttr*
SVGAnimatedTransformList::ToSMILAttr(nsSVGElement* aSVGElement)
{
return new SMILAnimatedTransformList(this, aSVGElement);
}
nsresult
SVGAnimatedTransformList::SMILAnimatedTransformList::ValueFromString(
const nsAString& aStr,
const nsISMILAnimationElement* aSrcElement,
nsSMILValue& aValue,
PRBool& aPreventCachingOfSandwich) const
{
NS_ENSURE_TRUE(aSrcElement, NS_ERROR_FAILURE);
NS_ABORT_IF_FALSE(aValue.IsNull(),
"aValue should have been cleared before calling ValueFromString");
const nsAttrValue* typeAttr = aSrcElement->GetAnimAttr(nsGkAtoms::type);
const nsIAtom* transformType = nsGkAtoms::translate; // default val
if (typeAttr) {
if (typeAttr->Type() != nsAttrValue::eAtom) {
// Recognized values of |type| are parsed as an atom -- so if we have
// something other than an atom, then we know already our |type| is
// invalid.
return NS_ERROR_FAILURE;
}
transformType = typeAttr->GetAtomValue();
}
ParseValue(aStr, transformType, aValue);
aPreventCachingOfSandwich = PR_FALSE;
return aValue.IsNull() ? NS_ERROR_FAILURE : NS_OK;
}
void
SVGAnimatedTransformList::SMILAnimatedTransformList::ParseValue(
const nsAString& aSpec,
const nsIAtom* aTransformType,
nsSMILValue& aResult)
{
NS_ABORT_IF_FALSE(aResult.IsNull(), "Unexpected type for SMIL value");
// nsSVGSMILTransform constructor should be expecting array with 3 params
PR_STATIC_ASSERT(SVGTransformSMILData::NUM_SIMPLE_PARAMS == 3);
float params[3] = { 0.f };
PRInt32 numParsed = ParseParameterList(aSpec, params, 3);
PRUint16 transformType;
if (aTransformType == nsGkAtoms::translate) {
// tx [ty=0]
if (numParsed != 1 && numParsed != 2)
return;
transformType = nsIDOMSVGTransform::SVG_TRANSFORM_TRANSLATE;
} else if (aTransformType == nsGkAtoms::scale) {
// sx [sy=sx]
if (numParsed != 1 && numParsed != 2)
return;
if (numParsed == 1) {
params[1] = params[0];
}
transformType = nsIDOMSVGTransform::SVG_TRANSFORM_SCALE;
} else if (aTransformType == nsGkAtoms::rotate) {
// r [cx=0 cy=0]
if (numParsed != 1 && numParsed != 3)
return;
transformType = nsIDOMSVGTransform::SVG_TRANSFORM_ROTATE;
} else if (aTransformType == nsGkAtoms::skewX) {
// x-angle
if (numParsed != 1)
return;
transformType = nsIDOMSVGTransform::SVG_TRANSFORM_SKEWX;
} else if (aTransformType == nsGkAtoms::skewY) {
// y-angle
if (numParsed != 1)
return;
transformType = nsIDOMSVGTransform::SVG_TRANSFORM_SKEWY;
} else {
return;
}
nsSMILValue val(&SVGTransformListSMILType::sSingleton);
SVGTransformSMILData transform(transformType, params);
if (NS_FAILED(SVGTransformListSMILType::AppendTransform(transform, val))) {
return; // OOM
}
// Success! Populate our outparam with parsed value.
aResult.Swap(val);
}
namespace
{
inline void
SkipWsp(nsACString::const_iterator& aIter,
const nsACString::const_iterator& aIterEnd)
{
while (aIter != aIterEnd && IsSVGWhitespace(*aIter))
++aIter;
}
} // end anonymous namespace block
PRInt32
SVGAnimatedTransformList::SMILAnimatedTransformList::ParseParameterList(
const nsAString& aSpec,
float* aVars,
PRInt32 aNVars)
{
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() || !NS_finite(f))
return -1;
if (numArgsFound < aNVars) {
aVars[numArgsFound] = f;
}
start.advance(argend - arg);
numArgsFound++;
SkipWsp(start, end);
if (*start == ',') {
++start;
SkipWsp(start, end);
}
}
return numArgsFound;
}
nsSMILValue
SVGAnimatedTransformList::SMILAnimatedTransformList::GetBaseValue() const
{
// To benefit from Return Value Optimization and avoid copy constructor calls
// due to our use of return-by-value, we must return the exact same object
// from ALL return points. This function must only return THIS variable:
nsSMILValue val(&SVGTransformListSMILType::sSingleton);
if (!SVGTransformListSMILType::AppendTransforms(mVal->mBaseVal, val)) {
val = nsSMILValue();
}
return val;
}
nsresult
SVGAnimatedTransformList::SMILAnimatedTransformList::SetAnimValue(
const nsSMILValue& aNewAnimValue)
{
NS_ABORT_IF_FALSE(
aNewAnimValue.mType == &SVGTransformListSMILType::sSingleton,
"Unexpected type to assign animated value");
SVGTransformList animVal;
if (!SVGTransformListSMILType::GetTransforms(aNewAnimValue,
animVal.mItems)) {
return NS_ERROR_FAILURE;
}
return mVal->SetAnimValue(animVal, mElement);
}
void
SVGAnimatedTransformList::SMILAnimatedTransformList::ClearAnimValue()
{
if (mVal->mAnimVal) {
mVal->ClearAnimValue(mElement);
}
}
#endif // MOZ_SMIL
} // namespace mozilla

View File

@ -0,0 +1,158 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SVG Project code.
*
* The Initial Developer of the Original Code is the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* 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 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 MOZILLA_SVGANIMATEDTRANSFORMLIST_H__
#define MOZILLA_SVGANIMATEDTRANSFORMLIST_H__
#include "SVGTransformList.h"
class nsSVGElement;
#ifdef MOZ_SMIL
#include "nsISMILAttr.h"
#endif // MOZ_SMIL
namespace mozilla {
/**
* Class SVGAnimatedTransformList
*
* This class is very different to the SVG DOM interface of the same name found
* in the SVG specification. This is a lightweight internal class - see
* DOMSVGAnimatedTransformList for the heavier DOM class that wraps instances of
* this class and implements the SVG specification's SVGAnimatedTransformList
* DOM interface.
*
* Except where noted otherwise, this class' methods take care of keeping the
* appropriate DOM wrappers in sync (see the comment in
* DOMSVGAnimatedTransformList::InternalBaseValListWillChangeTo) so that their
* consumers don't need to concern themselves with that.
*/
class SVGAnimatedTransformList
{
// friends so that they can get write access to mBaseVal
friend class DOMSVGTransform;
friend class DOMSVGTransformList;
public:
SVGAnimatedTransformList() : mIsAttrSet(PR_FALSE) { }
/**
* Because it's so important that mBaseVal and its DOMSVGTransformList wrapper
* (if any) be kept in sync (see the comment in
* DOMSVGAnimatedTransformList::InternalBaseValListWillChangeTo), this method
* returns a const reference. Only our friend classes may get mutable
* references to mBaseVal.
*/
const SVGTransformList& GetBaseValue() const {
return mBaseVal;
}
nsresult SetBaseValueString(const nsAString& aValue);
void ClearBaseValue();
const SVGTransformList& GetAnimValue() const {
return mAnimVal ? *mAnimVal : mBaseVal;
}
nsresult SetAnimValue(const SVGTransformList& aNewAnimValue,
nsSVGElement *aElement);
void ClearAnimValue(nsSVGElement *aElement);
PRBool IsExplicitlySet() const;
PRBool IsAnimating() const {
return !!mAnimVal;
}
#ifdef MOZ_SMIL
/// Callers own the returned nsISMILAttr
nsISMILAttr* ToSMILAttr(nsSVGElement* aSVGElement);
#endif // MOZ_SMIL
private:
// mAnimVal is a pointer to allow us to determine if we're being animated or
// not. Making it a non-pointer member and using mAnimVal.IsEmpty() to check
// if we're animating is not an option, since that would break animation *to*
// the empty string (<set to="">).
SVGTransformList mBaseVal;
nsAutoPtr<SVGTransformList> mAnimVal;
PRPackedBool mIsAttrSet;
#ifdef MOZ_SMIL
struct SMILAnimatedTransformList : public nsISMILAttr
{
public:
SMILAnimatedTransformList(SVGAnimatedTransformList* aVal,
nsSVGElement* aSVGElement)
: mVal(aVal)
, mElement(aSVGElement)
{}
// nsISMILAttr methods
virtual nsresult ValueFromString(const nsAString& aStr,
const nsISMILAnimationElement* aSrcElement,
nsSMILValue& aValue,
PRBool& aPreventCachingOfSandwich) const;
virtual nsSMILValue GetBaseValue() const;
virtual void ClearAnimValue();
virtual nsresult SetAnimValue(const nsSMILValue& aValue);
protected:
static void ParseValue(const nsAString& aSpec,
const nsIAtom* aTransformType,
nsSMILValue& aResult);
static PRInt32 ParseParameterList(const nsAString& aSpec, float* aVars,
PRInt32 aNVars);
// These will stay alive because a nsISMILAttr only lives as long
// as the Compositing step, and DOM elements don't get a chance to
// die during that.
SVGAnimatedTransformList* mVal;
nsSVGElement* mElement;
};
#endif // MOZ_SMIL
};
} // namespace mozilla
#endif // MOZILLA_SVGANIMATEDTRANSFORMLIST_H__

View File

@ -42,7 +42,6 @@
#include "nsSVGEnum.h"
#include "nsIDOMSVGTransform.h"
#include "nsIDOMSVGTransformable.h"
#include "nsSVGAnimatedTransformList.h"
#include "nsSVGTransformSMILAttr.h"
#include "nsSMILAnimationFunction.h"

View File

@ -1,184 +0,0 @@
/* -*- 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
* Crocodile Clips Ltd..
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
*
* 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 "nsSVGAnimatedTransformList.h"
#include "nsSVGTransformList.h"
#include "nsContentUtils.h"
//----------------------------------------------------------------------
// Implementation
nsSVGAnimatedTransformList::~nsSVGAnimatedTransformList()
{
if (!mBaseVal) return;
nsCOMPtr<nsISVGValue> val = do_QueryInterface(mBaseVal);
if (!val) return;
val->RemoveObserver(this);
}
void
nsSVGAnimatedTransformList::Init(nsIDOMSVGTransformList* baseVal)
{
mBaseVal = baseVal;
if (!mBaseVal) return;
nsCOMPtr<nsISVGValue> val = do_QueryInterface(mBaseVal);
if (!val) return;
val->AddObserver(this);
}
//----------------------------------------------------------------------
// nsISupports methods:
NS_IMPL_ADDREF(nsSVGAnimatedTransformList)
NS_IMPL_RELEASE(nsSVGAnimatedTransformList)
DOMCI_DATA(SVGAnimatedTransformList, nsSVGAnimatedTransformList)
NS_INTERFACE_MAP_BEGIN(nsSVGAnimatedTransformList)
NS_INTERFACE_MAP_ENTRY(nsISVGValue)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedTransformList)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGAnimatedTransformList)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISVGValue)
NS_INTERFACE_MAP_END
//----------------------------------------------------------------------
// nsISVGValue methods:
NS_IMETHODIMP
nsSVGAnimatedTransformList::SetValueString(const nsAString& aValue)
{
nsCOMPtr<nsISVGValue> value = do_QueryInterface(mBaseVal);
return value->SetValueString(aValue);
}
NS_IMETHODIMP
nsSVGAnimatedTransformList::GetValueString(nsAString& aValue)
{
nsCOMPtr<nsISVGValue> value = do_QueryInterface(mBaseVal);
return value->GetValueString(aValue);
}
//----------------------------------------------------------------------
// nsIDOMSVGAnimatedTransformList methods:
/* readonly attribute nsIDOMSVGTransformList baseVal; */
NS_IMETHODIMP
nsSVGAnimatedTransformList::GetBaseVal(nsIDOMSVGTransformList** aBaseVal)
{
*aBaseVal = mBaseVal;
NS_ADDREF(*aBaseVal);
return NS_OK;
}
/* readonly attribute nsIDOMSVGTransformList animVal; */
NS_IMETHODIMP
nsSVGAnimatedTransformList::GetAnimVal(nsIDOMSVGTransformList** aAnimVal)
{
*aAnimVal = mAnimVal ? mAnimVal : mBaseVal;
NS_ADDREF(*aAnimVal);
return NS_OK;
}
//----------------------------------------------------------------------
// nsISVGValueObserver methods
NS_IMETHODIMP
nsSVGAnimatedTransformList::WillModifySVGObservable(nsISVGValue* observable,
modificationType aModType)
{
WillModify(aModType);
return NS_OK;
}
NS_IMETHODIMP
nsSVGAnimatedTransformList::DidModifySVGObservable (nsISVGValue* observable,
modificationType aModType)
{
DidModify(aModType);
return NS_OK;
}
//----------------------------------------------------------------------
// Misc nsSVGAnimatedTransformList methods
PRBool
nsSVGAnimatedTransformList::IsExplicitlySet() const
{
// XXX Dummy implementation until bug 602759 is fixed.
// Like other methods of this name, we need to know when a transform value has
// been explicitly set (either by markup, a DOM call, or animation).
// Given our current implementation, we can say that's the case so long as
// mBaseVal has something in it or mAnimVal exists.
// It's not quite right because, for example, if we have transform="" we
// should probably behave as if the value is set, but for now it will do until
// bug 602759 is fixed.
if (mAnimVal)
return PR_TRUE;
if (!mBaseVal)
return PR_FALSE;
PRUint32 numItems = 0;
nsIDOMSVGTransformList *list = mBaseVal.get();
list->GetNumberOfItems(&numItems);
return numItems > 0;
}
////////////////////////////////////////////////////////////////////////
// Exported creation functions:
nsresult
NS_NewSVGAnimatedTransformList(nsIDOMSVGAnimatedTransformList** result,
nsIDOMSVGTransformList* baseVal)
{
*result = nsnull;
nsSVGAnimatedTransformList* animatedTransformList = new nsSVGAnimatedTransformList();
if(!animatedTransformList) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(animatedTransformList);
animatedTransformList->Init(baseVal);
*result = (nsIDOMSVGAnimatedTransformList*) animatedTransformList;
return NS_OK;
}

View File

@ -1,97 +0,0 @@
/* -*- 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
* Crocodile Clips Ltd..
* Portions created by the Initial Developer are Copyright (C) 2001
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
*
* 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_SVGANIMATEDTRANSFORMLIST_H__
#define __NS_SVGANIMATEDTRANSFORMLIST_H__
#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
PRBool IsExplicitlySet() const;
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,
nsIDOMSVGTransformList* baseVal);
#endif //__NS_SVGANIMATEDTRANSFORMLIST_H__

View File

@ -1,447 +0,0 @@
/* -*- 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"
#include "prlog.h"
#include "nsMathUtils.h"
nsresult
nsSVGTransformSMILAttr::ValueFromString(const nsAString& aStr,
const nsISMILAnimationElement* aSrcElement,
nsSMILValue& aValue,
PRBool& aPreventCachingOfSandwich) const
{
NS_ENSURE_TRUE(aSrcElement, NS_ERROR_FAILURE);
NS_ASSERTION(aValue.IsNull(),
"aValue should have been cleared before calling ValueFromString");
const nsAttrValue* typeAttr = aSrcElement->GetAnimAttr(nsGkAtoms::type);
const nsIAtom* transformType = nsGkAtoms::translate;
if (typeAttr) {
if (typeAttr->Type() != nsAttrValue::eAtom) {
// Recognized values of |type| are parsed as an atom -- so if we have
// something other than an atom, then it means our |type| was invalid.
return NS_ERROR_FAILURE;
}
transformType = typeAttr->GetAtomValue();
}
ParseValue(aStr, transformType, aValue);
aPreventCachingOfSandwich = PR_FALSE;
return aValue.IsNull() ? NS_ERROR_FAILURE : NS_OK;
}
nsSMILValue
nsSVGTransformSMILAttr::GetBaseValue() const
{
// To benefit from Return Value Optimization and avoid copy constructor calls
// due to our use of return-by-value, we must return the exact same object
// from ALL return points. This function must only return THIS variable:
nsSMILValue val(&nsSVGTransformSMILType::sSingleton);
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);
if (NS_FAILED(rv)) { // Appending to |val| failed (OOM?)
val = nsSMILValue();
break;
}
}
}
return val;
}
void
nsSVGTransformSMILAttr::ClearAnimValue()
{
PRBool animValSet = !!mVal->mAnimVal;
mVal->mAnimVal = nsnull;
if (animValSet) {
mSVGElement->DidAnimateTransform();
}
}
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
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);
mSVGElement->DidAnimateTransform();
return NS_OK;
}
//----------------------------------------------------------------------
// Implementation helpers
void
nsSVGTransformSMILAttr::ParseValue(const nsAString& aSpec,
const nsIAtom* aTransformType,
nsSMILValue& aResult)
{
NS_ASSERTION(aResult.IsNull(), "Unexpected type for SMIL value");
// nsSVGSMILTransform constructor should be expecting array with 3 params
PR_STATIC_ASSERT(nsSVGSMILTransform::NUM_SIMPLE_PARAMS == 3);
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;
transformType = nsSVGSMILTransform::TRANSFORM_TRANSLATE;
} else if (aTransformType == nsGkAtoms::scale) {
// sx [sy=sx]
if (numParsed != 1 && numParsed != 2)
return;
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;
transformType = nsSVGSMILTransform::TRANSFORM_ROTATE;
} else if (aTransformType == nsGkAtoms::skewX) {
// x-angle
if (numParsed != 1)
return;
transformType = nsSVGSMILTransform::TRANSFORM_SKEWX;
} else if (aTransformType == nsGkAtoms::skewY) {
// y-angle
if (numParsed != 1)
return;
transformType = nsSVGSMILTransform::TRANSFORM_SKEWY;
} else {
return;
}
nsSMILValue val(&nsSVGTransformSMILType::sSingleton);
nsSVGSMILTransform transform(transformType, params);
if (NS_FAILED(nsSVGTransformSMILType::AppendTransform(transform, val))) {
return;
}
// Success! Populate our outparam with parsed value.
aResult.Swap(val);
}
inline PRBool
IsSpace(const char c)
{
return (c == 0x9 || c == 0xA || c == 0xD || c == 0x20);
}
inline void
SkipWsp(nsACString::const_iterator& aIter,
const nsACString::const_iterator& aIterEnd)
{
while (aIter != aIterEnd && IsSpace(*aIter))
++aIter;
}
PRInt32
nsSVGTransformSMILAttr::ParseParameterList(const nsAString& aSpec,
float* aVars,
PRInt32 aNVars)
{
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() || !NS_finite(f))
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)
{
NS_ASSERTION(aValue.mType == &nsSVGTransformSMILType::sSingleton,
"Unexpected type for SMIL value");
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;
// nsSVGSMILTransform constructor should be expecting array with 3 params
PR_STATIC_ASSERT(nsSVGSMILTransform::NUM_SIMPLE_PARAMS == 3);
float params[3] = { 0.f };
nsSVGSMILTransform::TransformType transformType;
switch (svgTransformType)
{
case nsIDOMSVGTransform::SVG_TRANSFORM_TRANSLATE:
{
matrix->GetE(&params[0]);
matrix->GetF(&params[1]);
transformType = nsSVGSMILTransform::TRANSFORM_TRANSLATE;
}
break;
case nsIDOMSVGTransform::SVG_TRANSFORM_SCALE:
{
matrix->GetA(&params[0]);
matrix->GetD(&params[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(&params[0]);
svgTransform->GetRotationOrigin(params[1], params[2]);
transformType = nsSVGSMILTransform::TRANSFORM_ROTATE;
}
break;
case nsIDOMSVGTransform::SVG_TRANSFORM_SKEWX:
{
aTransform->GetAngle(&params[0]);
transformType = nsSVGSMILTransform::TRANSFORM_SKEWX;
}
break;
case nsIDOMSVGTransform::SVG_TRANSFORM_SKEWY:
{
aTransform->GetAngle(&params[0]);
transformType = nsSVGSMILTransform::TRANSFORM_SKEWY;
}
break;
case nsIDOMSVGTransform::SVG_TRANSFORM_MATRIX:
{
// nsSVGSMILTransform constructor for TRANSFORM_MATRIX type should be
// expecting array with 6 params
PR_STATIC_ASSERT(nsSVGSMILTransform::NUM_STORED_PARAMS == 6);
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]);
return nsSVGTransformSMILType::AppendTransform(nsSVGSMILTransform(mx),
aValue);
}
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;
}
NS_ABORT_IF_FALSE(transformType != nsSVGSMILTransform::TRANSFORM_MATRIX,
"generalized matrix case should have returned above");
return nsSVGTransformSMILType::
AppendTransform(nsSVGSMILTransform(transformType, params), aValue);
}
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)
{
switch (aSMILTransform.mTransformType)
{
case nsSVGSMILTransform::TRANSFORM_TRANSLATE:
return aSVGTransform->SetTranslate(aSMILTransform.mParams[0],
aSMILTransform.mParams[1]);
case nsSVGSMILTransform::TRANSFORM_SCALE:
return aSVGTransform->SetScale(aSMILTransform.mParams[0],
aSMILTransform.mParams[1]);
case nsSVGSMILTransform::TRANSFORM_ROTATE:
return aSVGTransform->SetRotate(aSMILTransform.mParams[0],
aSMILTransform.mParams[1],
aSMILTransform.mParams[2]);
case nsSVGSMILTransform::TRANSFORM_SKEWX:
return aSVGTransform->SetSkewX(aSMILTransform.mParams[0]);
case nsSVGSMILTransform::TRANSFORM_SKEWY:
return aSVGTransform->SetSkewY(aSMILTransform.mParams[0]);
case nsSVGSMILTransform::TRANSFORM_MATRIX:
{
nsCOMPtr<nsIDOMSVGMatrix> svgMatrix;
nsresult 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_ABORT_IF_FALSE(svgMatrix,
"NS_NewSVGMatrix succeeded, so it should have "
"given us a non-null result");
return aSVGTransform->SetMatrix(svgMatrix);
}
default:
NS_WARNING("Unexpected transform type");
return NS_ERROR_FAILURE;
}
}

View File

@ -1,90 +0,0 @@
/* -*- 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 nsresult ValueFromString(const nsAString& aStr,
const nsISMILAnimationElement* aSrcElement,
nsSMILValue& aValue,
PRBool& aPreventCachingOfSandwich) const;
virtual nsSMILValue GetBaseValue() const;
virtual void ClearAnimValue();
virtual nsresult SetAnimValue(const nsSMILValue& aValue);
protected:
static void ParseValue(const nsAString& aSpec,
const nsIAtom* aTransformType,
nsSMILValue& aResult);
static PRInt32 ParseParameterList(const nsAString& aSpec, float* aVars,
PRInt32 aNVars);
static nsresult AppendSVGTransformToSMILValue(nsIDOMSVGTransform* transform,
nsSMILValue& aValue);
static nsresult UpdateFromSMILValue(nsIDOMSVGTransformList* aTransformList,
const nsSMILValue& aValue);
static nsresult GetSVGTransformFromSMILValue(
const nsSVGSMILTransform& aSMILTransform,
nsIDOMSVGTransform* aSVGTransform);
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_