Skip to content

Commit

Permalink
Fix scroll animation UpdateTarget for zero-duration segments
Browse files Browse the repository at this point in the history
BUG=645317
CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_precise_blink_rel

Review-Url: https://codereview.chromium.org/2332923002
Cr-Commit-Position: refs/heads/master@{#418343}
  • Loading branch information
ymalik authored and Commit bot committed Sep 13, 2016
1 parent c60d663 commit 8576ae6
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 13 deletions.
21 changes: 9 additions & 12 deletions cc/animation/scroll_offset_animation_curve.cc
Original file line number Diff line number Diff line change
Expand Up @@ -207,18 +207,6 @@ void ScrollOffsetAnimationCurve::UpdateTarget(
return;
}

// The total_animation_duration_ is zero because of the delay that we
// accounted for when the animation was created. The new duration should
// also take the delay into account.
if (total_animation_duration_.is_zero()) {
DCHECK_LE(t, 0);
total_animation_duration_ =
SegmentDuration(new_target.DeltaFrom(initial_value_),
duration_behavior_, base::TimeDelta::FromSecondsD(-t));
target_value_ = new_target;
return;
}

base::TimeDelta delayed_by = base::TimeDelta::FromSecondsD(
std::max(0.0, last_retarget_.InSecondsF() - t));
t = std::max(t, last_retarget_.InSecondsF());
Expand All @@ -228,6 +216,15 @@ void ScrollOffsetAnimationCurve::UpdateTarget(
gfx::Vector2dF old_delta = target_value_.DeltaFrom(initial_value_);
gfx::Vector2dF new_delta = new_target.DeltaFrom(current_position);

// The last segement was of zero duration.
if ((total_animation_duration_ - last_retarget_).is_zero()) {
DCHECK_EQ(t, last_retarget_.InSecondsF());
total_animation_duration_ =
SegmentDuration(new_delta, duration_behavior_, delayed_by);
target_value_ = new_target;
return;
}

double old_duration =
(total_animation_duration_ - last_retarget_).InSecondsF();
double old_normalized_velocity = timing_function_->Velocity(
Expand Down
52 changes: 51 additions & 1 deletion cc/animation/scroll_offset_animation_curve_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ TEST(ScrollOffsetAnimationCurveTest, CurveWithLargeDelay) {
curve->UpdateTarget(-0.01, gfx::ScrollOffset(0.f, 300.f));
double duration =
ScrollOffsetAnimationCurve::SegmentDuration(
gfx::Vector2dF(0.f, 300.f),
gfx::Vector2dF(0.f, 200.f),
ScrollOffsetAnimationCurve::DurationBehavior::INVERSE_DELTA,
base::TimeDelta::FromSecondsD(0.01))
.InSecondsF();
Expand All @@ -257,5 +257,55 @@ TEST(ScrollOffsetAnimationCurveTest, CurveWithLargeDelay) {
curve->GetValue(base::TimeDelta::FromSecondsD(1.0)));
}

// This test verifies that if the last segment duration is zero, ::UpdateTarget
// simply updates the total animation duration see crbug.com/645317.
TEST(ScrollOffsetAnimationCurveTest, UpdateTargetZeroLastSegmentDuration) {
std::unique_ptr<ScrollOffsetAnimationCurve> curve(
ScrollOffsetAnimationCurve::Create(
gfx::ScrollOffset(0.f, 100.f),
CubicBezierTimingFunction::CreatePreset(
CubicBezierTimingFunction::EaseType::EASE_IN_OUT),
ScrollOffsetAnimationCurve::DurationBehavior::INVERSE_DELTA));
double duration_in_seconds = kInverseDeltaMaxDuration / kDurationDivisor;
double delay_in_seconds = 0.02;
double curve_duration = duration_in_seconds - delay_in_seconds;

curve->SetInitialValue(gfx::ScrollOffset(),
base::TimeDelta::FromSecondsD(delay_in_seconds));
EXPECT_NEAR(curve_duration, curve->Duration().InSecondsF(), 0.0002f);

// Re-target 1, this should set last_retarget_ to 0.05.
gfx::ScrollOffset new_delta =
gfx::ScrollOffset(0.f, 200.f) -
curve->GetValue(base::TimeDelta::FromSecondsD(0.05));
double expected_duration =
ScrollOffsetAnimationCurve::SegmentDuration(
gfx::Vector2dF(new_delta.x(), new_delta.y()),
ScrollOffsetAnimationCurve::DurationBehavior::INVERSE_DELTA,
base::TimeDelta())
.InSecondsF() +
0.05;
curve->UpdateTarget(0.05, gfx::ScrollOffset(0.f, 200.f));
EXPECT_NEAR(expected_duration, curve->Duration().InSecondsF(), 0.0002f);

// Re-target 2, this should set total_animation_duration to t, which is
// last_retarget_. This is what would cause the DCHECK failure in
// crbug.com/645317.
curve->UpdateTarget(-0.145, gfx::ScrollOffset(0.f, 300.f));
EXPECT_NEAR(0.05, curve->Duration().InSecondsF(), 0.0002f);

// Re-target 3, this should set total_animation_duration based on new_delta.
new_delta = gfx::ScrollOffset(0.f, 500.f) -
curve->GetValue(base::TimeDelta::FromSecondsD(0.05));
expected_duration =
ScrollOffsetAnimationCurve::SegmentDuration(
gfx::Vector2dF(new_delta.x(), new_delta.y()),
ScrollOffsetAnimationCurve::DurationBehavior::INVERSE_DELTA,
base::TimeDelta::FromSecondsD(0.15))
.InSecondsF();
curve->UpdateTarget(-0.1, gfx::ScrollOffset(0.f, 500.f));
EXPECT_NEAR(expected_duration, curve->Duration().InSecondsF(), 0.0002f);
}

} // namespace
} // namespace cc

0 comments on commit 8576ae6

Please sign in to comment.