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

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

Issue 1419123002: android: move overscroll effects to ui/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix exports for component build Created 5 years, 1 month 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 2014 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/edge_effect_l.h"
6
7 #include "cc/layers/ui_resource_layer.h"
8 #include "content/browser/android/animation_utils.h"
9 #include "content/public/browser/android/compositor.h"
10 #include "ui/android/resources/resource_manager.h"
11 #include "ui/android/resources/system_ui_resource_type.h"
12 #include "ui/gfx/geometry/rect_f.h"
13 #include "ui/gfx/geometry/size_conversions.h"
14
15 namespace content {
16
17 namespace {
18
19 // Time it will take the effect to fully recede in ms
20 const int kRecedeTimeMs = 600;
21
22 // Time it will take before a pulled glow begins receding in ms
23 const int kPullTimeMs = 167;
24
25 // Time it will take for a pulled glow to decay to partial strength before
26 // release
27 const int kPullDecayTimeMs = 2000;
28
29 const float kMaxAlpha = 0.5f;
30
31 const float kPullGlowBegin = 0.f;
32
33 // Min/max velocity that will be absorbed
34 const float kMinVelocity = 100.f;
35 const float kMaxVelocity = 10000.f;
36
37 const float kEpsilon = 0.001f;
38
39 const float kSin = 0.5f; // sin(PI / 6)
40 const float kCos = 0.866f; // cos(PI / 6);
41
42 // How much dragging should effect the height of the glow image.
43 // Number determined by user testing.
44 const float kPullDistanceAlphaGlowFactor = 0.8f;
45
46 const int kVelocityGlowFactor = 6;
47
48 const ui::SystemUIResourceType kResourceId = ui::OVERSCROLL_GLOW_L;
49
50 } // namespace
51
52 EdgeEffectL::EdgeEffectL(ui::ResourceManager* resource_manager)
53 : resource_manager_(resource_manager),
54 glow_(cc::UIResourceLayer::Create(Compositor::LayerSettings())),
55 glow_alpha_(0),
56 glow_scale_y_(0),
57 glow_alpha_start_(0),
58 glow_alpha_finish_(0),
59 glow_scale_y_start_(0),
60 glow_scale_y_finish_(0),
61 displacement_(0.5f),
62 target_displacement_(0.5f),
63 state_(STATE_IDLE),
64 pull_distance_(0) {
65 // Prevent the provided layers from drawing until the effect is activated.
66 glow_->SetIsDrawable(false);
67 }
68
69 EdgeEffectL::~EdgeEffectL() {
70 glow_->RemoveFromParent();
71 }
72
73 bool EdgeEffectL::IsFinished() const {
74 return state_ == STATE_IDLE;
75 }
76
77 void EdgeEffectL::Finish() {
78 glow_->SetIsDrawable(false);
79 pull_distance_ = 0;
80 state_ = STATE_IDLE;
81 }
82
83 void EdgeEffectL::Pull(base::TimeTicks current_time,
84 float delta_distance,
85 float displacement) {
86 target_displacement_ = displacement;
87 if (state_ == STATE_PULL_DECAY && current_time - start_time_ < duration_) {
88 return;
89 }
90 if (state_ != STATE_PULL) {
91 glow_scale_y_ = std::max(kPullGlowBegin, glow_scale_y_);
92 }
93 state_ = STATE_PULL;
94
95 start_time_ = current_time;
96 duration_ = base::TimeDelta::FromMilliseconds(kPullTimeMs);
97
98 float abs_delta_distance = std::abs(delta_distance);
99 pull_distance_ += delta_distance;
100
101 glow_alpha_ = glow_alpha_start_ = std::min(
102 kMaxAlpha,
103 glow_alpha_ + (abs_delta_distance * kPullDistanceAlphaGlowFactor));
104
105 if (pull_distance_ == 0) {
106 glow_scale_y_ = glow_scale_y_start_ = 0;
107 } else {
108 float scale = 1.f -
109 1.f / std::sqrt(std::abs(pull_distance_) * bounds_.height()) -
110 0.3f;
111 glow_scale_y_ = glow_scale_y_start_ = std::max(0.f, scale) / 0.7f;
112 }
113
114 glow_alpha_finish_ = glow_alpha_;
115 glow_scale_y_finish_ = glow_scale_y_;
116 }
117
118 void EdgeEffectL::Release(base::TimeTicks current_time) {
119 pull_distance_ = 0;
120
121 if (state_ != STATE_PULL && state_ != STATE_PULL_DECAY)
122 return;
123
124 state_ = STATE_RECEDE;
125 glow_alpha_start_ = glow_alpha_;
126 glow_scale_y_start_ = glow_scale_y_;
127
128 glow_alpha_finish_ = 0.f;
129 glow_scale_y_finish_ = 0.f;
130
131 start_time_ = current_time;
132 duration_ = base::TimeDelta::FromMilliseconds(kRecedeTimeMs);
133 }
134
135 void EdgeEffectL::Absorb(base::TimeTicks current_time, float velocity) {
136 state_ = STATE_ABSORB;
137
138 velocity = Clamp(std::abs(velocity), kMinVelocity, kMaxVelocity);
139
140 start_time_ = current_time;
141 // This should never be less than 1 millisecond.
142 duration_ = base::TimeDelta::FromMilliseconds(0.15f + (velocity * 0.02f));
143
144 // The glow depends more on the velocity, and therefore starts out
145 // nearly invisible.
146 glow_alpha_start_ = 0.3f;
147 glow_scale_y_start_ = std::max(glow_scale_y_, 0.f);
148
149 // Growth for the size of the glow should be quadratic to properly respond
150 // to a user's scrolling speed. The faster the scrolling speed, the more
151 // intense the effect should be for both the size and the saturation.
152 glow_scale_y_finish_ =
153 std::min(0.025f + (velocity * (velocity / 100) * 0.00015f) / 2.f, 1.f);
154 // Alpha should change for the glow as well as size.
155 glow_alpha_finish_ = Clamp(
156 glow_alpha_start_, velocity * kVelocityGlowFactor * .00001f, kMaxAlpha);
157 target_displacement_ = 0.5;
158 }
159
160 bool EdgeEffectL::Update(base::TimeTicks current_time) {
161 if (IsFinished())
162 return false;
163
164 const double dt = (current_time - start_time_).InMilliseconds();
165 const double t = std::min(dt / duration_.InMilliseconds(), 1.);
166 const float interp = static_cast<float>(Damp(t, 1.));
167
168 glow_alpha_ = Lerp(glow_alpha_start_, glow_alpha_finish_, interp);
169 glow_scale_y_ = Lerp(glow_scale_y_start_, glow_scale_y_finish_, interp);
170 displacement_ = (displacement_ + target_displacement_) / 2.f;
171
172 if (t >= 1.f - kEpsilon) {
173 switch (state_) {
174 case STATE_ABSORB:
175 state_ = STATE_RECEDE;
176 start_time_ = current_time;
177 duration_ = base::TimeDelta::FromMilliseconds(kRecedeTimeMs);
178
179 glow_alpha_start_ = glow_alpha_;
180 glow_scale_y_start_ = glow_scale_y_;
181
182 glow_alpha_finish_ = 0.f;
183 glow_scale_y_finish_ = 0.f;
184 break;
185 case STATE_PULL:
186 state_ = STATE_PULL_DECAY;
187 start_time_ = current_time;
188 duration_ = base::TimeDelta::FromMilliseconds(kPullDecayTimeMs);
189
190 glow_alpha_start_ = glow_alpha_;
191 glow_scale_y_start_ = glow_scale_y_;
192
193 // After pull, the glow should fade to nothing.
194 glow_alpha_finish_ = 0.f;
195 glow_scale_y_finish_ = 0.f;
196 break;
197 case STATE_PULL_DECAY:
198 state_ = STATE_RECEDE;
199 break;
200 case STATE_RECEDE:
201 Finish();
202 break;
203 default:
204 break;
205 }
206 }
207
208 bool one_last_frame = false;
209 if (state_ == STATE_RECEDE && glow_scale_y_ <= 0) {
210 Finish();
211 one_last_frame = true;
212 }
213
214 return !IsFinished() || one_last_frame;
215 }
216
217 float EdgeEffectL::GetAlpha() const {
218 return IsFinished() ? 0.f : glow_alpha_;
219 }
220
221 void EdgeEffectL::ApplyToLayers(Edge edge,
222 const gfx::SizeF& viewport_size,
223 float offset) {
224 if (IsFinished())
225 return;
226
227 // An empty viewport, while meaningless, is also relatively harmless, and will
228 // simply prevent any drawing of the layers.
229 if (viewport_size.IsEmpty()) {
230 glow_->SetIsDrawable(false);
231 return;
232 }
233
234 gfx::SizeF size = ComputeOrientedSize(edge, viewport_size);
235 const float r = size.width() * 0.75f / kSin;
236 const float y = kCos * r;
237 const float h = r - y;
238 const float o_r = size.height() * 0.75f / kSin;
239 const float o_y = kCos * o_r;
240 const float o_h = o_r - o_y;
241 const float base_glow_scale = h > 0.f ? std::min(o_h / h, 1.f) : 1.f;
242 bounds_ = gfx::Size(size.width(), (int)std::min(size.height(), h));
243 gfx::Size image_bounds(
244 r, std::min(1.f, glow_scale_y_) * base_glow_scale * bounds_.height());
245
246 // Compute the displaced image rect. This includes both the horizontal
247 // offset from the |displacement_| factor, as well as the vertical edge offset
248 // provided by the method call.
249 const float displacement = Clamp(displacement_, 0.f, 1.f) - 0.5f;
250 const float displacement_offset_x = bounds_.width() * displacement * 0.5f;
251 const float image_offset_x = (bounds_.width() - image_bounds.width()) * 0.5f;
252 gfx::RectF image_rect = gfx::RectF(gfx::SizeF(image_bounds));
253 image_rect.Offset(image_offset_x - displacement_offset_x, -std::abs(offset));
254
255 // Clip the image rect against the viewport. If either rect is empty there's
256 // no need to draw anything further.
257 gfx::RectF clipped_rect(size.width(), size.height());
258 clipped_rect.Intersect(image_rect);
259 if (clipped_rect.IsEmpty() || image_rect.IsEmpty()) {
260 glow_->SetIsDrawable(false);
261 return;
262 }
263
264 // Compute the logical UV coordinates of the clipped rect relative to the
265 // displaced image rect.
266 gfx::PointF clipped_top_left = clipped_rect.origin();
267 gfx::PointF clipped_bottom_right = clipped_rect.bottom_right();
268 gfx::PointF uv_top_left(
269 (clipped_top_left.x() - image_rect.x()) / image_rect.width(),
270 (clipped_top_left.y() - image_rect.y()) / image_rect.height());
271 gfx::PointF uv_bottom_right(
272 (clipped_bottom_right.x() - image_rect.x()) / image_rect.width(),
273 (clipped_bottom_right.y() - image_rect.y()) / image_rect.height());
274 glow_->SetUV(uv_top_left, uv_bottom_right);
275
276 // There's no need to use the provided |offset| when computing the transform;
277 // the offset is built in to the computed UV coordinates.
278 glow_->SetTransform(ComputeTransform(edge, viewport_size, 0));
279
280 glow_->SetIsDrawable(true);
281 glow_->SetUIResourceId(resource_manager_->GetUIResourceId(
282 ui::ANDROID_RESOURCE_TYPE_SYSTEM, kResourceId));
283 glow_->SetTransformOrigin(gfx::Point3F(bounds_.width() * 0.5f, 0, 0));
284 glow_->SetBounds(gfx::ToRoundedSize(clipped_rect.size()));
285 glow_->SetContentsOpaque(false);
286 glow_->SetOpacity(Clamp(glow_alpha_, 0.f, 1.f));
287 }
288
289 void EdgeEffectL::SetParent(cc::Layer* parent) {
290 if (glow_->parent() != parent)
291 parent->AddChild(glow_);
292 }
293
294 // static
295 void EdgeEffectL::PreloadResources(ui::ResourceManager* resource_manager) {
296 DCHECK(resource_manager);
297 resource_manager->PreloadResource(ui::ANDROID_RESOURCE_TYPE_SYSTEM,
298 kResourceId);
299 }
300
301 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/android/edge_effect_l.h ('k') | content/browser/android/overscroll_controller_android.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698