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 12namespace { 13 14const float kDefaultAlpha = -5.70762e+03f; 15const float kDefaultBeta = 1.72e+02f; 16const float kDefaultGamma = 3.7e+00f; 17 18inline double GetPositionAtTime(double t) { 19 return kDefaultAlpha * exp(-kDefaultGamma * t) - kDefaultBeta * t - 20 kDefaultAlpha; 21} 22 23inline double GetVelocityAtTime(double t) { 24 return -kDefaultAlpha * kDefaultGamma * exp(-kDefaultGamma * t) - 25 kDefaultBeta; 26} 27 28inline double GetTimeAtVelocity(double v) { 29 return -log((v + kDefaultBeta) / (-kDefaultAlpha * kDefaultGamma)) / 30 kDefaultGamma; 31} 32 33} // namespace 34 35namespace ui { 36 37FlingCurve::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 56FlingCurve::~FlingCurve() { 57} 58 59gfx::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