Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Unified Diff: content/browser/android/edge_effect.cc

Issue 367173003: [Android] Implementation of overscroll effect for Android L (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix build Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/android/edge_effect.cc
diff --git a/content/browser/android/edge_effect.cc b/content/browser/android/edge_effect.cc
index 94e5b512e20505bf5ad12c59f9258e88f9fa41b1..9f3475e095b0f2f40a567af8dc1aae24d7609791 100644
--- a/content/browser/android/edge_effect.cc
+++ b/content/browser/android/edge_effect.cc
@@ -1,23 +1,19 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.nes
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/android/edge_effect.h"
-#include "cc/layers/layer.h"
+#include "base/debug/trace_event.h"
+#include "base/lazy_instance.h"
+#include "cc/layers/image_layer.h"
+#include "skia/ext/image_operations.h"
+#include "ui/gfx/android/java_bitmap.h"
namespace content {
namespace {
-enum State {
- STATE_IDLE = 0,
- STATE_PULL,
- STATE_ABSORB,
- STATE_RECEDE,
- STATE_PULL_DECAY
-};
-
// Time it will take the effect to fully recede in ms
const int kRecedeTime = 1000;
@@ -41,7 +37,7 @@ const float kMaxVelocity = 10000.f;
const float kEpsilon = 0.001f;
-const float kGlowHeightToWidthRatio = 0.25f;
+const float kGlowHeightWidthRatio = 0.25f;
// How much dragging should effect the height of the edge image.
// Number determined by user testing.
@@ -55,6 +51,11 @@ const float kPullDistanceAlphaGlowFactor = 1.1f;
const int kVelocityEdgeFactor = 8;
const int kVelocityGlowFactor = 12;
+const int kScaledEdgeHeight = 12;
+const int kScaledGlowHeight = 64;
+const float kEdgeHeightAtMdpi = 12.f;
+const float kGlowHeightAtMdpi = 128.f;
+
template <typename T>
T Lerp(T a, T b, T t) {
return a + (b - a) * t;
@@ -76,48 +77,6 @@ T Damp(T input, T factor) {
return result;
}
-gfx::Transform ComputeTransform(EdgeEffect::Edge edge,
- const gfx::SizeF& window_size,
- int offset,
- int height) {
- // Edge effects that require rotation are translated to the center about which
- // the layer should be rotated to align with the corresponding edge.
- switch (edge) {
- case EdgeEffect::EDGE_TOP:
- return gfx::Transform(1, 0, 0, 1, 0, offset);
- case EdgeEffect::EDGE_LEFT:
- return gfx::Transform(0, 1, -1, 0,
- (-window_size.height() + height) / 2.f + offset,
- (window_size.height() - height) / 2.f);
- case EdgeEffect::EDGE_BOTTOM:
- return gfx::Transform(-1, 0, 0, -1,
- 0, window_size.height() - height + offset);
- case EdgeEffect::EDGE_RIGHT:
- return gfx::Transform(0, -1, 1, 0,
- (-window_size.height() - height) / 2.f + window_size.width() + offset,
- (window_size.height() - height) / 2.f);
- default:
- NOTREACHED() << "Invalid edge: " << edge;
- return gfx::Transform();
- };
-}
-
-gfx::Size ComputeBounds(EdgeEffect::Edge edge,
- const gfx::SizeF& window_size,
- int height) {
- switch (edge) {
- case EdgeEffect::EDGE_TOP:
- case EdgeEffect::EDGE_BOTTOM:
- return gfx::Size(window_size.width(), height);
- case EdgeEffect::EDGE_LEFT:
- case EdgeEffect::EDGE_RIGHT:
- return gfx::Size(window_size.height(), height);
- default:
- NOTREACHED() << "Invalid edge: " << edge;
- return gfx::Size();
- };
-}
-
void DisableLayer(cc::Layer* layer) {
DCHECK(layer);
layer->SetIsDrawable(false);
@@ -126,27 +85,90 @@ void DisableLayer(cc::Layer* layer) {
}
void UpdateLayer(cc::Layer* layer,
- EdgeEffect::Edge edge,
- const gfx::SizeF& window_size,
- int offset,
- int height,
+ const gfx::Size& size,
+ const gfx::Transform& transform,
float opacity) {
DCHECK(layer);
layer->SetIsDrawable(true);
- gfx::Size bounds = ComputeBounds(edge, window_size, height);
- layer->SetTransformOrigin(
- gfx::Point3F(bounds.width() * 0.5f, bounds.height() * 0.5f, 0));
- layer->SetTransform(ComputeTransform(edge, window_size, offset, height));
- layer->SetBounds(bounds);
+ layer->SetTransformOrigin(gfx::Point3F(size.width() * 0.5f, 0, 0));
+ layer->SetTransform(transform);
+ layer->SetBounds(size);
layer->SetOpacity(Clamp(opacity, 0.f, 1.f));
}
+scoped_refptr<cc::Layer> CreateImageLayer(const SkBitmap& bitmap) {
+ scoped_refptr<cc::ImageLayer> layer = cc::ImageLayer::Create();
+ layer->SetBitmap(bitmap);
+ return layer;
+}
+
+SkBitmap CreateSkBitmapFromAndroidResource(const char* name, gfx::Size size) {
+ base::android::ScopedJavaLocalRef<jobject> jobj =
+ gfx::CreateJavaBitmapFromAndroidResource(name, size);
+ if (jobj.is_null())
+ return SkBitmap();
+
+ SkBitmap bitmap = CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(jobj.obj()));
+ if (bitmap.isNull())
+ return bitmap;
+
+ return skia::ImageOperations::Resize(
+ bitmap, skia::ImageOperations::RESIZE_BOX, size.width(), size.height());
+}
+
+class EdgeEffectResources {
+ public:
+ EdgeEffectResources() {
+ TRACE_EVENT0("browser", "EdgeEffectResources::Create");
+ edge_bitmap_ =
+ CreateSkBitmapFromAndroidResource("android:drawable/overscroll_edge",
+ gfx::Size(128, kScaledEdgeHeight));
+ glow_bitmap_ =
+ CreateSkBitmapFromAndroidResource("android:drawable/overscroll_glow",
+ gfx::Size(128, kScaledGlowHeight));
+ }
+
+ const SkBitmap& edge_bitmap() const { return edge_bitmap_; }
+ const SkBitmap& glow_bitmap() const { return glow_bitmap_; }
+
+ private:
+ SkBitmap edge_bitmap_;
+ SkBitmap glow_bitmap_;
+
+ DISALLOW_COPY_AND_ASSIGN(EdgeEffectResources);
+};
+
+// Leaky to allow access from a worker thread.
+base::LazyInstance<EdgeEffectResources>::Leaky g_edge_effect_resources =
+ LAZY_INSTANCE_INITIALIZER;
+
} // namespace
-EdgeEffect::EdgeEffect(scoped_refptr<cc::Layer> edge,
- scoped_refptr<cc::Layer> glow)
+// static
+scoped_ptr<EdgeEffect> EdgeEffect::Create(cc::Layer* root_layer,
+ float device_scale_factor) {
+ DCHECK(root_layer);
+
+ const SkBitmap& edge = g_edge_effect_resources.Get().edge_bitmap();
+ const SkBitmap& glow = g_edge_effect_resources.Get().glow_bitmap();
+ if (edge.isNull() || glow.isNull())
+ return scoped_ptr<EdgeEffect>();
+
+ scoped_refptr<cc::Layer> edge_layer = CreateImageLayer(edge);
+ scoped_refptr<cc::Layer> glow_layer = CreateImageLayer(glow);
+ root_layer->AddChild(edge_layer);
+ root_layer->AddChild(glow_layer);
+ return make_scoped_ptr(
+ new EdgeEffect(edge_layer, glow_layer, device_scale_factor));
+}
+
+EdgeEffect::EdgeEffect(const scoped_refptr<cc::Layer>& edge,
+ const scoped_refptr<cc::Layer>& glow,
+ float device_scale_factor)
: edge_(edge)
, glow_(glow)
+ , base_edge_height_(kEdgeHeightAtMdpi * device_scale_factor)
+ , base_glow_height_(kGlowHeightAtMdpi * device_scale_factor)
, edge_alpha_(0)
, edge_scale_y_(0)
, glow_alpha_(0)
@@ -241,6 +263,12 @@ void EdgeEffect::Release(base::TimeTicks current_time) {
duration_ = base::TimeDelta::FromMilliseconds(kRecedeTime);
}
+void EdgeEffect::Pull(base::TimeTicks current_time,
+ float delta_distance,
+ float displacement) {
+ Pull(current_time, delta_distance);
+}
+
void EdgeEffect::Absorb(base::TimeTicks current_time, float velocity) {
state_ = STATE_ABSORB;
velocity = Clamp(std::abs(velocity), kMinVelocity, kMaxVelocity);
@@ -348,17 +376,14 @@ bool EdgeEffect::Update(base::TimeTicks current_time) {
return !IsFinished();
}
-void EdgeEffect::ApplyToLayers(gfx::SizeF window_size,
- Edge edge,
- float edge_height,
- float glow_height,
- float offset) {
+void EdgeEffect::ApplyToLayers(const gfx::SizeF& size,
+ const gfx::Transform& transform) {
if (IsFinished())
return;
// An empty window size, while meaningless, is also relatively harmless, and
// will simply prevent any drawing of the layers.
- if (window_size.IsEmpty()) {
+ if (size.IsEmpty()) {
DisableLayer(edge_.get());
DisableLayer(glow_.get());
return;
@@ -366,15 +391,21 @@ void EdgeEffect::ApplyToLayers(gfx::SizeF window_size,
// Glow
const int scaled_glow_height = static_cast<int>(
- std::min(glow_height * glow_scale_y_ * kGlowHeightToWidthRatio * 0.6f,
- glow_height * kMaxGlowHeight) + 0.5f);
- UpdateLayer(
- glow_.get(), edge, window_size, offset, scaled_glow_height, glow_alpha_);
+ std::min(base_glow_height_ * glow_scale_y_ * kGlowHeightWidthRatio * 0.6f,
+ base_glow_height_ * kMaxGlowHeight) + 0.5f);
+ const gfx::Size glow_size(size.width(), scaled_glow_height);
+ UpdateLayer(glow_.get(), glow_size, transform, glow_alpha_);
// Edge
- const int scaled_edge_height = static_cast<int>(edge_height * edge_scale_y_);
- UpdateLayer(
- edge_.get(), edge, window_size, offset, scaled_edge_height, edge_alpha_);
+ const int scaled_edge_height =
+ static_cast<int>(base_edge_height_ * edge_scale_y_);
+ const gfx::Size edge_size(size.width(), scaled_edge_height);
+ UpdateLayer(edge_.get(), edge_size, transform, edge_alpha_);
+}
+
+// static
+void EdgeEffect::EnsureResources() {
+ g_edge_effect_resources.Get();
}
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698