| 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
|
|
|