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/edge_effect.h" 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "cc/layers/layer.h" 86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "cc/layers/ui_resource_layer.h" 96e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ui/base/android/system_ui_resource_manager.h" 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace content { 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace { 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Time it will take the effect to fully recede in ms 1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const int kRecedeTimeMs = 1000; 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Time it will take before a pulled glow begins receding in ms 1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const int kPullTimeMs = 167; 2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Time it will take in ms for a pulled glow to decay before release 2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const int kPullDecayTimeMs = 1000; 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const float kMaxAlpha = 1.f; 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const float kHeldEdgeScaleY = .5f; 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const float kMaxGlowHeight = 4.f; 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const float kPullGlowBegin = 1.f; 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const float kPullEdgeBegin = 0.6f; 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Min/max velocity that will be absorbed 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const float kMinVelocity = 100.f; 348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const float kMaxVelocity = 10000.f; 3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const float kEpsilon = 0.001f; 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const float kGlowHeightWidthRatio = 0.25f; 39a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// How much dragging should effect the height of the edge image. 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Number determined by user testing. 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const int kPullDistanceEdgeFactor = 7; 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// How much dragging should effect the height of the glow image. 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Number determined by user testing. 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const int kPullDistanceGlowFactor = 7; 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const float kPullDistanceAlphaGlowFactor = 1.1f; 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const int kVelocityEdgeFactor = 8; 508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const int kVelocityGlowFactor = 12; 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const float kEdgeHeightAtMdpi = 12.f; 5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const float kGlowHeightAtMdpi = 128.f; 5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)template <typename T> 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)T Lerp(T a, T b, T t) { 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return a + (b - a) * t; 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)template <typename T> 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)T Clamp(T value, T low, T high) { 6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return value < low ? low : (value > high ? high : value); 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)template <typename T> 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)T Damp(T input, T factor) { 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) T result; 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (factor == 1) { 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) result = 1 - (1 - input) * (1 - input); 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) result = 1 - std::pow(1 - input, 2 * factor); 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return result; 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} // namespace 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class EdgeEffect::EffectLayer { 796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) public: 806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) EffectLayer(ui::SystemUIResourceManager::ResourceType resource_type, 816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::SystemUIResourceManager* resource_manager) 826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) : ui_resource_layer_(cc::UIResourceLayer::Create()), 836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) resource_type_(resource_type), 846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) resource_manager_(resource_manager) {} 856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ~EffectLayer() { ui_resource_layer_->RemoveFromParent(); } 876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void SetParent(cc::Layer* parent) { 896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (ui_resource_layer_->parent() != parent) 906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) parent->AddChild(ui_resource_layer_); 916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui_resource_layer_->SetUIResourceId( 926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) resource_manager_->GetUIResourceId(resource_type_)); 936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void Disable() { ui_resource_layer_->SetIsDrawable(false); } 966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 9703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) void Update(const gfx::Size& size, 9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const gfx::Transform& transform, 996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) float opacity) { 1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui_resource_layer_->SetUIResourceId( 1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) resource_manager_->GetUIResourceId(resource_type_)); 1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui_resource_layer_->SetIsDrawable(true); 1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui_resource_layer_->SetTransformOrigin( 10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) gfx::Point3F(size.width() * 0.5f, 0, 0)); 10503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ui_resource_layer_->SetTransform(transform); 10603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ui_resource_layer_->SetBounds(size); 1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui_resource_layer_->SetOpacity(Clamp(opacity, 0.f, 1.f)); 1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) scoped_refptr<cc::UIResourceLayer> ui_resource_layer_; 1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::SystemUIResourceManager::ResourceType resource_type_; 1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::SystemUIResourceManager* resource_manager_; 1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(EffectLayer); 1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}; 1166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)EdgeEffect::EdgeEffect(ui::SystemUIResourceManager* resource_manager, 11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) float device_scale_factor) 1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) : edge_(new EffectLayer(ui::SystemUIResourceManager::OVERSCROLL_EDGE, 1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) resource_manager)), 1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) glow_(new EffectLayer(ui::SystemUIResourceManager::OVERSCROLL_GLOW, 1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) resource_manager)), 12303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base_edge_height_(kEdgeHeightAtMdpi * device_scale_factor), 12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base_glow_height_(kGlowHeightAtMdpi * device_scale_factor), 1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) edge_alpha_(0), 1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) edge_scale_y_(0), 1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) glow_alpha_(0), 1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) glow_scale_y_(0), 1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) edge_alpha_start_(0), 1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) edge_alpha_finish_(0), 1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) edge_scale_y_start_(0), 1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) edge_scale_y_finish_(0), 1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) glow_alpha_start_(0), 1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) glow_alpha_finish_(0), 1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) glow_scale_y_start_(0), 1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) glow_scale_y_finish_(0), 1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) state_(STATE_IDLE), 1386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) pull_distance_(0) { 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)EdgeEffect::~EdgeEffect() { 14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool EdgeEffect::IsFinished() const { 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return state_ == STATE_IDLE; 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void EdgeEffect::Finish() { 1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) edge_->Disable(); 1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) glow_->Disable(); 15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) pull_distance_ = 0; 15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) state_ = STATE_IDLE; 15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void EdgeEffect::Pull(base::TimeTicks current_time, 15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) float delta_distance, 15703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) float displacement) { 15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (state_ == STATE_PULL_DECAY && current_time - start_time_ < duration_) { 15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (state_ != STATE_PULL) { 16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_scale_y_ = kPullGlowBegin; 16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) state_ = STATE_PULL; 16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) start_time_ = current_time; 16703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) duration_ = base::TimeDelta::FromMilliseconds(kPullTimeMs); 16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float abs_delta_distance = std::abs(delta_distance); 17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) pull_distance_ += delta_distance; 17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float distance = std::abs(pull_distance_); 17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_alpha_ = edge_alpha_start_ = Clamp(distance, kPullEdgeBegin, kMaxAlpha); 17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) edge_scale_y_ = edge_scale_y_start_ = 17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Clamp(distance * kPullDistanceEdgeFactor, kHeldEdgeScaleY, 1.f); 17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_alpha_ = glow_alpha_start_ = 17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::min(kMaxAlpha, 17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_alpha_ + abs_delta_distance * kPullDistanceAlphaGlowFactor); 18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) float glow_change = abs_delta_distance; 18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (delta_distance > 0 && pull_distance_ < 0) 18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_change = -glow_change; 18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (pull_distance_ == 0) 18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_scale_y_ = 0; 18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Do not allow glow to get larger than kMaxGlowHeight. 18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_scale_y_ = glow_scale_y_start_ = 18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Clamp(glow_scale_y_ + glow_change * kPullDistanceGlowFactor, 19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 0.f, 19103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) kMaxGlowHeight); 19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_alpha_finish_ = edge_alpha_; 19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_scale_y_finish_ = edge_scale_y_; 19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_alpha_finish_ = glow_alpha_; 19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_scale_y_finish_ = glow_scale_y_; 19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void EdgeEffect::Release(base::TimeTicks current_time) { 20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) pull_distance_ = 0; 20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (state_ != STATE_PULL && state_ != STATE_PULL_DECAY) 20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) state_ = STATE_RECEDE; 20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_alpha_start_ = edge_alpha_; 20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_scale_y_start_ = edge_scale_y_; 20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_alpha_start_ = glow_alpha_; 20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_scale_y_start_ = glow_scale_y_; 21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_alpha_finish_ = 0.f; 21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_scale_y_finish_ = 0.f; 21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_alpha_finish_ = 0.f; 21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_scale_y_finish_ = 0.f; 21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) start_time_ = current_time; 21703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) duration_ = base::TimeDelta::FromMilliseconds(kRecedeTimeMs); 21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void EdgeEffect::Absorb(base::TimeTicks current_time, float velocity) { 22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) state_ = STATE_ABSORB; 222a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch velocity = Clamp(std::abs(velocity), kMinVelocity, kMaxVelocity); 22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) start_time_ = current_time; 22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // This should never be less than 1 millisecond. 2268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) duration_ = base::TimeDelta::FromMilliseconds(0.15f + (velocity * 0.02f)); 22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // The edge should always be at least partially visible, regardless 22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // of velocity. 23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_alpha_start_ = 0.f; 23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_scale_y_ = edge_scale_y_start_ = 0.f; 23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // The glow depends more on the velocity, and therefore starts out 23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // nearly invisible. 2348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) glow_alpha_start_ = 0.3f; 23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_scale_y_start_ = 0.f; 23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Factor the velocity by 8. Testing on device shows this works best to 23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // reflect the strength of the user's scrolling. 239a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch edge_alpha_finish_ = Clamp(velocity * kVelocityEdgeFactor, 0.f, 1.f); 24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Edge should never get larger than the size of its asset. 24103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) edge_scale_y_finish_ = 24203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Clamp(velocity * kVelocityEdgeFactor, kHeldEdgeScaleY, 1.f); 24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Growth for the size of the glow should be quadratic to properly 24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // respond 24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // to a user's scrolling speed. The faster the scrolling speed, the more 24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // intense the effect should be for both the size and the saturation. 24803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) glow_scale_y_finish_ = 24903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::min(0.025f + (velocity * (velocity / 100) * 0.00015f), 1.75f); 25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Alpha should change for the glow as well as size. 25103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) glow_alpha_finish_ = Clamp( 25203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) glow_alpha_start_, velocity * kVelocityGlowFactor * .00001f, kMaxAlpha); 25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool EdgeEffect::Update(base::TimeTicks current_time) { 25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (IsFinished()) 25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const double dt = (current_time - start_time_).InMilliseconds(); 26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const double t = std::min(dt / duration_.InMilliseconds(), 1.); 26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const float interp = static_cast<float>(Damp(t, 1.)); 26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_alpha_ = Lerp(edge_alpha_start_, edge_alpha_finish_, interp); 26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_scale_y_ = Lerp(edge_scale_y_start_, edge_scale_y_finish_, interp); 26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_alpha_ = Lerp(glow_alpha_start_, glow_alpha_finish_, interp); 26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_scale_y_ = Lerp(glow_scale_y_start_, glow_scale_y_finish_, interp); 26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (t >= 1.f - kEpsilon) { 26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) switch (state_) { 27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case STATE_ABSORB: 27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) state_ = STATE_RECEDE; 27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) start_time_ = current_time; 27303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) duration_ = base::TimeDelta::FromMilliseconds(kRecedeTimeMs); 27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 27590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_alpha_start_ = edge_alpha_; 27690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_scale_y_start_ = edge_scale_y_; 27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_alpha_start_ = glow_alpha_; 27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_scale_y_start_ = glow_scale_y_; 27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // After absorb, the glow and edge should fade to nothing. 28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_alpha_finish_ = 0.f; 28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_scale_y_finish_ = 0.f; 28390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_alpha_finish_ = 0.f; 28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_scale_y_finish_ = 0.f; 28590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 28690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case STATE_PULL: 28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) state_ = STATE_PULL_DECAY; 28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) start_time_ = current_time; 28903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) duration_ = base::TimeDelta::FromMilliseconds(kPullDecayTimeMs); 29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_alpha_start_ = edge_alpha_; 29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_scale_y_start_ = edge_scale_y_; 29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_alpha_start_ = glow_alpha_; 29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_scale_y_start_ = glow_scale_y_; 29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // After pull, the glow and edge should fade to nothing. 29790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_alpha_finish_ = 0.f; 29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) edge_scale_y_finish_ = 0.f; 29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_alpha_finish_ = 0.f; 30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) glow_scale_y_finish_ = 0.f; 30190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 302a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch case STATE_PULL_DECAY: { 303a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // When receding, we want edge to decrease more slowly 304a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // than the glow. 30503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const float factor = 30603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) glow_scale_y_finish_ 30703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ? 1 / (glow_scale_y_finish_ * glow_scale_y_finish_) 30803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) : std::numeric_limits<float>::max(); 30903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) edge_scale_y_ = 31003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) edge_scale_y_start_ + 311a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch (edge_scale_y_finish_ - edge_scale_y_start_) * interp * factor; 312a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch state_ = STATE_RECEDE; 313a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } break; 31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case STATE_RECEDE: 31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Finish(); 31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) default: 31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (state_ == STATE_RECEDE && glow_scale_y_ <= 0 && edge_scale_y_ <= 0) 32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Finish(); 32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return !IsFinished(); 32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 32803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void EdgeEffect::ApplyToLayers(const gfx::SizeF& size, 32903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const gfx::Transform& transform) { 33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (IsFinished()) 33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 333a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // An empty window size, while meaningless, is also relatively harmless, and 33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // will simply prevent any drawing of the layers. 33503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (size.IsEmpty()) { 3366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) edge_->Disable(); 3376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) glow_->Disable(); 33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 34090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Glow 342a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const int scaled_glow_height = static_cast<int>( 34303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) std::min(base_glow_height_ * glow_scale_y_ * kGlowHeightWidthRatio * 0.6f, 34403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base_glow_height_ * kMaxGlowHeight) + 34503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 0.5f); 34603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const gfx::Size glow_size(size.width(), scaled_glow_height); 34703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) glow_->Update(glow_size, transform, glow_alpha_); 34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Edge 35003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const int scaled_edge_height = 35103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static_cast<int>(base_edge_height_ * edge_scale_y_); 35203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const gfx::Size edge_size(size.width(), scaled_edge_height); 35303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) edge_->Update(edge_size, transform, edge_alpha_); 3546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 3556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void EdgeEffect::SetParent(cc::Layer* parent) { 3576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) edge_->SetParent(parent); 3586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) glow_->SetParent(parent); 3596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 3606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// static 3626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void EdgeEffect::PreloadResources( 3636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::SystemUIResourceManager* resource_manager) { 3646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(resource_manager); 3656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) resource_manager->PreloadResource( 3666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::SystemUIResourceManager::OVERSCROLL_EDGE); 3676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) resource_manager->PreloadResource( 3686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::SystemUIResourceManager::OVERSCROLL_GLOW); 36990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 37090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 37103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} // namespace content 372