12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/animation/layer_animation_controller.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm>
81675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch#include <vector>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/animation/animation.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "cc/animation/animation_delegate.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/animation/animation_registrar.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/animation/keyframed_animation_curve.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/animation/layer_animation_value_observer.h"
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "cc/animation/layer_animation_value_provider.h"
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "cc/animation/scroll_offset_animation_curve.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/base/scoped_ptr_algorithm.h"
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "cc/output/filter_operations.h"
193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/gfx/box_f.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/transform.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LayerAnimationController::LayerAnimationController(int id)
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : registrar_(0),
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      id_(id),
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      is_active_(false),
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      value_provider_(NULL),
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      layer_animation_delegate_(NULL),
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      needs_to_start_animations_(false) {
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LayerAnimationController::~LayerAnimationController() {
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (registrar_)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    registrar_->UnregisterAnimationController(this);
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<LayerAnimationController> LayerAnimationController::Create(
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int id) {
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return make_scoped_refptr(new LayerAnimationController(id));
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LayerAnimationController::PauseAnimation(int animation_id,
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                              base::TimeDelta time_offset) {
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->id() == animation_id) {
475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      animations_[i]->SetRunState(Animation::Paused,
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  time_offset + animations_[i]->start_time());
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct HasAnimationId {
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  explicit HasAnimationId(int id) : id_(id) {}
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool operator()(Animation* animation) const {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return animation->id() == id_;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int id_;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LayerAnimationController::RemoveAnimation(int animation_id) {
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  animations_.erase(cc::remove_if(&animations_,
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  animations_.begin(),
665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  animations_.end(),
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  HasAnimationId(animation_id)),
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                    animations_.end());
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateActivation(NormalActivation);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct HasAnimationIdAndProperty {
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HasAnimationIdAndProperty(int id, Animation::TargetProperty target_property)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : id_(id), target_property_(target_property) {}
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool operator()(Animation* animation) const {
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return animation->id() == id_ &&
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        animation->target_property() == target_property_;
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int id_;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Animation::TargetProperty target_property_;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LayerAnimationController::RemoveAnimation(
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int animation_id,
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Animation::TargetProperty target_property) {
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  animations_.erase(
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      cc::remove_if(&animations_,
905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                    animations_.begin(),
915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                    animations_.end(),
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                    HasAnimationIdAndProperty(animation_id, target_property)),
935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      animations_.end());
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateActivation(NormalActivation);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void LayerAnimationController::AbortAnimations(
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Animation::TargetProperty target_property) {
995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->target_property() == target_property &&
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        !animations_[i]->is_finished())
1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      animations_[i]->SetRunState(Animation::Aborted, last_tick_time_);
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Ensures that the list of active animations on the main thread and the impl
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// thread are kept in sync.
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LayerAnimationController::PushAnimationUpdatesTo(
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LayerAnimationController* controller_impl) {
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(this != controller_impl);
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!has_any_animation() && !controller_impl->has_any_animation())
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PurgeAnimationsMarkedForDeletion();
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PushNewAnimationsToImplThread(controller_impl);
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Remove finished impl side animations only after pushing,
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // and only after the animations are deleted on the main thread
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // this insures we will never push an animation twice.
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  RemoveAnimationsCompletedOnMainThread(controller_impl);
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PushPropertiesToImplThread(controller_impl);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  controller_impl->UpdateActivation(NormalActivation);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateActivation(NormalActivation);
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LayerAnimationController::Animate(base::TimeTicks monotonic_time) {
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!monotonic_time.is_null());
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!HasValueObserver())
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (needs_to_start_animations_)
132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    StartAnimations(monotonic_time);
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TickAnimations(monotonic_time);
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  last_tick_time_ = monotonic_time;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LayerAnimationController::AccumulatePropertyUpdates(
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::TimeTicks monotonic_time,
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AnimationEventsVector* events) {
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!events)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
1445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    Animation* animation = animations_[i];
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!animation->is_impl_only())
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!animation->InEffect(monotonic_time))
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      continue;
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    double trimmed = animation->TrimTimeToCurrentIteration(monotonic_time);
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    switch (animation->target_property()) {
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      case Animation::Opacity: {
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        AnimationEvent event(AnimationEvent::PropertyUpdate,
1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             id_,
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             animation->group(),
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             Animation::Opacity,
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             monotonic_time);
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        const FloatAnimationCurve* float_animation_curve =
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            animation->curve()->ToFloatAnimationCurve();
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        event.opacity = float_animation_curve->GetValue(trimmed);
1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        event.is_impl_only = true;
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        events->push_back(event);
1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        break;
1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      case Animation::Transform: {
1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        AnimationEvent event(AnimationEvent::PropertyUpdate,
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             id_,
1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             animation->group(),
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             Animation::Transform,
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             monotonic_time);
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        const TransformAnimationCurve* transform_animation_curve =
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            animation->curve()->ToTransformAnimationCurve();
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        event.transform = transform_animation_curve->GetValue(trimmed);
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        event.is_impl_only = true;
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        events->push_back(event);
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        break;
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      case Animation::Filter: {
1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        AnimationEvent event(AnimationEvent::PropertyUpdate,
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             id_,
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             animation->group(),
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             Animation::Filter,
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             monotonic_time);
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        const FilterAnimationCurve* filter_animation_curve =
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            animation->curve()->ToFilterAnimationCurve();
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        event.filters = filter_animation_curve->GetValue(trimmed);
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        event.is_impl_only = true;
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        events->push_back(event);
1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        break;
1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      case Animation::BackgroundColor: { break; }
1961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case Animation::ScrollOffset: {
198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // Impl-side changes to scroll offset are already sent back to the
199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // main thread (e.g. for user-driven scrolling), so a PropertyUpdate
200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // isn't needed.
201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        break;
202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      }
203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      case Animation::TargetPropertyEnumSize:
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        NOTREACHED();
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void LayerAnimationController::UpdateState(bool start_ready_animations,
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           AnimationEventsVector* events) {
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!HasActiveValueObserver())
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(last_tick_time_ != base::TimeTicks());
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (start_ready_animations)
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PromoteStartedAnimations(last_tick_time_, events);
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MarkFinishedAnimations(last_tick_time_);
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MarkAnimationsForDeletion(last_tick_time_, events);
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
222010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (needs_to_start_animations_ && start_ready_animations) {
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    StartAnimations(last_tick_time_);
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PromoteStartedAnimations(last_tick_time_, events);
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AccumulatePropertyUpdates(last_tick_time_, events);
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateActivation(NormalActivation);
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustruct AffectsNoObservers {
2335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool operator()(Animation* animation) const {
2345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return !animation->affects_active_observers() &&
2355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu           !animation->affects_pending_observers();
2365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
2385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid LayerAnimationController::ActivateAnimations() {
2405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
2415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    animations_[i]->set_affects_active_observers(
2425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->affects_pending_observers());
2435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
2445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  animations_.erase(cc::remove_if(&animations_,
2455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  animations_.begin(),
2465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  animations_.end(),
2475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  AffectsNoObservers()),
2485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                    animations_.end());
2495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  UpdateActivation(NormalActivation);
2505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) {
2535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  animations_.push_back(animation.Pass());
254010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  needs_to_start_animations_ = true;
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateActivation(NormalActivation);
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Animation* LayerAnimationController::GetAnimation(
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int group_id,
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Animation::TargetProperty target_property) const {
2615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i)
2625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->group() == group_id &&
2635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->target_property() == target_property)
2645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return animations_[i];
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Animation* LayerAnimationController::GetAnimation(
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Animation::TargetProperty target_property) const {
2705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
2715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    size_t index = animations_.size() - i - 1;
2725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[index]->target_property() == target_property)
2735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return animations_[index];
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LayerAnimationController::HasActiveAnimation() const {
2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
2805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (!animations_[i]->is_finished())
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LayerAnimationController::IsAnimatingProperty(
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Animation::TargetProperty target_property) const {
2885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
2895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (!animations_[i]->is_finished() &&
290ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch        animations_[i]->InEffect(last_tick_time_) &&
2915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->target_property() == target_property)
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void LayerAnimationController::SetAnimationRegistrar(
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    AnimationRegistrar* registrar) {
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (registrar_ == registrar)
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (registrar_)
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    registrar_->UnregisterAnimationController(this);
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  registrar_ = registrar;
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (registrar_)
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    registrar_->RegisterAnimationController(this);
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  UpdateActivation(ForceActivation);
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void LayerAnimationController::NotifyAnimationStarted(
313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const AnimationEvent& event) {
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (event.is_impl_only) {
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      OnAnimationStarted(event));
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (layer_animation_delegate_)
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      layer_animation_delegate_->NotifyAnimationStarted(event.monotonic_time,
319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                        event.target_property);
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
3245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->group() == event.group_id &&
3255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->target_property() == event.target_property &&
3265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->needs_synchronized_start_time()) {
3275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      animations_[i]->set_needs_synchronized_start_time(false);
3285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (!animations_[i]->has_set_start_time())
3295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->set_start_time(event.monotonic_time);
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        OnAnimationStarted(event));
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (layer_animation_delegate_)
334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        layer_animation_delegate_->NotifyAnimationStarted(
335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            event.monotonic_time, event.target_property);
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void LayerAnimationController::NotifyAnimationFinished(
343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const AnimationEvent& event) {
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (event.is_impl_only) {
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (layer_animation_delegate_)
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      layer_animation_delegate_->NotifyAnimationFinished(event.monotonic_time,
347a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                         event.target_property);
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
3525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->group() == event.group_id &&
3535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->target_property() == event.target_property) {
3545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      animations_[i]->set_received_finished_event(true);
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (layer_animation_delegate_)
356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        layer_animation_delegate_->NotifyAnimationFinished(
357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            event.monotonic_time, event.target_property);
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void LayerAnimationController::NotifyAnimationAborted(
365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const AnimationEvent& event) {
3665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
3675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->group() == event.group_id &&
3685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->target_property() == event.target_property) {
3695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      animations_[i]->SetRunState(Animation::Aborted, event.monotonic_time);
370f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
371f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void LayerAnimationController::NotifyAnimationPropertyUpdate(
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const AnimationEvent& event) {
3765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool notify_active_observers = true;
3775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool notify_pending_observers = true;
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (event.target_property) {
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case Animation::Opacity:
3805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      NotifyObserversOpacityAnimated(
3815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          event.opacity, notify_active_observers, notify_pending_observers);
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case Animation::Transform:
3845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      NotifyObserversTransformAnimated(
3855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          event.transform, notify_active_observers, notify_pending_observers);
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    default:
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      NOTREACHED();
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void LayerAnimationController::AddValueObserver(
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LayerAnimationValueObserver* observer) {
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!value_observers_.HasObserver(observer))
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    value_observers_.AddObserver(observer);
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void LayerAnimationController::RemoveValueObserver(
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LayerAnimationValueObserver* observer) {
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  value_observers_.RemoveObserver(observer);
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void LayerAnimationController::AddEventObserver(
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LayerAnimationEventObserver* observer) {
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!event_observers_.HasObserver(observer))
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    event_observers_.AddObserver(observer);
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void LayerAnimationController::RemoveEventObserver(
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LayerAnimationEventObserver* observer) {
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  event_observers_.RemoveObserver(observer);
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool LayerAnimationController::HasFilterAnimationThatInflatesBounds() const {
4155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
4165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (!animations_[i]->is_finished() &&
4175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->target_property() == Animation::Filter &&
4185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            ->curve()
4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            ->ToFilterAnimationCurve()
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            ->HasFilterThatMovesPixels())
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return true;
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return false;
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool LayerAnimationController::HasTransformAnimationThatInflatesBounds() const {
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return IsAnimatingProperty(Animation::Transform);
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool LayerAnimationController::FilterAnimationBoundsForBox(
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const gfx::BoxF& box, gfx::BoxF* bounds) const {
4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(avallee): Implement.
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return false;
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool LayerAnimationController::TransformAnimationBoundsForBox(
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const gfx::BoxF& box,
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gfx::BoxF* bounds) const {
4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(HasTransformAnimationThatInflatesBounds())
4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      << "TransformAnimationBoundsForBox will give incorrect results if there "
4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      << "are no transform animations affecting bounds, non-animated transform "
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      << "is not known";
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Compute bounds based on animations for which is_finished() is false.
4473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Do nothing if there are no such animations; in this case, it is assumed
4483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // that callers will take care of computing bounds based on the owning layer's
4493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // actual transform.
4503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *bounds = gfx::BoxF();
4515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
4525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->is_finished() ||
4535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->target_property() != Animation::Transform)
4543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      continue;
4553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const TransformAnimationCurve* transform_animation_curve =
4575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->curve()->ToTransformAnimationCurve();
4583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    gfx::BoxF animation_bounds;
4593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    bool success =
4603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        transform_animation_curve->AnimatedBoundsForBox(box, &animation_bounds);
4613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (!success)
4623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return false;
4633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    bounds->Union(animation_bounds);
4643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
4653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return true;
4673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
469e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbool LayerAnimationController::HasAnimationThatAffectsScale() const {
4705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
4715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->is_finished() ||
4725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->target_property() != Animation::Transform)
473e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      continue;
474e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
475e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const TransformAnimationCurve* transform_animation_curve =
4765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->curve()->ToTransformAnimationCurve();
477e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (transform_animation_curve->AffectsScale())
478e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      return true;
479e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
480e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
481e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return false;
482e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
483e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
484c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool LayerAnimationController::HasOnlyTranslationTransforms() const {
4855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
4865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->is_finished() ||
4875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->target_property() != Animation::Transform)
488c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      continue;
489c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
490c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const TransformAnimationCurve* transform_animation_curve =
4915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->curve()->ToTransformAnimationCurve();
492c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (!transform_animation_curve->IsTranslation())
493c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return false;
494c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
495c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
496c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return true;
497c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
498c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
4991675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdochbool LayerAnimationController::MaximumTargetScale(float* max_scale) const {
500c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  *max_scale = 0.f;
5015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
5025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->is_finished() ||
5035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->target_property() != Animation::Transform)
504c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      continue;
505c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
5061675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    bool forward_direction = true;
5071675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    switch (animations_[i]->direction()) {
5081675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      case Animation::Normal:
5091675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      case Animation::Alternate:
5101675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        forward_direction = animations_[i]->playback_rate() >= 0.0;
5111675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        break;
5121675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      case Animation::Reverse:
5131675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      case Animation::AlternateReverse:
5141675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        forward_direction = animations_[i]->playback_rate() < 0.0;
5151675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        break;
5161675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    }
5171675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch
518c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const TransformAnimationCurve* transform_animation_curve =
5195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->curve()->ToTransformAnimationCurve();
520c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    float animation_scale = 0.f;
5211675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    if (!transform_animation_curve->MaximumTargetScale(forward_direction,
5221675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch                                                       &animation_scale))
523c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return false;
524c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    *max_scale = std::max(*max_scale, animation_scale);
525c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
526c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
527c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return true;
528c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
529c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LayerAnimationController::PushNewAnimationsToImplThread(
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LayerAnimationController* controller_impl) const {
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Any new animations owned by the main thread's controller are cloned and
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // add to the impl thread's controller.
5345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If the animation is already running on the impl thread, there is no
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // need to copy it over.
5375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (controller_impl->GetAnimation(animations_[i]->group(),
5385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                      animations_[i]->target_property()))
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If the animation is not running on the impl thread, it does not
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // necessarily mean that it needs to be copied over and started; it may
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // have already finished. In this case, the impl thread animation will
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // have already notified that it has started and the main thread animation
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // will no longer need
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // a synchronized start time.
5475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (!animations_[i]->needs_synchronized_start_time())
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
550a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Scroll animations always start at the current scroll offset.
5515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->target_property() == Animation::ScrollOffset) {
552a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      gfx::Vector2dF current_scroll_offset;
553a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (controller_impl->value_provider_) {
554a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        current_scroll_offset =
555a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            controller_impl->value_provider_->ScrollOffsetForAnimation();
556a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      } else {
557a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // The owning layer isn't yet in the active tree, so the main thread
558a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // scroll offset will be up-to-date.
559a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        current_scroll_offset = value_provider_->ScrollOffsetForAnimation();
560a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      }
5615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      animations_[i]->curve()->ToScrollOffsetAnimationCurve()->SetInitialValue(
5625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          current_scroll_offset);
563a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
564a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The new animation should be set to run as soon as possible.
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Animation::RunState initial_run_state =
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        Animation::WaitingForTargetAvailability;
5685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    scoped_ptr<Animation> to_add(
5695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->CloneAndInitialize(initial_run_state));
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!to_add->needs_synchronized_start_time());
5715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    to_add->set_affects_active_observers(false);
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    controller_impl->AddAnimation(to_add.Pass());
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic bool IsCompleted(
5775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    Animation* animation,
5785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const LayerAnimationController* main_thread_controller) {
5795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (animation->is_impl_only()) {
5805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return (animation->run_state() == Animation::WaitingForDeletion);
5815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  } else {
5825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return !main_thread_controller->GetAnimation(animation->group(),
5835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                 animation->target_property());
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic bool AffectsActiveOnlyAndIsWaitingForDeletion(Animation* animation) {
5885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return animation->run_state() == Animation::WaitingForDeletion &&
5895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         !animation->affects_pending_observers();
5905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LayerAnimationController* controller_impl) const {
5945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Animations removed on the main thread should no longer affect pending
5955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // observers, and should stop affecting active observers after the next call
5965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // to ActivateAnimations. If already WaitingForDeletion, they can be removed
5975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // immediately.
5985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ScopedPtrVector<Animation>& animations = controller_impl->animations_;
5995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations.size(); ++i) {
6005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (IsCompleted(animations[i], this))
6015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      animations[i]->set_affects_pending_observers(false);
6025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  animations.erase(cc::remove_if(&animations,
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 animations.begin(),
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 animations.end(),
6065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                 AffectsActiveOnlyAndIsWaitingForDeletion),
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   animations.end());
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LayerAnimationController::PushPropertiesToImplThread(
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LayerAnimationController* controller_impl) const {
6125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
6135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    Animation* current_impl = controller_impl->GetAnimation(
6145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->group(), animations_[i]->target_property());
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (current_impl)
6165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      animations_[i]->PushPropertiesTo(current_impl);
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
620cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LayerAnimationController::StartAnimations(base::TimeTicks monotonic_time) {
621010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(needs_to_start_animations_);
622010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  needs_to_start_animations_ = false;
6235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // First collect running properties affecting each type of observer.
6245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  TargetProperties blocked_properties_for_active_observers;
6255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  TargetProperties blocked_properties_for_pending_observers;
6265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<size_t> animations_waiting_for_target;
6275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  animations_waiting_for_target.reserve(animations_.size());
6295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
6305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->run_state() == Animation::Starting ||
6315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->run_state() == Animation::Running) {
6325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (animations_[i]->affects_active_observers()) {
6335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        blocked_properties_for_active_observers.insert(
6345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            animations_[i]->target_property());
6355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
6365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (animations_[i]->affects_pending_observers()) {
6375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        blocked_properties_for_pending_observers.insert(
6385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            animations_[i]->target_property());
6395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      }
6405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else if (animations_[i]->run_state() ==
6415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               Animation::WaitingForTargetAvailability) {
6425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      animations_waiting_for_target.push_back(i);
6435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (size_t i = 0; i < animations_waiting_for_target.size(); ++i) {
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Collect all properties for animations with the same group id (they
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // should all also be in the list of animations).
6495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size_t animation_index = animations_waiting_for_target[i];
6505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Animation* animation_waiting_for_target = animations_[animation_index];
6515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Check for the run state again even though the animation was waiting
6525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // for target because it might have changed the run state while handling
6535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // previous animation in this loop (if they belong to same group).
6545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (animation_waiting_for_target->run_state() ==
6555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        Animation::WaitingForTargetAvailability) {
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TargetProperties enqueued_properties;
6575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      bool affects_active_observers =
6585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          animation_waiting_for_target->affects_active_observers();
6595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      bool affects_pending_observers =
6605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          animation_waiting_for_target->affects_pending_observers();
6615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      enqueued_properties.insert(
6625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          animation_waiting_for_target->target_property());
6635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      for (size_t j = animation_index + 1; j < animations_.size(); ++j) {
6645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (animation_waiting_for_target->group() == animations_[j]->group()) {
6655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          enqueued_properties.insert(animations_[j]->target_property());
6665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          affects_active_observers |=
6675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              animations_[j]->affects_active_observers();
6685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          affects_pending_observers |=
6695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              animations_[j]->affects_pending_observers();
6705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        }
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Check to see if intersection of the list of properties affected by
6745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // the group and the list of currently blocked properties is null, taking
6755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // into account the type(s) of observers affected by the group. In any
6765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // case, the group's target properties need to be added to the lists of
6775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      // blocked properties.
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool null_intersection = true;
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (TargetProperties::iterator p_iter = enqueued_properties.begin();
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           p_iter != enqueued_properties.end();
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           ++p_iter) {
6825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        if (affects_active_observers &&
6835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            !blocked_properties_for_active_observers.insert(*p_iter).second)
6845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          null_intersection = false;
6855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        if (affects_pending_observers &&
6865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            !blocked_properties_for_pending_observers.insert(*p_iter).second)
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          null_intersection = false;
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If the intersection is null, then we are free to start the animations
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // in the group.
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (null_intersection) {
6935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        animation_waiting_for_target->SetRunState(Animation::Starting,
6945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                  monotonic_time);
6955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        for (size_t j = animation_index + 1; j < animations_.size(); ++j) {
6965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          if (animation_waiting_for_target->group() ==
6975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              animations_[j]->group()) {
6985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            animations_[j]->SetRunState(Animation::Starting, monotonic_time);
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
701010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      } else {
702010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        needs_to_start_animations_ = true;
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LayerAnimationController::PromoteStartedAnimations(
709cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::TimeTicks monotonic_time,
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AnimationEventsVector* events) {
7115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
7125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->run_state() == Animation::Starting &&
7135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->affects_active_observers()) {
7145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      animations_[i]->SetRunState(Animation::Running, monotonic_time);
7155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (!animations_[i]->has_set_start_time() &&
7165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          !animations_[i]->needs_synchronized_start_time())
7175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->set_start_time(monotonic_time);
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (events) {
7195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        AnimationEvent started_event(AnimationEvent::Started,
7205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     id_,
7215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     animations_[i]->group(),
7225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     animations_[i]->target_property(),
7235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     monotonic_time);
7245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        started_event.is_impl_only = animations_[i]->is_impl_only();
725116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        if (started_event.is_impl_only)
726116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          NotifyAnimationStarted(started_event);
727116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        else
728116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          events->push_back(started_event);
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
734cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LayerAnimationController::MarkFinishedAnimations(
735cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::TimeTicks monotonic_time) {
7365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
7375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->IsFinishedAt(monotonic_time) &&
7385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->run_state() != Animation::Aborted &&
7395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->run_state() != Animation::WaitingForDeletion)
7405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      animations_[i]->SetRunState(Animation::Finished, monotonic_time);
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LayerAnimationController::MarkAnimationsForDeletion(
745cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::TimeTicks monotonic_time,
746cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    AnimationEventsVector* events) {
747f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool marked_animations_for_deletions = false;
7485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<size_t> animations_with_same_group_id;
749f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  animations_with_same_group_id.reserve(animations_.size());
751c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Non-aborted animations are marked for deletion after a corresponding
752c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // AnimationEvent::Finished event is sent or received. This means that if
753c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // we don't have an events vector, we must ensure that non-aborted animations
754c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // have received a finished event before marking them for deletion.
7555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); i++) {
7565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    int group_id = animations_[i]->group();
7575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->run_state() == Animation::Aborted) {
7585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (events && !animations_[i]->is_impl_only()) {
7595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        AnimationEvent aborted_event(AnimationEvent::Aborted,
7605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     id_,
7615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     group_id,
7625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     animations_[i]->target_property(),
7635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                     monotonic_time);
764f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        events->push_back(aborted_event);
765f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
7665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      animations_[i]->SetRunState(Animation::WaitingForDeletion,
7675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  monotonic_time);
768f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      marked_animations_for_deletions = true;
769f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      continue;
770f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
771f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool all_anims_with_same_id_are_finished = false;
773c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
774c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Since deleting an animation on the main thread leads to its deletion
775c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // on the impl thread, we only mark a Finished main thread animation for
776c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // deletion once it has received a Finished event from the impl thread.
777c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool animation_i_will_send_or_has_received_finish_event =
7785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        events || animations_[i]->received_finished_event();
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If an animation is finished, and not already marked for deletion,
780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // find out if all other animations in the same group are also finished.
7815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->run_state() == Animation::Finished &&
782f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        animation_i_will_send_or_has_received_finish_event) {
7835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // Clear the animations_with_same_group_id if it was added for
7845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      // the previous animation's iteration.
7855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (animations_with_same_group_id.size() > 0)
7865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        animations_with_same_group_id.clear();
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      all_anims_with_same_id_are_finished = true;
7885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      for (size_t j = 0; j < animations_.size(); ++j) {
789c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        bool animation_j_will_send_or_has_received_finish_event =
7905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            events || animations_[j]->received_finished_event();
7915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (group_id == animations_[j]->group()) {
7925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          if (!animations_[j]->is_finished() ||
7935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              (animations_[j]->run_state() == Animation::Finished &&
7945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               !animation_j_will_send_or_has_received_finish_event)) {
7955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            all_anims_with_same_id_are_finished = false;
7965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            break;
7975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          } else if (j >= i &&
7985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     animations_[j]->run_state() != Animation::Aborted) {
7995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // Mark down the animations which belong to the same group
8005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // and is not yet aborted. If this current iteration finds that all
8015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // animations with same ID are finished, then the marked
8025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // animations below will be set to WaitingForDeletion in next
8035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            // iteration.
8045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            animations_with_same_group_id.push_back(j);
8055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          }
8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (all_anims_with_same_id_are_finished) {
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // We now need to remove all animations with the same group id as
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // group_id (and send along animation finished notifications, if
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // necessary).
8135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      for (size_t j = 0; j < animations_with_same_group_id.size(); j++) {
8145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        size_t animation_index = animations_with_same_group_id[j];
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (events) {
8165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            AnimationEvent finished_event(
8175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                AnimationEvent::Finished,
8185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                id_,
8195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                animations_[animation_index]->group(),
8205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                animations_[animation_index]->target_property(),
8215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                monotonic_time);
8225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            finished_event.is_impl_only =
8235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                animations_[animation_index]->is_impl_only();
824116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            if (finished_event.is_impl_only)
825116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              NotifyAnimationFinished(finished_event);
826116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            else
827116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              events->push_back(finished_event);
8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
8295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          animations_[animation_index]->SetRunState(
8305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              Animation::WaitingForDeletion, monotonic_time);
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
832f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      marked_animations_for_deletions = true;
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
835f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (marked_animations_for_deletions)
836f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    NotifyObserversAnimationWaitingForDeletion();
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static bool IsWaitingForDeletion(Animation* animation) {
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return animation->run_state() == Animation::WaitingForDeletion;
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
8445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  animations_.erase(cc::remove_if(&animations_,
8455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  animations_.begin(),
8465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  animations_.end(),
8475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                  IsWaitingForDeletion),
8485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                    animations_.end());
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
851cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void LayerAnimationController::TickAnimations(base::TimeTicks monotonic_time) {
8525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i < animations_.size(); ++i) {
8535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (animations_[i]->run_state() == Animation::Starting ||
8545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->run_state() == Animation::Running ||
8555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        animations_[i]->run_state() == Animation::Paused) {
8561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (!animations_[i]->InEffect(monotonic_time))
8571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        continue;
8581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      double trimmed =
8605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          animations_[i]->TrimTimeToCurrentIteration(monotonic_time);
8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      switch (animations_[i]->target_property()) {
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case Animation::Transform: {
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          const TransformAnimationCurve* transform_animation_curve =
8655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              animations_[i]->curve()->ToTransformAnimationCurve();
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          const gfx::Transform transform =
8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              transform_animation_curve->GetValue(trimmed);
8685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          NotifyObserversTransformAnimated(
8695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              transform,
8705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              animations_[i]->affects_active_observers(),
8715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              animations_[i]->affects_pending_observers());
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case Animation::Opacity: {
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          const FloatAnimationCurve* float_animation_curve =
8775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              animations_[i]->curve()->ToFloatAnimationCurve();
8786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          const float opacity = std::max(
8796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              std::min(float_animation_curve->GetValue(trimmed), 1.0f), 0.f);
8805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          NotifyObserversOpacityAnimated(
8815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              opacity,
8825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              animations_[i]->affects_active_observers(),
8835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              animations_[i]->affects_pending_observers());
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        case Animation::Filter: {
8884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          const FilterAnimationCurve* filter_animation_curve =
8895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              animations_[i]->curve()->ToFilterAnimationCurve();
8904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          const FilterOperations filter =
8914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)              filter_animation_curve->GetValue(trimmed);
8925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          NotifyObserversFilterAnimated(
8935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              filter,
8945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              animations_[i]->affects_active_observers(),
8955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              animations_[i]->affects_pending_observers());
8964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          break;
8974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        }
8984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        case Animation::BackgroundColor: {
9001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          // Not yet implemented.
9011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          break;
9021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        }
9031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
904a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        case Animation::ScrollOffset: {
905a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
9065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              animations_[i]->curve()->ToScrollOffsetAnimationCurve();
907a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          const gfx::Vector2dF scroll_offset =
908a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              scroll_offset_animation_curve->GetValue(trimmed);
9095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          NotifyObserversScrollOffsetAnimated(
9105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              scroll_offset,
9115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              animations_[i]->affects_active_observers(),
9125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              animations_[i]->affects_pending_observers());
913a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          break;
914a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        }
915a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
9164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        // Do nothing for sentinel value.
9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case Animation::TargetPropertyEnumSize:
9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          NOTREACHED();
9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LayerAnimationController::UpdateActivation(UpdateActivationType type) {
9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool force = type == ForceActivation;
9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (registrar_) {
927f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool was_active = is_active_;
928f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    is_active_ = false;
9295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    for (size_t i = 0; i < animations_.size(); ++i) {
9305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      if (animations_[i]->run_state() != Animation::WaitingForDeletion) {
931f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        is_active_ = true;
932f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        break;
933f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
934f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
935f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
936f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (is_active_ && (!was_active || force))
9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      registrar_->DidActivateAnimationController(this);
938f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    else if (!is_active_ && (was_active || force))
9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      registrar_->DidDeactivateAnimationController(this);
9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid LayerAnimationController::NotifyObserversOpacityAnimated(
9445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    float opacity,
9455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    bool notify_active_observers,
9465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    bool notify_pending_observers) {
9475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (value_observers_.might_have_observers()) {
9485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ObserverListBase<LayerAnimationValueObserver>::Iterator it(
9495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        value_observers_);
9505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    LayerAnimationValueObserver* obs;
9515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    while ((obs = it.GetNext()) != NULL) {
9525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if ((notify_active_observers && notify_pending_observers) ||
9535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          (notify_active_observers && obs->IsActive()) ||
9545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          (notify_pending_observers && !obs->IsActive()))
9555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        obs->OnOpacityAnimated(opacity);
9565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
9575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LayerAnimationController::NotifyObserversTransformAnimated(
9615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const gfx::Transform& transform,
9625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    bool notify_active_observers,
9635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    bool notify_pending_observers) {
9645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (value_observers_.might_have_observers()) {
9655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ObserverListBase<LayerAnimationValueObserver>::Iterator it(
9665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        value_observers_);
9675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    LayerAnimationValueObserver* obs;
9685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    while ((obs = it.GetNext()) != NULL) {
9695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if ((notify_active_observers && notify_pending_observers) ||
9705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          (notify_active_observers && obs->IsActive()) ||
9715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          (notify_pending_observers && !obs->IsActive()))
9725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        obs->OnTransformAnimated(transform);
9735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
9745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void LayerAnimationController::NotifyObserversFilterAnimated(
9785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const FilterOperations& filters,
9795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    bool notify_active_observers,
9805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    bool notify_pending_observers) {
9815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (value_observers_.might_have_observers()) {
9825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ObserverListBase<LayerAnimationValueObserver>::Iterator it(
983