LCOV - code coverage report
Current view: top level - dom/svg - SVGAnimatedPathSegList.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 16 82 19.5 %
Date: 2017-07-14 16:53:18 Functions: 2 10 20.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             : #include "SVGAnimatedPathSegList.h"
       8             : 
       9             : #include "DOMSVGPathSegList.h"
      10             : #include "mozilla/Move.h"
      11             : #include "nsSVGElement.h"
      12             : #include "nsSVGAttrTearoffTable.h"
      13             : #include "nsSMILValue.h"
      14             : #include "SVGPathSegListSMILType.h"
      15             : 
      16             : // See the comments in this file's header!
      17             : 
      18             : namespace mozilla {
      19             : 
      20             : nsresult
      21          44 : SVGAnimatedPathSegList::SetBaseValueString(const nsAString& aValue)
      22             : {
      23          88 :   SVGPathData newBaseValue;
      24             : 
      25             :   // The spec says that the path data is parsed and accepted up to the first
      26             :   // error encountered, so we don't return early if an error occurs. However,
      27             :   // we do want to throw any error code from setAttribute if there's a problem.
      28             : 
      29          44 :   nsresult rv = newBaseValue.SetValueFromString(aValue);
      30             : 
      31             :   // We must send these notifications *before* changing mBaseVal! Our baseVal's
      32             :   // DOM wrapper list may have to remove DOM items from itself, and any removed
      33             :   // DOM items need to copy their internal counterpart's values *before* we
      34             :   // change them. See the comments in
      35             :   // DOMSVGPathSegList::InternalListWillChangeTo().
      36             : 
      37             :   DOMSVGPathSegList *baseValWrapper =
      38          44 :     DOMSVGPathSegList::GetDOMWrapperIfExists(GetBaseValKey());
      39          44 :   if (baseValWrapper) {
      40           0 :     baseValWrapper->InternalListWillChangeTo(newBaseValue);
      41             :   }
      42             : 
      43          44 :   DOMSVGPathSegList* animValWrapper = nullptr;
      44          44 :   if (!IsAnimating()) {  // DOM anim val wraps our base val too!
      45          44 :     animValWrapper = DOMSVGPathSegList::GetDOMWrapperIfExists(GetAnimValKey());
      46          44 :     if (animValWrapper) {
      47           0 :       animValWrapper->InternalListWillChangeTo(newBaseValue);
      48             :     }
      49             :   }
      50             : 
      51             :   // Only now may we modify mBaseVal!
      52             : 
      53             :   // We don't need to call DidChange* here - we're only called by
      54             :   // nsSVGElement::ParseAttribute under Element::SetAttr,
      55             :   // which takes care of notifying.
      56             : 
      57          44 :   nsresult rv2 = mBaseVal.CopyFrom(newBaseValue);
      58          44 :   if (NS_FAILED(rv2)) {
      59             :     // Attempting to increase mBaseVal's length failed (mBaseVal is left
      60             :     // unmodified). We MUST keep any DOM wrappers in sync:
      61           0 :     if (baseValWrapper) {
      62           0 :       baseValWrapper->InternalListWillChangeTo(mBaseVal);
      63             :     }
      64           0 :     if (animValWrapper) {
      65           0 :       animValWrapper->InternalListWillChangeTo(mBaseVal);
      66             :     }
      67           0 :     return rv2;
      68             :   }
      69          44 :   return rv;
      70             : }
      71             : 
      72             : void
      73           0 : SVGAnimatedPathSegList::ClearBaseValue()
      74             : {
      75             :   // We must send these notifications *before* changing mBaseVal! (See above.)
      76             : 
      77             :   DOMSVGPathSegList *baseValWrapper =
      78           0 :     DOMSVGPathSegList::GetDOMWrapperIfExists(GetBaseValKey());
      79           0 :   if (baseValWrapper) {
      80           0 :     baseValWrapper->InternalListWillChangeTo(SVGPathData());
      81             :   }
      82             : 
      83           0 :   if (!IsAnimating()) { // DOM anim val wraps our base val too!
      84             :     DOMSVGPathSegList *animValWrapper =
      85           0 :       DOMSVGPathSegList::GetDOMWrapperIfExists(GetAnimValKey());
      86           0 :     if (animValWrapper) {
      87           0 :       animValWrapper->InternalListWillChangeTo(SVGPathData());
      88             :     }
      89             :   }
      90             : 
      91           0 :   mBaseVal.Clear();
      92             :   // Caller notifies
      93           0 : }
      94             : 
      95             : nsresult
      96           0 : SVGAnimatedPathSegList::SetAnimValue(const SVGPathData& aNewAnimValue,
      97             :                                      nsSVGElement *aElement)
      98             : {
      99             :   // Note that a new animation may totally change the number of items in the
     100             :   // animVal list, either replacing what was essentially a mirror of the
     101             :   // baseVal list, or else replacing and overriding an existing animation.
     102             :   // Unfortunately it is not possible for us to reliably distinguish between
     103             :   // calls to this method that are setting a new sample for an existing
     104             :   // animation, and calls that are setting the first sample of an animation
     105             :   // that will override an existing animation. In the case of DOMSVGPathSegList
     106             :   // the InternalListWillChangeTo method is not virtually free as it is for the
     107             :   // other DOM list classes, so this is a shame. We'd quite like to be able to
     108             :   // skip the call if possible.
     109             : 
     110             :   // We must send these notifications *before* changing mAnimVal! (See above.)
     111             : 
     112             :   DOMSVGPathSegList *domWrapper =
     113           0 :     DOMSVGPathSegList::GetDOMWrapperIfExists(GetAnimValKey());
     114           0 :   if (domWrapper) {
     115           0 :     domWrapper->InternalListWillChangeTo(aNewAnimValue);
     116             :   }
     117           0 :   if (!mAnimVal) {
     118           0 :     mAnimVal = new SVGPathData();
     119             :   }
     120           0 :   nsresult rv = mAnimVal->CopyFrom(aNewAnimValue);
     121           0 :   if (NS_FAILED(rv)) {
     122             :     // OOM. We clear the animation and, importantly, ClearAnimValue() ensures
     123             :     // that mAnimVal's DOM wrapper (if any) is kept in sync!
     124           0 :     ClearAnimValue(aElement);
     125             :   }
     126           0 :   aElement->DidAnimatePathSegList();
     127           0 :   return rv;
     128             : }
     129             : 
     130             : void
     131           0 : SVGAnimatedPathSegList::ClearAnimValue(nsSVGElement *aElement)
     132             : {
     133             :   // We must send these notifications *before* changing mAnimVal! (See above.)
     134             : 
     135             :   DOMSVGPathSegList *domWrapper =
     136           0 :     DOMSVGPathSegList::GetDOMWrapperIfExists(GetAnimValKey());
     137           0 :   if (domWrapper) {
     138             :     // When all animation ends, animVal simply mirrors baseVal, which may have
     139             :     // a different number of items to the last active animated value.
     140             :     //
     141           0 :     domWrapper->InternalListWillChangeTo(mBaseVal);
     142             :   }
     143           0 :   mAnimVal = nullptr;
     144           0 :   aElement->DidAnimatePathSegList();
     145           0 : }
     146             : 
     147             : UniquePtr<nsISMILAttr>
     148           0 : SVGAnimatedPathSegList::ToSMILAttr(nsSVGElement *aElement)
     149             : {
     150           0 :   return MakeUnique<SMILAnimatedPathSegList>(this, aElement);
     151             : }
     152             : 
     153             : nsresult
     154           0 : SVGAnimatedPathSegList::
     155             :   SMILAnimatedPathSegList::ValueFromString(const nsAString& aStr,
     156             :                                const dom::SVGAnimationElement* /*aSrcElement*/,
     157             :                                nsSMILValue& aValue,
     158             :                                bool& aPreventCachingOfSandwich) const
     159             : {
     160           0 :   nsSMILValue val(SVGPathSegListSMILType::Singleton());
     161           0 :   SVGPathDataAndInfo *list = static_cast<SVGPathDataAndInfo*>(val.mU.mPtr);
     162           0 :   nsresult rv = list->SetValueFromString(aStr);
     163           0 :   if (NS_SUCCEEDED(rv)) {
     164           0 :     list->SetElement(mElement);
     165           0 :     aValue = Move(val);
     166             :   }
     167           0 :   aPreventCachingOfSandwich = false;
     168           0 :   return rv;
     169             : }
     170             : 
     171             : nsSMILValue
     172           0 : SVGAnimatedPathSegList::SMILAnimatedPathSegList::GetBaseValue() const
     173             : {
     174             :   // To benefit from Return Value Optimization and avoid copy constructor calls
     175             :   // due to our use of return-by-value, we must return the exact same object
     176             :   // from ALL return points. This function must only return THIS variable:
     177           0 :   nsSMILValue val;
     178             : 
     179           0 :   nsSMILValue tmp(SVGPathSegListSMILType::Singleton());
     180           0 :   SVGPathDataAndInfo *list = static_cast<SVGPathDataAndInfo*>(tmp.mU.mPtr);
     181           0 :   nsresult rv = list->CopyFrom(mVal->mBaseVal);
     182           0 :   if (NS_SUCCEEDED(rv)) {
     183           0 :     list->SetElement(mElement);
     184           0 :     val = Move(tmp);
     185             :   }
     186           0 :   return val;
     187             : }
     188             : 
     189             : nsresult
     190           0 : SVGAnimatedPathSegList::SMILAnimatedPathSegList::SetAnimValue(const nsSMILValue& aValue)
     191             : {
     192           0 :   NS_ASSERTION(aValue.mType == SVGPathSegListSMILType::Singleton(),
     193             :                "Unexpected type to assign animated value");
     194           0 :   if (aValue.mType == SVGPathSegListSMILType::Singleton()) {
     195           0 :     mVal->SetAnimValue(*static_cast<SVGPathDataAndInfo*>(aValue.mU.mPtr),
     196           0 :                        mElement);
     197             :   }
     198           0 :   return NS_OK;
     199             : }
     200             : 
     201             : void
     202           0 : SVGAnimatedPathSegList::SMILAnimatedPathSegList::ClearAnimValue()
     203             : {
     204           0 :   if (mVal->mAnimVal) {
     205           0 :     mVal->ClearAnimValue(mElement);
     206             :   }
     207           0 : }
     208             : 
     209             : size_t
     210          33 : SVGAnimatedPathSegList::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
     211             : {
     212          33 :   size_t total = mBaseVal.SizeOfExcludingThis(aMallocSizeOf);
     213          33 :   if (mAnimVal) {
     214           0 :     mAnimVal->SizeOfIncludingThis(aMallocSizeOf);
     215             :   }
     216          33 :   return total;
     217             : }
     218             : 
     219             : } // namespace mozilla

Generated by: LCOV version 1.13