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 Keyframe>
16 void 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());
29 keyframes.push_back(keyframe.Pass());
32 template <class Keyframes>
33 float GetProgress(double t, size_t i, const Keyframes& keyframes) {
35 static_cast<float>((t - keyframes[i]->Time()) /
36 (keyframes[i + 1]->Time() - keyframes[i]->Time()));
38 if (keyframes[i]->timing_function())
39 progress = keyframes[i]->timing_function()->GetValue(progress);
45 Keyframe::Keyframe(double time, scoped_ptr<TimingFunction> timing_function)
47 timing_function_(timing_function.Pass()) {}
49 Keyframe::~Keyframe() {}
51 double Keyframe::Time() const {
55 scoped_ptr<ColorKeyframe> ColorKeyframe::Create(
58 scoped_ptr<TimingFunction> timing_function) {
59 return make_scoped_ptr(
60 new ColorKeyframe(time, value, timing_function.Pass()));
63 ColorKeyframe::ColorKeyframe(double time,
65 scoped_ptr<TimingFunction> timing_function)
66 : Keyframe(time, timing_function.Pass()),
69 ColorKeyframe::~ColorKeyframe() {}
71 SkColor ColorKeyframe::Value() const { return value_; }
73 scoped_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());
80 scoped_ptr<FloatKeyframe> FloatKeyframe::Create(
83 scoped_ptr<TimingFunction> timing_function) {
84 return make_scoped_ptr(
85 new FloatKeyframe(time, value, timing_function.Pass()));
88 FloatKeyframe::FloatKeyframe(double time,
90 scoped_ptr<TimingFunction> timing_function)
91 : Keyframe(time, timing_function.Pass()),
94 FloatKeyframe::~FloatKeyframe() {}
96 float FloatKeyframe::Value() const {
100 scoped_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());
107 scoped_ptr<TransformKeyframe> TransformKeyframe::Create(
109 const TransformOperations& value,
110 scoped_ptr<TimingFunction> timing_function) {
111 return make_scoped_ptr(
112 new TransformKeyframe(time, value, timing_function.Pass()));
115 TransformKeyframe::TransformKeyframe(double time,
116 const TransformOperations& value,
117 scoped_ptr<TimingFunction> timing_function)
118 : Keyframe(time, timing_function.Pass()),
121 TransformKeyframe::~TransformKeyframe() {}
123 const TransformOperations& TransformKeyframe::Value() const {
127 scoped_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());
134 scoped_ptr<FilterKeyframe> FilterKeyframe::Create(
136 const FilterOperations& value,
137 scoped_ptr<TimingFunction> timing_function) {
138 return make_scoped_ptr(
139 new FilterKeyframe(time, value, timing_function.Pass()));
142 FilterKeyframe::FilterKeyframe(double time,
143 const FilterOperations& value,
144 scoped_ptr<TimingFunction> timing_function)
145 : Keyframe(time, timing_function.Pass()),
148 FilterKeyframe::~FilterKeyframe() {}
150 const FilterOperations& FilterKeyframe::Value() const {
154 scoped_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());
161 scoped_ptr<KeyframedColorAnimationCurve> KeyframedColorAnimationCurve::
163 return make_scoped_ptr(new KeyframedColorAnimationCurve);
166 KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {}
168 KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {}
170 void KeyframedColorAnimationCurve::AddKeyframe(
171 scoped_ptr<ColorKeyframe> keyframe) {
172 InsertKeyframe(keyframe.Pass(), keyframes_);
175 double KeyframedColorAnimationCurve::Duration() const {
176 return keyframes_.back()->Time() - keyframes_.front()->Time();
179 scoped_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>();
187 SkColor KeyframedColorAnimationCurve::GetValue(double t) const {
188 if (t <= keyframes_.front()->Time())
189 return keyframes_.front()->Value();
191 if (t >= keyframes_.back()->Time())
192 return keyframes_.back()->Value();
195 for (; i < keyframes_.size() - 1; ++i) {
196 if (t < keyframes_[i + 1]->Time())
200 float progress = GetProgress(t, i, keyframes_);
202 return gfx::Tween::ColorValueBetween(
203 progress, keyframes_[i]->Value(), keyframes_[i + 1]->Value());
206 // KeyframedFloatAnimationCurve
208 scoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve::
210 return make_scoped_ptr(new KeyframedFloatAnimationCurve);
213 KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {}
215 KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {}
217 void KeyframedFloatAnimationCurve::AddKeyframe(
218 scoped_ptr<FloatKeyframe> keyframe) {
219 InsertKeyframe(keyframe.Pass(), keyframes_);
222 double KeyframedFloatAnimationCurve::Duration() const {
223 return keyframes_.back()->Time() - keyframes_.front()->Time();
226 scoped_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>();
234 float KeyframedFloatAnimationCurve::GetValue(double t) const {
235 if (t <= keyframes_.front()->Time())
236 return keyframes_.front()->Value();
238 if (t >= keyframes_.back()->Time())
239 return keyframes_.back()->Value();
242 for (; i < keyframes_.size() - 1; ++i) {
243 if (t < keyframes_[i+1]->Time())
247 float progress = GetProgress(t, i, keyframes_);
249 return keyframes_[i]->Value() +
250 (keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress;
253 scoped_ptr<KeyframedTransformAnimationCurve> KeyframedTransformAnimationCurve::
255 return make_scoped_ptr(new KeyframedTransformAnimationCurve);
258 KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {}
260 KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {}
262 void KeyframedTransformAnimationCurve::AddKeyframe(
263 scoped_ptr<TransformKeyframe> keyframe) {
264 InsertKeyframe(keyframe.Pass(), keyframes_);
267 double KeyframedTransformAnimationCurve::Duration() const {
268 return keyframes_.back()->Time() - keyframes_.front()->Time();
271 scoped_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>();
279 // Assumes that (*keyframes).front()->Time() < t < (*keyframes).back()-Time().
280 template<typename ValueType, typename KeyframeType>
281 static ValueType GetCurveValue(const ScopedPtrVector<KeyframeType>* keyframes,
284 for (; i < keyframes->size() - 1; ++i) {
285 if (t < (*keyframes)[i+1]->Time())
289 double progress = (t - (*keyframes)[i]->Time()) /
290 ((*keyframes)[i+1]->Time() - (*keyframes)[i]->Time());
292 if ((*keyframes)[i]->timing_function())
293 progress = (*keyframes)[i]->timing_function()->GetValue(progress);
295 return (*keyframes)[i+1]->Value().Blend((*keyframes)[i]->Value(), progress);
298 gfx::Transform KeyframedTransformAnimationCurve::GetValue(double t) const {
299 if (t <= keyframes_.front()->Time())
300 return keyframes_.front()->Value().Apply();
302 if (t >= keyframes_.back()->Time())
303 return keyframes_.back()->Value().Apply();
305 return GetCurveValue<gfx::Transform, TransformKeyframe>(&keyframes_, t);
308 bool 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(),
325 bounds->Union(bounds_for_step);
330 bool KeyframedTransformAnimationCurve::AffectsScale() const {
331 for (size_t i = 0; i < keyframes_.size(); ++i) {
332 if (keyframes_[i]->Value().AffectsScale())
338 bool KeyframedTransformAnimationCurve::IsTranslation() const {
339 for (size_t i = 0; i < keyframes_.size(); ++i) {
340 if (!keyframes_[i]->Value().IsTranslation() &&
341 !keyframes_[i]->Value().IsIdentity())
347 bool KeyframedTransformAnimationCurve::MaximumTargetScale(
348 bool forward_direction,
349 float* max_scale) const {
350 DCHECK_GE(keyframes_.size(), 2ul);
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.
356 size_t end = keyframes_.size();
357 if (!forward_direction) {
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))
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);
375 scoped_ptr<KeyframedFilterAnimationCurve> KeyframedFilterAnimationCurve::
377 return make_scoped_ptr(new KeyframedFilterAnimationCurve);
380 KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {}
382 KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {}
384 void KeyframedFilterAnimationCurve::AddKeyframe(
385 scoped_ptr<FilterKeyframe> keyframe) {
386 InsertKeyframe(keyframe.Pass(), keyframes_);
389 double KeyframedFilterAnimationCurve::Duration() const {
390 return keyframes_.back()->Time() - keyframes_.front()->Time();
393 scoped_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>();
401 FilterOperations KeyframedFilterAnimationCurve::GetValue(double t) const {
402 if (t <= keyframes_.front()->Time())
403 return keyframes_.front()->Value();
405 if (t >= keyframes_.back()->Time())
406 return keyframes_.back()->Value();
408 return GetCurveValue<FilterOperations, FilterKeyframe>(&keyframes_, t);
411 bool KeyframedFilterAnimationCurve::HasFilterThatMovesPixels() const {
412 for (size_t i = 0; i < keyframes_.size(); ++i) {
413 if (keyframes_[i]->Value().HasFilterThatMovesPixels()) {