Bug 1004365 part 1 - Make active duration calculation handle zero-duration animations; r=dholbert
authorBrian Birtles <birtles@gmail.com>
Wed, 11 Jun 2014 14:19:07 +0900
changeset 188064 bb50fd44b52a3293117690e8a116935832e3d536
parent 188063 88009c632734c2565a12e5cef6de2bb62855a8f3
child 188065 bda7f4d2b98b81296069a94fb9c3d9f95a9656c3
push id26944
push useremorley@mozilla.com
push dateWed, 11 Jun 2014 15:14:00 +0000
treeherdermozilla-central@c7391b84d9c2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1004365
milestone33.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 1004365 part 1 - Make active duration calculation handle zero-duration animations; r=dholbert This patch also makes ElementAnimation::ActiveDuration a static method that takes timing parameters as an argument. This is so that this method can be used within ElementAnimations::GetComputedTimingAt (a static method) in a future patch. We could also make ActiveDuration() a method of AnimationTiming. I suspect this logic belongs together in ElementAnimation however. In a future patch we could also add the active duration to the ComputedTiming struct which would simplify the only other place this is currently used which is ElementAnimations::GetEventsAt.
layout/style/AnimationCommon.cpp
layout/style/AnimationCommon.h
layout/style/nsAnimationManager.cpp
layout/style/nsStyleStruct.h
--- a/layout/style/AnimationCommon.cpp
+++ b/layout/style/AnimationCommon.cpp
@@ -359,17 +359,18 @@ ComputedTimingFunction::GetValue(double 
       return StepEnd(mSteps, aPortion);
   }
 }
 
 } /* end sub-namespace css */
 
 // In the Web Animations model, the time fraction can be outside the range
 // [0.0, 1.0] but it shouldn't be Infinity.
-const double ComputedTiming::kNullTimeFraction = NS_IEEEPositiveInfinity();
+const double ComputedTiming::kNullTimeFraction =
+  mozilla::PositiveInfinity<double>();
 
 bool
 ElementAnimation::IsRunningAt(TimeStamp aTime) const
 {
   if (IsPaused() || mTiming.mIterationDuration.ToMilliseconds() <= 0.0 ||
       mStartTime.IsNull()) {
     return false;
   }
--- a/layout/style/AnimationCommon.h
+++ b/layout/style/AnimationCommon.h
@@ -12,16 +12,17 @@
 #include "prclist.h"
 #include "nsStyleAnimation.h"
 #include "nsCSSProperty.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/Element.h"
 #include "nsSMILKeySpline.h"
 #include "nsStyleStruct.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/FloatingPoint.h"
 #include "nsCSSPseudoElements.h"
 
 class nsPresContext;
 class nsIFrame;
 class ElementPropertyTransition;
 
 
 namespace mozilla {
@@ -224,17 +225,17 @@ struct AnimationProperty
  *
  * Eventually this will represent all the input timing parameters specified
  * by content but for now it encapsulates just the subset of those
  * parameters passed to GetPositionInIteration.
  */
 struct AnimationTiming
 {
   mozilla::TimeDuration mIterationDuration;
-  float mIterationCount; // NS_IEEEPositiveInfinity() means infinite
+  float mIterationCount; // mozilla::PositiveInfinity<float>() means infinite
   uint8_t mDirection;
   uint8_t mFillMode;
 
   bool FillsForwards() const {
     return mFillMode == NS_STYLE_ANIMATION_FILL_MODE_BOTH ||
            mFillMode == NS_STYLE_ANIMATION_FILL_MODE_FORWARDS;
   }
   bool FillsBackwards() const {
@@ -305,19 +306,28 @@ struct ElementAnimation
   // Return the duration, at aTime (or, if paused, mPauseStart), since
   // the *end* of the delay period.  May be negative.
   mozilla::TimeDuration ElapsedDurationAt(mozilla::TimeStamp aTime) const {
     NS_ABORT_IF_FALSE(!IsPaused() || aTime >= mPauseStart,
                       "if paused, aTime must be at least mPauseStart");
     return (IsPaused() ? mPauseStart : aTime) - mStartTime - mDelay;
   }
 
-  // Return the duration of the active interval.
-  mozilla::TimeDuration ActiveDuration() const {
-    return mTiming.mIterationDuration.MultDouble(mTiming.mIterationCount);
+  // Return the duration of the active interval for the given timing parameters.
+  static mozilla::TimeDuration 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;
+      return aTiming.mIterationDuration == zeroDuration
+             ? zeroDuration
+             : mozilla::TimeDuration::Forever();
+    }
+    return aTiming.mIterationDuration.MultDouble(aTiming.mIterationCount);
   }
 
   // Return the duration from the start the active interval to the point where
   // the animation begins playback. This is zero unless the animation has
   // a negative delay in which case it is the absolute value of the delay.
   // This is used for setting the elapsedTime member of AnimationEvents.
   mozilla::TimeDuration InitialAdvance() const {
     return std::max(TimeDuration(), mDelay * -1);
--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -259,17 +259,18 @@ ElementAnimations::GetEventsAt(TimeStamp
             std::max(iterationStart, anim->InitialAdvance());
           AnimationEventInfo ei(mElement, anim->mName, message,
                                 elapsedTime, PseudoElement());
           aEventsToDispatch.AppendElement(ei);
         }
         break;
 
       case ComputedTiming::AnimationPhase_After:
-        TimeDuration activeDuration = anim->ActiveDuration();
+        TimeDuration activeDuration =
+          ElementAnimation::ActiveDuration(anim->mTiming);
         // If we skipped the animation interval entirely, dispatch
         // 'animationstart' first
         if (anim->mLastNotification ==
             ElementAnimation::LAST_NOTIFICATION_NONE) {
           // Notifying for start of 0th iteration.
           // (This is overwritten below but we set it here to maintain
           // internal consistency.)
           anim->mLastNotification = 0;
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1865,17 +1865,17 @@ struct nsAnimation {
 private:
   nsTimingFunction mTimingFunction;
   float mDuration;
   float mDelay;
   nsString mName; // empty string for 'none'
   uint8_t mDirection;
   uint8_t mFillMode;
   uint8_t mPlayState;
-  float mIterationCount; // NS_IEEEPositiveInfinity() means infinite
+  float mIterationCount; // mozilla::PositiveInfinity<float>() means infinite
 };
 
 struct nsStyleDisplay {
   nsStyleDisplay();
   nsStyleDisplay(const nsStyleDisplay& aOther);
   ~nsStyleDisplay() {
     MOZ_COUNT_DTOR(nsStyleDisplay);
   }