• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
LayerAnimationSequence()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 
LayerAnimationSequence(LayerAnimationElement * element)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 
~LayerAnimationSequence()37 LayerAnimationSequence::~LayerAnimationSequence() {
38   FOR_EACH_OBSERVER(LayerAnimationObserver,
39                     observers_,
40                     DetachedFromSequence(this, true));
41 }
42 
Start(LayerAnimationDelegate * delegate)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 
Progress(base::TimeTicks now,LayerAnimationDelegate * delegate)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 
IsFinished(base::TimeTicks time)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 
ProgressToEnd(LayerAnimationDelegate * delegate)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 
GetTargetValue(LayerAnimationElement::TargetValue * target) const160 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 
Abort(LayerAnimationDelegate * delegate)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 
AddElement(LayerAnimationElement * element)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 
HasConflictingProperty(const LayerAnimationElement::AnimatableProperties & other) const186 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 
IsFirstElementThreaded() const197 bool LayerAnimationSequence::IsFirstElementThreaded() const {
198   if (!elements_.empty())
199     return elements_[0]->IsThreaded();
200 
201   return false;
202 }
203 
AddObserver(LayerAnimationObserver * observer)204 void LayerAnimationSequence::AddObserver(LayerAnimationObserver* observer) {
205   if (!observers_.HasObserver(observer)) {
206     observers_.AddObserver(observer);
207     observer->AttachedToSequence(this);
208   }
209 }
210 
RemoveObserver(LayerAnimationObserver * observer)211 void LayerAnimationSequence::RemoveObserver(LayerAnimationObserver* observer) {
212   observers_.RemoveObserver(observer);
213   observer->DetachedFromSequence(this, true);
214 }
215 
OnThreadedAnimationStarted(const cc::AnimationEvent & event)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 
OnScheduled()232 void LayerAnimationSequence::OnScheduled() {
233   NotifyScheduled();
234 }
235 
OnAnimatorDestroyed()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 
size() const250 size_t LayerAnimationSequence::size() const {
251   return elements_.size();
252 }
253 
FirstElement() const254 LayerAnimationElement* LayerAnimationSequence::FirstElement() const {
255   if (elements_.empty()) {
256     return NULL;
257   }
258 
259   return elements_[0].get();
260 }
261 
NotifyScheduled()262 void LayerAnimationSequence::NotifyScheduled() {
263   FOR_EACH_OBSERVER(LayerAnimationObserver,
264                     observers_,
265                     OnLayerAnimationScheduled(this));
266 }
267 
NotifyEnded()268 void LayerAnimationSequence::NotifyEnded() {
269   FOR_EACH_OBSERVER(LayerAnimationObserver,
270                     observers_,
271                     OnLayerAnimationEnded(this));
272 }
273 
NotifyAborted()274 void LayerAnimationSequence::NotifyAborted() {
275   FOR_EACH_OBSERVER(LayerAnimationObserver,
276                     observers_,
277                     OnLayerAnimationAborted(this));
278 }
279 
CurrentElement() const280 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