Index: cc/animation/animation_host.cc |
diff --git a/cc/animation/animation_host.cc b/cc/animation/animation_host.cc |
index 4c709bcd6ffaaa26aee7aaa8a3b554f248d1e9f5..91a94ed1bd7fcfab12211396043d3f7fb28fbfa1 100644 |
--- a/cc/animation/animation_host.cc |
+++ b/cc/animation/animation_host.cc |
@@ -6,14 +6,117 @@ |
#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/scroll_offset_animation_curve.h" |
+#include "cc/animation/timing_function.h" |
#include "cc/trees/layer_tree_mutators_client.h" |
#include "ui/gfx/geometry/box_f.h" |
+#include "ui/gfx/geometry/scroll_offset.h" |
namespace cc { |
+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_->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_->layer_tree_mutators_client()); |
+ animation_host_->layer_tree_mutators_client() |
+ ->ScrollOffsetAnimationFinished(); |
+ } |
+ |
+ private: |
+ AnimationHost* animation_host_; |
+ scoped_refptr<AnimationTimeline> scroll_offset_timeline_; |
+ scoped_refptr<AnimationPlayer> scroll_offset_animation_player_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ScrollOffsetAnimations); |
+}; |
+ |
scoped_ptr<AnimationHost> AnimationHost::Create(bool is_impl_instance) { |
return make_scoped_ptr(new AnimationHost(is_impl_instance)); |
} |
@@ -22,9 +125,14 @@ AnimationHost::AnimationHost(bool is_impl_instance) |
: animation_registrar_(AnimationRegistrar::Create()), |
layer_tree_mutators_client_(), |
is_impl_instance_(is_impl_instance) { |
+ if (is_impl_instance_) |
+ scroll_offset_animations_ = |
+ make_scoped_ptr(new ScrollOffsetAnimations(this)); |
} |
AnimationHost::~AnimationHost() { |
+ scroll_offset_animations_ = nullptr; |
+ |
ClearTimelines(); |
DCHECK(!layer_tree_mutators_client()); |
} |
@@ -328,4 +436,23 @@ bool AnimationHost::HasActiveAnimation(int layer_id) const { |
: 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 |