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.
4
5 #include <algorithm>
6
7 #include "cc/animation/keyframed_animation_curve.h"
8 #include "ui/gfx/animation/tween.h"
9 #include "ui/gfx/box_f.h"
10
11 namespace cc {
12
13 namespace {
14
15 template <class Keyframe>
InsertKeyframe(scoped_ptr<Keyframe> keyframe,ScopedPtrVector<Keyframe> & keyframes)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());
24 return;
25 }
26 }
27 }
28
29 keyframes.push_back(keyframe.Pass());
30 }
31
32 template <class Keyframes>
GetProgress(double t,size_t i,const Keyframes & keyframes)33 float GetProgress(double t, size_t i, const Keyframes& keyframes) {
34 float progress =
35 static_cast<float>((t - keyframes[i]->Time()) /
36 (keyframes[i + 1]->Time() - keyframes[i]->Time()));
37
38 if (keyframes[i]->timing_function())
39 progress = keyframes[i]->timing_function()->GetValue(progress);
40 return progress;
41 }
42
43 } // namespace
44
Keyframe(double time,scoped_ptr<TimingFunction> timing_function)45 Keyframe::Keyframe(double time, scoped_ptr<TimingFunction> timing_function)
46 : time_(time),
47 timing_function_(timing_function.Pass()) {}
48
~Keyframe()49 Keyframe::~Keyframe() {}
50
Time() const51 double Keyframe::Time() const {
52 return time_;
53 }
54
Create(double time,SkColor value,scoped_ptr<TimingFunction> timing_function)55 scoped_ptr<ColorKeyframe> ColorKeyframe::Create(
56 double time,
57 SkColor value,
58 scoped_ptr<TimingFunction> timing_function) {
59 return make_scoped_ptr(
60 new ColorKeyframe(time, value, timing_function.Pass()));
61 }
62
ColorKeyframe(double time,SkColor value,scoped_ptr<TimingFunction> timing_function)63 ColorKeyframe::ColorKeyframe(double time,
64 SkColor value,
65 scoped_ptr<TimingFunction> timing_function)
66 : Keyframe(time, timing_function.Pass()),
67 value_(value) {}
68
~ColorKeyframe()69 ColorKeyframe::~ColorKeyframe() {}
70
Value() const71 SkColor ColorKeyframe::Value() const { return value_; }
72
Clone() const73 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());
78 }
79
Create(double time,float value,scoped_ptr<TimingFunction> timing_function)80 scoped_ptr<FloatKeyframe> FloatKeyframe::Create(
81 double time,
82 float value,
83 scoped_ptr<TimingFunction> timing_function) {
84 return make_scoped_ptr(
85 new FloatKeyframe(time, value, timing_function.Pass()));
86 }
87
FloatKeyframe(double time,float value,scoped_ptr<TimingFunction> timing_function)88 FloatKeyframe::FloatKeyframe(double time,
89 float value,
90 scoped_ptr<TimingFunction> timing_function)
91 : Keyframe(time, timing_function.Pass()),
92 value_(value) {}
93
~FloatKeyframe()94 FloatKeyframe::~FloatKeyframe() {}
95
Value() const96 float FloatKeyframe::Value() const {
97 return value_;
98 }
99
Clone() const100 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());
105 }
106
Create(double time,const TransformOperations & value,scoped_ptr<TimingFunction> timing_function)107 scoped_ptr<TransformKeyframe> TransformKeyframe::Create(
108 double time,
109 const TransformOperations& value,
110 scoped_ptr<TimingFunction> timing_function) {
111 return make_scoped_ptr(
112 new TransformKeyframe(time, value, timing_function.Pass()));
113 }
114
TransformKeyframe(double time,const TransformOperations & value,scoped_ptr<TimingFunction> timing_function)115 TransformKeyframe::TransformKeyframe(double time,
116 const TransformOperations& value,
117 scoped_ptr<TimingFunction> timing_function)
118 : Keyframe(time, timing_function.Pass()),
119 value_(value) {}
120
~TransformKeyframe()121 TransformKeyframe::~TransformKeyframe() {}
122
Value() const123 const TransformOperations& TransformKeyframe::Value() const {
124 return value_;
125 }
126
Clone() const127 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());
132 }
133
Create(double time,const FilterOperations & value,scoped_ptr<TimingFunction> timing_function)134 scoped_ptr<FilterKeyframe> FilterKeyframe::Create(
135 double time,
136 const FilterOperations& value,
137 scoped_ptr<TimingFunction> timing_function) {
138 return make_scoped_ptr(
139 new FilterKeyframe(time, value, timing_function.Pass()));
140 }
141
FilterKeyframe(double time,const FilterOperations & value,scoped_ptr<TimingFunction> timing_function)142 FilterKeyframe::FilterKeyframe(double time,
143 const FilterOperations& value,
144 scoped_ptr<TimingFunction> timing_function)
145 : Keyframe(time, timing_function.Pass()),
146 value_(value) {}
147
~FilterKeyframe()148 FilterKeyframe::~FilterKeyframe() {}
149
Value() const150 const FilterOperations& FilterKeyframe::Value() const {
151 return value_;
152 }
153
Clone() const154 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());
159 }
160
161 scoped_ptr<KeyframedColorAnimationCurve> KeyframedColorAnimationCurve::
Create()162 Create() {
163 return make_scoped_ptr(new KeyframedColorAnimationCurve);
164 }
165
KeyframedColorAnimationCurve()166 KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {}
167
~KeyframedColorAnimationCurve()168 KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {}
169
AddKeyframe(scoped_ptr<ColorKeyframe> keyframe)170 void KeyframedColorAnimationCurve::AddKeyframe(
171 scoped_ptr<ColorKeyframe> keyframe) {
172 InsertKeyframe(keyframe.Pass(), keyframes_);
173 }
174
Duration() const175 double KeyframedColorAnimationCurve::Duration() const {
176 return keyframes_.back()->Time() - keyframes_.front()->Time();
177 }
178
Clone() const179 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>();
185 }
186
GetValue(double t) const187 SkColor KeyframedColorAnimationCurve::GetValue(double t) const {
188 if (t <= keyframes_.front()->Time())
189 return keyframes_.front()->Value();
190
191 if (t >= keyframes_.back()->Time())
192 return keyframes_.back()->Value();
193
194 size_t i = 0;
195 for (; i < keyframes_.size() - 1; ++i) {
196 if (t < keyframes_[i + 1]->Time())
197 break;
198 }
199
200 float progress = GetProgress(t, i, keyframes_);
201
202 return gfx::Tween::ColorValueBetween(
203 progress, keyframes_[i]->Value(), keyframes_[i + 1]->Value());
204 }
205
206 // KeyframedFloatAnimationCurve
207
208 scoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve::
Create()209 Create() {
210 return make_scoped_ptr(new KeyframedFloatAnimationCurve);
211 }
212
KeyframedFloatAnimationCurve()213 KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {}
214
~KeyframedFloatAnimationCurve()215 KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {}
216
AddKeyframe(scoped_ptr<FloatKeyframe> keyframe)217 void KeyframedFloatAnimationCurve::AddKeyframe(
218 scoped_ptr<FloatKeyframe> keyframe) {
219 InsertKeyframe(keyframe.Pass(), keyframes_);
220 }
221
Duration() const222 double KeyframedFloatAnimationCurve::Duration() const {
223 return keyframes_.back()->Time() - keyframes_.front()->Time();
224 }
225
Clone() const226 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>();
232 }
233
GetValue(double t) const234 float KeyframedFloatAnimationCurve::GetValue(double t) const {
235 if (t <= keyframes_.front()->Time())
236 return keyframes_.front()->Value();
237
238 if (t >= keyframes_.back()->Time())
239 return keyframes_.back()->Value();
240
241 size_t i = 0;
242 for (; i < keyframes_.size() - 1; ++i) {
243 if (t < keyframes_[i+1]->Time())
244 break;
245 }
246
247 float progress = GetProgress(t, i, keyframes_);
248
249 return keyframes_[i]->Value() +
250 (keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress;
251 }
252
253 scoped_ptr<KeyframedTransformAnimationCurve> KeyframedTransformAnimationCurve::
Create()254 Create() {
255 return make_scoped_ptr(new KeyframedTransformAnimationCurve);
256 }
257
KeyframedTransformAnimationCurve()258 KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {}
259
~KeyframedTransformAnimationCurve()260 KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {}
261
AddKeyframe(scoped_ptr<TransformKeyframe> keyframe)262 void KeyframedTransformAnimationCurve::AddKeyframe(
263 scoped_ptr<TransformKeyframe> keyframe) {
264 InsertKeyframe(keyframe.Pass(), keyframes_);
265 }
266
Duration() const267 double KeyframedTransformAnimationCurve::Duration() const {
268 return keyframes_.back()->Time() - keyframes_.front()->Time();
269 }
270
Clone() const271 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>();
277 }
278
279 // Assumes that (*keyframes).front()->Time() < t < (*keyframes).back()-Time().
280 template<typename ValueType, typename KeyframeType>
GetCurveValue(const ScopedPtrVector<KeyframeType> * keyframes,double t)281 static ValueType GetCurveValue(const ScopedPtrVector<KeyframeType>* keyframes,
282 double t) {
283 size_t i = 0;
284 for (; i < keyframes->size() - 1; ++i) {
285 if (t < (*keyframes)[i+1]->Time())
286 break;
287 }
288
289 double progress = (t - (*keyframes)[i]->Time()) /
290 ((*keyframes)[i+1]->Time() - (*keyframes)[i]->Time());
291
292 if ((*keyframes)[i]->timing_function())
293 progress = (*keyframes)[i]->timing_function()->GetValue(progress);
294
295 return (*keyframes)[i+1]->Value().Blend((*keyframes)[i]->Value(), progress);
296 }
297
GetValue(double t) const298 gfx::Transform KeyframedTransformAnimationCurve::GetValue(double t) const {
299 if (t <= keyframes_.front()->Time())
300 return keyframes_.front()->Value().Apply();
301
302 if (t >= keyframes_.back()->Time())
303 return keyframes_.back()->Value().Apply();
304
305 return GetCurveValue<gfx::Transform, TransformKeyframe>(&keyframes_, t);
306 }
307
AnimatedBoundsForBox(const gfx::BoxF & box,gfx::BoxF * bounds) const308 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(),
321 min_progress,
322 max_progress,
323 &bounds_for_step))
324 return false;
325 bounds->Union(bounds_for_step);
326 }
327 return true;
328 }
329
AffectsScale() const330 bool KeyframedTransformAnimationCurve::AffectsScale() const {
331 for (size_t i = 0; i < keyframes_.size(); ++i) {
332 if (keyframes_[i]->Value().AffectsScale())
333 return true;
334 }
335 return false;
336 }
337
IsTranslation() const338 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())
342 return false;
343 }
344 return true;
345 }
346
MaximumTargetScale(bool forward_direction,float * max_scale) const347 bool KeyframedTransformAnimationCurve::MaximumTargetScale(
348 bool forward_direction,
349 float* max_scale) const {
350 DCHECK_GE(keyframes_.size(), 2ul);
351 *max_scale = 0.f;
352
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.
355 size_t start = 1;
356 size_t end = keyframes_.size();
357 if (!forward_direction) {
358 --start;
359 --end;
360 }
361
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))
365 return false;
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);
371 }
372 return true;
373 }
374
375 scoped_ptr<KeyframedFilterAnimationCurve> KeyframedFilterAnimationCurve::
Create()376 Create() {
377 return make_scoped_ptr(new KeyframedFilterAnimationCurve);
378 }
379
KeyframedFilterAnimationCurve()380 KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {}
381
~KeyframedFilterAnimationCurve()382 KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {}
383
AddKeyframe(scoped_ptr<FilterKeyframe> keyframe)384 void KeyframedFilterAnimationCurve::AddKeyframe(
385 scoped_ptr<FilterKeyframe> keyframe) {
386 InsertKeyframe(keyframe.Pass(), keyframes_);
387 }
388
Duration() const389 double KeyframedFilterAnimationCurve::Duration() const {
390 return keyframes_.back()->Time() - keyframes_.front()->Time();
391 }
392
Clone() const393 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>();
399 }
400
GetValue(double t) const401 FilterOperations KeyframedFilterAnimationCurve::GetValue(double t) const {
402 if (t <= keyframes_.front()->Time())
403 return keyframes_.front()->Value();
404
405 if (t >= keyframes_.back()->Time())
406 return keyframes_.back()->Value();
407
408 return GetCurveValue<FilterOperations, FilterKeyframe>(&keyframes_, t);
409 }
410
HasFilterThatMovesPixels() const411 bool KeyframedFilterAnimationCurve::HasFilterThatMovesPixels() const {
412 for (size_t i = 0; i < keyframes_.size(); ++i) {
413 if (keyframes_[i]->Value().HasFilterThatMovesPixels()) {
414 return true;
415 }
416 }
417 return false;
418 }
419
420 } // namespace cc
421