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_SVGNUMBERLIST_H__
8 : #define MOZILLA_SVGNUMBERLIST_H__
9 :
10 : #include "nsCOMPtr.h"
11 : #include "nsDebug.h"
12 : #include "nsIContent.h"
13 : #include "nsINode.h"
14 : #include "nsIWeakReferenceUtils.h"
15 : #include "nsSVGElement.h"
16 : #include "nsTArray.h"
17 :
18 : namespace mozilla {
19 :
20 : /**
21 : * ATTENTION! WARNING! WATCH OUT!!
22 : *
23 : * Consumers that modify objects of this type absolutely MUST keep the DOM
24 : * wrappers for those lists (if any) in sync!! That's why this class is so
25 : * locked down.
26 : *
27 : * The DOM wrapper class for this class is DOMSVGNumberList.
28 : */
29 : class SVGNumberList
30 : {
31 : friend class SVGAnimatedNumberList;
32 : friend class DOMSVGNumberList;
33 : friend class DOMSVGNumber;
34 :
35 : public:
36 :
37 0 : SVGNumberList(){}
38 0 : ~SVGNumberList(){}
39 :
40 : // Only methods that don't make/permit modification to this list are public.
41 : // Only our friend classes can access methods that may change us.
42 :
43 : /// This may return an incomplete string on OOM, but that's acceptable.
44 : void GetValueAsString(nsAString& aValue) const;
45 :
46 0 : bool IsEmpty() const {
47 0 : return mNumbers.IsEmpty();
48 : }
49 :
50 0 : uint32_t Length() const {
51 0 : return mNumbers.Length();
52 : }
53 :
54 0 : const float& operator[](uint32_t aIndex) const {
55 0 : return mNumbers[aIndex];
56 : }
57 :
58 0 : bool operator==(const SVGNumberList& rhs) const {
59 0 : return mNumbers == rhs.mNumbers;
60 : }
61 :
62 0 : bool SetCapacity(uint32_t size) {
63 0 : return mNumbers.SetCapacity(size, fallible);
64 : }
65 :
66 : void Compact() {
67 : mNumbers.Compact();
68 : }
69 :
70 : // Access to methods that can modify objects of this type is deliberately
71 : // limited. This is to reduce the chances of someone modifying objects of
72 : // this type without taking the necessary steps to keep DOM wrappers in sync.
73 : // If you need wider access to these methods, consider adding a method to
74 : // SVGAnimatedNumberList and having that class act as an intermediary so it
75 : // can take care of keeping DOM wrappers in sync.
76 :
77 : protected:
78 :
79 : /**
80 : * This may fail on OOM if the internal capacity needs to be increased, in
81 : * which case the list will be left unmodified.
82 : */
83 : nsresult CopyFrom(const SVGNumberList& rhs);
84 :
85 0 : float& operator[](uint32_t aIndex) {
86 0 : return mNumbers[aIndex];
87 : }
88 :
89 : /**
90 : * This may fail (return false) on OOM if the internal capacity is being
91 : * increased, in which case the list will be left unmodified.
92 : */
93 0 : bool SetLength(uint32_t aNumberOfItems) {
94 0 : return mNumbers.SetLength(aNumberOfItems, fallible);
95 : }
96 :
97 : private:
98 :
99 : // Marking the following private only serves to show which methods are only
100 : // used by our friend classes (as opposed to our subclasses) - it doesn't
101 : // really provide additional safety.
102 :
103 : nsresult SetValueFromString(const nsAString& aValue);
104 :
105 0 : void Clear() {
106 0 : mNumbers.Clear();
107 0 : }
108 :
109 0 : bool InsertItem(uint32_t aIndex, const float &aNumber) {
110 0 : if (aIndex >= mNumbers.Length()) {
111 0 : aIndex = mNumbers.Length();
112 : }
113 0 : return !!mNumbers.InsertElementAt(aIndex, aNumber, fallible);
114 : }
115 :
116 : void ReplaceItem(uint32_t aIndex, const float &aNumber) {
117 : MOZ_ASSERT(aIndex < mNumbers.Length(),
118 : "DOM wrapper caller should have raised INDEX_SIZE_ERR");
119 : mNumbers[aIndex] = aNumber;
120 : }
121 :
122 0 : void RemoveItem(uint32_t aIndex) {
123 0 : MOZ_ASSERT(aIndex < mNumbers.Length(),
124 : "DOM wrapper caller should have raised INDEX_SIZE_ERR");
125 0 : mNumbers.RemoveElementAt(aIndex);
126 0 : }
127 :
128 0 : bool AppendItem(float aNumber) {
129 0 : return !!mNumbers.AppendElement(aNumber, fallible);
130 : }
131 :
132 : protected:
133 :
134 : /* See SVGLengthList for the rationale for using FallibleTArray<float> instead
135 : * of FallibleTArray<float, 1>.
136 : */
137 : FallibleTArray<float> mNumbers;
138 : };
139 :
140 :
141 : /**
142 : * This SVGNumberList subclass is used by the SMIL code when a number list
143 : * is to be stored in an nsISMILValue instance. Since nsISMILValue objects may
144 : * be cached, it is necessary for us to hold a strong reference to our element
145 : * so that it doesn't disappear out from under us if, say, the element is
146 : * removed from the DOM tree.
147 : */
148 0 : class SVGNumberListAndInfo : public SVGNumberList
149 : {
150 : public:
151 :
152 0 : SVGNumberListAndInfo()
153 0 : : mElement(nullptr)
154 0 : {}
155 :
156 : explicit SVGNumberListAndInfo(nsSVGElement *aElement)
157 : : mElement(do_GetWeakReference(static_cast<nsINode*>(aElement)))
158 : {}
159 :
160 0 : void SetInfo(nsSVGElement *aElement) {
161 0 : mElement = do_GetWeakReference(static_cast<nsINode*>(aElement));
162 0 : }
163 :
164 0 : nsSVGElement* Element() const {
165 0 : nsCOMPtr<nsIContent> e = do_QueryReferent(mElement);
166 0 : return static_cast<nsSVGElement*>(e.get());
167 : }
168 :
169 0 : nsresult CopyFrom(const SVGNumberListAndInfo& rhs) {
170 0 : mElement = rhs.mElement;
171 0 : return SVGNumberList::CopyFrom(rhs);
172 : }
173 :
174 : // Instances of this special subclass do not have DOM wrappers that we need
175 : // to worry about keeping in sync, so it's safe to expose any hidden base
176 : // class methods required by the SMIL code, as we do below.
177 :
178 : /**
179 : * Exposed so that SVGNumberList baseVals can be copied to
180 : * SVGNumberListAndInfo objects. Note that callers should also call
181 : * SetInfo() when using this method!
182 : */
183 0 : nsresult CopyFrom(const SVGNumberList& rhs) {
184 0 : return SVGNumberList::CopyFrom(rhs);
185 : }
186 0 : const float& operator[](uint32_t aIndex) const {
187 0 : return SVGNumberList::operator[](aIndex);
188 : }
189 0 : float& operator[](uint32_t aIndex) {
190 0 : return SVGNumberList::operator[](aIndex);
191 : }
192 0 : bool SetLength(uint32_t aNumberOfItems) {
193 0 : return SVGNumberList::SetLength(aNumberOfItems);
194 : }
195 :
196 : private:
197 : // We must keep a weak reference to our element because we may belong to a
198 : // cached baseVal nsSMILValue. See the comments starting at:
199 : // https://bugzilla.mozilla.org/show_bug.cgi?id=515116#c15
200 : // See also https://bugzilla.mozilla.org/show_bug.cgi?id=653497
201 : nsWeakPtr mElement;
202 : };
203 :
204 : } // namespace mozilla
205 :
206 : #endif // MOZILLA_SVGNUMBERLIST_H__
|