| Index: cc/animation/layer_animation_controller.cc
|
| diff --git a/cc/animation/layer_animation_controller.cc b/cc/animation/layer_animation_controller.cc
|
| deleted file mode 100644
|
| index 25e38cc6dc697e99f9e94098907ee7c6e46233a2..0000000000000000000000000000000000000000
|
| --- a/cc/animation/layer_animation_controller.cc
|
| +++ /dev/null
|
| @@ -1,1047 +0,0 @@
|
| -// Copyright 2012 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 "cc/animation/layer_animation_controller.h"
|
| -
|
| -#include <algorithm>
|
| -#include <vector>
|
| -
|
| -#include "cc/animation/animation.h"
|
| -#include "cc/animation/animation_delegate.h"
|
| -#include "cc/animation/animation_registrar.h"
|
| -#include "cc/animation/keyframed_animation_curve.h"
|
| -#include "cc/animation/layer_animation_value_observer.h"
|
| -#include "cc/animation/layer_animation_value_provider.h"
|
| -#include "cc/animation/scroll_offset_animation_curve.h"
|
| -#include "cc/base/scoped_ptr_algorithm.h"
|
| -#include "cc/output/filter_operations.h"
|
| -#include "ui/gfx/geometry/box_f.h"
|
| -#include "ui/gfx/transform.h"
|
| -
|
| -namespace cc {
|
| -
|
| -LayerAnimationController::LayerAnimationController(int id)
|
| - : registrar_(0),
|
| - id_(id),
|
| - is_active_(false),
|
| - value_provider_(nullptr),
|
| - layer_animation_delegate_(nullptr),
|
| - needs_to_start_animations_(false),
|
| - scroll_offset_animation_was_interrupted_(false) {
|
| -}
|
| -
|
| -LayerAnimationController::~LayerAnimationController() {
|
| - if (registrar_)
|
| - registrar_->UnregisterAnimationController(this);
|
| -}
|
| -
|
| -scoped_refptr<LayerAnimationController> LayerAnimationController::Create(
|
| - int id) {
|
| - return make_scoped_refptr(new LayerAnimationController(id));
|
| -}
|
| -
|
| -void LayerAnimationController::PauseAnimation(int animation_id,
|
| - base::TimeDelta time_offset) {
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (animations_[i]->id() == animation_id) {
|
| - animations_[i]->SetRunState(Animation::PAUSED,
|
| - time_offset + animations_[i]->start_time());
|
| - }
|
| - }
|
| -}
|
| -
|
| -struct HasAnimationId {
|
| - explicit HasAnimationId(int id) : id_(id) {}
|
| - bool operator()(Animation* animation) const {
|
| - return animation->id() == id_;
|
| - }
|
| -
|
| - private:
|
| - int id_;
|
| -};
|
| -
|
| -void LayerAnimationController::RemoveAnimation(int animation_id) {
|
| - auto animations_to_remove =
|
| - animations_.remove_if(HasAnimationId(animation_id));
|
| - for (auto it = animations_to_remove; it != animations_.end(); ++it) {
|
| - if ((*it)->target_property() == Animation::SCROLL_OFFSET) {
|
| - scroll_offset_animation_was_interrupted_ = true;
|
| - break;
|
| - }
|
| - }
|
| - animations_.erase(animations_to_remove, animations_.end());
|
| - UpdateActivation(NORMAL_ACTIVATION);
|
| -}
|
| -
|
| -struct HasAnimationIdAndProperty {
|
| - HasAnimationIdAndProperty(int id, Animation::TargetProperty target_property)
|
| - : id_(id), target_property_(target_property) {}
|
| - bool operator()(Animation* animation) const {
|
| - return animation->id() == id_ &&
|
| - animation->target_property() == target_property_;
|
| - }
|
| -
|
| - private:
|
| - int id_;
|
| - Animation::TargetProperty target_property_;
|
| -};
|
| -
|
| -void LayerAnimationController::RemoveAnimation(
|
| - int animation_id,
|
| - Animation::TargetProperty target_property) {
|
| - auto animations_to_remove = animations_.remove_if(
|
| - HasAnimationIdAndProperty(animation_id, target_property));
|
| - if (target_property == Animation::SCROLL_OFFSET &&
|
| - animations_to_remove != animations_.end())
|
| - scroll_offset_animation_was_interrupted_ = true;
|
| -
|
| - animations_.erase(animations_to_remove, animations_.end());
|
| - UpdateActivation(NORMAL_ACTIVATION);
|
| -}
|
| -
|
| -void LayerAnimationController::AbortAnimations(
|
| - Animation::TargetProperty target_property) {
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (animations_[i]->target_property() == target_property &&
|
| - !animations_[i]->is_finished())
|
| - animations_[i]->SetRunState(Animation::ABORTED, last_tick_time_);
|
| - }
|
| -}
|
| -
|
| -// Ensures that the list of active animations on the main thread and the impl
|
| -// thread are kept in sync.
|
| -void LayerAnimationController::PushAnimationUpdatesTo(
|
| - LayerAnimationController* controller_impl) {
|
| - DCHECK(this != controller_impl);
|
| - if (!has_any_animation() && !controller_impl->has_any_animation())
|
| - return;
|
| - PurgeAnimationsMarkedForDeletion();
|
| - PushNewAnimationsToImplThread(controller_impl);
|
| -
|
| - // Remove finished impl side animations only after pushing,
|
| - // and only after the animations are deleted on the main thread
|
| - // this insures we will never push an animation twice.
|
| - RemoveAnimationsCompletedOnMainThread(controller_impl);
|
| -
|
| - PushPropertiesToImplThread(controller_impl);
|
| - controller_impl->UpdateActivation(NORMAL_ACTIVATION);
|
| - UpdateActivation(NORMAL_ACTIVATION);
|
| -}
|
| -
|
| -void LayerAnimationController::Animate(base::TimeTicks monotonic_time) {
|
| - DCHECK(!monotonic_time.is_null());
|
| - if (!HasValueObserver())
|
| - return;
|
| -
|
| - if (needs_to_start_animations_)
|
| - StartAnimations(monotonic_time);
|
| - TickAnimations(monotonic_time);
|
| - last_tick_time_ = monotonic_time;
|
| -}
|
| -
|
| -void LayerAnimationController::AccumulatePropertyUpdates(
|
| - base::TimeTicks monotonic_time,
|
| - AnimationEventsVector* events) {
|
| - if (!events)
|
| - return;
|
| -
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - Animation* animation = animations_[i];
|
| - if (!animation->is_impl_only())
|
| - continue;
|
| -
|
| - if (!animation->InEffect(monotonic_time))
|
| - continue;
|
| -
|
| - base::TimeDelta trimmed =
|
| - animation->TrimTimeToCurrentIteration(monotonic_time);
|
| - switch (animation->target_property()) {
|
| - case Animation::OPACITY: {
|
| - AnimationEvent event(AnimationEvent::PROPERTY_UPDATE, id_,
|
| - animation->group(), Animation::OPACITY,
|
| - monotonic_time);
|
| - const FloatAnimationCurve* float_animation_curve =
|
| - animation->curve()->ToFloatAnimationCurve();
|
| - event.opacity = float_animation_curve->GetValue(trimmed);
|
| - event.is_impl_only = true;
|
| - events->push_back(event);
|
| - break;
|
| - }
|
| -
|
| - case Animation::TRANSFORM: {
|
| - AnimationEvent event(AnimationEvent::PROPERTY_UPDATE, id_,
|
| - animation->group(), Animation::TRANSFORM,
|
| - monotonic_time);
|
| - const TransformAnimationCurve* transform_animation_curve =
|
| - animation->curve()->ToTransformAnimationCurve();
|
| - event.transform = transform_animation_curve->GetValue(trimmed);
|
| - event.is_impl_only = true;
|
| - events->push_back(event);
|
| - break;
|
| - }
|
| -
|
| - case Animation::FILTER: {
|
| - AnimationEvent event(AnimationEvent::PROPERTY_UPDATE, id_,
|
| - animation->group(), Animation::FILTER,
|
| - monotonic_time);
|
| - const FilterAnimationCurve* filter_animation_curve =
|
| - animation->curve()->ToFilterAnimationCurve();
|
| - event.filters = filter_animation_curve->GetValue(trimmed);
|
| - event.is_impl_only = true;
|
| - events->push_back(event);
|
| - break;
|
| - }
|
| -
|
| - case Animation::BACKGROUND_COLOR: {
|
| - break;
|
| - }
|
| -
|
| - case Animation::SCROLL_OFFSET: {
|
| - // Impl-side changes to scroll offset are already sent back to the
|
| - // main thread (e.g. for user-driven scrolling), so a PROPERTY_UPDATE
|
| - // isn't needed.
|
| - break;
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void LayerAnimationController::UpdateState(bool start_ready_animations,
|
| - AnimationEventsVector* events) {
|
| - if (!HasActiveValueObserver())
|
| - return;
|
| -
|
| - // Animate hasn't been called, this happens if an observer has been added
|
| - // between the Commit and Draw phases.
|
| - if (last_tick_time_ == base::TimeTicks())
|
| - return;
|
| -
|
| - if (start_ready_animations)
|
| - PromoteStartedAnimations(last_tick_time_, events);
|
| -
|
| - MarkFinishedAnimations(last_tick_time_);
|
| - MarkAnimationsForDeletion(last_tick_time_, events);
|
| -
|
| - if (needs_to_start_animations_ && start_ready_animations) {
|
| - StartAnimations(last_tick_time_);
|
| - PromoteStartedAnimations(last_tick_time_, events);
|
| - }
|
| -
|
| - AccumulatePropertyUpdates(last_tick_time_, events);
|
| -
|
| - UpdateActivation(NORMAL_ACTIVATION);
|
| -}
|
| -
|
| -struct AffectsNoObservers {
|
| - bool operator()(Animation* animation) const {
|
| - return !animation->affects_active_observers() &&
|
| - !animation->affects_pending_observers();
|
| - }
|
| -};
|
| -
|
| -void LayerAnimationController::ActivateAnimations() {
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - animations_[i]->set_affects_active_observers(
|
| - animations_[i]->affects_pending_observers());
|
| - }
|
| - animations_.erase(cc::remove_if(&animations_,
|
| - animations_.begin(),
|
| - animations_.end(),
|
| - AffectsNoObservers()),
|
| - animations_.end());
|
| - scroll_offset_animation_was_interrupted_ = false;
|
| - UpdateActivation(NORMAL_ACTIVATION);
|
| -}
|
| -
|
| -void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) {
|
| - animations_.push_back(animation.Pass());
|
| - needs_to_start_animations_ = true;
|
| - UpdateActivation(NORMAL_ACTIVATION);
|
| -}
|
| -
|
| -Animation* LayerAnimationController::GetAnimation(
|
| - Animation::TargetProperty target_property) const {
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - size_t index = animations_.size() - i - 1;
|
| - if (animations_[index]->target_property() == target_property)
|
| - return animations_[index];
|
| - }
|
| - return 0;
|
| -}
|
| -
|
| -Animation* LayerAnimationController::GetAnimationById(int animation_id) const {
|
| - for (size_t i = 0; i < animations_.size(); ++i)
|
| - if (animations_[i]->id() == animation_id)
|
| - return animations_[i];
|
| - return nullptr;
|
| -}
|
| -
|
| -bool LayerAnimationController::HasActiveAnimation() const {
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (!animations_[i]->is_finished())
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -bool LayerAnimationController::IsAnimatingProperty(
|
| - Animation::TargetProperty target_property) const {
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (!animations_[i]->is_finished() &&
|
| - animations_[i]->InEffect(last_tick_time_) &&
|
| - animations_[i]->target_property() == target_property)
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -void LayerAnimationController::SetAnimationRegistrar(
|
| - AnimationRegistrar* registrar) {
|
| - if (registrar_ == registrar)
|
| - return;
|
| -
|
| - if (registrar_)
|
| - registrar_->UnregisterAnimationController(this);
|
| -
|
| - registrar_ = registrar;
|
| - if (registrar_)
|
| - registrar_->RegisterAnimationController(this);
|
| -
|
| - UpdateActivation(FORCE_ACTIVATION);
|
| -}
|
| -
|
| -void LayerAnimationController::NotifyAnimationStarted(
|
| - const AnimationEvent& event) {
|
| - if (event.is_impl_only) {
|
| - FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
|
| - OnAnimationStarted(event));
|
| - if (layer_animation_delegate_)
|
| - layer_animation_delegate_->NotifyAnimationStarted(
|
| - event.monotonic_time, event.target_property, event.group_id);
|
| - return;
|
| - }
|
| -
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (animations_[i]->group() == event.group_id &&
|
| - animations_[i]->target_property() == event.target_property &&
|
| - animations_[i]->needs_synchronized_start_time()) {
|
| - animations_[i]->set_needs_synchronized_start_time(false);
|
| - if (!animations_[i]->has_set_start_time())
|
| - animations_[i]->set_start_time(event.monotonic_time);
|
| -
|
| - FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
|
| - OnAnimationStarted(event));
|
| - if (layer_animation_delegate_)
|
| - layer_animation_delegate_->NotifyAnimationStarted(
|
| - event.monotonic_time, event.target_property, event.group_id);
|
| -
|
| - return;
|
| - }
|
| - }
|
| -}
|
| -
|
| -void LayerAnimationController::NotifyAnimationFinished(
|
| - const AnimationEvent& event) {
|
| - if (event.is_impl_only) {
|
| - if (layer_animation_delegate_)
|
| - layer_animation_delegate_->NotifyAnimationFinished(
|
| - event.monotonic_time, event.target_property, event.group_id);
|
| - return;
|
| - }
|
| -
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (animations_[i]->group() == event.group_id &&
|
| - animations_[i]->target_property() == event.target_property) {
|
| - animations_[i]->set_received_finished_event(true);
|
| - if (layer_animation_delegate_)
|
| - layer_animation_delegate_->NotifyAnimationFinished(
|
| - event.monotonic_time, event.target_property, event.group_id);
|
| -
|
| - return;
|
| - }
|
| - }
|
| -}
|
| -
|
| -void LayerAnimationController::NotifyAnimationAborted(
|
| - const AnimationEvent& event) {
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (animations_[i]->group() == event.group_id &&
|
| - animations_[i]->target_property() == event.target_property) {
|
| - animations_[i]->SetRunState(Animation::ABORTED, event.monotonic_time);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void LayerAnimationController::NotifyAnimationPropertyUpdate(
|
| - const AnimationEvent& event) {
|
| - bool notify_active_observers = true;
|
| - bool notify_pending_observers = true;
|
| - switch (event.target_property) {
|
| - case Animation::OPACITY:
|
| - NotifyObserversOpacityAnimated(
|
| - event.opacity, notify_active_observers, notify_pending_observers);
|
| - break;
|
| - case Animation::TRANSFORM:
|
| - NotifyObserversTransformAnimated(
|
| - event.transform, notify_active_observers, notify_pending_observers);
|
| - break;
|
| - default:
|
| - NOTREACHED();
|
| - }
|
| -}
|
| -
|
| -void LayerAnimationController::AddValueObserver(
|
| - LayerAnimationValueObserver* observer) {
|
| - if (!value_observers_.HasObserver(observer))
|
| - value_observers_.AddObserver(observer);
|
| -}
|
| -
|
| -void LayerAnimationController::RemoveValueObserver(
|
| - LayerAnimationValueObserver* observer) {
|
| - value_observers_.RemoveObserver(observer);
|
| -}
|
| -
|
| -void LayerAnimationController::AddEventObserver(
|
| - LayerAnimationEventObserver* observer) {
|
| - if (!event_observers_.HasObserver(observer))
|
| - event_observers_.AddObserver(observer);
|
| -}
|
| -
|
| -void LayerAnimationController::RemoveEventObserver(
|
| - LayerAnimationEventObserver* observer) {
|
| - event_observers_.RemoveObserver(observer);
|
| -}
|
| -
|
| -bool LayerAnimationController::HasFilterAnimationThatInflatesBounds() const {
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (!animations_[i]->is_finished() &&
|
| - animations_[i]->target_property() == Animation::FILTER &&
|
| - animations_[i]
|
| - ->curve()
|
| - ->ToFilterAnimationCurve()
|
| - ->HasFilterThatMovesPixels())
|
| - return true;
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| -bool LayerAnimationController::HasTransformAnimationThatInflatesBounds() const {
|
| - return IsAnimatingProperty(Animation::TRANSFORM);
|
| -}
|
| -
|
| -bool LayerAnimationController::FilterAnimationBoundsForBox(
|
| - const gfx::BoxF& box, gfx::BoxF* bounds) const {
|
| - // TODO(avallee): Implement.
|
| - return false;
|
| -}
|
| -
|
| -bool LayerAnimationController::TransformAnimationBoundsForBox(
|
| - const gfx::BoxF& box,
|
| - gfx::BoxF* bounds) const {
|
| - DCHECK(HasTransformAnimationThatInflatesBounds())
|
| - << "TransformAnimationBoundsForBox will give incorrect results if there "
|
| - << "are no transform animations affecting bounds, non-animated transform "
|
| - << "is not known";
|
| -
|
| - // Compute bounds based on animations for which is_finished() is false.
|
| - // Do nothing if there are no such animations; in this case, it is assumed
|
| - // that callers will take care of computing bounds based on the owning layer's
|
| - // actual transform.
|
| - *bounds = gfx::BoxF();
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (animations_[i]->is_finished() ||
|
| - animations_[i]->target_property() != Animation::TRANSFORM)
|
| - continue;
|
| -
|
| - const TransformAnimationCurve* transform_animation_curve =
|
| - animations_[i]->curve()->ToTransformAnimationCurve();
|
| - gfx::BoxF animation_bounds;
|
| - bool success =
|
| - transform_animation_curve->AnimatedBoundsForBox(box, &animation_bounds);
|
| - if (!success)
|
| - return false;
|
| - bounds->Union(animation_bounds);
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool LayerAnimationController::HasAnimationThatAffectsScale() const {
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (animations_[i]->is_finished() ||
|
| - animations_[i]->target_property() != Animation::TRANSFORM)
|
| - continue;
|
| -
|
| - const TransformAnimationCurve* transform_animation_curve =
|
| - animations_[i]->curve()->ToTransformAnimationCurve();
|
| - if (transform_animation_curve->AffectsScale())
|
| - return true;
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| -bool LayerAnimationController::HasOnlyTranslationTransforms() const {
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (animations_[i]->is_finished() ||
|
| - animations_[i]->target_property() != Animation::TRANSFORM)
|
| - continue;
|
| -
|
| - const TransformAnimationCurve* transform_animation_curve =
|
| - animations_[i]->curve()->ToTransformAnimationCurve();
|
| - if (!transform_animation_curve->IsTranslation())
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool LayerAnimationController::AnimationsPreserveAxisAlignment() const {
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (animations_[i]->is_finished() ||
|
| - animations_[i]->target_property() != Animation::TRANSFORM)
|
| - continue;
|
| -
|
| - const TransformAnimationCurve* transform_animation_curve =
|
| - animations_[i]->curve()->ToTransformAnimationCurve();
|
| - if (!transform_animation_curve->PreservesAxisAlignment())
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool LayerAnimationController::MaximumTargetScale(float* max_scale) const {
|
| - *max_scale = 0.f;
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (animations_[i]->is_finished() ||
|
| - animations_[i]->target_property() != Animation::TRANSFORM)
|
| - continue;
|
| -
|
| - bool forward_direction = true;
|
| - switch (animations_[i]->direction()) {
|
| - case Animation::DIRECTION_NORMAL:
|
| - case Animation::DIRECTION_ALTERNATE:
|
| - forward_direction = animations_[i]->playback_rate() >= 0.0;
|
| - break;
|
| - case Animation::DIRECTION_REVERSE:
|
| - case Animation::DIRECTION_ALTERNATE_REVERSE:
|
| - forward_direction = animations_[i]->playback_rate() < 0.0;
|
| - break;
|
| - }
|
| -
|
| - const TransformAnimationCurve* transform_animation_curve =
|
| - animations_[i]->curve()->ToTransformAnimationCurve();
|
| - float animation_scale = 0.f;
|
| - if (!transform_animation_curve->MaximumTargetScale(forward_direction,
|
| - &animation_scale))
|
| - return false;
|
| - *max_scale = std::max(*max_scale, animation_scale);
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void LayerAnimationController::PushNewAnimationsToImplThread(
|
| - LayerAnimationController* controller_impl) const {
|
| - // Any new animations owned by the main thread's controller are cloned and
|
| - // add to the impl thread's controller.
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - // If the animation is already running on the impl thread, there is no
|
| - // need to copy it over.
|
| - if (controller_impl->GetAnimationById(animations_[i]->id()))
|
| - continue;
|
| -
|
| - // If the animation is not running on the impl thread, it does not
|
| - // necessarily mean that it needs to be copied over and started; it may
|
| - // have already finished. In this case, the impl thread animation will
|
| - // have already notified that it has started and the main thread animation
|
| - // will no longer need
|
| - // a synchronized start time.
|
| - if (!animations_[i]->needs_synchronized_start_time())
|
| - continue;
|
| -
|
| - // Scroll animations always start at the current scroll offset.
|
| - if (animations_[i]->target_property() == Animation::SCROLL_OFFSET) {
|
| - gfx::ScrollOffset current_scroll_offset;
|
| - if (controller_impl->value_provider_) {
|
| - current_scroll_offset =
|
| - controller_impl->value_provider_->ScrollOffsetForAnimation();
|
| - } else {
|
| - // The owning layer isn't yet in the active tree, so the main thread
|
| - // scroll offset will be up-to-date.
|
| - current_scroll_offset = value_provider_->ScrollOffsetForAnimation();
|
| - }
|
| - animations_[i]->curve()->ToScrollOffsetAnimationCurve()->SetInitialValue(
|
| - current_scroll_offset);
|
| - }
|
| -
|
| - // The new animation should be set to run as soon as possible.
|
| - Animation::RunState initial_run_state =
|
| - Animation::WAITING_FOR_TARGET_AVAILABILITY;
|
| - scoped_ptr<Animation> to_add(
|
| - animations_[i]->CloneAndInitialize(initial_run_state));
|
| - DCHECK(!to_add->needs_synchronized_start_time());
|
| - to_add->set_affects_active_observers(false);
|
| - controller_impl->AddAnimation(to_add.Pass());
|
| - }
|
| -}
|
| -
|
| -static bool IsCompleted(
|
| - Animation* animation,
|
| - const LayerAnimationController* main_thread_controller) {
|
| - if (animation->is_impl_only()) {
|
| - return (animation->run_state() == Animation::WAITING_FOR_DELETION);
|
| - } else {
|
| - return !main_thread_controller->GetAnimationById(animation->id());
|
| - }
|
| -}
|
| -
|
| -static bool AffectsActiveOnlyAndIsWaitingForDeletion(Animation* animation) {
|
| - return animation->run_state() == Animation::WAITING_FOR_DELETION &&
|
| - !animation->affects_pending_observers();
|
| -}
|
| -
|
| -void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
|
| - LayerAnimationController* controller_impl) const {
|
| - // Animations removed on the main thread should no longer affect pending
|
| - // observers, and should stop affecting active observers after the next call
|
| - // to ActivateAnimations. If already WAITING_FOR_DELETION, they can be removed
|
| - // immediately.
|
| - ScopedPtrVector<Animation>& animations = controller_impl->animations_;
|
| - for (size_t i = 0; i < animations.size(); ++i) {
|
| - if (IsCompleted(animations[i], this))
|
| - animations[i]->set_affects_pending_observers(false);
|
| - }
|
| - animations.erase(cc::remove_if(&animations,
|
| - animations.begin(),
|
| - animations.end(),
|
| - AffectsActiveOnlyAndIsWaitingForDeletion),
|
| - animations.end());
|
| -}
|
| -
|
| -void LayerAnimationController::PushPropertiesToImplThread(
|
| - LayerAnimationController* controller_impl) {
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - Animation* current_impl =
|
| - controller_impl->GetAnimationById(animations_[i]->id());
|
| - if (current_impl)
|
| - animations_[i]->PushPropertiesTo(current_impl);
|
| - }
|
| - controller_impl->scroll_offset_animation_was_interrupted_ =
|
| - scroll_offset_animation_was_interrupted_;
|
| - scroll_offset_animation_was_interrupted_ = false;
|
| -}
|
| -
|
| -void LayerAnimationController::StartAnimations(base::TimeTicks monotonic_time) {
|
| - DCHECK(needs_to_start_animations_);
|
| - needs_to_start_animations_ = false;
|
| - // First collect running properties affecting each type of observer.
|
| - TargetProperties blocked_properties_for_active_observers;
|
| - TargetProperties blocked_properties_for_pending_observers;
|
| - std::vector<size_t> animations_waiting_for_target;
|
| -
|
| - animations_waiting_for_target.reserve(animations_.size());
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (animations_[i]->run_state() == Animation::STARTING ||
|
| - animations_[i]->run_state() == Animation::RUNNING) {
|
| - if (animations_[i]->affects_active_observers()) {
|
| - blocked_properties_for_active_observers.insert(
|
| - animations_[i]->target_property());
|
| - }
|
| - if (animations_[i]->affects_pending_observers()) {
|
| - blocked_properties_for_pending_observers.insert(
|
| - animations_[i]->target_property());
|
| - }
|
| - } else if (animations_[i]->run_state() ==
|
| - Animation::WAITING_FOR_TARGET_AVAILABILITY) {
|
| - animations_waiting_for_target.push_back(i);
|
| - }
|
| - }
|
| -
|
| - for (size_t i = 0; i < animations_waiting_for_target.size(); ++i) {
|
| - // Collect all properties for animations with the same group id (they
|
| - // should all also be in the list of animations).
|
| - size_t animation_index = animations_waiting_for_target[i];
|
| - Animation* animation_waiting_for_target = animations_[animation_index];
|
| - // Check for the run state again even though the animation was waiting
|
| - // for target because it might have changed the run state while handling
|
| - // previous animation in this loop (if they belong to same group).
|
| - if (animation_waiting_for_target->run_state() ==
|
| - Animation::WAITING_FOR_TARGET_AVAILABILITY) {
|
| - TargetProperties enqueued_properties;
|
| - bool affects_active_observers =
|
| - animation_waiting_for_target->affects_active_observers();
|
| - bool affects_pending_observers =
|
| - animation_waiting_for_target->affects_pending_observers();
|
| - enqueued_properties.insert(
|
| - animation_waiting_for_target->target_property());
|
| - for (size_t j = animation_index + 1; j < animations_.size(); ++j) {
|
| - if (animation_waiting_for_target->group() == animations_[j]->group()) {
|
| - enqueued_properties.insert(animations_[j]->target_property());
|
| - affects_active_observers |=
|
| - animations_[j]->affects_active_observers();
|
| - affects_pending_observers |=
|
| - animations_[j]->affects_pending_observers();
|
| - }
|
| - }
|
| -
|
| - // Check to see if intersection of the list of properties affected by
|
| - // the group and the list of currently blocked properties is null, taking
|
| - // into account the type(s) of observers affected by the group. In any
|
| - // case, the group's target properties need to be added to the lists of
|
| - // blocked properties.
|
| - bool null_intersection = true;
|
| - for (TargetProperties::iterator p_iter = enqueued_properties.begin();
|
| - p_iter != enqueued_properties.end();
|
| - ++p_iter) {
|
| - if (affects_active_observers &&
|
| - !blocked_properties_for_active_observers.insert(*p_iter).second)
|
| - null_intersection = false;
|
| - if (affects_pending_observers &&
|
| - !blocked_properties_for_pending_observers.insert(*p_iter).second)
|
| - null_intersection = false;
|
| - }
|
| -
|
| - // If the intersection is null, then we are free to start the animations
|
| - // in the group.
|
| - if (null_intersection) {
|
| - animation_waiting_for_target->SetRunState(Animation::STARTING,
|
| - monotonic_time);
|
| - for (size_t j = animation_index + 1; j < animations_.size(); ++j) {
|
| - if (animation_waiting_for_target->group() ==
|
| - animations_[j]->group()) {
|
| - animations_[j]->SetRunState(Animation::STARTING, monotonic_time);
|
| - }
|
| - }
|
| - } else {
|
| - needs_to_start_animations_ = true;
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void LayerAnimationController::PromoteStartedAnimations(
|
| - base::TimeTicks monotonic_time,
|
| - AnimationEventsVector* events) {
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (animations_[i]->run_state() == Animation::STARTING &&
|
| - animations_[i]->affects_active_observers()) {
|
| - animations_[i]->SetRunState(Animation::RUNNING, monotonic_time);
|
| - if (!animations_[i]->has_set_start_time() &&
|
| - !animations_[i]->needs_synchronized_start_time())
|
| - animations_[i]->set_start_time(monotonic_time);
|
| - if (events) {
|
| - AnimationEvent started_event(
|
| - AnimationEvent::STARTED, id_, animations_[i]->group(),
|
| - animations_[i]->target_property(), monotonic_time);
|
| - started_event.is_impl_only = animations_[i]->is_impl_only();
|
| - if (started_event.is_impl_only)
|
| - NotifyAnimationStarted(started_event);
|
| - else
|
| - events->push_back(started_event);
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void LayerAnimationController::MarkFinishedAnimations(
|
| - base::TimeTicks monotonic_time) {
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (animations_[i]->IsFinishedAt(monotonic_time) &&
|
| - animations_[i]->run_state() != Animation::ABORTED &&
|
| - animations_[i]->run_state() != Animation::WAITING_FOR_DELETION)
|
| - animations_[i]->SetRunState(Animation::FINISHED, monotonic_time);
|
| - }
|
| -}
|
| -
|
| -void LayerAnimationController::MarkAnimationsForDeletion(
|
| - base::TimeTicks monotonic_time,
|
| - AnimationEventsVector* events) {
|
| - bool marked_animations_for_deletions = false;
|
| - std::vector<size_t> animations_with_same_group_id;
|
| -
|
| - animations_with_same_group_id.reserve(animations_.size());
|
| - // Non-aborted animations are marked for deletion after a corresponding
|
| - // AnimationEvent::FINISHED event is sent or received. This means that if
|
| - // we don't have an events vector, we must ensure that non-aborted animations
|
| - // have received a finished event before marking them for deletion.
|
| - for (size_t i = 0; i < animations_.size(); i++) {
|
| - int group_id = animations_[i]->group();
|
| - if (animations_[i]->run_state() == Animation::ABORTED) {
|
| - if (events && !animations_[i]->is_impl_only()) {
|
| - AnimationEvent aborted_event(AnimationEvent::ABORTED, id_, group_id,
|
| - animations_[i]->target_property(),
|
| - monotonic_time);
|
| - events->push_back(aborted_event);
|
| - }
|
| - animations_[i]->SetRunState(Animation::WAITING_FOR_DELETION,
|
| - monotonic_time);
|
| - marked_animations_for_deletions = true;
|
| - continue;
|
| - }
|
| -
|
| - bool all_anims_with_same_id_are_finished = false;
|
| -
|
| - // Since deleting an animation on the main thread leads to its deletion
|
| - // on the impl thread, we only mark a FINISHED main thread animation for
|
| - // deletion once it has received a FINISHED event from the impl thread.
|
| - bool animation_i_will_send_or_has_received_finish_event =
|
| - events || animations_[i]->received_finished_event();
|
| - // If an animation is finished, and not already marked for deletion,
|
| - // find out if all other animations in the same group are also finished.
|
| - if (animations_[i]->run_state() == Animation::FINISHED &&
|
| - animation_i_will_send_or_has_received_finish_event) {
|
| - // Clear the animations_with_same_group_id if it was added for
|
| - // the previous animation's iteration.
|
| - if (animations_with_same_group_id.size() > 0)
|
| - animations_with_same_group_id.clear();
|
| - all_anims_with_same_id_are_finished = true;
|
| - for (size_t j = 0; j < animations_.size(); ++j) {
|
| - bool animation_j_will_send_or_has_received_finish_event =
|
| - events || animations_[j]->received_finished_event();
|
| - if (group_id == animations_[j]->group()) {
|
| - if (!animations_[j]->is_finished() ||
|
| - (animations_[j]->run_state() == Animation::FINISHED &&
|
| - !animation_j_will_send_or_has_received_finish_event)) {
|
| - all_anims_with_same_id_are_finished = false;
|
| - break;
|
| - } else if (j >= i &&
|
| - animations_[j]->run_state() != Animation::ABORTED) {
|
| - // Mark down the animations which belong to the same group
|
| - // and is not yet aborted. If this current iteration finds that all
|
| - // animations with same ID are finished, then the marked
|
| - // animations below will be set to WAITING_FOR_DELETION in next
|
| - // iteration.
|
| - animations_with_same_group_id.push_back(j);
|
| - }
|
| - }
|
| - }
|
| - }
|
| - if (all_anims_with_same_id_are_finished) {
|
| - // We now need to remove all animations with the same group id as
|
| - // group_id (and send along animation finished notifications, if
|
| - // necessary).
|
| - for (size_t j = 0; j < animations_with_same_group_id.size(); j++) {
|
| - size_t animation_index = animations_with_same_group_id[j];
|
| - if (events) {
|
| - AnimationEvent finished_event(
|
| - AnimationEvent::FINISHED, id_,
|
| - animations_[animation_index]->group(),
|
| - animations_[animation_index]->target_property(),
|
| - monotonic_time);
|
| - finished_event.is_impl_only =
|
| - animations_[animation_index]->is_impl_only();
|
| - if (finished_event.is_impl_only)
|
| - NotifyAnimationFinished(finished_event);
|
| - else
|
| - events->push_back(finished_event);
|
| - }
|
| - animations_[animation_index]->SetRunState(
|
| - Animation::WAITING_FOR_DELETION, monotonic_time);
|
| - }
|
| - marked_animations_for_deletions = true;
|
| - }
|
| - }
|
| - if (marked_animations_for_deletions)
|
| - NotifyObserversAnimationWaitingForDeletion();
|
| -}
|
| -
|
| -static bool IsWaitingForDeletion(Animation* animation) {
|
| - return animation->run_state() == Animation::WAITING_FOR_DELETION;
|
| -}
|
| -
|
| -void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
|
| - animations_.erase(cc::remove_if(&animations_,
|
| - animations_.begin(),
|
| - animations_.end(),
|
| - IsWaitingForDeletion),
|
| - animations_.end());
|
| -}
|
| -
|
| -void LayerAnimationController::TickAnimations(base::TimeTicks monotonic_time) {
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (animations_[i]->run_state() == Animation::STARTING ||
|
| - animations_[i]->run_state() == Animation::RUNNING ||
|
| - animations_[i]->run_state() == Animation::PAUSED) {
|
| - if (!animations_[i]->InEffect(monotonic_time))
|
| - continue;
|
| -
|
| - base::TimeDelta trimmed =
|
| - animations_[i]->TrimTimeToCurrentIteration(monotonic_time);
|
| -
|
| - switch (animations_[i]->target_property()) {
|
| - case Animation::TRANSFORM: {
|
| - const TransformAnimationCurve* transform_animation_curve =
|
| - animations_[i]->curve()->ToTransformAnimationCurve();
|
| - const gfx::Transform transform =
|
| - transform_animation_curve->GetValue(trimmed);
|
| - NotifyObserversTransformAnimated(
|
| - transform,
|
| - animations_[i]->affects_active_observers(),
|
| - animations_[i]->affects_pending_observers());
|
| - break;
|
| - }
|
| -
|
| - case Animation::OPACITY: {
|
| - const FloatAnimationCurve* float_animation_curve =
|
| - animations_[i]->curve()->ToFloatAnimationCurve();
|
| - const float opacity = std::max(
|
| - std::min(float_animation_curve->GetValue(trimmed), 1.0f), 0.f);
|
| - NotifyObserversOpacityAnimated(
|
| - opacity,
|
| - animations_[i]->affects_active_observers(),
|
| - animations_[i]->affects_pending_observers());
|
| - break;
|
| - }
|
| -
|
| - case Animation::FILTER: {
|
| - const FilterAnimationCurve* filter_animation_curve =
|
| - animations_[i]->curve()->ToFilterAnimationCurve();
|
| - const FilterOperations filter =
|
| - filter_animation_curve->GetValue(trimmed);
|
| - NotifyObserversFilterAnimated(
|
| - filter,
|
| - animations_[i]->affects_active_observers(),
|
| - animations_[i]->affects_pending_observers());
|
| - break;
|
| - }
|
| -
|
| - case Animation::BACKGROUND_COLOR: {
|
| - // Not yet implemented.
|
| - break;
|
| - }
|
| -
|
| - case Animation::SCROLL_OFFSET: {
|
| - const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
|
| - animations_[i]->curve()->ToScrollOffsetAnimationCurve();
|
| - const gfx::ScrollOffset scroll_offset =
|
| - scroll_offset_animation_curve->GetValue(trimmed);
|
| - NotifyObserversScrollOffsetAnimated(
|
| - scroll_offset,
|
| - animations_[i]->affects_active_observers(),
|
| - animations_[i]->affects_pending_observers());
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void LayerAnimationController::UpdateActivation(UpdateActivationType type) {
|
| - bool force = type == FORCE_ACTIVATION;
|
| - if (registrar_) {
|
| - bool was_active = is_active_;
|
| - is_active_ = false;
|
| - for (size_t i = 0; i < animations_.size(); ++i) {
|
| - if (animations_[i]->run_state() != Animation::WAITING_FOR_DELETION) {
|
| - is_active_ = true;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - if (is_active_ && (!was_active || force))
|
| - registrar_->DidActivateAnimationController(this);
|
| - else if (!is_active_ && (was_active || force))
|
| - registrar_->DidDeactivateAnimationController(this);
|
| - }
|
| -}
|
| -
|
| -void LayerAnimationController::NotifyObserversOpacityAnimated(
|
| - float opacity,
|
| - bool notify_active_observers,
|
| - bool notify_pending_observers) {
|
| - if (value_observers_.might_have_observers()) {
|
| - ObserverListBase<LayerAnimationValueObserver>::Iterator it(
|
| - &value_observers_);
|
| - LayerAnimationValueObserver* obs;
|
| - while ((obs = it.GetNext()) != nullptr) {
|
| - if ((notify_active_observers && notify_pending_observers) ||
|
| - (notify_active_observers && obs->IsActive()) ||
|
| - (notify_pending_observers && !obs->IsActive()))
|
| - obs->OnOpacityAnimated(opacity);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void LayerAnimationController::NotifyObserversTransformAnimated(
|
| - const gfx::Transform& transform,
|
| - bool notify_active_observers,
|
| - bool notify_pending_observers) {
|
| - if (value_observers_.might_have_observers()) {
|
| - ObserverListBase<LayerAnimationValueObserver>::Iterator it(
|
| - &value_observers_);
|
| - LayerAnimationValueObserver* obs;
|
| - while ((obs = it.GetNext()) != nullptr) {
|
| - if ((notify_active_observers && notify_pending_observers) ||
|
| - (notify_active_observers && obs->IsActive()) ||
|
| - (notify_pending_observers && !obs->IsActive()))
|
| - obs->OnTransformAnimated(transform);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void LayerAnimationController::NotifyObserversFilterAnimated(
|
| - const FilterOperations& filters,
|
| - bool notify_active_observers,
|
| - bool notify_pending_observers) {
|
| - if (value_observers_.might_have_observers()) {
|
| - ObserverListBase<LayerAnimationValueObserver>::Iterator it(
|
| - &value_observers_);
|
| - LayerAnimationValueObserver* obs;
|
| - while ((obs = it.GetNext()) != nullptr) {
|
| - if ((notify_active_observers && notify_pending_observers) ||
|
| - (notify_active_observers && obs->IsActive()) ||
|
| - (notify_pending_observers && !obs->IsActive()))
|
| - obs->OnFilterAnimated(filters);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void LayerAnimationController::NotifyObserversScrollOffsetAnimated(
|
| - const gfx::ScrollOffset& scroll_offset,
|
| - bool notify_active_observers,
|
| - bool notify_pending_observers) {
|
| - if (value_observers_.might_have_observers()) {
|
| - ObserverListBase<LayerAnimationValueObserver>::Iterator it(
|
| - &value_observers_);
|
| - LayerAnimationValueObserver* obs;
|
| - while ((obs = it.GetNext()) != nullptr) {
|
| - if ((notify_active_observers && notify_pending_observers) ||
|
| - (notify_active_observers && obs->IsActive()) ||
|
| - (notify_pending_observers && !obs->IsActive()))
|
| - obs->OnScrollOffsetAnimated(scroll_offset);
|
| - }
|
| - }
|
| -}
|
| -
|
| -void LayerAnimationController::NotifyObserversAnimationWaitingForDeletion() {
|
| - FOR_EACH_OBSERVER(LayerAnimationValueObserver,
|
| - value_observers_,
|
| - OnAnimationWaitingForDeletion());
|
| -}
|
| -
|
| -bool LayerAnimationController::HasValueObserver() {
|
| - if (value_observers_.might_have_observers()) {
|
| - ObserverListBase<LayerAnimationValueObserver>::Iterator it(
|
| - &value_observers_);
|
| - return it.GetNext() != nullptr;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -bool LayerAnimationController::HasActiveValueObserver() {
|
| - if (value_observers_.might_have_observers()) {
|
| - ObserverListBase<LayerAnimationValueObserver>::Iterator it(
|
| - &value_observers_);
|
| - LayerAnimationValueObserver* obs;
|
| - while ((obs = it.GetNext()) != nullptr)
|
| - if (obs->IsActive())
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -} // namespace cc
|
|
|