DOMSVGPointList.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef MOZILLA_DOMSVGPOINTLIST_H__
  6. #define MOZILLA_DOMSVGPOINTLIST_H__
  7. #include "nsCOMPtr.h"
  8. #include "nsCycleCollectionParticipant.h"
  9. #include "nsDebug.h"
  10. #include "nsSVGElement.h"
  11. #include "nsTArray.h"
  12. #include "SVGPointList.h" // IWYU pragma: keep
  13. #include "mozilla/Attributes.h"
  14. #include "mozilla/ErrorResult.h"
  15. namespace mozilla {
  16. class DOMSVGPoint;
  17. class nsISVGPoint;
  18. class SVGAnimatedPointList;
  19. /**
  20. * Class DOMSVGPointList
  21. *
  22. * This class is used to create the DOM tearoff objects that wrap internal
  23. * SVGPointList objects.
  24. *
  25. * See the architecture comment in DOMSVGAnimatedLengthList.h first (that's
  26. * LENGTH list), then continue reading the remainder of this comment.
  27. *
  28. * The architecture of this class is very similar to that of DOMSVGLengthList
  29. * except that, since there is no nsIDOMSVGAnimatedPointList interface
  30. * in SVG, we have no parent DOMSVGAnimatedPointList (unlike DOMSVGLengthList
  31. * which has a parent DOMSVGAnimatedLengthList class). (There is an
  32. * SVGAnimatedPoints interface, but that is quite different to
  33. * DOMSVGAnimatedLengthList, since it is inherited by elements rather than
  34. * elements having members of that type.) As a consequence, much of the logic
  35. * that would otherwise be in DOMSVGAnimatedPointList (and is in
  36. * DOMSVGAnimatedLengthList) is contained in this class.
  37. *
  38. * This class is strongly intertwined with DOMSVGPoint. Our DOMSVGPoint
  39. * items are friends of us and responsible for nulling out our pointers to
  40. * them when they die.
  41. *
  42. * Our DOM items are created lazily on demand as and when script requests them.
  43. */
  44. class DOMSVGPointList final : public nsISupports,
  45. public nsWrapperCache
  46. {
  47. friend class AutoChangePointListNotifier;
  48. friend class nsISVGPoint;
  49. friend class mozilla::DOMSVGPoint;
  50. public:
  51. NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  52. NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGPointList)
  53. virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
  54. nsISupports* GetParentObject()
  55. {
  56. return static_cast<nsIContent*>(mElement);
  57. }
  58. /**
  59. * Factory method to create and return a DOMSVGPointList wrapper
  60. * for a given internal SVGPointList object. The factory takes care
  61. * of caching the object that it returns so that the same object can be
  62. * returned for the given SVGPointList each time it is requested.
  63. * The cached object is only removed from the cache when it is destroyed due
  64. * to there being no more references to it or to any of its descendant
  65. * objects. If that happens, any subsequent call requesting the DOM wrapper
  66. * for the SVGPointList will naturally result in a new
  67. * DOMSVGPointList being returned.
  68. *
  69. * It's unfortunate that aList is a void* instead of a typed argument. This
  70. * is because the mBaseVal and mAnimVal members of SVGAnimatedPointList are
  71. * of different types - a plain SVGPointList, and a SVGPointList*. We
  72. * use the addresses of these members as the key for the hash table, and
  73. * clearly SVGPointList* and a SVGPointList** are not the same type.
  74. */
  75. static already_AddRefed<DOMSVGPointList>
  76. GetDOMWrapper(void *aList,
  77. nsSVGElement *aElement,
  78. bool aIsAnimValList);
  79. /**
  80. * This method returns the DOMSVGPointList wrapper for an internal
  81. * SVGPointList object if it currently has a wrapper. If it does
  82. * not, then nullptr is returned.
  83. */
  84. static DOMSVGPointList*
  85. GetDOMWrapperIfExists(void *aList);
  86. /**
  87. * This will normally be the same as InternalList().Length(), except if
  88. * we've hit OOM, in which case our length will be zero.
  89. */
  90. uint32_t LengthNoFlush() const {
  91. MOZ_ASSERT(mItems.Length() == 0 ||
  92. mItems.Length() == InternalList().Length(),
  93. "DOM wrapper's list length is out of sync");
  94. return mItems.Length();
  95. }
  96. /**
  97. * WATCH OUT! If you add code to call this on a baseVal wrapper, then you
  98. * must also call it on the animVal wrapper too if necessary!! See other
  99. * callers!
  100. *
  101. * Called by internal code to notify us when we need to sync the length of
  102. * this DOM list with its internal list. This is called immediately prior to
  103. * the length of the internal list being changed so that any DOM list items
  104. * that need to be removed from the DOM list can first copy their values from
  105. * their internal counterpart.
  106. *
  107. * The only time this method could fail is on OOM when trying to increase the
  108. * length of the DOM list. If that happens then this method simply clears the
  109. * list and returns. Callers just proceed as normal, and we simply accept
  110. * that the DOM list will be empty (until successfully set to a new value).
  111. */
  112. void InternalListWillChangeTo(const SVGPointList& aNewValue);
  113. /**
  114. * Returns true if our attribute is animating (in which case our animVal is
  115. * not simply a mirror of our baseVal).
  116. */
  117. bool AttrIsAnimating() const;
  118. /**
  119. * Returns true if there is an animated list mirroring the base list.
  120. */
  121. bool AnimListMirrorsBaseList() const;
  122. uint32_t NumberOfItems() const
  123. {
  124. if (IsAnimValList()) {
  125. Element()->FlushAnimations();
  126. }
  127. return LengthNoFlush();
  128. }
  129. void Clear(ErrorResult& aError);
  130. already_AddRefed<nsISVGPoint> Initialize(nsISVGPoint& aNewItem,
  131. ErrorResult& aError);
  132. already_AddRefed<nsISVGPoint> GetItem(uint32_t index,
  133. ErrorResult& error);
  134. already_AddRefed<nsISVGPoint> IndexedGetter(uint32_t index, bool& found,
  135. ErrorResult& error);
  136. already_AddRefed<nsISVGPoint> InsertItemBefore(nsISVGPoint& aNewItem,
  137. uint32_t aIndex,
  138. ErrorResult& aError);
  139. already_AddRefed<nsISVGPoint> ReplaceItem(nsISVGPoint& aNewItem,
  140. uint32_t aIndex,
  141. ErrorResult& aError);
  142. already_AddRefed<nsISVGPoint> RemoveItem(uint32_t aIndex,
  143. ErrorResult& aError);
  144. already_AddRefed<nsISVGPoint> AppendItem(nsISVGPoint& aNewItem,
  145. ErrorResult& aError)
  146. {
  147. return InsertItemBefore(aNewItem, LengthNoFlush(), aError);
  148. }
  149. uint32_t Length() const
  150. {
  151. return NumberOfItems();
  152. }
  153. private:
  154. /**
  155. * Only our static GetDOMWrapper() factory method may create objects of our
  156. * type.
  157. */
  158. DOMSVGPointList(nsSVGElement *aElement, bool aIsAnimValList)
  159. : mElement(aElement)
  160. , mIsAnimValList(aIsAnimValList)
  161. {
  162. InternalListWillChangeTo(InternalList()); // Sync mItems
  163. }
  164. ~DOMSVGPointList();
  165. nsSVGElement* Element() const {
  166. return mElement.get();
  167. }
  168. /// Used to determine if this list is the baseVal or animVal list.
  169. bool IsAnimValList() const {
  170. return mIsAnimValList;
  171. }
  172. /**
  173. * Get a reference to this object's corresponding internal SVGPointList.
  174. *
  175. * To simplify the code we just have this one method for obtaining both
  176. * base val and anim val internal lists. This means that anim val lists don't
  177. * get const protection, but our setter methods guard against changing
  178. * anim val lists.
  179. */
  180. SVGPointList& InternalList() const;
  181. SVGAnimatedPointList& InternalAList() const;
  182. /// Returns the nsISVGPoint at aIndex, creating it if necessary.
  183. already_AddRefed<nsISVGPoint> GetItemAt(uint32_t aIndex);
  184. void MaybeInsertNullInAnimValListAt(uint32_t aIndex);
  185. void MaybeRemoveItemFromAnimValListAt(uint32_t aIndex);
  186. // Weak refs to our nsISVGPoint items. The items are friends and take care
  187. // of clearing our pointer to them when they die.
  188. FallibleTArray<nsISVGPoint*> mItems;
  189. // Strong ref to our element to keep it alive. We hold this not only for
  190. // ourself, but also for our nsISVGPoint items too.
  191. RefPtr<nsSVGElement> mElement;
  192. bool mIsAnimValList;
  193. };
  194. } // namespace mozilla
  195. #endif // MOZILLA_DOMSVGPOINTLIST_H__