mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Back out 26f0d590a021, d92e88a18263, 5a2d12a34466 (bug 846995) for not building
CLOSED TREE
This commit is contained in:
parent
3f78b114b0
commit
3b7e0c1622
141
content/svg/content/src/DOMSVGAnimatedTransformList.cpp
Normal file
141
content/svg/content/src/DOMSVGAnimatedTransformList.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "DOMSVGAnimatedTransformList.h"
|
||||
#include "DOMSVGTransformList.h"
|
||||
#include "SVGAnimatedTransformList.h"
|
||||
#include "nsSVGAttrTearoffTable.h"
|
||||
#include "mozilla/dom/SVGAnimatedTransformListBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
static
|
||||
nsSVGAttrTearoffTable<SVGAnimatedTransformList,DOMSVGAnimatedTransformList>
|
||||
sSVGAnimatedTransformListTearoffTable;
|
||||
|
||||
NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(DOMSVGAnimatedTransformList, mElement)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGAnimatedTransformList)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGAnimatedTransformList)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGAnimatedTransformList)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
JSObject*
|
||||
DOMSVGAnimatedTransformList::WrapObject(JSContext* aCx, JSObject* aScope)
|
||||
{
|
||||
return mozilla::dom::SVGAnimatedTransformListBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
already_AddRefed<DOMSVGTransformList>
|
||||
DOMSVGAnimatedTransformList::BaseVal()
|
||||
{
|
||||
if (!mBaseVal) {
|
||||
mBaseVal = new DOMSVGTransformList(this, InternalAList().GetBaseValue());
|
||||
}
|
||||
nsRefPtr<DOMSVGTransformList> baseVal = mBaseVal;
|
||||
return baseVal.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGTransformList>
|
||||
DOMSVGAnimatedTransformList::AnimVal()
|
||||
{
|
||||
if (!mAnimVal) {
|
||||
mAnimVal = new DOMSVGTransformList(this, InternalAList().GetAnimValue());
|
||||
}
|
||||
nsRefPtr<DOMSVGTransformList> animVal = mAnimVal;
|
||||
return animVal.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<DOMSVGAnimatedTransformList>
|
||||
DOMSVGAnimatedTransformList::GetDOMWrapper(SVGAnimatedTransformList *aList,
|
||||
nsSVGElement *aElement)
|
||||
{
|
||||
nsRefPtr<DOMSVGAnimatedTransformList> wrapper =
|
||||
sSVGAnimatedTransformListTearoffTable.GetTearoff(aList);
|
||||
if (!wrapper) {
|
||||
wrapper = new DOMSVGAnimatedTransformList(aElement);
|
||||
sSVGAnimatedTransformListTearoffTable.AddTearoff(aList, wrapper);
|
||||
}
|
||||
return wrapper.forget();
|
||||
}
|
||||
|
||||
/* 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(
|
||||
uint32_t 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->LengthNoFlush()) {
|
||||
// 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(
|
||||
uint32_t aNewLength)
|
||||
{
|
||||
if (mAnimVal) {
|
||||
mAnimVal->InternalListLengthWillChange(aNewLength);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DOMSVGAnimatedTransformList::IsAnimating() const
|
||||
{
|
||||
return InternalAList().IsAnimating();
|
||||
}
|
||||
|
||||
SVGAnimatedTransformList&
|
||||
DOMSVGAnimatedTransformList::InternalAList()
|
||||
{
|
||||
return *mElement->GetAnimatedTransformList();
|
||||
}
|
||||
|
||||
const SVGAnimatedTransformList&
|
||||
DOMSVGAnimatedTransformList::InternalAList() const
|
||||
{
|
||||
return *mElement->GetAnimatedTransformList();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
130
content/svg/content/src/DOMSVGAnimatedTransformList.h
Normal file
130
content/svg/content/src/DOMSVGAnimatedTransformList.h
Normal file
@ -0,0 +1,130 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_DOMSVGANIMATEDTRANSFORMLIST_H__
|
||||
#define MOZILLA_DOMSVGANIMATEDTRANSFORMLIST_H__
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsSVGElement.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class DOMSVGTransformList;
|
||||
class SVGAnimatedTransformList;
|
||||
|
||||
/**
|
||||
* 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 MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
friend class DOMSVGTransformList;
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGAnimatedTransformList)
|
||||
|
||||
/**
|
||||
* 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 nullptr 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(uint32_t aNewLength);
|
||||
void InternalAnimValListWillChangeLengthTo(uint32_t aNewLength);
|
||||
|
||||
/**
|
||||
* Returns true if our attribute is animating (in which case our animVal is
|
||||
* not simply a mirror of our baseVal).
|
||||
*/
|
||||
bool IsAnimating() const;
|
||||
|
||||
// WebIDL
|
||||
nsSVGElement* GetParentObject() const { return mElement; }
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope) MOZ_OVERRIDE;
|
||||
// These aren't weak refs because mBaseVal and mAnimVal are weak
|
||||
already_AddRefed<DOMSVGTransformList> BaseVal();
|
||||
already_AddRefed<DOMSVGTransformList> AnimVal();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Only our static GetDOMWrapper() factory method may create objects of our
|
||||
* type.
|
||||
*/
|
||||
explicit DOMSVGAnimatedTransformList(nsSVGElement *aElement)
|
||||
: mBaseVal(nullptr)
|
||||
, mAnimVal(nullptr)
|
||||
, mElement(aElement)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
~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__
|
@ -6,10 +6,10 @@
|
||||
|
||||
#include "DOMSVGTransform.h"
|
||||
#include "mozilla/dom/SVGMatrix.h"
|
||||
#include "SVGAnimatedTransformList.h"
|
||||
#include "nsError.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsAttrValueInlines.h"
|
||||
#include "nsSVGAnimatedTransformList.h"
|
||||
#include "nsSVGAttrTearoffTable.h"
|
||||
#include "mozilla/dom/SVGTransformBinding.h"
|
||||
|
||||
@ -292,7 +292,7 @@ DOMSVGTransform::RemovingFromList()
|
||||
SVGTransform&
|
||||
DOMSVGTransform::InternalItem()
|
||||
{
|
||||
nsSVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList();
|
||||
SVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList();
|
||||
return mIsAnimValItem && alist->mAnimVal ?
|
||||
(*alist->mAnimVal)[mListIndex] :
|
||||
alist->mBaseVal[mListIndex];
|
||||
@ -308,7 +308,7 @@ DOMSVGTransform::InternalItem() const
|
||||
bool
|
||||
DOMSVGTransform::IndexIsValid()
|
||||
{
|
||||
nsSVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList();
|
||||
SVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList();
|
||||
return (mIsAnimValItem &&
|
||||
mListIndex < alist->GetAnimValue().Length()) ||
|
||||
(!mIsAnimValItem &&
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "DOMSVGTransformList.h"
|
||||
#include "DOMSVGTransform.h"
|
||||
#include "mozilla/dom/SVGMatrix.h"
|
||||
#include "nsSVGAnimatedTransformList.h"
|
||||
#include "SVGAnimatedTransformList.h"
|
||||
#include "nsSVGElement.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "mozilla/dom/SVGTransformListBinding.h"
|
||||
@ -34,7 +34,7 @@ void UpdateListIndicesFromIndex(
|
||||
namespace mozilla {
|
||||
|
||||
// We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to
|
||||
// clear our SVGAnimatedTransformList's weak ref to us to be safe. (The other
|
||||
// clear our DOMSVGAnimatedTransformList's weak ref to us to be safe. (The other
|
||||
// option would be to not unlink and rely on the breaking of the other edges in
|
||||
// the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGTransformList)
|
||||
@ -114,7 +114,7 @@ DOMSVGTransformList::InternalListLengthWillChange(uint32_t aNewLength)
|
||||
SVGTransformList&
|
||||
DOMSVGTransformList::InternalList() const
|
||||
{
|
||||
nsSVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList();
|
||||
SVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList();
|
||||
return IsAnimValList() && alist->mAnimVal ?
|
||||
*alist->mAnimVal :
|
||||
alist->mBaseVal;
|
||||
|
@ -7,7 +7,7 @@
|
||||
#ifndef MOZILLA_DOMSVGTRANSFORMLIST_H__
|
||||
#define MOZILLA_DOMSVGTRANSFORMLIST_H__
|
||||
|
||||
#include "mozilla/dom/SVGAnimatedTransformList.h"
|
||||
#include "DOMSVGAnimatedTransformList.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDebug.h"
|
||||
@ -33,7 +33,7 @@ class DOMSVGTransform;
|
||||
* This class is used to create the DOM tearoff objects that wrap internal
|
||||
* SVGTransformList objects.
|
||||
*
|
||||
* See the architecture comment in SVGAnimatedTransformList.h.
|
||||
* See the architecture comment in DOMSVGAnimatedTransformList.h.
|
||||
*/
|
||||
class DOMSVGTransformList MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
@ -44,7 +44,7 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGTransformList)
|
||||
|
||||
DOMSVGTransformList(dom::SVGAnimatedTransformList *aAList,
|
||||
DOMSVGTransformList(DOMSVGAnimatedTransformList *aAList,
|
||||
const SVGTransformList &aInternalList)
|
||||
: mAList(aAList)
|
||||
{
|
||||
@ -162,7 +162,7 @@ private:
|
||||
// of clearing our pointer to them when they die.
|
||||
nsTArray<DOMSVGTransform*> mItems;
|
||||
|
||||
nsRefPtr<dom::SVGAnimatedTransformList> mAList;
|
||||
nsRefPtr<DOMSVGAnimatedTransformList> mAList;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -19,6 +19,7 @@ endif # !_MSC_VER
|
||||
CPPSRCS = \
|
||||
DOMSVGAnimatedLengthList.cpp \
|
||||
DOMSVGAnimatedNumberList.cpp \
|
||||
DOMSVGAnimatedTransformList.cpp \
|
||||
DOMSVGLength.cpp \
|
||||
DOMSVGLengthList.cpp \
|
||||
DOMSVGNumber.cpp \
|
||||
@ -33,7 +34,6 @@ CPPSRCS = \
|
||||
nsDOMSVGZoomEvent.cpp \
|
||||
nsISVGPoint.cpp \
|
||||
nsSVGAngle.cpp \
|
||||
nsSVGAnimatedTransformList.cpp \
|
||||
nsSVGBoolean.cpp \
|
||||
nsSVGClass.cpp \
|
||||
nsSVGDataParser.cpp \
|
||||
@ -156,7 +156,6 @@ include $(topsrcdir)/config/config.mk
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
EXPORTS = \
|
||||
nsSVGAnimatedTransformList.h \
|
||||
nsSVGClass.h \
|
||||
nsSVGElement.h \
|
||||
nsSVGFeatures.h \
|
||||
@ -174,7 +173,6 @@ EXPORTS_mozilla/dom = \
|
||||
SVGAnimatedAngle.h \
|
||||
SVGAnimatedBoolean.h \
|
||||
SVGAnimatedLength.h \
|
||||
SVGAnimatedTransformList.h \
|
||||
SVGAnimateElement.h \
|
||||
SVGAnimateTransformElement.h \
|
||||
SVGAnimateMotionElement.h \
|
||||
|
@ -3,136 +3,318 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/SVGAnimatedTransformList.h"
|
||||
#include "DOMSVGTransformList.h"
|
||||
#include "nsSVGAnimatedTransformList.h"
|
||||
#include "nsSVGAttrTearoffTable.h"
|
||||
#include "mozilla/dom/SVGAnimatedTransformListBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "SVGAnimatedTransformList.h"
|
||||
#include "DOMSVGAnimatedTransformList.h"
|
||||
|
||||
#include "mozilla/dom/SVGAnimationElement.h"
|
||||
#include "nsSMILValue.h"
|
||||
#include "prdtoa.h"
|
||||
#include "SVGContentUtils.h"
|
||||
#include "SVGTransform.h"
|
||||
#include "SVGTransformListSMILType.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
static
|
||||
nsSVGAttrTearoffTable<nsSVGAnimatedTransformList, SVGAnimatedTransformList>
|
||||
sSVGAnimatedTransformListTearoffTable;
|
||||
|
||||
NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(SVGAnimatedTransformList, mElement)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(SVGAnimatedTransformList, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(SVGAnimatedTransformList, Release)
|
||||
|
||||
JSObject*
|
||||
SVGAnimatedTransformList::WrapObject(JSContext* aCx, JSObject* aScope)
|
||||
nsresult
|
||||
SVGAnimatedTransformList::SetBaseValueString(const nsAString& aValue)
|
||||
{
|
||||
return SVGAnimatedTransformListBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
already_AddRefed<DOMSVGTransformList>
|
||||
SVGAnimatedTransformList::BaseVal()
|
||||
{
|
||||
if (!mBaseVal) {
|
||||
mBaseVal = new DOMSVGTransformList(this, InternalAList().GetBaseValue());
|
||||
SVGTransformList newBaseValue;
|
||||
nsresult rv = newBaseValue.SetValueFromString(aValue);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsRefPtr<DOMSVGTransformList> baseVal = mBaseVal;
|
||||
return baseVal.forget();
|
||||
|
||||
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 Element::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 = true;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
already_AddRefed<DOMSVGTransformList>
|
||||
SVGAnimatedTransformList::AnimVal()
|
||||
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 = 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 DOMSVGTransformList(this, InternalAList().GetAnimValue());
|
||||
mAnimVal = new SVGTransformList();
|
||||
}
|
||||
nsRefPtr<DOMSVGTransformList> animVal = mAnimVal;
|
||||
return animVal.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<SVGAnimatedTransformList>
|
||||
SVGAnimatedTransformList::GetDOMWrapper(nsSVGAnimatedTransformList *aList,
|
||||
nsSVGElement *aElement)
|
||||
{
|
||||
nsRefPtr<SVGAnimatedTransformList> wrapper =
|
||||
sSVGAnimatedTransformListTearoffTable.GetTearoff(aList);
|
||||
if (!wrapper) {
|
||||
wrapper = new SVGAnimatedTransformList(aElement);
|
||||
sSVGAnimatedTransformListTearoffTable.AddTearoff(aList, wrapper);
|
||||
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;
|
||||
}
|
||||
return wrapper.forget();
|
||||
}
|
||||
|
||||
/* static */ SVGAnimatedTransformList*
|
||||
SVGAnimatedTransformList::GetDOMWrapperIfExists(
|
||||
nsSVGAnimatedTransformList *aList)
|
||||
{
|
||||
return sSVGAnimatedTransformListTearoffTable.GetTearoff(aList);
|
||||
}
|
||||
|
||||
SVGAnimatedTransformList::~SVGAnimatedTransformList()
|
||||
{
|
||||
// Script no longer has any references to us, to our base/animVal objects, or
|
||||
// to any of their list items.
|
||||
sSVGAnimatedTransformListTearoffTable.RemoveTearoff(&InternalAList());
|
||||
aElement->DidAnimateTransformList();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
SVGAnimatedTransformList::InternalBaseValListWillChangeLengthTo(
|
||||
uint32_t aNewLength)
|
||||
SVGAnimatedTransformList::ClearAnimValue(nsSVGElement *aElement)
|
||||
{
|
||||
// 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<SVGAnimatedTransformList> kungFuDeathGrip;
|
||||
if (mBaseVal) {
|
||||
if (aNewLength < mBaseVal->LengthNoFlush()) {
|
||||
// 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
|
||||
SVGAnimatedTransformList::InternalAnimValListWillChangeLengthTo(
|
||||
uint32_t aNewLength)
|
||||
{
|
||||
if (mAnimVal) {
|
||||
mAnimVal->InternalListLengthWillChange(aNewLength);
|
||||
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 = nullptr;
|
||||
aElement->DidAnimateTransformList();
|
||||
}
|
||||
|
||||
bool
|
||||
SVGAnimatedTransformList::IsAnimating() const
|
||||
SVGAnimatedTransformList::IsExplicitlySet() const
|
||||
{
|
||||
return InternalAList().IsAnimating();
|
||||
// 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 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;
|
||||
}
|
||||
|
||||
nsSVGAnimatedTransformList&
|
||||
SVGAnimatedTransformList::InternalAList()
|
||||
nsISMILAttr*
|
||||
SVGAnimatedTransformList::ToSMILAttr(nsSVGElement* aSVGElement)
|
||||
{
|
||||
return *mElement->GetAnimatedTransformList();
|
||||
return new SMILAnimatedTransformList(this, aSVGElement);
|
||||
}
|
||||
|
||||
const nsSVGAnimatedTransformList&
|
||||
SVGAnimatedTransformList::InternalAList() const
|
||||
nsresult
|
||||
SVGAnimatedTransformList::SMILAnimatedTransformList::ValueFromString(
|
||||
const nsAString& aStr,
|
||||
const dom::SVGAnimationElement* aSrcElement,
|
||||
nsSMILValue& aValue,
|
||||
bool& aPreventCachingOfSandwich) const
|
||||
{
|
||||
return *mElement->GetAnimatedTransformList();
|
||||
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 = 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 };
|
||||
int32_t numParsed = ParseParameterList(aSpec, params, 3);
|
||||
uint16_t transformType;
|
||||
|
||||
if (aTransformType == nsGkAtoms::translate) {
|
||||
// tx [ty=0]
|
||||
if (numParsed != 1 && numParsed != 2)
|
||||
return;
|
||||
transformType = 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 = SVG_TRANSFORM_SCALE;
|
||||
} else if (aTransformType == nsGkAtoms::rotate) {
|
||||
// r [cx=0 cy=0]
|
||||
if (numParsed != 1 && numParsed != 3)
|
||||
return;
|
||||
transformType = SVG_TRANSFORM_ROTATE;
|
||||
} else if (aTransformType == nsGkAtoms::skewX) {
|
||||
// x-angle
|
||||
if (numParsed != 1)
|
||||
return;
|
||||
transformType = SVG_TRANSFORM_SKEWX;
|
||||
} else if (aTransformType == nsGkAtoms::skewY) {
|
||||
// y-angle
|
||||
if (numParsed != 1)
|
||||
return;
|
||||
transformType = 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
|
||||
|
||||
int32_t
|
||||
SVGAnimatedTransformList::SMILAnimatedTransformList::ParseParameterList(
|
||||
const nsAString& aSpec,
|
||||
float* aVars,
|
||||
int32_t 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);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -4,129 +4,123 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_SVGAnimatedTransformList_h
|
||||
#define mozilla_dom_SVGAnimatedTransformList_h
|
||||
#ifndef MOZILLA_SVGANIMATEDTRANSFORMLIST_H__
|
||||
#define MOZILLA_SVGANIMATEDTRANSFORMLIST_H__
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsSVGElement.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsISMILAttr.h"
|
||||
#include "SVGTransformList.h"
|
||||
|
||||
class nsIAtom;
|
||||
class nsSMILValue;
|
||||
class nsSVGElement;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class DOMSVGTransformList;
|
||||
class nsSVGAnimatedTransformList;
|
||||
|
||||
namespace dom {
|
||||
class SVGAnimationElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class SVGAnimatedTransformList
|
||||
*
|
||||
* This class is used to create the DOM tearoff objects that wrap internal
|
||||
* nsSVGAnimatedTransformList objects.
|
||||
* 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.
|
||||
*
|
||||
* 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).
|
||||
* 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 MOZ_FINAL : public nsWrapperCache
|
||||
class SVGAnimatedTransformList
|
||||
{
|
||||
// friends so that they can get write access to mBaseVal
|
||||
friend class DOMSVGTransform;
|
||||
friend class DOMSVGTransformList;
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(SVGAnimatedTransformList)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(SVGAnimatedTransformList)
|
||||
SVGAnimatedTransformList() : mIsAttrSet(false) { }
|
||||
|
||||
/**
|
||||
* Factory method to create and return a SVGAnimatedTransformList wrapper
|
||||
* for a given internal nsSVGAnimatedTransformList object. The factory takes
|
||||
* care of caching the object that it returns so that the same object can be
|
||||
* returned for the given nsSVGAnimatedTransformList 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 nsSVGAnimatedTransformList will naturally result in a new
|
||||
* SVGAnimatedTransformList being returned.
|
||||
* 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.
|
||||
*/
|
||||
static already_AddRefed<SVGAnimatedTransformList>
|
||||
GetDOMWrapper(nsSVGAnimatedTransformList *aList, nsSVGElement *aElement);
|
||||
const SVGTransformList& GetBaseValue() const {
|
||||
return mBaseVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the SVGAnimatedTransformList wrapper for an internal
|
||||
* nsSVGAnimatedTransformList object if it currently has a wrapper. If it does
|
||||
* not, then nullptr is returned.
|
||||
*/
|
||||
static SVGAnimatedTransformList*
|
||||
GetDOMWrapperIfExists(nsSVGAnimatedTransformList *aList);
|
||||
nsresult SetBaseValueString(const nsAString& aValue);
|
||||
|
||||
/**
|
||||
* 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(uint32_t aNewLength);
|
||||
void InternalAnimValListWillChangeLengthTo(uint32_t aNewLength);
|
||||
void ClearBaseValue();
|
||||
|
||||
/**
|
||||
* Returns true if our attribute is animating (in which case our animVal is
|
||||
* not simply a mirror of our baseVal).
|
||||
*/
|
||||
bool IsAnimating() const;
|
||||
const SVGTransformList& GetAnimValue() const {
|
||||
return mAnimVal ? *mAnimVal : mBaseVal;
|
||||
}
|
||||
|
||||
// WebIDL
|
||||
nsSVGElement* GetParentObject() const { return mElement; }
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope) MOZ_OVERRIDE;
|
||||
// These aren't weak refs because mBaseVal and mAnimVal are weak
|
||||
already_AddRefed<DOMSVGTransformList> BaseVal();
|
||||
already_AddRefed<DOMSVGTransformList> AnimVal();
|
||||
nsresult SetAnimValue(const SVGTransformList& aNewAnimValue,
|
||||
nsSVGElement *aElement);
|
||||
|
||||
void ClearAnimValue(nsSVGElement *aElement);
|
||||
|
||||
bool IsExplicitlySet() const;
|
||||
|
||||
bool IsAnimating() const {
|
||||
return !!mAnimVal;
|
||||
}
|
||||
|
||||
/// Callers own the returned nsISMILAttr
|
||||
nsISMILAttr* ToSMILAttr(nsSVGElement* aSVGElement);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Only our static GetDOMWrapper() factory method may create objects of our
|
||||
* type.
|
||||
*/
|
||||
explicit SVGAnimatedTransformList(nsSVGElement *aElement)
|
||||
: mBaseVal(nullptr)
|
||||
, mAnimVal(nullptr)
|
||||
, mElement(aElement)
|
||||
// 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;
|
||||
bool mIsAttrSet;
|
||||
|
||||
struct SMILAnimatedTransformList : public nsISMILAttr
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
public:
|
||||
SMILAnimatedTransformList(SVGAnimatedTransformList* aVal,
|
||||
nsSVGElement* aSVGElement)
|
||||
: mVal(aVal)
|
||||
, mElement(aSVGElement)
|
||||
{}
|
||||
|
||||
~SVGAnimatedTransformList();
|
||||
// nsISMILAttr methods
|
||||
virtual nsresult ValueFromString(const nsAString& aStr,
|
||||
const dom::SVGAnimationElement* aSrcElement,
|
||||
nsSMILValue& aValue,
|
||||
bool& aPreventCachingOfSandwich) const;
|
||||
virtual nsSMILValue GetBaseValue() const;
|
||||
virtual void ClearAnimValue();
|
||||
virtual nsresult SetAnimValue(const nsSMILValue& aValue);
|
||||
|
||||
/// Get a reference to this DOM wrapper object's internal counterpart.
|
||||
nsSVGAnimatedTransformList& InternalAList();
|
||||
const nsSVGAnimatedTransformList& InternalAList() const;
|
||||
protected:
|
||||
static void ParseValue(const nsAString& aSpec,
|
||||
const nsIAtom* aTransformType,
|
||||
nsSMILValue& aResult);
|
||||
static int32_t ParseParameterList(const nsAString& aSpec, float* aVars,
|
||||
int32_t aNVars);
|
||||
|
||||
// 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;
|
||||
// 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;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_SVGAnimatedTransformList_h
|
||||
#endif // MOZILLA_SVGANIMATEDTRANSFORMLIST_H__
|
||||
|
@ -156,7 +156,7 @@ SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString &aViewSpec,
|
||||
}
|
||||
preserveAspectRatioFound = true;
|
||||
} else if (IsMatchingParameter(token, NS_LITERAL_STRING("transform"))) {
|
||||
nsSVGAnimatedTransformList transforms;
|
||||
SVGAnimatedTransformList transforms;
|
||||
if (transformFound ||
|
||||
NS_FAILED(transforms.SetBaseValueString(params))) {
|
||||
return false;
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "mozilla/dom/SVGGradientElement.h"
|
||||
|
||||
#include "mozilla/dom/SVGAnimatedTransformList.h"
|
||||
#include "DOMSVGAnimatedTransformList.h"
|
||||
#include "mozilla/dom/SVGRadialGradientElementBinding.h"
|
||||
#include "mozilla/dom/SVGLinearGradientElementBinding.h"
|
||||
#include "mozilla/Util.h"
|
||||
@ -89,12 +89,12 @@ SVGGradientElement::GradientUnits()
|
||||
}
|
||||
|
||||
/* readonly attribute SVGAnimatedTransformList gradientTransform; */
|
||||
already_AddRefed<SVGAnimatedTransformList>
|
||||
already_AddRefed<DOMSVGAnimatedTransformList>
|
||||
SVGGradientElement::GradientTransform()
|
||||
{
|
||||
// We're creating a DOM wrapper, so we must tell GetAnimatedTransformList
|
||||
// to allocate the SVGAnimatedTransformList if it hasn't already done so:
|
||||
return SVGAnimatedTransformList::GetDOMWrapper(
|
||||
return DOMSVGAnimatedTransformList::GetDOMWrapper(
|
||||
GetAnimatedTransformList(DO_ALLOCATE), this);
|
||||
}
|
||||
|
||||
@ -190,11 +190,11 @@ SVGLinearGradientElement::Y2()
|
||||
//----------------------------------------------------------------------
|
||||
// nsSVGElement methods
|
||||
|
||||
nsSVGAnimatedTransformList*
|
||||
SVGAnimatedTransformList*
|
||||
SVGGradientElement::GetAnimatedTransformList(uint32_t aFlags)
|
||||
{
|
||||
if (!mGradientTransform && (aFlags & DO_ALLOCATE)) {
|
||||
mGradientTransform = new nsSVGAnimatedTransformList();
|
||||
mGradientTransform = new SVGAnimatedTransformList();
|
||||
}
|
||||
return mGradientTransform;
|
||||
}
|
||||
|
@ -7,11 +7,11 @@
|
||||
#define __NS_SVGGRADIENTELEMENT_H__
|
||||
|
||||
#include "nsIDOMSVGUnitTypes.h"
|
||||
#include "nsSVGAnimatedTransformList.h"
|
||||
#include "nsSVGElement.h"
|
||||
#include "nsSVGLength2.h"
|
||||
#include "nsSVGEnum.h"
|
||||
#include "nsSVGString.h"
|
||||
#include "SVGAnimatedTransformList.h"
|
||||
|
||||
static const unsigned short SVG_SPREADMETHOD_UNKNOWN = 0;
|
||||
static const unsigned short SVG_SPREADMETHOD_PAD = 1;
|
||||
@ -30,9 +30,10 @@ NS_NewSVGRadialGradientElement(nsIContent** aResult,
|
||||
already_AddRefed<nsINodeInfo> aNodeInfo);
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class SVGAnimatedTransformList;
|
||||
class DOMSVGAnimatedTransformList;
|
||||
|
||||
namespace dom {
|
||||
|
||||
//--------------------- Gradients------------------------
|
||||
|
||||
@ -55,7 +56,7 @@ public:
|
||||
// nsIContent
|
||||
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
|
||||
|
||||
virtual nsSVGAnimatedTransformList*
|
||||
virtual SVGAnimatedTransformList*
|
||||
GetAnimatedTransformList(uint32_t aFlags = 0);
|
||||
virtual nsIAtom* GetTransformListAttrName() const {
|
||||
return nsGkAtoms::gradientTransform;
|
||||
@ -63,7 +64,7 @@ public:
|
||||
|
||||
// WebIDL
|
||||
already_AddRefed<nsIDOMSVGAnimatedEnumeration> GradientUnits();
|
||||
already_AddRefed<SVGAnimatedTransformList> GradientTransform();
|
||||
already_AddRefed<DOMSVGAnimatedTransformList> GradientTransform();
|
||||
already_AddRefed<nsIDOMSVGAnimatedEnumeration> SpreadMethod();
|
||||
already_AddRefed<nsIDOMSVGAnimatedString> Href();
|
||||
|
||||
@ -81,7 +82,7 @@ protected:
|
||||
static StringInfo sStringInfo[1];
|
||||
|
||||
// SVGGradientElement values
|
||||
nsAutoPtr<nsSVGAnimatedTransformList> mGradientTransform;
|
||||
nsAutoPtr<SVGAnimatedTransformList> mGradientTransform;
|
||||
};
|
||||
|
||||
//---------------------Linear Gradients------------------------
|
||||
|
@ -5,12 +5,11 @@
|
||||
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "DOMSVGAnimatedTransformList.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "mozilla/dom/SVGAnimatedTransformList.h"
|
||||
#include "mozilla/dom/SVGPatternElement.h"
|
||||
#include "mozilla/dom/SVGPatternElementBinding.h"
|
||||
#include "nsSVGAnimatedTransformList.h"
|
||||
|
||||
NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Pattern)
|
||||
|
||||
@ -103,12 +102,12 @@ SVGPatternElement::PatternContentUnits()
|
||||
return mEnumAttributes[PATTERNCONTENTUNITS].ToDOMAnimatedEnum(this);
|
||||
}
|
||||
|
||||
already_AddRefed<SVGAnimatedTransformList>
|
||||
already_AddRefed<DOMSVGAnimatedTransformList>
|
||||
SVGPatternElement::PatternTransform()
|
||||
{
|
||||
// We're creating a DOM wrapper, so we must tell GetAnimatedTransformList
|
||||
// to allocate the SVGAnimatedTransformList if it hasn't already done so:
|
||||
return SVGAnimatedTransformList::GetDOMWrapper(
|
||||
return DOMSVGAnimatedTransformList::GetDOMWrapper(
|
||||
GetAnimatedTransformList(DO_ALLOCATE), this);
|
||||
}
|
||||
|
||||
@ -166,11 +165,11 @@ SVGPatternElement::IsAttributeMapped(const nsIAtom* name) const
|
||||
//----------------------------------------------------------------------
|
||||
// nsSVGElement methods
|
||||
|
||||
nsSVGAnimatedTransformList*
|
||||
SVGAnimatedTransformList*
|
||||
SVGPatternElement::GetAnimatedTransformList(uint32_t aFlags)
|
||||
{
|
||||
if (!mPatternTransform && (aFlags & DO_ALLOCATE)) {
|
||||
mPatternTransform = new nsSVGAnimatedTransformList();
|
||||
mPatternTransform = new SVGAnimatedTransformList();
|
||||
}
|
||||
return mPatternTransform;
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ nsresult NS_NewSVGPatternElement(nsIContent **aResult,
|
||||
already_AddRefed<nsINodeInfo> aNodeInfo);
|
||||
|
||||
namespace mozilla {
|
||||
class DOMSVGAnimatedTransformList;
|
||||
|
||||
namespace dom {
|
||||
class SVGAnimatedTransformList;
|
||||
|
||||
typedef nsSVGElement SVGPatternElementBase;
|
||||
|
||||
@ -40,6 +40,8 @@ protected:
|
||||
virtual JSObject* WrapNode(JSContext *cx, JSObject *scope) MOZ_OVERRIDE;
|
||||
|
||||
public:
|
||||
typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio;
|
||||
|
||||
// interfaces:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
@ -57,7 +59,7 @@ public:
|
||||
// nsSVGSVGElement methods:
|
||||
virtual bool HasValidDimensions() const;
|
||||
|
||||
virtual nsSVGAnimatedTransformList*
|
||||
virtual mozilla::SVGAnimatedTransformList*
|
||||
GetAnimatedTransformList(uint32_t aFlags = 0);
|
||||
virtual nsIAtom* GetTransformListAttrName() const {
|
||||
return nsGkAtoms::patternTransform;
|
||||
@ -68,7 +70,7 @@ public:
|
||||
already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
|
||||
already_AddRefed<nsIDOMSVGAnimatedEnumeration> PatternUnits();
|
||||
already_AddRefed<nsIDOMSVGAnimatedEnumeration> PatternContentUnits();
|
||||
already_AddRefed<SVGAnimatedTransformList> PatternTransform();
|
||||
already_AddRefed<DOMSVGAnimatedTransformList> PatternTransform();
|
||||
already_AddRefed<SVGAnimatedLength> X();
|
||||
already_AddRefed<SVGAnimatedLength> Y();
|
||||
already_AddRefed<SVGAnimatedLength> Width();
|
||||
@ -91,7 +93,7 @@ protected:
|
||||
nsSVGEnum mEnumAttributes[2];
|
||||
static EnumInfo sEnumInfo[2];
|
||||
|
||||
nsAutoPtr<nsSVGAnimatedTransformList> mPatternTransform;
|
||||
nsAutoPtr<mozilla::SVGAnimatedTransformList> mPatternTransform;
|
||||
|
||||
enum { HREF };
|
||||
nsSVGString mStringAttributes[1];
|
||||
|
@ -25,7 +25,7 @@ namespace mozilla {
|
||||
*/
|
||||
class SVGTransformList
|
||||
{
|
||||
friend class nsSVGAnimatedTransformList;
|
||||
friend class SVGAnimatedTransformList;
|
||||
friend class DOMSVGTransformList;
|
||||
friend class DOMSVGTransform;
|
||||
|
||||
|
@ -3,10 +3,10 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/SVGAnimatedTransformList.h"
|
||||
#include "mozilla/dom/SVGTransformableElement.h"
|
||||
#include "mozilla/dom/SVGMatrix.h"
|
||||
#include "mozilla/dom/SVGSVGElement.h"
|
||||
#include "DOMSVGAnimatedTransformList.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIDOMMutationEvent.h"
|
||||
#include "nsIFrame.h"
|
||||
@ -23,12 +23,12 @@ namespace dom {
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(SVGTransformableElement, nsSVGElement)
|
||||
|
||||
already_AddRefed<SVGAnimatedTransformList>
|
||||
already_AddRefed<DOMSVGAnimatedTransformList>
|
||||
SVGTransformableElement::Transform()
|
||||
{
|
||||
// We're creating a DOM wrapper, so we must tell GetAnimatedTransformList
|
||||
// to allocate the SVGAnimatedTransformList if it hasn't already done so:
|
||||
return SVGAnimatedTransformList::GetDOMWrapper(
|
||||
return DOMSVGAnimatedTransformList::GetDOMWrapper(
|
||||
GetAnimatedTransformList(DO_ALLOCATE), this).get();
|
||||
|
||||
}
|
||||
@ -139,11 +139,11 @@ SVGTransformableElement::SetAnimateMotionTransform(const gfxMatrix* aMatrix)
|
||||
DidAnimateTransformList();
|
||||
}
|
||||
|
||||
nsSVGAnimatedTransformList*
|
||||
SVGAnimatedTransformList*
|
||||
SVGTransformableElement::GetAnimatedTransformList(uint32_t aFlags)
|
||||
{
|
||||
if (!mTransforms && (aFlags & DO_ALLOCATE)) {
|
||||
mTransforms = new nsSVGAnimatedTransformList();
|
||||
mTransforms = new SVGAnimatedTransformList();
|
||||
}
|
||||
return mTransforms;
|
||||
}
|
||||
|
@ -6,16 +6,17 @@
|
||||
#ifndef SVGTransformableElement_h
|
||||
#define SVGTransformableElement_h
|
||||
|
||||
#include "nsSVGAnimatedTransformList.h"
|
||||
#include "nsSVGElement.h"
|
||||
#include "gfxMatrix.h"
|
||||
#include "SVGAnimatedTransformList.h"
|
||||
|
||||
class nsIDOMSVGRect;
|
||||
|
||||
namespace mozilla {
|
||||
class DOMSVGAnimatedTransformList;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class SVGAnimatedTransformList;
|
||||
class SVGGraphicsElement;
|
||||
class SVGMatrix;
|
||||
|
||||
@ -29,7 +30,7 @@ public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// WebIDL
|
||||
already_AddRefed<SVGAnimatedTransformList> Transform();
|
||||
already_AddRefed<DOMSVGAnimatedTransformList> Transform();
|
||||
nsSVGElement* GetNearestViewportElement();
|
||||
nsSVGElement* GetFarthestViewportElement();
|
||||
already_AddRefed<nsIDOMSVGRect> GetBBox(ErrorResult& rv);
|
||||
@ -53,7 +54,7 @@ public:
|
||||
virtual const gfxMatrix* GetAnimateMotionTransform() const;
|
||||
virtual void SetAnimateMotionTransform(const gfxMatrix* aMatrix);
|
||||
|
||||
virtual nsSVGAnimatedTransformList*
|
||||
virtual SVGAnimatedTransformList*
|
||||
GetAnimatedTransformList(uint32_t aFlags = 0);
|
||||
virtual nsIAtom* GetTransformListAttrName() const {
|
||||
return nsGkAtoms::transform;
|
||||
@ -62,7 +63,7 @@ public:
|
||||
protected:
|
||||
// nsSVGElement overrides
|
||||
|
||||
nsAutoPtr<nsSVGAnimatedTransformList> mTransforms;
|
||||
nsAutoPtr<SVGAnimatedTransformList> mTransforms;
|
||||
|
||||
// XXX maybe move this to property table, to save space on un-animated elems?
|
||||
nsAutoPtr<gfxMatrix> mAnimateMotionTransform;
|
||||
|
@ -1,321 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsSVGAnimatedTransformList.h"
|
||||
#include "mozilla/dom/SVGAnimatedTransformList.h"
|
||||
#include "mozilla/dom/SVGAnimationElement.h"
|
||||
#include "nsSMILValue.h"
|
||||
#include "prdtoa.h"
|
||||
#include "SVGContentUtils.h"
|
||||
#include "SVGTransform.h"
|
||||
#include "SVGTransformListSMILType.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace dom;
|
||||
|
||||
nsresult
|
||||
nsSVGAnimatedTransformList::SetBaseValueString(const nsAString& aValue)
|
||||
{
|
||||
SVGTransformList newBaseValue;
|
||||
nsresult rv = newBaseValue.SetValueFromString(aValue);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
SVGAnimatedTransformList *domWrapper =
|
||||
SVGAnimatedTransformList::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 Element::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 = true;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGAnimatedTransformList::ClearBaseValue()
|
||||
{
|
||||
SVGAnimatedTransformList *domWrapper =
|
||||
SVGAnimatedTransformList::GetDOMWrapperIfExists(this);
|
||||
if (domWrapper) {
|
||||
// We must send this notification *before* changing mBaseVal! (See above.)
|
||||
domWrapper->InternalBaseValListWillChangeLengthTo(0);
|
||||
}
|
||||
mBaseVal.Clear();
|
||||
mIsAttrSet = false;
|
||||
// Caller notifies
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSVGAnimatedTransformList::SetAnimValue(const SVGTransformList& aValue,
|
||||
nsSVGElement *aElement)
|
||||
{
|
||||
SVGAnimatedTransformList *domWrapper =
|
||||
SVGAnimatedTransformList::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 SVGAnimatedTransformList::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
|
||||
nsSVGAnimatedTransformList::ClearAnimValue(nsSVGElement *aElement)
|
||||
{
|
||||
SVGAnimatedTransformList *domWrapper =
|
||||
SVGAnimatedTransformList::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 = nullptr;
|
||||
aElement->DidAnimateTransformList();
|
||||
}
|
||||
|
||||
bool
|
||||
nsSVGAnimatedTransformList::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 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;
|
||||
}
|
||||
|
||||
nsISMILAttr*
|
||||
nsSVGAnimatedTransformList::ToSMILAttr(nsSVGElement* aSVGElement)
|
||||
{
|
||||
return new SMILAnimatedTransformList(this, aSVGElement);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSVGAnimatedTransformList::SMILAnimatedTransformList::ValueFromString(
|
||||
const nsAString& aStr,
|
||||
const dom::SVGAnimationElement* aSrcElement,
|
||||
nsSMILValue& aValue,
|
||||
bool& 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 = false;
|
||||
return aValue.IsNull() ? NS_ERROR_FAILURE : NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGAnimatedTransformList::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 };
|
||||
int32_t numParsed = ParseParameterList(aSpec, params, 3);
|
||||
uint16_t transformType;
|
||||
|
||||
if (aTransformType == nsGkAtoms::translate) {
|
||||
// tx [ty=0]
|
||||
if (numParsed != 1 && numParsed != 2)
|
||||
return;
|
||||
transformType = 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 = SVG_TRANSFORM_SCALE;
|
||||
} else if (aTransformType == nsGkAtoms::rotate) {
|
||||
// r [cx=0 cy=0]
|
||||
if (numParsed != 1 && numParsed != 3)
|
||||
return;
|
||||
transformType = SVG_TRANSFORM_ROTATE;
|
||||
} else if (aTransformType == nsGkAtoms::skewX) {
|
||||
// x-angle
|
||||
if (numParsed != 1)
|
||||
return;
|
||||
transformType = SVG_TRANSFORM_SKEWX;
|
||||
} else if (aTransformType == nsGkAtoms::skewY) {
|
||||
// y-angle
|
||||
if (numParsed != 1)
|
||||
return;
|
||||
transformType = 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
|
||||
|
||||
int32_t
|
||||
nsSVGAnimatedTransformList::SMILAnimatedTransformList::ParseParameterList(
|
||||
const nsAString& aSpec,
|
||||
float* aVars,
|
||||
int32_t 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
|
||||
nsSVGAnimatedTransformList::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
|
||||
nsSVGAnimatedTransformList::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
|
||||
nsSVGAnimatedTransformList::SMILAnimatedTransformList::ClearAnimValue()
|
||||
{
|
||||
if (mVal->mAnimVal) {
|
||||
mVal->ClearAnimValue(mElement);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -1,126 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef MOZILLA_SVGANIMATEDTRANSFORMLIST_H__
|
||||
#define MOZILLA_SVGANIMATEDTRANSFORMLIST_H__
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsISMILAttr.h"
|
||||
#include "SVGTransformList.h"
|
||||
|
||||
class nsIAtom;
|
||||
class nsSMILValue;
|
||||
class nsSVGElement;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
class SVGAnimationElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class nsSVGAnimatedTransformList
|
||||
*
|
||||
* 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
|
||||
* SVGAnimatedTransformList 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
|
||||
* SVGAnimatedTransformList::InternalBaseValListWillChangeTo) so that their
|
||||
* consumers don't need to concern themselves with that.
|
||||
*/
|
||||
class nsSVGAnimatedTransformList
|
||||
{
|
||||
// friends so that they can get write access to mBaseVal
|
||||
friend class DOMSVGTransform;
|
||||
friend class DOMSVGTransformList;
|
||||
|
||||
public:
|
||||
nsSVGAnimatedTransformList() : mIsAttrSet(false) { }
|
||||
|
||||
/**
|
||||
* Because it's so important that mBaseVal and its DOMSVGTransformList wrapper
|
||||
* (if any) be kept in sync (see the comment in
|
||||
* SVGAnimatedTransformList::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);
|
||||
|
||||
bool IsExplicitlySet() const;
|
||||
|
||||
bool IsAnimating() const {
|
||||
return !!mAnimVal;
|
||||
}
|
||||
|
||||
/// Callers own the returned nsISMILAttr
|
||||
nsISMILAttr* ToSMILAttr(nsSVGElement* aSVGElement);
|
||||
|
||||
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;
|
||||
bool mIsAttrSet;
|
||||
|
||||
struct SMILAnimatedTransformList : public nsISMILAttr
|
||||
{
|
||||
public:
|
||||
SMILAnimatedTransformList(nsSVGAnimatedTransformList* aVal,
|
||||
nsSVGElement* aSVGElement)
|
||||
: mVal(aVal)
|
||||
, mElement(aSVGElement)
|
||||
{}
|
||||
|
||||
// nsISMILAttr methods
|
||||
virtual nsresult ValueFromString(const nsAString& aStr,
|
||||
const dom::SVGAnimationElement* aSrcElement,
|
||||
nsSMILValue& aValue,
|
||||
bool& 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 int32_t ParseParameterList(const nsAString& aSpec, float* aVars,
|
||||
int32_t 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.
|
||||
nsSVGAnimatedTransformList* mVal;
|
||||
nsSVGElement* mElement;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // MOZILLA_SVGANIMATEDTRANSFORMLIST_H__
|
@ -24,7 +24,6 @@
|
||||
#include "nsCSSProps.h"
|
||||
#include "nsCSSParser.h"
|
||||
#include "nsEventListenerManager.h"
|
||||
#include "nsSVGAnimatedTransformList.h"
|
||||
#include "nsSVGLength2.h"
|
||||
#include "nsSVGNumber2.h"
|
||||
#include "nsSVGNumberPair.h"
|
||||
@ -39,6 +38,7 @@
|
||||
#include "SVGAnimatedLengthList.h"
|
||||
#include "SVGAnimatedPointList.h"
|
||||
#include "SVGAnimatedPathSegList.h"
|
||||
#include "SVGAnimatedTransformList.h"
|
||||
#include "SVGContentUtils.h"
|
||||
#include "nsIFrame.h"
|
||||
#include <stdarg.h>
|
||||
@ -589,8 +589,8 @@ nsSVGElement::ParseAttribute(int32_t aNamespaceID,
|
||||
// Check for SVGAnimatedTransformList attribute
|
||||
} else if (GetTransformListAttrName() == aAttribute) {
|
||||
// The transform attribute is being set, so we must ensure that the
|
||||
// nsSVGAnimatedTransformList is/has been allocated:
|
||||
nsSVGAnimatedTransformList *transformList =
|
||||
// SVGAnimatedTransformList is/has been allocated:
|
||||
SVGAnimatedTransformList *transformList =
|
||||
GetAnimatedTransformList(DO_ALLOCATE);
|
||||
rv = transformList->SetBaseValueString(aValue);
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -808,7 +808,7 @@ nsSVGElement::UnsetAttrInternal(int32_t aNamespaceID, nsIAtom* aName,
|
||||
|
||||
// Check if this is a transform list attribute going away
|
||||
if (GetTransformListAttrName() == aName) {
|
||||
nsSVGAnimatedTransformList *transformList = GetAnimatedTransformList();
|
||||
SVGAnimatedTransformList *transformList = GetAnimatedTransformList();
|
||||
if (transformList) {
|
||||
MaybeSerializeAttrBeforeRemoval(aName, aNotify);
|
||||
transformList->ClearBaseValue();
|
||||
|
@ -52,7 +52,7 @@ class SVGUserUnitList;
|
||||
class SVGAnimatedPointList;
|
||||
class SVGAnimatedPathSegList;
|
||||
class SVGAnimatedPreserveAspectRatio;
|
||||
class nsSVGAnimatedTransformList;
|
||||
class SVGAnimatedTransformList;
|
||||
class SVGStringList;
|
||||
class DOMSVGStringList;
|
||||
}
|
||||
@ -77,7 +77,7 @@ public:
|
||||
typedef mozilla::SVGAnimatedPointList SVGAnimatedPointList;
|
||||
typedef mozilla::SVGAnimatedPathSegList SVGAnimatedPathSegList;
|
||||
typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio;
|
||||
typedef mozilla::nsSVGAnimatedTransformList nsSVGAnimatedTransformList;
|
||||
typedef mozilla::SVGAnimatedTransformList SVGAnimatedTransformList;
|
||||
typedef mozilla::SVGStringList SVGStringList;
|
||||
|
||||
// nsISupports
|
||||
@ -262,18 +262,18 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
/**
|
||||
* Get the nsSVGAnimatedTransformList for this element.
|
||||
* Get the SVGAnimatedTransformList for this element.
|
||||
*
|
||||
* Despite the fact that animated transform lists are used for a variety of
|
||||
* attributes, no SVG element uses more than one.
|
||||
*
|
||||
* It's relatively uncommon for elements to have their transform attribute
|
||||
* set, so to save memory the nsSVGAnimatedTransformList is not allocated until
|
||||
* set, so to save memory the SVGAnimatedTransformList is not allocated until
|
||||
* the attribute is set/animated or its DOM wrapper is created. Callers that
|
||||
* require the nsSVGAnimatedTransformList to be allocated and for this method
|
||||
* require the SVGAnimatedTransformList to be allocated and for this method
|
||||
* to return non-null must pass the DO_ALLOCATE flag.
|
||||
*/
|
||||
virtual nsSVGAnimatedTransformList* GetAnimatedTransformList(
|
||||
virtual SVGAnimatedTransformList* GetAnimatedTransformList(
|
||||
uint32_t aFlags = 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -667,7 +667,8 @@ DOMInterfaces = {
|
||||
},
|
||||
|
||||
'SVGAnimatedTransformList': {
|
||||
'nativeOwnership': 'refcounted',
|
||||
'nativeType': 'mozilla::DOMSVGAnimatedTransformList',
|
||||
'headerFile': 'DOMSVGAnimatedTransformList.h'
|
||||
},
|
||||
|
||||
'SVGAnimationElement': {
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIDOMSVGAnimatedNumber.h"
|
||||
#include "nsSVGEffects.h"
|
||||
#include "nsSVGAnimatedTransformList.h"
|
||||
#include "SVGAnimatedTransformList.h"
|
||||
|
||||
// XXX Tight coupling with content classes ahead!
|
||||
|
||||
@ -157,10 +157,10 @@ nsSVGGradientFrame::GetSpreadMethod()
|
||||
return GetEnumValue(dom::SVGGradientElement::SPREADMETHOD);
|
||||
}
|
||||
|
||||
const nsSVGAnimatedTransformList*
|
||||
const SVGAnimatedTransformList*
|
||||
nsSVGGradientFrame::GetGradientTransformList(nsIContent* aDefault)
|
||||
{
|
||||
nsSVGAnimatedTransformList *thisTransformList =
|
||||
SVGAnimatedTransformList *thisTransformList =
|
||||
static_cast<dom::SVGGradientElement*>(mContent)->GetAnimatedTransformList();
|
||||
|
||||
if (thisTransformList && thisTransformList->IsExplicitlySet())
|
||||
@ -201,7 +201,7 @@ nsSVGGradientFrame::GetGradientTransform(nsIFrame *aSource,
|
||||
gfxMatrix(bbox.Width(), 0, 0, bbox.Height(), bbox.X(), bbox.Y());
|
||||
}
|
||||
|
||||
const nsSVGAnimatedTransformList* animTransformList =
|
||||
const SVGAnimatedTransformList* animTransformList =
|
||||
GetGradientTransformList(mContent);
|
||||
if (!animTransformList)
|
||||
return bboxMatrix;
|
||||
|
@ -22,7 +22,7 @@ class nsStyleContext;
|
||||
struct gfxRect;
|
||||
|
||||
namespace mozilla {
|
||||
class nsSVGAnimatedTransformList;
|
||||
class SVGAnimatedTransformList;
|
||||
|
||||
namespace dom {
|
||||
class SVGLinearGradientElement;
|
||||
@ -79,7 +79,7 @@ private:
|
||||
void GetStopInformation(int32_t aIndex,
|
||||
float *aOffset, nscolor *aColor, float *aStopOpacity);
|
||||
|
||||
const mozilla::nsSVGAnimatedTransformList* GetGradientTransformList(
|
||||
const mozilla::SVGAnimatedTransformList* GetGradientTransformList(
|
||||
nsIContent* aDefault);
|
||||
// Will be singular for gradientUnits="objectBoundingBox" with an empty bbox.
|
||||
gfxMatrix GetGradientTransform(nsIFrame *aSource,
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "nsSVGGeometryFrame.h"
|
||||
#include "mozilla/dom/SVGPatternElement.h"
|
||||
#include "nsSVGUtils.h"
|
||||
#include "nsSVGAnimatedTransformList.h"
|
||||
#include "SVGAnimatedTransformList.h"
|
||||
#include "SVGContentUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
@ -443,10 +443,10 @@ nsSVGPatternFrame::GetEnumValue(uint32_t aIndex, nsIContent *aDefault)
|
||||
mEnumAttributes[aIndex].GetAnimValue();
|
||||
}
|
||||
|
||||
nsSVGAnimatedTransformList*
|
||||
SVGAnimatedTransformList*
|
||||
nsSVGPatternFrame::GetPatternTransformList(nsIContent* aDefault)
|
||||
{
|
||||
nsSVGAnimatedTransformList *thisTransformList =
|
||||
SVGAnimatedTransformList *thisTransformList =
|
||||
static_cast<SVGPatternElement *>(mContent)->GetAnimatedTransformList();
|
||||
|
||||
if (thisTransformList && thisTransformList->IsExplicitlySet())
|
||||
@ -462,7 +462,7 @@ nsSVGPatternFrame::GetPatternTransformList(nsIContent* aDefault)
|
||||
gfxMatrix
|
||||
nsSVGPatternFrame::GetPatternTransform()
|
||||
{
|
||||
nsSVGAnimatedTransformList* animTransformList =
|
||||
SVGAnimatedTransformList* animTransformList =
|
||||
GetPatternTransformList(mContent);
|
||||
if (!animTransformList)
|
||||
return gfxMatrix();
|
||||
|
@ -18,7 +18,7 @@ class nsSVGViewBox;
|
||||
|
||||
namespace mozilla {
|
||||
class SVGAnimatedPreserveAspectRatio;
|
||||
class nsSVGAnimatedTransformList;
|
||||
class SVGAnimatedTransformList;
|
||||
} // namespace mozilla
|
||||
|
||||
typedef nsSVGPaintServerFrame nsSVGPatternFrameBase;
|
||||
@ -90,7 +90,7 @@ protected:
|
||||
{
|
||||
return GetEnumValue(aIndex, mContent);
|
||||
}
|
||||
mozilla::nsSVGAnimatedTransformList* GetPatternTransformList(
|
||||
mozilla::SVGAnimatedTransformList* GetPatternTransformList(
|
||||
nsIContent* aDefault);
|
||||
gfxMatrix GetPatternTransform();
|
||||
const nsSVGViewBox &GetViewBox(nsIContent *aDefault);
|
||||
|
Loading…
Reference in New Issue
Block a user