190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/browser/android/overscroll_glow.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/debug/trace_event.h"
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/lazy_instance.h"
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "cc/layers/image_layer.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/browser/android/edge_effect.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gfx/android/java_bitmap.h"
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using std::max;
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using std::min;
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace content {
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace {
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const float kEpsilon = 1e-3f;
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class OverscrollResources {
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public:
24a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  OverscrollResources() {
25a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    TRACE_EVENT0("browser", "OverscrollResources::Create");
26a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    edge_bitmap_ =
27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        gfx::CreateSkBitmapFromResource("android:drawable/overscroll_edge",
28a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                        gfx::Size(128, 12));
29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    glow_bitmap_ =
30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        gfx::CreateSkBitmapFromResource("android:drawable/overscroll_glow",
31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                        gfx::Size(128, 64));
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const SkBitmap& edge_bitmap() { return edge_bitmap_; }
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const SkBitmap& glow_bitmap() { return glow_bitmap_; }
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private:
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SkBitmap edge_bitmap_;
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SkBitmap glow_bitmap_;
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OverscrollResources);
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Leaky to allow access from a worker thread.
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)base::LazyInstance<OverscrollResources>::Leaky g_overscroll_resources =
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)scoped_refptr<cc::Layer> CreateImageLayer(const SkBitmap& bitmap) {
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_refptr<cc::ImageLayer> layer = cc::ImageLayer::Create();
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  layer->SetBitmap(bitmap);
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return layer;
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool IsApproxZero(float value) {
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return std::abs(value) < kEpsilon;
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)gfx::Vector2dF ZeroSmallComponents(gfx::Vector2dF vector) {
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (IsApproxZero(vector.x()))
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    vector.set_x(0);
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (IsApproxZero(vector.y()))
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    vector.set_y(0);
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return vector;
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochscoped_ptr<OverscrollGlow> OverscrollGlow::Create(bool enabled) {
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const SkBitmap& edge = g_overscroll_resources.Get().edge_bitmap();
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const SkBitmap& glow = g_overscroll_resources.Get().glow_bitmap();
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (edge.isNull() || glow.isNull())
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return scoped_ptr<OverscrollGlow>();
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return make_scoped_ptr(new OverscrollGlow(enabled, edge, glow));
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void OverscrollGlow::EnsureResources() {
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  g_overscroll_resources.Get();
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochOverscrollGlow::OverscrollGlow(bool enabled,
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               const SkBitmap& edge,
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               const SkBitmap& glow)
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  : enabled_(enabled),
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    horizontal_overscroll_enabled_(true),
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    vertical_overscroll_enabled_(true),
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    root_layer_(cc::Layer::Create()) {
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_refptr<cc::Layer> edge_layer = CreateImageLayer(edge);
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_refptr<cc::Layer> glow_layer = CreateImageLayer(glow);
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    root_layer_->AddChild(edge_layer);
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    root_layer_->AddChild(glow_layer);
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    edge_effects_[i] = make_scoped_ptr(new EdgeEffect(edge_layer, glow_layer));
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)OverscrollGlow::~OverscrollGlow() {
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  root_layer_->RemoveFromParent();
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void OverscrollGlow::OnOverscrolled(base::TimeTicks current_time,
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    gfx::Vector2dF overscroll,
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    gfx::Vector2dF velocity) {
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!enabled_)
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The size of the glow determines the relative effect of the inputs; an
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // empty-sized effect is effectively disabled.
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (size_.IsEmpty())
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!horizontal_overscroll_enabled_) {
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    overscroll.set_x(0);
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    velocity.set_x(0);
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!vertical_overscroll_enabled_) {
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    overscroll.set_y(0);
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    velocity.set_y(0);
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Ignore sufficiently small values that won't meaningfuly affect animation.
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  overscroll = ZeroSmallComponents(overscroll);
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  velocity = ZeroSmallComponents(velocity);
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (overscroll.IsZero()) {
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    Release(current_time);
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!velocity.IsZero()) {
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Release effects if scrolling has changed directions.
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (velocity.x() * old_velocity_.x() < 0)
133558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      ReleaseAxis(AXIS_X, current_time);
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (velocity.y() * old_velocity_.y() < 0)
135558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      ReleaseAxis(AXIS_Y, current_time);
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    Absorb(current_time, velocity, overscroll, old_overscroll_);
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Release effects when overscroll accumulation violates monotonicity.
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (overscroll.x() * old_overscroll_.x() < 0 ||
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        std::abs(overscroll.x()) < std::abs(old_overscroll_.x()))
142558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      ReleaseAxis(AXIS_X, current_time);
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (overscroll.y() * old_overscroll_.y() < 0 ||
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        std::abs(overscroll.y()) < std::abs(old_overscroll_.y()))
145558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      ReleaseAxis(AXIS_Y, current_time);
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    Pull(current_time, overscroll - old_overscroll_);
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  old_velocity_ = velocity;
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  old_overscroll_ = overscroll;
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
154558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid OverscrollGlow::Release(base::TimeTicks current_time) {
155558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
156558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    edge_effects_[i]->Release(current_time);
157558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
158558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  old_overscroll_ = old_velocity_ = gfx::Vector2dF();
159558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
160558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool OverscrollGlow::Animate(base::TimeTicks current_time) {
162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!NeedsAnimate())
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const gfx::SizeF sizes[EdgeEffect::EDGE_COUNT] = {
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    size_, gfx::SizeF(size_.height(), size_.width()),
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    size_, gfx::SizeF(size_.height(), size_.width())
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  };
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (edge_effects_[i]->Update(current_time)) {
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      edge_effects_[i]->ApplyToLayers(sizes[i],
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      static_cast<EdgeEffect::Edge>(i));
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return NeedsAnimate();
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid OverscrollGlow::SetEnabled(bool enabled) {
181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (enabled_ == enabled)
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  enabled_ = enabled;
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!enabled_) {
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i)
186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      edge_effects_[i]->Finish();
187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool OverscrollGlow::NeedsAnimate() const {
191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!enabled_)
192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return false;
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!edge_effects_[i]->IsFinished())
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return false;
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void OverscrollGlow::Pull(base::TimeTicks current_time,
20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                          gfx::Vector2dF overscroll_delta) {
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  overscroll_delta = ZeroSmallComponents(overscroll_delta);
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (overscroll_delta.IsZero())
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  gfx::Vector2dF overscroll_pull = gfx::ScaleVector2d(overscroll_delta,
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                                      1.f / size_.width(),
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                                      1.f / size_.height());
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  float edge_overscroll_pull[EdgeEffect::EDGE_COUNT] = {
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    min(overscroll_pull.y(), 0.f), // Top
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    min(overscroll_pull.x(), 0.f), // Left
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    max(overscroll_pull.y(), 0.f), // Bottom
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    max(overscroll_pull.x(), 0.f)  // Right
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  };
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!edge_overscroll_pull[i])
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      continue;
21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    edge_effects_[i]->Pull(current_time, std::abs(edge_overscroll_pull[i]));
22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    GetOppositeEdge(i)->Release(current_time);
22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void OverscrollGlow::Absorb(base::TimeTicks current_time,
22690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            gfx::Vector2dF velocity,
22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            gfx::Vector2dF overscroll,
22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            gfx::Vector2dF old_overscroll) {
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (overscroll.IsZero() || velocity.IsZero())
23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Only trigger on initial overscroll at a non-zero velocity
23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const float overscroll_velocities[EdgeEffect::EDGE_COUNT] = {
23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    old_overscroll.y() >= 0 && overscroll.y() < 0 ? min(velocity.y(), 0.f) : 0,
23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    old_overscroll.x() >= 0 && overscroll.x() < 0 ? min(velocity.x(), 0.f) : 0,
23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    old_overscroll.y() <= 0 && overscroll.y() > 0 ? max(velocity.y(), 0.f) : 0,
23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    old_overscroll.x() <= 0 && overscroll.x() > 0 ? max(velocity.x(), 0.f) : 0
23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  };
23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!overscroll_velocities[i])
24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      continue;
24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    edge_effects_[i]->Absorb(current_time, std::abs(overscroll_velocities[i]));
24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    GetOppositeEdge(i)->Release(current_time);
24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
249558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid OverscrollGlow::ReleaseAxis(Axis axis, base::TimeTicks current_time) {
25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (axis) {
25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case AXIS_X:
25290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      edge_effects_[EdgeEffect::EDGE_LEFT]->Release(current_time);
25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      edge_effects_[EdgeEffect::EDGE_RIGHT]->Release(current_time);
25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      old_overscroll_.set_x(0);
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      old_velocity_.set_x(0);
25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case AXIS_Y:
25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      edge_effects_[EdgeEffect::EDGE_TOP]->Release(current_time);
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      edge_effects_[EdgeEffect::EDGE_BOTTOM]->Release(current_time);
26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      old_overscroll_.set_y(0);
26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      old_velocity_.set_y(0);
26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  };
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)EdgeEffect* OverscrollGlow::GetOppositeEdge(int edge_index) {
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return edge_effects_[(edge_index + 2) % EdgeEffect::EDGE_COUNT].get();
26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace content
27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
272