Line data Source code
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/. */
6 :
7 : #ifndef MOZILLA_DOMSVGTRANSFORMLIST_H__
8 : #define MOZILLA_DOMSVGTRANSFORMLIST_H__
9 :
10 : #include "mozilla/dom/SVGAnimatedTransformList.h"
11 : #include "nsCycleCollectionParticipant.h"
12 : #include "nsDebug.h"
13 : #include "nsTArray.h"
14 : #include "SVGTransformList.h"
15 : #include "mozilla/Attributes.h"
16 : #include "mozilla/ErrorResult.h"
17 :
18 : class nsSVGElement;
19 :
20 : namespace mozilla {
21 :
22 : namespace dom {
23 : class SVGMatrix;
24 : class SVGTransform;
25 : } // namespace dom
26 :
27 : /**
28 : * Class DOMSVGTransformList
29 : *
30 : * This class is used to create the DOM tearoff objects that wrap internal
31 : * SVGTransformList objects.
32 : *
33 : * See the architecture comment in SVGAnimatedTransformList.h.
34 : */
35 : class DOMSVGTransformList final : public nsISupports,
36 : public nsWrapperCache
37 : {
38 : friend class AutoChangeTransformListNotifier;
39 : friend class dom::SVGTransform;
40 :
41 0 : ~DOMSVGTransformList() {
42 : // Our mAList's weak ref to us must be nulled out when we die. If GC has
43 : // unlinked us using the cycle collector code, then that has already
44 : // happened, and mAList is null.
45 0 : if (mAList) {
46 0 : ( IsAnimValList() ? mAList->mAnimVal : mAList->mBaseVal ) = nullptr;
47 : }
48 0 : }
49 :
50 : public:
51 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
52 0 : NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGTransformList)
53 :
54 0 : DOMSVGTransformList(dom::SVGAnimatedTransformList *aAList,
55 : const SVGTransformList &aInternalList)
56 0 : : mAList(aAList)
57 : {
58 : // aInternalList must be passed in explicitly because we can't use
59 : // InternalList() here. (Because it depends on IsAnimValList, which depends
60 : // on this object having been assigned to aAList's mBaseVal or mAnimVal,
61 : // which hasn't happend yet.)
62 :
63 0 : InternalListLengthWillChange(aInternalList.Length()); // Sync mItems
64 0 : }
65 :
66 : virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
67 :
68 0 : nsISupports* GetParentObject()
69 : {
70 0 : return static_cast<nsIContent*>(Element());
71 : }
72 :
73 : /**
74 : * This will normally be the same as InternalList().Length(), except if we've
75 : * hit OOM in which case our length will be zero.
76 : */
77 0 : uint32_t LengthNoFlush() const {
78 0 : MOZ_ASSERT(mItems.IsEmpty() || mItems.Length() == InternalList().Length(),
79 : "DOM wrapper's list length is out of sync");
80 0 : return mItems.Length();
81 : }
82 :
83 : /// Called to notify us to synchronize our length and detach excess items.
84 : void InternalListLengthWillChange(uint32_t aNewLength);
85 :
86 : /**
87 : * Returns true if our attribute is animating (in which case our animVal is
88 : * not simply a mirror of our baseVal).
89 : */
90 0 : bool IsAnimating() const {
91 0 : return mAList->IsAnimating();
92 : }
93 : /**
94 : * Returns true if there is an animated list mirroring the base list.
95 : */
96 0 : bool AnimListMirrorsBaseList() const {
97 0 : return mAList->mAnimVal && !mAList->IsAnimating();
98 : }
99 :
100 0 : uint32_t NumberOfItems() const
101 : {
102 0 : if (IsAnimValList()) {
103 0 : Element()->FlushAnimations();
104 : }
105 0 : return LengthNoFlush();
106 : }
107 : void Clear(ErrorResult& error);
108 : already_AddRefed<dom::SVGTransform> Initialize(dom::SVGTransform& newItem,
109 : ErrorResult& error);
110 : already_AddRefed<dom::SVGTransform> GetItem(uint32_t index,
111 : ErrorResult& error);
112 : already_AddRefed<dom::SVGTransform> IndexedGetter(uint32_t index, bool& found,
113 : ErrorResult& error);
114 : already_AddRefed<dom::SVGTransform> InsertItemBefore(dom::SVGTransform& newItem,
115 : uint32_t index,
116 : ErrorResult& error);
117 : already_AddRefed<dom::SVGTransform> ReplaceItem(dom::SVGTransform& newItem,
118 : uint32_t index,
119 : ErrorResult& error);
120 : already_AddRefed<dom::SVGTransform> RemoveItem(uint32_t index,
121 : ErrorResult& error);
122 0 : already_AddRefed<dom::SVGTransform> AppendItem(dom::SVGTransform& newItem,
123 : ErrorResult& error)
124 : {
125 0 : return InsertItemBefore(newItem, LengthNoFlush(), error);
126 : }
127 : already_AddRefed<dom::SVGTransform> CreateSVGTransformFromMatrix(dom::SVGMatrix& matrix);
128 : already_AddRefed<dom::SVGTransform> Consolidate(ErrorResult& error);
129 0 : uint32_t Length() const
130 : {
131 0 : return NumberOfItems();
132 : }
133 :
134 : private:
135 :
136 0 : nsSVGElement* Element() const {
137 0 : return mAList->mElement;
138 : }
139 :
140 : /// Used to determine if this list is the baseVal or animVal list.
141 0 : bool IsAnimValList() const {
142 0 : MOZ_ASSERT(this == mAList->mBaseVal || this == mAList->mAnimVal,
143 : "Calling IsAnimValList() too early?!");
144 0 : return this == mAList->mAnimVal;
145 : }
146 :
147 : /**
148 : * Get a reference to this object's corresponding internal SVGTransformList.
149 : *
150 : * To simplify the code we just have this one method for obtaining both
151 : * baseVal and animVal internal lists. This means that animVal lists don't
152 : * get const protection, but our setter methods guard against changing
153 : * animVal lists.
154 : */
155 : SVGTransformList& InternalList() const;
156 :
157 : /// Returns the SVGTransform at aIndex, creating it if necessary.
158 : already_AddRefed<dom::SVGTransform> GetItemAt(uint32_t aIndex);
159 :
160 : void MaybeInsertNullInAnimValListAt(uint32_t aIndex);
161 : void MaybeRemoveItemFromAnimValListAt(uint32_t aIndex);
162 :
163 : // Weak refs to our SVGTransform items. The items are friends and take care
164 : // of clearing our pointer to them when they die.
165 : FallibleTArray<dom::SVGTransform*> mItems;
166 :
167 : RefPtr<dom::SVGAnimatedTransformList> mAList;
168 : };
169 :
170 : } // namespace mozilla
171 :
172 : #endif // MOZILLA_DOMSVGTRANSFORMLIST_H__
|