1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef DOM_SVG_DOMSVGTRANSFORMLIST_H_
8 #define DOM_SVG_DOMSVGTRANSFORMLIST_H_
10 #include "DOMSVGAnimatedTransformList.h"
11 #include "mozAutoDocUpdate.h"
12 #include "nsCycleCollectionParticipant.h"
14 #include "SVGTransformList.h"
16 #include "mozilla/Attributes.h"
22 struct DOMMatrix2DInit
;
23 class DOMSVGTransform
;
27 //----------------------------------------------------------------------
28 // Helper class: AutoChangeTransformListNotifier
29 // Stack-based helper class to pair calls to WillChangeTransformList and
30 // DidChangeTransformList. Used by DOMSVGTransform and DOMSVGTransformList.
32 class MOZ_RAII AutoChangeTransformListNotifier
{
34 explicit AutoChangeTransformListNotifier(T
* aValue
) : mValue(aValue
) {
35 MOZ_ASSERT(mValue
, "Expecting non-null value");
36 // If we don't have an owner then changes don't affect anything else.
37 if (mValue
->HasOwner()) {
38 mUpdateBatch
.emplace(mValue
->Element()->GetComposedDoc(), true);
40 mValue
->Element()->WillChangeTransformList(mUpdateBatch
.ref());
44 ~AutoChangeTransformListNotifier() {
45 if (mValue
->HasOwner()) {
46 mValue
->Element()->DidChangeTransformList(mEmptyOrOldValue
,
48 if (mValue
->IsAnimating()) {
49 mValue
->Element()->AnimationNeedsResample();
56 Maybe
<mozAutoDocUpdate
> mUpdateBatch
;
57 nsAttrValue mEmptyOrOldValue
;
61 * Class DOMSVGTransformList
63 * This class is used to create the DOM tearoff objects that wrap internal
64 * SVGTransformList objects.
66 * See the architecture comment in DOMSVGAnimatedTransformList.h.
68 class DOMSVGTransformList final
: public nsISupports
, public nsWrapperCache
{
70 friend class AutoChangeTransformListNotifier
;
71 friend class dom::DOMSVGTransform
;
73 ~DOMSVGTransformList() {
74 // Our mAList's weak ref to us must be nulled out when we die. If GC has
75 // unlinked us using the cycle collector code, then that has already
76 // happened, and mAList is null.
78 (IsAnimValList() ? mAList
->mAnimVal
: mAList
->mBaseVal
) = nullptr;
83 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
84 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGTransformList
)
86 DOMSVGTransformList(dom::DOMSVGAnimatedTransformList
* aAList
,
87 const SVGTransformList
& aInternalList
)
89 // aInternalList must be passed in explicitly because we can't use
90 // InternalList() here. (Because it depends on IsAnimValList, which depends
91 // on this object having been assigned to aAList's mBaseVal or mAnimVal,
92 // which hasn't happened yet.)
94 InternalListLengthWillChange(aInternalList
.Length()); // Sync mItems
97 JSObject
* WrapObject(JSContext
* cx
,
98 JS::Handle
<JSObject
*> aGivenProto
) override
;
100 nsISupports
* GetParentObject() { return static_cast<nsIContent
*>(Element()); }
103 * This will normally be the same as InternalList().Length(), except if we've
104 * hit OOM in which case our length will be zero.
106 uint32_t LengthNoFlush() const {
107 MOZ_ASSERT(mItems
.IsEmpty() || mItems
.Length() == InternalList().Length(),
108 "DOM wrapper's list length is out of sync");
109 return mItems
.Length();
112 /// Called to notify us to synchronize our length and detach excess items.
113 void InternalListLengthWillChange(uint32_t aNewLength
);
116 * List classes always have an owner. We need this so that templates that work
117 * on lists and elements can check ownership where elements may be unowned.
119 bool HasOwner() const { return true; }
122 * Returns true if our attribute is animating (in which case our animVal is
123 * not simply a mirror of our baseVal).
125 bool IsAnimating() const { return mAList
->IsAnimating(); }
127 * Returns true if there is an animated list mirroring the base list.
129 bool AnimListMirrorsBaseList() const {
130 return mAList
->mAnimVal
&& !mAList
->IsAnimating();
133 uint32_t NumberOfItems() const {
134 if (IsAnimValList()) {
135 Element()->FlushAnimations();
137 return LengthNoFlush();
139 void Clear(ErrorResult
& error
);
140 already_AddRefed
<dom::DOMSVGTransform
> Initialize(
141 dom::DOMSVGTransform
& newItem
, ErrorResult
& error
);
142 already_AddRefed
<dom::DOMSVGTransform
> GetItem(uint32_t index
,
144 already_AddRefed
<dom::DOMSVGTransform
> IndexedGetter(uint32_t index
,
147 already_AddRefed
<dom::DOMSVGTransform
> InsertItemBefore(
148 dom::DOMSVGTransform
& newItem
, uint32_t index
, ErrorResult
& error
);
149 already_AddRefed
<dom::DOMSVGTransform
> ReplaceItem(
150 dom::DOMSVGTransform
& newItem
, uint32_t index
, ErrorResult
& error
);
151 already_AddRefed
<dom::DOMSVGTransform
> RemoveItem(uint32_t index
,
153 already_AddRefed
<dom::DOMSVGTransform
> AppendItem(
154 dom::DOMSVGTransform
& newItem
, ErrorResult
& error
) {
155 return InsertItemBefore(newItem
, LengthNoFlush(), error
);
157 already_AddRefed
<dom::DOMSVGTransform
> CreateSVGTransformFromMatrix(
158 const DOMMatrix2DInit
& aMatrix
, ErrorResult
& aRv
);
159 already_AddRefed
<dom::DOMSVGTransform
> Consolidate(ErrorResult
& error
);
160 uint32_t Length() const { return NumberOfItems(); }
163 dom::SVGElement
* Element() const { return mAList
->mElement
; }
165 /// Used to determine if this list is the baseVal or animVal list.
166 bool IsAnimValList() const {
167 MOZ_ASSERT(this == mAList
->mBaseVal
|| this == mAList
->mAnimVal
,
168 "Calling IsAnimValList() too early?!");
169 return this == mAList
->mAnimVal
;
173 * Get a reference to this object's corresponding internal SVGTransformList.
175 * To simplify the code we just have this one method for obtaining both
176 * baseVal and animVal internal lists. This means that animVal lists don't
177 * get const protection, but our setter methods guard against changing
180 SVGTransformList
& InternalList() const;
182 /// Returns the DOMSVGTransform at aIndex, creating it if necessary.
183 already_AddRefed
<dom::DOMSVGTransform
> GetItemAt(uint32_t aIndex
);
185 void MaybeInsertNullInAnimValListAt(uint32_t aIndex
);
186 void MaybeRemoveItemFromAnimValListAt(uint32_t aIndex
);
188 // Weak refs to our DOMSVGTransform items. The items are friends and take care
189 // of clearing our pointer to them when they die.
190 FallibleTArray
<dom::DOMSVGTransform
*> mItems
;
192 RefPtr
<dom::DOMSVGAnimatedTransformList
> mAList
;
196 } // namespace mozilla
198 #endif // DOM_SVG_DOMSVGTRANSFORMLIST_H_