Bug 1242872 - Part 4: Factor updating animation properties process out. r=dbaron
authorHiroyuki Ikezoe <hiikezoe@mozilla-japan.org>
Fri, 19 Feb 2016 09:16:15 +0900
changeset 321841 b257d647614093c646e718b679dfe6b282c5b33c
parent 321840 f50864e2c30de5b3dee4b1e5689d04c8d803692d
child 321842 d2459a786eef36c202b12635040e761eef1eebe1
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs1242872
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1242872 - Part 4: Factor updating animation properties process out. r=dbaron MozReview-Commit-ID: 8VWdC3wFRZX
layout/style/nsAnimationManager.cpp
--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -310,27 +310,74 @@ PullOutOldAnimationInCollection(const ns
   // Find the matching animation with this name in the old list
   // of animations.  We iterate through both lists in a backwards
   // direction which means that if there are more animations in
   // the new list of animations with a given name than in the old
   // list, it will be the animations towards the of the beginning of
   // the list that do not match and are treated as new animations.
   size_t oldIdx = aCollection->mAnimations.Length();
   while (oldIdx-- != 0) {
-    RefPtr<CSSAnimation> a = aCollection->mAnimations[oldIdx]->AsCSSAnimation();
+    CSSAnimation* a = aCollection->mAnimations[oldIdx]->AsCSSAnimation();
     MOZ_ASSERT(a, "All animations in the CSS Animation collection should"
-        " be CSSAnimation objects");
+      " be CSSAnimation objects");
     if (a->AnimationName() == aName) {
+      RefPtr<CSSAnimation> old = a;
       aCollection->mAnimations.RemoveElementAt(oldIdx);
-      return a.forget();
+      return old.forget();
     }
   }
   return nullptr;
 }
 
+static void
+UpdateOldAnimationPropertiesWithNew(CSSAnimation& aOld, Animation& aNew)
+{
+  bool animationChanged = false;
+
+  // Update the old from the new so we can keep the original object
+  // identity (and any expando properties attached to it).
+  if (aOld.GetEffect() && aNew.GetEffect()) {
+    KeyframeEffectReadOnly* oldEffect = aOld.GetEffect();
+    KeyframeEffectReadOnly* newEffect = aNew.GetEffect();
+    animationChanged =
+      oldEffect->SpecifiedTiming() != newEffect->SpecifiedTiming() ||
+      oldEffect->Properties() != newEffect->Properties();
+    oldEffect->SetSpecifiedTiming(newEffect->SpecifiedTiming());
+    oldEffect->CopyPropertiesFrom(*newEffect);
+  }
+
+  // Handle changes in play state. If the animation is idle, however,
+  // changes to animation-play-state should *not* restart it.
+  if (aOld.PlayState() != AnimationPlayState::Idle) {
+    // CSSAnimation takes care of override behavior so that,
+    // for example, if the author has called pause(), that will
+    // override the animation-play-state.
+    // (We should check aNew->IsStylePaused() but that requires
+    //  downcasting to CSSAnimation and we happen to know that
+    //  aNew will only ever be paused by calling PauseFromStyle
+    //  making IsPausedOrPausing synonymous in this case.)
+    if (!aOld.IsStylePaused() && aNew.IsPausedOrPausing()) {
+      aOld.PauseFromStyle();
+      animationChanged = true;
+    } else if (aOld.IsStylePaused() && !aNew.IsPausedOrPausing()) {
+      aOld.PlayFromStyle();
+      animationChanged = true;
+    }
+  }
+
+  aOld.CopyAnimationIndex(*aNew.AsCSSAnimation());
+
+  // Updating the effect timing above might already have caused the
+  // animation to become irrelevant so only add a changed record if
+  // the animation is still relevant.
+  if (animationChanged && aOld.IsRelevant()) {
+    nsNodeUtils::AnimationChanged(&aOld);
+  }
+}
+
 void
 nsAnimationManager::UpdateAnimations(nsStyleContext* aStyleContext,
                                      mozilla::dom::Element* aElement)
 {
   MOZ_ASSERT(mPresContext->IsDynamic(),
              "Should not update animations for print or print preview");
   MOZ_ASSERT(aElement->IsInComposedDoc(),
              "Should not update animations that are not attached to the "
@@ -404,59 +451,17 @@ nsAnimationManager::UpdateAnimations(nsS
           // until the animation is actually ready to run. However, we
           // currently have some tests that assume that these events are
           // dispatched within the same tick as the animation is added
           // so we need to queue up any animationstart events from newly-created
           // animations.
           newAnim->AsCSSAnimation()->QueueEvents();
           continue;
         }
-
-        bool animationChanged = false;
-
-        // Update the old from the new so we can keep the original object
-        // identity (and any expando properties attached to it).
-        if (oldAnim->GetEffect() && newAnim->GetEffect()) {
-          KeyframeEffectReadOnly* oldEffect = oldAnim->GetEffect();
-          KeyframeEffectReadOnly* newEffect = newAnim->GetEffect();
-          animationChanged =
-            oldEffect->SpecifiedTiming() != newEffect->SpecifiedTiming() ||
-            oldEffect->Properties() != newEffect->Properties();
-          oldEffect->SetSpecifiedTiming(newEffect->SpecifiedTiming());
-          oldEffect->CopyPropertiesFrom(*newEffect);
-        }
-
-        // Handle changes in play state. If the animation is idle, however,
-        // changes to animation-play-state should *not* restart it.
-        if (oldAnim->PlayState() != AnimationPlayState::Idle) {
-          // CSSAnimation takes care of override behavior so that,
-          // for example, if the author has called pause(), that will
-          // override the animation-play-state.
-          // (We should check newAnim->IsStylePaused() but that requires
-          //  downcasting to CSSAnimation and we happen to know that
-          //  newAnim will only ever be paused by calling PauseFromStyle
-          //  making IsPausedOrPausing synonymous in this case.)
-          if (!oldAnim->IsStylePaused() && newAnim->IsPausedOrPausing()) {
-            oldAnim->PauseFromStyle();
-            animationChanged = true;
-          } else if (oldAnim->IsStylePaused() &&
-                    !newAnim->IsPausedOrPausing()) {
-            oldAnim->PlayFromStyle();
-            animationChanged = true;
-          }
-        }
-
-        oldAnim->CopyAnimationIndex(*newAnim->AsCSSAnimation());
-
-        // Updating the effect timing above might already have caused the
-        // animation to become irrelevant so only add a changed record if
-        // the animation is still relevant.
-        if (animationChanged && oldAnim->IsRelevant()) {
-          nsNodeUtils::AnimationChanged(oldAnim);
-        }
+        UpdateOldAnimationPropertiesWithNew(*oldAnim, *newAnim);
 
         // Replace new animation with the (updated) old one.
         //
         // Although we're doing this while iterating this is safe because
         // we're not changing the length of newAnimations.
         newAnim->CancelFromStyle();
         newAnim = nullptr;
         newAnimations.ReplaceElementAt(newIdx, oldAnim);