Add a string for translation.
[chromium-blink-merge.git] / cc / animation / layer_animation_controller.cc
blob464801ce92fb02a3803c27cfe2b837f4d066c1e5
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 last_tick_time_(0),
28 value_provider_(NULL),
29 layer_animation_delegate_(NULL) {}
31 LayerAnimationController::~LayerAnimationController() {
32 if (registrar_)
33 registrar_->UnregisterAnimationController(this);
36 scoped_refptr<LayerAnimationController> LayerAnimationController::Create(
37 int id) {
38 return make_scoped_refptr(new LayerAnimationController(id));
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());
51 struct HasAnimationId {
52 explicit HasAnimationId(int id) : id_(id) {}
53 bool operator()(Animation* animation) const {
54 return animation->id() == id_;
57 private:
58 int 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);
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 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);
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_);
106 // Ensures that the list of active animations on the main thread and the impl
107 // thread are kept in sync.
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);
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);
121 PushPropertiesToImplThread(controller_impl);
122 controller_impl->UpdateActivation(NormalActivation);
123 UpdateActivation(NormalActivation);
126 void LayerAnimationController::Animate(double monotonic_time) {
127 DCHECK(monotonic_time);
128 if (!HasValueObserver())
129 return;
131 StartAnimations(monotonic_time);
132 TickAnimations(monotonic_time);
133 last_tick_time_ = monotonic_time;
136 void LayerAnimationController::AccumulatePropertyUpdates(
137 double monotonic_time,
138 AnimationEventsVector* events) {
139 if (!events)
140 return;
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;
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;
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;
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;
188 case Animation::BackgroundColor: { break; }
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;
197 case Animation::TargetPropertyEnumSize:
198 NOTREACHED();
203 void LayerAnimationController::UpdateState(bool start_ready_animations,
204 AnimationEventsVector* events) {
205 if (!HasActiveValueObserver())
206 return;
208 if (start_ready_animations)
209 PromoteStartedAnimations(last_tick_time_, events);
211 MarkFinishedAnimations(last_tick_time_);
212 MarkAnimationsForDeletion(last_tick_time_, events);
214 if (start_ready_animations) {
215 StartAnimations(last_tick_time_);
216 PromoteStartedAnimations(last_tick_time_, events);
219 AccumulatePropertyUpdates(last_tick_time_, events);
221 UpdateActivation(NormalActivation);
224 void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) {
225 active_animations_.push_back(animation.Pass());
226 UpdateActivation(NormalActivation);
229 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;
239 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];
246 return 0;
249 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;
254 return false;
257 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;
264 return false;
267 void LayerAnimationController::SetAnimationRegistrar(
268 AnimationRegistrar* registrar) {
269 if (registrar_ == registrar)
270 return;
272 if (registrar_)
273 registrar_->UnregisterAnimationController(this);
275 registrar_ = registrar;
276 if (registrar_)
277 registrar_->RegisterAnimationController(this);
279 UpdateActivation(ForceActivation);
282 void LayerAnimationController::NotifyAnimationStarted(
283 const AnimationEvent& event) {
284 base::TimeTicks monotonic_time = base::TimeTicks::FromInternalValue(
285 event.monotonic_time * base::Time::kMicrosecondsPerSecond);
286 if (event.is_impl_only) {
287 FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
288 OnAnimationStarted(event));
289 if (layer_animation_delegate_)
290 layer_animation_delegate_->NotifyAnimationStarted(monotonic_time,
291 event.target_property);
293 return;
296 for (size_t i = 0; i < active_animations_.size(); ++i) {
297 if (active_animations_[i]->group() == event.group_id &&
298 active_animations_[i]->target_property() == event.target_property &&
299 active_animations_[i]->needs_synchronized_start_time()) {
300 active_animations_[i]->set_needs_synchronized_start_time(false);
301 if (!active_animations_[i]->has_set_start_time())
302 active_animations_[i]->set_start_time(event.monotonic_time);
304 FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
305 OnAnimationStarted(event));
306 if (layer_animation_delegate_)
307 layer_animation_delegate_->NotifyAnimationStarted(
308 monotonic_time, event.target_property);
310 return;
315 void LayerAnimationController::NotifyAnimationFinished(
316 const AnimationEvent& event) {
317 base::TimeTicks monotonic_time = base::TimeTicks::FromInternalValue(
318 event.monotonic_time * base::Time::kMicrosecondsPerSecond);
319 if (event.is_impl_only) {
320 if (layer_animation_delegate_)
321 layer_animation_delegate_->NotifyAnimationFinished(monotonic_time,
322 event.target_property);
323 return;
326 for (size_t i = 0; i < active_animations_.size(); ++i) {
327 if (active_animations_[i]->group() == event.group_id &&
328 active_animations_[i]->target_property() == event.target_property) {
329 active_animations_[i]->set_received_finished_event(true);
330 if (layer_animation_delegate_)
331 layer_animation_delegate_->NotifyAnimationFinished(
332 monotonic_time, event.target_property);
334 return;
339 void LayerAnimationController::NotifyAnimationAborted(
340 const AnimationEvent& event) {
341 for (size_t i = 0; i < active_animations_.size(); ++i) {
342 if (active_animations_[i]->group() == event.group_id &&
343 active_animations_[i]->target_property() == event.target_property) {
344 active_animations_[i]->SetRunState(Animation::Aborted,
345 event.monotonic_time);
350 void LayerAnimationController::NotifyAnimationPropertyUpdate(
351 const AnimationEvent& event) {
352 switch (event.target_property) {
353 case Animation::Opacity:
354 NotifyObserversOpacityAnimated(event.opacity);
355 break;
356 case Animation::Transform:
357 NotifyObserversTransformAnimated(event.transform);
358 break;
359 default:
360 NOTREACHED();
364 void LayerAnimationController::AddValueObserver(
365 LayerAnimationValueObserver* observer) {
366 if (!value_observers_.HasObserver(observer))
367 value_observers_.AddObserver(observer);
370 void LayerAnimationController::RemoveValueObserver(
371 LayerAnimationValueObserver* observer) {
372 value_observers_.RemoveObserver(observer);
375 void LayerAnimationController::AddEventObserver(
376 LayerAnimationEventObserver* observer) {
377 if (!event_observers_.HasObserver(observer))
378 event_observers_.AddObserver(observer);
381 void LayerAnimationController::RemoveEventObserver(
382 LayerAnimationEventObserver* observer) {
383 event_observers_.RemoveObserver(observer);
386 bool LayerAnimationController::HasFilterAnimationThatInflatesBounds() const {
387 for (size_t i = 0; i < active_animations_.size(); ++i) {
388 if (!active_animations_[i]->is_finished() &&
389 active_animations_[i]->target_property() == Animation::Filter &&
390 active_animations_[i]
391 ->curve()
392 ->ToFilterAnimationCurve()
393 ->HasFilterThatMovesPixels())
394 return true;
397 return false;
400 bool LayerAnimationController::HasTransformAnimationThatInflatesBounds() const {
401 return IsAnimatingProperty(Animation::Transform);
404 bool LayerAnimationController::FilterAnimationBoundsForBox(
405 const gfx::BoxF& box, gfx::BoxF* bounds) const {
406 // TODO(avallee): Implement.
407 return false;
410 bool LayerAnimationController::TransformAnimationBoundsForBox(
411 const gfx::BoxF& box,
412 gfx::BoxF* bounds) const {
413 DCHECK(HasTransformAnimationThatInflatesBounds())
414 << "TransformAnimationBoundsForBox will give incorrect results if there "
415 << "are no transform animations affecting bounds, non-animated transform "
416 << "is not known";
418 // Compute bounds based on animations for which is_finished() is false.
419 // Do nothing if there are no such animations; in this case, it is assumed
420 // that callers will take care of computing bounds based on the owning layer's
421 // actual transform.
422 *bounds = gfx::BoxF();
423 for (size_t i = 0; i < active_animations_.size(); ++i) {
424 if (active_animations_[i]->is_finished() ||
425 active_animations_[i]->target_property() != Animation::Transform)
426 continue;
428 const TransformAnimationCurve* transform_animation_curve =
429 active_animations_[i]->curve()->ToTransformAnimationCurve();
430 gfx::BoxF animation_bounds;
431 bool success =
432 transform_animation_curve->AnimatedBoundsForBox(box, &animation_bounds);
433 if (!success)
434 return false;
435 bounds->Union(animation_bounds);
438 return true;
441 bool LayerAnimationController::HasAnimationThatAffectsScale() const {
442 for (size_t i = 0; i < active_animations_.size(); ++i) {
443 if (active_animations_[i]->is_finished() ||
444 active_animations_[i]->target_property() != Animation::Transform)
445 continue;
447 const TransformAnimationCurve* transform_animation_curve =
448 active_animations_[i]->curve()->ToTransformAnimationCurve();
449 if (transform_animation_curve->AffectsScale())
450 return true;
453 return false;
456 bool LayerAnimationController::HasOnlyTranslationTransforms() const {
457 for (size_t i = 0; i < active_animations_.size(); ++i) {
458 if (active_animations_[i]->is_finished() ||
459 active_animations_[i]->target_property() != Animation::Transform)
460 continue;
462 const TransformAnimationCurve* transform_animation_curve =
463 active_animations_[i]->curve()->ToTransformAnimationCurve();
464 if (!transform_animation_curve->IsTranslation())
465 return false;
468 return true;
471 bool LayerAnimationController::MaximumScale(float* max_scale) const {
472 *max_scale = 0.f;
473 for (size_t i = 0; i < active_animations_.size(); ++i) {
474 if (active_animations_[i]->is_finished() ||
475 active_animations_[i]->target_property() != Animation::Transform)
476 continue;
478 const TransformAnimationCurve* transform_animation_curve =
479 active_animations_[i]->curve()->ToTransformAnimationCurve();
480 float animation_scale = 0.f;
481 if (!transform_animation_curve->MaximumScale(&animation_scale))
482 return false;
483 *max_scale = std::max(*max_scale, animation_scale);
486 return true;
489 void LayerAnimationController::PushNewAnimationsToImplThread(
490 LayerAnimationController* controller_impl) const {
491 // Any new animations owned by the main thread's controller are cloned and
492 // add to the impl thread's controller.
493 for (size_t i = 0; i < active_animations_.size(); ++i) {
494 // If the animation is already running on the impl thread, there is no
495 // need to copy it over.
496 if (controller_impl->GetAnimation(active_animations_[i]->group(),
497 active_animations_[i]->target_property()))
498 continue;
500 // If the animation is not running on the impl thread, it does not
501 // necessarily mean that it needs to be copied over and started; it may
502 // have already finished. In this case, the impl thread animation will
503 // have already notified that it has started and the main thread animation
504 // will no longer need
505 // a synchronized start time.
506 if (!active_animations_[i]->needs_synchronized_start_time())
507 continue;
509 // Scroll animations always start at the current scroll offset.
510 if (active_animations_[i]->target_property() == Animation::ScrollOffset) {
511 gfx::Vector2dF current_scroll_offset;
512 if (controller_impl->value_provider_) {
513 current_scroll_offset =
514 controller_impl->value_provider_->ScrollOffsetForAnimation();
515 } else {
516 // The owning layer isn't yet in the active tree, so the main thread
517 // scroll offset will be up-to-date.
518 current_scroll_offset = value_provider_->ScrollOffsetForAnimation();
520 active_animations_[i]->curve()->ToScrollOffsetAnimationCurve()
521 ->SetInitialValue(current_scroll_offset);
524 // The new animation should be set to run as soon as possible.
525 Animation::RunState initial_run_state =
526 Animation::WaitingForTargetAvailability;
527 scoped_ptr<Animation> to_add(active_animations_[i]->CloneAndInitialize(
528 initial_run_state));
529 DCHECK(!to_add->needs_synchronized_start_time());
530 controller_impl->AddAnimation(to_add.Pass());
534 struct IsCompleted {
535 explicit IsCompleted(const LayerAnimationController& main_thread_controller)
536 : main_thread_controller_(main_thread_controller) {}
537 bool operator()(Animation* animation) const {
538 if (animation->is_impl_only()) {
539 return (animation->run_state() == Animation::WaitingForDeletion);
540 } else {
541 return !main_thread_controller_.GetAnimation(
542 animation->group(),
543 animation->target_property());
547 private:
548 const LayerAnimationController& main_thread_controller_;
551 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
552 LayerAnimationController* controller_impl) const {
553 // Delete all impl thread animations for which there is no corresponding
554 // main thread animation. Each iteration,
555 // controller->active_animations_.size() is decremented or i is incremented
556 // guaranteeing progress towards loop termination.
557 ScopedPtrVector<Animation>& animations =
558 controller_impl->active_animations_;
559 animations.erase(cc::remove_if(&animations,
560 animations.begin(),
561 animations.end(),
562 IsCompleted(*this)),
563 animations.end());
566 void LayerAnimationController::PushPropertiesToImplThread(
567 LayerAnimationController* controller_impl) const {
568 for (size_t i = 0; i < active_animations_.size(); ++i) {
569 Animation* current_impl =
570 controller_impl->GetAnimation(
571 active_animations_[i]->group(),
572 active_animations_[i]->target_property());
573 if (current_impl)
574 active_animations_[i]->PushPropertiesTo(current_impl);
578 void LayerAnimationController::StartAnimations(double monotonic_time) {
579 // First collect running properties.
580 TargetProperties blocked_properties;
581 for (size_t i = 0; i < active_animations_.size(); ++i) {
582 if (active_animations_[i]->run_state() == Animation::Starting ||
583 active_animations_[i]->run_state() == Animation::Running)
584 blocked_properties.insert(active_animations_[i]->target_property());
587 for (size_t i = 0; i < active_animations_.size(); ++i) {
588 if (active_animations_[i]->run_state() ==
589 Animation::WaitingForTargetAvailability) {
590 // Collect all properties for animations with the same group id (they
591 // should all also be in the list of animations).
592 TargetProperties enqueued_properties;
593 enqueued_properties.insert(active_animations_[i]->target_property());
594 for (size_t j = i + 1; j < active_animations_.size(); ++j) {
595 if (active_animations_[i]->group() == active_animations_[j]->group())
596 enqueued_properties.insert(active_animations_[j]->target_property());
599 // Check to see if intersection of the list of properties affected by
600 // the group and the list of currently blocked properties is null. In
601 // any case, the group's target properties need to be added to the list
602 // of blocked properties.
603 bool null_intersection = true;
604 for (TargetProperties::iterator p_iter = enqueued_properties.begin();
605 p_iter != enqueued_properties.end();
606 ++p_iter) {
607 if (!blocked_properties.insert(*p_iter).second)
608 null_intersection = false;
611 // If the intersection is null, then we are free to start the animations
612 // in the group.
613 if (null_intersection) {
614 active_animations_[i]->SetRunState(
615 Animation::Starting, monotonic_time);
616 for (size_t j = i + 1; j < active_animations_.size(); ++j) {
617 if (active_animations_[i]->group() ==
618 active_animations_[j]->group()) {
619 active_animations_[j]->SetRunState(
620 Animation::Starting, monotonic_time);
628 void LayerAnimationController::PromoteStartedAnimations(
629 double monotonic_time,
630 AnimationEventsVector* events) {
631 for (size_t i = 0; i < active_animations_.size(); ++i) {
632 if (active_animations_[i]->run_state() == Animation::Starting) {
633 active_animations_[i]->SetRunState(Animation::Running, monotonic_time);
634 if (!active_animations_[i]->has_set_start_time() &&
635 !active_animations_[i]->needs_synchronized_start_time())
636 active_animations_[i]->set_start_time(monotonic_time);
637 if (events) {
638 AnimationEvent started_event(
639 AnimationEvent::Started,
640 id_,
641 active_animations_[i]->group(),
642 active_animations_[i]->target_property(),
643 monotonic_time);
644 started_event.is_impl_only = active_animations_[i]->is_impl_only();
645 events->push_back(started_event);
651 void LayerAnimationController::MarkFinishedAnimations(double monotonic_time) {
652 for (size_t i = 0; i < active_animations_.size(); ++i) {
653 if (active_animations_[i]->IsFinishedAt(monotonic_time) &&
654 active_animations_[i]->run_state() != Animation::Aborted &&
655 active_animations_[i]->run_state() != Animation::WaitingForDeletion)
656 active_animations_[i]->SetRunState(Animation::Finished, monotonic_time);
660 void LayerAnimationController::MarkAnimationsForDeletion(
661 double monotonic_time, AnimationEventsVector* events) {
662 bool marked_animations_for_deletions = false;
664 // Non-aborted animations are marked for deletion after a corresponding
665 // AnimationEvent::Finished event is sent or received. This means that if
666 // we don't have an events vector, we must ensure that non-aborted animations
667 // have received a finished event before marking them for deletion.
668 for (size_t i = 0; i < active_animations_.size(); i++) {
669 int group_id = active_animations_[i]->group();
670 if (active_animations_[i]->run_state() == Animation::Aborted) {
671 if (events && !active_animations_[i]->is_impl_only()) {
672 AnimationEvent aborted_event(
673 AnimationEvent::Aborted,
674 id_,
675 group_id,
676 active_animations_[i]->target_property(),
677 monotonic_time);
678 events->push_back(aborted_event);
680 active_animations_[i]->SetRunState(Animation::WaitingForDeletion,
681 monotonic_time);
682 marked_animations_for_deletions = true;
683 continue;
686 bool all_anims_with_same_id_are_finished = false;
688 // Since deleting an animation on the main thread leads to its deletion
689 // on the impl thread, we only mark a Finished main thread animation for
690 // deletion once it has received a Finished event from the impl thread.
691 bool animation_i_will_send_or_has_received_finish_event =
692 events || active_animations_[i]->received_finished_event();
693 // If an animation is finished, and not already marked for deletion,
694 // find out if all other animations in the same group are also finished.
695 if (active_animations_[i]->run_state() == Animation::Finished &&
696 animation_i_will_send_or_has_received_finish_event) {
697 all_anims_with_same_id_are_finished = true;
698 for (size_t j = 0; j < active_animations_.size(); ++j) {
699 bool animation_j_will_send_or_has_received_finish_event =
700 events || active_animations_[j]->received_finished_event();
701 if (group_id == active_animations_[j]->group() &&
702 (!active_animations_[j]->is_finished() ||
703 (active_animations_[j]->run_state() == Animation::Finished &&
704 !animation_j_will_send_or_has_received_finish_event))) {
705 all_anims_with_same_id_are_finished = false;
706 break;
710 if (all_anims_with_same_id_are_finished) {
711 // We now need to remove all animations with the same group id as
712 // group_id (and send along animation finished notifications, if
713 // necessary).
714 for (size_t j = i; j < active_animations_.size(); j++) {
715 if (active_animations_[j]->group() == group_id &&
716 active_animations_[j]->run_state() != Animation::Aborted) {
717 if (events) {
718 AnimationEvent finished_event(
719 AnimationEvent::Finished,
720 id_,
721 active_animations_[j]->group(),
722 active_animations_[j]->target_property(),
723 monotonic_time);
724 finished_event.is_impl_only = active_animations_[j]->is_impl_only();
725 events->push_back(finished_event);
727 active_animations_[j]->SetRunState(Animation::WaitingForDeletion,
728 monotonic_time);
731 marked_animations_for_deletions = true;
734 if (marked_animations_for_deletions)
735 NotifyObserversAnimationWaitingForDeletion();
738 static bool IsWaitingForDeletion(Animation* animation) {
739 return animation->run_state() == Animation::WaitingForDeletion;
742 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
743 ScopedPtrVector<Animation>& animations = active_animations_;
744 animations.erase(cc::remove_if(&animations,
745 animations.begin(),
746 animations.end(),
747 IsWaitingForDeletion),
748 animations.end());
751 void LayerAnimationController::TickAnimations(double monotonic_time) {
752 for (size_t i = 0; i < active_animations_.size(); ++i) {
753 if (active_animations_[i]->run_state() == Animation::Starting ||
754 active_animations_[i]->run_state() == Animation::Running ||
755 active_animations_[i]->run_state() == Animation::Paused) {
756 double trimmed =
757 active_animations_[i]->TrimTimeToCurrentIteration(monotonic_time);
759 switch (active_animations_[i]->target_property()) {
760 case Animation::Transform: {
761 const TransformAnimationCurve* transform_animation_curve =
762 active_animations_[i]->curve()->ToTransformAnimationCurve();
763 const gfx::Transform transform =
764 transform_animation_curve->GetValue(trimmed);
765 NotifyObserversTransformAnimated(transform);
766 break;
769 case Animation::Opacity: {
770 const FloatAnimationCurve* float_animation_curve =
771 active_animations_[i]->curve()->ToFloatAnimationCurve();
772 const float opacity = float_animation_curve->GetValue(trimmed);
773 NotifyObserversOpacityAnimated(opacity);
774 break;
777 case Animation::Filter: {
778 const FilterAnimationCurve* filter_animation_curve =
779 active_animations_[i]->curve()->ToFilterAnimationCurve();
780 const FilterOperations filter =
781 filter_animation_curve->GetValue(trimmed);
782 NotifyObserversFilterAnimated(filter);
783 break;
786 case Animation::BackgroundColor: {
787 // Not yet implemented.
788 break;
791 case Animation::ScrollOffset: {
792 const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
793 active_animations_[i]->curve()->ToScrollOffsetAnimationCurve();
794 const gfx::Vector2dF scroll_offset =
795 scroll_offset_animation_curve->GetValue(trimmed);
796 NotifyObserversScrollOffsetAnimated(scroll_offset);
797 break;
800 // Do nothing for sentinel value.
801 case Animation::TargetPropertyEnumSize:
802 NOTREACHED();
808 void LayerAnimationController::UpdateActivation(UpdateActivationType type) {
809 bool force = type == ForceActivation;
810 if (registrar_) {
811 bool was_active = is_active_;
812 is_active_ = false;
813 for (size_t i = 0; i < active_animations_.size(); ++i) {
814 if (active_animations_[i]->run_state() != Animation::WaitingForDeletion) {
815 is_active_ = true;
816 break;
820 if (is_active_ && (!was_active || force))
821 registrar_->DidActivateAnimationController(this);
822 else if (!is_active_ && (was_active || force))
823 registrar_->DidDeactivateAnimationController(this);
827 void LayerAnimationController::NotifyObserversOpacityAnimated(float opacity) {
828 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
829 value_observers_,
830 OnOpacityAnimated(opacity));
833 void LayerAnimationController::NotifyObserversTransformAnimated(
834 const gfx::Transform& transform) {
835 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
836 value_observers_,
837 OnTransformAnimated(transform));
840 void LayerAnimationController::NotifyObserversFilterAnimated(
841 const FilterOperations& filters) {
842 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
843 value_observers_,
844 OnFilterAnimated(filters));
847 void LayerAnimationController::NotifyObserversScrollOffsetAnimated(
848 const gfx::Vector2dF& scroll_offset) {
849 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
850 value_observers_,
851 OnScrollOffsetAnimated(scroll_offset));
854 void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() {
855 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
856 value_observers_,
857 OnAnimationWaitingForDeletion());
860 bool LayerAnimationController::HasValueObserver() {
861 if (value_observers_.might_have_observers()) {
862 ObserverListBase<LayerAnimationValueObserver>::Iterator it(
863 value_observers_);
864 return it.GetNext() != NULL;
866 return false;
869 bool LayerAnimationController::HasActiveValueObserver() {
870 if (value_observers_.might_have_observers()) {
871 ObserverListBase<LayerAnimationValueObserver>::Iterator it(
872 value_observers_);
873 LayerAnimationValueObserver* obs;
874 while ((obs = it.GetNext()) != NULL)
875 if (obs->IsActive())
876 return true;
878 return false;
881 } // namespace cc