layer_animation_controller.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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
21namespace cc {
22
23LayerAnimationController::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
31LayerAnimationController::~LayerAnimationController() {
32  if (registrar_)
33    registrar_->UnregisterAnimationController(this);
34}
35
36scoped_refptr<LayerAnimationController> LayerAnimationController::Create(
37    int id) {
38  return make_scoped_refptr(new LayerAnimationController(id));
39}
40
41void 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
51struct HasAnimationId {
52  explicit HasAnimationId(int id) : id_(id) {}
53  bool operator()(Animation* animation) const {
54    return animation->id() == id_;
55  }
56
57 private:
58  int id_;
59};
60
61void 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
71struct 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_;
77  }
78
79 private:
80  int id_;
81  Animation::TargetProperty target_property_;
82};
83
84void 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
97void 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.
108void 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
126void 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
136void 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
203void 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
224void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) {
225  active_animations_.push_back(animation.Pass());
226  UpdateActivation(NormalActivation);
227}
228
229Animation* 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
239Animation* 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
249bool 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
257bool 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
267void 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
282void 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
315void 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
340void 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
351void 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
365void LayerAnimationController::AddValueObserver(
366    LayerAnimationValueObserver* observer) {
367  if (!value_observers_.HasObserver(observer))
368    value_observers_.AddObserver(observer);
369}
370
371void LayerAnimationController::RemoveValueObserver(
372    LayerAnimationValueObserver* observer) {
373  value_observers_.RemoveObserver(observer);
374}
375
376void LayerAnimationController::AddEventObserver(
377    LayerAnimationEventObserver* observer) {
378  if (!event_observers_.HasObserver(observer))
379    event_observers_.AddObserver(observer);
380}
381
382void LayerAnimationController::RemoveEventObserver(
383    LayerAnimationEventObserver* observer) {
384  event_observers_.RemoveObserver(observer);
385}
386
387bool 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
412void 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
458struct IsCompleted {
459  explicit IsCompleted(const LayerAnimationController& main_thread_controller)
460      : main_thread_controller_(main_thread_controller) {}
461  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
475void 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
490void 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
502void 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
552void 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
574void 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
583void 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
661static bool IsWaitingForDeletion(Animation* animation) {
662  return animation->run_state() == Animation::WaitingForDeletion;
663}
664
665void 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
674void 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
731void 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
750void LayerAnimationController::NotifyObserversOpacityAnimated(float opacity) {
751  FOR_EACH_OBSERVER(LayerAnimationValueObserver,
752                    value_observers_,
753                    OnOpacityAnimated(opacity));
754}
755
756void LayerAnimationController::NotifyObserversTransformAnimated(
757    const gfx::Transform& transform) {
758  FOR_EACH_OBSERVER(LayerAnimationValueObserver,
759                    value_observers_,
760                    OnTransformAnimated(transform));
761}
762
763void LayerAnimationController::NotifyObserversFilterAnimated(
764    const FilterOperations& filters) {
765  FOR_EACH_OBSERVER(LayerAnimationValueObserver,
766                    value_observers_,
767                    OnFilterAnimated(filters));
768}
769
770void LayerAnimationController::NotifyObserversScrollOffsetAnimated(
771    gfx::Vector2dF scroll_offset) {
772  FOR_EACH_OBSERVER(LayerAnimationValueObserver,
773                    value_observers_,
774                    OnScrollOffsetAnimated(scroll_offset));
775}
776
777void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() {
778  FOR_EACH_OBSERVER(LayerAnimationValueObserver,
779                    value_observers_,
780                    OnAnimationWaitingForDeletion());
781}
782
783bool 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
792bool 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