Bug 827687: Fix edge case in calculation of whichIteration. r=bzbarsky
authorL. David Baron <dbaron@dbaron.org>
Thu, 10 Jan 2013 21:14:51 -0800
changeset 118514 52e73ebc07e418b096e284ecf6a4313b378fd0a4
parent 118513 dcdb6d839e95f64c3fda9852215b9fe3463093f7
child 118515 d53d71d1c92eeacbcb4b8a1116fa5cd241f3f8cc
push id24166
push userMs2ger@gmail.com
push dateFri, 11 Jan 2013 13:57:41 +0000
treeherdermozilla-central@63c4b0f66a0c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs827687
milestone21.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 827687: Fix edge case in calculation of whichIteration. r=bzbarsky
layout/style/nsAnimationManager.cpp
--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -7,16 +7,17 @@
 #include "nsPresContext.h"
 #include "nsRuleProcessorData.h"
 #include "nsStyleSet.h"
 #include "nsCSSRules.h"
 #include "nsStyleAnimation.h"
 #include "nsSMILKeySpline.h"
 #include "nsEventDispatcher.h"
 #include "nsCSSFrameConstructor.h"
+#include <math.h>
 
 using namespace mozilla;
 using namespace mozilla::css;
 
 ElementAnimations::ElementAnimations(mozilla::dom::Element *aElement, nsIAtom *aElementProperty,
                                      nsAnimationManager *aAnimationManager)
   : CommonElementAnimationData(aElement, aElementProperty,
                                aAnimationManager),
@@ -89,39 +90,43 @@ ElementAnimations::GetPositionInIteratio
     } else {
       dispatchStartOrIteration = aAnimation && !aAnimation->IsPaused();
     }
   }
 
   // Set |positionInIteration| to the position from 0% to 100% along
   // the keyframes.
   NS_ABORT_IF_FALSE(currentIterationCount >= 0.0, "must be positive");
-  uint32_t whichIteration = int(currentIterationCount);
-  if (whichIteration == aIterationCount && whichIteration != 0) {
+  double whichIteration = floor(currentIterationCount);
+  if (whichIteration == aIterationCount && whichIteration != 0.0) {
     // When the animation's iteration count is an integer (as it
     // normally is), we need to end at 100% of its last iteration
     // rather than 0% of the next one (unless it's zero).
-    --whichIteration;
+    whichIteration -= 1.0;
   }
-  double positionInIteration =
-    currentIterationCount - double(whichIteration);
+  double positionInIteration = currentIterationCount - whichIteration;
 
   bool thisIterationReverse = false;
   switch (aDirection) {
     case NS_STYLE_ANIMATION_DIRECTION_NORMAL:
       thisIterationReverse = false;
       break;
     case NS_STYLE_ANIMATION_DIRECTION_REVERSE:
       thisIterationReverse = true;
       break;
     case NS_STYLE_ANIMATION_DIRECTION_ALTERNATE:
-      thisIterationReverse = (whichIteration & 1) == 1;
+      // uint64_t has more integer precision than double does, so if
+      // whichIteration is that large, we've already lost and we're just
+      // guessing.  But the animation is presumably oscillating so fast
+      // it doesn't matter anyway.
+      thisIterationReverse = (uint64_t(whichIteration) & 1) == 1;
       break;
     case NS_STYLE_ANIMATION_DIRECTION_ALTERNATE_REVERSE:
-      thisIterationReverse = (whichIteration & 1) == 0;
+      // see as previous case
+      thisIterationReverse = (uint64_t(whichIteration) & 1) == 0;
       break;
   }
   if (thisIterationReverse) {
     positionInIteration = 1.0 - positionInIteration;
   }
 
   // Dispatch 'animationstart' or 'animationiteration' when needed.
   if (aAnimation && aIsForElement && dispatchStartOrIteration &&