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.
7 #include "cc/animation/keyframed_animation_curve.h"
8 #include "cc/base/time_util.h"
9 #include "ui/gfx/animation/tween.h"
10 #include "ui/gfx/geometry/box_f.h"
16 template <class KeyframeType
>
17 void InsertKeyframe(scoped_ptr
<KeyframeType
> keyframe
,
18 ScopedPtrVector
<KeyframeType
>* keyframes
) {
19 // Usually, the keyframes will be added in order, so this loop would be
20 // unnecessary and we should skip it if possible.
21 if (!keyframes
->empty() && keyframe
->Time() < keyframes
->back()->Time()) {
22 for (size_t i
= 0; i
< keyframes
->size(); ++i
) {
23 if (keyframe
->Time() < keyframes
->at(i
)->Time()) {
24 keyframes
->insert(keyframes
->begin() + i
, keyframe
.Pass());
30 keyframes
->push_back(keyframe
.Pass());
33 template <typename KeyframeType
>
34 base::TimeDelta
TransformedAnimationTime(
35 const ScopedPtrVector
<KeyframeType
>& keyframes
,
36 const scoped_ptr
<TimingFunction
>& timing_function
,
37 base::TimeDelta time
) {
38 if (timing_function
) {
39 base::TimeDelta start_time
= keyframes
.front()->Time();
40 base::TimeDelta duration
=
41 keyframes
.back()->Time() - keyframes
.front()->Time();
42 double progress
= TimeUtil::Divide(time
- start_time
, duration
);
44 time
= TimeUtil::Scale(duration
, timing_function
->GetValue(progress
)) +
51 template <typename KeyframeType
>
52 size_t GetActiveKeyframe(const ScopedPtrVector
<KeyframeType
>& keyframes
,
53 base::TimeDelta time
) {
54 DCHECK_GE(keyframes
.size(), 2ul);
56 for (; i
< keyframes
.size() - 2; ++i
) { // Last keyframe is never active.
57 if (time
< keyframes
[i
+ 1]->Time())
64 template <typename KeyframeType
>
65 double TransformedKeyframeProgress(
66 const ScopedPtrVector
<KeyframeType
>& keyframes
,
70 TimeUtil::Divide(time
- keyframes
[i
]->Time(),
71 keyframes
[i
+ 1]->Time() - keyframes
[i
]->Time());
73 if (keyframes
[i
]->timing_function()) {
74 progress
= keyframes
[i
]->timing_function()->GetValue(progress
);
82 Keyframe::Keyframe(base::TimeDelta time
,
83 scoped_ptr
<TimingFunction
> timing_function
)
84 : time_(time
), timing_function_(timing_function
.Pass()) {
87 Keyframe::~Keyframe() {}
89 base::TimeDelta
Keyframe::Time() const {
93 scoped_ptr
<ColorKeyframe
> ColorKeyframe::Create(
96 scoped_ptr
<TimingFunction
> timing_function
) {
97 return make_scoped_ptr(
98 new ColorKeyframe(time
, value
, timing_function
.Pass()));
101 ColorKeyframe::ColorKeyframe(base::TimeDelta time
,
103 scoped_ptr
<TimingFunction
> timing_function
)
104 : Keyframe(time
, timing_function
.Pass()), value_(value
) {
107 ColorKeyframe::~ColorKeyframe() {}
109 SkColor
ColorKeyframe::Value() const { return value_
; }
111 scoped_ptr
<ColorKeyframe
> ColorKeyframe::Clone() const {
112 scoped_ptr
<TimingFunction
> func
;
113 if (timing_function())
114 func
= timing_function()->Clone();
115 return ColorKeyframe::Create(Time(), Value(), func
.Pass());
118 scoped_ptr
<FloatKeyframe
> FloatKeyframe::Create(
119 base::TimeDelta time
,
121 scoped_ptr
<TimingFunction
> timing_function
) {
122 return make_scoped_ptr(
123 new FloatKeyframe(time
, value
, timing_function
.Pass()));
126 FloatKeyframe::FloatKeyframe(base::TimeDelta time
,
128 scoped_ptr
<TimingFunction
> timing_function
)
129 : Keyframe(time
, timing_function
.Pass()), value_(value
) {
132 FloatKeyframe::~FloatKeyframe() {}
134 float FloatKeyframe::Value() const {
138 scoped_ptr
<FloatKeyframe
> FloatKeyframe::Clone() const {
139 scoped_ptr
<TimingFunction
> func
;
140 if (timing_function())
141 func
= timing_function()->Clone();
142 return FloatKeyframe::Create(Time(), Value(), func
.Pass());
145 scoped_ptr
<TransformKeyframe
> TransformKeyframe::Create(
146 base::TimeDelta time
,
147 const TransformOperations
& value
,
148 scoped_ptr
<TimingFunction
> timing_function
) {
149 return make_scoped_ptr(
150 new TransformKeyframe(time
, value
, timing_function
.Pass()));
153 TransformKeyframe::TransformKeyframe(base::TimeDelta time
,
154 const TransformOperations
& value
,
155 scoped_ptr
<TimingFunction
> timing_function
)
156 : Keyframe(time
, timing_function
.Pass()), value_(value
) {
159 TransformKeyframe::~TransformKeyframe() {}
161 const TransformOperations
& TransformKeyframe::Value() const {
165 scoped_ptr
<TransformKeyframe
> TransformKeyframe::Clone() const {
166 scoped_ptr
<TimingFunction
> func
;
167 if (timing_function())
168 func
= timing_function()->Clone();
169 return TransformKeyframe::Create(Time(), Value(), func
.Pass());
172 scoped_ptr
<FilterKeyframe
> FilterKeyframe::Create(
173 base::TimeDelta time
,
174 const FilterOperations
& value
,
175 scoped_ptr
<TimingFunction
> timing_function
) {
176 return make_scoped_ptr(
177 new FilterKeyframe(time
, value
, timing_function
.Pass()));
180 FilterKeyframe::FilterKeyframe(base::TimeDelta time
,
181 const FilterOperations
& value
,
182 scoped_ptr
<TimingFunction
> timing_function
)
183 : Keyframe(time
, timing_function
.Pass()), value_(value
) {
186 FilterKeyframe::~FilterKeyframe() {}
188 const FilterOperations
& FilterKeyframe::Value() const {
192 scoped_ptr
<FilterKeyframe
> FilterKeyframe::Clone() const {
193 scoped_ptr
<TimingFunction
> func
;
194 if (timing_function())
195 func
= timing_function()->Clone();
196 return FilterKeyframe::Create(Time(), Value(), func
.Pass());
199 scoped_ptr
<KeyframedColorAnimationCurve
> KeyframedColorAnimationCurve::
201 return make_scoped_ptr(new KeyframedColorAnimationCurve
);
204 KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {}
206 KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {}
208 void KeyframedColorAnimationCurve::AddKeyframe(
209 scoped_ptr
<ColorKeyframe
> keyframe
) {
210 InsertKeyframe(keyframe
.Pass(), &keyframes_
);
213 base::TimeDelta
KeyframedColorAnimationCurve::Duration() const {
214 return keyframes_
.back()->Time() - keyframes_
.front()->Time();
217 scoped_ptr
<AnimationCurve
> KeyframedColorAnimationCurve::Clone() const {
218 scoped_ptr
<KeyframedColorAnimationCurve
> to_return
=
219 KeyframedColorAnimationCurve::Create();
220 for (size_t i
= 0; i
< keyframes_
.size(); ++i
)
221 to_return
->AddKeyframe(keyframes_
[i
]->Clone());
223 if (timing_function_
)
224 to_return
->SetTimingFunction(timing_function_
->Clone());
226 return to_return
.Pass();
229 SkColor
KeyframedColorAnimationCurve::GetValue(base::TimeDelta t
) const {
230 if (t
<= keyframes_
.front()->Time())
231 return keyframes_
.front()->Value();
233 if (t
>= keyframes_
.back()->Time())
234 return keyframes_
.back()->Value();
236 t
= TransformedAnimationTime(keyframes_
, timing_function_
, t
);
237 size_t i
= GetActiveKeyframe(keyframes_
, t
);
238 double progress
= TransformedKeyframeProgress(keyframes_
, t
, i
);
240 return gfx::Tween::ColorValueBetween(
241 progress
, keyframes_
[i
]->Value(), keyframes_
[i
+ 1]->Value());
244 // KeyframedFloatAnimationCurve
246 scoped_ptr
<KeyframedFloatAnimationCurve
> KeyframedFloatAnimationCurve::
248 return make_scoped_ptr(new KeyframedFloatAnimationCurve
);
251 KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {}
253 KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {}
255 void KeyframedFloatAnimationCurve::AddKeyframe(
256 scoped_ptr
<FloatKeyframe
> keyframe
) {
257 InsertKeyframe(keyframe
.Pass(), &keyframes_
);
260 base::TimeDelta
KeyframedFloatAnimationCurve::Duration() const {
261 return keyframes_
.back()->Time() - keyframes_
.front()->Time();
264 scoped_ptr
<AnimationCurve
> KeyframedFloatAnimationCurve::Clone() const {
265 scoped_ptr
<KeyframedFloatAnimationCurve
> to_return
=
266 KeyframedFloatAnimationCurve::Create();
267 for (size_t i
= 0; i
< keyframes_
.size(); ++i
)
268 to_return
->AddKeyframe(keyframes_
[i
]->Clone());
270 if (timing_function_
)
271 to_return
->SetTimingFunction(timing_function_
->Clone());
273 return to_return
.Pass();
276 float KeyframedFloatAnimationCurve::GetValue(base::TimeDelta t
) const {
277 if (t
<= keyframes_
.front()->Time())
278 return keyframes_
.front()->Value();
280 if (t
>= keyframes_
.back()->Time())
281 return keyframes_
.back()->Value();
283 t
= TransformedAnimationTime(keyframes_
, timing_function_
, t
);
284 size_t i
= GetActiveKeyframe(keyframes_
, t
);
285 double progress
= TransformedKeyframeProgress(keyframes_
, t
, i
);
287 return keyframes_
[i
]->Value() +
288 (keyframes_
[i
+1]->Value() - keyframes_
[i
]->Value()) * progress
;
291 scoped_ptr
<KeyframedTransformAnimationCurve
> KeyframedTransformAnimationCurve::
293 return make_scoped_ptr(new KeyframedTransformAnimationCurve
);
296 KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {}
298 KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {}
300 void KeyframedTransformAnimationCurve::AddKeyframe(
301 scoped_ptr
<TransformKeyframe
> keyframe
) {
302 InsertKeyframe(keyframe
.Pass(), &keyframes_
);
305 base::TimeDelta
KeyframedTransformAnimationCurve::Duration() const {
306 return keyframes_
.back()->Time() - keyframes_
.front()->Time();
309 scoped_ptr
<AnimationCurve
> KeyframedTransformAnimationCurve::Clone() const {
310 scoped_ptr
<KeyframedTransformAnimationCurve
> to_return
=
311 KeyframedTransformAnimationCurve::Create();
312 for (size_t i
= 0; i
< keyframes_
.size(); ++i
)
313 to_return
->AddKeyframe(keyframes_
[i
]->Clone());
315 if (timing_function_
)
316 to_return
->SetTimingFunction(timing_function_
->Clone());
318 return to_return
.Pass();
321 gfx::Transform
KeyframedTransformAnimationCurve::GetValue(
322 base::TimeDelta t
) const {
323 if (t
<= keyframes_
.front()->Time())
324 return keyframes_
.front()->Value().Apply();
326 if (t
>= keyframes_
.back()->Time())
327 return keyframes_
.back()->Value().Apply();
329 t
= TransformedAnimationTime(keyframes_
, timing_function_
, t
);
330 size_t i
= GetActiveKeyframe(keyframes_
, t
);
331 double progress
= TransformedKeyframeProgress(keyframes_
, t
, i
);
333 return keyframes_
[i
+ 1]->Value().Blend(keyframes_
[i
]->Value(), progress
);
336 bool KeyframedTransformAnimationCurve::AnimatedBoundsForBox(
337 const gfx::BoxF
& box
,
338 gfx::BoxF
* bounds
) const {
339 DCHECK_GE(keyframes_
.size(), 2ul);
340 *bounds
= gfx::BoxF();
341 for (size_t i
= 0; i
< keyframes_
.size() - 1; ++i
) {
342 gfx::BoxF bounds_for_step
;
343 float min_progress
= 0.0;
344 float max_progress
= 1.0;
345 if (keyframes_
[i
]->timing_function())
346 keyframes_
[i
]->timing_function()->Range(&min_progress
, &max_progress
);
347 if (!keyframes_
[i
+1]->Value().BlendedBoundsForBox(box
,
348 keyframes_
[i
]->Value(),
353 bounds
->Union(bounds_for_step
);
358 bool KeyframedTransformAnimationCurve::AffectsScale() const {
359 for (size_t i
= 0; i
< keyframes_
.size(); ++i
) {
360 if (keyframes_
[i
]->Value().AffectsScale())
366 bool KeyframedTransformAnimationCurve::PreservesAxisAlignment() const {
367 for (size_t i
= 0; i
< keyframes_
.size(); ++i
) {
368 if (!keyframes_
[i
]->Value().PreservesAxisAlignment())
374 bool KeyframedTransformAnimationCurve::IsTranslation() const {
375 for (size_t i
= 0; i
< keyframes_
.size(); ++i
) {
376 if (!keyframes_
[i
]->Value().IsTranslation() &&
377 !keyframes_
[i
]->Value().IsIdentity())
382 bool KeyframedTransformAnimationCurve::AnimationStartScale(
383 bool forward_direction
,
384 float* start_scale
) const {
385 DCHECK_GE(keyframes_
.size(), 2ul);
387 size_t start_location
= 0;
388 if (!forward_direction
) {
389 start_location
= keyframes_
.size() - 1;
392 gfx::Vector3dF initial_target_scale
;
393 if (!keyframes_
[start_location
]->Value().ScaleComponent(
394 &initial_target_scale
))
396 float start_scale_for_segment
=
397 fmax(std::abs(initial_target_scale
.x()),
398 fmax(std::abs(initial_target_scale
.y()),
399 std::abs(initial_target_scale
.z())));
400 *start_scale
= start_scale_for_segment
;
403 bool KeyframedTransformAnimationCurve::MaximumTargetScale(
404 bool forward_direction
,
405 float* max_scale
) const {
406 DCHECK_GE(keyframes_
.size(), 2ul);
409 // If |forward_direction| is true, then skip the first frame, otherwise
410 // skip the last frame, since that is the original position in the animation.
412 size_t end
= keyframes_
.size();
413 if (!forward_direction
) {
418 for (size_t i
= start
; i
< end
; ++i
) {
419 gfx::Vector3dF target_scale_for_segment
;
420 if (!keyframes_
[i
]->Value().ScaleComponent(&target_scale_for_segment
))
422 float max_scale_for_segment
=
423 fmax(std::abs(target_scale_for_segment
.x()),
424 fmax(std::abs(target_scale_for_segment
.y()),
425 std::abs(target_scale_for_segment
.z())));
426 *max_scale
= fmax(*max_scale
, max_scale_for_segment
);
431 scoped_ptr
<KeyframedFilterAnimationCurve
> KeyframedFilterAnimationCurve::
433 return make_scoped_ptr(new KeyframedFilterAnimationCurve
);
436 KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {}
438 KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {}
440 void KeyframedFilterAnimationCurve::AddKeyframe(
441 scoped_ptr
<FilterKeyframe
> keyframe
) {
442 InsertKeyframe(keyframe
.Pass(), &keyframes_
);
445 base::TimeDelta
KeyframedFilterAnimationCurve::Duration() const {
446 return keyframes_
.back()->Time() - keyframes_
.front()->Time();
449 scoped_ptr
<AnimationCurve
> KeyframedFilterAnimationCurve::Clone() const {
450 scoped_ptr
<KeyframedFilterAnimationCurve
> to_return
=
451 KeyframedFilterAnimationCurve::Create();
452 for (size_t i
= 0; i
< keyframes_
.size(); ++i
)
453 to_return
->AddKeyframe(keyframes_
[i
]->Clone());
455 if (timing_function_
)
456 to_return
->SetTimingFunction(timing_function_
->Clone());
458 return to_return
.Pass();
461 FilterOperations
KeyframedFilterAnimationCurve::GetValue(
462 base::TimeDelta t
) const {
463 if (t
<= keyframes_
.front()->Time())
464 return keyframes_
.front()->Value();
466 if (t
>= keyframes_
.back()->Time())
467 return keyframes_
.back()->Value();
469 t
= TransformedAnimationTime(keyframes_
, timing_function_
, t
);
470 size_t i
= GetActiveKeyframe(keyframes_
, t
);
471 double progress
= TransformedKeyframeProgress(keyframes_
, t
, i
);
473 return keyframes_
[i
+ 1]->Value().Blend(keyframes_
[i
]->Value(), progress
);
476 bool KeyframedFilterAnimationCurve::HasFilterThatMovesPixels() const {
477 for (size_t i
= 0; i
< keyframes_
.size(); ++i
) {
478 if (keyframes_
[i
]->Value().HasFilterThatMovesPixels()) {