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