Index: ui/gfx/compositor/layer_animation_preemption_strategy.cc |
diff --git a/ui/gfx/compositor/layer_animation_preemption_strategy.cc b/ui/gfx/compositor/layer_animation_preemption_strategy.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5078cd8f587462e6c21e564c7cef9fd2c91e42af |
--- /dev/null |
+++ b/ui/gfx/compositor/layer_animation_preemption_strategy.cc |
@@ -0,0 +1,209 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "ui/gfx/compositor/layer_animation_preemption_strategy.h" |
+ |
+#include "base/logging.h" |
+#include "base/memory/singleton.h" |
+#include "ui/gfx/compositor/layer_animation_sequence.h" |
+ |
+namespace ui { |
+ |
+namespace { |
+ |
+void RemoveAnimation(LayerAnimationSequence* sequence, |
+ LayerAnimator::RunningAnimations* running, |
+ LayerAnimator::AnimationQueue* queue) { |
+ // First remove from running animations |
+ LayerAnimator::RunningAnimations::iterator iter = running->begin(); |
+ while (iter != running->end()) { |
+ if ((*iter).sequence == sequence) { |
+ running->erase(iter); |
+ break; |
+ } |
+ ++iter; |
+ } |
+ |
+ // Then remove from the queue |
+ LayerAnimator::AnimationQueue::iterator queue_iter = queue->begin(); |
+ while (queue_iter != queue->end()) { |
+ if ((*queue_iter).get() == sequence) { |
+ queue->erase(queue_iter); |
+ break; |
+ } |
+ ++queue_iter; |
+ } |
+} |
+ |
+// Precondition: there is no running animation with a property in common with |
+// sequence. |
+void StartSequence(LayerAnimationSequence* sequence, |
+ LayerAnimator::RunningAnimations* running, |
+ LayerAnimator::AnimationQueue* queue) { |
+ running->push_back(LayerAnimator::RunningAnimation(sequence, |
+ base::TimeTicks::Now())); |
+ |
+ // If we don't have the animation in the queue yet, add it. |
+ bool found_sequence = false; |
+ LayerAnimator::AnimationQueue::iterator queue_iter = queue->begin(); |
+ while (queue_iter != queue->end()) { |
+ if ((*queue_iter).get() == sequence) { |
+ found_sequence = true; |
+ break; |
+ } |
+ ++queue_iter; |
+ } |
+ |
+ if (!found_sequence) |
+ queue->push_front(make_scoped_refptr(sequence)); |
+} |
+ |
+// ImmediatelySetNewTarget ----------------------------------------------------- |
+ |
+class COMPOSITOR_EXPORT ImmediatelySetNewTarget |
+ : public LayerAnimationPreemptionStrategy { |
+ public: |
+ static ImmediatelySetNewTarget* GetInstance(); |
+ virtual void Preempt(LayerAnimationDelegate* delegate, |
+ LayerAnimationSequence* preempting, |
+ LayerAnimator::RunningAnimations* running, |
+ LayerAnimator::AnimationQueue* queue) { |
+ // For all the running animations, if they animate the same property, |
+ // progress them to the end and remove them. |
+ LayerAnimator::RunningAnimations copy = *running; |
+ LayerAnimator::RunningAnimations::const_iterator iter = copy.begin(); |
+ while (iter != copy.end()) { |
+ if ((*iter).sequence->HasCommonProperty(*preempting)) { |
+ // Abort the animation. |
+ (*iter).sequence->Abort(); |
+ RemoveAnimation((*iter).sequence, running, queue); |
+ } |
+ ++iter; |
+ } |
+ |
+ // Skip to the end of the animation. |
+ preempting->Progress(preempting->duration(), delegate); |
+ RemoveAnimation(preempting, running, queue); |
+ } |
+ private: |
+ ImmediatelySetNewTarget() {} |
+ friend struct DefaultSingletonTraits<ImmediatelySetNewTarget>; |
+ DISALLOW_COPY_AND_ASSIGN(ImmediatelySetNewTarget); |
+}; |
+ |
+ImmediatelySetNewTarget* ImmediatelySetNewTarget::GetInstance() { |
+ return Singleton<ImmediatelySetNewTarget>::get(); |
+} |
+ |
+// ImmediatelyAnimateToNewTarget ----------------------------------------------- |
+ |
+class COMPOSITOR_EXPORT ImmediatelyAnimateToNewTarget |
+ : public LayerAnimationPreemptionStrategy { |
+ public: |
+ static ImmediatelyAnimateToNewTarget* GetInstance(); |
+ virtual void Preempt(LayerAnimationDelegate* delegate, |
+ LayerAnimationSequence* preempting, |
+ LayerAnimator::RunningAnimations* running, |
+ LayerAnimator::AnimationQueue* queue) { |
+ // For all the running animations, if they animate the same property, |
+ // progress them to the end and remove them. |
+ LayerAnimator::RunningAnimations copy = *running; |
+ LayerAnimator::RunningAnimations::const_iterator iter = copy.begin(); |
+ while (iter != copy.end()) { |
+ if ((*iter).sequence->HasCommonProperty(*preempting)) { |
+ // Abort the animation. |
+ (*iter).sequence->Abort(); |
+ RemoveAnimation((*iter).sequence, running, queue); |
+ } |
+ ++iter; |
+ } |
+ StartSequence(preempting, running, queue); |
+ } |
+ private: |
+ ImmediatelyAnimateToNewTarget() {} |
+ friend struct DefaultSingletonTraits<ImmediatelyAnimateToNewTarget>; |
+ DISALLOW_COPY_AND_ASSIGN(ImmediatelyAnimateToNewTarget); |
+}; |
+ |
+ImmediatelyAnimateToNewTarget* ImmediatelyAnimateToNewTarget::GetInstance() { |
+ return Singleton<ImmediatelyAnimateToNewTarget>::get(); |
+} |
+ |
+// EnqueueNewAnimation --------------------------------------------------------- |
+ |
+class COMPOSITOR_EXPORT EnqueueNewAnimation |
+ : public LayerAnimationPreemptionStrategy { |
+ public: |
+ static EnqueueNewAnimation* GetInstance(); |
+ virtual void Preempt(LayerAnimationDelegate* delegate, |
+ LayerAnimationSequence* preempting, |
+ LayerAnimator::RunningAnimations* running, |
+ LayerAnimator::AnimationQueue* queue) { |
+ // It is assumed that if there was no conflicting animation, we would not |
+ // have been called. No need to check for a collision, then. Just add to the |
+ // queue. |
+ queue->push_back(make_scoped_refptr(preempting)); |
+ } |
+ private: |
+ EnqueueNewAnimation() {} |
+ friend struct DefaultSingletonTraits<EnqueueNewAnimation>; |
+ DISALLOW_COPY_AND_ASSIGN(EnqueueNewAnimation); |
+}; |
+ |
+EnqueueNewAnimation* EnqueueNewAnimation::GetInstance() { |
+ return Singleton<EnqueueNewAnimation>::get(); |
+} |
+ |
+// BlendCurrentWithNewAnimation ------------------------------------------------ |
+ |
+class COMPOSITOR_EXPORT BlendCurrentWithNewAnimation |
+ : public LayerAnimationPreemptionStrategy { |
+ public: |
+ static BlendCurrentWithNewAnimation* GetInstance(); |
+ virtual void Preempt(LayerAnimationDelegate* delegate, |
+ LayerAnimationSequence* preempting, |
+ LayerAnimator::RunningAnimations* running, |
+ LayerAnimator::AnimationQueue* queue) { |
+ // TODO(vollick) Add support for blended sequences, and use them here. |
+ NOTIMPLEMENTED(); |
+ } |
+ private: |
+ BlendCurrentWithNewAnimation() {} |
+ friend struct DefaultSingletonTraits<BlendCurrentWithNewAnimation>; |
+ DISALLOW_COPY_AND_ASSIGN(BlendCurrentWithNewAnimation); |
+}; |
+ |
+BlendCurrentWithNewAnimation* BlendCurrentWithNewAnimation::GetInstance() { |
+ return Singleton<BlendCurrentWithNewAnimation>::get(); |
+} |
+ |
+} // namespace |
+ |
+// LayerAnimationPreemptionStrategy -------------------------------------------- |
+ |
+/* static */ |
+LayerAnimationPreemptionStrategy* |
+LayerAnimationPreemptionStrategy::GetImmediatelySetNewTarget() { |
+ return ImmediatelySetNewTarget::GetInstance(); |
+} |
+ |
+/* static */ |
+LayerAnimationPreemptionStrategy* |
+LayerAnimationPreemptionStrategy::GetImmediatelyAnimateToNewTarget() { |
+ return ImmediatelyAnimateToNewTarget::GetInstance(); |
+} |
+ |
+/* static */ |
+LayerAnimationPreemptionStrategy* |
+LayerAnimationPreemptionStrategy::GetEnqueueNewAnimation() { |
+ return EnqueueNewAnimation::GetInstance(); |
+} |
+ |
+/* static */ |
+LayerAnimationPreemptionStrategy* |
+LayerAnimationPreemptionStrategy::GetBlendCurrentWithNewAnimation() { |
+ return BlendCurrentWithNewAnimation::GetInstance(); |
+} |
+ |
+} // namespace ui |