Handle account removal correctly on all platforms.
[chromium-blink-merge.git] / cc / animation / layer_animation_controller.cc
blob08a0ee91f1854cf4fc5020b50d8996803a9f1c01
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.
5 #include "cc/animation/layer_animation_controller.h"
7 #include <algorithm>
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"
21 namespace cc {
23 LayerAnimationController::LayerAnimationController(int id)
24 : registrar_(0),
25 id_(id),
26 is_active_(false),
27 value_provider_(NULL),
28 layer_animation_delegate_(NULL),
29 needs_to_start_animations_(false) {
32 LayerAnimationController::~LayerAnimationController() {
33 if (registrar_)
34 registrar_->UnregisterAnimationController(this);
37 scoped_refptr<LayerAnimationController> LayerAnimationController::Create(
38 int id) {
39 return make_scoped_refptr(new LayerAnimationController(id));
42 void LayerAnimationController::PauseAnimation(int animation_id,
43 base::TimeDelta time_offset) {
44 for (size_t i = 0; i < animations_.size(); ++i) {
45 if (animations_[i]->id() == animation_id) {
46 animations_[i]->SetRunState(Animation::Paused,
47 time_offset + animations_[i]->start_time());
52 struct HasAnimationId {
53 explicit HasAnimationId(int id) : id_(id) {}
54 bool operator()(Animation* animation) const {
55 return animation->id() == id_;
58 private:
59 int id_;
62 void LayerAnimationController::RemoveAnimation(int animation_id) {
63 animations_.erase(cc::remove_if(&animations_,
64 animations_.begin(),
65 animations_.end(),
66 HasAnimationId(animation_id)),
67 animations_.end());
68 UpdateActivation(NormalActivation);
71 struct HasAnimationIdAndProperty {
72 HasAnimationIdAndProperty(int id, Animation::TargetProperty target_property)
73 : id_(id), target_property_(target_property) {}
74 bool operator()(Animation* animation) const {
75 return animation->id() == id_ &&
76 animation->target_property() == target_property_;
79 private:
80 int id_;
81 Animation::TargetProperty target_property_;
84 void LayerAnimationController::RemoveAnimation(
85 int animation_id,
86 Animation::TargetProperty target_property) {
87 animations_.erase(
88 cc::remove_if(&animations_,
89 animations_.begin(),
90 animations_.end(),
91 HasAnimationIdAndProperty(animation_id, target_property)),
92 animations_.end());
93 UpdateActivation(NormalActivation);
96 void LayerAnimationController::AbortAnimations(
97 Animation::TargetProperty target_property) {
98 for (size_t i = 0; i < animations_.size(); ++i) {
99 if (animations_[i]->target_property() == target_property &&
100 !animations_[i]->is_finished())
101 animations_[i]->SetRunState(Animation::Aborted, last_tick_time_);
105 // Ensures that the list of active animations on the main thread and the impl
106 // thread are kept in sync.
107 void LayerAnimationController::PushAnimationUpdatesTo(
108 LayerAnimationController* controller_impl) {
109 DCHECK(this != controller_impl);
110 if (!has_any_animation() && !controller_impl->has_any_animation())
111 return;
112 PurgeAnimationsMarkedForDeletion();
113 PushNewAnimationsToImplThread(controller_impl);
115 // Remove finished impl side animations only after pushing,
116 // and only after the animations are deleted on the main thread
117 // this insures we will never push an animation twice.
118 RemoveAnimationsCompletedOnMainThread(controller_impl);
120 PushPropertiesToImplThread(controller_impl);
121 controller_impl->UpdateActivation(NormalActivation);
122 UpdateActivation(NormalActivation);
125 void LayerAnimationController::Animate(base::TimeTicks monotonic_time) {
126 DCHECK(!monotonic_time.is_null());
127 if (!HasValueObserver())
128 return;
130 if (needs_to_start_animations_)
131 StartAnimations(monotonic_time);
132 TickAnimations(monotonic_time);
133 last_tick_time_ = monotonic_time;
136 void LayerAnimationController::AccumulatePropertyUpdates(
137 base::TimeTicks monotonic_time,
138 AnimationEventsVector* events) {
139 if (!events)
140 return;
142 for (size_t i = 0; i < animations_.size(); ++i) {
143 Animation* animation = animations_[i];
144 if (!animation->is_impl_only())
145 continue;
147 if (!animation->InEffect(monotonic_time))
148 continue;
150 double trimmed = animation->TrimTimeToCurrentIteration(monotonic_time);
151 switch (animation->target_property()) {
152 case Animation::Opacity: {
153 AnimationEvent event(AnimationEvent::PropertyUpdate,
154 id_,
155 animation->group(),
156 Animation::Opacity,
157 monotonic_time);
158 const FloatAnimationCurve* float_animation_curve =
159 animation->curve()->ToFloatAnimationCurve();
160 event.opacity = float_animation_curve->GetValue(trimmed);
161 event.is_impl_only = true;
162 events->push_back(event);
163 break;
166 case Animation::Transform: {
167 AnimationEvent event(AnimationEvent::PropertyUpdate,
168 id_,
169 animation->group(),
170 Animation::Transform,
171 monotonic_time);
172 const TransformAnimationCurve* transform_animation_curve =
173 animation->curve()->ToTransformAnimationCurve();
174 event.transform = transform_animation_curve->GetValue(trimmed);
175 event.is_impl_only = true;
176 events->push_back(event);
177 break;
180 case Animation::Filter: {
181 AnimationEvent event(AnimationEvent::PropertyUpdate,
182 id_,
183 animation->group(),
184 Animation::Filter,
185 monotonic_time);
186 const FilterAnimationCurve* filter_animation_curve =
187 animation->curve()->ToFilterAnimationCurve();
188 event.filters = filter_animation_curve->GetValue(trimmed);
189 event.is_impl_only = true;
190 events->push_back(event);
191 break;
194 case Animation::BackgroundColor: { break; }
196 case Animation::ScrollOffset: {
197 // Impl-side changes to scroll offset are already sent back to the
198 // main thread (e.g. for user-driven scrolling), so a PropertyUpdate
199 // isn't needed.
200 break;
203 case Animation::TargetPropertyEnumSize:
204 NOTREACHED();
209 void LayerAnimationController::UpdateState(bool start_ready_animations,
210 AnimationEventsVector* events) {
211 if (!HasActiveValueObserver())
212 return;
214 DCHECK(last_tick_time_ != base::TimeTicks());
215 if (start_ready_animations)
216 PromoteStartedAnimations(last_tick_time_, events);
218 MarkFinishedAnimations(last_tick_time_);
219 MarkAnimationsForDeletion(last_tick_time_, events);
221 if (needs_to_start_animations_ && start_ready_animations) {
222 StartAnimations(last_tick_time_);
223 PromoteStartedAnimations(last_tick_time_, events);
226 AccumulatePropertyUpdates(last_tick_time_, events);
228 UpdateActivation(NormalActivation);
231 struct AffectsNoObservers {
232 bool operator()(Animation* animation) const {
233 return !animation->affects_active_observers() &&
234 !animation->affects_pending_observers();
238 void LayerAnimationController::ActivateAnimations() {
239 for (size_t i = 0; i < animations_.size(); ++i) {
240 animations_[i]->set_affects_active_observers(
241 animations_[i]->affects_pending_observers());
243 animations_.erase(cc::remove_if(&animations_,
244 animations_.begin(),
245 animations_.end(),
246 AffectsNoObservers()),
247 animations_.end());
248 UpdateActivation(NormalActivation);
251 void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) {
252 animations_.push_back(animation.Pass());
253 needs_to_start_animations_ = true;
254 UpdateActivation(NormalActivation);
257 Animation* LayerAnimationController::GetAnimation(
258 int group_id,
259 Animation::TargetProperty target_property) const {
260 for (size_t i = 0; i < animations_.size(); ++i)
261 if (animations_[i]->group() == group_id &&
262 animations_[i]->target_property() == target_property)
263 return animations_[i];
264 return 0;
267 Animation* LayerAnimationController::GetAnimation(
268 Animation::TargetProperty target_property) const {
269 for (size_t i = 0; i < animations_.size(); ++i) {
270 size_t index = animations_.size() - i - 1;
271 if (animations_[index]->target_property() == target_property)
272 return animations_[index];
274 return 0;
277 bool LayerAnimationController::HasActiveAnimation() const {
278 for (size_t i = 0; i < animations_.size(); ++i) {
279 if (!animations_[i]->is_finished())
280 return true;
282 return false;
285 bool LayerAnimationController::IsAnimatingProperty(
286 Animation::TargetProperty target_property) const {
287 for (size_t i = 0; i < animations_.size(); ++i) {
288 if (!animations_[i]->is_finished() &&
289 animations_[i]->target_property() == target_property)
290 return true;
292 return false;
295 void LayerAnimationController::SetAnimationRegistrar(
296 AnimationRegistrar* registrar) {
297 if (registrar_ == registrar)
298 return;
300 if (registrar_)
301 registrar_->UnregisterAnimationController(this);
303 registrar_ = registrar;
304 if (registrar_)
305 registrar_->RegisterAnimationController(this);
307 UpdateActivation(ForceActivation);
310 void LayerAnimationController::NotifyAnimationStarted(
311 const AnimationEvent& event) {
312 if (event.is_impl_only) {
313 FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
314 OnAnimationStarted(event));
315 if (layer_animation_delegate_)
316 layer_animation_delegate_->NotifyAnimationStarted(event.monotonic_time,
317 event.target_property);
318 return;
321 for (size_t i = 0; i < animations_.size(); ++i) {
322 if (animations_[i]->group() == event.group_id &&
323 animations_[i]->target_property() == event.target_property &&
324 animations_[i]->needs_synchronized_start_time()) {
325 animations_[i]->set_needs_synchronized_start_time(false);
326 if (!animations_[i]->has_set_start_time())
327 animations_[i]->set_start_time(event.monotonic_time);
329 FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
330 OnAnimationStarted(event));
331 if (layer_animation_delegate_)
332 layer_animation_delegate_->NotifyAnimationStarted(
333 event.monotonic_time, event.target_property);
335 return;
340 void LayerAnimationController::NotifyAnimationFinished(
341 const AnimationEvent& event) {
342 if (event.is_impl_only) {
343 if (layer_animation_delegate_)
344 layer_animation_delegate_->NotifyAnimationFinished(event.monotonic_time,
345 event.target_property);
346 return;
349 for (size_t i = 0; i < animations_.size(); ++i) {
350 if (animations_[i]->group() == event.group_id &&
351 animations_[i]->target_property() == event.target_property) {
352 animations_[i]->set_received_finished_event(true);
353 if (layer_animation_delegate_)
354 layer_animation_delegate_->NotifyAnimationFinished(
355 event.monotonic_time, event.target_property);
357 return;
362 void LayerAnimationController::NotifyAnimationAborted(
363 const AnimationEvent& event) {
364 for (size_t i = 0; i < animations_.size(); ++i) {
365 if (animations_[i]->group() == event.group_id &&
366 animations_[i]->target_property() == event.target_property) {
367 animations_[i]->SetRunState(Animation::Aborted, event.monotonic_time);
372 void LayerAnimationController::NotifyAnimationPropertyUpdate(
373 const AnimationEvent& event) {
374 bool notify_active_observers = true;
375 bool notify_pending_observers = true;
376 switch (event.target_property) {
377 case Animation::Opacity:
378 NotifyObserversOpacityAnimated(
379 event.opacity, notify_active_observers, notify_pending_observers);
380 break;
381 case Animation::Transform:
382 NotifyObserversTransformAnimated(
383 event.transform, notify_active_observers, notify_pending_observers);
384 break;
385 default:
386 NOTREACHED();
390 void LayerAnimationController::AddValueObserver(
391 LayerAnimationValueObserver* observer) {
392 if (!value_observers_.HasObserver(observer))
393 value_observers_.AddObserver(observer);
396 void LayerAnimationController::RemoveValueObserver(
397 LayerAnimationValueObserver* observer) {
398 value_observers_.RemoveObserver(observer);
401 void LayerAnimationController::AddEventObserver(
402 LayerAnimationEventObserver* observer) {
403 if (!event_observers_.HasObserver(observer))
404 event_observers_.AddObserver(observer);
407 void LayerAnimationController::RemoveEventObserver(
408 LayerAnimationEventObserver* observer) {
409 event_observers_.RemoveObserver(observer);
412 bool LayerAnimationController::HasFilterAnimationThatInflatesBounds() const {
413 for (size_t i = 0; i < animations_.size(); ++i) {
414 if (!animations_[i]->is_finished() &&
415 animations_[i]->target_property() == Animation::Filter &&
416 animations_[i]
417 ->curve()
418 ->ToFilterAnimationCurve()
419 ->HasFilterThatMovesPixels())
420 return true;
423 return false;
426 bool LayerAnimationController::HasTransformAnimationThatInflatesBounds() const {
427 return IsAnimatingProperty(Animation::Transform);
430 bool LayerAnimationController::FilterAnimationBoundsForBox(
431 const gfx::BoxF& box, gfx::BoxF* bounds) const {
432 // TODO(avallee): Implement.
433 return false;
436 bool LayerAnimationController::TransformAnimationBoundsForBox(
437 const gfx::BoxF& box,
438 gfx::BoxF* bounds) const {
439 DCHECK(HasTransformAnimationThatInflatesBounds())
440 << "TransformAnimationBoundsForBox will give incorrect results if there "
441 << "are no transform animations affecting bounds, non-animated transform "
442 << "is not known";
444 // Compute bounds based on animations for which is_finished() is false.
445 // Do nothing if there are no such animations; in this case, it is assumed
446 // that callers will take care of computing bounds based on the owning layer's
447 // actual transform.
448 *bounds = gfx::BoxF();
449 for (size_t i = 0; i < animations_.size(); ++i) {
450 if (animations_[i]->is_finished() ||
451 animations_[i]->target_property() != Animation::Transform)
452 continue;
454 const TransformAnimationCurve* transform_animation_curve =
455 animations_[i]->curve()->ToTransformAnimationCurve();
456 gfx::BoxF animation_bounds;
457 bool success =
458 transform_animation_curve->AnimatedBoundsForBox(box, &animation_bounds);
459 if (!success)
460 return false;
461 bounds->Union(animation_bounds);
464 return true;
467 bool LayerAnimationController::HasAnimationThatAffectsScale() const {
468 for (size_t i = 0; i < animations_.size(); ++i) {
469 if (animations_[i]->is_finished() ||
470 animations_[i]->target_property() != Animation::Transform)
471 continue;
473 const TransformAnimationCurve* transform_animation_curve =
474 animations_[i]->curve()->ToTransformAnimationCurve();
475 if (transform_animation_curve->AffectsScale())
476 return true;
479 return false;
482 bool LayerAnimationController::HasOnlyTranslationTransforms() const {
483 for (size_t i = 0; i < animations_.size(); ++i) {
484 if (animations_[i]->is_finished() ||
485 animations_[i]->target_property() != Animation::Transform)
486 continue;
488 const TransformAnimationCurve* transform_animation_curve =
489 animations_[i]->curve()->ToTransformAnimationCurve();
490 if (!transform_animation_curve->IsTranslation())
491 return false;
494 return true;
497 bool LayerAnimationController::MaximumScale(float* max_scale) const {
498 *max_scale = 0.f;
499 for (size_t i = 0; i < animations_.size(); ++i) {
500 if (animations_[i]->is_finished() ||
501 animations_[i]->target_property() != Animation::Transform)
502 continue;
504 const TransformAnimationCurve* transform_animation_curve =
505 animations_[i]->curve()->ToTransformAnimationCurve();
506 float animation_scale = 0.f;
507 if (!transform_animation_curve->MaximumScale(&animation_scale))
508 return false;
509 *max_scale = std::max(*max_scale, animation_scale);
512 return true;
515 void LayerAnimationController::PushNewAnimationsToImplThread(
516 LayerAnimationController* controller_impl) const {
517 // Any new animations owned by the main thread's controller are cloned and
518 // add to the impl thread's controller.
519 for (size_t i = 0; i < animations_.size(); ++i) {
520 // If the animation is already running on the impl thread, there is no
521 // need to copy it over.
522 if (controller_impl->GetAnimation(animations_[i]->group(),
523 animations_[i]->target_property()))
524 continue;
526 // If the animation is not running on the impl thread, it does not
527 // necessarily mean that it needs to be copied over and started; it may
528 // have already finished. In this case, the impl thread animation will
529 // have already notified that it has started and the main thread animation
530 // will no longer need
531 // a synchronized start time.
532 if (!animations_[i]->needs_synchronized_start_time())
533 continue;
535 // Scroll animations always start at the current scroll offset.
536 if (animations_[i]->target_property() == Animation::ScrollOffset) {
537 gfx::Vector2dF current_scroll_offset;
538 if (controller_impl->value_provider_) {
539 current_scroll_offset =
540 controller_impl->value_provider_->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 = value_provider_->ScrollOffsetForAnimation();
546 animations_[i]->curve()->ToScrollOffsetAnimationCurve()->SetInitialValue(
547 current_scroll_offset);
550 // The new animation should be set to run as soon as possible.
551 Animation::RunState initial_run_state =
552 Animation::WaitingForTargetAvailability;
553 scoped_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_observers(false);
557 controller_impl->AddAnimation(to_add.Pass());
561 static bool IsCompleted(
562 Animation* animation,
563 const LayerAnimationController* main_thread_controller) {
564 if (animation->is_impl_only()) {
565 return (animation->run_state() == Animation::WaitingForDeletion);
566 } else {
567 return !main_thread_controller->GetAnimation(animation->group(),
568 animation->target_property());
572 static bool AffectsActiveOnlyAndIsWaitingForDeletion(Animation* animation) {
573 return animation->run_state() == Animation::WaitingForDeletion &&
574 !animation->affects_pending_observers();
577 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
578 LayerAnimationController* controller_impl) const {
579 // Animations removed on the main thread should no longer affect pending
580 // observers, and should stop affecting active observers after the next call
581 // to ActivateAnimations. If already WaitingForDeletion, they can be removed
582 // immediately.
583 ScopedPtrVector<Animation>& animations = controller_impl->animations_;
584 for (size_t i = 0; i < animations.size(); ++i) {
585 if (IsCompleted(animations[i], this))
586 animations[i]->set_affects_pending_observers(false);
588 animations.erase(cc::remove_if(&animations,
589 animations.begin(),
590 animations.end(),
591 AffectsActiveOnlyAndIsWaitingForDeletion),
592 animations.end());
595 void LayerAnimationController::PushPropertiesToImplThread(
596 LayerAnimationController* controller_impl) const {
597 for (size_t i = 0; i < animations_.size(); ++i) {
598 Animation* current_impl = controller_impl->GetAnimation(
599 animations_[i]->group(), animations_[i]->target_property());
600 if (current_impl)
601 animations_[i]->PushPropertiesTo(current_impl);
605 void LayerAnimationController::StartAnimations(base::TimeTicks monotonic_time) {
606 DCHECK(needs_to_start_animations_);
607 needs_to_start_animations_ = false;
608 // First collect running properties affecting each type of observer.
609 TargetProperties blocked_properties_for_active_observers;
610 TargetProperties blocked_properties_for_pending_observers;
611 std::vector<size_t> animations_waiting_for_target;
613 animations_waiting_for_target.reserve(animations_.size());
614 for (size_t i = 0; i < animations_.size(); ++i) {
615 if (animations_[i]->run_state() == Animation::Starting ||
616 animations_[i]->run_state() == Animation::Running) {
617 if (animations_[i]->affects_active_observers()) {
618 blocked_properties_for_active_observers.insert(
619 animations_[i]->target_property());
621 if (animations_[i]->affects_pending_observers()) {
622 blocked_properties_for_pending_observers.insert(
623 animations_[i]->target_property());
625 } else if (animations_[i]->run_state() ==
626 Animation::WaitingForTargetAvailability) {
627 animations_waiting_for_target.push_back(i);
631 for (size_t i = 0; i < animations_waiting_for_target.size(); ++i) {
632 // Collect all properties for animations with the same group id (they
633 // should all also be in the list of animations).
634 size_t animation_index = animations_waiting_for_target[i];
635 Animation* animation_waiting_for_target = animations_[animation_index];
636 // Check for the run state again even though the animation was waiting
637 // for target because it might have changed the run state while handling
638 // previous animation in this loop (if they belong to same group).
639 if (animation_waiting_for_target->run_state() ==
640 Animation::WaitingForTargetAvailability) {
641 TargetProperties enqueued_properties;
642 bool affects_active_observers =
643 animation_waiting_for_target->affects_active_observers();
644 bool affects_pending_observers =
645 animation_waiting_for_target->affects_pending_observers();
646 enqueued_properties.insert(
647 animation_waiting_for_target->target_property());
648 for (size_t j = animation_index + 1; j < animations_.size(); ++j) {
649 if (animation_waiting_for_target->group() == animations_[j]->group()) {
650 enqueued_properties.insert(animations_[j]->target_property());
651 affects_active_observers |=
652 animations_[j]->affects_active_observers();
653 affects_pending_observers |=
654 animations_[j]->affects_pending_observers();
658 // Check to see if intersection of the list of properties affected by
659 // the group and the list of currently blocked properties is null, taking
660 // into account the type(s) of observers affected by the group. In any
661 // case, the group's target properties need to be added to the lists of
662 // blocked properties.
663 bool null_intersection = true;
664 for (TargetProperties::iterator p_iter = enqueued_properties.begin();
665 p_iter != enqueued_properties.end();
666 ++p_iter) {
667 if (affects_active_observers &&
668 !blocked_properties_for_active_observers.insert(*p_iter).second)
669 null_intersection = false;
670 if (affects_pending_observers &&
671 !blocked_properties_for_pending_observers.insert(*p_iter).second)
672 null_intersection = false;
675 // If the intersection is null, then we are free to start the animations
676 // in the group.
677 if (null_intersection) {
678 animation_waiting_for_target->SetRunState(Animation::Starting,
679 monotonic_time);
680 for (size_t j = animation_index + 1; j < animations_.size(); ++j) {
681 if (animation_waiting_for_target->group() ==
682 animations_[j]->group()) {
683 animations_[j]->SetRunState(Animation::Starting, monotonic_time);
686 } else {
687 needs_to_start_animations_ = true;
693 void LayerAnimationController::PromoteStartedAnimations(
694 base::TimeTicks monotonic_time,
695 AnimationEventsVector* events) {
696 for (size_t i = 0; i < animations_.size(); ++i) {
697 if (animations_[i]->run_state() == Animation::Starting &&
698 animations_[i]->affects_active_observers()) {
699 animations_[i]->SetRunState(Animation::Running, monotonic_time);
700 if (!animations_[i]->has_set_start_time() &&
701 !animations_[i]->needs_synchronized_start_time())
702 animations_[i]->set_start_time(monotonic_time);
703 if (events) {
704 AnimationEvent started_event(AnimationEvent::Started,
705 id_,
706 animations_[i]->group(),
707 animations_[i]->target_property(),
708 monotonic_time);
709 started_event.is_impl_only = animations_[i]->is_impl_only();
710 if (started_event.is_impl_only)
711 NotifyAnimationStarted(started_event);
712 else
713 events->push_back(started_event);
719 void LayerAnimationController::MarkFinishedAnimations(
720 base::TimeTicks monotonic_time) {
721 for (size_t i = 0; i < animations_.size(); ++i) {
722 if (animations_[i]->IsFinishedAt(monotonic_time) &&
723 animations_[i]->run_state() != Animation::Aborted &&
724 animations_[i]->run_state() != Animation::WaitingForDeletion)
725 animations_[i]->SetRunState(Animation::Finished, monotonic_time);
729 void LayerAnimationController::MarkAnimationsForDeletion(
730 base::TimeTicks monotonic_time,
731 AnimationEventsVector* events) {
732 bool marked_animations_for_deletions = false;
733 std::vector<size_t> animations_with_same_group_id;
735 animations_with_same_group_id.reserve(animations_.size());
736 // Non-aborted animations are marked for deletion after a corresponding
737 // AnimationEvent::Finished event is sent or received. This means that if
738 // we don't have an events vector, we must ensure that non-aborted animations
739 // have received a finished event before marking them for deletion.
740 for (size_t i = 0; i < animations_.size(); i++) {
741 int group_id = animations_[i]->group();
742 if (animations_[i]->run_state() == Animation::Aborted) {
743 if (events && !animations_[i]->is_impl_only()) {
744 AnimationEvent aborted_event(AnimationEvent::Aborted,
745 id_,
746 group_id,
747 animations_[i]->target_property(),
748 monotonic_time);
749 events->push_back(aborted_event);
751 animations_[i]->SetRunState(Animation::WaitingForDeletion,
752 monotonic_time);
753 marked_animations_for_deletions = true;
754 continue;
757 bool all_anims_with_same_id_are_finished = false;
759 // Since deleting an animation on the main thread leads to its deletion
760 // on the impl thread, we only mark a Finished main thread animation for
761 // deletion once it has received a Finished event from the impl thread.
762 bool animation_i_will_send_or_has_received_finish_event =
763 events || animations_[i]->received_finished_event();
764 // If an animation is finished, and not already marked for deletion,
765 // find out if all other animations in the same group are also finished.
766 if (animations_[i]->run_state() == Animation::Finished &&
767 animation_i_will_send_or_has_received_finish_event) {
768 // Clear the animations_with_same_group_id if it was added for
769 // the previous animation's iteration.
770 if (animations_with_same_group_id.size() > 0)
771 animations_with_same_group_id.clear();
772 all_anims_with_same_id_are_finished = true;
773 for (size_t j = 0; j < animations_.size(); ++j) {
774 bool animation_j_will_send_or_has_received_finish_event =
775 events || animations_[j]->received_finished_event();
776 if (group_id == animations_[j]->group()) {
777 if (!animations_[j]->is_finished() ||
778 (animations_[j]->run_state() == Animation::Finished &&
779 !animation_j_will_send_or_has_received_finish_event)) {
780 all_anims_with_same_id_are_finished = false;
781 break;
782 } else if (j >= i &&
783 animations_[j]->run_state() != Animation::Aborted) {
784 // Mark down the animations which belong to the same group
785 // and is not yet aborted. If this current iteration finds that all
786 // animations with same ID are finished, then the marked
787 // animations below will be set to WaitingForDeletion in next
788 // iteration.
789 animations_with_same_group_id.push_back(j);
794 if (all_anims_with_same_id_are_finished) {
795 // We now need to remove all animations with the same group id as
796 // group_id (and send along animation finished notifications, if
797 // necessary).
798 for (size_t j = 0; j < animations_with_same_group_id.size(); j++) {
799 size_t animation_index = animations_with_same_group_id[j];
800 if (events) {
801 AnimationEvent finished_event(
802 AnimationEvent::Finished,
803 id_,
804 animations_[animation_index]->group(),
805 animations_[animation_index]->target_property(),
806 monotonic_time);
807 finished_event.is_impl_only =
808 animations_[animation_index]->is_impl_only();
809 if (finished_event.is_impl_only)
810 NotifyAnimationFinished(finished_event);
811 else
812 events->push_back(finished_event);
814 animations_[animation_index]->SetRunState(
815 Animation::WaitingForDeletion, monotonic_time);
817 marked_animations_for_deletions = true;
820 if (marked_animations_for_deletions)
821 NotifyObserversAnimationWaitingForDeletion();
824 static bool IsWaitingForDeletion(Animation* animation) {
825 return animation->run_state() == Animation::WaitingForDeletion;
828 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
829 animations_.erase(cc::remove_if(&animations_,
830 animations_.begin(),
831 animations_.end(),
832 IsWaitingForDeletion),
833 animations_.end());
836 void LayerAnimationController::TickAnimations(base::TimeTicks monotonic_time) {
837 for (size_t i = 0; i < animations_.size(); ++i) {
838 if (animations_[i]->run_state() == Animation::Starting ||
839 animations_[i]->run_state() == Animation::Running ||
840 animations_[i]->run_state() == Animation::Paused) {
841 if (!animations_[i]->InEffect(monotonic_time))
842 continue;
844 double trimmed =
845 animations_[i]->TrimTimeToCurrentIteration(monotonic_time);
847 switch (animations_[i]->target_property()) {
848 case Animation::Transform: {
849 const TransformAnimationCurve* transform_animation_curve =
850 animations_[i]->curve()->ToTransformAnimationCurve();
851 const gfx::Transform transform =
852 transform_animation_curve->GetValue(trimmed);
853 NotifyObserversTransformAnimated(
854 transform,
855 animations_[i]->affects_active_observers(),
856 animations_[i]->affects_pending_observers());
857 break;
860 case Animation::Opacity: {
861 const FloatAnimationCurve* float_animation_curve =
862 animations_[i]->curve()->ToFloatAnimationCurve();
863 const float opacity = std::max(
864 std::min(float_animation_curve->GetValue(trimmed), 1.0f), 0.f);
865 NotifyObserversOpacityAnimated(
866 opacity,
867 animations_[i]->affects_active_observers(),
868 animations_[i]->affects_pending_observers());
869 break;
872 case Animation::Filter: {
873 const FilterAnimationCurve* filter_animation_curve =
874 animations_[i]->curve()->ToFilterAnimationCurve();
875 const FilterOperations filter =
876 filter_animation_curve->GetValue(trimmed);
877 NotifyObserversFilterAnimated(
878 filter,
879 animations_[i]->affects_active_observers(),
880 animations_[i]->affects_pending_observers());
881 break;
884 case Animation::BackgroundColor: {
885 // Not yet implemented.
886 break;
889 case Animation::ScrollOffset: {
890 const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
891 animations_[i]->curve()->ToScrollOffsetAnimationCurve();
892 const gfx::Vector2dF scroll_offset =
893 scroll_offset_animation_curve->GetValue(trimmed);
894 NotifyObserversScrollOffsetAnimated(
895 scroll_offset,
896 animations_[i]->affects_active_observers(),
897 animations_[i]->affects_pending_observers());
898 break;
901 // Do nothing for sentinel value.
902 case Animation::TargetPropertyEnumSize:
903 NOTREACHED();
909 void LayerAnimationController::UpdateActivation(UpdateActivationType type) {
910 bool force = type == ForceActivation;
911 if (registrar_) {
912 bool was_active = is_active_;
913 is_active_ = false;
914 for (size_t i = 0; i < animations_.size(); ++i) {
915 if (animations_[i]->run_state() != Animation::WaitingForDeletion) {
916 is_active_ = true;
917 break;
921 if (is_active_ && (!was_active || force))
922 registrar_->DidActivateAnimationController(this);
923 else if (!is_active_ && (was_active || force))
924 registrar_->DidDeactivateAnimationController(this);
928 void LayerAnimationController::NotifyObserversOpacityAnimated(
929 float opacity,
930 bool notify_active_observers,
931 bool notify_pending_observers) {
932 if (value_observers_.might_have_observers()) {
933 ObserverListBase<LayerAnimationValueObserver>::Iterator it(
934 value_observers_);
935 LayerAnimationValueObserver* obs;
936 while ((obs = it.GetNext()) != NULL) {
937 if ((notify_active_observers && notify_pending_observers) ||
938 (notify_active_observers && obs->IsActive()) ||
939 (notify_pending_observers && !obs->IsActive()))
940 obs->OnOpacityAnimated(opacity);
945 void LayerAnimationController::NotifyObserversTransformAnimated(
946 const gfx::Transform& transform,
947 bool notify_active_observers,
948 bool notify_pending_observers) {
949 if (value_observers_.might_have_observers()) {
950 ObserverListBase<LayerAnimationValueObserver>::Iterator it(
951 value_observers_);
952 LayerAnimationValueObserver* obs;
953 while ((obs = it.GetNext()) != NULL) {
954 if ((notify_active_observers && notify_pending_observers) ||
955 (notify_active_observers && obs->IsActive()) ||
956 (notify_pending_observers && !obs->IsActive()))
957 obs->OnTransformAnimated(transform);
962 void LayerAnimationController::NotifyObserversFilterAnimated(
963 const FilterOperations& filters,
964 bool notify_active_observers,
965 bool notify_pending_observers) {
966 if (value_observers_.might_have_observers()) {
967 ObserverListBase<LayerAnimationValueObserver>::Iterator it(
968 value_observers_);
969 LayerAnimationValueObserver* obs;
970 while ((obs = it.GetNext()) != NULL) {
971 if ((notify_active_observers && notify_pending_observers) ||
972 (notify_active_observers && obs->IsActive()) ||
973 (notify_pending_observers && !obs->IsActive()))
974 obs->OnFilterAnimated(filters);
979 void LayerAnimationController::NotifyObserversScrollOffsetAnimated(
980 const gfx::Vector2dF& scroll_offset,
981 bool notify_active_observers,
982 bool notify_pending_observers) {
983 if (value_observers_.might_have_observers()) {
984 ObserverListBase<LayerAnimationValueObserver>::Iterator it(
985 value_observers_);
986 LayerAnimationValueObserver* obs;
987 while ((obs = it.GetNext()) != NULL) {
988 if ((notify_active_observers && notify_pending_observers) ||
989 (notify_active_observers && obs->IsActive()) ||
990 (notify_pending_observers && !obs->IsActive()))
991 obs->OnScrollOffsetAnimated(scroll_offset);
996 void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() {
997 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
998 value_observers_,
999 OnAnimationWaitingForDeletion());
1002 bool LayerAnimationController::HasValueObserver() {
1003 if (value_observers_.might_have_observers()) {
1004 ObserverListBase<LayerAnimationValueObserver>::Iterator it(
1005 value_observers_);
1006 return it.GetNext() != NULL;
1008 return false;
1011 bool LayerAnimationController::HasActiveValueObserver() {
1012 if (value_observers_.might_have_observers()) {
1013 ObserverListBase<LayerAnimationValueObserver>::Iterator it(
1014 value_observers_);
1015 LayerAnimationValueObserver* obs;
1016 while ((obs = it.GetNext()) != NULL)
1017 if (obs->IsActive())
1018 return true;
1020 return false;
1023 } // namespace cc