LCOV - code coverage report
Current view: top level - dom/smil - nsSMILCompositor.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 103 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 11 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             : #include "nsSMILCompositor.h"
       8             : 
       9             : #include "nsComputedDOMStyle.h"
      10             : #include "nsCSSProps.h"
      11             : #include "nsHashKeys.h"
      12             : #include "nsSMILCSSProperty.h"
      13             : 
      14             : // PLDHashEntryHdr methods
      15             : bool
      16           0 : nsSMILCompositor::KeyEquals(KeyTypePointer aKey) const
      17             : {
      18           0 :   return aKey && aKey->Equals(mKey);
      19             : }
      20             : 
      21             : /*static*/ PLDHashNumber
      22           0 : nsSMILCompositor::HashKey(KeyTypePointer aKey)
      23             : {
      24             :   // Combine the 3 values into one numeric value, which will be hashed.
      25             :   // NOTE: We right-shift one of the pointers by 2 to get some randomness in
      26             :   // its 2 lowest-order bits. (Those shifted-off bits will always be 0 since
      27             :   // our pointers will be word-aligned.)
      28           0 :   return (NS_PTR_TO_UINT32(aKey->mElement.get()) >> 2) +
      29           0 :     NS_PTR_TO_UINT32(aKey->mAttributeName.get());
      30             : }
      31             : 
      32             : // Cycle-collection support
      33             : void
      34           0 : nsSMILCompositor::Traverse(nsCycleCollectionTraversalCallback* aCallback)
      35             : {
      36           0 :   if (!mKey.mElement)
      37           0 :     return;
      38             : 
      39           0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*aCallback, "Compositor mKey.mElement");
      40           0 :   aCallback->NoteXPCOMChild(mKey.mElement);
      41             : }
      42             : 
      43             : // Other methods
      44             : void
      45           0 : nsSMILCompositor::AddAnimationFunction(nsSMILAnimationFunction* aFunc)
      46             : {
      47           0 :   if (aFunc) {
      48           0 :     mAnimationFunctions.AppendElement(aFunc);
      49             :   }
      50           0 : }
      51             : 
      52             : void
      53           0 : nsSMILCompositor::ComposeAttribute(bool& aMightHavePendingStyleUpdates)
      54             : {
      55           0 :   if (!mKey.mElement)
      56           0 :     return;
      57             : 
      58             :   // If we might need to resolve base styles, grab a suitable style context
      59             :   // for initializing our nsISMILAttr with.
      60           0 :   RefPtr<nsStyleContext> baseStyleContext;
      61           0 :   if (MightNeedBaseStyle()) {
      62             :     baseStyleContext =
      63           0 :       nsComputedDOMStyle::GetUnanimatedStyleContextNoFlush(mKey.mElement,
      64           0 :                                                            nullptr, nullptr);
      65             :   }
      66             : 
      67             :   // FIRST: Get the nsISMILAttr (to grab base value from, and to eventually
      68             :   // give animated value to)
      69           0 :   UniquePtr<nsISMILAttr> smilAttr = CreateSMILAttr(baseStyleContext);
      70           0 :   if (!smilAttr) {
      71             :     // Target attribute not found (or, out of memory)
      72           0 :     return;
      73             :   }
      74           0 :   if (mAnimationFunctions.IsEmpty()) {
      75             :     // No active animation functions. (We can still have a nsSMILCompositor in
      76             :     // that case if an animation function has *just* become inactive)
      77           0 :     smilAttr->ClearAnimValue();
      78             :     // Removing the animation effect may require a style update.
      79           0 :     aMightHavePendingStyleUpdates = true;
      80           0 :     return;
      81             :   }
      82             : 
      83             :   // SECOND: Sort the animationFunctions, to prepare for compositing.
      84             :   nsSMILAnimationFunction::Comparator comparator;
      85           0 :   mAnimationFunctions.Sort(comparator);
      86             : 
      87             :   // THIRD: Step backwards through animation functions to find out
      88             :   // which ones we actually care about.
      89           0 :   uint32_t firstFuncToCompose = GetFirstFuncToAffectSandwich();
      90             : 
      91             :   // FOURTH: Get & cache base value
      92           0 :   nsSMILValue sandwichResultValue;
      93           0 :   if (!mAnimationFunctions[firstFuncToCompose]->WillReplace()) {
      94           0 :     sandwichResultValue = smilAttr->GetBaseValue();
      95           0 :     MOZ_ASSERT(!sandwichResultValue.IsNull(),
      96             :                "Result of GetBaseValue should not be null");
      97             :   }
      98           0 :   UpdateCachedBaseValue(sandwichResultValue);
      99             : 
     100           0 :   if (!mForceCompositing) {
     101           0 :     return;
     102             :   }
     103             : 
     104             :   // FIFTH: Compose animation functions
     105           0 :   aMightHavePendingStyleUpdates = true;
     106           0 :   uint32_t length = mAnimationFunctions.Length();
     107           0 :   for (uint32_t i = firstFuncToCompose; i < length; ++i) {
     108           0 :     mAnimationFunctions[i]->ComposeResult(*smilAttr, sandwichResultValue);
     109             :   }
     110           0 :   if (sandwichResultValue.IsNull()) {
     111           0 :     smilAttr->ClearAnimValue();
     112           0 :     return;
     113             :   }
     114             : 
     115             :   // SIXTH: Set the animated value to the final composited result.
     116           0 :   nsresult rv = smilAttr->SetAnimValue(sandwichResultValue);
     117           0 :   if (NS_FAILED(rv)) {
     118           0 :     NS_WARNING("nsISMILAttr::SetAnimValue failed");
     119             :   }
     120             : }
     121             : 
     122             : void
     123           0 : nsSMILCompositor::ClearAnimationEffects()
     124             : {
     125           0 :   if (!mKey.mElement || !mKey.mAttributeName)
     126           0 :     return;
     127             : 
     128           0 :   UniquePtr<nsISMILAttr> smilAttr = CreateSMILAttr(nullptr);
     129           0 :   if (!smilAttr) {
     130             :     // Target attribute not found (or, out of memory)
     131           0 :     return;
     132             :   }
     133           0 :   smilAttr->ClearAnimValue();
     134             : }
     135             : 
     136             : // Protected Helper Functions
     137             : // --------------------------
     138             : UniquePtr<nsISMILAttr>
     139           0 : nsSMILCompositor::CreateSMILAttr(nsStyleContext* aBaseStyleContext)
     140             : {
     141           0 :   nsCSSPropertyID propID = GetCSSPropertyToAnimate();
     142             : 
     143           0 :   if (propID != eCSSProperty_UNKNOWN) {
     144           0 :     return MakeUnique<nsSMILCSSProperty>(propID, mKey.mElement.get(),
     145           0 :                                          aBaseStyleContext);
     146             :   }
     147             : 
     148           0 :   return mKey.mElement->GetAnimatedAttr(mKey.mAttributeNamespaceID,
     149           0 :                                         mKey.mAttributeName);
     150             : }
     151             : 
     152             : nsCSSPropertyID
     153           0 : nsSMILCompositor::GetCSSPropertyToAnimate() const
     154             : {
     155           0 :   if (mKey.mAttributeNamespaceID != kNameSpaceID_None) {
     156           0 :     return eCSSProperty_UNKNOWN;
     157             :   }
     158             : 
     159             :   nsCSSPropertyID propID =
     160           0 :     nsCSSProps::LookupProperty(nsDependentAtomString(mKey.mAttributeName),
     161           0 :                                CSSEnabledState::eForAllContent);
     162             : 
     163           0 :   if (!nsSMILCSSProperty::IsPropertyAnimatable(propID,
     164           0 :         mKey.mElement->OwnerDoc()->GetStyleBackendType())) {
     165           0 :     return eCSSProperty_UNKNOWN;
     166             :   }
     167             : 
     168             :   // If we are animating the 'width' or 'height' of an outer SVG
     169             :   // element we should animate it as a CSS property, but for other elements
     170             :   // (e.g. <rect>) we should animate it as a length attribute.
     171             :   // The easiest way to test for an outer SVG element, is to see if it is an
     172             :   // SVG-namespace element mapping its width/height attribute to style.
     173             :   //
     174             :   // If we have animation of 'width' or 'height' on an SVG element that is
     175             :   // NOT mapping that attributes to style then it must not be an outermost SVG
     176             :   // element so we should return eCSSProperty_UNKNOWN to indicate that we
     177             :   // should animate as an attribute instead.
     178           0 :   if ((mKey.mAttributeName == nsGkAtoms::width ||
     179           0 :        mKey.mAttributeName == nsGkAtoms::height) &&
     180           0 :       mKey.mElement->GetNameSpaceID() == kNameSpaceID_SVG &&
     181           0 :       !mKey.mElement->IsAttributeMapped(mKey.mAttributeName)) {
     182           0 :     return eCSSProperty_UNKNOWN;
     183             :   }
     184             : 
     185           0 :   return propID;
     186             : }
     187             : 
     188             : bool
     189           0 : nsSMILCompositor::MightNeedBaseStyle() const
     190             : {
     191           0 :   if (GetCSSPropertyToAnimate() == eCSSProperty_UNKNOWN) {
     192           0 :     return false;
     193             :   }
     194             : 
     195             :   // We should return true if at least one animation function might build on
     196             :   // the base value.
     197           0 :   for (const nsSMILAnimationFunction* func : mAnimationFunctions) {
     198           0 :     if (!func->WillReplace()) {
     199           0 :       return true;
     200             :     }
     201             :   }
     202             : 
     203           0 :   return false;
     204             : }
     205             : 
     206             : uint32_t
     207           0 : nsSMILCompositor::GetFirstFuncToAffectSandwich()
     208             : {
     209             :   // For performance reasons, we throttle most animations on elements in
     210             :   // display:none subtrees. (We can't throttle animations that target the
     211             :   // "display" property itself, though -- if we did, display:none elements
     212             :   // could never be dynamically displayed via animations.)
     213             :   // To determine whether we're in a display:none subtree, we will check the
     214             :   // element's primary frame since element in display:none subtree doesn't have
     215             :   // a primary frame. Before this process, we will construct frame when we
     216             :   // append an element to subtree. So we will not need to worry about pending
     217             :   // frame construction in this step.
     218           0 :   bool canThrottle = mKey.mAttributeName != nsGkAtoms::display &&
     219           0 :                      !mKey.mElement->GetPrimaryFrame();
     220             : 
     221             :   uint32_t i;
     222           0 :   for (i = mAnimationFunctions.Length(); i > 0; --i) {
     223           0 :     nsSMILAnimationFunction* curAnimFunc = mAnimationFunctions[i-1];
     224             :     // In the following, the lack of short-circuit behavior of |= means that we
     225             :     // will ALWAYS run UpdateCachedTarget (even if mForceCompositing is true)
     226             :     // but only call HasChanged and WasSkippedInPrevSample if necessary.  This
     227             :     // is important since we need UpdateCachedTarget to run in order to detect
     228             :     // changes to the target in subsequent samples.
     229           0 :     mForceCompositing |=
     230           0 :       curAnimFunc->UpdateCachedTarget(mKey) ||
     231           0 :       (curAnimFunc->HasChanged() && !canThrottle) ||
     232           0 :       curAnimFunc->WasSkippedInPrevSample();
     233             : 
     234           0 :     if (curAnimFunc->WillReplace()) {
     235           0 :       --i;
     236           0 :       break;
     237             :     }
     238             :   }
     239             : 
     240             :   // Mark remaining animation functions as having been skipped so if we later
     241             :   // use them we'll know to force compositing.
     242             :   // Note that we only really need to do this if something has changed
     243             :   // (otherwise we would have set the flag on a previous sample) and if
     244             :   // something has changed mForceCompositing will be true.
     245           0 :   if (mForceCompositing) {
     246           0 :     for (uint32_t j = i; j > 0; --j) {
     247           0 :       mAnimationFunctions[j-1]->SetWasSkipped();
     248             :     }
     249             :   }
     250           0 :   return i;
     251             : }
     252             : 
     253             : void
     254           0 : nsSMILCompositor::UpdateCachedBaseValue(const nsSMILValue& aBaseValue)
     255             : {
     256           0 :   if (mCachedBaseValue != aBaseValue) {
     257             :     // Base value has changed since last sample.
     258           0 :     mCachedBaseValue = aBaseValue;
     259           0 :     mForceCompositing = true;
     260             :   }
     261           0 : }

Generated by: LCOV version 1.13