Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1002)

Unified Diff: content/browser/renderer_host/input/fling/fling_curve_impl.cc

Issue 41703006: Move fling implementation from renderer to browser: (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: patch Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/input/fling/fling_curve_impl.cc
diff --git a/content/browser/renderer_host/input/fling/fling_curve_impl.cc b/content/browser/renderer_host/input/fling/fling_curve_impl.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f2aa437c31fb278baf8493cca62dccd5da7069e0
--- /dev/null
+++ b/content/browser/renderer_host/input/fling/fling_curve_impl.cc
@@ -0,0 +1,168 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/fling/fling_curve_impl.h"
+
+#include <cmath>
+
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "content/browser/renderer_host/input/fling/fling_curve_configuration.h"
+#include "content/public/common/renderer_preferences.h"
+
+namespace {
+
+const char* kCurveName = "FlingCurveImpl";
+
+inline double Position(double t, float* p) {
+ return p[0] * exp(-p[2] * t) - p[1] * t - p[0];
+}
+
+inline double Velocity(double t, float* p) {
+ return -p[0] * p[2] * exp(-p[2] * t) - p[1];
+}
+
+inline double TimeAtVelocity(double v, float* p) {
+ DCHECK(p[0]);
+ DCHECK(p[2]);
+ return -log((v + p[1]) / (-p[0] * p[2])) / p[2];
+}
+
+} // namespace
+
+
+namespace content {
+
+// This curve implementation is based on the notion of a single, absolute
+// curve, which starts at a large velocity and smoothly decreases to
+// zero. For a given input velocity, we find where on the curve this
+// velocity occurs, and start the animation at this point---denoted by
+// (time_offset_, position_offset_).
+//
+// This has the effect of automatically determining an animation duration
+// that scales with input velocity, as faster initial velocities start
+// earlier on the curve and thus take longer to reach the end. No
+// complicated time scaling is required.
+//
+// Since the starting velocity is implicitly determined by our starting
+// point, we only store the relative magnitude and direction of both
+// initial x- and y-velocities, and use this to scale the computed
+// displacement at any point in time. This guarantees that fling
+// trajectories are straight lines when viewed in x-y space. Initial
+// velocities that lie outside the max velocity are constrained to start
+// at zero (and thus are implicitly scaled).
+//
+// The curve is modelled as a 4th order polynomial, starting at t = 0,
+// and ending at t = curve_duration_. Attempts to generate
+// position/velocity estimates outside this range are undefined.
+
+FlingCurve* FlingCurveImpl::Create(
+ const gfx::PointF& initial_velocity,
+ float p0,
+ float p1,
+ float p2,
+ const gfx::Point& cumulative_scroll) {
+ return new FlingCurveImpl(initial_velocity, p0, p1, p2,
+ cumulative_scroll);
+}
+
+FlingCurveImpl::FlingCurveImpl(
+ const gfx::PointF& initial_velocity,
+ float alpha,
+ float beta,
+ float gamma,
+ const gfx::Point& cumulative_scroll)
+ : cumulative_scroll_(gfx::PointF(cumulative_scroll.x(),
+ cumulative_scroll.y())) {
+ DCHECK(initial_velocity != gfx::PointF());
+
+ coefficients_[0] = alpha;
+ coefficients_[1] = beta;
+ coefficients_[2] = gamma;
+
+ // Curve ends when velocity reaches zero.
+ curve_duration_ = TimeAtVelocity(0, coefficients_);
+ DCHECK(curve_duration_ > 0);
+
+ float max_start_velocity = std::max(std::fabs(initial_velocity.x()),
+ std::fabs(initial_velocity.y()));
+
+ // Force max_start_velocity to lie in the range v(0) to v(curve_duration),
+ // and assume that the curve parameters define a monotonically decreasing
+ // velocity, or else bisection search may fail.
+ if (max_start_velocity > Velocity(0, coefficients_))
+ max_start_velocity = Velocity(0, coefficients_);
+
+ if (max_start_velocity < 0)
+ max_start_velocity = 0;
+
+ // We keep track of relative magnitudes and directions of the
+ // velocity/displacement components here.
+ displacement_ratio_ = gfx::PointF(initial_velocity.x() / max_start_velocity,
+ initial_velocity.y() / max_start_velocity);
+
+ // Compute time-offset for start velocity.
+ time_offset_ = TimeAtVelocity(max_start_velocity, coefficients_);
+
+ // Compute curve position at offset time
+ position_offset_ = Position(time_offset_, coefficients_);
+ TRACE_EVENT_ASYNC_BEGIN1("input", "GestureAnimation", this, "curve",
+ kCurveName);
+}
+
+FlingCurveImpl::~FlingCurveImpl() {
+ TRACE_EVENT_ASYNC_END0("input", "GestureAnimation", this);
+}
+
+bool FlingCurveImpl::Apply(double time_in_secs, FlingCurveTarget* target) {
+ float displacement;
+ float speed;
+ if (time_in_secs < 0) {
+ displacement = 0.f;
+ speed = 0.f;
+ } else if (time_in_secs + time_offset_ < curve_duration_) {
+ displacement =
+ Position(time_in_secs + time_offset_, coefficients_) - position_offset_;
+ speed = Velocity(time_in_secs + time_offset_, coefficients_);
+ } else {
+ displacement = Position(curve_duration_, coefficients_) - position_offset_;
+ speed = 0.f;
+ }
+
+ // Keep track of integer portion of scroll thus far, and prepare increment.
+ gfx::PointF scroll(displacement * displacement_ratio_.x(),
+ displacement * displacement_ratio_.y());
+ gfx::PointF scroll_increment(scroll.x() - cumulative_scroll_.x(),
+ scroll.y() - cumulative_scroll_.y());
+ gfx::PointF scroll_velocity(speed * displacement_ratio_.x(),
+ speed * displacement_ratio_.y());
+ cumulative_scroll_ = scroll;
+
+ if (time_in_secs + time_offset_ < curve_duration_ ||
+ scroll_increment != gfx::PointF()) {
+ target->NotifyCurrentFlingVelocity(scroll_velocity);
+ // scrollBy() could delete this curve if the animation is over, so don't
+ // touch any member variables after making that call.
+ target->ScrollBy(scroll_increment);
+ return true;
+ }
+
+ return false;
+}
+
+// static
+FlingCurve* FlingCurve::Create(blink::WebGestureEvent::SourceDevice source,
+ const gfx::PointF& velocity,
+ const gfx::Point& cumulative_scroll) {
+ FlingCurveConfiguration config;
+ // TODO(varunjain): Set these parameters from actual preferences.
+ content::RendererPreferences def_prefs;
+ config.SetCurveParameters(def_prefs.touchpad_fling_profile,
+ def_prefs.touchscreen_fling_profile);
+ if (source == blink::WebGestureEvent::Touchscreen)
+ return config.CreateForTouchScreen(velocity, cumulative_scroll);
+ return config.CreateForTouchPad(velocity, cumulative_scroll);
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698