Pass CreateDirectory errors up to IndexedDB.
[chromium-blink-merge.git] / cc / animation / layer_animation_controller.cc
blob902e394e74e5f150d2f0e6f63f6610e7dd009e89
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_registrar.h"
11 #include "cc/animation/keyframed_animation_curve.h"
12 #include "cc/animation/layer_animation_value_observer.h"
13 #include "cc/base/scoped_ptr_algorithm.h"
14 #include "third_party/WebKit/public/platform/WebAnimationDelegate.h"
15 #include "ui/gfx/transform.h"
17 namespace cc {
19 LayerAnimationController::LayerAnimationController(int id)
20 : force_sync_(false),
21 registrar_(0),
22 id_(id),
23 is_active_(false),
24 last_tick_time_(0),
25 layer_animation_delegate_(NULL) {}
27 LayerAnimationController::~LayerAnimationController() {
28 if (registrar_)
29 registrar_->UnregisterAnimationController(this);
32 scoped_refptr<LayerAnimationController> LayerAnimationController::Create(
33 int id) {
34 return make_scoped_refptr(new LayerAnimationController(id));
37 void LayerAnimationController::PauseAnimation(int animation_id,
38 double time_offset) {
39 for (size_t i = 0; i < active_animations_.size(); ++i) {
40 if (active_animations_[i]->id() == animation_id) {
41 active_animations_[i]->SetRunState(
42 Animation::Paused, time_offset + active_animations_[i]->start_time());
47 struct HasAnimationId {
48 explicit HasAnimationId(int id) : id_(id) {}
49 bool operator()(Animation* animation) const {
50 return animation->id() == id_;
53 private:
54 int id_;
57 void LayerAnimationController::RemoveAnimation(int animation_id) {
58 ScopedPtrVector<Animation>& animations = active_animations_;
59 animations.erase(cc::remove_if(&animations,
60 animations.begin(),
61 animations.end(),
62 HasAnimationId(animation_id)),
63 animations.end());
64 UpdateActivation(NormalActivation);
67 struct HasAnimationIdAndProperty {
68 HasAnimationIdAndProperty(int id, Animation::TargetProperty target_property)
69 : id_(id), target_property_(target_property) {}
70 bool operator()(Animation* animation) const {
71 return animation->id() == id_ &&
72 animation->target_property() == target_property_;
75 private:
76 int id_;
77 Animation::TargetProperty target_property_;
80 void LayerAnimationController::RemoveAnimation(
81 int animation_id,
82 Animation::TargetProperty target_property) {
83 ScopedPtrVector<Animation>& animations = active_animations_;
84 animations.erase(cc::remove_if(&animations,
85 animations.begin(),
86 animations.end(),
87 HasAnimationIdAndProperty(animation_id,
88 target_property)),
89 animations.end());
90 UpdateActivation(NormalActivation);
93 // According to render layer backing, these are for testing only.
94 void LayerAnimationController::SuspendAnimations(double monotonic_time) {
95 for (size_t i = 0; i < active_animations_.size(); ++i) {
96 if (!active_animations_[i]->is_finished())
97 active_animations_[i]->SetRunState(Animation::Paused, monotonic_time);
101 // Looking at GraphicsLayerCA, this appears to be the analog to
102 // SuspendAnimations, which is for testing.
103 void LayerAnimationController::ResumeAnimations(double monotonic_time) {
104 for (size_t i = 0; i < active_animations_.size(); ++i) {
105 if (active_animations_[i]->run_state() == Animation::Paused)
106 active_animations_[i]->SetRunState(Animation::Running, monotonic_time);
110 // Ensures that the list of active animations on the main thread and the impl
111 // thread are kept in sync.
112 void LayerAnimationController::PushAnimationUpdatesTo(
113 LayerAnimationController* controller_impl) {
114 DCHECK(this != controller_impl);
115 if (force_sync_) {
116 ReplaceImplThreadAnimations(controller_impl);
117 force_sync_ = false;
118 } else {
119 PurgeAnimationsMarkedForDeletion();
120 PushNewAnimationsToImplThread(controller_impl);
122 // Remove finished impl side animations only after pushing,
123 // and only after the animations are deleted on the main thread
124 // this insures we will never push an animation twice.
125 RemoveAnimationsCompletedOnMainThread(controller_impl);
127 PushPropertiesToImplThread(controller_impl);
129 controller_impl->UpdateActivation(NormalActivation);
130 UpdateActivation(NormalActivation);
133 void LayerAnimationController::Animate(double monotonic_time) {
134 if (!HasValueObserver())
135 return;
137 StartAnimationsWaitingForNextTick(monotonic_time);
138 StartAnimationsWaitingForStartTime(monotonic_time);
139 StartAnimationsWaitingForTargetAvailability(monotonic_time);
140 ResolveConflicts(monotonic_time);
141 TickAnimations(monotonic_time);
142 last_tick_time_ = monotonic_time;
145 void LayerAnimationController::AccumulatePropertyUpdates(
146 double monotonic_time,
147 AnimationEventsVector* events) {
148 if (!events)
149 return;
151 for (size_t i = 0; i < active_animations_.size(); ++i) {
152 Animation* animation = active_animations_[i];
153 if (!animation->is_impl_only())
154 continue;
156 if (animation->target_property() == Animation::Opacity) {
157 AnimationEvent event(AnimationEvent::PropertyUpdate,
158 id_,
159 animation->group(),
160 Animation::Opacity,
161 monotonic_time);
162 event.opacity = animation->curve()->ToFloatAnimationCurve()->GetValue(
163 monotonic_time);
164 event.is_impl_only = true;
165 events->push_back(event);
166 } else if (animation->target_property() == Animation::Transform) {
167 AnimationEvent event(AnimationEvent::PropertyUpdate,
168 id_,
169 animation->group(),
170 Animation::Transform,
171 monotonic_time);
172 event.transform =
173 animation->curve()->ToTransformAnimationCurve()->GetValue(
174 monotonic_time);
175 event.is_impl_only = true;
176 events->push_back(event);
181 void LayerAnimationController::UpdateState(bool start_ready_animations,
182 AnimationEventsVector* events) {
183 if (!HasActiveValueObserver())
184 return;
186 if (start_ready_animations)
187 PromoteStartedAnimations(last_tick_time_, events);
189 MarkFinishedAnimations(last_tick_time_);
190 MarkAnimationsForDeletion(last_tick_time_, events);
192 if (start_ready_animations) {
193 StartAnimationsWaitingForTargetAvailability(last_tick_time_);
194 PromoteStartedAnimations(last_tick_time_, events);
197 AccumulatePropertyUpdates(last_tick_time_, events);
199 UpdateActivation(NormalActivation);
202 void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) {
203 active_animations_.push_back(animation.Pass());
204 UpdateActivation(NormalActivation);
207 Animation* LayerAnimationController::GetAnimation(
208 int group_id,
209 Animation::TargetProperty target_property) const {
210 for (size_t i = 0; i < active_animations_.size(); ++i)
211 if (active_animations_[i]->group() == group_id &&
212 active_animations_[i]->target_property() == target_property)
213 return active_animations_[i];
214 return 0;
217 Animation* LayerAnimationController::GetAnimation(
218 Animation::TargetProperty target_property) const {
219 for (size_t i = 0; i < active_animations_.size(); ++i) {
220 size_t index = active_animations_.size() - i - 1;
221 if (active_animations_[index]->target_property() == target_property)
222 return active_animations_[index];
224 return 0;
227 bool LayerAnimationController::HasActiveAnimation() const {
228 for (size_t i = 0; i < active_animations_.size(); ++i) {
229 if (!active_animations_[i]->is_finished())
230 return true;
232 return false;
235 bool LayerAnimationController::IsAnimatingProperty(
236 Animation::TargetProperty target_property) const {
237 for (size_t i = 0; i < active_animations_.size(); ++i) {
238 if (!active_animations_[i]->is_finished() &&
239 active_animations_[i]->target_property() == target_property)
240 return true;
242 return false;
245 void LayerAnimationController::SetAnimationRegistrar(
246 AnimationRegistrar* registrar) {
247 if (registrar_ == registrar)
248 return;
250 if (registrar_)
251 registrar_->UnregisterAnimationController(this);
253 registrar_ = registrar;
254 if (registrar_)
255 registrar_->RegisterAnimationController(this);
257 UpdateActivation(ForceActivation);
260 void LayerAnimationController::NotifyAnimationStarted(
261 const AnimationEvent& event,
262 double wall_clock_time) {
263 if (event.is_impl_only) {
264 FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
265 OnAnimationStarted(event));
266 if (layer_animation_delegate_)
267 layer_animation_delegate_->notifyAnimationStarted(wall_clock_time);
269 return;
272 for (size_t i = 0; i < active_animations_.size(); ++i) {
273 if (active_animations_[i]->group() == event.group_id &&
274 active_animations_[i]->target_property() == event.target_property &&
275 active_animations_[i]->needs_synchronized_start_time()) {
276 active_animations_[i]->set_needs_synchronized_start_time(false);
277 active_animations_[i]->set_start_time(event.monotonic_time);
279 FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
280 OnAnimationStarted(event));
281 if (layer_animation_delegate_)
282 layer_animation_delegate_->notifyAnimationStarted(wall_clock_time);
284 return;
289 void LayerAnimationController::NotifyAnimationFinished(
290 const AnimationEvent& event,
291 double wall_clock_time) {
292 if (event.is_impl_only) {
293 if (layer_animation_delegate_)
294 layer_animation_delegate_->notifyAnimationFinished(wall_clock_time);
295 return;
298 for (size_t i = 0; i < active_animations_.size(); ++i) {
299 if (active_animations_[i]->group() == event.group_id &&
300 active_animations_[i]->target_property() == event.target_property) {
301 active_animations_[i]->set_received_finished_event(true);
302 if (layer_animation_delegate_)
303 layer_animation_delegate_->notifyAnimationFinished(wall_clock_time);
305 return;
310 void LayerAnimationController::NotifyAnimationPropertyUpdate(
311 const AnimationEvent& event) {
312 switch (event.target_property) {
313 case Animation::Opacity:
314 NotifyObserversOpacityAnimated(event.opacity);
315 break;
316 case Animation::Transform:
317 NotifyObserversTransformAnimated(event.transform);
318 break;
319 default:
320 NOTREACHED();
324 void LayerAnimationController::AddValueObserver(
325 LayerAnimationValueObserver* observer) {
326 if (!value_observers_.HasObserver(observer))
327 value_observers_.AddObserver(observer);
330 void LayerAnimationController::RemoveValueObserver(
331 LayerAnimationValueObserver* observer) {
332 value_observers_.RemoveObserver(observer);
335 void LayerAnimationController::AddEventObserver(
336 LayerAnimationEventObserver* observer) {
337 if (!event_observers_.HasObserver(observer))
338 event_observers_.AddObserver(observer);
341 void LayerAnimationController::RemoveEventObserver(
342 LayerAnimationEventObserver* observer) {
343 event_observers_.RemoveObserver(observer);
346 void LayerAnimationController::PushNewAnimationsToImplThread(
347 LayerAnimationController* controller_impl) const {
348 // Any new animations owned by the main thread's controller are cloned and
349 // add to the impl thread's controller.
350 for (size_t i = 0; i < active_animations_.size(); ++i) {
351 // If the animation is already running on the impl thread, there is no
352 // need to copy it over.
353 if (controller_impl->GetAnimation(active_animations_[i]->group(),
354 active_animations_[i]->target_property()))
355 continue;
357 // If the animation is not running on the impl thread, it does not
358 // necessarily mean that it needs to be copied over and started; it may
359 // have already finished. In this case, the impl thread animation will
360 // have already notified that it has started and the main thread animation
361 // will no longer need
362 // a synchronized start time.
363 if (!active_animations_[i]->needs_synchronized_start_time())
364 continue;
366 // The new animation should be set to run as soon as possible.
367 Animation::RunState initial_run_state =
368 Animation::WaitingForTargetAvailability;
369 double start_time = 0;
370 scoped_ptr<Animation> to_add(active_animations_[i]->CloneAndInitialize(
371 Animation::ControllingInstance, initial_run_state, start_time));
372 DCHECK(!to_add->needs_synchronized_start_time());
373 controller_impl->AddAnimation(to_add.Pass());
377 struct IsCompleted {
378 explicit IsCompleted(const LayerAnimationController& main_thread_controller)
379 : main_thread_controller_(main_thread_controller) {}
380 bool operator()(Animation* animation) const {
381 if (animation->is_impl_only()) {
382 return (animation->run_state() == Animation::WaitingForDeletion);
383 } else {
384 return !main_thread_controller_.GetAnimation(
385 animation->group(),
386 animation->target_property());
390 private:
391 const LayerAnimationController& main_thread_controller_;
394 void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
395 LayerAnimationController* controller_impl) const {
396 // Delete all impl thread animations for which there is no corresponding
397 // main thread animation. Each iteration,
398 // controller->active_animations_.size() is decremented or i is incremented
399 // guaranteeing progress towards loop termination.
400 ScopedPtrVector<Animation>& animations =
401 controller_impl->active_animations_;
402 animations.erase(cc::remove_if(&animations,
403 animations.begin(),
404 animations.end(),
405 IsCompleted(*this)),
406 animations.end());
409 void LayerAnimationController::PushPropertiesToImplThread(
410 LayerAnimationController* controller_impl) const {
411 for (size_t i = 0; i < active_animations_.size(); ++i) {
412 Animation* current_impl =
413 controller_impl->GetAnimation(
414 active_animations_[i]->group(),
415 active_animations_[i]->target_property());
416 if (current_impl)
417 active_animations_[i]->PushPropertiesTo(current_impl);
421 void LayerAnimationController::StartAnimationsWaitingForNextTick(
422 double monotonic_time) {
423 for (size_t i = 0; i < active_animations_.size(); ++i) {
424 if (active_animations_[i]->run_state() == Animation::WaitingForNextTick)
425 active_animations_[i]->SetRunState(Animation::Starting, monotonic_time);
429 void LayerAnimationController::StartAnimationsWaitingForStartTime(
430 double monotonic_time) {
431 for (size_t i = 0; i < active_animations_.size(); ++i) {
432 if (active_animations_[i]->run_state() == Animation::WaitingForStartTime &&
433 active_animations_[i]->start_time() <= monotonic_time)
434 active_animations_[i]->SetRunState(Animation::Starting, monotonic_time);
438 void LayerAnimationController::StartAnimationsWaitingForTargetAvailability(
439 double monotonic_time) {
440 // First collect running properties.
441 TargetProperties blocked_properties;
442 for (size_t i = 0; i < active_animations_.size(); ++i) {
443 if (active_animations_[i]->run_state() == Animation::Starting ||
444 active_animations_[i]->run_state() == Animation::Running)
445 blocked_properties.insert(active_animations_[i]->target_property());
448 for (size_t i = 0; i < active_animations_.size(); ++i) {
449 if (active_animations_[i]->run_state() ==
450 Animation::WaitingForTargetAvailability) {
451 // Collect all properties for animations with the same group id (they
452 // should all also be in the list of animations).
453 TargetProperties enqueued_properties;
454 enqueued_properties.insert(active_animations_[i]->target_property());
455 for (size_t j = i + 1; j < active_animations_.size(); ++j) {
456 if (active_animations_[i]->group() == active_animations_[j]->group())
457 enqueued_properties.insert(active_animations_[j]->target_property());
460 // Check to see if intersection of the list of properties affected by
461 // the group and the list of currently blocked properties is null. In
462 // any case, the group's target properties need to be added to the list
463 // of blocked properties.
464 bool null_intersection = true;
465 for (TargetProperties::iterator p_iter = enqueued_properties.begin();
466 p_iter != enqueued_properties.end();
467 ++p_iter) {
468 if (!blocked_properties.insert(*p_iter).second)
469 null_intersection = false;
472 // If the intersection is null, then we are free to start the animations
473 // in the group.
474 if (null_intersection) {
475 active_animations_[i]->SetRunState(
476 Animation::Starting, monotonic_time);
477 for (size_t j = i + 1; j < active_animations_.size(); ++j) {
478 if (active_animations_[i]->group() ==
479 active_animations_[j]->group()) {
480 active_animations_[j]->SetRunState(
481 Animation::Starting, monotonic_time);
489 void LayerAnimationController::PromoteStartedAnimations(
490 double monotonic_time,
491 AnimationEventsVector* events) {
492 for (size_t i = 0; i < active_animations_.size(); ++i) {
493 if (active_animations_[i]->run_state() == Animation::Starting) {
494 active_animations_[i]->SetRunState(Animation::Running, monotonic_time);
495 if (!active_animations_[i]->has_set_start_time())
496 active_animations_[i]->set_start_time(monotonic_time);
497 if (events) {
498 AnimationEvent started_event(
499 AnimationEvent::Started,
500 id_,
501 active_animations_[i]->group(),
502 active_animations_[i]->target_property(),
503 monotonic_time);
504 started_event.is_impl_only = active_animations_[i]->is_impl_only();
505 events->push_back(started_event);
511 void LayerAnimationController::MarkFinishedAnimations(double monotonic_time) {
512 for (size_t i = 0; i < active_animations_.size(); ++i) {
513 if (active_animations_[i]->IsFinishedAt(monotonic_time) &&
514 active_animations_[i]->run_state() != Animation::WaitingForDeletion)
515 active_animations_[i]->SetRunState(Animation::Finished, monotonic_time);
519 void LayerAnimationController::ResolveConflicts(double monotonic_time) {
520 // Find any animations that are animating the same property and resolve the
521 // confict. We could eventually blend, but for now we'll just abort the
522 // previous animation (where 'previous' means: (1) has a prior start time or
523 // (2) has an equal start time, but was added to the queue earlier, i.e.,
524 // has a lower index in active_animations_).
525 for (size_t i = 0; i < active_animations_.size(); ++i) {
526 if (active_animations_[i]->run_state() == Animation::Starting ||
527 active_animations_[i]->run_state() == Animation::Running) {
528 for (size_t j = i + 1; j < active_animations_.size(); ++j) {
529 if ((active_animations_[j]->run_state() == Animation::Starting ||
530 active_animations_[j]->run_state() == Animation::Running) &&
531 active_animations_[i]->target_property() ==
532 active_animations_[j]->target_property()) {
533 if (active_animations_[i]->start_time() >
534 active_animations_[j]->start_time()) {
535 active_animations_[j]->SetRunState(Animation::Aborted,
536 monotonic_time);
537 } else {
538 active_animations_[i]->SetRunState(Animation::Aborted,
539 monotonic_time);
547 void LayerAnimationController::MarkAnimationsForDeletion(
548 double monotonic_time, AnimationEventsVector* events) {
549 // Non-aborted animations are marked for deletion after a corresponding
550 // AnimationEvent::Finished event is sent or received. This means that if
551 // we don't have an events vector, we must ensure that non-aborted animations
552 // have received a finished event before marking them for deletion.
553 for (size_t i = 0; i < active_animations_.size(); i++) {
554 int group_id = active_animations_[i]->group();
555 bool all_anims_with_same_id_are_finished = false;
557 // Since deleting an animation on the main thread leads to its deletion
558 // on the impl thread, we only mark a Finished main thread animation for
559 // deletion once it has received a Finished event from the impl thread.
560 bool animation_i_will_send_or_has_received_finish_event =
561 events || active_animations_[i]->received_finished_event();
562 // If an animation is finished, and not already marked for deletion,
563 // find out if all other animations in the same group are also finished.
564 if (active_animations_[i]->run_state() == Animation::Aborted ||
565 (active_animations_[i]->run_state() == Animation::Finished &&
566 animation_i_will_send_or_has_received_finish_event)) {
567 all_anims_with_same_id_are_finished = true;
568 for (size_t j = 0; j < active_animations_.size(); ++j) {
569 bool animation_j_will_send_or_has_received_finish_event =
570 events || active_animations_[j]->received_finished_event();
571 if (group_id == active_animations_[j]->group() &&
572 (!active_animations_[j]->is_finished() ||
573 (active_animations_[j]->run_state() == Animation::Finished &&
574 !animation_j_will_send_or_has_received_finish_event))) {
575 all_anims_with_same_id_are_finished = false;
576 break;
580 if (all_anims_with_same_id_are_finished) {
581 // We now need to remove all animations with the same group id as
582 // group_id (and send along animation finished notifications, if
583 // necessary).
584 for (size_t j = i; j < active_animations_.size(); j++) {
585 if (group_id == active_animations_[j]->group()) {
586 if (events) {
587 AnimationEvent finished_event(
588 AnimationEvent::Finished,
589 id_,
590 active_animations_[j]->group(),
591 active_animations_[j]->target_property(),
592 monotonic_time);
593 finished_event.is_impl_only = active_animations_[j]->is_impl_only();
594 events->push_back(finished_event);
596 active_animations_[j]->SetRunState(Animation::WaitingForDeletion,
597 monotonic_time);
604 static bool IsWaitingForDeletion(Animation* animation) {
605 return animation->run_state() == Animation::WaitingForDeletion;
608 void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
609 ScopedPtrVector<Animation>& animations = active_animations_;
610 animations.erase(cc::remove_if(&animations,
611 animations.begin(),
612 animations.end(),
613 IsWaitingForDeletion),
614 animations.end());
617 void LayerAnimationController::ReplaceImplThreadAnimations(
618 LayerAnimationController* controller_impl) const {
619 controller_impl->active_animations_.clear();
620 for (size_t i = 0; i < active_animations_.size(); ++i) {
621 scoped_ptr<Animation> to_add;
622 if (active_animations_[i]->needs_synchronized_start_time()) {
623 // We haven't received an animation started notification yet, so it
624 // is important that we add it in a 'waiting' and not 'running' state.
625 Animation::RunState initial_run_state =
626 Animation::WaitingForTargetAvailability;
627 double start_time = 0;
628 to_add = active_animations_[i]->CloneAndInitialize(
629 Animation::ControllingInstance,
630 initial_run_state, start_time).Pass();
631 } else {
632 to_add = active_animations_[i]->Clone(
633 Animation::ControllingInstance).Pass();
636 controller_impl->AddAnimation(to_add.Pass());
640 void LayerAnimationController::TickAnimations(double monotonic_time) {
641 for (size_t i = 0; i < active_animations_.size(); ++i) {
642 if (active_animations_[i]->run_state() == Animation::Starting ||
643 active_animations_[i]->run_state() == Animation::Running ||
644 active_animations_[i]->run_state() == Animation::Paused) {
645 double trimmed =
646 active_animations_[i]->TrimTimeToCurrentIteration(monotonic_time);
648 // Animation assumes its initial value until it gets the synchronized
649 // start time from the impl thread and can start ticking.
650 if (active_animations_[i]->needs_synchronized_start_time())
651 trimmed = 0;
653 // A just-started animation assumes its initial value.
654 if (active_animations_[i]->run_state() == Animation::Starting &&
655 !active_animations_[i]->has_set_start_time())
656 trimmed = 0;
658 switch (active_animations_[i]->target_property()) {
659 case Animation::Transform: {
660 const TransformAnimationCurve* transform_animation_curve =
661 active_animations_[i]->curve()->ToTransformAnimationCurve();
662 const gfx::Transform transform =
663 transform_animation_curve->GetValue(trimmed);
664 NotifyObserversTransformAnimated(transform);
665 break;
668 case Animation::Opacity: {
669 const FloatAnimationCurve* float_animation_curve =
670 active_animations_[i]->curve()->ToFloatAnimationCurve();
671 const float opacity = float_animation_curve->GetValue(trimmed);
672 NotifyObserversOpacityAnimated(opacity);
673 break;
676 // Do nothing for sentinel value.
677 case Animation::TargetPropertyEnumSize:
678 NOTREACHED();
684 void LayerAnimationController::UpdateActivation(UpdateActivationType type) {
685 bool force = type == ForceActivation;
686 if (registrar_) {
687 if (!active_animations_.empty() && (!is_active_ || force))
688 registrar_->DidActivateAnimationController(this);
689 else if (active_animations_.empty() && (is_active_ || force))
690 registrar_->DidDeactivateAnimationController(this);
691 is_active_ = !active_animations_.empty();
695 void LayerAnimationController::NotifyObserversOpacityAnimated(float opacity) {
696 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
697 value_observers_,
698 OnOpacityAnimated(opacity));
701 void LayerAnimationController::NotifyObserversTransformAnimated(
702 const gfx::Transform& transform) {
703 FOR_EACH_OBSERVER(LayerAnimationValueObserver,
704 value_observers_,
705 OnTransformAnimated(transform));
708 bool LayerAnimationController::HasValueObserver() {
709 if (value_observers_.might_have_observers()) {
710 ObserverListBase<LayerAnimationValueObserver>::Iterator it(
711 value_observers_);
712 return it.GetNext() != NULL;
714 return false;
717 bool LayerAnimationController::HasActiveValueObserver() {
718 if (value_observers_.might_have_observers()) {
719 ObserverListBase<LayerAnimationValueObserver>::Iterator it(
720 value_observers_);
721 LayerAnimationValueObserver* obs;
722 while ((obs = it.GetNext()) != NULL)
723 if (obs->IsActive())
724 return true;
726 return false;
729 } // namespace cc