1 // Copyright 2012 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 "cc/animation/layer_animation_controller.h"
6
7 #include <algorithm>
8
9 #include "cc/animation/animation.h"
10 #include "cc/animation/animation_delegate.h"
11 #include "cc/animation/animation_registrar.h"
12 #include "cc/animation/keyframed_animation_curve.h"
13 #include "cc/animation/layer_animation_value_observer.h"
14 #include "cc/animation/layer_animation_value_provider.h"
15 #include "cc/animation/scroll_offset_animation_curve.h"
16 #include "cc/base/scoped_ptr_algorithm.h"
17 #include "cc/output/filter_operations.h"
18 #include "ui/gfx/box_f.h"
19 #include "ui/gfx/transform.h"
20
21 namespace cc {
22
LayerAnimationController(int id)23 LayerAnimationController::LayerAnimationController(int id)
24 : registrar_(0),
25 id_(id),
26 is_active_(false),
27 last_tick_time_(0),
28 value_provider_(NULL),
29 layer_animation_delegate_(NULL) {}
30
~LayerAnimationController()31 LayerAnimationController::~LayerAnimationController() {
32 if (registrar_)
33 registrar_->UnregisterAnimationController(this);
34 }
35
Create(int id)36 scoped_refptr<LayerAnimationController> LayerAnimationController::Create(
37 int id) {
38 return make_scoped_refptr(new LayerAnimationController(id));
39 }
40
PauseAnimation(int animation_id,double time_offset)41 void LayerAnimationController::PauseAnimation(int animation_id,
42 double time_offset) {
43 for (size_t i = 0; i < active_animations_.size(); ++i) {
44 if (active_animations_[i]->id() == animation_id) {
45 active_animations_[i]->SetRunState(
46 Animation::Paused, time_offset + active_animations_[i]->start_time());
47 }
48 }
49 }
50
51 struct HasAnimationId {
HasAnimationIdcc::HasAnimationId52 explicit HasAnimationId(int id) : id_(id) {}
operator ()cc::HasAnimationId53 bool operator()(Animation* animation) const {
54 return animation->id() == id_;
55 }
56
57 private:
58 int id_;
59 };
60
RemoveAnimation(int animation_id)61 void LayerAnimationController::RemoveAnimation(int animation_id) {
62 ScopedPtrVector<Animation>& animations = active_animations_;
63 animations.erase(cc::remove_if(&animations,
64 animations.begin(),
65 animations.end(),
66 HasAnimationId(animation_id)),
67 animations.end());
68 UpdateActivation(NormalActivation);
69 }
70
71 struct HasAnimationIdAndProperty {
HasAnimationIdAndPropertycc::HasAnimationIdAndProperty72 HasAnimationIdAndProperty(int id, Animation::TargetProperty target_property)
73 : id_(id), target_property_(target_property) {}
operator ()cc::HasAnimationIdAndProperty74 bool operator()(Animation* animation) const {
75 return animation->id() == id_ &&
76 animation->target_property() == target_property_;
77 }
78
79 private:
80 int id_;
81 Animation::TargetProperty target_property_;
82 };
83
RemoveAnimation(int animation_id,Animation::TargetProperty target_property)84 void LayerAnimationController::RemoveAnimation(
85 int animation_id,
86 Animation::TargetProperty target_property) {
87 ScopedPtrVector<Animation>& animations = active_animations_;
88 animations.erase(
89 cc::remove_if(&animations,
90 animations.begin(),
91 animations.end(),
92 HasAnimationIdAndProperty(animation_id, target_property)),
93 animations.end());
94 UpdateActivation(NormalActivation);
95 }
96
AbortAnimations(Animation::TargetProperty target_property)97 void LayerAnimationController::AbortAnimations(
98 Animation::TargetProperty target_property) {
99 for (size_t i = 0; i < active_animations_.size(); ++i) {
100 if (active_animations_[i]->target_property() == target_property &&
101 !active_animations_[i]->is_finished())
102 active_animations_[i]->SetRunState(Animation::Aborted, last_tick_time_);
103 }
104 }
105
106 // Ensures that the list of active animations on the main thread and the impl
107 // thread are kept in sync.
PushAnimationUpdatesTo(LayerAnimationController * controller_impl)108 void LayerAnimationController::PushAnimationUpdatesTo(
109 LayerAnimationController* controller_impl) {
110 DCHECK(this != controller_impl);
111 if (!has_any_animation() && !controller_impl->has_any_animation())
112 return;
113 PurgeAnimationsMarkedForDeletion();
114 PushNewAnimationsToImplThread(controller_impl);
115
116 // Remove finished impl side animations only after pushing,
117 // and only after the animations are deleted on the main thread
118 // this insures we will never push an animation twice.
119 RemoveAnimationsCompletedOnMainThread(controller_impl);
120
121 PushPropertiesToImplThread(controller_impl);
122 controller_impl->UpdateActivation(NormalActivation);
123 UpdateActivation(NormalActivation);
124 }
125
Animate(double monotonic_time)126 void LayerAnimationController::Animate(double monotonic_time) {
127 DCHECK(monotonic_time);
128 if (!HasValueObserver())
129 return;
130
131 StartAnimations(monotonic_time);
132 TickAnimations(monotonic_time);
133 last_tick_time_ = monotonic_time;
134 }
135
AccumulatePropertyUpdates(double monotonic_time,AnimationEventsVector * events)136 void LayerAnimationController::AccumulatePropertyUpdates(
137 double monotonic_time,
138 AnimationEventsVector* events) {
139 if (!events)
140 return;
141
142 for (size_t i = 0; i < active_animations_.size(); ++i) {
143 Animation* animation = active_animations_[i];
144 if (!animation->is_impl_only())
145 continue;
146
147 double trimmed = animation->TrimTimeToCurrentIteration(monotonic_time);
148 switch (animation->target_property()) {
149 case Animation::Opacity: {
150 AnimationEvent event(AnimationEvent::PropertyUpdate,
151 id_,
152 animation->group(),
153 Animation::Opacity,
154 monotonic_time);
155 event.opacity = animation->curve()->ToFloatAnimationCurve()->GetValue(
156 trimmed);
157 event.is_impl_only = true;
158 events->push_back(event);
159 break;
160 }
161
162 case Animation::Transform: {
163 AnimationEvent event(AnimationEvent::PropertyUpdate,
164 id_,
165 animation->group(),
166 Animation::Transform,
167 monotonic_time);
168 event.transform =
169 animation->curve()->ToTransformAnimationCurve()->GetValue(trimmed);
170 event.is_impl_only = true;
171 events->push_back(event);
172 break;
173 }
174
175 case Animation::Filter: {
176 AnimationEvent event(AnimationEvent::PropertyUpdate,
177 id_,
178 animation->group(),
179 Animation::Filter,
180 monotonic_time);
181 event.filters = animation->curve()->ToFilterAnimationCurve()->GetValue(
182 trimmed);
183 event.is_impl_only = true;
184 events->push_back(event);
185 break;
186 }
187
188 case Animation::BackgroundColor: { break; }
189
190 case Animation::ScrollOffset: {
191 // Impl-side changes to scroll offset are already sent back to the
192 // main thread (e.g. for user-driven scrolling), so a PropertyUpdate
193 // isn't needed.
194 break;
195 }
196
197 case Animation::TargetPropertyEnumSize:
198 NOTREACHED();
199 }
200 }
201 }
202
UpdateState(bool start_ready_animations,AnimationEventsVector * events)203 void LayerAnimationController::UpdateState(bool start_ready_animations,
204 AnimationEventsVector* events) {
205 if (!HasActiveValueObserver())
206 return;
207
208 if (start_ready_animations)
209 PromoteStartedAnimations(last_tick_time_, events);
210
211 MarkFinishedAnimations(last_tick_time_);
212 MarkAnimationsForDeletion(last_tick_time_, events);
213
214 if (start_ready_animations) {
215 StartAnimations(last_tick_time_);
216 PromoteStartedAnimations(last_tick_time_, events);
217 }
218
219 AccumulatePropertyUpdates(last_tick_time_, events);
220
221 UpdateActivation(NormalActivation);
222 }
223
AddAnimation(scoped_ptr<Animation> animation)224 void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) {
225 active_animations_.push_back(animation.Pass());
226 UpdateActivation(NormalActivation);
227 }
228
GetAnimation(int group_id,Animation::TargetProperty target_property) const229 Animation* LayerAnimationController::GetAnimation(
230 int group_id,
231 Animation::TargetProperty target_property) const {
232 for (size_t i = 0; i < active_animations_.size(); ++i)
233 if (active_animations_[i]->group() == group_id &&
234 active_animations_[i]->target_property() == target_property)
235 return active_animations_[i];
236 return 0;
237 }
238
GetAnimation(Animation::TargetProperty target_property) const239 Animation* LayerAnimationController::GetAnimation(
240 Animation::TargetProperty target_property) const {
241 for (size_t i = 0; i < active_animations_.size(); ++i) {
242 size_t index = active_animations_.size() - i - 1;
243 if (active_animations_[index]->target_property() == target_property)
244 return active_animations_[index];
245 }
246 return 0;
247 }
248
HasActiveAnimation() const249 bool LayerAnimationController::HasActiveAnimation() const {
250 for (size_t i = 0; i < active_animations_.size(); ++i) {
251 if (!active_animations_[i]->is_finished())
252 return true;
253 }
254 return false;
255 }
256
IsAnimatingProperty(Animation::TargetProperty target_property) const257 bool LayerAnimationController::IsAnimatingProperty(
258 Animation::TargetProperty target_property) const {
259 for (size_t i = 0; i < active_animations_.size(); ++i) {
260 if (!active_animations_[i]->is_finished() &&
261 active_animations_[i]->target_property() == target_property)
262 return true;
263 }
264 return false;
265 }
266
SetAnimationRegistrar(AnimationRegistrar * registrar)267 void LayerAnimationController::SetAnimationRegistrar(
268 AnimationRegistrar* registrar) {
269 if (registrar_ == registrar)
270 return;
271
272 if (registrar_)
273 registrar_->UnregisterAnimationController(this);
274
275 registrar_ = registrar;
276 if (registrar_)
277 registrar_->RegisterAnimationController(this);
278
279 UpdateActivation(ForceActivation);
280 }
281
NotifyAnimationStarted(const AnimationEvent & event,double wall_clock_time)282 void LayerAnimationController::NotifyAnimationStarted(
283 const AnimationEvent& event,
284 double wall_clock_time) {
285 base::TimeTicks monotonic_time = base::TimeTicks::FromInternalValue(
286 event.monotonic_time * base::Time::kMicrosecondsPerSecond);
287 if (event.is_impl_only) {
288 FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
289 OnAnimationStarted(event));
290 if (layer_animation_delegate_)
291 layer_animation_delegate_->NotifyAnimationStarted(
292 wall_clock_time, monotonic_time, event.target_property);
293
294 return;
295 }
296
297 for (size_t i = 0; i < active_animations_.size(); ++i) {
298 if (active_animations_[i]->group() == event.group_id &&
299 active_animations_[i]->target_property() == event.target_property &&
300 active_animations_[i]->needs_synchronized_start_time()) {
301 active_animations_[i]->set_needs_synchronized_start_time(false);
302 active_animations_[i]->set_start_time(event.monotonic_time);
303
304 FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
305 OnAnimationStarted(event));
306 if (layer_animation_delegate_)
307 layer_animation_delegate_->NotifyAnimationStarted(
308 wall_clock_time, monotonic_time, event.target_property);
309
310 return;
311 }
312 }
313 }
314
NotifyAnimationFinished(const AnimationEvent & event,double wall_clock_time)315 void LayerAnimationController::NotifyAnimationFinished(
316 const AnimationEvent& event,
317 double wall_clock_time) {
318 base::TimeTicks monotonic_time = base::TimeTicks::FromInternalValue(
319 event.monotonic_time * base::Time::kMicrosecondsPerSecond);
320 if (event.is_impl_only) {
321 if (layer_animation_delegate_)
322 layer_animation_delegate_->NotifyAnimationFinished(
323 wall_clock_time, monotonic_time, event.target_property);
324 return;
325 }
326
327 for (size_t i = 0; i < active_animations_.size(); ++i) {
328 if (active_animations_[i]->group() == event.group_id &&
329 active_animations_[i]->target_property() == event.target_property) {
330 active_animations_[i]->set_received_finished_event(true);
331 if (layer_animation_delegate_)
332 layer_animation_delegate_->NotifyAnimationFinished(
333 wall_clock_time, monotonic_time, event.target_property);
334
335 return;
336 }
337 }
338 }
339
NotifyAnimationAborted(const AnimationEvent & event)340 void LayerAnimationController::NotifyAnimationAborted(
341 const AnimationEvent& event) {
342 for (size_t i = 0; i < active_animations_.size(); ++i) {
343 if (active_animations_[i]->group() == event.group_id &&
344 active_animations_[i]->target_property() == event.target_property) {
345 active_animations_[i]->SetRunState(Animation::Aborted,
346 event.monotonic_time);
347 }
348 }
349 }
350
NotifyAnimationPropertyUpdate(const AnimationEvent & event)351 void LayerAnimationController::NotifyAnimationPropertyUpdate(
352 const AnimationEvent& event) {
353 switch (event.target_property) {
354 case Animation::Opacity:
355 NotifyObserversOpacityAnimated(event.opacity);
356 break;
357 case Animation::Transform:
358 NotifyObserversTransformAnimated(event.transform);
359 break;
360 default:
361 NOTREACHED();
362 }
363 }
364
AddValueObserver(LayerAnimationValueObserver * observer)365 void LayerAnimationController::AddValueObserver(
366 LayerAnimationValueObserver* observer) {
367 if (!value_observers_.HasObserver(observer))
368 value_observers_.AddObserver(observer);
369 }
370
RemoveValueObserver(LayerAnimationValueObserver * observer)371 void LayerAnimationController::RemoveValueObserver(
372 LayerAnimationValueObserver* observer) {
373 value_observers_.RemoveObserver(observer);
374 }
375
AddEventObserver(LayerAnimationEventObserver * observer)376 void LayerAnimationController::AddEventObserver(
377 LayerAnimationEventObserver* observer) {
378 if (!event_observers_.HasObserver(observer))
379 event_observers_.AddObserver(observer);
380 }
381
RemoveEventObserver(LayerAnimationEventObserver * observer)382 void LayerAnimationController::RemoveEventObserver(
383 LayerAnimationEventObserver* observer) {
384 event_observers_.RemoveObserver(observer);
385 }
386
AnimatedBoundsForBox(const gfx::BoxF & box,gfx::BoxF * bounds)387 bool LayerAnimationController::AnimatedBoundsForBox(const gfx::BoxF& box,
388 gfx::BoxF* bounds) {
389 // Compute bounds based on animations for which is_finished() is false.
390 // Do nothing if there are no such animations; in this case, it is assumed
391 // that callers will take care of computing bounds based on the owning layer's
392 // actual transform.
393 *bounds = gfx::BoxF();
394 for (size_t i = 0; i < active_animations_.size(); ++i) {
395 if (active_animations_[i]->is_finished() ||
396 active_animations_[i]->target_property() != Animation::Transform)
397 continue;
398
399 const TransformAnimationCurve* transform_animation_curve =
400 active_animations_[i]->curve()->ToTransformAnimationCurve();
401 gfx::BoxF animation_bounds;
402 bool success =
403 transform_animation_curve->AnimatedBoundsForBox(box, &animation_bounds);
404 if (!success)
405 return false;
406 bounds->Union(animation_bounds);
407 }
408
409 return true;
410 }
411
PushNewAnimationsToImplThread(LayerAnimationController * controller_impl) const412 void LayerAnimationController::PushNewAnimationsToImplThread(
413 LayerAnimationController* controller_impl) const {
414 // Any new animations owned by the main thread's controller are cloned and
415 // add to the impl thread's controller.
416 for (size_t i = 0; i < active_animations_.size(); ++i) {
417 // If the animation is already running on the impl thread, there is no
418 // need to copy it over.
419 if (controller_impl->GetAnimation(active_animations_[i]->group(),
420 active_animations_[i]->target_property()))
421 continue;
422
423 // If the animation is not running on the impl thread, it does not
424 // necessarily mean that it needs to be copied over and started; it may
425 // have already finished. In this case, the impl thread animation will
426 // have already notified that it has started and the main thread animation
427 // will no longer need
428 // a synchronized start time.
429 if (!active_animations_[i]->needs_synchronized_start_time())
430 continue;
431
432 // Scroll animations always start at the current scroll offset.
433 if (active_animations_[i]->target_property() == Animation::ScrollOffset) {
434 gfx::Vector2dF current_scroll_offset;
435 if (controller_impl->value_provider_) {
436 current_scroll_offset =
437 controller_impl->value_provider_->ScrollOffsetForAnimation();
438 } else {
439 // The owning layer isn't yet in the active tree, so the main thread
440 // scroll offset will be up-to-date.
441 current_scroll_offset = value_provider_->ScrollOffsetForAnimation();
442 }
443 active_animations_[i]->curve()->ToScrollOffsetAnimationCurve()
444 ->SetInitialValue(current_scroll_offset);
445 }
446
447 // The new animation should be set to run as soon as possible.
448 Animation::RunState initial_run_state =
449 Animation::WaitingForTargetAvailability;
450 double start_time = 0;
451 scoped_ptr<Animation> to_add(active_animations_[i]->CloneAndInitialize(
452 initial_run_state, start_time));
453 DCHECK(!to_add->needs_synchronized_start_time());
454 controller_impl->AddAnimation(to_add.Pass());
455 }
456 }
457
458 struct IsCompleted {
IsCompletedcc::IsCompleted459 explicit IsCompleted(const LayerAnimationController& main_thread_controller)
460 : main_thread_controller_(main_thread_controller) {}
operator ()cc::IsCompleted461 bool operator()(Animation* animation) const {
462 if (animation->is_impl_only()) {
463 return (animation->run_state() == Animation::WaitingForDeletion);
464 } else {
465 return !main_thread_controller_.GetAnimation(
466 animation->group(),
467 animation->target_property());
468 }
469 }
470
471 private:
472 const LayerAnimationController& main_thread_controller_;
473 };
474
RemoveAnimationsCompletedOnMainThread(LayerAnimationController * controller_impl) const475 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
476 LayerAnimationController* controller_impl) const {
477 // Delete all impl thread animations for which there is no corresponding
478 // main thread animation. Each iteration,
479 // controller->active_animations_.size() is decremented or i is incremented
480 // guaranteeing progress towards loop termination.
481 ScopedPtrVector<Animation>& animations =
482 controller_impl->active_animations_;
483 animations.erase(cc::remove_if(&animations,
484 animations.begin(),
485 animations.end(),
486 IsCompleted(*this)),
487 animations.end());
488 }
489
PushPropertiesToImplThread(LayerAnimationController * controller_impl) const490 void LayerAnimationController::PushPropertiesToImplThread(
491 LayerAnimationController* controller_impl) const {
492 for (size_t i = 0; i < active_animations_.size(); ++i) {
493 Animation* current_impl =
494 controller_impl->GetAnimation(
495 active_animations_[i]->group(),
496 active_animations_[i]->target_property());
497 if (current_impl)
498 active_animations_[i]->PushPropertiesTo(current_impl);
499 }
500 }
501
StartAnimations(double monotonic_time)502 void LayerAnimationController::StartAnimations(double monotonic_time) {
503 // First collect running properties.
504 TargetProperties blocked_properties;
505 for (size_t i = 0; i < active_animations_.size(); ++i) {
506 if (active_animations_[i]->run_state() == Animation::Starting ||
507 active_animations_[i]->run_state() == Animation::Running)
508 blocked_properties.insert(active_animations_[i]->target_property());
509 }
510
511 for (size_t i = 0; i < active_animations_.size(); ++i) {
512 if (active_animations_[i]->run_state() ==
513 Animation::WaitingForTargetAvailability) {
514 // Collect all properties for animations with the same group id (they
515 // should all also be in the list of animations).
516 TargetProperties enqueued_properties;
517 enqueued_properties.insert(active_animations_[i]->target_property());
518 for (size_t j = i + 1; j < active_animations_.size(); ++j) {
519 if (active_animations_[i]->group() == active_animations_[j]->group())
520 enqueued_properties.insert(active_animations_[j]->target_property());
521 }
522
523 // Check to see if intersection of the list of properties affected by
524 // the group and the list of currently blocked properties is null. In
525 // any case, the group's target properties need to be added to the list
526 // of blocked properties.
527 bool null_intersection = true;
528 for (TargetProperties::iterator p_iter = enqueued_properties.begin();
529 p_iter != enqueued_properties.end();
530 ++p_iter) {
531 if (!blocked_properties.insert(*p_iter).second)
532 null_intersection = false;
533 }
534
535 // If the intersection is null, then we are free to start the animations
536 // in the group.
537 if (null_intersection) {
538 active_animations_[i]->SetRunState(
539 Animation::Starting, monotonic_time);
540 for (size_t j = i + 1; j < active_animations_.size(); ++j) {
541 if (active_animations_[i]->group() ==
542 active_animations_[j]->group()) {
543 active_animations_[j]->SetRunState(
544 Animation::Starting, monotonic_time);
545 }
546 }
547 }
548 }
549 }
550 }
551
PromoteStartedAnimations(double monotonic_time,AnimationEventsVector * events)552 void LayerAnimationController::PromoteStartedAnimations(
553 double monotonic_time,
554 AnimationEventsVector* events) {
555 for (size_t i = 0; i < active_animations_.size(); ++i) {
556 if (active_animations_[i]->run_state() == Animation::Starting) {
557 active_animations_[i]->SetRunState(Animation::Running, monotonic_time);
558 if (!active_animations_[i]->has_set_start_time())
559 active_animations_[i]->set_start_time(monotonic_time);
560 if (events) {
561 AnimationEvent started_event(
562 AnimationEvent::Started,
563 id_,
564 active_animations_[i]->group(),
565 active_animations_[i]->target_property(),
566 monotonic_time);
567 started_event.is_impl_only = active_animations_[i]->is_impl_only();
568 events->push_back(started_event);
569 }
570 }
571 }
572 }
573
MarkFinishedAnimations(double monotonic_time)574 void LayerAnimationController::MarkFinishedAnimations(double monotonic_time) {
575 for (size_t i = 0; i < active_animations_.size(); ++i) {
576 if (active_animations_[i]->IsFinishedAt(monotonic_time) &&
577 active_animations_[i]->run_state() != Animation::Aborted &&
578 active_animations_[i]->run_state() != Animation::WaitingForDeletion)
579 active_animations_[i]->SetRunState(Animation::Finished, monotonic_time);
580 }
581 }
582
MarkAnimationsForDeletion(double monotonic_time,AnimationEventsVector * events)583 void LayerAnimationController::MarkAnimationsForDeletion(
584 double monotonic_time, AnimationEventsVector* events) {
585 bool marked_animations_for_deletions = false;
586
587 // Non-aborted animations are marked for deletion after a corresponding
588 // AnimationEvent::Finished event is sent or received. This means that if
589 // we don't have an events vector, we must ensure that non-aborted animations
590 // have received a finished event before marking them for deletion.
591 for (size_t i = 0; i < active_animations_.size(); i++) {
592 int group_id = active_animations_[i]->group();
593 if (active_animations_[i]->run_state() == Animation::Aborted) {
594 if (events && !active_animations_[i]->is_impl_only()) {
595 AnimationEvent aborted_event(
596 AnimationEvent::Aborted,
597 id_,
598 group_id,
599 active_animations_[i]->target_property(),
600 monotonic_time);
601 events->push_back(aborted_event);
602 }
603 active_animations_[i]->SetRunState(Animation::WaitingForDeletion,
604 monotonic_time);
605 marked_animations_for_deletions = true;
606 continue;
607 }
608
609 bool all_anims_with_same_id_are_finished = false;
610
611 // Since deleting an animation on the main thread leads to its deletion
612 // on the impl thread, we only mark a Finished main thread animation for
613 // deletion once it has received a Finished event from the impl thread.
614 bool animation_i_will_send_or_has_received_finish_event =
615 events || active_animations_[i]->received_finished_event();
616 // If an animation is finished, and not already marked for deletion,
617 // find out if all other animations in the same group are also finished.
618 if (active_animations_[i]->run_state() == Animation::Finished &&
619 animation_i_will_send_or_has_received_finish_event) {
620 all_anims_with_same_id_are_finished = true;
621 for (size_t j = 0; j < active_animations_.size(); ++j) {
622 bool animation_j_will_send_or_has_received_finish_event =
623 events || active_animations_[j]->received_finished_event();
624 if (group_id == active_animations_[j]->group() &&
625 (!active_animations_[j]->is_finished() ||
626 (active_animations_[j]->run_state() == Animation::Finished &&
627 !animation_j_will_send_or_has_received_finish_event))) {
628 all_anims_with_same_id_are_finished = false;
629 break;
630 }
631 }
632 }
633 if (all_anims_with_same_id_are_finished) {
634 // We now need to remove all animations with the same group id as
635 // group_id (and send along animation finished notifications, if
636 // necessary).
637 for (size_t j = i; j < active_animations_.size(); j++) {
638 if (active_animations_[j]->group() == group_id &&
639 active_animations_[j]->run_state() != Animation::Aborted) {
640 if (events) {
641 AnimationEvent finished_event(
642 AnimationEvent::Finished,
643 id_,
644 active_animations_[j]->group(),
645 active_animations_[j]->target_property(),
646 monotonic_time);
647 finished_event.is_impl_only = active_animations_[j]->is_impl_only();
648 events->push_back(finished_event);
649 }
650 active_animations_[j]->SetRunState(Animation::WaitingForDeletion,
651 monotonic_time);
652 }
653 }
654 marked_animations_for_deletions = true;
655 }
656 }
657 if (marked_animations_for_deletions)
658 NotifyObserversAnimationWaitingForDeletion();
659 }
660
IsWaitingForDeletion(Animation * animation)661 static bool IsWaitingForDeletion(Animation* animation) {
662 return animation->run_state() == Animation::WaitingForDeletion;
663 }
664
PurgeAnimationsMarkedForDeletion()665 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
666 ScopedPtrVector<Animation>& animations = active_animations_;
667 animations.erase(cc::remove_if(&animations,
668 animations.begin(),
669 animations.end(),
670 IsWaitingForDeletion),
671 animations.end());
672 }
673
TickAnimations(double monotonic_time)674 void LayerAnimationController::TickAnimations(double monotonic_time) {
675 for (size_t i = 0; i < active_animations_.size(); ++i) {
676 if (active_animations_[i]->run_state() == Animation::Starting ||
677 active_animations_[i]->run_state() == Animation::Running ||
678 active_animations_[i]->run_state() == Animation::Paused) {
679 double trimmed =
680 active_animations_[i]->TrimTimeToCurrentIteration(monotonic_time);
681
682 switch (active_animations_[i]->target_property()) {
683 case Animation::Transform: {
684 const TransformAnimationCurve* transform_animation_curve =
685 active_animations_[i]->curve()->ToTransformAnimationCurve();
686 const gfx::Transform transform =
687 transform_animation_curve->GetValue(trimmed);
688 NotifyObserversTransformAnimated(transform);
689 break;
690 }
691
692 case Animation::Opacity: {
693 const FloatAnimationCurve* float_animation_curve =
694 active_animations_[i]->curve()->ToFloatAnimationCurve();
695 const float opacity = float_animation_curve->GetValue(trimmed);
696 NotifyObserversOpacityAnimated(opacity);
697 break;
698 }
699
700 case Animation::Filter: {
701 const FilterAnimationCurve* filter_animation_curve =
702 active_animations_[i]->curve()->ToFilterAnimationCurve();
703 const FilterOperations filter =
704 filter_animation_curve->GetValue(trimmed);
705 NotifyObserversFilterAnimated(filter);
706 break;
707 }
708
709 case Animation::BackgroundColor: {
710 // Not yet implemented.
711 break;
712 }
713
714 case Animation::ScrollOffset: {
715 const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
716 active_animations_[i]->curve()->ToScrollOffsetAnimationCurve();
717 const gfx::Vector2dF scroll_offset =
718 scroll_offset_animation_curve->GetValue(trimmed);
719 NotifyObserversScrollOffsetAnimated(scroll_offset);
720 break;
721 }
722
723 // Do nothing for sentinel value.
724 case Animation::TargetPropertyEnumSize:
725 NOTREACHED();
726 }
727 }
728 }
729 }
730
UpdateActivation(UpdateActivationType type)731 void LayerAnimationController::UpdateActivation(UpdateActivationType type) {
732 bool force = type == ForceActivation;
733 if (registrar_) {
734 bool was_active = is_active_;
735 is_active_ = false;
736 for (size_t i = 0; i < active_animations_.size(); ++i) {
737 if (active_animations_[i]->run_state() != Animation::WaitingForDeletion) {
738 is_active_ = true;
739 break;
740 }
741 }
742
743 if (is_active_ && (!was_active || force))
744 registrar_->DidActivateAnimationController(this);
745 else if (!is_active_ && (was_active || force))
746 registrar_->DidDeactivateAnimationController(this);
747 }
748 }
749
NotifyObserversOpacityAnimated(float opacity)750 void LayerAnimationController::NotifyObserversOpacityAnimated(float opacity) {
751 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
752 value_observers_,
753 OnOpacityAnimated(opacity));
754 }
755
NotifyObserversTransformAnimated(const gfx::Transform & transform)756 void LayerAnimationController::NotifyObserversTransformAnimated(
757 const gfx::Transform& transform) {
758 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
759 value_observers_,
760 OnTransformAnimated(transform));
761 }
762
NotifyObserversFilterAnimated(const FilterOperations & filters)763 void LayerAnimationController::NotifyObserversFilterAnimated(
764 const FilterOperations& filters) {
765 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
766 value_observers_,
767 OnFilterAnimated(filters));
768 }
769
NotifyObserversScrollOffsetAnimated(gfx::Vector2dF scroll_offset)770 void LayerAnimationController::NotifyObserversScrollOffsetAnimated(
771 gfx::Vector2dF scroll_offset) {
772 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
773 value_observers_,
774 OnScrollOffsetAnimated(scroll_offset));
775 }
776
NotifyObserversAnimationWaitingForDeletion()777 void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() {
778 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
779 value_observers_,
780 OnAnimationWaitingForDeletion());
781 }
782
HasValueObserver()783 bool LayerAnimationController::HasValueObserver() {
784 if (value_observers_.might_have_observers()) {
785 ObserverListBase<LayerAnimationValueObserver>::Iterator it(
786 value_observers_);
787 return it.GetNext() != NULL;
788 }
789 return false;
790 }
791
HasActiveValueObserver()792 bool LayerAnimationController::HasActiveValueObserver() {
793 if (value_observers_.might_have_observers()) {
794 ObserverListBase<LayerAnimationValueObserver>::Iterator it(
795 value_observers_);
796 LayerAnimationValueObserver* obs;
797 while ((obs = it.GetNext()) != NULL)
798 if (obs->IsActive())
799 return true;
800 }
801 return false;
802 }
803
804 } // namespace cc
805