LCOV - code coverage report
Current view: top level - dom/svg - DOMSVGPathSegList.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 29 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 17 0.0 %
Legend: Lines: hit not hit

          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_DOMSVGPATHSEGLIST_H__
       8             : #define MOZILLA_DOMSVGPATHSEGLIST_H__
       9             : 
      10             : #include "nsCOMPtr.h"
      11             : #include "nsCycleCollectionParticipant.h"
      12             : #include "nsDebug.h"
      13             : #include "nsSVGElement.h"
      14             : #include "nsTArray.h"
      15             : #include "SVGPathData.h" // IWYU pragma: keep
      16             : #include "mozilla/Attributes.h"
      17             : #include "mozilla/ErrorResult.h"
      18             : 
      19             : namespace mozilla {
      20             : 
      21             : class DOMSVGPathSeg;
      22             : class SVGAnimatedPathSegList;
      23             : 
      24             : /**
      25             :  * Class DOMSVGPathSegList
      26             :  *
      27             :  * This class is used to create the DOM tearoff objects that wrap internal
      28             :  * SVGPathData objects.
      29             :  *
      30             :  * See the architecture comment in DOMSVGAnimatedLengthList.h first (that's
      31             :  * LENGTH list), then continue reading the remainder of this comment.
      32             :  *
      33             :  * The architecture of this class is very similar to that of DOMSVGLengthList
      34             :  * except that, since there is no nsIDOMSVGAnimatedPathSegList interface
      35             :  * in SVG, we have no parent DOMSVGAnimatedPathSegList (unlike DOMSVGLengthList
      36             :  * which has a parent DOMSVGAnimatedLengthList class). (There is an
      37             :  * SVGAnimatedPathData interface, but that is quite different to
      38             :  * DOMSVGAnimatedLengthList, since it is inherited by elements rather than
      39             :  * elements having members of that type.) As a consequence, much of the logic
      40             :  * that would otherwise be in DOMSVGAnimatedPathSegList (and is in
      41             :  * DOMSVGAnimatedLengthList) is contained in this class.
      42             :  *
      43             :  * This class is strongly intertwined with DOMSVGPathSeg. Our DOMSVGPathSeg
      44             :  * items are friends of us and responsible for nulling out our pointers to
      45             :  * them when they die.
      46             :  *
      47             :  * Our DOM items are created lazily on demand as and when script requests them.
      48             :  */
      49             : class DOMSVGPathSegList final : public nsISupports,
      50             :                                 public nsWrapperCache
      51             : {
      52             :   friend class AutoChangePathSegListNotifier;
      53             :   friend class DOMSVGPathSeg;
      54             : 
      55             : public:
      56             :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
      57           0 :   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGPathSegList)
      58             : 
      59             :   virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
      60             : 
      61           0 :   nsISupports* GetParentObject()
      62             :   {
      63           0 :     return static_cast<nsIContent*>(mElement);
      64             :   }
      65             : 
      66             :   /**
      67             :    * Factory method to create and return a DOMSVGPathSegList wrapper
      68             :    * for a given internal SVGPathData object. The factory takes care
      69             :    * of caching the object that it returns so that the same object can be
      70             :    * returned for the given SVGPathData each time it is requested.
      71             :    * The cached object is only removed from the cache when it is destroyed due
      72             :    * to there being no more references to it or to any of its descendant
      73             :    * objects. If that happens, any subsequent call requesting the DOM wrapper
      74             :    * for the SVGPathData will naturally result in a new
      75             :    * DOMSVGPathSegList being returned.
      76             :    *
      77             :    * It's unfortunate that aList is a void* instead of a typed argument. This
      78             :    * is because the mBaseVal and mAnimVal members of SVGAnimatedPathSegList are
      79             :    * of different types - a plain SVGPathData, and a SVGPathData*. We
      80             :    * use the addresses of these members as the key for the hash table, and
      81             :    * clearly SVGPathData* and a SVGPathData** are not the same type.
      82             :    */
      83             :   static already_AddRefed<DOMSVGPathSegList>
      84             :   GetDOMWrapper(void *aList,
      85             :                 nsSVGElement *aElement,
      86             :                 bool aIsAnimValList);
      87             : 
      88             :   /**
      89             :    * This method returns the DOMSVGPathSegList wrapper for an internal
      90             :    * SVGPathData object if it currently has a wrapper. If it does
      91             :    * not, then nullptr is returned.
      92             :    */
      93             :   static DOMSVGPathSegList*
      94             :   GetDOMWrapperIfExists(void *aList);
      95             : 
      96             :   /**
      97             :    * This will normally be the same as InternalList().CountItems(), except if
      98             :    * we've hit OOM, in which case our length will be zero.
      99             :    */
     100           0 :   uint32_t LengthNoFlush() const {
     101           0 :     MOZ_ASSERT(mItems.Length() == 0 ||
     102             :                mItems.Length() == InternalList().CountItems(),
     103             :                "DOM wrapper's list length is out of sync");
     104           0 :     return mItems.Length();
     105             :   }
     106             : 
     107             :   /**
     108             :    * WATCH OUT! If you add code to call this on a baseVal wrapper, then you
     109             :    * must also call it on the animVal wrapper too if necessary!! See other
     110             :    * callers!
     111             :    *
     112             :    * Called by internal code to notify us when we need to sync the length of
     113             :    * this DOM list with its internal list. This is called immediately prior to
     114             :    * the length of the internal list being changed so that any DOM list items
     115             :    * that need to be removed from the DOM list can first copy their values from
     116             :    * their internal counterpart.
     117             :    *
     118             :    * The only time this method could fail is on OOM when trying to increase the
     119             :    * length of the DOM list. If that happens then this method simply clears the
     120             :    * list and returns. Callers just proceed as normal, and we simply accept
     121             :    * that the DOM list will be empty (until successfully set to a new value).
     122             :    */
     123             :   void InternalListWillChangeTo(const SVGPathData& aNewValue);
     124             : 
     125             :   /**
     126             :    * Returns true if our attribute is animating (in which case our animVal is
     127             :    * not simply a mirror of our baseVal).
     128             :    */
     129             :   bool AttrIsAnimating() const;
     130             :   /**
     131             :    * Returns true if there is an animated list mirroring the base list.
     132             :    */
     133             :   bool AnimListMirrorsBaseList() const;
     134             : 
     135           0 :   uint32_t NumberOfItems() const
     136             :   {
     137           0 :     if (IsAnimValList()) {
     138           0 :       Element()->FlushAnimations();
     139             :     }
     140           0 :     return LengthNoFlush();
     141             :   }
     142             :   void Clear(ErrorResult& aError);
     143             :   already_AddRefed<DOMSVGPathSeg> Initialize(DOMSVGPathSeg& aNewItem,
     144             :                                              ErrorResult& aError);
     145             :   already_AddRefed<DOMSVGPathSeg> GetItem(uint32_t index,
     146             :                                           ErrorResult& error);
     147             :   already_AddRefed<DOMSVGPathSeg> IndexedGetter(uint32_t index, bool& found,
     148             :                                                 ErrorResult& error);
     149             :   already_AddRefed<DOMSVGPathSeg> InsertItemBefore(DOMSVGPathSeg& aNewItem,
     150             :                                                    uint32_t aIndex,
     151             :                                                    ErrorResult& aError);
     152             :   already_AddRefed<DOMSVGPathSeg> ReplaceItem(DOMSVGPathSeg& aNewItem,
     153             :                                               uint32_t aIndex,
     154             :                                               ErrorResult& aError);
     155             :   already_AddRefed<DOMSVGPathSeg> RemoveItem(uint32_t aIndex,
     156             :                                              ErrorResult& aError);
     157           0 :   already_AddRefed<DOMSVGPathSeg> AppendItem(DOMSVGPathSeg& aNewItem,
     158             :                                              ErrorResult& aError)
     159             :   {
     160           0 :     return InsertItemBefore(aNewItem, LengthNoFlush(), aError);
     161             :   }
     162           0 :   uint32_t Length() const
     163             :   {
     164           0 :     return NumberOfItems();
     165             :   }
     166             : 
     167             : private:
     168             : 
     169             :   /**
     170             :    * Only our static GetDOMWrapper() factory method may create objects of our
     171             :    * type.
     172             :    */
     173           0 :   DOMSVGPathSegList(nsSVGElement *aElement, bool aIsAnimValList)
     174           0 :     : mElement(aElement)
     175           0 :     , mIsAnimValList(aIsAnimValList)
     176             :   {
     177           0 :     InternalListWillChangeTo(InternalList()); // Sync mItems
     178           0 :   }
     179             : 
     180             :   ~DOMSVGPathSegList();
     181             : 
     182           0 :   nsSVGElement* Element() const {
     183           0 :     return mElement.get();
     184             :   }
     185             : 
     186             :   /// Used to determine if this list is the baseVal or animVal list.
     187           0 :   bool IsAnimValList() const {
     188           0 :     return mIsAnimValList;
     189             :   }
     190             : 
     191             :   /**
     192             :    * Get a reference to this object's corresponding internal SVGPathData.
     193             :    *
     194             :    * To simplify the code we just have this one method for obtaining both
     195             :    * base val and anim val internal lists. This means that anim val lists don't
     196             :    * get const protection, but our setter methods guard against changing
     197             :    * anim val lists.
     198             :    */
     199             :   SVGPathData& InternalList() const;
     200             : 
     201             :   SVGAnimatedPathSegList& InternalAList() const;
     202             : 
     203             :   /// Creates an instance of the appropriate DOMSVGPathSeg sub-class for
     204             :   // aIndex, if it doesn't already exist, and then returs it.
     205             :   already_AddRefed<DOMSVGPathSeg> GetItemAt(uint32_t aIndex);
     206             : 
     207             :   void MaybeInsertNullInAnimValListAt(uint32_t aIndex,
     208             :                                       uint32_t aInternalIndex,
     209             :                                       uint32_t aArgCountForItem);
     210             :   void MaybeRemoveItemFromAnimValListAt(uint32_t aIndex,
     211             :                                         int32_t aArgCountForItem);
     212             : 
     213             :   // Calls UpdateListIndex on all elements in |mItems| that satisfy ItemAt(),
     214             :   // from |aStartingIndex| to the end of |mItems|.  Also adjusts
     215             :   // |mItems.mInternalDataIndex| by the requested amount.
     216             :   void UpdateListIndicesFromIndex(uint32_t aStartingIndex,
     217             :                                   int32_t  aInternalDataIndexDelta);
     218             : 
     219           0 :   DOMSVGPathSeg*& ItemAt(uint32_t aIndex) {
     220           0 :     return mItems[aIndex].mItem;
     221             :   }
     222             : 
     223             :   /**
     224             :    * This struct is used in our array of mItems to provide us with somewhere to
     225             :    * store the indexes into the internal SVGPathData of the internal seg data
     226             :    * that our DOMSVGPathSeg items wrap (the internal segment data is or varying
     227             :    * length, so we can't just use the index of our DOMSVGPathSeg items
     228             :    * themselves). The reason that we have this separate struct rather than
     229             :    * just storing the internal indexes in the DOMSVGPathSeg items is because we
     230             :    * want to create the DOMSVGPathSeg items lazily on demand.
     231             :    */
     232             :   struct ItemProxy {
     233             :     ItemProxy(){}
     234           0 :     ItemProxy(DOMSVGPathSeg *aItem, uint32_t aInternalDataIndex)
     235           0 :       : mItem(aItem)
     236           0 :       , mInternalDataIndex(aInternalDataIndex)
     237           0 :     {}
     238             : 
     239             :     DOMSVGPathSeg *mItem;
     240             :     uint32_t mInternalDataIndex;
     241             :   };
     242             : 
     243             :   // Weak refs to our DOMSVGPathSeg items. The items are friends and take care
     244             :   // of clearing our pointer to them when they die.
     245             :   FallibleTArray<ItemProxy> mItems;
     246             : 
     247             :   // Strong ref to our element to keep it alive. We hold this not only for
     248             :   // ourself, but also for our DOMSVGPathSeg items too.
     249             :   RefPtr<nsSVGElement> mElement;
     250             : 
     251             :   bool mIsAnimValList;
     252             : };
     253             : 
     254             : } // namespace mozilla
     255             : 
     256             : #endif // MOZILLA_DOMSVGPATHSEGLIST_H__

Generated by: LCOV version 1.13