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.
5 #include "cc/animation/keyframed_animation_curve.h"
6 #include "ui/gfx/animation/tween.h"
7 #include "ui/gfx/box_f.h"
13 template <class Keyframe
>
14 void InsertKeyframe(scoped_ptr
<Keyframe
> keyframe
,
15 ScopedPtrVector
<Keyframe
>& keyframes
) {
16 // Usually, the keyframes will be added in order, so this loop would be
17 // unnecessary and we should skip it if possible.
18 if (!keyframes
.empty() && keyframe
->Time() < keyframes
.back()->Time()) {
19 for (size_t i
= 0; i
< keyframes
.size(); ++i
) {
20 if (keyframe
->Time() < keyframes
[i
]->Time()) {
21 keyframes
.insert(keyframes
.begin() + i
, keyframe
.Pass());
27 keyframes
.push_back(keyframe
.Pass());
30 template <class Keyframes
>
31 float GetProgress(double t
, size_t i
, const Keyframes
& keyframes
) {
33 static_cast<float>((t
- keyframes
[i
]->Time()) /
34 (keyframes
[i
+ 1]->Time() - keyframes
[i
]->Time()));
36 if (keyframes
[i
]->timing_function())
37 progress
= keyframes
[i
]->timing_function()->GetValue(progress
);
41 scoped_ptr
<TimingFunction
> CloneTimingFunction(
42 const TimingFunction
* timing_function
) {
43 DCHECK(timing_function
);
44 scoped_ptr
<AnimationCurve
> curve(timing_function
->Clone());
45 return scoped_ptr
<TimingFunction
>(
46 static_cast<TimingFunction
*>(curve
.release()));
51 Keyframe::Keyframe(double time
, scoped_ptr
<TimingFunction
> timing_function
)
53 timing_function_(timing_function
.Pass()) {}
55 Keyframe::~Keyframe() {}
57 double Keyframe::Time() const {
61 scoped_ptr
<ColorKeyframe
> ColorKeyframe::Create(
64 scoped_ptr
<TimingFunction
> timing_function
) {
65 return make_scoped_ptr(
66 new ColorKeyframe(time
, value
, timing_function
.Pass()));
69 ColorKeyframe::ColorKeyframe(double time
,
71 scoped_ptr
<TimingFunction
> timing_function
)
72 : Keyframe(time
, timing_function
.Pass()),
75 ColorKeyframe::~ColorKeyframe() {}
77 SkColor
ColorKeyframe::Value() const { return value_
; }
79 scoped_ptr
<ColorKeyframe
> ColorKeyframe::Clone() const {
80 scoped_ptr
<TimingFunction
> func
;
81 if (timing_function())
82 func
= CloneTimingFunction(timing_function());
83 return ColorKeyframe::Create(Time(), Value(), func
.Pass());
86 scoped_ptr
<FloatKeyframe
> FloatKeyframe::Create(
89 scoped_ptr
<TimingFunction
> timing_function
) {
90 return make_scoped_ptr(
91 new FloatKeyframe(time
, value
, timing_function
.Pass()));
94 FloatKeyframe::FloatKeyframe(double time
,
96 scoped_ptr
<TimingFunction
> timing_function
)
97 : Keyframe(time
, timing_function
.Pass()),
100 FloatKeyframe::~FloatKeyframe() {}
102 float FloatKeyframe::Value() const {
106 scoped_ptr
<FloatKeyframe
> FloatKeyframe::Clone() const {
107 scoped_ptr
<TimingFunction
> func
;
108 if (timing_function())
109 func
= CloneTimingFunction(timing_function());
110 return FloatKeyframe::Create(Time(), Value(), func
.Pass());
113 scoped_ptr
<TransformKeyframe
> TransformKeyframe::Create(
115 const TransformOperations
& value
,
116 scoped_ptr
<TimingFunction
> timing_function
) {
117 return make_scoped_ptr(
118 new TransformKeyframe(time
, value
, timing_function
.Pass()));
121 TransformKeyframe::TransformKeyframe(double time
,
122 const TransformOperations
& value
,
123 scoped_ptr
<TimingFunction
> timing_function
)
124 : Keyframe(time
, timing_function
.Pass()),
127 TransformKeyframe::~TransformKeyframe() {}
129 const TransformOperations
& TransformKeyframe::Value() const {
133 scoped_ptr
<TransformKeyframe
> TransformKeyframe::Clone() const {
134 scoped_ptr
<TimingFunction
> func
;
135 if (timing_function())
136 func
= CloneTimingFunction(timing_function());
137 return TransformKeyframe::Create(Time(), Value(), func
.Pass());
140 scoped_ptr
<FilterKeyframe
> FilterKeyframe::Create(
142 const FilterOperations
& value
,
143 scoped_ptr
<TimingFunction
> timing_function
) {
144 return make_scoped_ptr(
145 new FilterKeyframe(time
, value
, timing_function
.Pass()));
148 FilterKeyframe::FilterKeyframe(double time
,
149 const FilterOperations
& value
,
150 scoped_ptr
<TimingFunction
> timing_function
)
151 : Keyframe(time
, timing_function
.Pass()),
154 FilterKeyframe::~FilterKeyframe() {}
156 const FilterOperations
& FilterKeyframe::Value() const {
160 scoped_ptr
<FilterKeyframe
> FilterKeyframe::Clone() const {
161 scoped_ptr
<TimingFunction
> func
;
162 if (timing_function())
163 func
= CloneTimingFunction(timing_function());
164 return FilterKeyframe::Create(Time(), Value(), func
.Pass());
167 scoped_ptr
<KeyframedColorAnimationCurve
> KeyframedColorAnimationCurve::
169 return make_scoped_ptr(new KeyframedColorAnimationCurve
);
172 KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {}
174 KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {}
176 void KeyframedColorAnimationCurve::AddKeyframe(
177 scoped_ptr
<ColorKeyframe
> keyframe
) {
178 InsertKeyframe(keyframe
.Pass(), keyframes_
);
181 double KeyframedColorAnimationCurve::Duration() const {
182 return keyframes_
.back()->Time() - keyframes_
.front()->Time();
185 scoped_ptr
<AnimationCurve
> KeyframedColorAnimationCurve::Clone() const {
186 scoped_ptr
<KeyframedColorAnimationCurve
> to_return(
187 KeyframedColorAnimationCurve::Create());
188 for (size_t i
= 0; i
< keyframes_
.size(); ++i
)
189 to_return
->AddKeyframe(keyframes_
[i
]->Clone());
190 return to_return
.PassAs
<AnimationCurve
>();
193 SkColor
KeyframedColorAnimationCurve::GetValue(double t
) const {
194 if (t
<= keyframes_
.front()->Time())
195 return keyframes_
.front()->Value();
197 if (t
>= keyframes_
.back()->Time())
198 return keyframes_
.back()->Value();
201 for (; i
< keyframes_
.size() - 1; ++i
) {
202 if (t
< keyframes_
[i
+ 1]->Time())
206 float progress
= GetProgress(t
, i
, keyframes_
);
208 return gfx::Tween::ColorValueBetween(
209 progress
, keyframes_
[i
]->Value(), keyframes_
[i
+ 1]->Value());
212 // KeyframedFloatAnimationCurve
214 scoped_ptr
<KeyframedFloatAnimationCurve
> KeyframedFloatAnimationCurve::
216 return make_scoped_ptr(new KeyframedFloatAnimationCurve
);
219 KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {}
221 KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {}
223 void KeyframedFloatAnimationCurve::AddKeyframe(
224 scoped_ptr
<FloatKeyframe
> keyframe
) {
225 InsertKeyframe(keyframe
.Pass(), keyframes_
);
228 double KeyframedFloatAnimationCurve::Duration() const {
229 return keyframes_
.back()->Time() - keyframes_
.front()->Time();
232 scoped_ptr
<AnimationCurve
> KeyframedFloatAnimationCurve::Clone() const {
233 scoped_ptr
<KeyframedFloatAnimationCurve
> to_return(
234 KeyframedFloatAnimationCurve::Create());
235 for (size_t i
= 0; i
< keyframes_
.size(); ++i
)
236 to_return
->AddKeyframe(keyframes_
[i
]->Clone());
237 return to_return
.PassAs
<AnimationCurve
>();
240 float KeyframedFloatAnimationCurve::GetValue(double t
) const {
241 if (t
<= keyframes_
.front()->Time())
242 return keyframes_
.front()->Value();
244 if (t
>= keyframes_
.back()->Time())
245 return keyframes_
.back()->Value();
248 for (; i
< keyframes_
.size() - 1; ++i
) {
249 if (t
< keyframes_
[i
+1]->Time())
253 float progress
= GetProgress(t
, i
, keyframes_
);
255 return keyframes_
[i
]->Value() +
256 (keyframes_
[i
+1]->Value() - keyframes_
[i
]->Value()) * progress
;
259 scoped_ptr
<KeyframedTransformAnimationCurve
> KeyframedTransformAnimationCurve::
261 return make_scoped_ptr(new KeyframedTransformAnimationCurve
);
264 KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {}
266 KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {}
268 void KeyframedTransformAnimationCurve::AddKeyframe(
269 scoped_ptr
<TransformKeyframe
> keyframe
) {
270 InsertKeyframe(keyframe
.Pass(), keyframes_
);
273 double KeyframedTransformAnimationCurve::Duration() const {
274 return keyframes_
.back()->Time() - keyframes_
.front()->Time();
277 scoped_ptr
<AnimationCurve
> KeyframedTransformAnimationCurve::Clone() const {
278 scoped_ptr
<KeyframedTransformAnimationCurve
> to_return(
279 KeyframedTransformAnimationCurve::Create());
280 for (size_t i
= 0; i
< keyframes_
.size(); ++i
)
281 to_return
->AddKeyframe(keyframes_
[i
]->Clone());
282 return to_return
.PassAs
<AnimationCurve
>();
285 // Assumes that (*keyframes).front()->Time() < t < (*keyframes).back()-Time().
286 template<typename ValueType
, typename KeyframeType
>
287 static ValueType
GetCurveValue(const ScopedPtrVector
<KeyframeType
>* keyframes
,
290 for (; i
< keyframes
->size() - 1; ++i
) {
291 if (t
< (*keyframes
)[i
+1]->Time())
295 double progress
= (t
- (*keyframes
)[i
]->Time()) /
296 ((*keyframes
)[i
+1]->Time() - (*keyframes
)[i
]->Time());
298 if ((*keyframes
)[i
]->timing_function())
299 progress
= (*keyframes
)[i
]->timing_function()->GetValue(progress
);
301 return (*keyframes
)[i
+1]->Value().Blend((*keyframes
)[i
]->Value(), progress
);
304 gfx::Transform
KeyframedTransformAnimationCurve::GetValue(double t
) const {
305 if (t
<= keyframes_
.front()->Time())
306 return keyframes_
.front()->Value().Apply();
308 if (t
>= keyframes_
.back()->Time())
309 return keyframes_
.back()->Value().Apply();
311 return GetCurveValue
<gfx::Transform
, TransformKeyframe
>(&keyframes_
, t
);
314 bool KeyframedTransformAnimationCurve::AnimatedBoundsForBox(
315 const gfx::BoxF
& box
,
316 gfx::BoxF
* bounds
) const {
317 DCHECK_GE(keyframes_
.size(), 2ul);
318 *bounds
= gfx::BoxF();
319 for (size_t i
= 0; i
< keyframes_
.size() - 1; ++i
) {
320 gfx::BoxF bounds_for_step
;
321 float min_progress
= 0.0;
322 float max_progress
= 1.0;
323 if (keyframes_
[i
]->timing_function())
324 keyframes_
[i
]->timing_function()->Range(&min_progress
, &max_progress
);
325 if (!keyframes_
[i
+1]->Value().BlendedBoundsForBox(box
,
326 keyframes_
[i
]->Value(),
331 bounds
->Union(bounds_for_step
);
336 scoped_ptr
<KeyframedFilterAnimationCurve
> KeyframedFilterAnimationCurve::
338 return make_scoped_ptr(new KeyframedFilterAnimationCurve
);
341 KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {}
343 KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {}
345 void KeyframedFilterAnimationCurve::AddKeyframe(
346 scoped_ptr
<FilterKeyframe
> keyframe
) {
347 InsertKeyframe(keyframe
.Pass(), keyframes_
);
350 double KeyframedFilterAnimationCurve::Duration() const {
351 return keyframes_
.back()->Time() - keyframes_
.front()->Time();
354 scoped_ptr
<AnimationCurve
> KeyframedFilterAnimationCurve::Clone() const {
355 scoped_ptr
<KeyframedFilterAnimationCurve
> to_return(
356 KeyframedFilterAnimationCurve::Create());
357 for (size_t i
= 0; i
< keyframes_
.size(); ++i
)
358 to_return
->AddKeyframe(keyframes_
[i
]->Clone());
359 return to_return
.PassAs
<AnimationCurve
>();
362 FilterOperations
KeyframedFilterAnimationCurve::GetValue(double t
) const {
363 if (t
<= keyframes_
.front()->Time())
364 return keyframes_
.front()->Value();
366 if (t
>= keyframes_
.back()->Time())
367 return keyframes_
.back()->Value();
369 return GetCurveValue
<FilterOperations
, FilterKeyframe
>(&keyframes_
, t
);
372 bool KeyframedFilterAnimationCurve::HasFilterThatMovesPixels() const {
373 for (size_t i
= 0; i
< keyframes_
.size(); ++i
) {
374 if (keyframes_
[i
]->Value().HasFilterThatMovesPixels()) {