diff options
author | ajuma <ajuma@chromium.org> | 2015-07-07 12:50:13 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-07-07 19:50:59 +0000 |
commit | 45889f71292639858fb21c391b545d818d980b36 (patch) | |
tree | 58c8295a68572d75135e2cadcac344d4d0ad07b8 | |
parent | fd3dd99c434e9e4ea371899c88fb1f236c4ae129 (diff) | |
download | chromium_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}
-rw-r--r-- | cc/animation/scroll_offset_animation_curve.cc | 17 | ||||
-rw-r--r-- | cc/animation/scroll_offset_animation_curve_unittest.cc | 23 |
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 |