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

Side by Side Diff: content/browser/android/overscroll_glow.cc

Issue 14268004: Add overscroll edge effect animations for Android. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 8 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/android/overscroll_glow.h"
6
7 #include "cc/layers/image_layer.h"
8
9 namespace content {
10
11 namespace {
12
13 static scoped_refptr<cc::Layer> NewLayer(const SkBitmap& bitmap) {
14 scoped_refptr<cc::ImageLayer> layer = cc::ImageLayer::Create();
15 layer->SetContentsOpaque(false);
16 layer->SetBitmap(bitmap);
17 return layer;
18 }
19
20 }
21
22 OverscrollGlow::OverscrollGlow(const SkBitmap& edge, const SkBitmap& glow)
23 : horizontal_overscroll_enabled_(true) {
24 for (unsigned i = 0; i < EDGE_COUNT; ++i)
25 edge_effects_[i]
26 = make_scoped_ptr(new EdgeEffect(NewLayer(edge), NewLayer(glow)));
27 }
28
29 OverscrollGlow::~OverscrollGlow() { }
30
31 void OverscrollGlow::OnOverscrolled(base::TimeTicks current_time,
32 gfx::Vector2dF overscroll,
33 gfx::Vector2dF velocity) {
34 if (!horizontal_overscroll_enabled_) {
35 overscroll.set_x(0);
36 velocity.set_x(0);
37 }
38
39 if (overscroll.IsZero()) {
40 old_overscroll_ = overscroll;
41 if (IsAnimating())
42 Release(current_time);
43 return;
44 }
45
46 if (!velocity.IsZero()) {
47 Absorb(current_time, velocity, overscroll, old_overscroll_);
48 } else {
49 if (overscroll.x() * old_overscroll_.x() <= 0 ||
50 std::abs(overscroll.x()) < std::abs(old_overscroll_.x())) {
51 edge_effects_[EdgeEffect::EDGE_LEFT]->Release(current_time);
52 edge_effects_[EdgeEffect::EDGE_RIGHT]->Release(current_time);
53 }
54 if (overscroll.y() * old_overscroll_.y() <= 0 ||
55 std::abs(overscroll.y()) < std::abs(old_overscroll_.y())) {
56 edge_effects_[EdgeEffect::EDGE_TOP]->Release(current_time);
57 edge_effects_[EdgeEffect::EDGE_BOTTOM]->Release(current_time);
58 }
59
60 gfx::Vector2dF overscroll_delta = overscroll - old_overscroll_;
61 // Ensure monotonic overscroll accumulation
62 if (overscroll_delta.x() * old_overscroll_.x() < 0)
63 overscroll_delta.set_x(0);
64 if (overscroll_delta.y() * old_overscroll_.y() < 0)
65 overscroll_delta.set_y(0);
66 Pull(current_time, overscroll_delta);
67 }
68
69 old_overscroll_ = overscroll;
70 }
71
72 void OverscrollGlow::Release(base::TimeTicks current_time) {
73 for (unsigned i = 0; i < EDGE_COUNT; ++i) {
74 edge_effects_[i]->Release(current_time);
75 }
76 old_overscroll_ = gfx::Vector2dF();
77 }
78
79 void OverscrollGlow::Finish() {
80 for (unsigned i = 0; i < EDGE_COUNT; ++i) {
81 edge_effects_[i]->Finish();
82 }
83 old_overscroll_ = gfx::Vector2dF();
84 }
85
86 bool OverscrollGlow::Animate(base::TimeTicks current_time) {
87 if (size_.GetArea() == 0)
88 return IsAnimating();
89
90 gfx::SizeF sizes[EDGE_COUNT] = {
91 size_, gfx::SizeF(size_.height(), size_.width()),
92 size_, gfx::SizeF(size_.height(), size_.width())
93 };
94
95 bool active = false;
96 for (unsigned i = 0; i < EDGE_COUNT; ++i) {
97 active |= edge_effects_[i]->Update(current_time);
98 edge_effects_[i]->Draw(parent_layer_, sizes[i],
99 static_cast<EdgeEffect::Edge>(i));
100 }
101
102 return active;
103 }
104
105 bool OverscrollGlow::IsAnimating() const {
106 for (unsigned i = 0; i < EDGE_COUNT; ++i) {
107 if (!edge_effects_[i]->IsFinished())
108 return false;
109 }
110 return true;
111 }
112
113 void OverscrollGlow::set_horizontal_overscroll_enabled(bool enabled) {
114 horizontal_overscroll_enabled_ = enabled;
115 }
116
117 void OverscrollGlow::set_size(const gfx::SizeF& size) {
118 size_ = size;
119 }
120
121 void OverscrollGlow::set_parent_layer(scoped_refptr<cc::Layer> parent_layer) {
122 if (parent_layer == parent_layer_)
123 return;
124
125 Finish();
126
127 parent_layer_ = parent_layer;
128 }
129
130
131 void OverscrollGlow::Pull(base::TimeTicks current_time,
132 const gfx::Vector2dF& overscroll_delta) {
133 using std::max;
134 using std::min;
135
136 if (overscroll_delta.IsZero())
137 return;
138
139 gfx::Vector2dF overscroll_pull = gfx::ScaleVector2d(overscroll_delta,
140 1.f / size_.width(),
141 1.f / size_.height());
142 float edge_overscroll_pull[EDGE_COUNT] = {
143 min(overscroll_pull.y(), 0.f), // Top
144 min(overscroll_pull.x(), 0.f), // Left
145 max(overscroll_pull.y(), 0.f), // Bottom
146 max(overscroll_pull.x(), 0.f) // Right
147 };
148
149 for (unsigned i = 0; i < EDGE_COUNT; ++i) {
150 if (!edge_overscroll_pull[i])
151 continue;
152
153 EdgeEffect& edge_effect = *edge_effects_[i];
154 EdgeEffect& opposite_edge_effect = *edge_effects_[(i + 2) % EDGE_COUNT];
155 edge_effect.Pull(current_time, std::abs(edge_overscroll_pull[i]));
156 if (!opposite_edge_effect.IsFinished())
157 opposite_edge_effect.Release(current_time);
158 }
159 }
160
161 void OverscrollGlow::Absorb(base::TimeTicks current_time,
162 const gfx::Vector2dF& velocity,
163 const gfx::Vector2dF& overscroll,
164 const gfx::Vector2dF& old_overscroll) {
165 using std::max;
166 using std::min;
167
168 if (overscroll.IsZero() || velocity.IsZero())
169 return;
170
171 // Only trigger on initial overscroll at a non-zero velocity
172 const float overscroll_velocities[EDGE_COUNT] = {
173 old_overscroll.y() >= 0 && overscroll.y() < 0 ? min(velocity.y(), 0.f) : 0,
174 old_overscroll.x() >= 0 && overscroll.x() < 0 ? min(velocity.x(), 0.f) : 0,
175 old_overscroll.y() <= 0 && overscroll.y() > 0 ? max(velocity.y(), 0.f) : 0,
176 old_overscroll.x() <= 0 && overscroll.x() > 0 ? max(velocity.x(), 0.f) : 0
177 };
178
179 for (unsigned i = 0; i < EDGE_COUNT; ++i) {
180 if (!overscroll_velocities[i])
181 continue;
182
183 EdgeEffect& edge_effect = *edge_effects_[i];
184 EdgeEffect& opposite_edge_effect = *edge_effects_[(i + 2) % EDGE_COUNT];
185 edge_effect.Absorb(current_time, std::abs(overscroll_velocities[i]));
186 if (!opposite_edge_effect.IsFinished()) {
187 opposite_edge_effect.Release(current_time);
188 }
189 }
190 }
191
192 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698