keyframed_animation_curve.cc revision 3551c9c881056c480085172ff9840cab31610854
1// Copyright 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#include "cc/animation/keyframed_animation_curve.h"
6#include "ui/gfx/box_f.h"
7
8namespace cc {
9
10namespace {
11
12template <class Keyframe>
13void InsertKeyframe(scoped_ptr<Keyframe> keyframe,
14                    ScopedPtrVector<Keyframe>& keyframes) {
15  // Usually, the keyframes will be added in order, so this loop would be
16  // unnecessary and we should skip it if possible.
17  if (!keyframes.empty() && keyframe->Time() < keyframes.back()->Time()) {
18    for (size_t i = 0; i < keyframes.size(); ++i) {
19      if (keyframe->Time() < keyframes[i]->Time()) {
20        keyframes.insert(keyframes.begin() + i, keyframe.Pass());
21        return;
22      }
23    }
24  }
25
26  keyframes.push_back(keyframe.Pass());
27}
28
29scoped_ptr<TimingFunction> CloneTimingFunction(
30    const TimingFunction* timing_function) {
31  DCHECK(timing_function);
32  scoped_ptr<AnimationCurve> curve(timing_function->Clone());
33  return scoped_ptr<TimingFunction>(
34      static_cast<TimingFunction*>(curve.release()));
35}
36
37}  // namespace
38
39Keyframe::Keyframe(double time, scoped_ptr<TimingFunction> timing_function)
40    : time_(time),
41      timing_function_(timing_function.Pass()) {}
42
43Keyframe::~Keyframe() {}
44
45double Keyframe::Time() const {
46  return time_;
47}
48
49scoped_ptr<FloatKeyframe> FloatKeyframe::Create(
50    double time,
51    float value,
52    scoped_ptr<TimingFunction> timing_function) {
53  return make_scoped_ptr(
54      new FloatKeyframe(time, value, timing_function.Pass()));
55}
56
57FloatKeyframe::FloatKeyframe(double time,
58                             float value,
59                             scoped_ptr<TimingFunction> timing_function)
60    : Keyframe(time, timing_function.Pass()),
61      value_(value) {}
62
63FloatKeyframe::~FloatKeyframe() {}
64
65float FloatKeyframe::Value() const {
66  return value_;
67}
68
69scoped_ptr<FloatKeyframe> FloatKeyframe::Clone() const {
70  scoped_ptr<TimingFunction> func;
71  if (timing_function())
72    func = CloneTimingFunction(timing_function());
73  return FloatKeyframe::Create(Time(), Value(), func.Pass());
74}
75
76scoped_ptr<TransformKeyframe> TransformKeyframe::Create(
77    double time,
78    const TransformOperations& value,
79    scoped_ptr<TimingFunction> timing_function) {
80  return make_scoped_ptr(
81      new TransformKeyframe(time, value, timing_function.Pass()));
82}
83
84TransformKeyframe::TransformKeyframe(double time,
85                                     const TransformOperations& value,
86                                     scoped_ptr<TimingFunction> timing_function)
87    : Keyframe(time, timing_function.Pass()),
88      value_(value) {}
89
90TransformKeyframe::~TransformKeyframe() {}
91
92const TransformOperations& TransformKeyframe::Value() const {
93  return value_;
94}
95
96scoped_ptr<TransformKeyframe> TransformKeyframe::Clone() const {
97  scoped_ptr<TimingFunction> func;
98  if (timing_function())
99    func = CloneTimingFunction(timing_function());
100  return TransformKeyframe::Create(Time(), Value(), func.Pass());
101}
102
103scoped_ptr<FilterKeyframe> FilterKeyframe::Create(
104    double time,
105    const FilterOperations& value,
106    scoped_ptr<TimingFunction> timing_function) {
107  return make_scoped_ptr(
108      new FilterKeyframe(time, value, timing_function.Pass()));
109}
110
111FilterKeyframe::FilterKeyframe(double time,
112                               const FilterOperations& value,
113                               scoped_ptr<TimingFunction> timing_function)
114    : Keyframe(time, timing_function.Pass()),
115      value_(value) {}
116
117FilterKeyframe::~FilterKeyframe() {}
118
119const FilterOperations& FilterKeyframe::Value() const {
120  return value_;
121}
122
123scoped_ptr<FilterKeyframe> FilterKeyframe::Clone() const {
124  scoped_ptr<TimingFunction> func;
125  if (timing_function())
126    func = CloneTimingFunction(timing_function());
127  return FilterKeyframe::Create(Time(), Value(), func.Pass());
128}
129
130scoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve::
131    Create() {
132  return make_scoped_ptr(new KeyframedFloatAnimationCurve);
133}
134
135KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {}
136
137KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {}
138
139void KeyframedFloatAnimationCurve::AddKeyframe(
140    scoped_ptr<FloatKeyframe> keyframe) {
141  InsertKeyframe(keyframe.Pass(), keyframes_);
142}
143
144double KeyframedFloatAnimationCurve::Duration() const {
145  return keyframes_.back()->Time() - keyframes_.front()->Time();
146}
147
148scoped_ptr<AnimationCurve> KeyframedFloatAnimationCurve::Clone() const {
149  scoped_ptr<KeyframedFloatAnimationCurve> to_return(
150      KeyframedFloatAnimationCurve::Create());
151  for (size_t i = 0; i < keyframes_.size(); ++i)
152    to_return->AddKeyframe(keyframes_[i]->Clone());
153  return to_return.PassAs<AnimationCurve>();
154}
155
156float KeyframedFloatAnimationCurve::GetValue(double t) const {
157  if (t <= keyframes_.front()->Time())
158    return keyframes_.front()->Value();
159
160  if (t >= keyframes_.back()->Time())
161    return keyframes_.back()->Value();
162
163  size_t i = 0;
164  for (; i < keyframes_.size() - 1; ++i) {
165    if (t < keyframes_[i+1]->Time())
166      break;
167  }
168
169  float progress =
170      static_cast<float>((t - keyframes_[i]->Time()) /
171                         (keyframes_[i+1]->Time() - keyframes_[i]->Time()));
172
173  if (keyframes_[i]->timing_function())
174    progress = keyframes_[i]->timing_function()->GetValue(progress);
175
176  return keyframes_[i]->Value() +
177      (keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress;
178}
179
180scoped_ptr<KeyframedTransformAnimationCurve> KeyframedTransformAnimationCurve::
181    Create() {
182  return make_scoped_ptr(new KeyframedTransformAnimationCurve);
183}
184
185KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {}
186
187KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {}
188
189void KeyframedTransformAnimationCurve::AddKeyframe(
190    scoped_ptr<TransformKeyframe> keyframe) {
191  InsertKeyframe(keyframe.Pass(), keyframes_);
192}
193
194double KeyframedTransformAnimationCurve::Duration() const {
195  return keyframes_.back()->Time() - keyframes_.front()->Time();
196}
197
198scoped_ptr<AnimationCurve> KeyframedTransformAnimationCurve::Clone() const {
199  scoped_ptr<KeyframedTransformAnimationCurve> to_return(
200      KeyframedTransformAnimationCurve::Create());
201  for (size_t i = 0; i < keyframes_.size(); ++i)
202    to_return->AddKeyframe(keyframes_[i]->Clone());
203  return to_return.PassAs<AnimationCurve>();
204}
205
206// Assumes that (*keyframes).front()->Time() < t < (*keyframes).back()-Time().
207template<typename ValueType, typename KeyframeType>
208static ValueType GetCurveValue(const ScopedPtrVector<KeyframeType>* keyframes,
209                               double t) {
210  size_t i = 0;
211  for (; i < keyframes->size() - 1; ++i) {
212    if (t < (*keyframes)[i+1]->Time())
213      break;
214  }
215
216  double progress = (t - (*keyframes)[i]->Time()) /
217                    ((*keyframes)[i+1]->Time() - (*keyframes)[i]->Time());
218
219  if ((*keyframes)[i]->timing_function())
220    progress = (*keyframes)[i]->timing_function()->GetValue(progress);
221
222  return (*keyframes)[i+1]->Value().Blend((*keyframes)[i]->Value(), progress);
223}
224
225gfx::Transform KeyframedTransformAnimationCurve::GetValue(double t) const {
226  if (t <= keyframes_.front()->Time())
227    return keyframes_.front()->Value().Apply();
228
229  if (t >= keyframes_.back()->Time())
230    return keyframes_.back()->Value().Apply();
231
232  return GetCurveValue<gfx::Transform, TransformKeyframe>(&keyframes_, t);
233}
234
235bool KeyframedTransformAnimationCurve::AnimatedBoundsForBox(
236    const gfx::BoxF& box,
237    gfx::BoxF* bounds) const {
238  DCHECK_GE(keyframes_.size(), 2ul);
239  *bounds = gfx::BoxF();
240  for (size_t i = 0; i < keyframes_.size() - 1; ++i) {
241    gfx::BoxF bounds_for_step;
242    float min_progress = 0.0;
243    float max_progress = 1.0;
244    if (keyframes_[i]->timing_function())
245      keyframes_[i]->timing_function()->Range(&min_progress, &max_progress);
246    if (!keyframes_[i+1]->Value().BlendedBoundsForBox(box,
247                                                      keyframes_[i]->Value(),
248                                                      min_progress,
249                                                      max_progress,
250                                                      &bounds_for_step))
251      return false;
252    bounds->Union(bounds_for_step);
253  }
254  return true;
255}
256
257scoped_ptr<KeyframedFilterAnimationCurve> KeyframedFilterAnimationCurve::
258    Create() {
259  return make_scoped_ptr(new KeyframedFilterAnimationCurve);
260}
261
262KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {}
263
264KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {}
265
266void KeyframedFilterAnimationCurve::AddKeyframe(
267    scoped_ptr<FilterKeyframe> keyframe) {
268  InsertKeyframe(keyframe.Pass(), keyframes_);
269}
270
271double KeyframedFilterAnimationCurve::Duration() const {
272  return keyframes_.back()->Time() - keyframes_.front()->Time();
273}
274
275scoped_ptr<AnimationCurve> KeyframedFilterAnimationCurve::Clone() const {
276  scoped_ptr<KeyframedFilterAnimationCurve> to_return(
277      KeyframedFilterAnimationCurve::Create());
278  for (size_t i = 0; i < keyframes_.size(); ++i)
279    to_return->AddKeyframe(keyframes_[i]->Clone());
280  return to_return.PassAs<AnimationCurve>();
281}
282
283FilterOperations KeyframedFilterAnimationCurve::GetValue(double t) const {
284  if (t <= keyframes_.front()->Time())
285    return keyframes_.front()->Value();
286
287  if (t >= keyframes_.back()->Time())
288    return keyframes_.back()->Value();
289
290  return GetCurveValue<FilterOperations, FilterKeyframe>(&keyframes_, t);
291}
292
293}  // namespace cc
294