This source file includes following definitions.
- layer_animation_delegate_
- Create
- PauseAnimation
- RemoveAnimation
- RemoveAnimation
- AbortAnimations
- PushAnimationUpdatesTo
- Animate
- AccumulatePropertyUpdates
- UpdateState
- AddAnimation
- GetAnimation
- GetAnimation
- HasActiveAnimation
- IsAnimatingProperty
- SetAnimationRegistrar
- NotifyAnimationStarted
- NotifyAnimationFinished
- NotifyAnimationAborted
- NotifyAnimationPropertyUpdate
- AddValueObserver
- RemoveValueObserver
- AddEventObserver
- RemoveEventObserver
- HasFilterAnimationThatInflatesBounds
- HasTransformAnimationThatInflatesBounds
- FilterAnimationBoundsForBox
- TransformAnimationBoundsForBox
- HasAnimationThatAffectsScale
- HasOnlyTranslationTransforms
- MaximumScale
- PushNewAnimationsToImplThread
- RemoveAnimationsCompletedOnMainThread
- PushPropertiesToImplThread
- StartAnimations
- PromoteStartedAnimations
- MarkFinishedAnimations
- MarkAnimationsForDeletion
- IsWaitingForDeletion
- PurgeAnimationsMarkedForDeletion
- TickAnimations
- UpdateActivation
- NotifyObserversOpacityAnimated
- NotifyObserversTransformAnimated
- NotifyObserversFilterAnimated
- NotifyObserversScrollOffsetAnimated
- NotifyObserversAnimationWaitingForDeletion
- HasValueObserver
- HasActiveValueObserver
#include "cc/animation/layer_animation_controller.h"
#include <algorithm>
#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/box_f.h"
#include "ui/gfx/transform.h"
namespace cc {
LayerAnimationController::LayerAnimationController(int id)
: registrar_(0),
id_(id),
is_active_(false),
last_tick_time_(0),
value_provider_(NULL),
layer_animation_delegate_(NULL) {}
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,
double time_offset) {
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (active_animations_[i]->id() == animation_id) {
active_animations_[i]->SetRunState(
Animation::Paused, time_offset + active_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) {
ScopedPtrVector<Animation>& animations = active_animations_;
animations.erase(cc::remove_if(&animations,
animations.begin(),
animations.end(),
HasAnimationId(animation_id)),
animations.end());
UpdateActivation(NormalActivation);
}
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) {
ScopedPtrVector<Animation>& animations = active_animations_;
animations.erase(
cc::remove_if(&animations,
animations.begin(),
animations.end(),
HasAnimationIdAndProperty(animation_id, target_property)),
animations.end());
UpdateActivation(NormalActivation);
}
void LayerAnimationController::AbortAnimations(
Animation::TargetProperty target_property) {
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (active_animations_[i]->target_property() == target_property &&
!active_animations_[i]->is_finished())
active_animations_[i]->SetRunState(Animation::Aborted, last_tick_time_);
}
}
void LayerAnimationController::PushAnimationUpdatesTo(
LayerAnimationController* controller_impl) {
DCHECK(this != controller_impl);
if (!has_any_animation() && !controller_impl->has_any_animation())
return;
PurgeAnimationsMarkedForDeletion();
PushNewAnimationsToImplThread(controller_impl);
RemoveAnimationsCompletedOnMainThread(controller_impl);
PushPropertiesToImplThread(controller_impl);
controller_impl->UpdateActivation(NormalActivation);
UpdateActivation(NormalActivation);
}
void LayerAnimationController::Animate(double monotonic_time) {
DCHECK(monotonic_time);
if (!HasValueObserver())
return;
StartAnimations(monotonic_time);
TickAnimations(monotonic_time);
last_tick_time_ = monotonic_time;
}
void LayerAnimationController::AccumulatePropertyUpdates(
double monotonic_time,
AnimationEventsVector* events) {
if (!events)
return;
for (size_t i = 0; i < active_animations_.size(); ++i) {
Animation* animation = active_animations_[i];
if (!animation->is_impl_only())
continue;
double trimmed = animation->TrimTimeToCurrentIteration(monotonic_time);
switch (animation->target_property()) {
case Animation::Opacity: {
AnimationEvent event(AnimationEvent::PropertyUpdate,
id_,
animation->group(),
Animation::Opacity,
monotonic_time);
event.opacity = animation->curve()->ToFloatAnimationCurve()->GetValue(
trimmed);
event.is_impl_only = true;
events->push_back(event);
break;
}
case Animation::Transform: {
AnimationEvent event(AnimationEvent::PropertyUpdate,
id_,
animation->group(),
Animation::Transform,
monotonic_time);
event.transform =
animation->curve()->ToTransformAnimationCurve()->GetValue(trimmed);
event.is_impl_only = true;
events->push_back(event);
break;
}
case Animation::Filter: {
AnimationEvent event(AnimationEvent::PropertyUpdate,
id_,
animation->group(),
Animation::Filter,
monotonic_time);
event.filters = animation->curve()->ToFilterAnimationCurve()->GetValue(
trimmed);
event.is_impl_only = true;
events->push_back(event);
break;
}
case Animation::BackgroundColor: { break; }
case Animation::ScrollOffset: {
break;
}
case Animation::TargetPropertyEnumSize:
NOTREACHED();
}
}
}
void LayerAnimationController::UpdateState(bool start_ready_animations,
AnimationEventsVector* events) {
if (!HasActiveValueObserver())
return;
if (start_ready_animations)
PromoteStartedAnimations(last_tick_time_, events);
MarkFinishedAnimations(last_tick_time_);
MarkAnimationsForDeletion(last_tick_time_, events);
if (start_ready_animations) {
StartAnimations(last_tick_time_);
PromoteStartedAnimations(last_tick_time_, events);
}
AccumulatePropertyUpdates(last_tick_time_, events);
UpdateActivation(NormalActivation);
}
void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) {
active_animations_.push_back(animation.Pass());
UpdateActivation(NormalActivation);
}
Animation* LayerAnimationController::GetAnimation(
int group_id,
Animation::TargetProperty target_property) const {
for (size_t i = 0; i < active_animations_.size(); ++i)
if (active_animations_[i]->group() == group_id &&
active_animations_[i]->target_property() == target_property)
return active_animations_[i];
return 0;
}
Animation* LayerAnimationController::GetAnimation(
Animation::TargetProperty target_property) const {
for (size_t i = 0; i < active_animations_.size(); ++i) {
size_t index = active_animations_.size() - i - 1;
if (active_animations_[index]->target_property() == target_property)
return active_animations_[index];
}
return 0;
}
bool LayerAnimationController::HasActiveAnimation() const {
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (!active_animations_[i]->is_finished())
return true;
}
return false;
}
bool LayerAnimationController::IsAnimatingProperty(
Animation::TargetProperty target_property) const {
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (!active_animations_[i]->is_finished() &&
active_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(ForceActivation);
}
void LayerAnimationController::NotifyAnimationStarted(
const AnimationEvent& event) {
base::TimeTicks monotonic_time = base::TimeTicks::FromInternalValue(
event.monotonic_time * base::Time::kMicrosecondsPerSecond);
if (event.is_impl_only) {
FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
OnAnimationStarted(event));
if (layer_animation_delegate_)
layer_animation_delegate_->NotifyAnimationStarted(monotonic_time,
event.target_property);
return;
}
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (active_animations_[i]->group() == event.group_id &&
active_animations_[i]->target_property() == event.target_property &&
active_animations_[i]->needs_synchronized_start_time()) {
active_animations_[i]->set_needs_synchronized_start_time(false);
active_animations_[i]->set_start_time(event.monotonic_time);
FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_,
OnAnimationStarted(event));
if (layer_animation_delegate_)
layer_animation_delegate_->NotifyAnimationStarted(
monotonic_time, event.target_property);
return;
}
}
}
void LayerAnimationController::NotifyAnimationFinished(
const AnimationEvent& event) {
base::TimeTicks monotonic_time = base::TimeTicks::FromInternalValue(
event.monotonic_time * base::Time::kMicrosecondsPerSecond);
if (event.is_impl_only) {
if (layer_animation_delegate_)
layer_animation_delegate_->NotifyAnimationFinished(monotonic_time,
event.target_property);
return;
}
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (active_animations_[i]->group() == event.group_id &&
active_animations_[i]->target_property() == event.target_property) {
active_animations_[i]->set_received_finished_event(true);
if (layer_animation_delegate_)
layer_animation_delegate_->NotifyAnimationFinished(
monotonic_time, event.target_property);
return;
}
}
}
void LayerAnimationController::NotifyAnimationAborted(
const AnimationEvent& event) {
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (active_animations_[i]->group() == event.group_id &&
active_animations_[i]->target_property() == event.target_property) {
active_animations_[i]->SetRunState(Animation::Aborted,
event.monotonic_time);
}
}
}
void LayerAnimationController::NotifyAnimationPropertyUpdate(
const AnimationEvent& event) {
switch (event.target_property) {
case Animation::Opacity:
NotifyObserversOpacityAnimated(event.opacity);
break;
case Animation::Transform:
NotifyObserversTransformAnimated(event.transform);
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 < active_animations_.size(); ++i) {
if (!active_animations_[i]->is_finished() &&
active_animations_[i]->target_property() == Animation::Filter &&
active_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 {
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";
*bounds = gfx::BoxF();
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (active_animations_[i]->is_finished() ||
active_animations_[i]->target_property() != Animation::Transform)
continue;
const TransformAnimationCurve* transform_animation_curve =
active_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 < active_animations_.size(); ++i) {
if (active_animations_[i]->is_finished() ||
active_animations_[i]->target_property() != Animation::Transform)
continue;
const TransformAnimationCurve* transform_animation_curve =
active_animations_[i]->curve()->ToTransformAnimationCurve();
if (transform_animation_curve->AffectsScale())
return true;
}
return false;
}
bool LayerAnimationController::HasOnlyTranslationTransforms() const {
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (active_animations_[i]->is_finished() ||
active_animations_[i]->target_property() != Animation::Transform)
continue;
const TransformAnimationCurve* transform_animation_curve =
active_animations_[i]->curve()->ToTransformAnimationCurve();
if (!transform_animation_curve->IsTranslation())
return false;
}
return true;
}
bool LayerAnimationController::MaximumScale(float* max_scale) const {
*max_scale = 0.f;
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (active_animations_[i]->is_finished() ||
active_animations_[i]->target_property() != Animation::Transform)
continue;
const TransformAnimationCurve* transform_animation_curve =
active_animations_[i]->curve()->ToTransformAnimationCurve();
float animation_scale = 0.f;
if (!transform_animation_curve->MaximumScale(&animation_scale))
return false;
*max_scale = std::max(*max_scale, animation_scale);
}
return true;
}
void LayerAnimationController::PushNewAnimationsToImplThread(
LayerAnimationController* controller_impl) const {
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (controller_impl->GetAnimation(active_animations_[i]->group(),
active_animations_[i]->target_property()))
continue;
if (!active_animations_[i]->needs_synchronized_start_time())
continue;
if (active_animations_[i]->target_property() == Animation::ScrollOffset) {
gfx::Vector2dF current_scroll_offset;
if (controller_impl->value_provider_) {
current_scroll_offset =
controller_impl->value_provider_->ScrollOffsetForAnimation();
} else {
current_scroll_offset = value_provider_->ScrollOffsetForAnimation();
}
active_animations_[i]->curve()->ToScrollOffsetAnimationCurve()
->SetInitialValue(current_scroll_offset);
}
Animation::RunState initial_run_state =
Animation::WaitingForTargetAvailability;
double start_time = 0;
scoped_ptr<Animation> to_add(active_animations_[i]->CloneAndInitialize(
initial_run_state, start_time));
DCHECK(!to_add->needs_synchronized_start_time());
controller_impl->AddAnimation(to_add.Pass());
}
}
struct IsCompleted {
explicit IsCompleted(const LayerAnimationController& main_thread_controller)
: main_thread_controller_(main_thread_controller) {}
bool operator()(Animation* animation) const {
if (animation->is_impl_only()) {
return (animation->run_state() == Animation::WaitingForDeletion);
} else {
return !main_thread_controller_.GetAnimation(
animation->group(),
animation->target_property());
}
}
private:
const LayerAnimationController& main_thread_controller_;
};
void LayerAnimationController::RemoveAnimationsCompletedOnMainThread(
LayerAnimationController* controller_impl) const {
ScopedPtrVector<Animation>& animations =
controller_impl->active_animations_;
animations.erase(cc::remove_if(&animations,
animations.begin(),
animations.end(),
IsCompleted(*this)),
animations.end());
}
void LayerAnimationController::PushPropertiesToImplThread(
LayerAnimationController* controller_impl) const {
for (size_t i = 0; i < active_animations_.size(); ++i) {
Animation* current_impl =
controller_impl->GetAnimation(
active_animations_[i]->group(),
active_animations_[i]->target_property());
if (current_impl)
active_animations_[i]->PushPropertiesTo(current_impl);
}
}
void LayerAnimationController::StartAnimations(double monotonic_time) {
TargetProperties blocked_properties;
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (active_animations_[i]->run_state() == Animation::Starting ||
active_animations_[i]->run_state() == Animation::Running)
blocked_properties.insert(active_animations_[i]->target_property());
}
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (active_animations_[i]->run_state() ==
Animation::WaitingForTargetAvailability) {
TargetProperties enqueued_properties;
enqueued_properties.insert(active_animations_[i]->target_property());
for (size_t j = i + 1; j < active_animations_.size(); ++j) {
if (active_animations_[i]->group() == active_animations_[j]->group())
enqueued_properties.insert(active_animations_[j]->target_property());
}
bool null_intersection = true;
for (TargetProperties::iterator p_iter = enqueued_properties.begin();
p_iter != enqueued_properties.end();
++p_iter) {
if (!blocked_properties.insert(*p_iter).second)
null_intersection = false;
}
if (null_intersection) {
active_animations_[i]->SetRunState(
Animation::Starting, monotonic_time);
for (size_t j = i + 1; j < active_animations_.size(); ++j) {
if (active_animations_[i]->group() ==
active_animations_[j]->group()) {
active_animations_[j]->SetRunState(
Animation::Starting, monotonic_time);
}
}
}
}
}
}
void LayerAnimationController::PromoteStartedAnimations(
double monotonic_time,
AnimationEventsVector* events) {
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (active_animations_[i]->run_state() == Animation::Starting) {
active_animations_[i]->SetRunState(Animation::Running, monotonic_time);
if (!active_animations_[i]->has_set_start_time())
active_animations_[i]->set_start_time(monotonic_time);
if (events) {
AnimationEvent started_event(
AnimationEvent::Started,
id_,
active_animations_[i]->group(),
active_animations_[i]->target_property(),
monotonic_time);
started_event.is_impl_only = active_animations_[i]->is_impl_only();
events->push_back(started_event);
}
}
}
}
void LayerAnimationController::MarkFinishedAnimations(double monotonic_time) {
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (active_animations_[i]->IsFinishedAt(monotonic_time) &&
active_animations_[i]->run_state() != Animation::Aborted &&
active_animations_[i]->run_state() != Animation::WaitingForDeletion)
active_animations_[i]->SetRunState(Animation::Finished, monotonic_time);
}
}
void LayerAnimationController::MarkAnimationsForDeletion(
double monotonic_time, AnimationEventsVector* events) {
bool marked_animations_for_deletions = false;
for (size_t i = 0; i < active_animations_.size(); i++) {
int group_id = active_animations_[i]->group();
if (active_animations_[i]->run_state() == Animation::Aborted) {
if (events && !active_animations_[i]->is_impl_only()) {
AnimationEvent aborted_event(
AnimationEvent::Aborted,
id_,
group_id,
active_animations_[i]->target_property(),
monotonic_time);
events->push_back(aborted_event);
}
active_animations_[i]->SetRunState(Animation::WaitingForDeletion,
monotonic_time);
marked_animations_for_deletions = true;
continue;
}
bool all_anims_with_same_id_are_finished = false;
bool animation_i_will_send_or_has_received_finish_event =
events || active_animations_[i]->received_finished_event();
if (active_animations_[i]->run_state() == Animation::Finished &&
animation_i_will_send_or_has_received_finish_event) {
all_anims_with_same_id_are_finished = true;
for (size_t j = 0; j < active_animations_.size(); ++j) {
bool animation_j_will_send_or_has_received_finish_event =
events || active_animations_[j]->received_finished_event();
if (group_id == active_animations_[j]->group() &&
(!active_animations_[j]->is_finished() ||
(active_animations_[j]->run_state() == Animation::Finished &&
!animation_j_will_send_or_has_received_finish_event))) {
all_anims_with_same_id_are_finished = false;
break;
}
}
}
if (all_anims_with_same_id_are_finished) {
for (size_t j = i; j < active_animations_.size(); j++) {
if (active_animations_[j]->group() == group_id &&
active_animations_[j]->run_state() != Animation::Aborted) {
if (events) {
AnimationEvent finished_event(
AnimationEvent::Finished,
id_,
active_animations_[j]->group(),
active_animations_[j]->target_property(),
monotonic_time);
finished_event.is_impl_only = active_animations_[j]->is_impl_only();
events->push_back(finished_event);
}
active_animations_[j]->SetRunState(Animation::WaitingForDeletion,
monotonic_time);
}
}
marked_animations_for_deletions = true;
}
}
if (marked_animations_for_deletions)
NotifyObserversAnimationWaitingForDeletion();
}
static bool IsWaitingForDeletion(Animation* animation) {
return animation->run_state() == Animation::WaitingForDeletion;
}
void LayerAnimationController::PurgeAnimationsMarkedForDeletion() {
ScopedPtrVector<Animation>& animations = active_animations_;
animations.erase(cc::remove_if(&animations,
animations.begin(),
animations.end(),
IsWaitingForDeletion),
animations.end());
}
void LayerAnimationController::TickAnimations(double monotonic_time) {
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (active_animations_[i]->run_state() == Animation::Starting ||
active_animations_[i]->run_state() == Animation::Running ||
active_animations_[i]->run_state() == Animation::Paused) {
double trimmed =
active_animations_[i]->TrimTimeToCurrentIteration(monotonic_time);
switch (active_animations_[i]->target_property()) {
case Animation::Transform: {
const TransformAnimationCurve* transform_animation_curve =
active_animations_[i]->curve()->ToTransformAnimationCurve();
const gfx::Transform transform =
transform_animation_curve->GetValue(trimmed);
NotifyObserversTransformAnimated(transform);
break;
}
case Animation::Opacity: {
const FloatAnimationCurve* float_animation_curve =
active_animations_[i]->curve()->ToFloatAnimationCurve();
const float opacity = float_animation_curve->GetValue(trimmed);
NotifyObserversOpacityAnimated(opacity);
break;
}
case Animation::Filter: {
const FilterAnimationCurve* filter_animation_curve =
active_animations_[i]->curve()->ToFilterAnimationCurve();
const FilterOperations filter =
filter_animation_curve->GetValue(trimmed);
NotifyObserversFilterAnimated(filter);
break;
}
case Animation::BackgroundColor: {
break;
}
case Animation::ScrollOffset: {
const ScrollOffsetAnimationCurve* scroll_offset_animation_curve =
active_animations_[i]->curve()->ToScrollOffsetAnimationCurve();
const gfx::Vector2dF scroll_offset =
scroll_offset_animation_curve->GetValue(trimmed);
NotifyObserversScrollOffsetAnimated(scroll_offset);
break;
}
case Animation::TargetPropertyEnumSize:
NOTREACHED();
}
}
}
}
void LayerAnimationController::UpdateActivation(UpdateActivationType type) {
bool force = type == ForceActivation;
if (registrar_) {
bool was_active = is_active_;
is_active_ = false;
for (size_t i = 0; i < active_animations_.size(); ++i) {
if (active_animations_[i]->run_state() != Animation::WaitingForDeletion) {
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) {
FOR_EACH_OBSERVER(LayerAnimationValueObserver,
value_observers_,
OnOpacityAnimated(opacity));
}
void LayerAnimationController::NotifyObserversTransformAnimated(
const gfx::Transform& transform) {
FOR_EACH_OBSERVER(LayerAnimationValueObserver,
value_observers_,
OnTransformAnimated(transform));
}
void LayerAnimationController::NotifyObserversFilterAnimated(
const FilterOperations& filters) {
FOR_EACH_OBSERVER(LayerAnimationValueObserver,
value_observers_,
OnFilterAnimated(filters));
}
void LayerAnimationController::NotifyObserversScrollOffsetAnimated(
const gfx::Vector2dF& scroll_offset) {
FOR_EACH_OBSERVER(LayerAnimationValueObserver,
value_observers_,
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() != NULL;
}
return false;
}
bool LayerAnimationController::HasActiveValueObserver() {
if (value_observers_.might_have_observers()) {
ObserverListBase<LayerAnimationValueObserver>::Iterator it(
value_observers_);
LayerAnimationValueObserver* obs;
while ((obs = it.GetNext()) != NULL)
if (obs->IsActive())
return true;
}
return false;
}
}