LCOV - code coverage report
Current view: directory - content/svg/content/src - nsSVGAnimationElement.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 190 2 1.1 %
Date: 2012-06-02 Functions: 38 2 5.3 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is the Mozilla SVG project.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is Brian Birtles.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2005
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *   Brian Birtles <birtles@gmail.com>
      23                 :  *   Chris Double  <chris.double@double.co.nz>
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      27                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "nsSVGAnimationElement.h"
      40                 : #include "nsSVGSVGElement.h"
      41                 : #include "nsSMILTimeContainer.h"
      42                 : #include "nsSMILAnimationController.h"
      43                 : #include "nsSMILAnimationFunction.h"
      44                 : #include "nsISMILAttr.h"
      45                 : #include "nsContentUtils.h"
      46                 : 
      47                 : using namespace mozilla::dom;
      48                 : 
      49                 : //----------------------------------------------------------------------
      50                 : // nsISupports methods
      51                 : 
      52               0 : NS_IMPL_ADDREF_INHERITED(nsSVGAnimationElement, nsSVGAnimationElementBase)
      53               0 : NS_IMPL_RELEASE_INHERITED(nsSVGAnimationElement, nsSVGAnimationElementBase)
      54                 : 
      55               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGAnimationElement)
      56               0 :   NS_INTERFACE_MAP_ENTRY(nsISMILAnimationElement)
      57               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMElementTimeControl)
      58               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGTests)
      59               0 : NS_INTERFACE_MAP_END_INHERITING(nsSVGAnimationElementBase)
      60                 : 
      61                 : // Cycle collection magic -- based on nsSVGUseElement
      62            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsSVGAnimationElement)
      63               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsSVGAnimationElement,
      64                 :                                                 nsSVGAnimationElementBase)
      65               0 :   tmp->mHrefTarget.Unlink();
      66               0 :   tmp->mTimedElement.Unlink();
      67               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      68                 : 
      69               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsSVGAnimationElement,
      70                 :                                                   nsSVGAnimationElementBase)
      71               0 :   tmp->mHrefTarget.Traverse(&cb);
      72               0 :   tmp->mTimedElement.Traverse(&cb);
      73               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      74                 : 
      75                 : //----------------------------------------------------------------------
      76                 : // Implementation
      77                 : 
      78                 : #ifdef _MSC_VER
      79                 : // Disable "warning C4355: 'this' : used in base member initializer list".
      80                 : // We can ignore that warning because we know that mHrefTarget's constructor 
      81                 : // doesn't dereference the pointer passed to it.
      82                 : #pragma warning(push)
      83                 : #pragma warning(disable:4355)
      84                 : #endif
      85               0 : nsSVGAnimationElement::nsSVGAnimationElement(already_AddRefed<nsINodeInfo> aNodeInfo)
      86                 :   : nsSVGAnimationElementBase(aNodeInfo),
      87               0 :     mHrefTarget(this)
      88                 : #ifdef _MSC_VER
      89                 : #pragma warning(pop)
      90                 : #endif
      91                 : {
      92               0 : }
      93                 : 
      94                 : nsresult
      95               0 : nsSVGAnimationElement::Init()
      96                 : {
      97               0 :   nsresult rv = nsSVGAnimationElementBase::Init();
      98               0 :   NS_ENSURE_SUCCESS(rv, rv);
      99                 : 
     100               0 :   mTimedElement.SetAnimationElement(this);
     101               0 :   AnimationFunction().SetAnimationElement(this);
     102               0 :   mTimedElement.SetTimeClient(&AnimationFunction());
     103                 : 
     104               0 :   return NS_OK;
     105                 : }
     106                 : 
     107                 : //----------------------------------------------------------------------
     108                 : // nsISMILAnimationElement methods
     109                 : 
     110                 : const Element&
     111               0 : nsSVGAnimationElement::AsElement() const
     112                 : {
     113               0 :   return *this;
     114                 : }
     115                 : 
     116                 : Element&
     117               0 : nsSVGAnimationElement::AsElement()
     118                 : {
     119               0 :   return *this;
     120                 : }
     121                 : 
     122                 : bool
     123               0 : nsSVGAnimationElement::PassesConditionalProcessingTests()
     124                 : {
     125                 :   nsCOMPtr<DOMSVGTests> tests(do_QueryInterface(
     126               0 :     static_cast<nsSVGElement*>(this)));
     127               0 :   return tests->PassesConditionalProcessingTests();
     128                 : }
     129                 : 
     130                 : const nsAttrValue*
     131               0 : nsSVGAnimationElement::GetAnimAttr(nsIAtom* aName) const
     132                 : {
     133               0 :   return mAttrsAndChildren.GetAttr(aName, kNameSpaceID_None);
     134                 : }
     135                 : 
     136                 : bool
     137               0 : nsSVGAnimationElement::GetAnimAttr(nsIAtom* aAttName,
     138                 :                                    nsAString& aResult) const
     139                 : {
     140               0 :   return GetAttr(kNameSpaceID_None, aAttName, aResult);
     141                 : }
     142                 : 
     143                 : bool
     144               0 : nsSVGAnimationElement::HasAnimAttr(nsIAtom* aAttName) const
     145                 : {
     146               0 :   return HasAttr(kNameSpaceID_None, aAttName);
     147                 : }
     148                 : 
     149                 : Element*
     150               0 : nsSVGAnimationElement::GetTargetElementContent()
     151                 : {
     152               0 :   if (HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)) {
     153               0 :     return mHrefTarget.get();
     154                 :   }
     155               0 :   NS_ABORT_IF_FALSE(!mHrefTarget.get(),
     156                 :                     "We shouldn't have an xlink:href target "
     157                 :                     "if we don't have an xlink:href attribute");
     158                 : 
     159                 :   // No "xlink:href" attribute --> I should target my parent.
     160               0 :   nsIContent* parent = GetFlattenedTreeParent();
     161               0 :   return parent && parent->IsElement() ? parent->AsElement() : nsnull;
     162                 : }
     163                 : 
     164                 : bool
     165               0 : nsSVGAnimationElement::GetTargetAttributeName(PRInt32 *aNamespaceID,
     166                 :                                               nsIAtom **aLocalName) const
     167                 : {
     168                 :   const nsAttrValue* nameAttr
     169               0 :     = mAttrsAndChildren.GetAttr(nsGkAtoms::attributeName);
     170                 : 
     171               0 :   if (!nameAttr)
     172               0 :     return false;
     173                 : 
     174               0 :   NS_ASSERTION(nameAttr->Type() == nsAttrValue::eAtom,
     175                 :     "attributeName should have been parsed as an atom");
     176                 : 
     177               0 :   return NS_SUCCEEDED(nsContentUtils::SplitQName(
     178                 :                         this, nsDependentAtomString(nameAttr->GetAtomValue()),
     179                 :                         aNamespaceID, aLocalName));
     180                 : }
     181                 : 
     182                 : nsSMILTargetAttrType
     183               0 : nsSVGAnimationElement::GetTargetAttributeType() const
     184                 : {
     185                 :   nsIContent::AttrValuesArray typeValues[] = { &nsGkAtoms::css,
     186                 :                                                &nsGkAtoms::XML,
     187               0 :                                                nsnull};
     188                 :   nsSMILTargetAttrType smilTypes[] = { eSMILTargetAttrType_CSS,
     189               0 :                                        eSMILTargetAttrType_XML };
     190                 :   PRInt32 index = FindAttrValueIn(kNameSpaceID_None,
     191                 :                                   nsGkAtoms::attributeType,
     192                 :                                   typeValues,
     193               0 :                                   eCaseMatters);
     194               0 :   return (index >= 0) ? smilTypes[index] : eSMILTargetAttrType_auto;
     195                 : }
     196                 : 
     197                 : nsSMILTimedElement&
     198               0 : nsSVGAnimationElement::TimedElement()
     199                 : {
     200               0 :   return mTimedElement;
     201                 : }
     202                 : 
     203                 : //----------------------------------------------------------------------
     204                 : // nsIDOMSVGAnimationElement methods
     205                 : 
     206                 : /* readonly attribute SVGElement targetElement; */
     207                 : NS_IMETHODIMP
     208               0 : nsSVGAnimationElement::GetTargetElement(nsIDOMSVGElement** aTarget)
     209                 : {
     210               0 :   FlushAnimations();
     211                 : 
     212                 :   // We'll just call the other GetTargetElement method, and QI to the right type
     213               0 :   nsIContent* targetContent = GetTargetElementContent();
     214                 : 
     215               0 :   nsCOMPtr<nsIDOMSVGElement> targetSVG = do_QueryInterface(targetContent);
     216               0 :   NS_IF_ADDREF(*aTarget = targetSVG);
     217                 : 
     218               0 :   return NS_OK;
     219                 : }
     220                 : 
     221                 : /* float getStartTime() raises( DOMException ); */
     222                 : NS_IMETHODIMP
     223               0 : nsSVGAnimationElement::GetStartTime(float* retval)
     224                 : {
     225               0 :   FlushAnimations();
     226                 : 
     227               0 :   nsSMILTimeValue startTime = mTimedElement.GetStartTime();
     228               0 :   if (!startTime.IsDefinite())
     229               0 :     return NS_ERROR_DOM_INVALID_STATE_ERR;
     230                 : 
     231               0 :   *retval = float(double(startTime.GetMillis()) / PR_MSEC_PER_SEC);
     232                 : 
     233               0 :   return NS_OK;
     234                 : }
     235                 : 
     236                 : /* float getCurrentTime(); */
     237                 : NS_IMETHODIMP
     238               0 : nsSVGAnimationElement::GetCurrentTime(float* retval)
     239                 : {
     240                 :   // Not necessary to call FlushAnimations() for this
     241                 : 
     242               0 :   nsSMILTimeContainer* root = GetTimeContainer();
     243               0 :   if (root) {
     244               0 :     *retval = float(double(root->GetCurrentTime()) / PR_MSEC_PER_SEC);
     245                 :   } else {
     246               0 :     *retval = 0.f;
     247                 :   }
     248               0 :   return NS_OK;
     249                 : }
     250                 : 
     251                 : /* float getSimpleDuration() raises( DOMException ); */
     252                 : NS_IMETHODIMP
     253               0 : nsSVGAnimationElement::GetSimpleDuration(float* retval)
     254                 : {
     255                 :   // Not necessary to call FlushAnimations() for this
     256                 : 
     257               0 :   nsSMILTimeValue simpleDur = mTimedElement.GetSimpleDuration();
     258               0 :   if (!simpleDur.IsDefinite()) {
     259               0 :     *retval = 0.f;
     260               0 :     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
     261                 :   }
     262                 : 
     263               0 :   *retval = float(double(simpleDur.GetMillis()) / PR_MSEC_PER_SEC);
     264               0 :   return NS_OK;
     265                 : }
     266                 : 
     267                 : //----------------------------------------------------------------------
     268                 : // nsIContent methods
     269                 : 
     270                 : nsresult
     271               0 : nsSVGAnimationElement::BindToTree(nsIDocument* aDocument,
     272                 :                                   nsIContent* aParent,
     273                 :                                   nsIContent* aBindingParent,
     274                 :                                   bool aCompileEventHandlers)
     275                 : {
     276               0 :   NS_ABORT_IF_FALSE(!mHrefTarget.get(),
     277                 :                     "Shouldn't have href-target yet "
     278                 :                     "(or it should've been cleared)");
     279                 :   nsresult rv = nsSVGAnimationElementBase::BindToTree(aDocument, aParent,
     280                 :                                                       aBindingParent,
     281               0 :                                                       aCompileEventHandlers);
     282               0 :   NS_ENSURE_SUCCESS(rv,rv);
     283                 : 
     284                 :   // XXXdholbert is GetCtx (as a check for SVG parent) still needed here?
     285               0 :   if (!GetCtx()) {
     286                 :     // No use proceeding. We don't have an SVG parent (yet) so we won't be able
     287                 :     // to register ourselves etc. Maybe next time we'll have more luck.
     288                 :     // (This sort of situation will arise a lot when trees are being constructed
     289                 :     // piece by piece via script)
     290               0 :     return NS_OK;
     291                 :   }
     292                 : 
     293                 :   // Add myself to the animation controller's master set of animation elements.
     294               0 :   if (aDocument) {
     295               0 :     nsSMILAnimationController *controller = aDocument->GetAnimationController();
     296               0 :     if (controller) {
     297               0 :       controller->RegisterAnimationElement(this);
     298                 :     }
     299                 :     const nsAttrValue* href = mAttrsAndChildren.GetAttr(nsGkAtoms::href,
     300               0 :                                                         kNameSpaceID_XLink);
     301               0 :     if (href) {
     302               0 :       nsAutoString hrefStr;
     303               0 :       href->ToString(hrefStr);
     304                 : 
     305                 :       // Pass in |aParent| instead of |this| -- first argument is only used
     306                 :       // for a call to GetCurrentDoc(), and |this| might not have a current
     307                 :       // document yet.
     308               0 :       UpdateHrefTarget(aParent, hrefStr);
     309                 :     }
     310                 : 
     311               0 :     mTimedElement.BindToTree(aParent);
     312                 :   }
     313                 : 
     314               0 :   AnimationNeedsResample();
     315                 : 
     316               0 :   return NS_OK;
     317                 : }
     318                 : 
     319                 : void
     320               0 : nsSVGAnimationElement::UnbindFromTree(bool aDeep, bool aNullParent)
     321                 : {
     322               0 :   nsSMILAnimationController *controller = OwnerDoc()->GetAnimationController();
     323               0 :   if (controller) {
     324               0 :     controller->UnregisterAnimationElement(this);
     325                 :   }
     326                 : 
     327               0 :   mHrefTarget.Unlink();
     328               0 :   mTimedElement.DissolveReferences();
     329                 : 
     330               0 :   AnimationNeedsResample();
     331                 : 
     332               0 :   nsSVGAnimationElementBase::UnbindFromTree(aDeep, aNullParent);
     333               0 : }
     334                 : 
     335                 : bool
     336               0 : nsSVGAnimationElement::ParseAttribute(PRInt32 aNamespaceID,
     337                 :                                       nsIAtom* aAttribute,
     338                 :                                       const nsAString& aValue,
     339                 :                                       nsAttrValue& aResult)
     340                 : {
     341               0 :   if (aNamespaceID == kNameSpaceID_None) {
     342                 :     // Deal with target-related attributes here
     343               0 :     if (aAttribute == nsGkAtoms::attributeName ||
     344                 :         aAttribute == nsGkAtoms::attributeType) {
     345               0 :       aResult.ParseAtom(aValue);
     346               0 :       AnimationNeedsResample();
     347               0 :       return true;
     348                 :     }
     349                 : 
     350               0 :     nsresult rv = NS_ERROR_FAILURE;
     351                 : 
     352                 :     // First let the animation function try to parse it...
     353                 :     bool foundMatch =
     354               0 :       AnimationFunction().SetAttr(aAttribute, aValue, aResult, &rv);
     355                 : 
     356                 :     // ... and if that didn't recognize the attribute, let the timed element
     357                 :     // try to parse it.
     358               0 :     if (!foundMatch) {
     359                 :       foundMatch =
     360               0 :         mTimedElement.SetAttr(aAttribute, aValue, aResult, this, &rv);
     361                 :     }
     362                 : 
     363               0 :     if (foundMatch) {
     364               0 :       AnimationNeedsResample();
     365               0 :       if (NS_FAILED(rv)) {
     366               0 :         ReportAttributeParseFailure(OwnerDoc(), aAttribute, aValue);
     367               0 :         return false;
     368                 :       }
     369               0 :       return true;
     370                 :     }
     371                 :   }
     372                 : 
     373                 :   return nsSVGAnimationElementBase::ParseAttribute(aNamespaceID, aAttribute,
     374               0 :                                                    aValue, aResult);
     375                 : }
     376                 : 
     377                 : nsresult
     378               0 : nsSVGAnimationElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
     379                 :                                     const nsAttrValue* aValue, bool aNotify)
     380                 : {
     381                 :   nsresult rv =
     382                 :     nsSVGAnimationElementBase::AfterSetAttr(aNamespaceID, aName, aValue,
     383               0 :                                             aNotify);
     384                 : 
     385               0 :   if (aNamespaceID != kNameSpaceID_XLink || aName != nsGkAtoms::href)
     386               0 :     return rv;
     387                 : 
     388               0 :   if (!aValue) {
     389               0 :     mHrefTarget.Unlink();
     390               0 :     AnimationTargetChanged();
     391               0 :   } else if (IsInDoc()) {
     392               0 :     NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eString,
     393                 :                       "Expected href attribute to be string type");
     394               0 :     UpdateHrefTarget(this, aValue->GetStringValue());
     395                 :   } // else: we're not yet in a document -- we'll update the target on
     396                 :     // next BindToTree call.
     397                 : 
     398               0 :   return rv;
     399                 : }
     400                 : 
     401                 : nsresult
     402               0 : nsSVGAnimationElement::UnsetAttr(PRInt32 aNamespaceID,
     403                 :                                  nsIAtom* aAttribute, bool aNotify)
     404                 : {
     405                 :   nsresult rv = nsSVGAnimationElementBase::UnsetAttr(aNamespaceID, aAttribute,
     406               0 :                                                      aNotify);
     407               0 :   NS_ENSURE_SUCCESS(rv,rv);
     408                 : 
     409               0 :   if (aNamespaceID == kNameSpaceID_None) {
     410               0 :     if (AnimationFunction().UnsetAttr(aAttribute) ||
     411               0 :         mTimedElement.UnsetAttr(aAttribute)) {
     412               0 :       AnimationNeedsResample();
     413                 :     }
     414                 :   }
     415                 : 
     416               0 :   return NS_OK;
     417                 : }
     418                 : 
     419                 : bool
     420               0 : nsSVGAnimationElement::IsNodeOfType(PRUint32 aFlags) const
     421                 : {
     422               0 :   return !(aFlags & ~(eCONTENT | eANIMATION));
     423                 : }
     424                 : 
     425                 : //----------------------------------------------------------------------
     426                 : // Implementation helpers
     427                 : 
     428                 : nsSMILTimeContainer*
     429               0 : nsSVGAnimationElement::GetTimeContainer()
     430                 : {
     431               0 :   nsSVGSVGElement *element = nsSVGUtils::GetOuterSVGElement(this);
     432                 : 
     433               0 :   if (element) {
     434               0 :     return element->GetTimedDocumentRoot();
     435                 :   }
     436                 : 
     437               0 :   return nsnull;
     438                 : }
     439                 : 
     440                 : // nsIDOMElementTimeControl
     441                 : /* void beginElement (); */
     442                 : NS_IMETHODIMP
     443               0 : nsSVGAnimationElement::BeginElement(void)
     444                 : {
     445               0 :   return BeginElementAt(0.f);
     446                 : }
     447                 : 
     448                 : /* void beginElementAt (in float offset); */
     449                 : NS_IMETHODIMP
     450               0 : nsSVGAnimationElement::BeginElementAt(float offset)
     451                 : {
     452               0 :   NS_ENSURE_FINITE(offset, NS_ERROR_ILLEGAL_VALUE);
     453                 : 
     454                 :   // Make sure the timegraph is up-to-date
     455               0 :   FlushAnimations();
     456                 : 
     457                 :   // This will fail if we're not attached to a time container (SVG document
     458                 :   // fragment).
     459               0 :   nsresult rv = mTimedElement.BeginElementAt(offset);
     460               0 :   if (NS_FAILED(rv))
     461               0 :     return rv;
     462                 : 
     463               0 :   AnimationNeedsResample();
     464                 :   // Force synchronous sample so that events resulting from this call arrive in
     465                 :   // the expected order and we get an up-to-date paint.
     466               0 :   FlushAnimations();
     467                 : 
     468               0 :   return NS_OK;
     469                 : }
     470                 : 
     471                 : /* void endElement (); */
     472                 : NS_IMETHODIMP
     473               0 : nsSVGAnimationElement::EndElement(void)
     474                 : {
     475               0 :   return EndElementAt(0.f);
     476                 : }
     477                 : 
     478                 : /* void endElementAt (in float offset); */
     479                 : NS_IMETHODIMP
     480               0 : nsSVGAnimationElement::EndElementAt(float offset)
     481                 : {
     482               0 :   NS_ENSURE_FINITE(offset, NS_ERROR_ILLEGAL_VALUE);
     483                 : 
     484                 :   // Make sure the timegraph is up-to-date
     485               0 :   FlushAnimations();
     486                 : 
     487               0 :   nsresult rv = mTimedElement.EndElementAt(offset);
     488               0 :   if (NS_FAILED(rv))
     489               0 :     return rv;
     490                 : 
     491               0 :   AnimationNeedsResample();
     492                 :   // Force synchronous sample
     493               0 :   FlushAnimations();
     494                 :  
     495               0 :   return NS_OK;
     496                 : }
     497                 : 
     498                 : bool
     499               0 : nsSVGAnimationElement::IsEventName(nsIAtom* aName)
     500                 : {
     501               0 :   return nsContentUtils::IsEventAttributeName(aName, EventNameType_SMIL);
     502                 : }
     503                 : 
     504                 : void
     505               0 : nsSVGAnimationElement::UpdateHrefTarget(nsIContent* aNodeForContext,
     506                 :                                         const nsAString& aHrefStr)
     507                 : {
     508               0 :   nsCOMPtr<nsIURI> targetURI;
     509               0 :   nsCOMPtr<nsIURI> baseURI = GetBaseURI();
     510               0 :   nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI),
     511               0 :                                             aHrefStr, OwnerDoc(), baseURI);
     512               0 :   mHrefTarget.Reset(aNodeForContext, targetURI);
     513               0 :   AnimationTargetChanged();
     514               0 : }
     515                 : 
     516                 : void
     517               0 : nsSVGAnimationElement::AnimationTargetChanged()
     518                 : {
     519               0 :   mTimedElement.HandleTargetElementChange(GetTargetElementContent());
     520               0 :   AnimationNeedsResample();
     521            4392 : }

Generated by: LCOV version 1.7