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 <algorithm>
6
7#include "cc/animation/keyframed_animation_curve.h"
8#include "ui/gfx/animation/tween.h"
9#include "ui/gfx/box_f.h"
10
11namespace cc {
12
13namespace {
14
15template <class Keyframe>
16void InsertKeyframe(scoped_ptr<Keyframe> keyframe,
17                    ScopedPtrVector<Keyframe>& keyframes) {
18  // Usually, the keyframes will be added in order, so this loop would be
19  // unnecessary and we should skip it if possible.
20  if (!keyframes.empty() && keyframe->Time() < keyframes.back()->Time()) {
21    for (size_t i = 0; i < keyframes.size(); ++i) {
22      if (keyframe->Time() < keyframes[i]->Time()) {
23        keyframes.insert(keyframes.begin() + i, keyframe.Pass());
24        return;
25      }
26    }
27  }
28
29  keyframes.push_back(keyframe.Pass());
30}
31
32template <class Keyframes>
33float GetProgress(double t, size_t i, const Keyframes& keyframes) {
34  float progress =
35      static_cast<float>((t - keyframes[i]->Time()) /
36                         (keyframes[i + 1]->Time() - keyframes[i]->Time()));
37
38  if (keyframes[i]->timing_function())
39    progress = keyframes[i]->timing_function()->GetValue(progress);
40  return progress;
41}
42
43}  // namespace
44
45Keyframe::Keyframe(double time, scoped_ptr<TimingFunction> timing_function)
46    : time_(time),
47      timing_function_(timing_function.Pass()) {}
48
49Keyframe::~Keyframe() {}
50
51double Keyframe::Time() const {
52  return time_;
53}
54
55scoped_ptr<ColorKeyframe> ColorKeyframe::Create(
56    double time,
57    SkColor value,
58    scoped_ptr<TimingFunction> timing_function) {
59  return make_scoped_ptr(
60      new ColorKeyframe(time, value, timing_function.Pass()));
61}
62
63ColorKeyframe::ColorKeyframe(double time,
64                             SkColor value,
65                             scoped_ptr<TimingFunction> timing_function)
66    : Keyframe(time, timing_function.Pass()),
67      value_(value) {}
68
69ColorKeyframe::~ColorKeyframe() {}
70
71SkColor ColorKeyframe::Value() const { return value_; }
72
73scoped_ptr<ColorKeyframe> ColorKeyframe::Clone() const {
74  scoped_ptr<TimingFunction> func;
75  if (timing_function())
76    func = timing_function()->Clone();
77  return ColorKeyframe::Create(Time(), Value(), func.Pass());
78}
79
80scoped_ptr<FloatKeyframe> FloatKeyframe::Create(
81    double time,
82    float value,
83    scoped_ptr<TimingFunction> timing_function) {
84  return make_scoped_ptr(
85      new FloatKeyframe(time, value, timing_function.Pass()));
86}
87
88FloatKeyframe::FloatKeyframe(double time,
89                             float value,
90                             scoped_ptr<TimingFunction> timing_function)
91    : Keyframe(time, timing_function.Pass()),
92      value_(value) {}
93
94FloatKeyframe::~FloatKeyframe() {}
95
96float FloatKeyframe::Value() const {
97  return value_;
98}
99
100scoped_ptr<FloatKeyframe> FloatKeyframe::Clone() const {
101  scoped_ptr<TimingFunction> func;
102  if (timing_function())
103    func = timing_function()->Clone();
104  return FloatKeyframe::Create(Time(), Value(), func.Pass());
105}
106
107scoped_ptr<TransformKeyframe> TransformKeyframe::Create(
108    double time,
109    const TransformOperations& value,
110    scoped_ptr<TimingFunction> timing_function) {
111  return make_scoped_ptr(
112      new TransformKeyframe(time, value, timing_function.Pass()));
113}
114
115TransformKeyframe::TransformKeyframe(double time,
116                                     const TransformOperations& value,
117                                     scoped_ptr<TimingFunction> timing_function)
118    : Keyframe(time, timing_function.Pass()),
119      value_(value) {}
120
121TransformKeyframe::~TransformKeyframe() {}
122
123const TransformOperations& TransformKeyframe::Value() const {
124  return value_;
125}
126
127scoped_ptr<TransformKeyframe> TransformKeyframe::Clone() const {
128  scoped_ptr<TimingFunction> func;
129  if (timing_function())
130    func = timing_function()->Clone();
131  return TransformKeyframe::Create(Time(), Value(), func.Pass());
132}
133
134scoped_ptr<FilterKeyframe> FilterKeyframe::Create(
135    double time,
136    const FilterOperations& value,
137    scoped_ptr<TimingFunction> timing_function) {
138  return make_scoped_ptr(
139      new FilterKeyframe(time, value, timing_function.Pass()));
140}
141
142FilterKeyframe::FilterKeyframe(double time,
143                               const FilterOperations& value,
144                               scoped_ptr<TimingFunction> timing_function)
145    : Keyframe(time, timing_function.Pass()),
146      value_(value) {}
147
148FilterKeyframe::~FilterKeyframe() {}
149
150const FilterOperations& FilterKeyframe::Value() const {
151  return value_;
152}
153
154scoped_ptr<FilterKeyframe> FilterKeyframe::Clone() const {
155  scoped_ptr<TimingFunction> func;
156  if (timing_function())
157    func = timing_function()->Clone();
158  return FilterKeyframe::Create(Time(), Value(), func.Pass());
159}
160
161scoped_ptr<KeyframedColorAnimationCurve> KeyframedColorAnimationCurve::
162    Create() {
163  return make_scoped_ptr(new KeyframedColorAnimationCurve);
164}
165
166KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {}
167
168KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {}
169
170void KeyframedColorAnimationCurve::AddKeyframe(
171    scoped_ptr<ColorKeyframe> keyframe) {
172  InsertKeyframe(keyframe.Pass(), keyframes_);
173}
174
175double KeyframedColorAnimationCurve::Duration() const {
176  return keyframes_.back()->Time() - keyframes_.front()->Time();
177}
178
179scoped_ptr<AnimationCurve> KeyframedColorAnimationCurve::Clone() const {
180  scoped_ptr<KeyframedColorAnimationCurve> to_return(
181      KeyframedColorAnimationCurve::Create());
182  for (size_t i = 0; i < keyframes_.size(); ++i)
183    to_return->AddKeyframe(keyframes_[i]->Clone());
184  return to_return.PassAs<AnimationCurve>();
185}
186
187SkColor KeyframedColorAnimationCurve::GetValue(double t) const {
188  if (t <= keyframes_.front()->Time())
189    return keyframes_.front()->Value();
190
191  if (t >= keyframes_.back()->Time())
192    return keyframes_.back()->Value();
193
194  size_t i = 0;
195  for (; i < keyframes_.size() - 1; ++i) {
196    if (t < keyframes_[i + 1]->Time())
197      break;
198  }
199
200  float progress = GetProgress(t, i, keyframes_);
201
202  return gfx::Tween::ColorValueBetween(
203      progress, keyframes_[i]->Value(), keyframes_[i + 1]->Value());
204}
205
206// KeyframedFloatAnimationCurve
207
208scoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve::
209    Create() {
210  return make_scoped_ptr(new KeyframedFloatAnimationCurve);
211}
212
213KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {}
214
215KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {}
216
217void KeyframedFloatAnimationCurve::AddKeyframe(
218    scoped_ptr<FloatKeyframe> keyframe) {
219  InsertKeyframe(keyframe.Pass(), keyframes_);
220}
221
222double KeyframedFloatAnimationCurve::Duration() const {
223  return keyframes_.back()->Time() - keyframes_.front()->Time();
224}
225
226scoped_ptr<AnimationCurve> KeyframedFloatAnimationCurve::Clone() const {
227  scoped_ptr<KeyframedFloatAnimationCurve> to_return(
228      KeyframedFloatAnimationCurve::Create());
229  for (size_t i = 0; i < keyframes_.size(); ++i)
230    to_return->AddKeyframe(keyframes_[i]->Clone());
231  return to_return.PassAs<AnimationCurve>();
232}
233
234float KeyframedFloatAnimationCurve::GetValue(double t) const {
235  if (t <= keyframes_.front()->Time())
236    return keyframes_.front()->Value();
237
238  if (t >= keyframes_.back()->Time())
239    return keyframes_.back()->Value();
240
241  size_t i = 0;
242  for (; i < keyframes_.size() - 1; ++i) {
243    if (t < keyframes_[i+1]->Time())
244      break;
245  }
246
247  float progress = GetProgress(t, i, keyframes_);
248
249  return keyframes_[i]->Value() +
250      (keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress;
251}
252
253scoped_ptr<KeyframedTransformAnimationCurve> KeyframedTransformAnimationCurve::
254    Create() {
255  return make_scoped_ptr(new KeyframedTransformAnimationCurve);
256}
257
258KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {}
259
260KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {}
261
262void KeyframedTransformAnimationCurve::AddKeyframe(
263    scoped_ptr<TransformKeyframe> keyframe) {
264  InsertKeyframe(keyframe.Pass(), keyframes_);
265}
266
267double KeyframedTransformAnimationCurve::Duration() const {
268  return keyframes_.back()->Time() - keyframes_.front()->Time();
269}
270
271scoped_ptr<AnimationCurve> KeyframedTransformAnimationCurve::Clone() const {
272  scoped_ptr<KeyframedTransformAnimationCurve> to_return(
273      KeyframedTransformAnimationCurve::Create());
274  for (size_t i = 0; i < keyframes_.size(); ++i)
275    to_return->AddKeyframe(keyframes_[i]->Clone());
276  return to_return.PassAs<AnimationCurve>();
277}
278
279// Assumes that (*keyframes).front()->Time() < t < (*keyframes).back()-Time().
280template<typename ValueType, typename KeyframeType>
281static ValueType GetCurveValue(const ScopedPtrVector<KeyframeType>* keyframes,
282                               double t) {
283  size_t i = 0;
284  for (; i < keyframes->size() - 1; ++i) {
285    if (t < (*keyframes)[i+1]->Time())
286      break;
287  }
288
289  double progress = (t - (*keyframes)[i]->Time()) /
290                    ((*keyframes)[i+1]->Time() - (*keyframes)[i]->Time());
291
292  if ((*keyframes)[i]->timing_function())
293    progress = (*keyframes)[i]->timing_function()->GetValue(progress);
294
295  return (*keyframes)[i+1]->Value().Blend((*keyframes)[i]->Value(), progress);
296}
297
298gfx::Transform KeyframedTransformAnimationCurve::GetValue(double t) const {
299  if (t <= keyframes_.front()->Time())
300    return keyframes_.front()->Value().Apply();
301
302  if (t >= keyframes_.back()->Time())
303    return keyframes_.back()->Value().Apply();
304
305  return GetCurveValue<gfx::Transform, TransformKeyframe>(&keyframes_, t);
306}
307
308bool KeyframedTransformAnimationCurve::AnimatedBoundsForBox(
309    const gfx::BoxF& box,
310    gfx::BoxF* bounds) const {
311  DCHECK_GE(keyframes_.size(), 2ul);
312  *bounds = gfx::BoxF();
313  for (size_t i = 0; i < keyframes_.size() - 1; ++i) {
314    gfx::BoxF bounds_for_step;
315    float min_progress = 0.0;
316    float max_progress = 1.0;
317    if (keyframes_[i]->timing_function())
318      keyframes_[i]->timing_function()->Range(&min_progress, &max_progress);
319    if (!keyframes_[i+1]->Value().BlendedBoundsForBox(box,
320                                                      keyframes_[i]->Value(),
321                                                      min_progress,
322                                                      max_progress,
323                                                      &bounds_for_step))
324      return false;
325    bounds->Union(bounds_for_step);
326  }
327  return true;
328}
329
330bool KeyframedTransformAnimationCurve::AffectsScale() const {
331  for (size_t i = 0; i < keyframes_.size(); ++i) {
332    if (keyframes_[i]->Value().AffectsScale())
333      return true;
334  }
335  return false;
336}
337
338bool KeyframedTransformAnimationCurve::IsTranslation() const {
339  for (size_t i = 0; i < keyframes_.size(); ++i) {
340    if (!keyframes_[i]->Value().IsTranslation() &&
341        !keyframes_[i]->Value().IsIdentity())
342      return false;
343  }
344  return true;
345}
346
347bool KeyframedTransformAnimationCurve::MaximumTargetScale(
348    bool forward_direction,
349    float* max_scale) const {
350  DCHECK_GE(keyframes_.size(), 2ul);
351  *max_scale = 0.f;
352
353  // If |forward_direction| is true, then skip the first frame, otherwise
354  // skip the last frame, since that is the original position in the animation.
355  size_t start = 1;
356  size_t end = keyframes_.size();
357  if (!forward_direction) {
358    --start;
359    --end;
360  }
361
362  for (size_t i = start; i < end; ++i) {
363    gfx::Vector3dF target_scale_for_segment;
364    if (!keyframes_[i]->Value().ScaleComponent(&target_scale_for_segment))
365      return false;
366    float max_scale_for_segment =
367        fmax(std::abs(target_scale_for_segment.x()),
368             fmax(std::abs(target_scale_for_segment.y()),
369                  std::abs(target_scale_for_segment.z())));
370    *max_scale = fmax(*max_scale, max_scale_for_segment);
371  }
372  return true;
373}
374
375scoped_ptr<KeyframedFilterAnimationCurve> KeyframedFilterAnimationCurve::
376    Create() {
377  return make_scoped_ptr(new KeyframedFilterAnimationCurve);
378}
379
380KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {}
381
382KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {}
383
384void KeyframedFilterAnimationCurve::AddKeyframe(
385    scoped_ptr<FilterKeyframe> keyframe) {
386  InsertKeyframe(keyframe.Pass(), keyframes_);
387}
388
389double KeyframedFilterAnimationCurve::Duration() const {
390  return keyframes_.back()->Time() - keyframes_.front()->Time();
391}
392
393scoped_ptr<AnimationCurve> KeyframedFilterAnimationCurve::Clone() const {
394  scoped_ptr<KeyframedFilterAnimationCurve> to_return(
395      KeyframedFilterAnimationCurve::Create());
396  for (size_t i = 0; i < keyframes_.size(); ++i)
397    to_return->AddKeyframe(keyframes_[i]->Clone());
398  return to_return.PassAs<AnimationCurve>();
399}
400
401FilterOperations KeyframedFilterAnimationCurve::GetValue(double t) const {
402  if (t <= keyframes_.front()->Time())
403    return keyframes_.front()->Value();
404
405  if (t >= keyframes_.back()->Time())
406    return keyframes_.back()->Value();
407
408  return GetCurveValue<FilterOperations, FilterKeyframe>(&keyframes_, t);
409}
410
411bool KeyframedFilterAnimationCurve::HasFilterThatMovesPixels() const {
412  for (size_t i = 0; i < keyframes_.size(); ++i) {
413    if (keyframes_[i]->Value().HasFilterThatMovesPixels()) {
414      return true;
415    }
416  }
417  return false;
418}
419
420}  // namespace cc
421