1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ui/events/gestures/fling_curve.h" 6 7 #include <algorithm> 8 #include <cmath> 9 10 #include "base/logging.h" 11 12 namespace { 13 14 const float kDefaultAlpha = -5.70762e+03f; 15 const float kDefaultBeta = 1.72e+02f; 16 const float kDefaultGamma = 3.7e+00f; 17 18 inline double GetPositionAtTime(double t) { 19 return kDefaultAlpha * exp(-kDefaultGamma * t) - kDefaultBeta * t - 20 kDefaultAlpha; 21 } 22 23 inline double GetVelocityAtTime(double t) { 24 return -kDefaultAlpha * kDefaultGamma * exp(-kDefaultGamma * t) - 25 kDefaultBeta; 26 } 27 28 inline double GetTimeAtVelocity(double v) { 29 return -log((v + kDefaultBeta) / (-kDefaultAlpha * kDefaultGamma)) / 30 kDefaultGamma; 31 } 32 33 } // namespace 34 35 namespace ui { 36 37 FlingCurve::FlingCurve(const gfx::Vector2dF& velocity, 38 base::TimeTicks start_timestamp) 39 : curve_duration_(GetTimeAtVelocity(0)), 40 start_timestamp_(start_timestamp), 41 time_offset_(0), 42 position_offset_(0) { 43 float max_start_velocity = std::max(fabs(velocity.x()), fabs(velocity.y())); 44 if (max_start_velocity > GetVelocityAtTime(0)) 45 max_start_velocity = GetVelocityAtTime(0); 46 CHECK_GT(max_start_velocity, 0); 47 48 displacement_ratio_ = gfx::Vector2dF(velocity.x() / max_start_velocity, 49 velocity.y() / max_start_velocity); 50 time_offset_ = GetTimeAtVelocity(max_start_velocity); 51 position_offset_ = GetPositionAtTime(time_offset_); 52 last_timestamp_ = start_timestamp_ + base::TimeDelta::FromSecondsD( 53 curve_duration_ - time_offset_); 54 } 55 56 FlingCurve::~FlingCurve() { 57 } 58 59 gfx::Vector2dF FlingCurve::GetScrollAmountAtTime(base::TimeTicks current) { 60 if (current < start_timestamp_) 61 return gfx::Vector2dF(); 62 63 float displacement = 0; 64 if (current < last_timestamp_) { 65 float time = time_offset_ + (current - start_timestamp_).InSecondsF(); 66 CHECK_LT(time, curve_duration_); 67 displacement = GetPositionAtTime(time) - position_offset_; 68 } else { 69 displacement = GetPositionAtTime(curve_duration_) - position_offset_; 70 } 71 72 gfx::Vector2dF scroll(displacement * displacement_ratio_.x(), 73 displacement * displacement_ratio_.y()); 74 gfx::Vector2dF scroll_increment(scroll.x() - cumulative_scroll_.x(), 75 scroll.y() - cumulative_scroll_.y()); 76 cumulative_scroll_ = scroll; 77 return scroll_increment; 78 } 79 80 } // namespace ui 81