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