layer_animation_controller.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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_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/Source/Platform/chromium/public/WebAnimationDelegate.h"
15#include "ui/gfx/transform.h"
16
17namespace cc {
18
19LayerAnimationController::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) {}
26
27LayerAnimationController::~LayerAnimationController() {
28  if (registrar_)
29    registrar_->UnregisterAnimationController(this);
30}
31
32scoped_refptr<LayerAnimationController> LayerAnimationController::Create(
33    int id) {
34  return make_scoped_refptr(new LayerAnimationController(id));
35}
36
37void 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());
43    }
44  }
45}
46
47struct HasAnimationId {
48  explicit HasAnimationId(int id) : id_(id) {}
49  bool operator()(Animation* animation) const {
50    return animation->id() == id_;
51  }
52
53 private:
54  int id_;
55};
56
57void 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);
65}
66
67struct 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_;
73  }
74
75 private:
76  int id_;
77  Animation::TargetProperty target_property_;
78};
79
80void 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);
91}
92
93// According to render layer backing, these are for testing only.
94void 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);
98  }
99}
100
101// Looking at GraphicsLayerCA, this appears to be the analog to
102// SuspendAnimations, which is for testing.
103void 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);
107  }
108}
109
110// Ensures that the list of active animations on the main thread and the impl
111// thread are kept in sync.
112void 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);
121
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);
126
127    PushPropertiesToImplThread(controller_impl);
128  }
129  controller_impl->UpdateActivation(NormalActivation);
130  UpdateActivation(NormalActivation);
131}
132
133void LayerAnimationController::TransferAnimationsTo(
134    LayerAnimationController* other_controller) {
135  other_controller->active_animations_.clear();
136  active_animations_.swap(other_controller->active_animations_);
137  UpdateActivation(NormalActivation);
138  set_force_sync();
139  other_controller->UpdateActivation(NormalActivation);
140  other_controller->set_force_sync();
141  other_controller->SetAnimationRegistrar(registrar_);
142}
143
144void LayerAnimationController::Animate(double monotonic_time) {
145  if (!HasActiveValueObserver())
146    return;
147
148  StartAnimationsWaitingForNextTick(monotonic_time);
149  StartAnimationsWaitingForStartTime(monotonic_time);
150  StartAnimationsWaitingForTargetAvailability(monotonic_time);
151  ResolveConflicts(monotonic_time);
152  TickAnimations(monotonic_time);
153  last_tick_time_ = monotonic_time;
154}
155
156void LayerAnimationController::AccumulatePropertyUpdates(
157    double monotonic_time,
158    AnimationEventsVector* events) {
159  if (!events)
160    return;
161
162  for (size_t i = 0; i < active_animations_.size(); ++i) {
163    Animation* animation = active_animations_[i];
164    if (!animation->is_impl_only())
165      continue;
166
167    if (animation->target_property() == Animation::Opacity) {
168      AnimationEvent event(AnimationEvent::PropertyUpdate,
169                           id_,
170                           animation->group(),
171                           Animation::Opacity,
172                           monotonic_time);
173      event.opacity = animation->curve()->ToFloatAnimationCurve()->GetValue(
174          monotonic_time);
175      event.is_impl_only = true;
176      events->push_back(event);
177    } else if (animation->target_property() == Animation::Transform) {
178      AnimationEvent event(AnimationEvent::PropertyUpdate,
179                           id_,
180                           animation->group(),
181                           Animation::Transform,
182                           monotonic_time);
183      event.transform =
184          animation->curve()->ToTransformAnimationCurve()->GetValue(
185              monotonic_time);
186      event.is_impl_only = true;
187      events->push_back(event);
188    }
189  }
190}
191
192void LayerAnimationController::UpdateState(bool start_ready_animations,
193                                           AnimationEventsVector* events) {
194  if (!HasActiveValueObserver())
195    return;
196
197  if (start_ready_animations)
198    PromoteStartedAnimations(last_tick_time_, events);
199
200  MarkFinishedAnimations(last_tick_time_);
201  MarkAnimationsForDeletion(last_tick_time_, events);
202
203  if (start_ready_animations) {
204    StartAnimationsWaitingForTargetAvailability(last_tick_time_);
205    PromoteStartedAnimations(last_tick_time_, events);
206  }
207
208  AccumulatePropertyUpdates(last_tick_time_, events);
209
210  UpdateActivation(NormalActivation);
211}
212
213void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) {
214  active_animations_.push_back(animation.Pass());
215  UpdateActivation(NormalActivation);
216}
217
218Animation* LayerAnimationController::GetAnimation(
219    int group_id,
220    Animation::TargetProperty target_property) const {
221  for (size_t i = 0; i < active_animations_.size(); ++i)
222    if (active_animations_[i]->group() == group_id &&
223        active_animations_[i]->target_property() == target_property)
224      return active_animations_[i];
225  return 0;
226}
227
228Animation* LayerAnimationController::GetAnimation(
229    Animation::TargetProperty target_property) const {
230  for (size_t i = 0; i < active_animations_.size(); ++i) {
231    size_t index = active_animations_.size() - i - 1;
232    if (active_animations_[index]->target_property() == target_property)
233      return active_animations_[index];
234  }
235  return 0;
236}
237
238bool LayerAnimationController::HasActiveAnimation() const {
239  for (size_t i = 0; i < active_animations_.size(); ++i) {
240    if (!active_animations_[i]->is_finished())
241      return true;
242  }
243  return false;
244}
245
246bool LayerAnimationController::IsAnimatingProperty(
247    Animation::TargetProperty target_property) const {
248  for (size_t i = 0; i < active_animations_.size(); ++i) {
249    if (!active_animations_[i]->is_finished() &&
250        active_animations_[i]->target_property() == target_property)
251      return true;
252  }
253  return false;
254}
255
256void LayerAnimationController::SetAnimationRegistrar(
257    AnimationRegistrar* registrar) {
258  if (registrar_ == registrar)
259    return;
260
261  if (registrar_)
262    registrar_->UnregisterAnimationController(this);
263
264  registrar_ = registrar;
265  if (registrar_)
266    registrar_->RegisterAnimationController(this);
267
268  UpdateActivation(ForceActivation);
269}
270
271void LayerAnimationController::NotifyAnimationStarted(
272    const AnimationEvent& event,
273    double wall_clock_time) {
274  if (event.is_impl_only) {
275    FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
276                      OnAnimationStarted(event));
277    if (layer_animation_delegate_)
278      layer_animation_delegate_->notifyAnimationStarted(wall_clock_time);
279
280    return;
281  }
282
283  for (size_t i = 0; i < active_animations_.size(); ++i) {
284    if (active_animations_[i]->group() == event.group_id &&
285        active_animations_[i]->target_property() == event.target_property &&
286        active_animations_[i]->needs_synchronized_start_time()) {
287      active_animations_[i]->set_needs_synchronized_start_time(false);
288      active_animations_[i]->set_start_time(event.monotonic_time);
289
290      FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
291                        OnAnimationStarted(event));
292      if (layer_animation_delegate_)
293        layer_animation_delegate_->notifyAnimationStarted(wall_clock_time);
294
295      return;
296    }
297  }
298}
299
300void LayerAnimationController::NotifyAnimationFinished(
301    const AnimationEvent& event,
302    double wall_clock_time) {
303  if (event.is_impl_only) {
304    if (layer_animation_delegate_)
305      layer_animation_delegate_->notifyAnimationFinished(wall_clock_time);
306    return;
307  }
308
309  for (size_t i = 0; i < active_animations_.size(); ++i) {
310    if (active_animations_[i]->group() == event.group_id &&
311        active_animations_[i]->target_property() == event.target_property) {
312      active_animations_[i]->set_received_finished_event(true);
313      if (layer_animation_delegate_)
314        layer_animation_delegate_->notifyAnimationFinished(wall_clock_time);
315
316      return;
317    }
318  }
319}
320
321void LayerAnimationController::NotifyAnimationPropertyUpdate(
322    const AnimationEvent& event) {
323  switch (event.target_property) {
324    case Animation::Opacity:
325      NotifyObserversOpacityAnimated(event.opacity);
326      break;
327    case Animation::Transform:
328      NotifyObserversTransformAnimated(event.transform);
329      break;
330    default:
331      NOTREACHED();
332  }
333}
334
335void LayerAnimationController::AddValueObserver(
336    LayerAnimationValueObserver* observer) {
337  if (!value_observers_.HasObserver(observer))
338    value_observers_.AddObserver(observer);
339}
340
341void LayerAnimationController::RemoveValueObserver(
342    LayerAnimationValueObserver* observer) {
343  value_observers_.RemoveObserver(observer);
344}
345
346void LayerAnimationController::AddEventObserver(
347    LayerAnimationEventObserver* observer) {
348  if (!event_observers_.HasObserver(observer))
349    event_observers_.AddObserver(observer);
350}
351
352void LayerAnimationController::RemoveEventObserver(
353    LayerAnimationEventObserver* observer) {
354  event_observers_.RemoveObserver(observer);
355}
356
357void LayerAnimationController::PushNewAnimationsToImplThread(
358    LayerAnimationController* controller_impl) const {
359  // Any new animations owned by the main thread's controller are cloned and
360  // add to the impl thread's controller.
361  for (size_t i = 0; i < active_animations_.size(); ++i) {
362    // If the animation is already running on the impl thread, there is no
363    // need to copy it over.
364    if (controller_impl->GetAnimation(active_animations_[i]->group(),
365                                      active_animations_[i]->target_property()))
366      continue;
367
368    // If the animation is not running on the impl thread, it does not
369    // necessarily mean that it needs to be copied over and started; it may
370    // have already finished. In this case, the impl thread animation will
371    // have already notified that it has started and the main thread animation
372    // will no longer need
373    // a synchronized start time.
374    if (!active_animations_[i]->needs_synchronized_start_time())
375      continue;
376
377    // The new animation should be set to run as soon as possible.
378    Animation::RunState initial_run_state =
379        Animation::WaitingForTargetAvailability;
380    double start_time = 0;
381    scoped_ptr<Animation> to_add(active_animations_[i]->CloneAndInitialize(
382        Animation::ControllingInstance, initial_run_state, start_time));
383    DCHECK(!to_add->needs_synchronized_start_time());
384    controller_impl->AddAnimation(to_add.Pass());
385  }
386}
387
388struct IsCompleted {
389  explicit IsCompleted(const LayerAnimationController& main_thread_controller)
390      : main_thread_controller_(main_thread_controller) {}
391  bool operator()(Animation* animation) const {
392    if (animation->is_impl_only()) {
393      return (animation->run_state() == Animation::WaitingForDeletion);
394    } else {
395      return !main_thread_controller_.GetAnimation(
396          animation->group(),
397          animation->target_property());
398    }
399  }
400
401 private:
402  const LayerAnimationController& main_thread_controller_;
403};
404
405void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
406    LayerAnimationController* controller_impl) const {
407  // Delete all impl thread animations for which there is no corresponding
408  // main thread animation. Each iteration,
409  // controller->active_animations_.size() is decremented or i is incremented
410  // guaranteeing progress towards loop termination.
411  ScopedPtrVector<Animation>& animations =
412      controller_impl->active_animations_;
413  animations.erase(cc::remove_if(&animations,
414                                 animations.begin(),
415                                 animations.end(),
416                                 IsCompleted(*this)),
417                   animations.end());
418}
419
420void LayerAnimationController::PushPropertiesToImplThread(
421    LayerAnimationController* controller_impl) const {
422  for (size_t i = 0; i < active_animations_.size(); ++i) {
423    Animation* current_impl =
424        controller_impl->GetAnimation(
425            active_animations_[i]->group(),
426            active_animations_[i]->target_property());
427    if (current_impl)
428      active_animations_[i]->PushPropertiesTo(current_impl);
429  }
430}
431
432void LayerAnimationController::StartAnimationsWaitingForNextTick(
433    double monotonic_time) {
434  for (size_t i = 0; i < active_animations_.size(); ++i) {
435    if (active_animations_[i]->run_state() == Animation::WaitingForNextTick)
436      active_animations_[i]->SetRunState(Animation::Starting, monotonic_time);
437  }
438}
439
440void LayerAnimationController::StartAnimationsWaitingForStartTime(
441    double monotonic_time) {
442  for (size_t i = 0; i < active_animations_.size(); ++i) {
443    if (active_animations_[i]->run_state() == Animation::WaitingForStartTime &&
444        active_animations_[i]->start_time() <= monotonic_time)
445      active_animations_[i]->SetRunState(Animation::Starting, monotonic_time);
446  }
447}
448
449void LayerAnimationController::StartAnimationsWaitingForTargetAvailability(
450    double monotonic_time) {
451  // First collect running properties.
452  TargetProperties blocked_properties;
453  for (size_t i = 0; i < active_animations_.size(); ++i) {
454    if (active_animations_[i]->run_state() == Animation::Starting ||
455        active_animations_[i]->run_state() == Animation::Running)
456      blocked_properties.insert(active_animations_[i]->target_property());
457  }
458
459  for (size_t i = 0; i < active_animations_.size(); ++i) {
460    if (active_animations_[i]->run_state() ==
461        Animation::WaitingForTargetAvailability) {
462      // Collect all properties for animations with the same group id (they
463      // should all also be in the list of animations).
464      TargetProperties enqueued_properties;
465      enqueued_properties.insert(active_animations_[i]->target_property());
466      for (size_t j = i + 1; j < active_animations_.size(); ++j) {
467        if (active_animations_[i]->group() == active_animations_[j]->group())
468          enqueued_properties.insert(active_animations_[j]->target_property());
469      }
470
471      // Check to see if intersection of the list of properties affected by
472      // the group and the list of currently blocked properties is null. In
473      // any case, the group's target properties need to be added to the list
474      // of blocked properties.
475      bool null_intersection = true;
476      for (TargetProperties::iterator p_iter = enqueued_properties.begin();
477           p_iter != enqueued_properties.end();
478           ++p_iter) {
479        if (!blocked_properties.insert(*p_iter).second)
480          null_intersection = false;
481      }
482
483      // If the intersection is null, then we are free to start the animations
484      // in the group.
485      if (null_intersection) {
486        active_animations_[i]->SetRunState(
487            Animation::Starting, monotonic_time);
488        for (size_t j = i + 1; j < active_animations_.size(); ++j) {
489          if (active_animations_[i]->group() ==
490              active_animations_[j]->group()) {
491            active_animations_[j]->SetRunState(
492                Animation::Starting, monotonic_time);
493          }
494        }
495      }
496    }
497  }
498}
499
500void LayerAnimationController::PromoteStartedAnimations(
501    double monotonic_time,
502    AnimationEventsVector* events) {
503  for (size_t i = 0; i < active_animations_.size(); ++i) {
504    if (active_animations_[i]->run_state() == Animation::Starting) {
505      active_animations_[i]->SetRunState(Animation::Running, monotonic_time);
506      if (!active_animations_[i]->has_set_start_time())
507        active_animations_[i]->set_start_time(monotonic_time);
508      if (events) {
509        AnimationEvent started_event(
510            AnimationEvent::Started,
511            id_,
512            active_animations_[i]->group(),
513            active_animations_[i]->target_property(),
514            monotonic_time);
515        started_event.is_impl_only = active_animations_[i]->is_impl_only();
516        events->push_back(started_event);
517      }
518    }
519  }
520}
521
522void LayerAnimationController::MarkFinishedAnimations(double monotonic_time) {
523  for (size_t i = 0; i < active_animations_.size(); ++i) {
524    if (active_animations_[i]->IsFinishedAt(monotonic_time) &&
525        active_animations_[i]->run_state() != Animation::WaitingForDeletion)
526      active_animations_[i]->SetRunState(Animation::Finished, monotonic_time);
527  }
528}
529
530void LayerAnimationController::ResolveConflicts(double monotonic_time) {
531  // Find any animations that are animating the same property and resolve the
532  // confict. We could eventually blend, but for now we'll just abort the
533  // previous animation (where 'previous' means: (1) has a prior start time or
534  // (2) has an equal start time, but was added to the queue earlier, i.e.,
535  // has a lower index in active_animations_).
536  for (size_t i = 0; i < active_animations_.size(); ++i) {
537    if (active_animations_[i]->run_state() == Animation::Starting ||
538        active_animations_[i]->run_state() == Animation::Running) {
539      for (size_t j = i + 1; j < active_animations_.size(); ++j) {
540        if ((active_animations_[j]->run_state() == Animation::Starting ||
541             active_animations_[j]->run_state() == Animation::Running) &&
542            active_animations_[i]->target_property() ==
543            active_animations_[j]->target_property()) {
544          if (active_animations_[i]->start_time() >
545              active_animations_[j]->start_time()) {
546            active_animations_[j]->SetRunState(Animation::Aborted,
547                                               monotonic_time);
548          } else {
549            active_animations_[i]->SetRunState(Animation::Aborted,
550                                               monotonic_time);
551          }
552        }
553      }
554    }
555  }
556}
557
558void LayerAnimationController::MarkAnimationsForDeletion(
559    double monotonic_time, AnimationEventsVector* events) {
560  // Non-aborted animations are marked for deletion after a corresponding
561  // AnimationEvent::Finished event is sent or received. This means that if
562  // we don't have an events vector, we must ensure that non-aborted animations
563  // have received a finished event before marking them for deletion.
564  for (size_t i = 0; i < active_animations_.size(); i++) {
565    int group_id = active_animations_[i]->group();
566    bool all_anims_with_same_id_are_finished = false;
567
568    // Since deleting an animation on the main thread leads to its deletion
569    // on the impl thread, we only mark a Finished main thread animation for
570    // deletion once it has received a Finished event from the impl thread.
571    bool animation_i_will_send_or_has_received_finish_event =
572        events || active_animations_[i]->received_finished_event();
573    // If an animation is finished, and not already marked for deletion,
574    // find out if all other animations in the same group are also finished.
575    if (active_animations_[i]->run_state() == Animation::Aborted ||
576        (active_animations_[i]->run_state() == Animation::Finished &&
577         animation_i_will_send_or_has_received_finish_event)) {
578      all_anims_with_same_id_are_finished = true;
579      for (size_t j = 0; j < active_animations_.size(); ++j) {
580        bool animation_j_will_send_or_has_received_finish_event =
581            events || active_animations_[j]->received_finished_event();
582        if (group_id == active_animations_[j]->group() &&
583            (!active_animations_[j]->is_finished() ||
584             (active_animations_[j]->run_state() == Animation::Finished &&
585              !animation_j_will_send_or_has_received_finish_event))) {
586          all_anims_with_same_id_are_finished = false;
587          break;
588        }
589      }
590    }
591    if (all_anims_with_same_id_are_finished) {
592      // We now need to remove all animations with the same group id as
593      // group_id (and send along animation finished notifications, if
594      // necessary).
595      for (size_t j = i; j < active_animations_.size(); j++) {
596        if (group_id == active_animations_[j]->group()) {
597          if (events) {
598            AnimationEvent finished_event(
599                AnimationEvent::Finished,
600                id_,
601                active_animations_[j]->group(),
602                active_animations_[j]->target_property(),
603                monotonic_time);
604            finished_event.is_impl_only = active_animations_[j]->is_impl_only();
605            events->push_back(finished_event);
606          }
607          active_animations_[j]->SetRunState(Animation::WaitingForDeletion,
608                                             monotonic_time);
609        }
610      }
611    }
612  }
613}
614
615static bool IsWaitingForDeletion(Animation* animation) {
616  return animation->run_state() == Animation::WaitingForDeletion;
617}
618
619void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
620  ScopedPtrVector<Animation>& animations = active_animations_;
621  animations.erase(cc::remove_if(&animations,
622                                 animations.begin(),
623                                 animations.end(),
624                                 IsWaitingForDeletion),
625                   animations.end());
626}
627
628void LayerAnimationController::ReplaceImplThreadAnimations(
629    LayerAnimationController* controller_impl) const {
630  controller_impl->active_animations_.clear();
631  for (size_t i = 0; i < active_animations_.size(); ++i) {
632    scoped_ptr<Animation> to_add;
633    if (active_animations_[i]->needs_synchronized_start_time()) {
634      // We haven't received an animation started notification yet, so it
635      // is important that we add it in a 'waiting' and not 'running' state.
636      Animation::RunState initial_run_state =
637          Animation::WaitingForTargetAvailability;
638      double start_time = 0;
639      to_add = active_animations_[i]->CloneAndInitialize(
640          Animation::ControllingInstance,
641          initial_run_state, start_time).Pass();
642    } else {
643      to_add = active_animations_[i]->Clone(
644          Animation::ControllingInstance).Pass();
645    }
646
647    controller_impl->AddAnimation(to_add.Pass());
648  }
649}
650
651void LayerAnimationController::TickAnimations(double monotonic_time) {
652  for (size_t i = 0; i < active_animations_.size(); ++i) {
653    if (active_animations_[i]->run_state() == Animation::Starting ||
654        active_animations_[i]->run_state() == Animation::Running ||
655        active_animations_[i]->run_state() == Animation::Paused) {
656      double trimmed =
657          active_animations_[i]->TrimTimeToCurrentIteration(monotonic_time);
658
659      // Animation assumes its initial value until it gets the synchronized
660      // start time from the impl thread and can start ticking.
661      if (active_animations_[i]->needs_synchronized_start_time())
662        trimmed = 0;
663
664      // A just-started animation assumes its initial value.
665      if (active_animations_[i]->run_state() == Animation::Starting &&
666          !active_animations_[i]->has_set_start_time())
667        trimmed = 0;
668
669      switch (active_animations_[i]->target_property()) {
670        case Animation::Transform: {
671          const TransformAnimationCurve* transform_animation_curve =
672              active_animations_[i]->curve()->ToTransformAnimationCurve();
673          const gfx::Transform transform =
674              transform_animation_curve->GetValue(trimmed);
675          NotifyObserversTransformAnimated(transform);
676          break;
677        }
678
679        case Animation::Opacity: {
680          const FloatAnimationCurve* float_animation_curve =
681              active_animations_[i]->curve()->ToFloatAnimationCurve();
682          const float opacity = float_animation_curve->GetValue(trimmed);
683          NotifyObserversOpacityAnimated(opacity);
684          break;
685        }
686
687          // Do nothing for sentinel value.
688        case Animation::TargetPropertyEnumSize:
689          NOTREACHED();
690      }
691    }
692  }
693}
694
695void LayerAnimationController::UpdateActivation(UpdateActivationType type) {
696  bool force = type == ForceActivation;
697  if (registrar_) {
698    if (!active_animations_.empty() && (!is_active_ || force))
699      registrar_->DidActivateAnimationController(this);
700    else if (active_animations_.empty() && (is_active_ || force))
701      registrar_->DidDeactivateAnimationController(this);
702    is_active_ = !active_animations_.empty();
703  }
704}
705
706void LayerAnimationController::NotifyObserversOpacityAnimated(float opacity) {
707  FOR_EACH_OBSERVER(LayerAnimationValueObserver,
708                    value_observers_,
709                    OnOpacityAnimated(opacity));
710}
711
712void LayerAnimationController::NotifyObserversTransformAnimated(
713    const gfx::Transform& transform) {
714  FOR_EACH_OBSERVER(LayerAnimationValueObserver,
715                    value_observers_,
716                    OnTransformAnimated(transform));
717}
718
719bool LayerAnimationController::HasActiveValueObserver() {
720  if (value_observers_.might_have_observers()) {
721    ObserverListBase<LayerAnimationValueObserver>::Iterator it(
722        value_observers_);
723    LayerAnimationValueObserver* obs;
724    while ((obs = it.GetNext()) != NULL)
725      if (obs->IsActive())
726        return true;
727  }
728  return false;
729}
730
731}  // namespace cc
732