1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef UI_GFX_INTERPOLATED_TRANSFORM_H_
6#define UI_GFX_INTERPOLATED_TRANSFORM_H_
7
8#include "base/basictypes.h"
9#include "base/memory/scoped_ptr.h"
10#include "ui/gfx/point.h"
11#include "ui/gfx/point3_f.h"
12#include "ui/gfx/transform.h"
13#include "ui/gfx/transform_util.h"
14#include "ui/gfx/vector3d_f.h"
15
16namespace ui {
17
18///////////////////////////////////////////////////////////////////////////////
19// class InterpolatedTransform
20//
21// Abstract base class for transforms that animate over time. These
22// interpolated transforms can be combined to allow for more sophisticated
23// animations. For example, you might combine a rotation of 90 degrees between
24// times 0 and 1, with a scale from 1 to 0.3 between times 0 and 0.25 and a
25// scale from 0.3 to 1 from between times 0.75 and 1.
26//
27///////////////////////////////////////////////////////////////////////////////
28class GFX_EXPORT InterpolatedTransform {
29 public:
30  InterpolatedTransform();
31  // The interpolated transform varies only when t in (start_time, end_time).
32  // If t <= start_time, Interpolate(t) will return the initial transform, and
33  // if t >= end_time, Interpolate(t) will return the final transform.
34  InterpolatedTransform(float start_time, float end_time);
35  virtual ~InterpolatedTransform();
36
37  // Returns the interpolated transform at time t. Note: not virtual.
38  gfx::Transform Interpolate(float t) const;
39
40  // The Intepolate ultimately returns the product of our transform at time t
41  // and our child's transform at time t (if we have one).
42  //
43  // This function takes ownership of the passed InterpolatedTransform.
44  void SetChild(InterpolatedTransform* child);
45
46  // If the interpolated transform is reversed, Interpolate(t) will return
47  // Interpolate(1 - t)
48  void SetReversed(bool reversed) { reversed_ = reversed; }
49  bool Reversed() const { return reversed_; }
50
51 protected:
52  // Calculates the interpolated transform without considering our child.
53  virtual gfx::Transform InterpolateButDoNotCompose(float t) const = 0;
54
55  // If time in (start_time_, end_time_], this function linearly interpolates
56  // between start_value and end_value.  More precisely it returns
57  // (1 - t) * start_value + t * end_value where
58  // t = (start_time_ - time) / (end_time_ - start_time_).
59  // If time < start_time_ it returns start_value, and if time >= end_time_
60  // it returns end_value.
61  float ValueBetween(float time, float start_value, float end_value) const;
62
63  float start_time() const { return start_time_; }
64  float end_time() const { return end_time_; }
65
66 private:
67  const float start_time_;
68  const float end_time_;
69
70  // The child transform. If you consider an interpolated transform as a
71  // function of t. If, without a child, we are f(t), and our child is
72  // g(t), then with a child we become f'(t) = f(t) * g(t). Using a child
73  // transform, we can chain collections of transforms together.
74  scoped_ptr<InterpolatedTransform> child_;
75
76  bool reversed_;
77
78  DISALLOW_COPY_AND_ASSIGN(InterpolatedTransform);
79};
80
81///////////////////////////////////////////////////////////////////////////////
82// class InterpolatedRotation
83//
84// Represents an animated rotation.
85//
86///////////////////////////////////////////////////////////////////////////////
87class GFX_EXPORT InterpolatedRotation : public InterpolatedTransform {
88 public:
89  InterpolatedRotation(float start_degrees, float end_degrees);
90  InterpolatedRotation(float start_degrees,
91                       float end_degrees,
92                       float start_time,
93                       float end_time);
94  virtual ~InterpolatedRotation();
95
96 protected:
97  virtual gfx::Transform InterpolateButDoNotCompose(float t) const OVERRIDE;
98
99 private:
100  const float start_degrees_;
101  const float end_degrees_;
102
103  DISALLOW_COPY_AND_ASSIGN(InterpolatedRotation);
104};
105
106///////////////////////////////////////////////////////////////////////////////
107// class InterpolatedAxisAngleRotation
108//
109// Represents an animated rotation.
110//
111///////////////////////////////////////////////////////////////////////////////
112class GFX_EXPORT InterpolatedAxisAngleRotation : public InterpolatedTransform {
113 public:
114  InterpolatedAxisAngleRotation(const gfx::Vector3dF& axis,
115                                float start_degrees,
116                                float end_degrees);
117  InterpolatedAxisAngleRotation(const gfx::Vector3dF& axis,
118                                float start_degrees,
119                                float end_degrees,
120                                float start_time,
121                                float end_time);
122  virtual ~InterpolatedAxisAngleRotation();
123
124 protected:
125  virtual gfx::Transform InterpolateButDoNotCompose(float t) const OVERRIDE;
126
127 private:
128  gfx::Vector3dF axis_;
129  const float start_degrees_;
130  const float end_degrees_;
131
132  DISALLOW_COPY_AND_ASSIGN(InterpolatedAxisAngleRotation);
133};
134
135///////////////////////////////////////////////////////////////////////////////
136// class InterpolatedScale
137//
138// Represents an animated scale.
139//
140///////////////////////////////////////////////////////////////////////////////
141class GFX_EXPORT InterpolatedScale : public InterpolatedTransform {
142 public:
143  InterpolatedScale(float start_scale, float end_scale);
144  InterpolatedScale(float start_scale, float end_scale,
145                    float start_time, float end_time);
146  InterpolatedScale(const gfx::Point3F& start_scale,
147                    const gfx::Point3F& end_scale);
148  InterpolatedScale(const gfx::Point3F& start_scale,
149                    const gfx::Point3F& end_scale,
150                    float start_time,
151                    float end_time);
152  virtual ~InterpolatedScale();
153
154 protected:
155  virtual gfx::Transform InterpolateButDoNotCompose(float t) const OVERRIDE;
156
157 private:
158  const gfx::Point3F start_scale_;
159  const gfx::Point3F end_scale_;
160
161  DISALLOW_COPY_AND_ASSIGN(InterpolatedScale);
162};
163
164class GFX_EXPORT InterpolatedTranslation : public InterpolatedTransform {
165 public:
166  InterpolatedTranslation(const gfx::Point& start_pos,
167                          const gfx::Point& end_pos);
168  InterpolatedTranslation(const gfx::Point& start_pos,
169                          const gfx::Point& end_pos,
170                          float start_time,
171                          float end_time);
172  virtual ~InterpolatedTranslation();
173
174 protected:
175  virtual gfx::Transform InterpolateButDoNotCompose(float t) const OVERRIDE;
176
177 private:
178  const gfx::Point start_pos_;
179  const gfx::Point end_pos_;
180
181  DISALLOW_COPY_AND_ASSIGN(InterpolatedTranslation);
182};
183
184///////////////////////////////////////////////////////////////////////////////
185// class InterpolatedConstantTransform
186//
187// Represents a transform that is constant over time. This is only useful when
188// composed with other interpolated transforms.
189//
190// See InterpolatedTransformAboutPivot for an example of its usage.
191//
192///////////////////////////////////////////////////////////////////////////////
193class GFX_EXPORT InterpolatedConstantTransform : public InterpolatedTransform {
194 public:
195  explicit InterpolatedConstantTransform(const gfx::Transform& transform);
196  virtual ~InterpolatedConstantTransform();
197
198 protected:
199  virtual gfx::Transform InterpolateButDoNotCompose(float t) const OVERRIDE;
200
201 private:
202  const gfx::Transform transform_;
203
204  DISALLOW_COPY_AND_ASSIGN(InterpolatedConstantTransform);
205};
206
207///////////////////////////////////////////////////////////////////////////////
208// class InterpolatedTransformAboutPivot
209//
210// Represents an animated transform with a transformed origin. Essentially,
211// at each time, t, the interpolated transform is created by composing
212// P * T * P^-1 where P is a constant transform to the new origin.
213//
214///////////////////////////////////////////////////////////////////////////////
215class GFX_EXPORT InterpolatedTransformAboutPivot
216    : public InterpolatedTransform {
217 public:
218  // Takes ownership of the passed transform.
219  InterpolatedTransformAboutPivot(const gfx::Point& pivot,
220                                  InterpolatedTransform* transform);
221
222  // Takes ownership of the passed transform.
223  InterpolatedTransformAboutPivot(const gfx::Point& pivot,
224                                  InterpolatedTransform* transform,
225                                  float start_time,
226                                  float end_time);
227  virtual ~InterpolatedTransformAboutPivot();
228
229 protected:
230  virtual gfx::Transform InterpolateButDoNotCompose(float t) const OVERRIDE;
231
232 private:
233  void Init(const gfx::Point& pivot, InterpolatedTransform* transform);
234
235  scoped_ptr<InterpolatedTransform> transform_;
236
237  DISALLOW_COPY_AND_ASSIGN(InterpolatedTransformAboutPivot);
238};
239
240class GFX_EXPORT InterpolatedMatrixTransform : public InterpolatedTransform {
241 public:
242  InterpolatedMatrixTransform(const gfx::Transform& start_transform,
243                              const gfx::Transform& end_transform);
244
245  InterpolatedMatrixTransform(const gfx::Transform& start_transform,
246                              const gfx::Transform& end_transform,
247                              float start_time,
248                              float end_time);
249
250  virtual ~InterpolatedMatrixTransform();
251
252 protected:
253  virtual gfx::Transform InterpolateButDoNotCompose(float t) const OVERRIDE;
254
255 private:
256  void Init(const gfx::Transform& start_transform,
257            const gfx::Transform& end_transform);
258
259  gfx::DecomposedTransform start_decomp_;
260  gfx::DecomposedTransform end_decomp_;
261};
262
263} // namespace ui
264
265#endif  // UI_GFX_INTERPOLATED_TRANSFORM_H_
266