12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2011 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef CC_INPUT_PAGE_SCALE_ANIMATION_H_
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define CC_INPUT_PAGE_SCALE_ANIMATION_H_
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/time/time.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/vector2d_f.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class TimingFunction;
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A small helper class that does the math for zoom animations, primarily for
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// double-tap zoom. Initialize it with starting and ending scroll/page scale
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// positions and an animation length time, then call ...AtTime() at every frame
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// to obtain the current interpolated position. The supplied timing function
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// is used to ease the animation.
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// All sizes and vectors in this class's public methods are in the root scroll
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// layer's coordinate space.
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class PageScaleAnimation {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Construct with the state at the beginning of the animation.
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static scoped_ptr<PageScaleAnimation> Create(
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const gfx::Vector2dF& start_scroll_offset,
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      float start_page_scale_factor,
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const gfx::SizeF& viewport_size,
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const gfx::SizeF& root_layer_size,
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      scoped_ptr<TimingFunction> timing_function);
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~PageScaleAnimation();
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The following methods initialize the animation. Call one of them
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // immediately after construction to set the final scroll and page scale.
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Zoom while explicitly specifying the top-left scroll position.
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ZoomTo(const gfx::Vector2dF& target_scroll_offset,
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              float target_page_scale_factor,
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              double duration);
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Zoom based on a specified anchor. The animator will attempt to keep it
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // at the same position on the physical display throughout the animation,
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // unless the edges of the root layer are hit. The anchor is specified
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // as an offset from the content layer.
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ZoomWithAnchor(const gfx::Vector2dF& anchor,
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      float target_page_scale_factor,
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      double duration);
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // These should be called before the first frame of animation to initialize
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // the start time. StartAnimation should only be called once after creation.
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool IsAnimationStarted() const;
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void StartAnimation(base::TimeTicks time);
584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Call these functions while the animation is in progress to output the
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // current state.
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  gfx::Vector2dF ScrollOffsetAtTime(base::TimeTicks time) const;
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  float PageScaleFactorAtTime(base::TimeTicks time) const;
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool IsAnimationCompleteAtTime(base::TimeTicks time) const;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The following methods return state which is invariant throughout the
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // course of the animation.
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::TimeTicks start_time() const { return start_time_; }
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::TimeDelta duration() const { return duration_; }
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::TimeTicks end_time() const { return start_time_ + duration_; }
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2dF target_scroll_offset() const { return target_scroll_offset_; }
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float target_page_scale_factor() const { return target_page_scale_factor_; }
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PageScaleAnimation(const gfx::Vector2dF& start_scroll_offset,
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     float start_page_scale_factor,
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     const gfx::SizeF& viewport_size,
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     const gfx::SizeF& root_layer_size,
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     scoped_ptr<TimingFunction> timing_function);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ClampTargetScrollOffset();
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void InferTargetScrollOffsetFromStartAnchor();
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void InferTargetAnchorFromScrollOffsets();
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::SizeF StartViewportSize() const;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::SizeF TargetViewportSize() const;
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  float InterpAtTime(base::TimeTicks time) const;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::SizeF ViewportSizeAt(float interp) const;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2dF ScrollOffsetAt(float interp) const;
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2dF AnchorAt(float interp) const;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2dF ViewportRelativeAnchorAt(float interp) const;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float PageScaleFactorAt(float interp) const;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float start_page_scale_factor_;
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float target_page_scale_factor_;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2dF start_scroll_offset_;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2dF target_scroll_offset_;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2dF start_anchor_;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Vector2dF target_anchor_;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::SizeF viewport_size_;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::SizeF root_layer_size_;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::TimeTicks start_time_;
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::TimeDelta duration_;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<TimingFunction> timing_function_;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PageScaleAnimation);
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // CC_INPUT_PAGE_SCALE_ANIMATION_H_
116