Home | History | Annotate | Download | only in gestures
      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