Chromium Code Reviews| Index: content/browser/android/overscroll_glow.cc |
| diff --git a/content/browser/android/overscroll_glow.cc b/content/browser/android/overscroll_glow.cc |
| index 3f316d8aee62236969e084b2072c555a2e7b8859..0b3dba320c29b0042021b9653722b2198cbe4578 100644 |
| --- a/content/browser/android/overscroll_glow.cc |
| +++ b/content/browser/android/overscroll_glow.cc |
| @@ -4,10 +4,13 @@ |
| #include "content/browser/android/overscroll_glow.h" |
| +#include "base/android/build_info.h" |
| #include "base/debug/trace_event.h" |
| #include "base/lazy_instance.h" |
| #include "cc/layers/layer.h" |
| #include "content/browser/android/edge_effect.h" |
| +#include "content/browser/android/edge_effect_l.h" |
| +#include "ui/gfx/screen.h" |
| using std::max; |
| using std::min; |
| @@ -17,8 +20,9 @@ namespace content { |
| namespace { |
| const float kEpsilon = 1e-3f; |
| -const float kEdgeHeightAtMdpi = 12.f; |
| -const float kGlowHeightAtMdpi = 128.f; |
| + |
| +// The maximum Android build version prior to L release. |
| +const int kKitKatSDKVersion = 19; |
|
aelias_OOO_until_Jul13
2014/08/14 22:54:19
Suggest rename to kKitKatMR2SDKVersion to avoid am
jdduke (slow)
2014/08/15 19:15:06
Done.
|
| bool IsApproxZero(float value) { |
| return std::abs(value) < kEpsilon; |
| @@ -32,6 +36,76 @@ gfx::Vector2dF ZeroSmallComponents(gfx::Vector2dF vector) { |
| return vector; |
| } |
| +gfx::Transform ComputeTransform(OverscrollGlow::Edge edge, |
| + const gfx::SizeF& window_size, |
| + float offset) { |
| + // Transforms assume the edge layers are anchored to their *top center point*. |
| + switch (edge) { |
| + case OverscrollGlow::EDGE_TOP: |
| + return gfx::Transform(1, 0, 0, 1, 0, offset); |
| + case OverscrollGlow::EDGE_LEFT: |
| + return gfx::Transform(0, |
| + 1, |
| + -1, |
| + 0, |
| + -window_size.height() / 2.f + offset, |
| + window_size.height() / 2.f); |
| + case OverscrollGlow::EDGE_BOTTOM: |
| + return gfx::Transform(-1, 0, 0, -1, 0, window_size.height() + offset); |
| + case OverscrollGlow::EDGE_RIGHT: |
| + return gfx::Transform( |
| + 0, |
| + -1, |
| + 1, |
| + 0, |
| + -window_size.height() / 2.f + window_size.width() + offset, |
| + window_size.height() / 2.f); |
| + default: |
| + NOTREACHED() << "Invalid edge: " << edge; |
| + return gfx::Transform(); |
| + }; |
| +} |
| + |
| +gfx::SizeF ComputeSize(OverscrollGlow::Edge edge, |
| + const gfx::SizeF& window_size) { |
| + switch (edge) { |
| + case OverscrollGlow::EDGE_TOP: |
| + case OverscrollGlow::EDGE_BOTTOM: |
| + return window_size; |
| + case OverscrollGlow::EDGE_LEFT: |
| + case OverscrollGlow::EDGE_RIGHT: |
| + return gfx::SizeF(window_size.height(), window_size.width()); |
| + default: |
| + NOTREACHED() << "Invalid edge: " << edge; |
| + return gfx::SizeF(); |
| + }; |
| +} |
| + |
| +bool UseEdgeEffectL() { |
|
aelias_OOO_until_Jul13
2014/08/14 22:54:19
I don't like this kind of global factory policy.
jdduke (slow)
2014/08/15 19:15:06
Hmm, the EdgeEffects are currently setup to be laz
|
| + static bool use_edge_effect_l = |
| + base::android::BuildInfo::GetInstance()->sdk_int() > kKitKatSDKVersion; |
| + return use_edge_effect_l; |
| +} |
| + |
| +void PreloadResourcesNonBlocking( |
| + ui::SystemUIResourceManager* resource_manager) { |
| + if (UseEdgeEffectL()) |
| + EdgeEffectL::PreloadResources(resource_manager); |
| + else |
| + EdgeEffect::PreloadResources(resource_manager); |
| +} |
| + |
| +scoped_ptr<EdgeEffectBase> CreateEdgeEffect( |
| + ui::SystemUIResourceManager* resource_manager, |
| + float device_scale_factor) { |
| + scoped_ptr<EdgeEffectBase> result; |
| + if (UseEdgeEffectL()) |
| + result.reset(new EdgeEffectL(resource_manager)); |
| + else |
| + result.reset(new EdgeEffect(resource_manager, device_scale_factor)); |
| + return result.Pass(); |
| +} |
| + |
| } // namespace |
| scoped_ptr<OverscrollGlow> OverscrollGlow::Create( |
| @@ -42,7 +116,7 @@ scoped_ptr<OverscrollGlow> OverscrollGlow::Create( |
| OverscrollGlow::OverscrollGlow(ui::SystemUIResourceManager* resource_manager) |
| : enabled_(true), initialized_(false), resource_manager_(resource_manager) { |
| DCHECK(resource_manager_); |
| - EdgeEffect::PreloadResources(resource_manager_); |
| + PreloadResourcesNonBlocking(resource_manager_); |
| } |
| OverscrollGlow::~OverscrollGlow() { |
| @@ -59,7 +133,7 @@ void OverscrollGlow::Disable() { |
| enabled_ = false; |
| if (!enabled_ && initialized_) { |
| Detach(); |
| - for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) |
| + for (size_t i = 0; i < EDGE_COUNT; ++i) |
| edge_effects_[i]->Finish(); |
| } |
| } |
| @@ -68,7 +142,8 @@ bool OverscrollGlow::OnOverscrolled(cc::Layer* overscrolling_layer, |
| base::TimeTicks current_time, |
| gfx::Vector2dF accumulated_overscroll, |
| gfx::Vector2dF overscroll_delta, |
| - gfx::Vector2dF velocity) { |
| + gfx::Vector2dF velocity, |
| + gfx::Vector2dF displacement) { |
| DCHECK(overscrolling_layer); |
| if (!enabled_) |
| @@ -98,16 +173,11 @@ bool OverscrollGlow::OnOverscrolled(cc::Layer* overscrolling_layer, |
| bool y_overscroll_started = |
| !IsApproxZero(overscroll_delta.y()) && IsApproxZero(old_overscroll.y()); |
| - if (x_overscroll_started) |
| - ReleaseAxis(AXIS_X, current_time); |
| - if (y_overscroll_started) |
| - ReleaseAxis(AXIS_Y, current_time); |
| - |
| velocity = ZeroSmallComponents(velocity); |
| if (!velocity.IsZero()) |
| Absorb(current_time, velocity, x_overscroll_started, y_overscroll_started); |
| else |
| - Pull(current_time, overscroll_delta); |
| + Pull(current_time, overscroll_delta, displacement); |
| UpdateLayerAttachment(overscrolling_layer); |
| return NeedsAnimate(); |
| @@ -119,14 +189,13 @@ bool OverscrollGlow::Animate(base::TimeTicks current_time) { |
| return false; |
| } |
| - for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) { |
| + for (size_t i = 0; i < EDGE_COUNT; ++i) { |
| if (edge_effects_[i]->Update(current_time)) { |
| + Edge edge = static_cast<Edge>(i); |
| edge_effects_[i]->ApplyToLayers( |
| - display_params_.size, |
| - static_cast<EdgeEffect::Edge>(i), |
| - kEdgeHeightAtMdpi * display_params_.device_scale_factor, |
| - kGlowHeightAtMdpi * display_params_.device_scale_factor, |
| - display_params_.edge_offsets[i]); |
| + ComputeSize(edge, display_params_.size), |
| + ComputeTransform( |
| + edge, display_params_.size, display_params_.edge_offsets[i])); |
| } |
| } |
| @@ -145,7 +214,7 @@ void OverscrollGlow::UpdateDisplayParameters(const DisplayParameters& params) { |
| bool OverscrollGlow::NeedsAnimate() const { |
| if (!enabled_ || !initialized_) |
| return false; |
| - for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) { |
| + for (size_t i = 0; i < EDGE_COUNT; ++i) { |
| if (!edge_effects_[i]->IsFinished()) |
| return true; |
| } |
| @@ -165,7 +234,7 @@ void OverscrollGlow::UpdateLayerAttachment(cc::Layer* parent) { |
| if (root_layer_->parent() != parent) |
| parent->AddChild(root_layer_); |
| - for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) |
| + for (size_t i = 0; i < EDGE_COUNT; ++i) |
| edge_effects_[i]->SetParent(root_layer_); |
| } |
| @@ -181,57 +250,69 @@ bool OverscrollGlow::InitializeIfNecessary() { |
| DCHECK(!root_layer_); |
| root_layer_ = cc::Layer::Create(); |
| - for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) |
| - edge_effects_[i] = make_scoped_ptr(new EdgeEffect(resource_manager_)); |
| + const float device_scale_factor = |
| + gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().device_scale_factor(); |
|
aelias_OOO_until_Jul13
2014/08/14 22:54:19
Can this also be passed in the OverscrollGlow cons
jdduke (slow)
2014/08/15 19:15:06
Hmm, if I pass in a factory method I think we can
|
| + for (size_t i = 0; i < EDGE_COUNT; ++i) |
| + edge_effects_[i] = CreateEdgeEffect(resource_manager_, device_scale_factor); |
| initialized_ = true; |
| return true; |
| } |
| void OverscrollGlow::Pull(base::TimeTicks current_time, |
| - gfx::Vector2dF overscroll_delta) { |
| + const gfx::Vector2dF& overscroll_delta, |
| + const gfx::Vector2dF& overscroll_location) { |
| DCHECK(enabled_ && initialized_); |
| - overscroll_delta = ZeroSmallComponents(overscroll_delta); |
| - if (overscroll_delta.IsZero()) |
| - return; |
| + DCHECK(!overscroll_delta.IsZero()); |
| + const float inv_width = 1.f / display_params_.size.width(); |
| + const float inv_height = 1.f / display_params_.size.height(); |
| gfx::Vector2dF overscroll_pull = |
| - gfx::ScaleVector2d(overscroll_delta, |
| - 1.f / display_params_.size.width(), |
| - 1.f / display_params_.size.height()); |
| - float edge_overscroll_pull[EdgeEffect::EDGE_COUNT] = { |
| + gfx::ScaleVector2d(overscroll_delta, inv_width, inv_height); |
| + const float edge_pull[EDGE_COUNT] = { |
| min(overscroll_pull.y(), 0.f), // Top |
| min(overscroll_pull.x(), 0.f), // Left |
| max(overscroll_pull.y(), 0.f), // Bottom |
| max(overscroll_pull.x(), 0.f) // Right |
| }; |
| - for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) { |
| - if (!edge_overscroll_pull[i]) |
| + gfx::Vector2dF displacement = |
| + gfx::ScaleVector2d(overscroll_location, inv_width, inv_height); |
| + displacement.set_x(max(0.f, min(1.f, displacement.x()))); |
| + displacement.set_y(max(0.f, min(1.f, displacement.y()))); |
| + const float edge_displacement[EDGE_COUNT] = { |
| + 1.f - displacement.x(), // Top |
| + displacement.y(), // Left |
| + displacement.x(), // Bottom |
| + 1.f - displacement.y() // Right |
| + }; |
| + |
| + for (size_t i = 0; i < EDGE_COUNT; ++i) { |
| + if (!edge_pull[i]) |
| continue; |
| - edge_effects_[i]->Pull(current_time, std::abs(edge_overscroll_pull[i])); |
| + edge_effects_[i]->Pull( |
| + current_time, std::abs(edge_pull[i]), edge_displacement[i]); |
| GetOppositeEdge(i)->Release(current_time); |
| } |
| } |
| void OverscrollGlow::Absorb(base::TimeTicks current_time, |
| - gfx::Vector2dF velocity, |
| + const gfx::Vector2dF& velocity, |
| bool x_overscroll_started, |
| bool y_overscroll_started) { |
| DCHECK(enabled_ && initialized_); |
| - if (velocity.IsZero()) |
| - return; |
| + DCHECK(!velocity.IsZero()); |
| // Only trigger on initial overscroll at a non-zero velocity |
| - const float overscroll_velocities[EdgeEffect::EDGE_COUNT] = { |
| + const float overscroll_velocities[EDGE_COUNT] = { |
| y_overscroll_started ? min(velocity.y(), 0.f) : 0, // Top |
| x_overscroll_started ? min(velocity.x(), 0.f) : 0, // Left |
| y_overscroll_started ? max(velocity.y(), 0.f) : 0, // Bottom |
| x_overscroll_started ? max(velocity.x(), 0.f) : 0 // Right |
| }; |
| - for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) { |
| + for (size_t i = 0; i < EDGE_COUNT; ++i) { |
| if (!overscroll_velocities[i]) |
| continue; |
| @@ -242,31 +323,16 @@ void OverscrollGlow::Absorb(base::TimeTicks current_time, |
| void OverscrollGlow::Release(base::TimeTicks current_time) { |
| DCHECK(initialized_); |
| - for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) |
| + for (size_t i = 0; i < EDGE_COUNT; ++i) |
| edge_effects_[i]->Release(current_time); |
| } |
| -void OverscrollGlow::ReleaseAxis(Axis axis, base::TimeTicks current_time) { |
| - DCHECK(initialized_); |
| - switch (axis) { |
| - case AXIS_X: |
| - edge_effects_[EdgeEffect::EDGE_LEFT]->Release(current_time); |
| - edge_effects_[EdgeEffect::EDGE_RIGHT]->Release(current_time); |
| - break; |
| - case AXIS_Y: |
| - edge_effects_[EdgeEffect::EDGE_TOP]->Release(current_time); |
| - edge_effects_[EdgeEffect::EDGE_BOTTOM]->Release(current_time); |
| - break; |
| - }; |
| -} |
| - |
| -EdgeEffect* OverscrollGlow::GetOppositeEdge(int edge_index) { |
| +EdgeEffectBase* OverscrollGlow::GetOppositeEdge(int edge_index) { |
| DCHECK(initialized_); |
| - return edge_effects_[(edge_index + 2) % EdgeEffect::EDGE_COUNT].get(); |
| + return edge_effects_[(edge_index + 2) % EDGE_COUNT].get(); |
| } |
| -OverscrollGlow::DisplayParameters::DisplayParameters() |
| - : device_scale_factor(1) { |
| +OverscrollGlow::DisplayParameters::DisplayParameters() { |
| edge_offsets[0] = edge_offsets[1] = edge_offsets[2] = edge_offsets[3] = 0.f; |
| } |