summaryrefslogtreecommitdiffstats
path: root/cc/animation
diff options
context:
space:
mode:
authorajuma <ajuma@chromium.org>2015-07-07 12:50:13 -0700
committerCommit bot <commit-bot@chromium.org>2015-07-07 19:50:59 +0000
commit45889f71292639858fb21c391b545d818d980b36 (patch)
tree58c8295a68572d75135e2cadcac344d4d0ad07b8 /cc/animation
parentfd3dd99c434e9e4ea371899c88fb1f236c4ae129 (diff)
downloadchromium_src-45889f71292639858fb21c391b545d818d980b36.zip
chromium_src-45889f71292639858fb21c391b545d818d980b36.tar.gz
chromium_src-45889f71292639858fb21c391b545d818d980b36.tar.bz2
cc: Make ScrollOffsetAnimationCurve::UpdateTarget better handle large velocity
When ScrollOffsetAnimationCurve::UpdateTarget computes a new initial velocity, it doesn't address the possibility that this velocity will be large enough to trigger Inf or NaN when used elsewhere. However, given infinite precision math, increasing the velocity above 1000 has little effect on the cubic bezier curve used for the animation. This CL makes ScrollOffsetAnimationCurve no longer perform computations using large velocities; instead, we set the parameters of the cubic bezier curver directly to the values they approach as velocity approaches infinity. BUG=507252 CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel Review URL: https://codereview.chromium.org/1215713017 Cr-Commit-Position: refs/heads/master@{#337668}
Diffstat (limited to 'cc/animation')
-rw-r--r--cc/animation/scroll_offset_animation_curve.cc17
-rw-r--r--cc/animation/scroll_offset_animation_curve_unittest.cc23
2 files changed, 35 insertions, 5 deletions
diff --git a/cc/animation/scroll_offset_animation_curve.cc b/cc/animation/scroll_offset_animation_curve.cc
index 68761fb..17dff26 100644
--- a/cc/animation/scroll_offset_animation_curve.cc
+++ b/cc/animation/scroll_offset_animation_curve.cc
@@ -35,11 +35,18 @@ static base::TimeDelta DurationFromDelta(const gfx::Vector2dF& delta) {
static scoped_ptr<TimingFunction> EaseOutWithInitialVelocity(double velocity) {
// Based on EaseInOutTimingFunction::Create with first control point rotated.
- const double r2 = 0.42 * 0.42;
- const double v2 = velocity * velocity;
- const double x1 = std::sqrt(r2 / (v2 + 1));
- const double y1 = std::sqrt(r2 * v2 / (v2 + 1));
- return CubicBezierTimingFunction::Create(x1, y1, 0.58, 1);
+ if (std::abs(velocity) < 1000.0) {
+ const double r2 = 0.42 * 0.42;
+ const double v2 = velocity * velocity;
+ const double x1 = std::sqrt(r2 / (v2 + 1));
+ const double y1 = std::sqrt(r2 * v2 / (v2 + 1));
+ return CubicBezierTimingFunction::Create(x1, y1, 0.58, 1);
+ }
+
+ // For large |velocity|, x1 approaches 0 and y1 approaches 0.42. To avoid the
+ // risk of floating point arithmetic involving infinity and NaN, use those
+ // values directly rather than computing them above.
+ return CubicBezierTimingFunction::Create(0, 0.42, 0.58, 1);
}
} // namespace
diff --git a/cc/animation/scroll_offset_animation_curve_unittest.cc b/cc/animation/scroll_offset_animation_curve_unittest.cc
index 8aea905..5887513 100644
--- a/cc/animation/scroll_offset_animation_curve_unittest.cc
+++ b/cc/animation/scroll_offset_animation_curve_unittest.cc
@@ -154,5 +154,28 @@ TEST(ScrollOffsetAnimationCurveTest, UpdateTarget) {
EXPECT_EQ(7200.0, curve->GetValue(base::TimeDelta::FromSecondsD(1.674)).y());
}
+TEST(ScrollOffsetAnimationCurveTest, UpdateTargetWithLargeVelocity) {
+ gfx::ScrollOffset initial_value(0.f, 0.f);
+ gfx::ScrollOffset target_value(0.f, 900.f);
+ scoped_ptr<ScrollOffsetAnimationCurve> curve(
+ ScrollOffsetAnimationCurve::Create(
+ target_value, EaseInOutTimingFunction::Create().Pass()));
+ curve->SetInitialValue(initial_value);
+ EXPECT_EQ(0.5, curve->Duration().InSecondsF());
+
+ EXPECT_EQ(450.0, curve->GetValue(base::TimeDelta::FromSecondsD(0.25)).y());
+
+ // This leads to a new computed velocity larger than 5000.
+ curve->UpdateTarget(0.25, gfx::ScrollOffset(0.0, 450.0001));
+
+ EXPECT_NEAR(0.25015, curve->Duration().InSecondsF(), 0.0001);
+ EXPECT_NEAR(450.0,
+ curve->GetValue(base::TimeDelta::FromSecondsD(0.22501)).y(),
+ 0.001);
+ EXPECT_NEAR(450.0,
+ curve->GetValue(base::TimeDelta::FromSecondsD(0.225015)).y(),
+ 0.001);
+}
+
} // namespace
} // namespace cc