Index: cc/animation/animation_host.cc |
diff --git a/cc/animation/animation_host.cc b/cc/animation/animation_host.cc |
index 82a5e722c3230f4e4ebeb6dfaa9785282330187f..e7f289fad9a0ae64190aaf7921b64e7db0a7e7a9 100644 |
--- a/cc/animation/animation_host.cc |
+++ b/cc/animation/animation_host.cc |
@@ -6,24 +6,137 @@ |
#include <algorithm> |
+#include "cc/animation/animation_delegate.h" |
+#include "cc/animation/animation_id_provider.h" |
#include "cc/animation/animation_player.h" |
#include "cc/animation/animation_registrar.h" |
#include "cc/animation/animation_timeline.h" |
#include "cc/animation/element_animations.h" |
+#include "cc/animation/scroll_offset_animation_curve.h" |
+#include "cc/animation/timing_function.h" |
#include "ui/gfx/geometry/box_f.h" |
+#include "ui/gfx/geometry/scroll_offset.h" |
namespace cc { |
-scoped_ptr<AnimationHost> AnimationHost::Create() { |
- return make_scoped_ptr(new AnimationHost); |
+class AnimationHost::ScrollOffsetAnimations : public AnimationDelegate { |
+ public: |
+ explicit ScrollOffsetAnimations(AnimationHost* animation_host) |
+ : animation_host_(animation_host), |
+ scroll_offset_timeline_( |
+ AnimationTimeline::Create(AnimationIdProvider::NextTimelineId())), |
+ scroll_offset_animation_player_( |
+ AnimationPlayer::Create(AnimationIdProvider::NextPlayerId())) { |
+ scroll_offset_timeline_->set_is_impl_only(true); |
+ scroll_offset_animation_player_->set_layer_animation_delegate(this); |
+ |
+ animation_host_->AddAnimationTimeline(scroll_offset_timeline_.get()); |
+ scroll_offset_timeline_->AttachPlayer( |
+ scroll_offset_animation_player_.get()); |
+ } |
+ |
+ ~ScrollOffsetAnimations() override { |
+ scroll_offset_timeline_->DetachPlayer( |
+ scroll_offset_animation_player_.get()); |
+ animation_host_->RemoveAnimationTimeline(scroll_offset_timeline_.get()); |
+ } |
+ |
+ void ScrollAnimationCreate(int layer_id, |
+ const gfx::ScrollOffset& target_offset, |
+ const gfx::ScrollOffset& current_offset) { |
+ scoped_ptr<ScrollOffsetAnimationCurve> curve = |
+ ScrollOffsetAnimationCurve::Create(target_offset, |
+ EaseInOutTimingFunction::Create()); |
+ curve->SetInitialValue(current_offset); |
+ |
+ scoped_ptr<Animation> animation = Animation::Create( |
+ curve.Pass(), AnimationIdProvider::NextAnimationId(), |
+ AnimationIdProvider::NextGroupId(), Animation::SCROLL_OFFSET); |
+ animation->set_is_impl_only(true); |
+ |
+ DCHECK(scroll_offset_animation_player_); |
+ DCHECK(scroll_offset_animation_player_->animation_timeline()); |
+ |
+ if (scroll_offset_animation_player_->layer_id() != layer_id) { |
+ if (scroll_offset_animation_player_->layer_id()) |
+ scroll_offset_animation_player_->DetachLayer(); |
+ scroll_offset_animation_player_->AttachLayer(layer_id); |
+ } |
+ |
+ scroll_offset_animation_player_->AddAnimation(animation.Pass()); |
+ } |
+ |
+ bool ScrollAnimationUpdateTarget(int layer_id, |
+ const gfx::Vector2dF& scroll_delta, |
+ const gfx::ScrollOffset& max_scroll_offset, |
+ base::TimeTicks frame_monotonic_time) { |
+ DCHECK(scroll_offset_animation_player_); |
+ DCHECK_EQ(layer_id, scroll_offset_animation_player_->layer_id()); |
+ |
+ Animation* animation = scroll_offset_animation_player_->element_animations() |
+ ->layer_animation_controller() |
+ ->GetAnimation(Animation::SCROLL_OFFSET); |
+ if (!animation) { |
+ scroll_offset_animation_player_->DetachLayer(); |
+ return false; |
+ } |
+ |
+ ScrollOffsetAnimationCurve* curve = |
+ animation->curve()->ToScrollOffsetAnimationCurve(); |
+ |
+ gfx::ScrollOffset new_target = |
+ gfx::ScrollOffsetWithDelta(curve->target_value(), scroll_delta); |
+ new_target.SetToMax(gfx::ScrollOffset()); |
+ new_target.SetToMin(max_scroll_offset); |
+ |
+ curve->UpdateTarget(animation->TrimTimeToCurrentIteration( |
+ frame_monotonic_time).InSecondsF(), |
+ new_target); |
+ |
+ return true; |
+ } |
+ |
+ // AnimationDelegate implementation. |
+ void NotifyAnimationStarted(base::TimeTicks monotonic_time, |
+ Animation::TargetProperty target_property, |
+ int group) override {} |
+ void NotifyAnimationFinished(base::TimeTicks monotonic_time, |
+ Animation::TargetProperty target_property, |
+ int group) override { |
+ DCHECK_EQ(target_property, Animation::SCROLL_OFFSET); |
+ DCHECK(animation_host_->mutator_host_client()); |
+ animation_host_->mutator_host_client()->ScrollOffsetAnimationFinished(); |
+ } |
+ |
+ private: |
+ AnimationHost* animation_host_; |
+ scoped_refptr<AnimationTimeline> scroll_offset_timeline_; |
+ |
+ // We have just one player for impl-only scroll offset animations. |
+ // I.e. only one layer can have an impl-only scroll offset animation at |
+ // any given time. |
+ scoped_refptr<AnimationPlayer> scroll_offset_animation_player_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ScrollOffsetAnimations); |
+}; |
+ |
+scoped_ptr<AnimationHost> AnimationHost::Create( |
+ ThreadInstance thread_instance) { |
+ return make_scoped_ptr(new AnimationHost(thread_instance)); |
} |
-AnimationHost::AnimationHost() |
+AnimationHost::AnimationHost(ThreadInstance thread_instance) |
: animation_registrar_(AnimationRegistrar::Create()), |
- mutator_host_client_(nullptr) { |
+ mutator_host_client_(nullptr), |
+ thread_instance_(thread_instance) { |
+ if (thread_instance_ == ThreadInstance::IMPL) |
+ scroll_offset_animations_ = |
+ make_scoped_ptr(new ScrollOffsetAnimations(this)); |
} |
AnimationHost::~AnimationHost() { |
+ scroll_offset_animations_ = nullptr; |
+ |
ClearTimelines(); |
DCHECK(!mutator_host_client()); |
DCHECK(layer_to_element_animations_map_.empty()); |
@@ -376,4 +489,23 @@ bool AnimationHost::HasActiveAnimation(int layer_id) const { |
return controller ? controller->HasActiveAnimation() : false; |
} |
+void AnimationHost::ImplOnlyScrollAnimationCreate( |
+ int layer_id, |
+ const gfx::ScrollOffset& target_offset, |
+ const gfx::ScrollOffset& current_offset) { |
+ DCHECK(scroll_offset_animations_); |
+ scroll_offset_animations_->ScrollAnimationCreate(layer_id, target_offset, |
+ current_offset); |
+} |
+ |
+bool AnimationHost::ImplOnlyScrollAnimationUpdateTarget( |
+ int layer_id, |
+ const gfx::Vector2dF& scroll_delta, |
+ const gfx::ScrollOffset& max_scroll_offset, |
+ base::TimeTicks frame_monotonic_time) { |
+ DCHECK(scroll_offset_animations_); |
+ return scroll_offset_animations_->ScrollAnimationUpdateTarget( |
+ layer_id, scroll_delta, max_scroll_offset, frame_monotonic_time); |
+} |
+ |
} // namespace cc |