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

Side by Side Diff: cc/animation/element_animations.cc

Issue 2335043002: CC Animation: Move animations_ from ElementAnimations to AnimationPlayer. (Closed)
Patch Set: Clean it up harder. Rework UpdateClientAnimationState. Created 4 years, 3 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/animation/element_animations.h" 5 #include "cc/animation/element_animations.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 10
11 #include "base/macros.h" 11 #include "base/macros.h"
12 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "cc/animation/animation_delegate.h" 13 #include "cc/animation/animation_delegate.h"
14 #include "cc/animation/animation_host.h" 14 #include "cc/animation/animation_host.h"
15 #include "cc/animation/animation_player.h" 15 #include "cc/animation/animation_player.h"
16 #include "cc/animation/keyframed_animation_curve.h" 16 #include "cc/animation/keyframed_animation_curve.h"
17 #include "cc/animation/scroll_offset_animation_curve.h"
18 #include "cc/output/filter_operations.h" 17 #include "cc/output/filter_operations.h"
19 #include "cc/trees/mutator_host_client.h" 18 #include "cc/trees/mutator_host_client.h"
20 #include "ui/gfx/geometry/box_f.h" 19 #include "ui/gfx/geometry/box_f.h"
21 20
22 namespace cc { 21 namespace cc {
23 22
24 scoped_refptr<ElementAnimations> ElementAnimations::Create() { 23 scoped_refptr<ElementAnimations> ElementAnimations::Create() {
25 return make_scoped_refptr(new ElementAnimations()); 24 return make_scoped_refptr(new ElementAnimations());
26 } 25 }
27 26
28 ElementAnimations::ElementAnimations() 27 ElementAnimations::ElementAnimations()
29 : players_list_(new PlayersList()), 28 : players_list_(new PlayersList()),
30 animation_host_(), 29 animation_host_(),
31 element_id_(), 30 element_id_(),
32 is_active_(false), 31 is_active_(false),
33 has_element_in_active_list_(false), 32 has_element_in_active_list_(false),
34 has_element_in_pending_list_(false), 33 has_element_in_pending_list_(false),
35 needs_to_start_animations_(false),
36 scroll_offset_animation_was_interrupted_(false), 34 scroll_offset_animation_was_interrupted_(false),
37 needs_push_properties_(false) {} 35 needs_push_properties_(false) {
36 ClearNeedsUpdateImplClientState();
37 }
38 38
39 ElementAnimations::~ElementAnimations() {} 39 ElementAnimations::~ElementAnimations() {}
40 40
41 void ElementAnimations::SetAnimationHost(AnimationHost* host) { 41 void ElementAnimations::SetAnimationHost(AnimationHost* host) {
42 animation_host_ = host; 42 animation_host_ = host;
43 } 43 }
44 44
45 void ElementAnimations::SetElementId(ElementId element_id) { 45 void ElementAnimations::SetElementId(ElementId element_id) {
46 element_id_ = element_id; 46 element_id_ = element_id;
47 } 47 }
48 48
49 void ElementAnimations::InitAffectedElementTypes() { 49 void ElementAnimations::InitAffectedElementTypes() {
50 DCHECK(element_id_); 50 DCHECK(element_id_);
51 DCHECK(animation_host_); 51 DCHECK(animation_host_);
52 52
53 UpdateActivation(FORCE_ACTIVATION); 53 UpdateActivation(ActivationType::FORCE);
54 54
55 DCHECK(animation_host_->mutator_host_client()); 55 DCHECK(animation_host_->mutator_host_client());
56 if (animation_host_->mutator_host_client()->IsElementInList( 56 if (animation_host_->mutator_host_client()->IsElementInList(
57 element_id_, ElementListType::ACTIVE)) { 57 element_id_, ElementListType::ACTIVE)) {
58 set_has_element_in_active_list(true); 58 set_has_element_in_active_list(true);
59 } 59 }
60 if (animation_host_->mutator_host_client()->IsElementInList( 60 if (animation_host_->mutator_host_client()->IsElementInList(
61 element_id_, ElementListType::PENDING)) { 61 element_id_, ElementListType::PENDING)) {
62 set_has_element_in_pending_list(true); 62 set_has_element_in_pending_list(true);
63 } 63 }
(...skipping 12 matching lines...) Expand all
76 76
77 if (has_element_in_pending_list()) { 77 if (has_element_in_pending_list()) {
78 IsAnimatingChanged(ElementListType::PENDING, TargetProperty::TRANSFORM, 78 IsAnimatingChanged(ElementListType::PENDING, TargetProperty::TRANSFORM,
79 AnimationChangeType::BOTH, false); 79 AnimationChangeType::BOTH, false);
80 IsAnimatingChanged(ElementListType::PENDING, TargetProperty::OPACITY, 80 IsAnimatingChanged(ElementListType::PENDING, TargetProperty::OPACITY,
81 AnimationChangeType::BOTH, false); 81 AnimationChangeType::BOTH, false);
82 } 82 }
83 set_has_element_in_pending_list(false); 83 set_has_element_in_pending_list(false);
84 84
85 animation_host_->DidDeactivateElementAnimations(this); 85 animation_host_->DidDeactivateElementAnimations(this);
86 UpdateActivation(FORCE_ACTIVATION); 86 UpdateActivation(ActivationType::FORCE);
87 } 87 }
88 88
89 void ElementAnimations::ElementRegistered(ElementId element_id, 89 void ElementAnimations::ElementRegistered(ElementId element_id,
90 ElementListType list_type) { 90 ElementListType list_type) {
91 DCHECK_EQ(element_id_, element_id); 91 DCHECK_EQ(element_id_, element_id);
92 92
93 if (!has_element_in_any_list()) 93 if (!has_element_in_any_list())
94 UpdateActivation(FORCE_ACTIVATION); 94 UpdateActivation(ActivationType::FORCE);
95 95
96 if (list_type == ElementListType::ACTIVE) 96 if (list_type == ElementListType::ACTIVE)
97 set_has_element_in_active_list(true); 97 set_has_element_in_active_list(true);
98 else 98 else
99 set_has_element_in_pending_list(true); 99 set_has_element_in_pending_list(true);
100 } 100 }
101 101
102 void ElementAnimations::ElementUnregistered(ElementId element_id, 102 void ElementAnimations::ElementUnregistered(ElementId element_id,
103 ElementListType list_type) { 103 ElementListType list_type) {
104 DCHECK_EQ(this->element_id(), element_id); 104 DCHECK_EQ(this->element_id(), element_id);
(...skipping 23 matching lines...) Expand all
128 } 128 }
129 129
130 void ElementAnimations::PushPropertiesTo( 130 void ElementAnimations::PushPropertiesTo(
131 scoped_refptr<ElementAnimations> element_animations_impl) { 131 scoped_refptr<ElementAnimations> element_animations_impl) {
132 DCHECK_NE(this, element_animations_impl); 132 DCHECK_NE(this, element_animations_impl);
133 133
134 if (!needs_push_properties_) 134 if (!needs_push_properties_)
135 return; 135 return;
136 needs_push_properties_ = false; 136 needs_push_properties_ = false;
137 137
138 if (!HasAnyAnimation() && !element_animations_impl->HasAnyAnimation()) 138 element_animations_impl->scroll_offset_animation_was_interrupted_ =
139 return; 139 scroll_offset_animation_was_interrupted_;
140 MarkAbortedAnimationsForDeletion(element_animations_impl.get()); 140 scroll_offset_animation_was_interrupted_ = false;
141 PurgeAnimationsMarkedForDeletion();
142 PushNewAnimationsToImplThread(element_animations_impl.get());
143 141
144 // Remove finished impl side animations only after pushing, 142 // Update impl client state.
145 // and only after the animations are deleted on the main thread 143 element_animations_impl->UpdateClientAnimationState(
146 // this insures we will never push an animation twice. 144 needs_update_impl_client_state_transform_,
147 RemoveAnimationsCompletedOnMainThread(element_animations_impl.get()); 145 needs_update_impl_client_state_opacity_,
146 needs_update_impl_client_state_filter_);
147 ClearNeedsUpdateImplClientState();
148 148
149 PushPropertiesToImplThread(element_animations_impl.get()); 149 element_animations_impl->UpdateActivation(ActivationType::NORMAL);
150 element_animations_impl->UpdateActivation(NORMAL_ACTIVATION); 150 UpdateActivation(ActivationType::NORMAL);
151 UpdateActivation(NORMAL_ACTIVATION);
152 } 151 }
153 152
154 void ElementAnimations::AddAnimation(std::unique_ptr<Animation> animation) { 153 void ElementAnimations::UpdateClientAnimationState(
155 DCHECK(!animation->is_impl_only() || 154 TargetProperty::Type target_property) {
156 animation->target_property() == TargetProperty::SCROLL_OFFSET);
157 TargetProperty::Type target_property = animation->target_property();
158 animations_.push_back(std::move(animation));
159 needs_to_start_animations_ = true;
160 UpdateActivation(NORMAL_ACTIVATION);
161 switch (target_property) { 155 switch (target_property) {
162 case TargetProperty::TRANSFORM: 156 case TargetProperty::TRANSFORM:
163 case TargetProperty::OPACITY: 157 case TargetProperty::OPACITY:
164 case TargetProperty::FILTER: 158 case TargetProperty::FILTER:
165 UpdateClientAnimationState(target_property); 159 UpdateClientAnimationStateInternal(target_property);
166 break; 160 break;
167 default: 161 default:
162 // Do not update for other properties.
168 break; 163 break;
169 } 164 }
170 SetNeedsPushProperties(); 165 }
166
167 void ElementAnimations::UpdateClientAnimationState(bool transform,
168 bool opacity,
169 bool filter) {
170 if (transform)
171 UpdateClientAnimationStateInternal(TargetProperty::TRANSFORM);
172 if (opacity)
173 UpdateClientAnimationStateInternal(TargetProperty::OPACITY);
174 if (filter)
175 UpdateClientAnimationStateInternal(TargetProperty::FILTER);
176 }
177
178 void ElementAnimations::AddAnimation(std::unique_ptr<Animation> animation) {
179 // TODO(loyso): Erase this. Rewrite element_animations_unittest to use
180 // AnimationPlayer::AddAnimation.
181
182 // Add animation to the first player.
183 DCHECK(players_list_->might_have_observers());
184 ElementAnimations::PlayersList::Iterator it(players_list_.get());
185 AnimationPlayer* player = it.GetNext();
186 DCHECK(player);
187 player->AddAnimation(std::move(animation));
171 } 188 }
172 189
173 void ElementAnimations::Animate(base::TimeTicks monotonic_time) { 190 void ElementAnimations::Animate(base::TimeTicks monotonic_time) {
174 DCHECK(!monotonic_time.is_null()); 191 DCHECK(!monotonic_time.is_null());
175 if (!has_element_in_active_list() && !has_element_in_pending_list()) 192 if (!has_element_in_active_list() && !has_element_in_pending_list())
176 return; 193 return;
177 194
178 if (needs_to_start_animations_) 195 {
179 StartAnimations(monotonic_time); 196 // TODO(crbug.com/634916): Shouldn't manually iterate through the list if
180 TickAnimations(monotonic_time); 197 // base::ObserverList has a callback mechanism.
198 ElementAnimations::PlayersList::Iterator it(players_list_.get());
199 AnimationPlayer* player;
200 while ((player = it.GetNext()) != nullptr) {
201 if (player->needs_to_start_animations())
202 player->StartAnimations(monotonic_time);
203 }
204 }
205 {
206 ElementAnimations::PlayersList::Iterator it(players_list_.get());
207 AnimationPlayer* player;
208 while ((player = it.GetNext()) != nullptr)
209 player->TickAnimations(monotonic_time);
210 }
181 last_tick_time_ = monotonic_time; 211 last_tick_time_ = monotonic_time;
182 UpdateClientAnimationState(TargetProperty::OPACITY); 212
183 UpdateClientAnimationState(TargetProperty::TRANSFORM); 213 UpdateClientAnimationStateInternal(TargetProperty::OPACITY);
184 UpdateClientAnimationState(TargetProperty::FILTER); 214 UpdateClientAnimationStateInternal(TargetProperty::TRANSFORM);
215 UpdateClientAnimationStateInternal(TargetProperty::FILTER);
185 } 216 }
186 217
187 void ElementAnimations::UpdateState(bool start_ready_animations, 218 void ElementAnimations::UpdateState(bool start_ready_animations,
188 AnimationEvents* events) { 219 AnimationEvents* events) {
189 if (!has_element_in_active_list()) 220 if (!has_element_in_active_list())
190 return; 221 return;
191 222
192 // Animate hasn't been called, this happens if an element has been added 223 // Animate hasn't been called, this happens if an element has been added
193 // between the Commit and Draw phases. 224 // between the Commit and Draw phases.
194 if (last_tick_time_ == base::TimeTicks()) 225 if (last_tick_time_ == base::TimeTicks())
195 return; 226 return;
196 227
197 if (start_ready_animations) 228 if (start_ready_animations) {
198 PromoteStartedAnimations(last_tick_time_, events); 229 ElementAnimations::PlayersList::Iterator it(players_list_.get());
199 230 AnimationPlayer* player;
200 MarkFinishedAnimations(last_tick_time_); 231 while ((player = it.GetNext()) != nullptr)
201 MarkAnimationsForDeletion(last_tick_time_, events); 232 player->PromoteStartedAnimations(last_tick_time_, events);
202
203 if (needs_to_start_animations_ && start_ready_animations) {
204 StartAnimations(last_tick_time_);
205 PromoteStartedAnimations(last_tick_time_, events);
206 } 233 }
207 234
208 UpdateActivation(NORMAL_ACTIVATION); 235 {
236 ElementAnimations::PlayersList::Iterator it(players_list_.get());
237 AnimationPlayer* player;
238 while ((player = it.GetNext()) != nullptr)
239 player->MarkFinishedAnimations(last_tick_time_);
240 }
241 {
242 ElementAnimations::PlayersList::Iterator it(players_list_.get());
243 AnimationPlayer* player;
244 while ((player = it.GetNext()) != nullptr)
245 player->MarkAnimationsForDeletion(last_tick_time_, events);
246 }
247
248 if (start_ready_animations) {
249 ElementAnimations::PlayersList::Iterator it(players_list_.get());
250 AnimationPlayer* player;
251 while ((player = it.GetNext()) != nullptr) {
252 if (player->needs_to_start_animations()) {
253 player->StartAnimations(last_tick_time_);
254 player->PromoteStartedAnimations(last_tick_time_, events);
255 }
256 }
257 }
258
259 UpdateActivation(ActivationType::NORMAL);
209 } 260 }
210 261
211 void ElementAnimations::ActivateAnimations() { 262 void ElementAnimations::ActivateAnimations() {
212 bool changed_transform_animation = false; 263 bool changed_transform_animation = false;
213 bool changed_opacity_animation = false; 264 bool changed_opacity_animation = false;
214 bool changed_filter_animation = false; 265 bool changed_filter_animation = false;
215 for (size_t i = 0; i < animations_.size(); ++i) { 266
216 if (animations_[i]->affects_active_elements() != 267 ElementAnimations::PlayersList::Iterator it(players_list_.get());
217 animations_[i]->affects_pending_elements()) { 268 AnimationPlayer* player;
218 if (animations_[i]->target_property() == TargetProperty::TRANSFORM) 269 while ((player = it.GetNext()) != nullptr) {
219 changed_transform_animation = true; 270 player->ActivateAnimations(&changed_transform_animation,
220 else if (animations_[i]->target_property() == TargetProperty::OPACITY) 271 &changed_opacity_animation,
221 changed_opacity_animation = true; 272 &changed_filter_animation);
222 else if (animations_[i]->target_property() == TargetProperty::FILTER)
223 changed_filter_animation = true;
224 }
225 animations_[i]->set_affects_active_elements(
226 animations_[i]->affects_pending_elements());
227 } 273 }
228 auto affects_no_elements = [](const std::unique_ptr<Animation>& animation) { 274
229 return !animation->affects_active_elements() &&
230 !animation->affects_pending_elements();
231 };
232 animations_.erase(std::remove_if(animations_.begin(), animations_.end(),
233 affects_no_elements),
234 animations_.end());
235 scroll_offset_animation_was_interrupted_ = false; 275 scroll_offset_animation_was_interrupted_ = false;
236 UpdateActivation(NORMAL_ACTIVATION); 276 UpdateActivation(ActivationType::NORMAL);
237 if (changed_transform_animation) 277 UpdateClientAnimationState(changed_transform_animation,
238 UpdateClientAnimationState(TargetProperty::TRANSFORM); 278 changed_opacity_animation,
239 if (changed_opacity_animation) 279 changed_filter_animation);
240 UpdateClientAnimationState(TargetProperty::OPACITY);
241 if (changed_filter_animation)
242 UpdateClientAnimationState(TargetProperty::FILTER);
243 } 280 }
244 281
245 void ElementAnimations::NotifyAnimationStarted(const AnimationEvent& event) { 282 void ElementAnimations::NotifyAnimationStarted(const AnimationEvent& event) {
246 if (event.is_impl_only) { 283 DCHECK(!event.is_impl_only);
247 NotifyPlayersAnimationStarted(event.monotonic_time, event.target_property, 284 ElementAnimations::PlayersList::Iterator it(players_list_.get());
248 event.group_id); 285 AnimationPlayer* player;
249 return; 286 while ((player = it.GetNext()) != nullptr) {
250 } 287 if (player->NotifyAnimationStarted(event))
251 288 break;
252 for (size_t i = 0; i < animations_.size(); ++i) {
253 if (animations_[i]->group() == event.group_id &&
254 animations_[i]->target_property() == event.target_property &&
255 animations_[i]->needs_synchronized_start_time()) {
256 animations_[i]->set_needs_synchronized_start_time(false);
257 if (!animations_[i]->has_set_start_time())
258 animations_[i]->set_start_time(event.monotonic_time);
259
260 NotifyPlayersAnimationStarted(event.monotonic_time, event.target_property,
261 event.group_id);
262
263 return;
264 }
265 } 289 }
266 } 290 }
267 291
268 void ElementAnimations::NotifyAnimationFinished(const AnimationEvent& event) { 292 void ElementAnimations::NotifyAnimationFinished(const AnimationEvent& event) {
269 if (event.is_impl_only) { 293 DCHECK(!event.is_impl_only);
270 NotifyPlayersAnimationFinished(event.monotonic_time, event.target_property, 294 ElementAnimations::PlayersList::Iterator it(players_list_.get());
271 event.group_id); 295 AnimationPlayer* player;
272 return; 296 while ((player = it.GetNext()) != nullptr) {
273 } 297 if (player->NotifyAnimationFinished(event))
274 298 break;
275 for (size_t i = 0; i < animations_.size(); ++i) {
276 if (animations_[i]->group() == event.group_id &&
277 animations_[i]->target_property() == event.target_property) {
278 animations_[i]->set_received_finished_event(true);
279 NotifyPlayersAnimationFinished(event.monotonic_time,
280 event.target_property, event.group_id);
281
282 return;
283 }
284 } 299 }
285 } 300 }
286 301
287 void ElementAnimations::NotifyAnimationTakeover(const AnimationEvent& event) { 302 void ElementAnimations::NotifyAnimationTakeover(const AnimationEvent& event) {
303 DCHECK(!event.is_impl_only);
288 DCHECK(event.target_property == TargetProperty::SCROLL_OFFSET); 304 DCHECK(event.target_property == TargetProperty::SCROLL_OFFSET);
289 if (!IsEmpty()) { 305
290 std::unique_ptr<AnimationCurve> animation_curve = event.curve->Clone(); 306 ElementAnimations::PlayersList::Iterator it(players_list_.get());
291 NotifyPlayersAnimationTakeover(event.monotonic_time, event.target_property, 307 AnimationPlayer* player;
292 event.animation_start_time, 308 while ((player = it.GetNext()) != nullptr)
293 std::move(animation_curve)); 309 player->NotifyAnimationTakeover(event);
294 }
295 } 310 }
296 311
297 void ElementAnimations::NotifyAnimationAborted(const AnimationEvent& event) { 312 void ElementAnimations::NotifyAnimationAborted(const AnimationEvent& event) {
298 for (size_t i = 0; i < animations_.size(); ++i) { 313 DCHECK(!event.is_impl_only);
299 if (animations_[i]->group() == event.group_id && 314
300 animations_[i]->target_property() == event.target_property) { 315 ElementAnimations::PlayersList::Iterator it(players_list_.get());
301 animations_[i]->SetRunState(Animation::ABORTED, event.monotonic_time); 316 AnimationPlayer* player;
302 animations_[i]->set_received_finished_event(true); 317 while ((player = it.GetNext()) != nullptr) {
303 NotifyPlayersAnimationAborted(event.monotonic_time, event.target_property, 318 if (player->NotifyAnimationAborted(event))
304 event.group_id);
305 break;
306 }
307 }
308 switch (event.target_property) {
309 case TargetProperty::TRANSFORM:
310 case TargetProperty::OPACITY:
311 case TargetProperty::FILTER:
312 UpdateClientAnimationState(event.target_property);
313 break;
314 default:
315 break; 319 break;
316 } 320 }
321
322 UpdateClientAnimationState(event.target_property);
317 } 323 }
318 324
319 void ElementAnimations::NotifyAnimationPropertyUpdate( 325 void ElementAnimations::NotifyAnimationPropertyUpdate(
320 const AnimationEvent& event) { 326 const AnimationEvent& event) {
327 DCHECK(!event.is_impl_only);
321 bool notify_active_elements = true; 328 bool notify_active_elements = true;
322 bool notify_pending_elements = true; 329 bool notify_pending_elements = true;
323 switch (event.target_property) { 330 switch (event.target_property) {
324 case TargetProperty::OPACITY: 331 case TargetProperty::OPACITY:
325 NotifyClientOpacityAnimated(event.opacity, notify_active_elements, 332 NotifyClientOpacityAnimated(event.opacity, notify_active_elements,
326 notify_pending_elements); 333 notify_pending_elements);
327 break; 334 break;
328 case TargetProperty::TRANSFORM: 335 case TargetProperty::TRANSFORM:
329 NotifyClientTransformAnimated(event.transform, notify_active_elements, 336 NotifyClientTransformAnimated(event.transform, notify_active_elements,
330 notify_pending_elements); 337 notify_pending_elements);
331 break; 338 break;
332 default: 339 default:
333 NOTREACHED(); 340 NOTREACHED();
334 } 341 }
335 } 342 }
336 343
337 bool ElementAnimations::HasFilterAnimationThatInflatesBounds() const { 344 bool ElementAnimations::HasFilterAnimationThatInflatesBounds() const {
338 for (size_t i = 0; i < animations_.size(); ++i) { 345 ElementAnimations::PlayersList::Iterator it(players_list_.get());
339 if (!animations_[i]->is_finished() && 346 AnimationPlayer* player;
340 animations_[i]->target_property() == TargetProperty::FILTER && 347 while ((player = it.GetNext()) != nullptr) {
341 animations_[i] 348 if (player->HasFilterAnimationThatInflatesBounds())
342 ->curve()
343 ->ToFilterAnimationCurve()
344 ->HasFilterThatMovesPixels())
345 return true; 349 return true;
346 } 350 }
347
348 return false; 351 return false;
349 } 352 }
350 353
351 bool ElementAnimations::HasTransformAnimationThatInflatesBounds() const { 354 bool ElementAnimations::HasTransformAnimationThatInflatesBounds() const {
352 return IsCurrentlyAnimatingProperty(TargetProperty::TRANSFORM, 355 ElementAnimations::PlayersList::Iterator it(players_list_.get());
353 ElementListType::ACTIVE) || 356 AnimationPlayer* player;
354 IsCurrentlyAnimatingProperty(TargetProperty::TRANSFORM, 357 while ((player = it.GetNext()) != nullptr) {
355 ElementListType::PENDING); 358 if (player->HasTransformAnimationThatInflatesBounds())
359 return true;
360 }
361 return false;
356 } 362 }
357 363
358 bool ElementAnimations::FilterAnimationBoundsForBox(const gfx::BoxF& box, 364 bool ElementAnimations::FilterAnimationBoundsForBox(const gfx::BoxF& box,
359 gfx::BoxF* bounds) const { 365 gfx::BoxF* bounds) const {
360 // TODO(avallee): Implement. 366 // TODO(avallee): Implement.
361 return false; 367 return false;
362 } 368 }
363 369
364 bool ElementAnimations::TransformAnimationBoundsForBox( 370 bool ElementAnimations::TransformAnimationBoundsForBox(
365 const gfx::BoxF& box, 371 const gfx::BoxF& box,
366 gfx::BoxF* bounds) const { 372 gfx::BoxF* bounds) const {
367 DCHECK(HasTransformAnimationThatInflatesBounds()) 373 *bounds = gfx::BoxF();
368 << "TransformAnimationBoundsForBox will give incorrect results if there "
369 << "are no transform animations affecting bounds, non-animated transform "
370 << "is not known";
371 374
372 // Compute bounds based on animations for which is_finished() is false. 375 ElementAnimations::PlayersList::Iterator it(players_list_.get());
373 // Do nothing if there are no such animations; in this case, it is assumed 376 AnimationPlayer* player;
374 // that callers will take care of computing bounds based on the owning layer's 377 while ((player = it.GetNext()) != nullptr) {
375 // actual transform. 378 gfx::BoxF player_bounds;
376 *bounds = gfx::BoxF(); 379 bool success = player->TransformAnimationBoundsForBox(box, &player_bounds);
377 for (size_t i = 0; i < animations_.size(); ++i) {
378 if (animations_[i]->is_finished() ||
379 animations_[i]->target_property() != TargetProperty::TRANSFORM)
380 continue;
381
382 const TransformAnimationCurve* transform_animation_curve =
383 animations_[i]->curve()->ToTransformAnimationCurve();
384 gfx::BoxF animation_bounds;
385 bool success =
386 transform_animation_curve->AnimatedBoundsForBox(box, &animation_bounds);
387 if (!success) 380 if (!success)
388 return false; 381 return false;
389 bounds->Union(animation_bounds); 382 bounds->Union(player_bounds);
390 } 383 }
391
392 return true; 384 return true;
393 } 385 }
394 386
395 bool ElementAnimations::HasAnimationThatAffectsScale() const { 387 bool ElementAnimations::HasAnimationThatAffectsScale() const {
396 for (size_t i = 0; i < animations_.size(); ++i) { 388 ElementAnimations::PlayersList::Iterator it(players_list_.get());
397 if (animations_[i]->is_finished() || 389 AnimationPlayer* player;
398 animations_[i]->target_property() != TargetProperty::TRANSFORM) 390 while ((player = it.GetNext()) != nullptr) {
399 continue; 391 if (player->HasAnimationThatAffectsScale())
400
401 const TransformAnimationCurve* transform_animation_curve =
402 animations_[i]->curve()->ToTransformAnimationCurve();
403 if (transform_animation_curve->AffectsScale())
404 return true; 392 return true;
405 } 393 }
406
407 return false; 394 return false;
408 } 395 }
409 396
410 bool ElementAnimations::HasOnlyTranslationTransforms( 397 bool ElementAnimations::HasOnlyTranslationTransforms(
411 ElementListType list_type) const { 398 ElementListType list_type) const {
412 for (size_t i = 0; i < animations_.size(); ++i) { 399 ElementAnimations::PlayersList::Iterator it(players_list_.get());
413 if (animations_[i]->is_finished() || 400 AnimationPlayer* player;
414 animations_[i]->target_property() != TargetProperty::TRANSFORM) 401 while ((player = it.GetNext()) != nullptr) {
415 continue; 402 if (!player->HasOnlyTranslationTransforms(list_type))
416
417 if ((list_type == ElementListType::ACTIVE &&
418 !animations_[i]->affects_active_elements()) ||
419 (list_type == ElementListType::PENDING &&
420 !animations_[i]->affects_pending_elements()))
421 continue;
422
423 const TransformAnimationCurve* transform_animation_curve =
424 animations_[i]->curve()->ToTransformAnimationCurve();
425 if (!transform_animation_curve->IsTranslation())
426 return false; 403 return false;
427 } 404 }
428
429 return true; 405 return true;
430 } 406 }
431 407
432 bool ElementAnimations::AnimationsPreserveAxisAlignment() const { 408 bool ElementAnimations::AnimationsPreserveAxisAlignment() const {
433 for (size_t i = 0; i < animations_.size(); ++i) { 409 ElementAnimations::PlayersList::Iterator it(players_list_.get());
434 if (animations_[i]->is_finished() || 410 AnimationPlayer* player;
435 animations_[i]->target_property() != TargetProperty::TRANSFORM) 411 while ((player = it.GetNext()) != nullptr) {
436 continue; 412 if (!player->AnimationsPreserveAxisAlignment())
437
438 const TransformAnimationCurve* transform_animation_curve =
439 animations_[i]->curve()->ToTransformAnimationCurve();
440 if (!transform_animation_curve->PreservesAxisAlignment())
441 return false; 413 return false;
442 } 414 }
443
444 return true; 415 return true;
445 } 416 }
446 417
447 bool ElementAnimations::AnimationStartScale(ElementListType list_type, 418 bool ElementAnimations::AnimationStartScale(ElementListType list_type,
448 float* start_scale) const { 419 float* start_scale) const {
449 *start_scale = 0.f; 420 *start_scale = 0.f;
450 for (size_t i = 0; i < animations_.size(); ++i) {
451 if (animations_[i]->is_finished() ||
452 animations_[i]->target_property() != TargetProperty::TRANSFORM)
453 continue;
454 421
455 if ((list_type == ElementListType::ACTIVE && 422 ElementAnimations::PlayersList::Iterator it(players_list_.get());
456 !animations_[i]->affects_active_elements()) || 423 AnimationPlayer* player;
457 (list_type == ElementListType::PENDING && 424 while ((player = it.GetNext()) != nullptr) {
458 !animations_[i]->affects_pending_elements())) 425 float player_start_scale = 0.f;
459 continue; 426 bool success = player->AnimationStartScale(list_type, &player_start_scale);
427 if (!success)
428 return false;
429 // Union: a maximum.
430 *start_scale = std::max(*start_scale, player_start_scale);
431 }
460 432
461 bool forward_direction = true;
462 switch (animations_[i]->direction()) {
463 case Animation::Direction::NORMAL:
464 case Animation::Direction::ALTERNATE_NORMAL:
465 forward_direction = animations_[i]->playback_rate() >= 0.0;
466 break;
467 case Animation::Direction::REVERSE:
468 case Animation::Direction::ALTERNATE_REVERSE:
469 forward_direction = animations_[i]->playback_rate() < 0.0;
470 break;
471 }
472
473 const TransformAnimationCurve* transform_animation_curve =
474 animations_[i]->curve()->ToTransformAnimationCurve();
475 float animation_start_scale = 0.f;
476 if (!transform_animation_curve->AnimationStartScale(forward_direction,
477 &animation_start_scale))
478 return false;
479 *start_scale = std::max(*start_scale, animation_start_scale);
480 }
481 return true; 433 return true;
482 } 434 }
483 435
484 bool ElementAnimations::MaximumTargetScale(ElementListType list_type, 436 bool ElementAnimations::MaximumTargetScale(ElementListType list_type,
485 float* max_scale) const { 437 float* max_scale) const {
486 *max_scale = 0.f; 438 *max_scale = 0.f;
487 for (size_t i = 0; i < animations_.size(); ++i) {
488 if (animations_[i]->is_finished() ||
489 animations_[i]->target_property() != TargetProperty::TRANSFORM)
490 continue;
491 439
492 if ((list_type == ElementListType::ACTIVE && 440 ElementAnimations::PlayersList::Iterator it(players_list_.get());
493 !animations_[i]->affects_active_elements()) || 441 AnimationPlayer* player;
494 (list_type == ElementListType::PENDING && 442 while ((player = it.GetNext()) != nullptr) {
495 !animations_[i]->affects_pending_elements())) 443 float player_max_scale = 0.f;
496 continue; 444 bool success = player->MaximumTargetScale(list_type, &player_max_scale);
497 445 if (!success)
498 bool forward_direction = true;
499 switch (animations_[i]->direction()) {
500 case Animation::Direction::NORMAL:
501 case Animation::Direction::ALTERNATE_NORMAL:
502 forward_direction = animations_[i]->playback_rate() >= 0.0;
503 break;
504 case Animation::Direction::REVERSE:
505 case Animation::Direction::ALTERNATE_REVERSE:
506 forward_direction = animations_[i]->playback_rate() < 0.0;
507 break;
508 }
509
510 const TransformAnimationCurve* transform_animation_curve =
511 animations_[i]->curve()->ToTransformAnimationCurve();
512 float animation_scale = 0.f;
513 if (!transform_animation_curve->MaximumTargetScale(forward_direction,
514 &animation_scale))
515 return false; 446 return false;
516 *max_scale = std::max(*max_scale, animation_scale); 447 // Union: a maximum.
448 *max_scale = std::max(*max_scale, player_max_scale);
517 } 449 }
518 450
519 return true; 451 return true;
520 } 452 }
521 453
522 void ElementAnimations::PushNewAnimationsToImplThread( 454 void ElementAnimations::SetNeedsUpdateImplClientState(bool transform,
523 ElementAnimations* element_animations_impl) const { 455 bool opacity,
524 // Any new animations owned by the main thread's ElementAnimations are cloned 456 bool filter) {
525 // and added to the impl thread's ElementAnimations. 457 if (transform)
526 for (size_t i = 0; i < animations_.size(); ++i) { 458 needs_update_impl_client_state_transform_ = true;
527 // If the animation is already running on the impl thread, there is no 459 if (opacity)
528 // need to copy it over. 460 needs_update_impl_client_state_opacity_ = true;
529 if (element_animations_impl->GetAnimationById(animations_[i]->id())) 461 if (filter)
530 continue; 462 needs_update_impl_client_state_filter_ = true;
531 463
532 if (animations_[i]->target_property() == TargetProperty::SCROLL_OFFSET && 464 if (needs_update_impl_client_state_transform_ ||
533 !animations_[i] 465 needs_update_impl_client_state_opacity_ ||
534 ->curve() 466 needs_update_impl_client_state_filter_)
535 ->ToScrollOffsetAnimationCurve() 467 SetNeedsPushProperties();
536 ->HasSetInitialValue()) {
537 gfx::ScrollOffset current_scroll_offset;
538 if (element_animations_impl->has_element_in_active_list()) {
539 current_scroll_offset =
540 element_animations_impl->ScrollOffsetForAnimation();
541 } else {
542 // The owning layer isn't yet in the active tree, so the main thread
543 // scroll offset will be up to date.
544 current_scroll_offset = ScrollOffsetForAnimation();
545 }
546 animations_[i]->curve()->ToScrollOffsetAnimationCurve()->SetInitialValue(
547 current_scroll_offset);
548 }
549
550 // The new animation should be set to run as soon as possible.
551 Animation::RunState initial_run_state =
552 Animation::WAITING_FOR_TARGET_AVAILABILITY;
553 std::unique_ptr<Animation> to_add(
554 animations_[i]->CloneAndInitialize(initial_run_state));
555 DCHECK(!to_add->needs_synchronized_start_time());
556 to_add->set_affects_active_elements(false);
557 element_animations_impl->AddAnimation(std::move(to_add));
558 }
559 } 468 }
560 469
561 static bool IsCompleted( 470 void ElementAnimations::ClearNeedsUpdateImplClientState() {
562 Animation* animation, 471 needs_update_impl_client_state_transform_ = false;
563 const ElementAnimations* main_thread_element_animations) { 472 needs_update_impl_client_state_opacity_ = false;
564 if (animation->is_impl_only()) { 473 needs_update_impl_client_state_filter_ = false;
565 return (animation->run_state() == Animation::WAITING_FOR_DELETION);
566 } else {
567 return !main_thread_element_animations->GetAnimationById(animation->id());
568 }
569 } 474 }
570 475
571 void ElementAnimations::RemoveAnimationsCompletedOnMainThread( 476 void ElementAnimations::UpdateActivation(ActivationType type) {
572 ElementAnimations* element_animations_impl) const { 477 bool force = type == ActivationType::FORCE;
573 bool removed_transform_animation = false;
574 bool removed_opacity_animation = false;
575 bool removed_filter_animation = false;
576 // Animations removed on the main thread should no longer affect pending
577 // elements, and should stop affecting active elements after the next call
578 // to ActivateAnimations. If already WAITING_FOR_DELETION, they can be removed
579 // immediately.
580 auto& animations = element_animations_impl->animations_;
581 for (const auto& animation : animations) {
582 if (IsCompleted(animation.get(), this)) {
583 animation->set_affects_pending_elements(false);
584 if (animation->target_property() == TargetProperty::TRANSFORM)
585 removed_transform_animation = true;
586 else if (animation->target_property() == TargetProperty::OPACITY)
587 removed_opacity_animation = true;
588 else if (animation->target_property() == TargetProperty::FILTER)
589 removed_filter_animation = true;
590 }
591 }
592 auto affects_active_only_and_is_waiting_for_deletion =
593 [](const std::unique_ptr<Animation>& animation) {
594 return animation->run_state() == Animation::WAITING_FOR_DELETION &&
595 !animation->affects_pending_elements();
596 };
597 animations.erase(
598 std::remove_if(animations.begin(), animations.end(),
599 affects_active_only_and_is_waiting_for_deletion),
600 animations.end());
601
602 if (removed_transform_animation) {
603 element_animations_impl->UpdateClientAnimationState(
604 TargetProperty::TRANSFORM);
605 }
606 if (removed_opacity_animation) {
607 element_animations_impl->UpdateClientAnimationState(
608 TargetProperty::OPACITY);
609 }
610 if (removed_filter_animation) {
611 element_animations_impl->UpdateClientAnimationState(TargetProperty::FILTER);
612 }
613 }
614
615 void ElementAnimations::PushPropertiesToImplThread(
616 ElementAnimations* element_animations_impl) {
617 for (size_t i = 0; i < animations_.size(); ++i) {
618 Animation* current_impl =
619 element_animations_impl->GetAnimationById(animations_[i]->id());
620 if (current_impl)
621 animations_[i]->PushPropertiesTo(current_impl);
622 }
623 element_animations_impl->scroll_offset_animation_was_interrupted_ =
624 scroll_offset_animation_was_interrupted_;
625 scroll_offset_animation_was_interrupted_ = false;
626 }
627
628 void ElementAnimations::StartAnimations(base::TimeTicks monotonic_time) {
629 DCHECK(needs_to_start_animations_);
630 needs_to_start_animations_ = false;
631 // First collect running properties affecting each type of element.
632 TargetProperties blocked_properties_for_active_elements;
633 TargetProperties blocked_properties_for_pending_elements;
634 std::vector<size_t> animations_waiting_for_target;
635
636 animations_waiting_for_target.reserve(animations_.size());
637 for (size_t i = 0; i < animations_.size(); ++i) {
638 if (animations_[i]->run_state() == Animation::STARTING ||
639 animations_[i]->run_state() == Animation::RUNNING) {
640 if (animations_[i]->affects_active_elements()) {
641 blocked_properties_for_active_elements[animations_[i]
642 ->target_property()] = true;
643 }
644 if (animations_[i]->affects_pending_elements()) {
645 blocked_properties_for_pending_elements[animations_[i]
646 ->target_property()] = true;
647 }
648 } else if (animations_[i]->run_state() ==
649 Animation::WAITING_FOR_TARGET_AVAILABILITY) {
650 animations_waiting_for_target.push_back(i);
651 }
652 }
653
654 for (size_t i = 0; i < animations_waiting_for_target.size(); ++i) {
655 // Collect all properties for animations with the same group id (they
656 // should all also be in the list of animations).
657 size_t animation_index = animations_waiting_for_target[i];
658 Animation* animation_waiting_for_target =
659 animations_[animation_index].get();
660 // Check for the run state again even though the animation was waiting
661 // for target because it might have changed the run state while handling
662 // previous animation in this loop (if they belong to same group).
663 if (animation_waiting_for_target->run_state() ==
664 Animation::WAITING_FOR_TARGET_AVAILABILITY) {
665 TargetProperties enqueued_properties;
666 bool affects_active_elements =
667 animation_waiting_for_target->affects_active_elements();
668 bool affects_pending_elements =
669 animation_waiting_for_target->affects_pending_elements();
670 enqueued_properties[animation_waiting_for_target->target_property()] =
671 true;
672 for (size_t j = animation_index + 1; j < animations_.size(); ++j) {
673 if (animation_waiting_for_target->group() == animations_[j]->group()) {
674 enqueued_properties[animations_[j]->target_property()] = true;
675 affects_active_elements |= animations_[j]->affects_active_elements();
676 affects_pending_elements |=
677 animations_[j]->affects_pending_elements();
678 }
679 }
680
681 // Check to see if intersection of the list of properties affected by
682 // the group and the list of currently blocked properties is null, taking
683 // into account the type(s) of elements affected by the group. In any
684 // case, the group's target properties need to be added to the lists of
685 // blocked properties.
686 bool null_intersection = true;
687 static_assert(TargetProperty::FIRST_TARGET_PROPERTY == 0,
688 "TargetProperty must be 0-based enum");
689 for (int property = TargetProperty::FIRST_TARGET_PROPERTY;
690 property <= TargetProperty::LAST_TARGET_PROPERTY; ++property) {
691 if (enqueued_properties[property]) {
692 if (affects_active_elements) {
693 if (blocked_properties_for_active_elements[property])
694 null_intersection = false;
695 else
696 blocked_properties_for_active_elements[property] = true;
697 }
698 if (affects_pending_elements) {
699 if (blocked_properties_for_pending_elements[property])
700 null_intersection = false;
701 else
702 blocked_properties_for_pending_elements[property] = true;
703 }
704 }
705 }
706
707 // If the intersection is null, then we are free to start the animations
708 // in the group.
709 if (null_intersection) {
710 animation_waiting_for_target->SetRunState(Animation::STARTING,
711 monotonic_time);
712 for (size_t j = animation_index + 1; j < animations_.size(); ++j) {
713 if (animation_waiting_for_target->group() ==
714 animations_[j]->group()) {
715 animations_[j]->SetRunState(Animation::STARTING, monotonic_time);
716 }
717 }
718 } else {
719 needs_to_start_animations_ = true;
720 }
721 }
722 }
723 }
724
725 void ElementAnimations::PromoteStartedAnimations(base::TimeTicks monotonic_time,
726 AnimationEvents* events) {
727 for (size_t i = 0; i < animations_.size(); ++i) {
728 if (animations_[i]->run_state() == Animation::STARTING &&
729 animations_[i]->affects_active_elements()) {
730 animations_[i]->SetRunState(Animation::RUNNING, monotonic_time);
731 if (!animations_[i]->has_set_start_time() &&
732 !animations_[i]->needs_synchronized_start_time())
733 animations_[i]->set_start_time(monotonic_time);
734 if (events) {
735 base::TimeTicks start_time;
736 if (animations_[i]->has_set_start_time())
737 start_time = animations_[i]->start_time();
738 else
739 start_time = monotonic_time;
740 AnimationEvent started_event(
741 AnimationEvent::STARTED, element_id_, animations_[i]->group(),
742 animations_[i]->target_property(), start_time);
743 started_event.is_impl_only = animations_[i]->is_impl_only();
744 if (started_event.is_impl_only)
745 NotifyAnimationStarted(started_event);
746 else
747 events->events_.push_back(started_event);
748 }
749 }
750 }
751 }
752
753 void ElementAnimations::MarkFinishedAnimations(base::TimeTicks monotonic_time) {
754 bool finished_transform_animation = false;
755 bool finished_opacity_animation = false;
756 bool finished_filter_animation = false;
757 for (size_t i = 0; i < animations_.size(); ++i) {
758 if (!animations_[i]->is_finished() &&
759 animations_[i]->IsFinishedAt(monotonic_time)) {
760 animations_[i]->SetRunState(Animation::FINISHED, monotonic_time);
761 if (animations_[i]->target_property() == TargetProperty::TRANSFORM)
762 finished_transform_animation = true;
763 else if (animations_[i]->target_property() == TargetProperty::OPACITY)
764 finished_opacity_animation = true;
765 else if (animations_[i]->target_property() == TargetProperty::FILTER)
766 finished_filter_animation = true;
767 }
768 }
769 if (finished_transform_animation)
770 UpdateClientAnimationState(TargetProperty::TRANSFORM);
771 if (finished_opacity_animation)
772 UpdateClientAnimationState(TargetProperty::OPACITY);
773 if (finished_filter_animation)
774 UpdateClientAnimationState(TargetProperty::FILTER);
775 }
776
777 void ElementAnimations::MarkAnimationsForDeletion(
778 base::TimeTicks monotonic_time,
779 AnimationEvents* events) {
780 bool marked_animations_for_deletions = false;
781 std::vector<size_t> animations_with_same_group_id;
782
783 animations_with_same_group_id.reserve(animations_.size());
784 // Non-aborted animations are marked for deletion after a corresponding
785 // AnimationEvent::FINISHED event is sent or received. This means that if
786 // we don't have an events vector, we must ensure that non-aborted animations
787 // have received a finished event before marking them for deletion.
788 for (size_t i = 0; i < animations_.size(); i++) {
789 int group_id = animations_[i]->group();
790 if (animations_[i]->run_state() == Animation::ABORTED) {
791 if (events && !animations_[i]->is_impl_only()) {
792 AnimationEvent aborted_event(
793 AnimationEvent::ABORTED, element_id_, group_id,
794 animations_[i]->target_property(), monotonic_time);
795 events->events_.push_back(aborted_event);
796 }
797 // If on the compositor or on the main thread and received finish event,
798 // animation can be marked for deletion.
799 if (events || animations_[i]->received_finished_event()) {
800 animations_[i]->SetRunState(Animation::WAITING_FOR_DELETION,
801 monotonic_time);
802 marked_animations_for_deletions = true;
803 }
804 continue;
805 }
806
807 // If running on the compositor and need to complete an aborted animation
808 // on the main thread.
809 if (events &&
810 animations_[i]->run_state() ==
811 Animation::ABORTED_BUT_NEEDS_COMPLETION) {
812 AnimationEvent aborted_event(AnimationEvent::TAKEOVER, element_id_,
813 group_id, animations_[i]->target_property(),
814 monotonic_time);
815 aborted_event.animation_start_time =
816 (animations_[i]->start_time() - base::TimeTicks()).InSecondsF();
817 const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
818 animations_[i]->curve()->ToScrollOffsetAnimationCurve();
819 aborted_event.curve = scroll_offset_animation_curve->Clone();
820 // Notify the compositor that the animation is finished.
821 NotifyPlayersAnimationFinished(aborted_event.monotonic_time,
822 aborted_event.target_property,
823 aborted_event.group_id);
824 // Notify main thread.
825 events->events_.push_back(aborted_event);
826
827 // Remove the animation from the compositor.
828 animations_[i]->SetRunState(Animation::WAITING_FOR_DELETION,
829 monotonic_time);
830 marked_animations_for_deletions = true;
831 continue;
832 }
833
834 bool all_anims_with_same_id_are_finished = false;
835
836 // Since deleting an animation on the main thread leads to its deletion
837 // on the impl thread, we only mark a FINISHED main thread animation for
838 // deletion once it has received a FINISHED event from the impl thread.
839 bool animation_i_will_send_or_has_received_finish_event =
840 animations_[i]->is_controlling_instance() ||
841 animations_[i]->is_impl_only() ||
842 animations_[i]->received_finished_event();
843 // If an animation is finished, and not already marked for deletion,
844 // find out if all other animations in the same group are also finished.
845 if (animations_[i]->run_state() == Animation::FINISHED &&
846 animation_i_will_send_or_has_received_finish_event) {
847 // Clear the animations_with_same_group_id if it was added for
848 // the previous animation's iteration.
849 if (animations_with_same_group_id.size() > 0)
850 animations_with_same_group_id.clear();
851 all_anims_with_same_id_are_finished = true;
852 for (size_t j = 0; j < animations_.size(); ++j) {
853 bool animation_j_will_send_or_has_received_finish_event =
854 animations_[j]->is_controlling_instance() ||
855 animations_[j]->is_impl_only() ||
856 animations_[j]->received_finished_event();
857 if (group_id == animations_[j]->group()) {
858 if (!animations_[j]->is_finished() ||
859 (animations_[j]->run_state() == Animation::FINISHED &&
860 !animation_j_will_send_or_has_received_finish_event)) {
861 all_anims_with_same_id_are_finished = false;
862 break;
863 } else if (j >= i &&
864 animations_[j]->run_state() != Animation::ABORTED) {
865 // Mark down the animations which belong to the same group
866 // and is not yet aborted. If this current iteration finds that all
867 // animations with same ID are finished, then the marked
868 // animations below will be set to WAITING_FOR_DELETION in next
869 // iteration.
870 animations_with_same_group_id.push_back(j);
871 }
872 }
873 }
874 }
875 if (all_anims_with_same_id_are_finished) {
876 // We now need to remove all animations with the same group id as
877 // group_id (and send along animation finished notifications, if
878 // necessary).
879 for (size_t j = 0; j < animations_with_same_group_id.size(); j++) {
880 size_t animation_index = animations_with_same_group_id[j];
881 if (events) {
882 AnimationEvent finished_event(
883 AnimationEvent::FINISHED, element_id_,
884 animations_[animation_index]->group(),
885 animations_[animation_index]->target_property(), monotonic_time);
886 finished_event.is_impl_only =
887 animations_[animation_index]->is_impl_only();
888 if (finished_event.is_impl_only)
889 NotifyAnimationFinished(finished_event);
890 else
891 events->events_.push_back(finished_event);
892 }
893 animations_[animation_index]->SetRunState(
894 Animation::WAITING_FOR_DELETION, monotonic_time);
895 }
896 marked_animations_for_deletions = true;
897 }
898 }
899 if (marked_animations_for_deletions)
900 NotifyPlayersAnimationWaitingForDeletion();
901 }
902
903 void ElementAnimations::MarkAbortedAnimationsForDeletion(
904 ElementAnimations* element_animations_impl) const {
905 bool aborted_transform_animation = false;
906 bool aborted_opacity_animation = false;
907 bool aborted_filter_animation = false;
908 auto& animations_impl = element_animations_impl->animations_;
909 for (const auto& animation_impl : animations_impl) {
910 // If the animation has been aborted on the main thread, mark it for
911 // deletion.
912 if (Animation* animation = GetAnimationById(animation_impl->id())) {
913 if (animation->run_state() == Animation::ABORTED) {
914 animation_impl->SetRunState(Animation::WAITING_FOR_DELETION,
915 element_animations_impl->last_tick_time_);
916 animation->SetRunState(Animation::WAITING_FOR_DELETION,
917 last_tick_time_);
918 if (animation_impl->target_property() == TargetProperty::TRANSFORM)
919 aborted_transform_animation = true;
920 else if (animation_impl->target_property() == TargetProperty::OPACITY)
921 aborted_opacity_animation = true;
922 else if (animation_impl->target_property() == TargetProperty::FILTER)
923 aborted_filter_animation = true;
924 }
925 }
926 }
927
928 if (aborted_transform_animation) {
929 element_animations_impl->UpdateClientAnimationState(
930 TargetProperty::TRANSFORM);
931 }
932 if (aborted_opacity_animation) {
933 element_animations_impl->UpdateClientAnimationState(
934 TargetProperty::OPACITY);
935 }
936 if (aborted_filter_animation) {
937 element_animations_impl->UpdateClientAnimationState(TargetProperty::FILTER);
938 }
939 }
940
941 void ElementAnimations::PurgeAnimationsMarkedForDeletion() {
942 animations_.erase(
943 std::remove_if(animations_.begin(), animations_.end(),
944 [](const std::unique_ptr<Animation>& animation) {
945 return animation->run_state() ==
946 Animation::WAITING_FOR_DELETION;
947 }),
948 animations_.end());
949 }
950
951 void ElementAnimations::TickAnimations(base::TimeTicks monotonic_time) {
952 for (size_t i = 0; i < animations_.size(); ++i) {
953 if (animations_[i]->run_state() == Animation::STARTING ||
954 animations_[i]->run_state() == Animation::RUNNING ||
955 animations_[i]->run_state() == Animation::PAUSED) {
956 if (!animations_[i]->InEffect(monotonic_time))
957 continue;
958
959 base::TimeDelta trimmed =
960 animations_[i]->TrimTimeToCurrentIteration(monotonic_time);
961
962 switch (animations_[i]->target_property()) {
963 case TargetProperty::TRANSFORM: {
964 const TransformAnimationCurve* transform_animation_curve =
965 animations_[i]->curve()->ToTransformAnimationCurve();
966 const gfx::Transform transform =
967 transform_animation_curve->GetValue(trimmed);
968 NotifyClientTransformAnimated(
969 transform, animations_[i]->affects_active_elements(),
970 animations_[i]->affects_pending_elements());
971 break;
972 }
973
974 case TargetProperty::OPACITY: {
975 const FloatAnimationCurve* float_animation_curve =
976 animations_[i]->curve()->ToFloatAnimationCurve();
977 const float opacity = std::max(
978 std::min(float_animation_curve->GetValue(trimmed), 1.0f), 0.f);
979 NotifyClientOpacityAnimated(
980 opacity, animations_[i]->affects_active_elements(),
981 animations_[i]->affects_pending_elements());
982 break;
983 }
984
985 case TargetProperty::FILTER: {
986 const FilterAnimationCurve* filter_animation_curve =
987 animations_[i]->curve()->ToFilterAnimationCurve();
988 const FilterOperations filter =
989 filter_animation_curve->GetValue(trimmed);
990 NotifyClientFilterAnimated(
991 filter, animations_[i]->affects_active_elements(),
992 animations_[i]->affects_pending_elements());
993 break;
994 }
995
996 case TargetProperty::BACKGROUND_COLOR: {
997 // Not yet implemented.
998 break;
999 }
1000
1001 case TargetProperty::SCROLL_OFFSET: {
1002 const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
1003 animations_[i]->curve()->ToScrollOffsetAnimationCurve();
1004 const gfx::ScrollOffset scroll_offset =
1005 scroll_offset_animation_curve->GetValue(trimmed);
1006 NotifyClientScrollOffsetAnimated(
1007 scroll_offset, animations_[i]->affects_active_elements(),
1008 animations_[i]->affects_pending_elements());
1009 break;
1010 }
1011 }
1012 }
1013 }
1014 }
1015
1016 void ElementAnimations::UpdateActivation(UpdateActivationType type) {
1017 bool force = type == FORCE_ACTIVATION;
1018 if (animation_host_) { 478 if (animation_host_) {
1019 bool was_active = is_active_; 479 bool was_active = is_active_;
1020 is_active_ = false; 480 is_active_ = false;
1021 for (size_t i = 0; i < animations_.size(); ++i) { 481
1022 if (animations_[i]->run_state() != Animation::WAITING_FOR_DELETION) { 482 ElementAnimations::PlayersList::Iterator it(players_list_.get());
483 AnimationPlayer* player;
484 while ((player = it.GetNext()) != nullptr) {
485 if (player->HasNonDeletedAnimation()) {
1023 is_active_ = true; 486 is_active_ = true;
1024 break; 487 break;
1025 } 488 }
1026 } 489 }
1027 490
1028 if (is_active_ && (!was_active || force)) { 491 if (is_active_ && (!was_active || force)) {
1029 animation_host_->DidActivateElementAnimations(this); 492 animation_host_->DidActivateElementAnimations(this);
1030 } else if (!is_active_ && (was_active || force)) { 493 } else if (!is_active_ && (was_active || force)) {
1031 // Resetting last_tick_time_ here ensures that calling ::UpdateState 494 // Resetting last_tick_time_ here ensures that calling ::UpdateState
1032 // before ::Animate doesn't start an animation. 495 // before ::Animate doesn't start an animation.
1033 last_tick_time_ = base::TimeTicks(); 496 last_tick_time_ = base::TimeTicks();
1034 animation_host_->DidDeactivateElementAnimations(this); 497 animation_host_->DidDeactivateElementAnimations(this);
1035 } 498 }
1036 } 499 }
1037 } 500 }
1038 501
502 void ElementAnimations::UpdateActivationNormal() {
503 UpdateActivation(ActivationType::NORMAL);
504 }
505
1039 void ElementAnimations::NotifyClientOpacityAnimated( 506 void ElementAnimations::NotifyClientOpacityAnimated(
1040 float opacity, 507 float opacity,
1041 bool notify_active_elements, 508 bool notify_active_elements,
1042 bool notify_pending_elements) { 509 bool notify_pending_elements) {
1043 if (notify_active_elements && has_element_in_active_list()) 510 if (notify_active_elements && has_element_in_active_list())
1044 OnOpacityAnimated(ElementListType::ACTIVE, opacity); 511 OnOpacityAnimated(ElementListType::ACTIVE, opacity);
1045 if (notify_pending_elements && has_element_in_pending_list()) 512 if (notify_pending_elements && has_element_in_pending_list())
1046 OnOpacityAnimated(ElementListType::PENDING, opacity); 513 OnOpacityAnimated(ElementListType::PENDING, opacity);
1047 } 514 }
1048 515
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1119 potentially_animating); 586 potentially_animating);
1120 } else if (notify_elements_about_running_animation) { 587 } else if (notify_elements_about_running_animation) {
1121 bool currently_animating = 588 bool currently_animating =
1122 active ? animation_state->currently_running_for_active_elements 589 active ? animation_state->currently_running_for_active_elements
1123 : animation_state->currently_running_for_pending_elements; 590 : animation_state->currently_running_for_pending_elements;
1124 IsAnimatingChanged(list_type, property, AnimationChangeType::RUNNING, 591 IsAnimatingChanged(list_type, property, AnimationChangeType::RUNNING,
1125 currently_animating); 592 currently_animating);
1126 } 593 }
1127 } 594 }
1128 595
1129 void ElementAnimations::UpdateClientAnimationState( 596 void ElementAnimations::UpdateClientAnimationStateInternal(
1130 TargetProperty::Type property) { 597 TargetProperty::Type property) {
1131 struct PropertyAnimationState* animation_state = nullptr; 598 struct PropertyAnimationState* animation_state = nullptr;
1132 switch (property) { 599 switch (property) {
1133 case TargetProperty::OPACITY: 600 case TargetProperty::OPACITY:
1134 animation_state = &opacity_animation_state_; 601 animation_state = &opacity_animation_state_;
1135 break; 602 break;
1136 case TargetProperty::TRANSFORM: 603 case TargetProperty::TRANSFORM:
1137 animation_state = &transform_animation_state_; 604 animation_state = &transform_animation_state_;
1138 break; 605 break;
1139 case TargetProperty::FILTER: 606 case TargetProperty::FILTER:
(...skipping 11 matching lines...) Expand all
1151 animation_state->potentially_animating_for_active_elements; 618 animation_state->potentially_animating_for_active_elements;
1152 bool was_potentially_animating_for_pending_elements = 619 bool was_potentially_animating_for_pending_elements =
1153 animation_state->potentially_animating_for_pending_elements; 620 animation_state->potentially_animating_for_pending_elements;
1154 621
1155 animation_state->Clear(); 622 animation_state->Clear();
1156 DCHECK(was_potentially_animating_for_active_elements || 623 DCHECK(was_potentially_animating_for_active_elements ||
1157 !was_currently_running_animation_for_active_elements); 624 !was_currently_running_animation_for_active_elements);
1158 DCHECK(was_potentially_animating_for_pending_elements || 625 DCHECK(was_potentially_animating_for_pending_elements ||
1159 !was_currently_running_animation_for_pending_elements); 626 !was_currently_running_animation_for_pending_elements);
1160 627
1161 for (const auto& animation : animations_) { 628 ElementAnimations::PlayersList::Iterator it(players_list_.get());
1162 if (!animation->is_finished() && animation->target_property() == property) { 629 AnimationPlayer* player;
1163 animation_state->potentially_animating_for_active_elements |= 630 while ((player = it.GetNext()) != nullptr) {
1164 animation->affects_active_elements(); 631 for (const auto& animation : player->animations()) {
1165 animation_state->potentially_animating_for_pending_elements |= 632 if (!animation->is_finished() &&
1166 animation->affects_pending_elements(); 633 animation->target_property() == property) {
1167 animation_state->currently_running_for_active_elements = 634 animation_state->potentially_animating_for_active_elements |=
1168 animation_state->potentially_animating_for_active_elements && 635 animation->affects_active_elements();
1169 animation->InEffect(last_tick_time_); 636 animation_state->potentially_animating_for_pending_elements |=
1170 animation_state->currently_running_for_pending_elements = 637 animation->affects_pending_elements();
1171 animation_state->potentially_animating_for_pending_elements && 638 animation_state->currently_running_for_active_elements =
1172 animation->InEffect(last_tick_time_); 639 animation_state->potentially_animating_for_active_elements &&
640 animation->InEffect(last_tick_time_);
641 animation_state->currently_running_for_pending_elements =
642 animation_state->potentially_animating_for_pending_elements &&
643 animation->InEffect(last_tick_time_);
644 }
1173 } 645 }
1174 } 646 }
1175 647
1176 bool potentially_animating_changed_for_active_elements = 648 bool potentially_animating_changed_for_active_elements =
1177 was_potentially_animating_for_active_elements != 649 was_potentially_animating_for_active_elements !=
1178 animation_state->potentially_animating_for_active_elements; 650 animation_state->potentially_animating_for_active_elements;
1179 bool potentially_animating_changed_for_pending_elements = 651 bool potentially_animating_changed_for_pending_elements =
1180 was_potentially_animating_for_pending_elements != 652 was_potentially_animating_for_pending_elements !=
1181 animation_state->potentially_animating_for_pending_elements; 653 animation_state->potentially_animating_for_pending_elements;
1182 bool currently_running_animation_changed_for_active_elements = 654 bool currently_running_animation_changed_for_active_elements =
(...skipping 13 matching lines...) Expand all
1196 potentially_animating_changed_for_active_elements, 668 potentially_animating_changed_for_active_elements,
1197 currently_running_animation_changed_for_active_elements); 669 currently_running_animation_changed_for_active_elements);
1198 if (has_element_in_pending_list()) 670 if (has_element_in_pending_list())
1199 NotifyClientAnimationChanged( 671 NotifyClientAnimationChanged(
1200 property, ElementListType::PENDING, 672 property, ElementListType::PENDING,
1201 potentially_animating_changed_for_pending_elements, 673 potentially_animating_changed_for_pending_elements,
1202 currently_running_animation_changed_for_pending_elements); 674 currently_running_animation_changed_for_pending_elements);
1203 } 675 }
1204 676
1205 bool ElementAnimations::HasActiveAnimation() const { 677 bool ElementAnimations::HasActiveAnimation() const {
1206 for (size_t i = 0; i < animations_.size(); ++i) { 678 ElementAnimations::PlayersList::Iterator it(players_list_.get());
1207 if (!animations_[i]->is_finished()) 679 AnimationPlayer* player;
680 while ((player = it.GetNext()) != nullptr) {
681 if (player->HasActiveAnimation())
1208 return true; 682 return true;
1209 } 683 }
684
1210 return false; 685 return false;
1211 } 686 }
1212 687
1213 bool ElementAnimations::HasAnyAnimation() const { 688 bool ElementAnimations::HasAnyAnimation() const {
1214 return !animations_.empty(); 689 ElementAnimations::PlayersList::Iterator it(players_list_.get());
690 AnimationPlayer* player;
691 while ((player = it.GetNext()) != nullptr) {
692 if (player->has_any_animation())
693 return true;
694 }
695
696 return false;
1215 } 697 }
1216 698
1217 bool ElementAnimations::IsPotentiallyAnimatingProperty( 699 bool ElementAnimations::IsPotentiallyAnimatingProperty(
1218 TargetProperty::Type target_property, 700 TargetProperty::Type target_property,
1219 ElementListType list_type) const { 701 ElementListType list_type) const {
1220 for (size_t i = 0; i < animations_.size(); ++i) { 702 ElementAnimations::PlayersList::Iterator it(players_list_.get());
1221 if (!animations_[i]->is_finished() && 703 AnimationPlayer* player;
1222 animations_[i]->target_property() == target_property) { 704 while ((player = it.GetNext()) != nullptr) {
1223 if ((list_type == ElementListType::ACTIVE && 705 if (player->IsPotentiallyAnimatingProperty(target_property, list_type))
1224 animations_[i]->affects_active_elements()) || 706 return true;
1225 (list_type == ElementListType::PENDING &&
1226 animations_[i]->affects_pending_elements()))
1227 return true;
1228 }
1229 } 707 }
708
1230 return false; 709 return false;
1231 } 710 }
1232 711
1233 bool ElementAnimations::IsCurrentlyAnimatingProperty( 712 bool ElementAnimations::IsCurrentlyAnimatingProperty(
1234 TargetProperty::Type target_property, 713 TargetProperty::Type target_property,
1235 ElementListType list_type) const { 714 ElementListType list_type) const {
1236 for (size_t i = 0; i < animations_.size(); ++i) { 715 ElementAnimations::PlayersList::Iterator it(players_list_.get());
1237 if (!animations_[i]->is_finished() && 716 AnimationPlayer* player;
1238 animations_[i]->InEffect(last_tick_time_) && 717 while ((player = it.GetNext()) != nullptr) {
1239 animations_[i]->target_property() == target_property) { 718 if (player->IsCurrentlyAnimatingProperty(target_property, list_type))
1240 if ((list_type == ElementListType::ACTIVE && 719 return true;
1241 animations_[i]->affects_active_elements()) ||
1242 (list_type == ElementListType::PENDING &&
1243 animations_[i]->affects_pending_elements()))
1244 return true;
1245 }
1246 } 720 }
721
722 return false;
723 }
724
725 void ElementAnimations::SetScrollOffsetAnimationWasInterrupted() {
726 scroll_offset_animation_was_interrupted_ = true;
727 }
728
729 bool ElementAnimations::needs_to_start_animations_for_testing() const {
730 ElementAnimations::PlayersList::Iterator it(players_list_.get());
731 AnimationPlayer* player;
732 while ((player = it.GetNext()) != nullptr) {
733 if (player->needs_to_start_animations())
734 return true;
735 }
736
1247 return false; 737 return false;
1248 } 738 }
1249 739
1250 void ElementAnimations::PauseAnimation(int animation_id, 740 void ElementAnimations::PauseAnimation(int animation_id,
1251 base::TimeDelta time_offset) { 741 base::TimeDelta time_offset) {
1252 for (size_t i = 0; i < animations_.size(); ++i) { 742 ElementAnimations::PlayersList::Iterator it(players_list_.get());
1253 if (animations_[i]->id() == animation_id) { 743 AnimationPlayer* player;
1254 animations_[i]->SetRunState(Animation::PAUSED, 744 while ((player = it.GetNext()) != nullptr)
1255 time_offset + animations_[i]->start_time() + 745 player->PauseAnimation(animation_id, time_offset.InSecondsF());
1256 animations_[i]->time_offset());
1257 }
1258 }
1259 SetNeedsPushProperties();
1260 } 746 }
1261 747
1262 void ElementAnimations::RemoveAnimation(int animation_id) { 748 void ElementAnimations::RemoveAnimation(int animation_id) {
1263 bool removed_transform_animation = false; 749 ElementAnimations::PlayersList::Iterator it(players_list_.get());
1264 bool removed_opacity_animation = false; 750 AnimationPlayer* player;
1265 bool removed_filter_animation = false; 751 while ((player = it.GetNext()) != nullptr)
1266 // Since we want to use the animations that we're going to remove, we need to 752 player->RemoveAnimation(animation_id);
1267 // use a stable_parition here instead of remove_if. Remove_if leaves the
1268 // removed items in an unspecified state.
1269 auto animations_to_remove = std::stable_partition(
1270 animations_.begin(), animations_.end(),
1271 [animation_id](const std::unique_ptr<Animation>& animation) {
1272 return animation->id() != animation_id;
1273 });
1274 for (auto it = animations_to_remove; it != animations_.end(); ++it) {
1275 if ((*it)->target_property() == TargetProperty::SCROLL_OFFSET) {
1276 scroll_offset_animation_was_interrupted_ = true;
1277 } else if ((*it)->target_property() == TargetProperty::TRANSFORM &&
1278 !(*it)->is_finished()) {
1279 removed_transform_animation = true;
1280 } else if ((*it)->target_property() == TargetProperty::OPACITY &&
1281 !(*it)->is_finished()) {
1282 removed_opacity_animation = true;
1283 } else if ((*it)->target_property() == TargetProperty::FILTER &&
1284 !(*it)->is_finished()) {
1285 removed_filter_animation = true;
1286 }
1287 }
1288
1289 animations_.erase(animations_to_remove, animations_.end());
1290 UpdateActivation(NORMAL_ACTIVATION);
1291 if (removed_transform_animation)
1292 UpdateClientAnimationState(TargetProperty::TRANSFORM);
1293 if (removed_opacity_animation)
1294 UpdateClientAnimationState(TargetProperty::OPACITY);
1295 if (removed_filter_animation)
1296 UpdateClientAnimationState(TargetProperty::FILTER);
1297
1298 SetNeedsPushProperties();
1299 } 753 }
1300 754
1301 void ElementAnimations::AbortAnimation(int animation_id) { 755 void ElementAnimations::AbortAnimation(int animation_id) {
1302 if (Animation* animation = GetAnimationById(animation_id)) { 756 ElementAnimations::PlayersList::Iterator it(players_list_.get());
1303 if (!animation->is_finished()) { 757 AnimationPlayer* player;
1304 animation->SetRunState(Animation::ABORTED, last_tick_time_); 758 while ((player = it.GetNext()) != nullptr)
1305 switch (animation->target_property()) { 759 player->AbortAnimation(animation_id);
1306 case TargetProperty::TRANSFORM:
1307 case TargetProperty::OPACITY:
1308 case TargetProperty::FILTER:
1309 UpdateClientAnimationState(animation->target_property());
1310 break;
1311 default:
1312 break;
1313 }
1314 }
1315 }
1316
1317 SetNeedsPushProperties();
1318 } 760 }
1319 761
1320 void ElementAnimations::AbortAnimations(TargetProperty::Type target_property, 762 void ElementAnimations::AbortAnimations(TargetProperty::Type target_property,
1321 bool needs_completion) { 763 bool needs_completion) {
1322 if (needs_completion) 764 ElementAnimations::PlayersList::Iterator it(players_list_.get());
1323 DCHECK(target_property == TargetProperty::SCROLL_OFFSET); 765 AnimationPlayer* player;
1324 766 while ((player = it.GetNext()) != nullptr)
1325 bool aborted_animation = false; 767 player->AbortAnimations(target_property, needs_completion);
1326 for (size_t i = 0; i < animations_.size(); ++i) {
1327 if (animations_[i]->target_property() == target_property &&
1328 !animations_[i]->is_finished()) {
1329 // Currently only impl-only scroll offset animations can be completed on
1330 // the main thread.
1331 if (needs_completion && animations_[i]->is_impl_only()) {
1332 animations_[i]->SetRunState(Animation::ABORTED_BUT_NEEDS_COMPLETION,
1333 last_tick_time_);
1334 } else {
1335 animations_[i]->SetRunState(Animation::ABORTED, last_tick_time_);
1336 }
1337 aborted_animation = true;
1338 }
1339 }
1340 if (aborted_animation) {
1341 switch (target_property) {
1342 case TargetProperty::TRANSFORM:
1343 case TargetProperty::OPACITY:
1344 case TargetProperty::FILTER:
1345 UpdateClientAnimationState(target_property);
1346 break;
1347 default:
1348 break;
1349 }
1350 }
1351
1352 SetNeedsPushProperties();
1353 } 768 }
1354 769
1355 Animation* ElementAnimations::GetAnimation( 770 Animation* ElementAnimations::GetAnimation(
1356 TargetProperty::Type target_property) const { 771 TargetProperty::Type target_property) const {
1357 for (size_t i = 0; i < animations_.size(); ++i) { 772 ElementAnimations::PlayersList::Iterator it(players_list_.get());
1358 size_t index = animations_.size() - i - 1; 773 AnimationPlayer* player;
1359 if (animations_[index]->target_property() == target_property) 774 while ((player = it.GetNext()) != nullptr) {
1360 return animations_[index].get(); 775 if (Animation* animation = player->GetAnimation(target_property))
776 return animation;
1361 } 777 }
1362 return nullptr; 778 return nullptr;
1363 } 779 }
1364 780
1365 Animation* ElementAnimations::GetAnimationById(int animation_id) const { 781 Animation* ElementAnimations::GetAnimationById(int animation_id) const {
1366 for (size_t i = 0; i < animations_.size(); ++i) 782 ElementAnimations::PlayersList::Iterator it(players_list_.get());
1367 if (animations_[i]->id() == animation_id) 783 AnimationPlayer* player;
1368 return animations_[i].get(); 784 while ((player = it.GetNext()) != nullptr) {
785 if (Animation* animation = player->GetAnimationById(animation_id))
786 return animation;
787 }
1369 return nullptr; 788 return nullptr;
1370 } 789 }
1371 790
1372 void ElementAnimations::OnFilterAnimated(ElementListType list_type, 791 void ElementAnimations::OnFilterAnimated(ElementListType list_type,
1373 const FilterOperations& filters) { 792 const FilterOperations& filters) {
1374 DCHECK(element_id()); 793 DCHECK(element_id());
1375 DCHECK(animation_host()); 794 DCHECK(animation_host());
1376 DCHECK(animation_host()->mutator_host_client()); 795 DCHECK(animation_host()->mutator_host_client());
1377 animation_host()->mutator_host_client()->SetElementFilterMutated( 796 animation_host()->mutator_host_client()->SetElementFilterMutated(
1378 element_id(), list_type, filters); 797 element_id(), list_type, filters);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1433 ->ElementFilterIsAnimatingChanged(element_id(), list_type, 852 ->ElementFilterIsAnimatingChanged(element_id(), list_type,
1434 change_type, is_animating); 853 change_type, is_animating);
1435 break; 854 break;
1436 default: 855 default:
1437 NOTREACHED(); 856 NOTREACHED();
1438 break; 857 break;
1439 } 858 }
1440 } 859 }
1441 } 860 }
1442 861
1443 void ElementAnimations::NotifyPlayersAnimationStarted(
1444 base::TimeTicks monotonic_time,
1445 TargetProperty::Type target_property,
1446 int group) {
1447 ElementAnimations::PlayersList::Iterator it(players_list_.get());
1448 AnimationPlayer* player;
1449 // TODO(crbug.com/634916): Shouldn't manually iterate through the list if
1450 // base::ObserverList has a callback mechanism.
1451 while ((player = it.GetNext()) != nullptr)
1452 player->NotifyAnimationStarted(monotonic_time, target_property, group);
1453 }
1454
1455 void ElementAnimations::NotifyPlayersAnimationFinished(
1456 base::TimeTicks monotonic_time,
1457 TargetProperty::Type target_property,
1458 int group) {
1459 ElementAnimations::PlayersList::Iterator it(players_list_.get());
1460 AnimationPlayer* player;
1461 while ((player = it.GetNext()) != nullptr)
1462 player->NotifyAnimationFinished(monotonic_time, target_property, group);
1463 }
1464
1465 void ElementAnimations::NotifyPlayersAnimationAborted(
1466 base::TimeTicks monotonic_time,
1467 TargetProperty::Type target_property,
1468 int group) {
1469 ElementAnimations::PlayersList::Iterator it(players_list_.get());
1470 AnimationPlayer* player;
1471 while ((player = it.GetNext()) != nullptr)
1472 player->NotifyAnimationAborted(monotonic_time, target_property, group);
1473 }
1474
1475 void ElementAnimations::NotifyPlayersAnimationWaitingForDeletion() {
1476 ElementAnimations::PlayersList::Iterator it(players_list_.get());
1477 AnimationPlayer* player;
1478 while ((player = it.GetNext()) != nullptr)
1479 player->NotifyAnimationWaitingForDeletion();
1480 }
1481
1482 void ElementAnimations::NotifyPlayersAnimationTakeover(
1483 base::TimeTicks monotonic_time,
1484 TargetProperty::Type target_property,
1485 double animation_start_time,
1486 std::unique_ptr<AnimationCurve> curve) {
1487 DCHECK(curve);
1488 ElementAnimations::PlayersList::Iterator it(players_list_.get());
1489 AnimationPlayer* player;
1490 while ((player = it.GetNext()) != nullptr) {
1491 std::unique_ptr<AnimationCurve> animation_curve = curve->Clone();
1492 player->NotifyAnimationTakeover(monotonic_time, target_property,
1493 animation_start_time,
1494 std::move(animation_curve));
1495 }
1496 }
1497
1498 gfx::ScrollOffset ElementAnimations::ScrollOffsetForAnimation() const { 862 gfx::ScrollOffset ElementAnimations::ScrollOffsetForAnimation() const {
1499 if (animation_host()) { 863 if (animation_host()) {
1500 DCHECK(animation_host()->mutator_host_client()); 864 DCHECK(animation_host()->mutator_host_client());
1501 return animation_host()->mutator_host_client()->GetScrollOffsetForAnimation( 865 return animation_host()->mutator_host_client()->GetScrollOffsetForAnimation(
1502 element_id()); 866 element_id());
1503 } 867 }
1504 868
1505 return gfx::ScrollOffset(); 869 return gfx::ScrollOffset();
1506 } 870 }
1507 871
1508 } // namespace cc 872 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698