Add long running gmail memory benchmark for background tab.
[chromium-blink-merge.git] / content / browser / android / edge_effect_l.cc
blobd67d4c2d1b0b6976f1d4c951a7a1619784e4c151
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.
5 #include "content/browser/android/edge_effect_l.h"
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"
13 namespace content {
15 namespace {
17 // Time it will take the effect to fully recede in ms
18 const int kRecedeTimeMs = 600;
20 // Time it will take before a pulled glow begins receding in ms
21 const int kPullTimeMs = 167;
23 // Time it will take for a pulled glow to decay to partial strength before
24 // release
25 const int kPullDecayTimeMs = 2000;
27 const float kMaxAlpha = 0.5f;
29 const float kPullGlowBegin = 0.f;
31 // Min/max velocity that will be absorbed
32 const float kMinVelocity = 100.f;
33 const float kMaxVelocity = 10000.f;
35 const float kEpsilon = 0.001f;
37 const float kSin = 0.5f; // sin(PI / 6)
38 const float kCos = 0.866f; // cos(PI / 6);
40 // How much dragging should effect the height of the glow image.
41 // Number determined by user testing.
42 const float kPullDistanceAlphaGlowFactor = 0.8f;
44 const int kVelocityGlowFactor = 6;
46 const ui::SystemUIResourceType kResourceId = ui::OVERSCROLL_GLOW_L;
48 } // namespace
50 EdgeEffectL::EdgeEffectL(ui::ResourceManager* resource_manager)
51 : resource_manager_(resource_manager),
52 glow_(cc::UIResourceLayer::Create(Compositor::LayerSettings())),
53 glow_alpha_(0),
54 glow_scale_y_(0),
55 glow_alpha_start_(0),
56 glow_alpha_finish_(0),
57 glow_scale_y_start_(0),
58 glow_scale_y_finish_(0),
59 displacement_(0.5f),
60 target_displacement_(0.5f),
61 state_(STATE_IDLE),
62 pull_distance_(0) {
63 // Prevent the provided layers from drawing until the effect is activated.
64 glow_->SetIsDrawable(false);
67 EdgeEffectL::~EdgeEffectL() {
68 glow_->RemoveFromParent();
71 bool EdgeEffectL::IsFinished() const {
72 return state_ == STATE_IDLE;
75 void EdgeEffectL::Finish() {
76 glow_->SetIsDrawable(false);
77 pull_distance_ = 0;
78 state_ = STATE_IDLE;
81 void EdgeEffectL::Pull(base::TimeTicks current_time,
82 float delta_distance,
83 float displacement) {
84 target_displacement_ = displacement;
85 if (state_ == STATE_PULL_DECAY && current_time - start_time_ < duration_) {
86 return;
88 if (state_ != STATE_PULL) {
89 glow_scale_y_ = std::max(kPullGlowBegin, glow_scale_y_);
91 state_ = STATE_PULL;
93 start_time_ = current_time;
94 duration_ = base::TimeDelta::FromMilliseconds(kPullTimeMs);
96 float abs_delta_distance = std::abs(delta_distance);
97 pull_distance_ += delta_distance;
99 glow_alpha_ = glow_alpha_start_ = std::min(
100 kMaxAlpha,
101 glow_alpha_ + (abs_delta_distance * kPullDistanceAlphaGlowFactor));
103 if (pull_distance_ == 0) {
104 glow_scale_y_ = glow_scale_y_start_ = 0;
105 } else {
106 float scale = 1.f -
107 1.f / std::sqrt(std::abs(pull_distance_) * bounds_.height()) -
108 0.3f;
109 glow_scale_y_ = glow_scale_y_start_ = std::max(0.f, scale) / 0.7f;
112 glow_alpha_finish_ = glow_alpha_;
113 glow_scale_y_finish_ = glow_scale_y_;
116 void EdgeEffectL::Release(base::TimeTicks current_time) {
117 pull_distance_ = 0;
119 if (state_ != STATE_PULL && state_ != STATE_PULL_DECAY)
120 return;
122 state_ = STATE_RECEDE;
123 glow_alpha_start_ = glow_alpha_;
124 glow_scale_y_start_ = glow_scale_y_;
126 glow_alpha_finish_ = 0.f;
127 glow_scale_y_finish_ = 0.f;
129 start_time_ = current_time;
130 duration_ = base::TimeDelta::FromMilliseconds(kRecedeTimeMs);
133 void EdgeEffectL::Absorb(base::TimeTicks current_time, float velocity) {
134 state_ = STATE_ABSORB;
136 velocity = Clamp(std::abs(velocity), kMinVelocity, kMaxVelocity);
138 start_time_ = current_time;
139 // This should never be less than 1 millisecond.
140 duration_ = base::TimeDelta::FromMilliseconds(0.15f + (velocity * 0.02f));
142 // The glow depends more on the velocity, and therefore starts out
143 // nearly invisible.
144 glow_alpha_start_ = 0.3f;
145 glow_scale_y_start_ = std::max(glow_scale_y_, 0.f);
147 // Growth for the size of the glow should be quadratic to properly respond
148 // to a user's scrolling speed. The faster the scrolling speed, the more
149 // intense the effect should be for both the size and the saturation.
150 glow_scale_y_finish_ =
151 std::min(0.025f + (velocity * (velocity / 100) * 0.00015f) / 2.f, 1.f);
152 // Alpha should change for the glow as well as size.
153 glow_alpha_finish_ = Clamp(
154 glow_alpha_start_, velocity * kVelocityGlowFactor * .00001f, kMaxAlpha);
155 target_displacement_ = 0.5;
158 bool EdgeEffectL::Update(base::TimeTicks current_time) {
159 if (IsFinished())
160 return false;
162 const double dt = (current_time - start_time_).InMilliseconds();
163 const double t = std::min(dt / duration_.InMilliseconds(), 1.);
164 const float interp = static_cast<float>(Damp(t, 1.));
166 glow_alpha_ = Lerp(glow_alpha_start_, glow_alpha_finish_, interp);
167 glow_scale_y_ = Lerp(glow_scale_y_start_, glow_scale_y_finish_, interp);
168 displacement_ = (displacement_ + target_displacement_) / 2.f;
170 if (t >= 1.f - kEpsilon) {
171 switch (state_) {
172 case STATE_ABSORB:
173 state_ = STATE_RECEDE;
174 start_time_ = current_time;
175 duration_ = base::TimeDelta::FromMilliseconds(kRecedeTimeMs);
177 glow_alpha_start_ = glow_alpha_;
178 glow_scale_y_start_ = glow_scale_y_;
180 glow_alpha_finish_ = 0.f;
181 glow_scale_y_finish_ = 0.f;
182 break;
183 case STATE_PULL:
184 state_ = STATE_PULL_DECAY;
185 start_time_ = current_time;
186 duration_ = base::TimeDelta::FromMilliseconds(kPullDecayTimeMs);
188 glow_alpha_start_ = glow_alpha_;
189 glow_scale_y_start_ = glow_scale_y_;
191 // After pull, the glow should fade to nothing.
192 glow_alpha_finish_ = 0.f;
193 glow_scale_y_finish_ = 0.f;
194 break;
195 case STATE_PULL_DECAY:
196 state_ = STATE_RECEDE;
197 break;
198 case STATE_RECEDE:
199 Finish();
200 break;
201 default:
202 break;
206 bool one_last_frame = false;
207 if (state_ == STATE_RECEDE && glow_scale_y_ <= 0) {
208 Finish();
209 one_last_frame = true;
212 return !IsFinished() || one_last_frame;
215 float EdgeEffectL::GetAlpha() const {
216 return IsFinished() ? 0.f : glow_alpha_;
219 void EdgeEffectL::ApplyToLayers(const gfx::SizeF& size,
220 const gfx::Transform& transform) {
221 if (IsFinished())
222 return;
224 // An empty window size, while meaningless, is also relatively harmless, and
225 // will simply prevent any drawing of the layers.
226 if (size.IsEmpty()) {
227 glow_->SetIsDrawable(false);
228 return;
231 const float r = size.width() * 0.75f / kSin;
232 const float y = kCos * r;
233 const float h = r - y;
234 const float o_r = size.height() * 0.75f / kSin;
235 const float o_y = kCos * o_r;
236 const float o_h = o_r - o_y;
237 const float base_glow_scale = h > 0.f ? std::min(o_h / h, 1.f) : 1.f;
238 bounds_ = gfx::Size(size.width(), (int)std::min(size.height(), h));
239 gfx::Size image_bounds(
240 r, std::min(1.f, glow_scale_y_) * base_glow_scale * bounds_.height());
242 glow_->SetIsDrawable(true);
243 glow_->SetUIResourceId(resource_manager_->GetUIResourceId(
244 ui::ANDROID_RESOURCE_TYPE_SYSTEM, kResourceId));
245 glow_->SetTransformOrigin(gfx::Point3F(bounds_.width() * 0.5f, 0, 0));
246 glow_->SetBounds(image_bounds);
247 glow_->SetContentsOpaque(false);
248 glow_->SetOpacity(Clamp(glow_alpha_, 0.f, 1.f));
250 const float displacement = Clamp(displacement_, 0.f, 1.f) - 0.5f;
251 const float displacement_offset_x = bounds_.width() * displacement * 0.5f;
252 const float image_offset_x = (bounds_.width() - image_bounds.width()) * 0.5f;
253 gfx::Transform offset_transform;
254 offset_transform.Translate(image_offset_x - displacement_offset_x, 0);
255 offset_transform.ConcatTransform(transform);
256 glow_->SetTransform(offset_transform);
259 void EdgeEffectL::SetParent(cc::Layer* parent) {
260 if (glow_->parent() != parent)
261 parent->AddChild(glow_);
264 // static
265 void EdgeEffectL::PreloadResources(ui::ResourceManager* resource_manager) {
266 DCHECK(resource_manager);
267 resource_manager->PreloadResource(ui::ANDROID_RESOURCE_TYPE_SYSTEM,
268 kResourceId);
271 } // namespace content