1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file. 4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/gfx/android/scroller.h" 6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <cmath> 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/lazy_instance.h" 10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace gfx { 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace { 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Default scroll duration from android.widget.Scroller. 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int kDefaultDurationMs = 250; 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Default friction constant in android.view.ViewConfiguration. 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const float kDefaultFriction = 0.015f; 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// == std::log(0.78f) / std::log(0.9f) 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const float kDecelerationRate = 2.3582018f; 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Tension lines cross at (kInflexion, 1). 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const float kInflexion = 0.35f; 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const float kEpsilon = 1e-5f; 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ApproxEquals(float a, float b) { 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return std::abs(a - b) < kEpsilon; 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct ViscosityConstants { 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ViscosityConstants() 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : viscous_fluid_scale_(8.f), viscous_fluid_normalize_(1.f) { 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) viscous_fluid_normalize_ = 1.0f / ApplyViscosity(1.0f); 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float ApplyViscosity(float x) { 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) x *= viscous_fluid_scale_; 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (x < 1.0f) { 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) x -= (1.0f - std::exp(-x)); 42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float start = 0.36787944117f; // 1/e == exp(-1) 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) x = 1.0f - std::exp(1.0f - x); 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) x = start + x * (1.0f - start); 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) x *= viscous_fluid_normalize_; 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return x; 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private: 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // This controls the intensity of the viscous fluid effect. 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float viscous_fluid_scale_; 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float viscous_fluid_normalize_; 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ViscosityConstants); 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}; 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct SplineConstants { 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SplineConstants() { 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float kStartTension = 0.5f; 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float kEndTension = 1.0f; 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float kP1 = kStartTension * kInflexion; 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float kP2 = 1.0f - kEndTension * (1.0f - kInflexion); 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float x_min = 0.0f; 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float y_min = 0.0f; 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (int i = 0; i < NUM_SAMPLES; i++) { 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float alpha = static_cast<float>(i) / NUM_SAMPLES; 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float x_max = 1.0f; 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float x, tx, coef; 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) while (true) { 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) x = x_min + (x_max - x_min) / 2.0f; 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) coef = 3.0f * x * (1.0f - x); 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) tx = coef * ((1.0f - x) * kP1 + x * kP2) + x * x * x; 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (ApproxEquals(tx, alpha)) 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (tx > alpha) 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) x_max = x; 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) else 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) x_min = x; 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) spline_position_[i] = coef * ((1.0f - x) * kStartTension + x) + x * x * x; 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float y_max = 1.0f; 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float y, dy; 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) while (true) { 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) y = y_min + (y_max - y_min) / 2.0f; 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) coef = 3.0f * y * (1.0f - y); 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dy = coef * ((1.0f - y) * kStartTension + y) + y * y * y; 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (ApproxEquals(dy, alpha)) 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (dy > alpha) 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) y_max = y; 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) else 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) y_min = y; 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) spline_time_[i] = coef * ((1.0f - y) * kP1 + y * kP2) + y * y * y; 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) spline_position_[NUM_SAMPLES] = spline_time_[NUM_SAMPLES] = 1.0f; 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void CalculateCoefficients(float t, 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float* distance_coef, 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float* velocity_coef) { 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *distance_coef = 1.f; 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *velocity_coef = 0.f; 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const int index = static_cast<int>(NUM_SAMPLES * t); 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (index < NUM_SAMPLES) { 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float t_inf = static_cast<float>(index) / NUM_SAMPLES; 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float t_sup = static_cast<float>(index + 1) / NUM_SAMPLES; 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float d_inf = spline_position_[index]; 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float d_sup = spline_position_[index + 1]; 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *velocity_coef = (d_sup - d_inf) / (t_sup - t_inf); 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *distance_coef = d_inf + (t - t_inf) * *velocity_coef; 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private: 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) enum { 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NUM_SAMPLES = 100 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }; 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float spline_position_[NUM_SAMPLES + 1]; 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float spline_time_[NUM_SAMPLES + 1]; 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SplineConstants); 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}; 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)float ComputeDeceleration(float friction) { 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float kGravityEarth = 9.80665f; 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return kGravityEarth // g (m/s^2) 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * 39.37f // inch/meter 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * 160.f // pixels/inch 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * friction; 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)template <typename T> 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int Signum(T t) { 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return (T(0) < t) - (t < T(0)); 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)template <typename T> 145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)T Clamped(T t, T a, T b) { 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return t < a ? a : (t > b ? b : t); 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Leaky to allow access from the impl thread. 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::LazyInstance<ViscosityConstants>::Leaky g_viscosity_constants = 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LAZY_INSTANCE_INITIALIZER; 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::LazyInstance<SplineConstants>::Leaky g_spline_constants = 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LAZY_INSTANCE_INITIALIZER; 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)Scroller::Config::Config() 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : fling_friction(kDefaultFriction), 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) flywheel_enabled(false) {} 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)Scroller::Scroller(const Config& config) 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : mode_(UNDEFINED), 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) start_x_(0), 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) start_y_(0), 166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) final_x_(0), 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) final_y_(0), 168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) min_x_(0), 169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) max_x_(0), 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) min_y_(0), 171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) max_y_(0), 172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_x_(0), 173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_y_(0), 174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) duration_seconds_reciprocal_(1), 175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delta_x_(0), 176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delta_x_norm_(1), 177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delta_y_(0), 178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delta_y_norm_(1), 179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) finished_(true), 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) flywheel_enabled_(config.flywheel_enabled), 181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) velocity_(0), 182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_velocity_(0), 183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) distance_(0), 184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) fling_friction_(config.fling_friction), 185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) deceleration_(ComputeDeceleration(fling_friction_)), 186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) tuning_coeff_(ComputeDeceleration(0.84f)) {} 187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)Scroller::~Scroller() {} 189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void Scroller::StartScroll(float start_x, 191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float start_y, 192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float dx, 193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float dy, 194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks start_time) { 195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) StartScroll(start_x, 196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) start_y, 197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dx, 198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dy, 199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) start_time, 200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kDefaultDurationMs)); 201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void Scroller::StartScroll(float start_x, 204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float start_y, 205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float dx, 206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float dy, 207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks start_time, 208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeDelta duration) { 209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) mode_ = SCROLL_MODE; 210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) finished_ = false; 211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) duration_ = duration; 212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) duration_seconds_reciprocal_ = 1.0 / duration_.InSecondsF(); 213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) start_time_ = start_time; 214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_x_ = start_x_ = start_x; 215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_y_ = start_y_ = start_y; 216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) final_x_ = start_x + dx; 217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) final_y_ = start_y + dy; 218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RecomputeDeltas(); 219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_time_ = start_time_; 220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void Scroller::Fling(float start_x, 223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float start_y, 224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float velocity_x, 225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float velocity_y, 226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float min_x, 227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float max_x, 228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float min_y, 229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float max_y, 230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks start_time) { 231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Continue a scroll or fling in progress. 232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (flywheel_enabled_ && !finished_) { 233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float old_velocity_x = GetCurrVelocityX(); 234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float old_velocity_y = GetCurrVelocityY(); 235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (Signum(velocity_x) == Signum(old_velocity_x) && 236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Signum(velocity_y) == Signum(old_velocity_y)) { 237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) velocity_x += old_velocity_x; 238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) velocity_y += old_velocity_y; 239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) mode_ = FLING_MODE; 243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) finished_ = false; 244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float velocity = std::sqrt(velocity_x * velocity_x + velocity_y * velocity_y); 246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) velocity_ = velocity; 248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) duration_ = GetSplineFlingDuration(velocity); 249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) duration_seconds_reciprocal_ = 1.0 / duration_.InSecondsF(); 250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) start_time_ = start_time; 251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_time_ = start_time_; 252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_x_ = start_x_ = start_x; 253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_y_ = start_y_ = start_y; 254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float coeff_x = velocity == 0 ? 1.0f : velocity_x / velocity; 256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float coeff_y = velocity == 0 ? 1.0f : velocity_y / velocity; 257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) double total_distance = GetSplineFlingDistance(velocity); 259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) distance_ = total_distance * Signum(velocity); 260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) min_x_ = min_x; 262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) max_x_ = max_x; 263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) min_y_ = min_y; 264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) max_y_ = max_y; 265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) final_x_ = start_x + total_distance * coeff_x; 267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) final_x_ = Clamped(final_x_, min_x_, max_x_); 268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) final_y_ = start_y + total_distance * coeff_y; 270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) final_y_ = Clamped(final_y_, min_y_, max_y_); 271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RecomputeDeltas(); 273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool Scroller::ComputeScrollOffset(base::TimeTicks time) { 276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (finished_) 277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 279e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (time == curr_time_) 280e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return true; 281e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeDelta time_passed = time - start_time_; 283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (time_passed < base::TimeDelta()) { 285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) time_passed = base::TimeDelta(); 286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (time_passed >= duration_) { 289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_x_ = final_x_; 290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_y_ = final_y_; 291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_time_ = start_time_ + duration_; 292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) finished_ = true; 293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_time_ = time; 297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float t = time_passed.InSecondsF() * duration_seconds_reciprocal_; 299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) switch (mode_) { 301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case UNDEFINED: 302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NOTREACHED() << "|StartScroll()| or |Fling()| must be called prior to " 303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "scroll offset computation."; 304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case SCROLL_MODE: { 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float x = g_viscosity_constants.Get().ApplyViscosity(t); 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_x_ = start_x_ + x * delta_x_; 310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_y_ = start_y_ + x * delta_y_; 311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } break; 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case FLING_MODE: { 314a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float distance_coef = 1.f; 315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float velocity_coef = 0.f; 316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) g_spline_constants.Get().CalculateCoefficients( 317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) t, &distance_coef, &velocity_coef); 318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_velocity_ = velocity_coef * distance_ * duration_seconds_reciprocal_; 320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_x_ = start_x_ + distance_coef * delta_x_; 322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_x_ = Clamped(curr_x_, min_x_, max_x_); 323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_y_ = start_y_ + distance_coef * delta_y_; 325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_y_ = Clamped(curr_y_, min_y_, max_y_); 326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (ApproxEquals(curr_x_, final_x_) && ApproxEquals(curr_y_, final_y_)) { 328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) finished_ = true; 329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } break; 331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void Scroller::ExtendDuration(base::TimeDelta extend) { 337a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeDelta passed = GetTimePassed(); 338a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) duration_ = passed + extend; 339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) duration_seconds_reciprocal_ = 1.0 / duration_.InSecondsF(); 340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) finished_ = false; 341a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void Scroller::SetFinalX(float new_x) { 344a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) final_x_ = new_x; 345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) finished_ = false; 346a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RecomputeDeltas(); 347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 348a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 349a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void Scroller::SetFinalY(float new_y) { 350a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) final_y_ = new_y; 351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) finished_ = false; 352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RecomputeDeltas(); 353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void Scroller::AbortAnimation() { 356a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_x_ = final_x_; 357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_y_ = final_y_; 358a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_velocity_ = 0; 359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) curr_time_ = start_time_ + duration_; 360a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) finished_ = true; 361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 362a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 363a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void Scroller::ForceFinished(bool finished) { finished_ = finished; } 364a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 365a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool Scroller::IsFinished() const { return finished_; } 366a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 367a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::TimeDelta Scroller::GetTimePassed() const { 368a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return curr_time_ - start_time_; 369a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 371a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::TimeDelta Scroller::GetDuration() const { return duration_; } 372a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)float Scroller::GetCurrX() const { return curr_x_; } 374a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 375a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)float Scroller::GetCurrY() const { return curr_y_; } 376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)float Scroller::GetCurrVelocity() const { 378a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (finished_) 379a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return 0; 380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (mode_ == FLING_MODE) 381a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return curr_velocity_; 382a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return velocity_ - deceleration_ * GetTimePassed().InSecondsF() * 0.5f; 383a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 384a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 385a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)float Scroller::GetCurrVelocityX() const { 386a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return delta_x_norm_ * GetCurrVelocity(); 387a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 388a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)float Scroller::GetCurrVelocityY() const { 390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return delta_y_norm_ * GetCurrVelocity(); 391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 393a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)float Scroller::GetStartX() const { return start_x_; } 394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)float Scroller::GetStartY() const { return start_y_; } 396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)float Scroller::GetFinalX() const { return final_x_; } 398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 399a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)float Scroller::GetFinalY() const { return final_y_; } 400a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 401a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool Scroller::IsScrollingInDirection(float xvel, float yvel) const { 402a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return !finished_ && Signum(xvel) == Signum(delta_x_) && 403a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Signum(yvel) == Signum(delta_y_); 404a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 406a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void Scroller::RecomputeDeltas() { 407a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delta_x_ = final_x_ - start_x_; 408a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delta_y_ = final_y_ - start_y_; 409a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float hyp = std::sqrt(delta_x_ * delta_x_ + delta_y_ * delta_y_); 411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (hyp > kEpsilon) { 412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delta_x_norm_ = delta_x_ / hyp; 413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delta_y_norm_ = delta_y_ / hyp; 414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) delta_x_norm_ = delta_y_norm_ = 1; 416a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 417a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)double Scroller::GetSplineDeceleration(float velocity) const { 420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return std::log(kInflexion * std::abs(velocity) / 421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (fling_friction_ * tuning_coeff_)); 422a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 423a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)base::TimeDelta Scroller::GetSplineFlingDuration(float velocity) const { 425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const double l = GetSplineDeceleration(velocity); 426a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const double decel_minus_one = kDecelerationRate - 1.0; 427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const double time_seconds = std::exp(l / decel_minus_one); 428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return base::TimeDelta::FromMicroseconds(time_seconds * 429a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Time::kMicrosecondsPerSecond); 430a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)double Scroller::GetSplineFlingDistance(float velocity) const { 433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const double l = GetSplineDeceleration(velocity); 434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const double decel_minus_one = kDecelerationRate - 1.0; 435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return fling_friction_ * tuning_coeff_ * 436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::exp(kDecelerationRate / decel_minus_one * l); 437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 438a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 439a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace gfx 440