Home | History | Annotate | Download | only in compositor
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ui/compositor/layer_animation_sequence.h"
      6 
      7 #include <algorithm>
      8 #include <iterator>
      9 
     10 #include "base/debug/trace_event.h"
     11 #include "cc/animation/animation_id_provider.h"
     12 #include "ui/compositor/layer_animation_delegate.h"
     13 #include "ui/compositor/layer_animation_element.h"
     14 #include "ui/compositor/layer_animation_observer.h"
     15 
     16 namespace ui {
     17 
     18 LayerAnimationSequence::LayerAnimationSequence()
     19     : is_cyclic_(false),
     20       last_element_(0),
     21       waiting_for_group_start_(false),
     22       animation_group_id_(0),
     23       last_progressed_fraction_(0.0),
     24       weak_ptr_factory_(this) {
     25 }
     26 
     27 LayerAnimationSequence::LayerAnimationSequence(LayerAnimationElement* element)
     28     : is_cyclic_(false),
     29       last_element_(0),
     30       waiting_for_group_start_(false),
     31       animation_group_id_(0),
     32       last_progressed_fraction_(0.0),
     33       weak_ptr_factory_(this) {
     34   AddElement(element);
     35 }
     36 
     37 LayerAnimationSequence::~LayerAnimationSequence() {
     38   FOR_EACH_OBSERVER(LayerAnimationObserver,
     39                     observers_,
     40                     DetachedFromSequence(this, true));
     41 }
     42 
     43 void LayerAnimationSequence::Start(LayerAnimationDelegate* delegate) {
     44   DCHECK(start_time_ != base::TimeTicks());
     45   last_progressed_fraction_ = 0.0;
     46   if (elements_.empty())
     47     return;
     48 
     49   elements_[0]->set_requested_start_time(start_time_);
     50   elements_[0]->Start(delegate, animation_group_id_);
     51 }
     52 
     53 void LayerAnimationSequence::Progress(base::TimeTicks now,
     54                                       LayerAnimationDelegate* delegate) {
     55   DCHECK(start_time_ != base::TimeTicks());
     56   bool redraw_required = false;
     57 
     58   if (elements_.empty())
     59     return;
     60 
     61   if (last_element_ == 0)
     62     last_start_ = start_time_;
     63 
     64   size_t current_index = last_element_ % elements_.size();
     65   base::TimeDelta element_duration;
     66   while (is_cyclic_ || last_element_ < elements_.size()) {
     67     elements_[current_index]->set_requested_start_time(last_start_);
     68     if (!elements_[current_index]->IsFinished(now, &element_duration))
     69       break;
     70 
     71     // Let the element we're passing finish.
     72     if (elements_[current_index]->ProgressToEnd(delegate))
     73       redraw_required = true;
     74     last_start_ += element_duration;
     75     ++last_element_;
     76     last_progressed_fraction_ =
     77         elements_[current_index]->last_progressed_fraction();
     78     current_index = last_element_ % elements_.size();
     79   }
     80 
     81   if (is_cyclic_ || last_element_ < elements_.size()) {
     82     if (!elements_[current_index]->Started()) {
     83       animation_group_id_ = cc::AnimationIdProvider::NextGroupId();
     84       elements_[current_index]->Start(delegate, animation_group_id_);
     85     }
     86     base::WeakPtr<LayerAnimationSequence> alive(weak_ptr_factory_.GetWeakPtr());
     87     if (elements_[current_index]->Progress(now, delegate))
     88       redraw_required = true;
     89     if (!alive)
     90       return;
     91     last_progressed_fraction_ =
     92         elements_[current_index]->last_progressed_fraction();
     93   }
     94 
     95   // Since the delegate may be deleted due to the notifications below, it is
     96   // important that we schedule a draw before sending them.
     97   if (redraw_required)
     98     delegate->ScheduleDrawForAnimation();
     99 
    100   if (!is_cyclic_ && last_element_ == elements_.size()) {
    101     last_element_ = 0;
    102     waiting_for_group_start_ = false;
    103     animation_group_id_ = 0;
    104     NotifyEnded();
    105   }
    106 }
    107 
    108 bool LayerAnimationSequence::IsFinished(base::TimeTicks time) {
    109   if (is_cyclic_ || waiting_for_group_start_)
    110     return false;
    111 
    112   if (elements_.empty())
    113     return true;
    114 
    115   if (last_element_ == 0)
    116     last_start_ = start_time_;
    117 
    118   base::TimeTicks current_start = last_start_;
    119   size_t current_index = last_element_;
    120   base::TimeDelta element_duration;
    121   while (current_index < elements_.size()) {
    122     elements_[current_index]->set_requested_start_time(current_start);
    123     if (!elements_[current_index]->IsFinished(time, &element_duration))
    124       break;
    125 
    126     current_start += element_duration;
    127     ++current_index;
    128   }
    129 
    130   return (current_index == elements_.size());
    131 }
    132 
    133 void LayerAnimationSequence::ProgressToEnd(LayerAnimationDelegate* delegate) {
    134   bool redraw_required = false;
    135 
    136   if (elements_.empty())
    137     return;
    138 
    139   size_t current_index = last_element_ % elements_.size();
    140   while (current_index < elements_.size()) {
    141     if (elements_[current_index]->ProgressToEnd(delegate))
    142       redraw_required = true;
    143     last_progressed_fraction_ =
    144         elements_[current_index]->last_progressed_fraction();
    145     ++current_index;
    146     ++last_element_;
    147   }
    148 
    149   if (redraw_required)
    150     delegate->ScheduleDrawForAnimation();
    151 
    152   if (!is_cyclic_) {
    153     last_element_ = 0;
    154     waiting_for_group_start_ = false;
    155     animation_group_id_ = 0;
    156     NotifyEnded();
    157   }
    158 }
    159 
    160 void LayerAnimationSequence::GetTargetValue(
    161     LayerAnimationElement::TargetValue* target) const {
    162   if (is_cyclic_)
    163     return;
    164 
    165   for (size_t i = last_element_; i < elements_.size(); ++i)
    166     elements_[i]->GetTargetValue(target);
    167 }
    168 
    169 void LayerAnimationSequence::Abort(LayerAnimationDelegate* delegate) {
    170   size_t current_index = last_element_ % elements_.size();
    171   while (current_index < elements_.size()) {
    172     elements_[current_index]->Abort(delegate);
    173     ++current_index;
    174   }
    175   last_element_ = 0;
    176   waiting_for_group_start_ = false;
    177   NotifyAborted();
    178 }
    179 
    180 void LayerAnimationSequence::AddElement(LayerAnimationElement* element) {
    181   properties_.insert(element->properties().begin(),
    182                      element->properties().end());
    183   elements_.push_back(make_linked_ptr(element));
    184 }
    185 
    186 bool LayerAnimationSequence::HasConflictingProperty(
    187     const LayerAnimationElement::AnimatableProperties& other) const {
    188   LayerAnimationElement::AnimatableProperties intersection;
    189   std::insert_iterator<LayerAnimationElement::AnimatableProperties> ii(
    190       intersection, intersection.begin());
    191   std::set_intersection(properties_.begin(), properties_.end(),
    192                         other.begin(), other.end(),
    193                         ii);
    194   return (intersection.size() > 0);
    195 }
    196 
    197 bool LayerAnimationSequence::IsFirstElementThreaded() const {
    198   if (!elements_.empty())
    199     return elements_[0]->IsThreaded();
    200 
    201   return false;
    202 }
    203 
    204 void LayerAnimationSequence::AddObserver(LayerAnimationObserver* observer) {
    205   if (!observers_.HasObserver(observer)) {
    206     observers_.AddObserver(observer);
    207     observer->AttachedToSequence(this);
    208   }
    209 }
    210 
    211 void LayerAnimationSequence::RemoveObserver(LayerAnimationObserver* observer) {
    212   observers_.RemoveObserver(observer);
    213   observer->DetachedFromSequence(this, true);
    214 }
    215 
    216 void LayerAnimationSequence::OnThreadedAnimationStarted(
    217     const cc::AnimationEvent& event) {
    218   if (elements_.empty() || event.group_id != animation_group_id_)
    219     return;
    220 
    221   size_t current_index = last_element_ % elements_.size();
    222   const LayerAnimationElement::AnimatableProperties& element_properties =
    223     elements_[current_index]->properties();
    224   LayerAnimationElement::AnimatableProperty event_property =
    225       LayerAnimationElement::ToAnimatableProperty(event.target_property);
    226   DCHECK(element_properties.find(event_property) != element_properties.end());
    227   elements_[current_index]->set_effective_start_time(
    228       base::TimeTicks::FromInternalValue(
    229           event.monotonic_time * base::Time::kMicrosecondsPerSecond));
    230 }
    231 
    232 void LayerAnimationSequence::OnScheduled() {
    233   NotifyScheduled();
    234 }
    235 
    236 void LayerAnimationSequence::OnAnimatorDestroyed() {
    237   if (observers_.might_have_observers()) {
    238     ObserverListBase<LayerAnimationObserver>::Iterator it(observers_);
    239     LayerAnimationObserver* obs;
    240     while ((obs = it.GetNext()) != NULL) {
    241       if (!obs->RequiresNotificationWhenAnimatorDestroyed()) {
    242         // Remove the observer, but do not allow notifications to be sent.
    243         observers_.RemoveObserver(obs);
    244         obs->DetachedFromSequence(this, false);
    245       }
    246     }
    247   }
    248 }
    249 
    250 size_t LayerAnimationSequence::size() const {
    251   return elements_.size();
    252 }
    253 
    254 LayerAnimationElement* LayerAnimationSequence::FirstElement() const {
    255   if (elements_.empty()) {
    256     return NULL;
    257   }
    258 
    259   return elements_[0].get();
    260 }
    261 
    262 void LayerAnimationSequence::NotifyScheduled() {
    263   FOR_EACH_OBSERVER(LayerAnimationObserver,
    264                     observers_,
    265                     OnLayerAnimationScheduled(this));
    266 }
    267 
    268 void LayerAnimationSequence::NotifyEnded() {
    269   FOR_EACH_OBSERVER(LayerAnimationObserver,
    270                     observers_,
    271                     OnLayerAnimationEnded(this));
    272 }
    273 
    274 void LayerAnimationSequence::NotifyAborted() {
    275   FOR_EACH_OBSERVER(LayerAnimationObserver,
    276                     observers_,
    277                     OnLayerAnimationAborted(this));
    278 }
    279 
    280 LayerAnimationElement* LayerAnimationSequence::CurrentElement() const {
    281   if (elements_.empty())
    282     return NULL;
    283 
    284   size_t current_index = last_element_ % elements_.size();
    285   return elements_[current_index].get();
    286 }
    287 
    288 }  // namespace ui
    289