Merge mozilla-central to autoland on a CLOSED TREE
[gecko.git] / dom / svg / DOMSVGTransformList.h
blob2bfb975c718ea244a652c18b9158b1787d813239
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"
13 #include "nsDebug.h"
14 #include "SVGTransformList.h"
15 #include "nsTArray.h"
16 #include "mozilla/Attributes.h"
18 namespace mozilla {
19 class ErrorResult;
21 namespace dom {
22 struct DOMMatrix2DInit;
23 class DOMSVGTransform;
24 class SVGElement;
25 class SVGMatrix;
27 //----------------------------------------------------------------------
28 // Helper class: AutoChangeTransformListNotifier
29 // Stack-based helper class to pair calls to WillChangeTransformList and
30 // DidChangeTransformList. Used by DOMSVGTransform and DOMSVGTransformList.
31 template <class T>
32 class MOZ_RAII AutoChangeTransformListNotifier {
33 public:
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);
39 mEmptyOrOldValue =
40 mValue->Element()->WillChangeTransformList(mUpdateBatch.ref());
44 ~AutoChangeTransformListNotifier() {
45 if (mValue->HasOwner()) {
46 mValue->Element()->DidChangeTransformList(mEmptyOrOldValue,
47 mUpdateBatch.ref());
48 if (mValue->IsAnimating()) {
49 mValue->Element()->AnimationNeedsResample();
54 private:
55 T* const mValue;
56 Maybe<mozAutoDocUpdate> mUpdateBatch;
57 nsAttrValue mEmptyOrOldValue;
60 /**
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 {
69 template <class T>
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.
77 if (mAList) {
78 (IsAnimValList() ? mAList->mAnimVal : mAList->mBaseVal) = nullptr;
82 public:
83 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
84 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGTransformList)
86 DOMSVGTransformList(dom::DOMSVGAnimatedTransformList* aAList,
87 const SVGTransformList& aInternalList)
88 : mAList(aAList) {
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,
143 ErrorResult& error);
144 already_AddRefed<dom::DOMSVGTransform> IndexedGetter(uint32_t index,
145 bool& found,
146 ErrorResult& error);
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,
152 ErrorResult& error);
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(); }
162 private:
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
178 * animVal lists.
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;
195 } // namespace dom
196 } // namespace mozilla
198 #endif // DOM_SVG_DOMSVGTRANSFORMLIST_H_