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 "ui/gfx/animation/tween.h"
9 #include "ui/gfx/box_f.h"
15 template <class KeyframeType
>
16 void InsertKeyframe(scoped_ptr
<KeyframeType
> keyframe
,
17 ScopedPtrVector
<KeyframeType
>* 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
->at(i
)->Time()) {
23 keyframes
->insert(keyframes
->begin() + i
, keyframe
.Pass());
29 keyframes
->push_back(keyframe
.Pass());
32 template <typename KeyframeType
>
33 double TransformedAnimationTime(
34 const ScopedPtrVector
<KeyframeType
>& keyframes
,
35 const scoped_ptr
<TimingFunction
>& timing_function
,
37 if (timing_function
) {
38 double start_time
= keyframes
.front()->Time();
39 double duration
= keyframes
.back()->Time() - start_time
;
40 double progress
= (time
- start_time
) / duration
;
42 time
= timing_function
->GetValue(progress
) * duration
+ start_time
;
48 template <typename KeyframeType
>
49 size_t GetActiveKeyframe(const ScopedPtrVector
<KeyframeType
>& keyframes
,
51 DCHECK_GE(keyframes
.size(), 2ul);
53 for (; i
< keyframes
.size() - 2; ++i
) { // Last keyframe is never active.
54 if (time
< keyframes
[i
+ 1]->Time())
61 template <typename KeyframeType
>
62 double TransformedKeyframeProgress(
63 const ScopedPtrVector
<KeyframeType
>& keyframes
,
66 double progress
= (time
- keyframes
[i
]->Time()) /
67 (keyframes
[i
+ 1]->Time() - keyframes
[i
]->Time());
69 if (keyframes
[i
]->timing_function()) {
70 progress
= keyframes
[i
]->timing_function()->GetValue(progress
);
78 Keyframe::Keyframe(double time
, scoped_ptr
<TimingFunction
> timing_function
)
80 timing_function_(timing_function
.Pass()) {}
82 Keyframe::~Keyframe() {}
84 double Keyframe::Time() const {
88 scoped_ptr
<ColorKeyframe
> ColorKeyframe::Create(
91 scoped_ptr
<TimingFunction
> timing_function
) {
92 return make_scoped_ptr(
93 new ColorKeyframe(time
, value
, timing_function
.Pass()));
96 ColorKeyframe::ColorKeyframe(double time
,
98 scoped_ptr
<TimingFunction
> timing_function
)
99 : Keyframe(time
, timing_function
.Pass()),
102 ColorKeyframe::~ColorKeyframe() {}
104 SkColor
ColorKeyframe::Value() const { return value_
; }
106 scoped_ptr
<ColorKeyframe
> ColorKeyframe::Clone() const {
107 scoped_ptr
<TimingFunction
> func
;
108 if (timing_function())
109 func
= timing_function()->Clone();
110 return ColorKeyframe::Create(Time(), Value(), func
.Pass());
113 scoped_ptr
<FloatKeyframe
> FloatKeyframe::Create(
116 scoped_ptr
<TimingFunction
> timing_function
) {
117 return make_scoped_ptr(
118 new FloatKeyframe(time
, value
, timing_function
.Pass()));
121 FloatKeyframe::FloatKeyframe(double time
,
123 scoped_ptr
<TimingFunction
> timing_function
)
124 : Keyframe(time
, timing_function
.Pass()),
127 FloatKeyframe::~FloatKeyframe() {}
129 float FloatKeyframe::Value() const {
133 scoped_ptr
<FloatKeyframe
> FloatKeyframe::Clone() const {
134 scoped_ptr
<TimingFunction
> func
;
135 if (timing_function())
136 func
= timing_function()->Clone();
137 return FloatKeyframe::Create(Time(), Value(), func
.Pass());
140 scoped_ptr
<TransformKeyframe
> TransformKeyframe::Create(
142 const TransformOperations
& value
,
143 scoped_ptr
<TimingFunction
> timing_function
) {
144 return make_scoped_ptr(
145 new TransformKeyframe(time
, value
, timing_function
.Pass()));
148 TransformKeyframe::TransformKeyframe(double time
,
149 const TransformOperations
& value
,
150 scoped_ptr
<TimingFunction
> timing_function
)
151 : Keyframe(time
, timing_function
.Pass()),
154 TransformKeyframe::~TransformKeyframe() {}
156 const TransformOperations
& TransformKeyframe::Value() const {
160 scoped_ptr
<TransformKeyframe
> TransformKeyframe::Clone() const {
161 scoped_ptr
<TimingFunction
> func
;
162 if (timing_function())
163 func
= timing_function()->Clone();
164 return TransformKeyframe::Create(Time(), Value(), func
.Pass());
167 scoped_ptr
<FilterKeyframe
> FilterKeyframe::Create(
169 const FilterOperations
& value
,
170 scoped_ptr
<TimingFunction
> timing_function
) {
171 return make_scoped_ptr(
172 new FilterKeyframe(time
, value
, timing_function
.Pass()));
175 FilterKeyframe::FilterKeyframe(double time
,
176 const FilterOperations
& value
,
177 scoped_ptr
<TimingFunction
> timing_function
)
178 : Keyframe(time
, timing_function
.Pass()),
181 FilterKeyframe::~FilterKeyframe() {}
183 const FilterOperations
& FilterKeyframe::Value() const {
187 scoped_ptr
<FilterKeyframe
> FilterKeyframe::Clone() const {
188 scoped_ptr
<TimingFunction
> func
;
189 if (timing_function())
190 func
= timing_function()->Clone();
191 return FilterKeyframe::Create(Time(), Value(), func
.Pass());
194 scoped_ptr
<KeyframedColorAnimationCurve
> KeyframedColorAnimationCurve::
196 return make_scoped_ptr(new KeyframedColorAnimationCurve
);
199 KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {}
201 KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {}
203 void KeyframedColorAnimationCurve::AddKeyframe(
204 scoped_ptr
<ColorKeyframe
> keyframe
) {
205 InsertKeyframe(keyframe
.Pass(), &keyframes_
);
208 double KeyframedColorAnimationCurve::Duration() const {
209 return keyframes_
.back()->Time() - keyframes_
.front()->Time();
212 scoped_ptr
<AnimationCurve
> KeyframedColorAnimationCurve::Clone() const {
213 scoped_ptr
<KeyframedColorAnimationCurve
> to_return
=
214 KeyframedColorAnimationCurve::Create();
215 for (size_t i
= 0; i
< keyframes_
.size(); ++i
)
216 to_return
->AddKeyframe(keyframes_
[i
]->Clone());
218 if (timing_function_
)
219 to_return
->SetTimingFunction(timing_function_
->Clone());
221 return to_return
.Pass();
224 SkColor
KeyframedColorAnimationCurve::GetValue(double t
) const {
225 if (t
<= keyframes_
.front()->Time())
226 return keyframes_
.front()->Value();
228 if (t
>= keyframes_
.back()->Time())
229 return keyframes_
.back()->Value();
231 t
= TransformedAnimationTime(keyframes_
, timing_function_
, t
);
232 size_t i
= GetActiveKeyframe(keyframes_
, t
);
233 double progress
= TransformedKeyframeProgress(keyframes_
, t
, i
);
235 return gfx::Tween::ColorValueBetween(
236 progress
, keyframes_
[i
]->Value(), keyframes_
[i
+ 1]->Value());
239 // KeyframedFloatAnimationCurve
241 scoped_ptr
<KeyframedFloatAnimationCurve
> KeyframedFloatAnimationCurve::
243 return make_scoped_ptr(new KeyframedFloatAnimationCurve
);
246 KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {}
248 KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {}
250 void KeyframedFloatAnimationCurve::AddKeyframe(
251 scoped_ptr
<FloatKeyframe
> keyframe
) {
252 InsertKeyframe(keyframe
.Pass(), &keyframes_
);
255 double KeyframedFloatAnimationCurve::Duration() const {
256 return keyframes_
.back()->Time() - keyframes_
.front()->Time();
259 scoped_ptr
<AnimationCurve
> KeyframedFloatAnimationCurve::Clone() const {
260 scoped_ptr
<KeyframedFloatAnimationCurve
> to_return
=
261 KeyframedFloatAnimationCurve::Create();
262 for (size_t i
= 0; i
< keyframes_
.size(); ++i
)
263 to_return
->AddKeyframe(keyframes_
[i
]->Clone());
265 if (timing_function_
)
266 to_return
->SetTimingFunction(timing_function_
->Clone());
268 return to_return
.Pass();
271 float KeyframedFloatAnimationCurve::GetValue(double t
) const {
272 if (t
<= keyframes_
.front()->Time())
273 return keyframes_
.front()->Value();
275 if (t
>= keyframes_
.back()->Time())
276 return keyframes_
.back()->Value();
278 t
= TransformedAnimationTime(keyframes_
, timing_function_
, t
);
279 size_t i
= GetActiveKeyframe(keyframes_
, t
);
280 double progress
= TransformedKeyframeProgress(keyframes_
, t
, i
);
282 return keyframes_
[i
]->Value() +
283 (keyframes_
[i
+1]->Value() - keyframes_
[i
]->Value()) * progress
;
286 scoped_ptr
<KeyframedTransformAnimationCurve
> KeyframedTransformAnimationCurve::
288 return make_scoped_ptr(new KeyframedTransformAnimationCurve
);
291 KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {}
293 KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {}
295 void KeyframedTransformAnimationCurve::AddKeyframe(
296 scoped_ptr
<TransformKeyframe
> keyframe
) {
297 InsertKeyframe(keyframe
.Pass(), &keyframes_
);
300 double KeyframedTransformAnimationCurve::Duration() const {
301 return keyframes_
.back()->Time() - keyframes_
.front()->Time();
304 scoped_ptr
<AnimationCurve
> KeyframedTransformAnimationCurve::Clone() const {
305 scoped_ptr
<KeyframedTransformAnimationCurve
> to_return
=
306 KeyframedTransformAnimationCurve::Create();
307 for (size_t i
= 0; i
< keyframes_
.size(); ++i
)
308 to_return
->AddKeyframe(keyframes_
[i
]->Clone());
310 if (timing_function_
)
311 to_return
->SetTimingFunction(timing_function_
->Clone());
313 return to_return
.Pass();
316 gfx::Transform
KeyframedTransformAnimationCurve::GetValue(double t
) const {
317 if (t
<= keyframes_
.front()->Time())
318 return keyframes_
.front()->Value().Apply();
320 if (t
>= keyframes_
.back()->Time())
321 return keyframes_
.back()->Value().Apply();
323 t
= TransformedAnimationTime(keyframes_
, timing_function_
, t
);
324 size_t i
= GetActiveKeyframe(keyframes_
, t
);
325 double progress
= TransformedKeyframeProgress(keyframes_
, t
, i
);
327 return keyframes_
[i
+ 1]->Value().Blend(keyframes_
[i
]->Value(), progress
);
330 bool KeyframedTransformAnimationCurve::AnimatedBoundsForBox(
331 const gfx::BoxF
& box
,
332 gfx::BoxF
* bounds
) const {
333 DCHECK_GE(keyframes_
.size(), 2ul);
334 *bounds
= gfx::BoxF();
335 for (size_t i
= 0; i
< keyframes_
.size() - 1; ++i
) {
336 gfx::BoxF bounds_for_step
;
337 float min_progress
= 0.0;
338 float max_progress
= 1.0;
339 if (keyframes_
[i
]->timing_function())
340 keyframes_
[i
]->timing_function()->Range(&min_progress
, &max_progress
);
341 if (!keyframes_
[i
+1]->Value().BlendedBoundsForBox(box
,
342 keyframes_
[i
]->Value(),
347 bounds
->Union(bounds_for_step
);
352 bool KeyframedTransformAnimationCurve::AffectsScale() const {
353 for (size_t i
= 0; i
< keyframes_
.size(); ++i
) {
354 if (keyframes_
[i
]->Value().AffectsScale())
360 bool KeyframedTransformAnimationCurve::IsTranslation() const {
361 for (size_t i
= 0; i
< keyframes_
.size(); ++i
) {
362 if (!keyframes_
[i
]->Value().IsTranslation() &&
363 !keyframes_
[i
]->Value().IsIdentity())
369 bool KeyframedTransformAnimationCurve::MaximumScale(float* max_scale
) const {
370 DCHECK_GE(keyframes_
.size(), 2ul);
372 for (size_t i
= 1; i
< keyframes_
.size(); ++i
) {
373 float min_progress
= 0.f
;
374 float max_progress
= 1.f
;
375 if (keyframes_
[i
- 1]->timing_function())
376 keyframes_
[i
- 1]->timing_function()->Range(&min_progress
, &max_progress
);
378 float max_scale_for_segment
= 0.f
;
379 if (!keyframes_
[i
]->Value().MaximumScale(keyframes_
[i
- 1]->Value(),
382 &max_scale_for_segment
))
385 *max_scale
= std::max(*max_scale
, max_scale_for_segment
);
390 scoped_ptr
<KeyframedFilterAnimationCurve
> KeyframedFilterAnimationCurve::
392 return make_scoped_ptr(new KeyframedFilterAnimationCurve
);
395 KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {}
397 KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {}
399 void KeyframedFilterAnimationCurve::AddKeyframe(
400 scoped_ptr
<FilterKeyframe
> keyframe
) {
401 InsertKeyframe(keyframe
.Pass(), &keyframes_
);
404 double KeyframedFilterAnimationCurve::Duration() const {
405 return keyframes_
.back()->Time() - keyframes_
.front()->Time();
408 scoped_ptr
<AnimationCurve
> KeyframedFilterAnimationCurve::Clone() const {
409 scoped_ptr
<KeyframedFilterAnimationCurve
> to_return
=
410 KeyframedFilterAnimationCurve::Create();
411 for (size_t i
= 0; i
< keyframes_
.size(); ++i
)
412 to_return
->AddKeyframe(keyframes_
[i
]->Clone());
414 if (timing_function_
)
415 to_return
->SetTimingFunction(timing_function_
->Clone());
417 return to_return
.Pass();
420 FilterOperations
KeyframedFilterAnimationCurve::GetValue(double t
) const {
421 if (t
<= keyframes_
.front()->Time())
422 return keyframes_
.front()->Value();
424 if (t
>= keyframes_
.back()->Time())
425 return keyframes_
.back()->Value();
427 t
= TransformedAnimationTime(keyframes_
, timing_function_
, t
);
428 size_t i
= GetActiveKeyframe(keyframes_
, t
);
429 double progress
= TransformedKeyframeProgress(keyframes_
, t
, i
);
431 return keyframes_
[i
+ 1]->Value().Blend(keyframes_
[i
]->Value(), progress
);
434 bool KeyframedFilterAnimationCurve::HasFilterThatMovesPixels() const {
435 for (size_t i
= 0; i
< keyframes_
.size(); ++i
) {
436 if (keyframes_
[i
]->Value().HasFilterThatMovesPixels()) {