Merge mozilla-central to autoland on a CLOSED TREE
[gecko.git] / dom / svg / SVGPointList.h
blob5ece6207ed39f49e118f07fa04740dd571636892
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_SVGPOINTLIST_H_
8 #define DOM_SVG_SVGPOINTLIST_H_
10 #include "nsCOMPtr.h"
11 #include "nsDebug.h"
12 #include "nsIContent.h"
13 #include "nsINode.h"
14 #include "nsIWeakReferenceUtils.h"
15 #include "SVGElement.h"
16 #include "nsTArray.h"
17 #include "SVGPoint.h"
19 #include <string.h>
21 namespace mozilla {
23 namespace dom {
24 class DOMSVGPoint;
25 class DOMSVGPointList;
26 } // namespace dom
28 /**
29 * ATTENTION! WARNING! WATCH OUT!!
31 * Consumers that modify objects of this type absolutely MUST keep the DOM
32 * wrappers for those lists (if any) in sync!! That's why this class is so
33 * locked down.
35 * The DOM wrapper class for this class is DOMSVGPointList.
37 class SVGPointList {
38 friend class SVGAnimatedPointList;
39 friend class dom::DOMSVGPointList;
40 friend class dom::DOMSVGPoint;
42 public:
43 SVGPointList() = default;
44 ~SVGPointList() = default;
46 SVGPointList& operator=(const SVGPointList& aOther) {
47 mItems.ClearAndRetainStorage();
48 // Best-effort, really.
49 Unused << mItems.AppendElements(aOther.mItems, fallible);
50 return *this;
53 SVGPointList(const SVGPointList& aOther) { *this = aOther; }
55 // Only methods that don't make/permit modification to this list are public.
56 // Only our friend classes can access methods that may change us.
58 /// This may return an incomplete string on OOM, but that's acceptable.
59 void GetValueAsString(nsAString& aValue) const;
61 bool IsEmpty() const { return mItems.IsEmpty(); }
63 uint32_t Length() const { return mItems.Length(); }
65 const SVGPoint& operator[](uint32_t aIndex) const { return mItems[aIndex]; }
67 bool operator==(const SVGPointList& rhs) const {
68 // memcmp can be faster than |mItems == rhs.mItems|
69 return mItems.Length() == rhs.mItems.Length() &&
70 memcmp(mItems.Elements(), rhs.mItems.Elements(),
71 mItems.Length() * sizeof(SVGPoint)) == 0;
74 bool SetCapacity(uint32_t aSize) {
75 return mItems.SetCapacity(aSize, fallible);
78 void Compact() { mItems.Compact(); }
80 // Access to methods that can modify objects of this type is deliberately
81 // limited. This is to reduce the chances of someone modifying objects of
82 // this type without taking the necessary steps to keep DOM wrappers in sync.
83 // If you need wider access to these methods, consider adding a method to
84 // SVGAnimatedPointList and having that class act as an intermediary so it
85 // can take care of keeping DOM wrappers in sync.
87 protected:
88 /**
89 * This may fail on OOM if the internal capacity needs to be increased, in
90 * which case the list will be left unmodified.
92 nsresult CopyFrom(const SVGPointList& rhs);
93 void SwapWith(SVGPointList& aRhs) { mItems.SwapElements(aRhs.mItems); }
95 SVGPoint& operator[](uint32_t aIndex) { return mItems[aIndex]; }
97 /**
98 * This may fail (return false) on OOM if the internal capacity is being
99 * increased, in which case the list will be left unmodified.
101 bool SetLength(uint32_t aNumberOfItems) {
102 return mItems.SetLength(aNumberOfItems, fallible);
105 private:
106 // Marking the following private only serves to show which methods are only
107 // used by our friend classes (as opposed to our subclasses) - it doesn't
108 // really provide additional safety.
110 nsresult SetValueFromString(const nsAString& aValue);
112 void Clear() { mItems.Clear(); }
114 bool InsertItem(uint32_t aIndex, const SVGPoint& aPoint) {
115 if (aIndex >= mItems.Length()) {
116 aIndex = mItems.Length();
118 return !!mItems.InsertElementAt(aIndex, aPoint, fallible);
121 void ReplaceItem(uint32_t aIndex, const SVGPoint& aPoint) {
122 MOZ_ASSERT(aIndex < mItems.Length(),
123 "DOM wrapper caller should have raised INDEX_SIZE_ERR");
124 mItems[aIndex] = aPoint;
127 void RemoveItem(uint32_t aIndex) {
128 MOZ_ASSERT(aIndex < mItems.Length(),
129 "DOM wrapper caller should have raised INDEX_SIZE_ERR");
130 mItems.RemoveElementAt(aIndex);
133 bool AppendItem(SVGPoint aPoint) {
134 return !!mItems.AppendElement(aPoint, fallible);
137 protected:
138 /* See SVGLengthList for the rationale for using FallibleTArray<SVGPoint>
139 * instead of FallibleTArray<SVGPoint, 1>.
141 FallibleTArray<SVGPoint> mItems;
145 * This SVGPointList subclass is for SVGPointListSMILType which needs a
146 * mutable version of SVGPointList. Instances of this class do not have
147 * DOM wrappers that need to be kept in sync, so we can safely expose any
148 * protected base class methods required by the SMIL code.
150 * This class contains a strong reference to the element that instances of
151 * this class are being used to animate. This is because the SMIL code stores
152 * instances of this class in SMILValue objects, some of which are cached.
153 * Holding a strong reference to the element here prevents the element from
154 * disappearing out from under the SMIL code unexpectedly.
156 class SVGPointListAndInfo : public SVGPointList {
157 public:
158 explicit SVGPointListAndInfo(dom::SVGElement* aElement = nullptr)
159 : mElement(do_GetWeakReference(static_cast<nsINode*>(aElement))) {}
161 void SetInfo(dom::SVGElement* aElement) {
162 mElement = do_GetWeakReference(static_cast<nsINode*>(aElement));
165 dom::SVGElement* Element() const {
166 nsCOMPtr<nsIContent> e = do_QueryReferent(mElement);
167 return static_cast<dom::SVGElement*>(e.get());
171 * Returns true if this object is an "identity" value, from the perspective
172 * of SMIL. In other words, returns true until the initial value set up in
173 * SVGPointListSMILType::Init() has been changed with a SetInfo() call.
175 bool IsIdentity() const {
176 if (!mElement) {
177 MOZ_ASSERT(IsEmpty(), "target element propagation failure");
178 return true;
180 return false;
183 nsresult CopyFrom(const SVGPointListAndInfo& rhs) {
184 mElement = rhs.mElement;
185 return SVGPointList::CopyFrom(rhs);
189 * Exposed so that SVGPointList baseVals can be copied to
190 * SVGPointListAndInfo objects. Note that callers should also call
191 * SetElement() when using this method!
193 nsresult CopyFrom(const SVGPointList& rhs) {
194 return SVGPointList::CopyFrom(rhs);
196 const SVGPoint& operator[](uint32_t aIndex) const {
197 return SVGPointList::operator[](aIndex);
199 SVGPoint& operator[](uint32_t aIndex) {
200 return SVGPointList::operator[](aIndex);
202 bool SetLength(uint32_t aNumberOfItems) {
203 return SVGPointList::SetLength(aNumberOfItems);
206 private:
207 // We must keep a weak reference to our element because we may belong to a
208 // cached baseVal SMILValue. See the comments starting at:
209 // https://bugzilla.mozilla.org/show_bug.cgi?id=515116#c15
210 // See also https://bugzilla.mozilla.org/show_bug.cgi?id=653497
211 nsWeakPtr mElement;
214 } // namespace mozilla
216 #endif // DOM_SVG_SVGPOINTLIST_H_