Bug 1039924 part 6 - Use StickyTimeDuration for timing calculations; r=dholbert
authorBrian Birtles <birtles@gmail.com>
Thu, 25 Sep 2014 14:25:50 +0900
changeset 222594 b92289e2e95f203eb60580dba6bccf4119ef7458
parent 222593 2dd874cbd5f794bbfb6879c14464ef03018275ab
child 222595 a9a56008599fb1f7620533b874e5f073eb40c326
push id7107
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 17:43:31 +0000
treeherdermozilla-aurora@b4b34e0acc75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1039924
milestone35.0a1
Bug 1039924 part 6 - Use StickyTimeDuration for timing calculations; r=dholbert This patch takes the StickyTimeDuration defined in the previous patch and uses it within the calculation of animation timing for parameters that are expected to be +/- Forever.
dom/animation/Animation.cpp
dom/animation/Animation.h
layout/style/nsAnimationManager.cpp
layout/style/nsAnimationManager.h
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -109,22 +109,18 @@ Animation::GetComputedTimingAt(const Nul
   const TimeDuration& localTime = aLocalTime.Value();
 
   // When we finish exactly at the end of an iteration we need to report
   // the end of the final iteration and not the start of the next iteration
   // so we set up a flag for that case.
   bool isEndOfFinalIteration = false;
 
   // Get the normalized time within the active interval.
-  TimeDuration activeTime;
-  // FIXME: The following check that the active duration is not equal to Forever
-  // is a temporary workaround to avoid overflow and should be removed once
-  // bug 1039924 is fixed.
-  if (result.mActiveDuration != TimeDuration::Forever() &&
-      localTime >= aTiming.mDelay + result.mActiveDuration) {
+  StickyTimeDuration activeTime;
+  if (localTime >= aTiming.mDelay + result.mActiveDuration) {
     result.mPhase = ComputedTiming::AnimationPhase_After;
     if (!aTiming.FillsForwards()) {
       // The animation isn't active or filling at this time.
       result.mTimeFraction = ComputedTiming::kNullTimeFraction;
       return result;
     }
     activeTime = result.mActiveDuration;
     // Note that infinity == floor(infinity) so this will also be true when we
@@ -143,20 +139,20 @@ Animation::GetComputedTimingAt(const Nul
   } else {
     MOZ_ASSERT(result.mActiveDuration != zeroDuration,
                "How can we be in the middle of a zero-duration interval?");
     result.mPhase = ComputedTiming::AnimationPhase_Active;
     activeTime = localTime - aTiming.mDelay;
   }
 
   // Get the position within the current iteration.
-  TimeDuration iterationTime;
+  StickyTimeDuration iterationTime;
   if (aTiming.mIterationDuration != zeroDuration) {
     iterationTime = isEndOfFinalIteration
-                    ? aTiming.mIterationDuration
+                    ? StickyTimeDuration(aTiming.mIterationDuration)
                     : activeTime % aTiming.mIterationDuration;
   } /* else, iterationTime is zero */
 
   // Determine the 0-based index of the current iteration.
   if (isEndOfFinalIteration) {
     result.mCurrentIteration =
       aTiming.mIterationCount == NS_IEEEPositiveInfinity()
       ? UINT64_MAX // FIXME: When we return this via the API we'll need
@@ -210,29 +206,30 @@ Animation::GetComputedTimingAt(const Nul
   }
   if (thisIterationReverse) {
     result.mTimeFraction = 1.0 - result.mTimeFraction;
   }
 
   return result;
 }
 
-TimeDuration
+StickyTimeDuration
 Animation::ActiveDuration(const AnimationTiming& aTiming)
 {
   if (aTiming.mIterationCount == mozilla::PositiveInfinity<float>()) {
     // An animation that repeats forever has an infinite active duration
     // unless its iteration duration is zero, in which case it has a zero
     // active duration.
-    const TimeDuration zeroDuration;
+    const StickyTimeDuration zeroDuration;
     return aTiming.mIterationDuration == zeroDuration
            ? zeroDuration
-           : TimeDuration::Forever();
+           : StickyTimeDuration::Forever();
   }
-  return aTiming.mIterationDuration.MultDouble(aTiming.mIterationCount);
+  return StickyTimeDuration(
+    aTiming.mIterationDuration.MultDouble(aTiming.mIterationCount));
 }
 
 bool
 Animation::HasAnimationOfProperty(nsCSSProperty aProperty) const
 {
   for (size_t propIdx = 0, propEnd = mProperties.Length();
        propIdx != propEnd; ++propIdx) {
     if (aProperty == mProperties[propIdx].mProperty) {
--- a/dom/animation/Animation.h
+++ b/dom/animation/Animation.h
@@ -6,16 +6,17 @@
 #ifndef mozilla_dom_Animation_h
 #define mozilla_dom_Animation_h
 
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDocument.h"
 #include "nsWrapperCache.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/StickyTimeDuration.h"
 #include "mozilla/StyleAnimationValue.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/dom/Nullable.h"
 #include "nsSMILKeySpline.h"
 #include "nsStyleStruct.h" // for nsTimingFunction
 
 struct JSContext;
 
@@ -56,18 +57,19 @@ struct ComputedTiming
     : mTimeFraction(kNullTimeFraction)
     , mCurrentIteration(0)
     , mPhase(AnimationPhase_Null)
   { }
 
   static const double kNullTimeFraction;
 
   // The total duration of the animation including all iterations.
-  // Will equal TimeDuration::Forever() if the animation repeats indefinitely.
-  TimeDuration mActiveDuration;
+  // Will equal StickyTimeDuration::Forever() if the animation repeats
+  // indefinitely.
+  StickyTimeDuration mActiveDuration;
 
   // Will be kNullTimeFraction if the animation is neither animating nor
   // filling at the sampled time.
   double mTimeFraction;
 
   // Zero-based iteration index (meaningless if mTimeFraction is
   // kNullTimeFraction).
   uint64_t mCurrentIteration;
@@ -200,17 +202,18 @@ public:
   // Shortcut for that gets the computed timing using the current local time as
   // calculated from the timeline time.
   ComputedTiming GetComputedTiming(const AnimationTiming* aTiming
                                      = nullptr) const {
     return GetComputedTimingAt(GetLocalTime(), aTiming ? *aTiming : mTiming);
   }
 
   // Return the duration of the active interval for the given timing parameters.
-  static TimeDuration ActiveDuration(const AnimationTiming& aTiming);
+  static StickyTimeDuration
+  ActiveDuration(const AnimationTiming& aTiming);
 
   // After transitions finish they need to be retained for one throttle-able
   // cycle (for reasons see explanation in
   // layout/style/nsTransitionManager.cpp).
   // In the meantime, however, they should be ignored.
   bool IsFinishedTransition() const {
     return mIsFinishedTransition;
   }
--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -73,31 +73,33 @@ nsAnimationManager::GetEventsForCurrentT
                                         : NS_ANIMATION_ITERATION;
           anim->SetLastNotification(computedTiming.mCurrentIteration);
           TimeDuration iterationStart =
             anim->Timing().mIterationDuration *
             computedTiming.mCurrentIteration;
           TimeDuration elapsedTime =
             std::max(iterationStart, anim->InitialAdvance());
           AnimationEventInfo ei(aCollection->mElement, player->Name(), message,
-                                elapsedTime, aCollection->PseudoElement());
+                                StickyTimeDuration(elapsedTime),
+                                aCollection->PseudoElement());
           aEventsToDispatch.AppendElement(ei);
         }
         break;
 
       case ComputedTiming::AnimationPhase_After:
         // If we skipped the animation interval entirely, dispatch
         // 'animationstart' first
         if (anim->LastNotification() == Animation::LAST_NOTIFICATION_NONE) {
           // Notifying for start of 0th iteration.
           // (This is overwritten below but we set it here to maintain
           // internal consistency.)
           anim->SetLastNotification(0);
-          TimeDuration elapsedTime =
-            std::min(anim->InitialAdvance(), computedTiming.mActiveDuration);
+          StickyTimeDuration elapsedTime =
+            std::min(StickyTimeDuration(anim->InitialAdvance()),
+                     computedTiming.mActiveDuration);
           AnimationEventInfo ei(aCollection->mElement,
                                 player->Name(), NS_ANIMATION_START,
                                 elapsedTime, aCollection->PseudoElement());
           aEventsToDispatch.AppendElement(ei);
         }
         // Dispatch 'animationend' when needed.
         if (anim->LastNotification() != Animation::LAST_NOTIFICATION_END) {
           anim->SetLastNotification(Animation::LAST_NOTIFICATION_END);
--- a/layout/style/nsAnimationManager.h
+++ b/layout/style/nsAnimationManager.h
@@ -22,17 +22,18 @@ class Declaration;
 }
 
 struct AnimationEventInfo {
   nsRefPtr<mozilla::dom::Element> mElement;
   mozilla::InternalAnimationEvent mEvent;
 
   AnimationEventInfo(mozilla::dom::Element *aElement,
                      const nsSubstring& aAnimationName,
-                     uint32_t aMessage, mozilla::TimeDuration aElapsedTime,
+                     uint32_t aMessage,
+                     const mozilla::StickyTimeDuration& aElapsedTime,
                      const nsAString& aPseudoElement)
     : mElement(aElement), mEvent(true, aMessage)
   {
     // XXX Looks like nobody initialize WidgetEvent::time
     mEvent.animationName = aAnimationName;
     mEvent.elapsedTime = aElapsedTime.ToSeconds();
     mEvent.pseudoElement = aPseudoElement;
   }