summaryrefslogtreecommitdiffstats
path: root/webkit/child
diff options
context:
space:
mode:
authorscottmg@chromium.org <scottmg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-13 23:09:31 +0000
committerscottmg@chromium.org <scottmg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-13 23:09:31 +0000
commitbd6da4796782dadd66ad6d580dfd3a9bed5641b2 (patch)
tree29b052f19a3592a5954c9390181c9ecce561fb69 /webkit/child
parent311a64be267032dce25cf7a1ee652a3bb233bf69 (diff)
downloadchromium_src-bd6da4796782dadd66ad6d580dfd3a9bed5641b2.zip
chromium_src-bd6da4796782dadd66ad6d580dfd3a9bed5641b2.tar.gz
chromium_src-bd6da4796782dadd66ad6d580dfd3a9bed5641b2.tar.bz2
move webkit/glue/touch_fling_* to webkit/child/
(pipelined on https://codereview.chromium.org/16424008/) TBR=jamesr@chromium.org BUG=237249 Review URL: https://codereview.chromium.org/16816003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@206202 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/child')
-rw-r--r--webkit/child/fling_curve_configuration.cc2
-rw-r--r--webkit/child/touch_fling_gesture_curve.cc163
-rw-r--r--webkit/child/touch_fling_gesture_curve.h55
-rw-r--r--webkit/child/touch_fling_gesture_curve_unittest.cc71
4 files changed, 290 insertions, 1 deletions
diff --git a/webkit/child/fling_curve_configuration.cc b/webkit/child/fling_curve_configuration.cc
index 6095ca9..154e338 100644
--- a/webkit/child/fling_curve_configuration.cc
+++ b/webkit/child/fling_curve_configuration.cc
@@ -6,7 +6,7 @@
#include "base/logging.h"
#include "third_party/WebKit/public/platform/WebGestureCurve.h"
-#include "webkit/glue/touch_fling_gesture_curve.h"
+#include "webkit/child/touch_fling_gesture_curve.h"
namespace webkit_glue {
diff --git a/webkit/child/touch_fling_gesture_curve.cc b/webkit/child/touch_fling_gesture_curve.cc
new file mode 100644
index 0000000..274dcaa
--- /dev/null
+++ b/webkit/child/touch_fling_gesture_curve.cc
@@ -0,0 +1,163 @@
+// Copyright (c) 2012 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 "webkit/child/touch_fling_gesture_curve.h"
+
+#include <cmath>
+
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "third_party/WebKit/public/platform/WebFloatPoint.h"
+#include "third_party/WebKit/public/platform/WebFloatSize.h"
+#include "third_party/WebKit/public/platform/WebGestureCurve.h"
+#include "third_party/WebKit/public/platform/WebGestureCurveTarget.h"
+#include "third_party/WebKit/public/platform/WebSize.h"
+
+using WebKit::WebFloatPoint;
+using WebKit::WebFloatSize;
+using WebKit::WebGestureCurve;
+using WebKit::WebGestureCurveTarget;
+using WebKit::WebSize;
+
+namespace {
+
+const char* kCurveName = "TouchFlingGestureCurve";
+
+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 webkit_glue {
+
+// 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.
+
+WebGestureCurve* TouchFlingGestureCurve::Create(
+ const WebFloatPoint& initial_velocity,
+ float p0,
+ float p1,
+ float p2,
+ const WebSize& cumulative_scroll) {
+ return new TouchFlingGestureCurve(initial_velocity, p0, p1, p2,
+ cumulative_scroll);
+}
+
+TouchFlingGestureCurve::TouchFlingGestureCurve(
+ const WebFloatPoint& initial_velocity,
+ float alpha,
+ float beta,
+ float gamma,
+ const WebSize& cumulative_scroll)
+ : cumulative_scroll_(WebFloatSize(cumulative_scroll.width,
+ cumulative_scroll.height)) {
+ DCHECK(initial_velocity != WebFloatPoint());
+
+ 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(fabs(initial_velocity.x),
+ 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_ = WebFloatPoint(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);
+}
+
+TouchFlingGestureCurve::~TouchFlingGestureCurve() {
+ TRACE_EVENT_ASYNC_END0("input", "GestureAnimation", this);
+}
+
+bool TouchFlingGestureCurve::apply(double time, WebGestureCurveTarget* target) {
+ float displacement;
+ float speed;
+ if (time < 0) {
+ displacement = 0.f;
+ speed = 0.f;
+ } else if (time + time_offset_ < curve_duration_) {
+ displacement =
+ position(time + time_offset_, coefficients_) - position_offset_;
+ speed = velocity(time + 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.
+ WebFloatSize scroll(displacement * displacement_ratio_.x,
+ displacement * displacement_ratio_.y);
+ WebFloatSize scroll_increment(scroll.width - cumulative_scroll_.width,
+ scroll.height - cumulative_scroll_.height);
+ WebFloatSize scroll_velocity(speed * displacement_ratio_.x,
+ speed * displacement_ratio_.y);
+ cumulative_scroll_ = scroll;
+
+ if (time + time_offset_ < curve_duration_ ||
+ scroll_increment != WebFloatSize()) {
+ 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;
+}
+
+} // namespace webkit_glue
diff --git a/webkit/child/touch_fling_gesture_curve.h b/webkit/child/touch_fling_gesture_curve.h
new file mode 100644
index 0000000..6776797
--- /dev/null
+++ b/webkit/child/touch_fling_gesture_curve.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2012 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.
+
+#ifndef WEBKIT_CHILD_TOUCH_FLING_GESTURE_CURVE_H_
+#define WEBKIT_CHILD_TOUCH_FLING_GESTURE_CURVE_H_
+
+#include "third_party/WebKit/public/platform/WebFloatPoint.h"
+#include "third_party/WebKit/public/platform/WebFloatSize.h"
+#include "third_party/WebKit/public/platform/WebGestureCurve.h"
+#include "third_party/WebKit/public/platform/WebSize.h"
+#include "webkit/child/webkit_child_export.h"
+
+namespace WebKit {
+class WebGestureCurveTarget;
+}
+
+namespace webkit_glue {
+
+// Implementation of WebGestureCurve suitable for touch pad/screen-based
+// fling scroll. Starts with a flat velocity profile based on 'velocity', which
+// tails off to zero. Time is scaled to that duration of the fling is
+// proportional to the initial velocity.
+class TouchFlingGestureCurve : public WebKit::WebGestureCurve {
+ public:
+
+ WEBKIT_CHILD_EXPORT static WebGestureCurve* Create(
+ const WebKit::WebFloatPoint& initial_velocity,
+ float p0, float p1, float p2,
+ const WebKit::WebSize& cumulativeScroll);
+
+ virtual bool apply(double monotonicTime,
+ WebKit::WebGestureCurveTarget*) OVERRIDE;
+
+ private:
+ TouchFlingGestureCurve(const WebKit::WebFloatPoint& initial_velocity,
+ float p0,
+ float p1,
+ float p2,
+ const WebKit::WebSize& cumulativeScroll);
+ virtual ~TouchFlingGestureCurve();
+
+ WebKit::WebFloatPoint displacement_ratio_;
+ WebKit::WebFloatSize cumulative_scroll_;
+ float coefficients_[3];
+ float time_offset_;
+ float curve_duration_;
+ float position_offset_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchFlingGestureCurve);
+};
+
+} // namespace webkit_glue
+
+#endif // WEBKIT_CHILD_TOUCH_FLING_GESTURE_CURVE_H_
diff --git a/webkit/child/touch_fling_gesture_curve_unittest.cc b/webkit/child/touch_fling_gesture_curve_unittest.cc
new file mode 100644
index 0000000..5e4a90a
--- /dev/null
+++ b/webkit/child/touch_fling_gesture_curve_unittest.cc
@@ -0,0 +1,71 @@
+ // Copyright (c) 2012 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.
+
+// Tests for the TouchFlingGestureCurve.
+
+#include "webkit/child/touch_fling_gesture_curve.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebFloatPoint.h"
+#include "third_party/WebKit/public/platform/WebFloatSize.h"
+#include "third_party/WebKit/public/platform/WebGestureCurve.h"
+#include "third_party/WebKit/public/platform/WebGestureCurveTarget.h"
+#include "third_party/WebKit/public/platform/WebSize.h"
+
+using WebKit::WebFloatPoint;
+using WebKit::WebFloatSize;
+using WebKit::WebGestureCurve;
+using WebKit::WebGestureCurveTarget;
+using WebKit::WebSize;
+
+namespace {
+
+class MockGestureCurveTarget : public WebGestureCurveTarget {
+ public:
+ virtual void scrollBy(const WebFloatSize& delta) {
+ cumulative_delta_.width += delta.width;
+ cumulative_delta_.height += delta.height;
+ }
+
+ virtual void notifyCurrentFlingVelocity(const WebFloatSize& velocity) {
+ current_velocity_ = velocity;
+ }
+
+ WebFloatSize cumulative_delta() const { return cumulative_delta_; }
+ void resetCumulativeDelta() { cumulative_delta_ = WebFloatSize(); }
+
+ WebFloatSize current_velocity() const { return current_velocity_; }
+
+ private:
+ WebFloatSize cumulative_delta_;
+ WebFloatSize current_velocity_;
+};
+
+} // namespace anonymous
+
+TEST(TouchFlingGestureCurve, flingCurveTouch)
+{
+ double initialVelocity = 5000;
+ MockGestureCurveTarget target;
+
+ scoped_ptr<WebGestureCurve> curve(webkit_glue::TouchFlingGestureCurve::Create(
+ WebFloatPoint(initialVelocity, 0),
+ -5.70762e+03f, 1.72e+02f, 3.7e+00f, WebSize()));
+
+ // Note: the expectations below are dependent on the curve parameters hard
+ // coded into the create call above.
+ EXPECT_TRUE(curve->apply(0, &target));
+ EXPECT_TRUE(curve->apply(0.25, &target));
+ EXPECT_NEAR(target.current_velocity().width, 1878, 1);
+ EXPECT_EQ(target.current_velocity().height, 0);
+ EXPECT_TRUE(curve->apply(0.45f, &target)); // Use non-uniform tick spacing.
+ EXPECT_TRUE(curve->apply(1, &target));
+ EXPECT_FALSE(curve->apply(1.5, &target));
+ EXPECT_NEAR(target.cumulative_delta().width, 1193, 1);
+ EXPECT_EQ(target.cumulative_delta().height, 0);
+ EXPECT_EQ(target.current_velocity().width, 0);
+ EXPECT_EQ(target.current_velocity().height, 0);
+}
+