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