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