| OLD | NEW | 
|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "ui/gfx/compositor/layer_animator.h" | 5 #include "ui/gfx/compositor/layer_animator.h" | 
| 6 | 6 | 
|  | 7 #include "base/debug/trace_event.h" | 
| 7 #include "base/logging.h" | 8 #include "base/logging.h" | 
| 8 #include "base/stl_util.h" | 9 #include "base/memory/scoped_ptr.h" | 
| 9 #include "ui/base/animation/animation_container.h" | 10 #include "ui/base/animation/animation_container.h" | 
| 10 #include "ui/base/animation/animation.h" |  | 
| 11 #include "ui/base/animation/tween.h" |  | 
| 12 #include "ui/gfx/compositor/compositor.h" | 11 #include "ui/gfx/compositor/compositor.h" | 
| 13 #include "ui/gfx/compositor/layer.h" | 12 #include "ui/gfx/compositor/layer.h" | 
| 14 #include "ui/gfx/compositor/layer_animator_delegate.h" | 13 #include "ui/gfx/compositor/layer_animation_delegate.h" | 
| 15 #include "ui/gfx/transform.h" | 14 #include "ui/gfx/compositor/layer_animation_sequence.h" | 
| 16 #include "ui/gfx/rect.h" | 15 | 
|  | 16 namespace ui { | 
|  | 17 | 
|  | 18 class LayerAnimator; | 
| 17 | 19 | 
| 18 namespace { | 20 namespace { | 
| 19 | 21 | 
| 20 void SetMatrixElement(SkMatrix44& matrix, int index, SkMScalar value) { | 22 static const base::TimeDelta kDefaultTransitionDuration = | 
| 21   int row = index / 4; | 23     base::TimeDelta::FromMilliseconds(250); | 
| 22   int col = index % 4; | 24 | 
| 23   matrix.set(row, col, value); | 25 static const base::TimeDelta kTimerInterval = | 
| 24 } | 26     base::TimeDelta::FromMilliseconds(10); | 
| 25 | 27 | 
| 26 SkMScalar GetMatrixElement(const SkMatrix44& matrix, int index) { | 28 } // namespace; | 
| 27   int row = index / 4; | 29 | 
| 28   int col = index % 4; | 30 // LayerAnimator public -------------------------------------------------------- | 
| 29   return matrix.get(row, col); | 31 | 
| 30 } | 32 LayerAnimator::LayerAnimator(base::TimeDelta transition_duration) | 
| 31 | 33     : delegate_(NULL), | 
| 32 } // anonymous namespace | 34       preemption_strategy_(IMMEDIATELY_SET_NEW_TARGET), | 
| 33 | 35       transition_duration_(transition_duration), | 
| 34 namespace ui { | 36       is_started_(false), | 
| 35 | 37       disable_timer_for_test_(false) { | 
| 36 LayerAnimator::LayerAnimator(Layer* layer) |  | 
| 37     : layer_(layer), |  | 
| 38       got_initial_tick_(false) { |  | 
| 39 } | 38 } | 
| 40 | 39 | 
| 41 LayerAnimator::~LayerAnimator() { | 40 LayerAnimator::~LayerAnimator() { | 
| 42 } | 41   ClearAnimations(); | 
| 43 | 42 } | 
| 44 void LayerAnimator::SetAnimation(Animation* animation) { | 43 | 
| 45   animation_.reset(animation); | 44 // static | 
| 46   if (animation_.get()) { | 45 LayerAnimator* LayerAnimator::CreateDefaultAnimator() { | 
| 47     static ui::AnimationContainer* container = NULL; | 46   return new LayerAnimator(base::TimeDelta::FromMilliseconds(0)); | 
| 48     if (!container) { | 47 } | 
| 49       container = new AnimationContainer; | 48 | 
| 50       container->AddRef(); | 49 // static | 
| 51     } | 50 LayerAnimator* LayerAnimator::CreateImplicitAnimator() { | 
| 52     animation_->set_delegate(this); | 51   return new LayerAnimator(kDefaultTransitionDuration); | 
| 53     animation_->SetContainer(container); | 52 } | 
| 54     got_initial_tick_ = false; | 53 | 
| 55   } | 54 void LayerAnimator::SetTransform(const Transform& transform) { | 
| 56 } | 55   if (transition_duration_ == base::TimeDelta()) | 
| 57 | 56     delegate_->SetTransformFromAnimation(transform); | 
| 58 void LayerAnimator::AnimateToPoint(const gfx::Point& target) { | 57   else | 
| 59   StopAnimating(LOCATION); | 58     StartAnimation(new LayerAnimationSequence( | 
| 60   const gfx::Rect& layer_bounds = layer_->bounds(); | 59         LayerAnimationElement::CreateTransformElement(transform, | 
| 61   if (target == layer_bounds.origin()) | 60                                                       transition_duration_))); | 
| 62     return;  // Already there. | 61 } | 
| 63 | 62 | 
| 64   Params& element = elements_[LOCATION]; | 63 void LayerAnimator::SetBounds(const gfx::Rect& bounds) { | 
| 65   element.location.target_x = target.x(); | 64   if (transition_duration_ == base::TimeDelta()) | 
| 66   element.location.target_y = target.y(); | 65     delegate_->SetBoundsFromAnimation(bounds); | 
| 67   element.location.start_x = layer_bounds.origin().x(); | 66   else | 
| 68   element.location.start_y = layer_bounds.origin().y(); | 67     StartAnimation(new LayerAnimationSequence( | 
| 69 } | 68         LayerAnimationElement::CreateBoundsElement(bounds, | 
| 70 | 69                                                    transition_duration_))); | 
| 71 void LayerAnimator::AnimateTransform(const Transform& transform) { | 70 } | 
| 72   StopAnimating(TRANSFORM); | 71 | 
| 73   const Transform& layer_transform = layer_->transform(); | 72 void LayerAnimator::SetOpacity(float opacity) { | 
| 74   if (transform == layer_transform) | 73   if (transition_duration_ == base::TimeDelta()) | 
| 75     return;  // Already there. | 74     delegate_->SetOpacityFromAnimation(opacity); | 
| 76 | 75   else | 
| 77   Params& element = elements_[TRANSFORM]; | 76     StartAnimation(new LayerAnimationSequence( | 
| 78   for (int i = 0; i < 16; ++i) { | 77         LayerAnimationElement::CreateOpacityElement(opacity, | 
| 79     element.transform.start[i] = | 78                                                     transition_duration_))); | 
| 80         GetMatrixElement(layer_transform.matrix(), i); | 79 } | 
| 81     element.transform.target[i] = | 80 | 
| 82         GetMatrixElement(transform.matrix(), i); | 81 void LayerAnimator::SetDelegate(LayerAnimationDelegate* delegate) { | 
| 83   } | 82   DCHECK(delegate); | 
| 84 } | 83   delegate_ = delegate; | 
| 85 | 84 } | 
| 86 void LayerAnimator::AnimateOpacity(float target_opacity) { | 85 | 
| 87   StopAnimating(OPACITY); | 86 void LayerAnimator::StartAnimation(LayerAnimationSequence* animation) { | 
| 88   if (layer_->opacity() == target_opacity) | 87   if (!StartSequenceImmediately(animation)) { | 
|  | 88     // Attempt to preempt a running animation. | 
|  | 89     switch (preemption_strategy_) { | 
|  | 90       case IMMEDIATELY_SET_NEW_TARGET: | 
|  | 91         ImmediatelySetNewTarget(animation); | 
|  | 92         break; | 
|  | 93       case IMMEDIATELY_ANIMATE_TO_NEW_TARGET: | 
|  | 94         ImmediatelyAnimateToNewTarget(animation); | 
|  | 95         break; | 
|  | 96       case ENQUEUE_NEW_ANIMATION: | 
|  | 97         EnqueueNewAnimation(animation); | 
|  | 98         break; | 
|  | 99       case REPLACE_QUEUED_ANIMATIONS: | 
|  | 100         ReplaceQueuedAnimations(animation); | 
|  | 101         break; | 
|  | 102       case BLEND_WITH_CURRENT_ANIMATION: { | 
|  | 103         // TODO(vollick) Add support for blended sequences and use them here. | 
|  | 104         NOTIMPLEMENTED(); | 
|  | 105         break; | 
|  | 106       } | 
|  | 107     } | 
|  | 108   } | 
|  | 109   FinishAnyAnimationWithZeroDuration(); | 
|  | 110 } | 
|  | 111 | 
|  | 112 void LayerAnimator::ScheduleAnimation(LayerAnimationSequence* animation) { | 
|  | 113   if (is_animating()) { | 
|  | 114     animation_queue_.push_back(make_linked_ptr(animation)); | 
|  | 115     ProcessQueue(); | 
|  | 116   } else { | 
|  | 117     StartSequenceImmediately(animation); | 
|  | 118   } | 
|  | 119 } | 
|  | 120 | 
|  | 121 void LayerAnimator::ScheduleTogether( | 
|  | 122     const std::vector<LayerAnimationSequence*>& animations) { | 
|  | 123   // Collect all the affected properties. | 
|  | 124   LayerAnimationElement::AnimatableProperties animated_properties; | 
|  | 125   std::vector<LayerAnimationSequence*>::const_iterator iter; | 
|  | 126   for (iter = animations.begin(); iter != animations.end(); ++iter) { | 
|  | 127     animated_properties.insert((*iter)->properties().begin(), | 
|  | 128                                (*iter)->properties().end()); | 
|  | 129   } | 
|  | 130 | 
|  | 131   // Scheduling a zero duration pause that affects all the animated properties | 
|  | 132   // will prevent any of the sequences from animating until there are no | 
|  | 133   // running animations that affect any of these properties. | 
|  | 134   ScheduleAnimation( | 
|  | 135       new LayerAnimationSequence( | 
|  | 136           LayerAnimationElement::CreatePauseElement(animated_properties, | 
|  | 137                                                     base::TimeDelta()))); | 
|  | 138 | 
|  | 139   // These animations (provided they don't animate any common properties) will | 
|  | 140   // now animate together if trivially scheduled. | 
|  | 141   for (iter = animations.begin(); iter != animations.end(); ++iter) { | 
|  | 142     ScheduleAnimation(*iter); | 
|  | 143   } | 
|  | 144 } | 
|  | 145 | 
|  | 146 void LayerAnimator::StopAnimatingProperty( | 
|  | 147     LayerAnimationElement::AnimatableProperty property) { | 
|  | 148   while (true) { | 
|  | 149     RunningAnimation* running = GetRunningAnimation(property); | 
|  | 150     if (!running) | 
|  | 151       break; | 
|  | 152     FinishAnimation(running->sequence); | 
|  | 153   } | 
|  | 154 } | 
|  | 155 | 
|  | 156 void LayerAnimator::StopAnimating() { | 
|  | 157   while (is_animating()) | 
|  | 158     FinishAnimation(running_animations_[0].sequence); | 
|  | 159 } | 
|  | 160 | 
|  | 161 // LayerAnimator private ------------------------------------------------------- | 
|  | 162 | 
|  | 163 void LayerAnimator::Step(base::TimeTicks now) { | 
|  | 164   TRACE_EVENT0("LayerAnimator", "Step"); | 
|  | 165   last_step_time_ = now; | 
|  | 166   std::vector<LayerAnimationSequence*> to_finish; | 
|  | 167   for (RunningAnimations::iterator iter = running_animations_.begin(); | 
|  | 168        iter != running_animations_.end(); ++iter) { | 
|  | 169     base::TimeDelta delta = now - (*iter).start_time; | 
|  | 170     if (delta >= (*iter).sequence->duration() && | 
|  | 171         !(*iter).sequence->is_cyclic()) { | 
|  | 172       to_finish.push_back((*iter).sequence); | 
|  | 173     } else { | 
|  | 174       (*iter).sequence->Progress(delta, delegate()); | 
|  | 175     } | 
|  | 176   } | 
|  | 177   for (std::vector<LayerAnimationSequence*>::iterator iter = to_finish.begin(); | 
|  | 178        iter != to_finish.end(); ++iter) { | 
|  | 179     FinishAnimation(*iter); | 
|  | 180   } | 
|  | 181 } | 
|  | 182 | 
|  | 183 void LayerAnimator::SetStartTime(base::TimeTicks start_time) { | 
|  | 184 } | 
|  | 185 | 
|  | 186 base::TimeDelta LayerAnimator::GetTimerInterval() const { | 
|  | 187   return kTimerInterval; | 
|  | 188 } | 
|  | 189 | 
|  | 190 void LayerAnimator::UpdateAnimationState() { | 
|  | 191   if (disable_timer_for_test_) | 
| 89     return; | 192     return; | 
| 90 | 193 | 
| 91   Params& element = elements_[OPACITY]; | 194   static ui::AnimationContainer* container = NULL; | 
| 92   element.opacity.start = layer_->opacity(); | 195   if (!container) { | 
| 93   element.opacity.target = target_opacity; | 196     container = new AnimationContainer(); | 
| 94 } | 197     container->AddRef(); | 
| 95 | 198   } | 
| 96 gfx::Point LayerAnimator::GetTargetPoint() { | 199 | 
| 97   return IsAnimating(LOCATION) ? | 200   const bool should_start = is_animating(); | 
| 98       gfx::Point(elements_[LOCATION].location.target_x, | 201   if (should_start && !is_started_) | 
| 99                  elements_[LOCATION].location.target_y) : | 202     container->Start(this); | 
| 100       layer_->bounds().origin(); | 203   else if (!should_start && is_started_) | 
| 101 } | 204     container->Stop(this); | 
| 102 | 205 | 
| 103 float LayerAnimator::GetTargetOpacity() { | 206   is_started_ = should_start; | 
| 104   return IsAnimating(OPACITY) ? | 207 } | 
| 105       elements_[OPACITY].opacity.target : layer_->opacity(); | 208 | 
| 106 } | 209 void LayerAnimator::RemoveAnimation(LayerAnimationSequence* sequence) { | 
| 107 | 210     // First remove from running animations | 
| 108 ui::Transform LayerAnimator::GetTargetTransform() { | 211   for (RunningAnimations::iterator iter = running_animations_.begin(); | 
| 109   if (IsAnimating(TRANSFORM)) { | 212        iter != running_animations_.end(); ++iter) { | 
| 110     Transform transform; | 213     if ((*iter).sequence == sequence) { | 
| 111     for (int i = 0; i < 16; ++i) { | 214       running_animations_.erase(iter); | 
| 112       SetMatrixElement(transform.matrix(), i, | 215       break; | 
| 113                        elements_[TRANSFORM].transform.target[i]); | 216     } | 
| 114     } | 217   } | 
| 115     return transform; | 218 | 
| 116   } | 219   // Then remove from the queue | 
| 117   return layer_->transform(); | 220   for (AnimationQueue::iterator queue_iter = animation_queue_.begin(); | 
| 118 } | 221        queue_iter != animation_queue_.end(); ++queue_iter) { | 
| 119 | 222     if ((*queue_iter) == sequence) { | 
| 120 bool LayerAnimator::IsAnimating(AnimationProperty property) const { | 223       animation_queue_.erase(queue_iter); | 
| 121   return elements_.count(property) > 0; | 224       break; | 
| 122 } | 225     } | 
| 123 | 226   } | 
| 124 bool LayerAnimator::IsRunning() const { | 227 } | 
| 125   return animation_.get() && animation_->is_animating(); | 228 | 
| 126 } | 229 void LayerAnimator::FinishAnimation(LayerAnimationSequence* sequence) { | 
| 127 | 230   sequence->Progress(sequence->duration(), delegate()); | 
| 128 void LayerAnimator::AnimationProgressed(const ui::Animation* animation) { | 231   RemoveAnimation(sequence); | 
| 129   got_initial_tick_ = true; | 232   ProcessQueue(); | 
| 130   for (Elements::const_iterator i = elements_.begin(); i != elements_.end(); | 233   UpdateAnimationState(); | 
| 131        ++i) { | 234 } | 
| 132     switch (i->first) { | 235 | 
| 133       case LOCATION: { | 236 void LayerAnimator::FinishAnyAnimationWithZeroDuration() { | 
| 134         const gfx::Rect& current_bounds(layer_->bounds()); | 237   // Special case: if we've started a 0 duration animation, just finish it now | 
| 135         gfx::Rect new_bounds = animation_->CurrentValueBetween( | 238   // and get rid of it. Note at each iteration of the loop, we either increment | 
| 136             gfx::Rect(gfx::Point(i->second.location.start_x, | 239   // i or remove an element from running_animations_, so | 
| 137                                  i->second.location.start_y), | 240   // running_animations_.size() - i is always decreasing and we are always | 
| 138                       current_bounds.size()), | 241   // progressing towards the termination of the loop. | 
| 139             gfx::Rect(gfx::Point(i->second.location.target_x, | 242   for (size_t i = 0; i < running_animations_.size();) { | 
| 140                                  i->second.location.target_y), | 243     if (running_animations_[i].sequence->duration() == base::TimeDelta()) { | 
| 141                       current_bounds.size())); | 244       running_animations_[i].sequence->Progress( | 
| 142         delegate()->SetBoundsFromAnimator(new_bounds); | 245           running_animations_[i].sequence->duration(), delegate()); | 
|  | 246       RemoveAnimation(running_animations_[i].sequence); | 
|  | 247     } else { | 
|  | 248       ++i; | 
|  | 249     } | 
|  | 250   } | 
|  | 251   ProcessQueue(); | 
|  | 252   UpdateAnimationState(); | 
|  | 253 } | 
|  | 254 | 
|  | 255 void LayerAnimator::ClearAnimations() { | 
|  | 256   for (RunningAnimations::iterator iter = running_animations_.begin(); | 
|  | 257        iter != running_animations_.end(); ++iter) { | 
|  | 258     (*iter).sequence->Abort(); | 
|  | 259   } | 
|  | 260   running_animations_.clear(); | 
|  | 261   animation_queue_.clear(); | 
|  | 262   UpdateAnimationState(); | 
|  | 263 } | 
|  | 264 | 
|  | 265 LayerAnimator::RunningAnimation* LayerAnimator::GetRunningAnimation( | 
|  | 266     LayerAnimationElement::AnimatableProperty property) { | 
|  | 267   for (RunningAnimations::iterator iter = running_animations_.begin(); | 
|  | 268        iter != running_animations_.end(); ++iter) { | 
|  | 269     if ((*iter).sequence->properties().find(property) != | 
|  | 270         (*iter).sequence->properties().end()) | 
|  | 271       return &(*iter); | 
|  | 272   } | 
|  | 273   return NULL; | 
|  | 274 } | 
|  | 275 | 
|  | 276 void LayerAnimator::AddToQueueIfNotPresent(LayerAnimationSequence* animation) { | 
|  | 277   // If we don't have the animation in the queue yet, add it. | 
|  | 278   bool found_sequence = false; | 
|  | 279   for (AnimationQueue::iterator queue_iter = animation_queue_.begin(); | 
|  | 280        queue_iter != animation_queue_.end(); ++queue_iter) { | 
|  | 281     if ((*queue_iter) == animation) { | 
|  | 282       found_sequence = true; | 
|  | 283       break; | 
|  | 284     } | 
|  | 285   } | 
|  | 286 | 
|  | 287   if (!found_sequence) | 
|  | 288     animation_queue_.push_front(make_linked_ptr(animation)); | 
|  | 289 } | 
|  | 290 | 
|  | 291 void LayerAnimator::RemoveAllAnimationsWithACommonProperty( | 
|  | 292     LayerAnimationSequence* sequence, | 
|  | 293     bool abort) { | 
|  | 294   // For all the running animations, if they animate the same property, | 
|  | 295   // progress them to the end and remove them. Note: at each iteration i is | 
|  | 296   // incremented or an element is removed from the queue, so | 
|  | 297   // animation_queue_.size() - i is always decreasing and we are always making | 
|  | 298   // progress towards the loop terminating. | 
|  | 299   for (size_t i = 0; i < running_animations_.size();) { | 
|  | 300     if (running_animations_[i].sequence->HasCommonProperty( | 
|  | 301             sequence->properties())) { | 
|  | 302       // Finish the animation. | 
|  | 303       if (abort) | 
|  | 304         running_animations_[i].sequence->Abort(); | 
|  | 305       else | 
|  | 306         running_animations_[i].sequence->Progress( | 
|  | 307             running_animations_[i].sequence->duration(), delegate()); | 
|  | 308       RemoveAnimation(running_animations_[i].sequence); | 
|  | 309     } else { | 
|  | 310       ++i; | 
|  | 311     } | 
|  | 312   } | 
|  | 313 | 
|  | 314   // Same for the queued animations. See comment above about loop termination. | 
|  | 315   for (size_t i = 0; i < animation_queue_.size();) { | 
|  | 316     if (animation_queue_[i]->HasCommonProperty(sequence->properties())) { | 
|  | 317       // Finish the animation. | 
|  | 318       if (abort) | 
|  | 319         animation_queue_[i]->Abort(); | 
|  | 320       else | 
|  | 321         animation_queue_[i]->Progress(animation_queue_[i]->duration(), | 
|  | 322                                       delegate()); | 
|  | 323       RemoveAnimation(animation_queue_[i].get()); | 
|  | 324     } else { | 
|  | 325       ++i; | 
|  | 326     } | 
|  | 327   } | 
|  | 328 } | 
|  | 329 | 
|  | 330 void LayerAnimator::ImmediatelySetNewTarget(LayerAnimationSequence* sequence) { | 
|  | 331   const bool abort = false; | 
|  | 332   RemoveAllAnimationsWithACommonProperty(sequence, abort); | 
|  | 333   sequence->Progress(sequence->duration(), delegate()); | 
|  | 334   RemoveAnimation(sequence); | 
|  | 335 } | 
|  | 336 | 
|  | 337 void LayerAnimator::ImmediatelyAnimateToNewTarget( | 
|  | 338     LayerAnimationSequence* sequence) { | 
|  | 339   const bool abort = true; | 
|  | 340   RemoveAllAnimationsWithACommonProperty(sequence, abort); | 
|  | 341   AddToQueueIfNotPresent(sequence); | 
|  | 342   StartSequenceImmediately(sequence); | 
|  | 343 } | 
|  | 344 | 
|  | 345 void LayerAnimator::EnqueueNewAnimation(LayerAnimationSequence* sequence) { | 
|  | 346   // It is assumed that if there was no conflicting animation, we would | 
|  | 347   // not have been called. No need to check for a collision; just | 
|  | 348   // add to the queue. | 
|  | 349   animation_queue_.push_back(make_linked_ptr(sequence)); | 
|  | 350   ProcessQueue(); | 
|  | 351 } | 
|  | 352 | 
|  | 353 void LayerAnimator::ReplaceQueuedAnimations(LayerAnimationSequence* sequence) { | 
|  | 354   // Remove all animations that aren't running. Note: at each iteration i is | 
|  | 355   // incremented or an element is removed from the queue, so | 
|  | 356   // animation_queue_.size() - i is always decreasing and we are always making | 
|  | 357   // progress towards the loop terminating. | 
|  | 358   for (size_t i = 0; i < animation_queue_.size();) { | 
|  | 359     bool is_running = false; | 
|  | 360     for (RunningAnimations::const_iterator iter = running_animations_.begin(); | 
|  | 361          iter != running_animations_.end(); ++iter) { | 
|  | 362       if ((*iter).sequence == animation_queue_[i]) { | 
|  | 363         is_running = true; | 
| 143         break; | 364         break; | 
| 144       } | 365       } | 
| 145 | 366     } | 
| 146       case TRANSFORM: { | 367     if (!is_running) | 
| 147         Transform transform; | 368       RemoveAnimation(animation_queue_[i].get()); | 
| 148         for (int j = 0; j < 16; ++j) { | 369     else | 
| 149           SkMScalar value = animation_->CurrentValueBetween( | 370       ++i; | 
| 150               i->second.transform.start[j], | 371   } | 
| 151               i->second.transform.target[j]); | 372   animation_queue_.push_back(make_linked_ptr(sequence)); | 
| 152           SetMatrixElement(transform.matrix(), j, value); | 373   ProcessQueue(); | 
| 153         } | 374 } | 
| 154         delegate()->SetTransformFromAnimator(transform); | 375 | 
|  | 376 void LayerAnimator::ProcessQueue() { | 
|  | 377   bool started_sequence = false; | 
|  | 378   do { | 
|  | 379     started_sequence = false; | 
|  | 380 | 
|  | 381     // Build a list of all currently animated properties. | 
|  | 382     LayerAnimationElement::AnimatableProperties animated; | 
|  | 383 | 
|  | 384     for (RunningAnimations::const_iterator iter = running_animations_.begin(); | 
|  | 385          iter != running_animations_.end(); ++iter) { | 
|  | 386       animated.insert((*iter).sequence->properties().begin(), | 
|  | 387                       (*iter).sequence->properties().end()); | 
|  | 388     } | 
|  | 389 | 
|  | 390     // Try to find an animation that doesn't conflict with an animated | 
|  | 391     // property or a property that will be animated before it. | 
|  | 392     for (AnimationQueue::iterator queue_iter = animation_queue_.begin(); | 
|  | 393          queue_iter != animation_queue_.end(); ++queue_iter) { | 
|  | 394       if (!(*queue_iter)->HasCommonProperty(animated)) { | 
|  | 395         StartSequenceImmediately((*queue_iter).get()); | 
|  | 396         started_sequence = true; | 
| 155         break; | 397         break; | 
| 156       } | 398       } | 
| 157 | 399 | 
| 158       case OPACITY: { | 400       // Animation couldn't be started. Add its properties to the collection so | 
| 159         delegate()->SetOpacityFromAnimator(animation_->CurrentValueBetween( | 401       // that we don't start a conflicting animation. For example, if our queue | 
| 160             i->second.opacity.start, i->second.opacity.target)); | 402       // has the elements { {T,B}, {B} } (that is, an element that animates both | 
| 161         break; | 403       // the transform and the bounds followed by an element that animates the | 
| 162       } | 404       // bounds), and we're currently animating the transform, we can't start | 
| 163 | 405       // the first element because it animates the transform, too. We cannot | 
| 164       default: | 406       // start the second element, either, because the first element animates | 
| 165         NOTREACHED(); | 407       // bounds too, and needs to go first. | 
| 166     } | 408       animated.insert((*queue_iter)->properties().begin(), | 
| 167   } | 409                       (*queue_iter)->properties().end()); | 
| 168   layer_->ScheduleDraw(); | 410     } | 
| 169 } | 411 | 
| 170 | 412     // If we started a sequence, try again. We may be able to start several. | 
| 171 void LayerAnimator::AnimationEnded(const ui::Animation* animation) { | 413   } while (started_sequence); | 
| 172   AnimationProgressed(animation); | 414 } | 
| 173   if (layer_->delegate()) | 415 | 
| 174     layer_->delegate()->OnLayerAnimationEnded(animation); | 416 bool LayerAnimator::StartSequenceImmediately(LayerAnimationSequence* sequence) { | 
| 175 } | 417   // Ensure that no one is animating one of the sequence's properties already. | 
| 176 | 418   for (RunningAnimations::const_iterator iter = running_animations_.begin(); | 
| 177 void LayerAnimator::StopAnimating(AnimationProperty property) { | 419        iter != running_animations_.end(); ++iter) { | 
| 178   if (!IsAnimating(property)) | 420     if ((*iter).sequence->HasCommonProperty(sequence->properties())) | 
| 179     return; | 421       return false; | 
| 180 | 422   } | 
| 181   elements_.erase(property); | 423 | 
| 182 } | 424   // All clear, actually start the sequence. Note: base::TimeTicks::Now has | 
| 183 | 425   // a resolution that can be as bad as 15ms. If this causes glitches in the | 
| 184 LayerAnimatorDelegate* LayerAnimator::delegate() { | 426   // animations, this can be switched to HighResNow() (animation uses Now() | 
| 185   return static_cast<LayerAnimatorDelegate*>(layer_); | 427   // internally). | 
|  | 428   base::TimeTicks start_time = is_animating() | 
|  | 429       ? last_step_time_ | 
|  | 430       : base::TimeTicks::Now(); | 
|  | 431 | 
|  | 432   running_animations_.push_back(RunningAnimation(sequence, start_time)); | 
|  | 433 | 
|  | 434   // Need to keep a reference to the animation. | 
|  | 435   AddToQueueIfNotPresent(sequence); | 
|  | 436 | 
|  | 437   // Ensure that animations get stepped at their start time. | 
|  | 438   Step(start_time); | 
|  | 439 | 
|  | 440   return true; | 
| 186 } | 441 } | 
| 187 | 442 | 
| 188 }  // namespace ui | 443 }  // namespace ui | 
| OLD | NEW | 
|---|