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 "cc/animation/keyframed_animation_curve.h"
6
7 #include <stddef.h>
8
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12
13 #include "base/memory/ptr_util.h"
14 #include "ui/gfx/animation/tween.h"
15 #include "ui/gfx/geometry/box_f.h"
16
17 namespace cc {
18
19 namespace {
20
21 template <class KeyframeType>
InsertKeyframe(std::unique_ptr<KeyframeType> keyframe,std::vector<std::unique_ptr<KeyframeType>> * keyframes)22 void InsertKeyframe(std::unique_ptr<KeyframeType> keyframe,
23 std::vector<std::unique_ptr<KeyframeType>>* keyframes) {
24 // Usually, the keyframes will be added in order, so this loop would be
25 // unnecessary and we should skip it if possible.
26 if (!keyframes->empty() && keyframe->Time() < keyframes->back()->Time()) {
27 for (size_t i = 0; i < keyframes->size(); ++i) {
28 if (keyframe->Time() < keyframes->at(i)->Time()) {
29 keyframes->insert(keyframes->begin() + i, std::move(keyframe));
30 return;
31 }
32 }
33 }
34
35 keyframes->push_back(std::move(keyframe));
36 }
37
38 template <typename KeyframeType>
TransformedAnimationTime(const std::vector<std::unique_ptr<KeyframeType>> & keyframes,const std::unique_ptr<TimingFunction> & timing_function,double scaled_duration,base::TimeDelta time)39 base::TimeDelta TransformedAnimationTime(
40 const std::vector<std::unique_ptr<KeyframeType>>& keyframes,
41 const std::unique_ptr<TimingFunction>& timing_function,
42 double scaled_duration,
43 base::TimeDelta time) {
44 if (timing_function) {
45 base::TimeDelta start_time = keyframes.front()->Time() * scaled_duration;
46 base::TimeDelta duration =
47 (keyframes.back()->Time() - keyframes.front()->Time()) *
48 scaled_duration;
49 const double progress =
50 duration.is_zero() ? 1.0 : ((time - start_time) / duration);
51
52 time = (duration * timing_function->GetValue(progress)) + start_time;
53 }
54
55 return time;
56 }
57
58 template <typename KeyframeType>
GetActiveKeyframe(const std::vector<std::unique_ptr<KeyframeType>> & keyframes,double scaled_duration,base::TimeDelta time)59 size_t GetActiveKeyframe(
60 const std::vector<std::unique_ptr<KeyframeType>>& keyframes,
61 double scaled_duration,
62 base::TimeDelta time) {
63 DCHECK_GE(keyframes.size(), 2ul);
64 size_t i = 0;
65 while ((i < keyframes.size() - 2) && // Last keyframe is never active.
66 (time >= (keyframes[i + 1]->Time() * scaled_duration)))
67 ++i;
68
69 return i;
70 }
71
72 template <typename KeyframeType>
TransformedKeyframeProgress(const std::vector<std::unique_ptr<KeyframeType>> & keyframes,double scaled_duration,base::TimeDelta time,size_t i)73 double TransformedKeyframeProgress(
74 const std::vector<std::unique_ptr<KeyframeType>>& keyframes,
75 double scaled_duration,
76 base::TimeDelta time,
77 size_t i) {
78 const base::TimeDelta start_time = keyframes[i]->Time() * scaled_duration;
79 const base::TimeDelta duration =
80 keyframes[i + 1]->Time() * scaled_duration - start_time;
81 const double progress =
82 duration.is_zero() ? 1.0 : ((time - start_time) / duration);
83
84 return keyframes[i]->timing_function()
85 ? keyframes[i]->timing_function()->GetValue(progress)
86 : progress;
87 }
88
89 } // namespace
90
Keyframe(base::TimeDelta time,std::unique_ptr<TimingFunction> timing_function)91 Keyframe::Keyframe(base::TimeDelta time,
92 std::unique_ptr<TimingFunction> timing_function)
93 : time_(time), timing_function_(std::move(timing_function)) {}
94
95 Keyframe::~Keyframe() = default;
96
Time() const97 base::TimeDelta Keyframe::Time() const {
98 return time_;
99 }
100
Create(base::TimeDelta time,SkColor value,std::unique_ptr<TimingFunction> timing_function)101 std::unique_ptr<ColorKeyframe> ColorKeyframe::Create(
102 base::TimeDelta time,
103 SkColor value,
104 std::unique_ptr<TimingFunction> timing_function) {
105 return base::WrapUnique(
106 new ColorKeyframe(time, value, std::move(timing_function)));
107 }
108
ColorKeyframe(base::TimeDelta time,SkColor value,std::unique_ptr<TimingFunction> timing_function)109 ColorKeyframe::ColorKeyframe(base::TimeDelta time,
110 SkColor value,
111 std::unique_ptr<TimingFunction> timing_function)
112 : Keyframe(time, std::move(timing_function)), value_(value) {}
113
114 ColorKeyframe::~ColorKeyframe() = default;
115
Value() const116 SkColor ColorKeyframe::Value() const { return value_; }
117
Clone() const118 std::unique_ptr<ColorKeyframe> ColorKeyframe::Clone() const {
119 std::unique_ptr<TimingFunction> func;
120 if (timing_function())
121 func = timing_function()->Clone();
122 return ColorKeyframe::Create(Time(), Value(), std::move(func));
123 }
124
Create(base::TimeDelta time,float value,std::unique_ptr<TimingFunction> timing_function)125 std::unique_ptr<FloatKeyframe> FloatKeyframe::Create(
126 base::TimeDelta time,
127 float value,
128 std::unique_ptr<TimingFunction> timing_function) {
129 return base::WrapUnique(
130 new FloatKeyframe(time, value, std::move(timing_function)));
131 }
132
FloatKeyframe(base::TimeDelta time,float value,std::unique_ptr<TimingFunction> timing_function)133 FloatKeyframe::FloatKeyframe(base::TimeDelta time,
134 float value,
135 std::unique_ptr<TimingFunction> timing_function)
136 : Keyframe(time, std::move(timing_function)), value_(value) {}
137
138 FloatKeyframe::~FloatKeyframe() = default;
139
Value() const140 float FloatKeyframe::Value() const {
141 return value_;
142 }
143
Clone() const144 std::unique_ptr<FloatKeyframe> FloatKeyframe::Clone() const {
145 std::unique_ptr<TimingFunction> func;
146 if (timing_function())
147 func = timing_function()->Clone();
148 return FloatKeyframe::Create(Time(), Value(), std::move(func));
149 }
150
Create(base::TimeDelta time,const TransformOperations & value,std::unique_ptr<TimingFunction> timing_function)151 std::unique_ptr<TransformKeyframe> TransformKeyframe::Create(
152 base::TimeDelta time,
153 const TransformOperations& value,
154 std::unique_ptr<TimingFunction> timing_function) {
155 return base::WrapUnique(
156 new TransformKeyframe(time, value, std::move(timing_function)));
157 }
158
TransformKeyframe(base::TimeDelta time,const TransformOperations & value,std::unique_ptr<TimingFunction> timing_function)159 TransformKeyframe::TransformKeyframe(
160 base::TimeDelta time,
161 const TransformOperations& value,
162 std::unique_ptr<TimingFunction> timing_function)
163 : Keyframe(time, std::move(timing_function)), value_(value) {}
164
165 TransformKeyframe::~TransformKeyframe() = default;
166
Value() const167 const TransformOperations& TransformKeyframe::Value() const {
168 return value_;
169 }
170
Clone() const171 std::unique_ptr<TransformKeyframe> TransformKeyframe::Clone() const {
172 std::unique_ptr<TimingFunction> func;
173 if (timing_function())
174 func = timing_function()->Clone();
175 return TransformKeyframe::Create(Time(), Value(), std::move(func));
176 }
177
Create(base::TimeDelta time,const FilterOperations & value,std::unique_ptr<TimingFunction> timing_function)178 std::unique_ptr<FilterKeyframe> FilterKeyframe::Create(
179 base::TimeDelta time,
180 const FilterOperations& value,
181 std::unique_ptr<TimingFunction> timing_function) {
182 return base::WrapUnique(
183 new FilterKeyframe(time, value, std::move(timing_function)));
184 }
185
FilterKeyframe(base::TimeDelta time,const FilterOperations & value,std::unique_ptr<TimingFunction> timing_function)186 FilterKeyframe::FilterKeyframe(base::TimeDelta time,
187 const FilterOperations& value,
188 std::unique_ptr<TimingFunction> timing_function)
189 : Keyframe(time, std::move(timing_function)), value_(value) {}
190
191 FilterKeyframe::~FilterKeyframe() = default;
192
Value() const193 const FilterOperations& FilterKeyframe::Value() const {
194 return value_;
195 }
196
Clone() const197 std::unique_ptr<FilterKeyframe> FilterKeyframe::Clone() const {
198 std::unique_ptr<TimingFunction> func;
199 if (timing_function())
200 func = timing_function()->Clone();
201 return FilterKeyframe::Create(Time(), Value(), std::move(func));
202 }
203
Create(base::TimeDelta time,const gfx::SizeF & value,std::unique_ptr<TimingFunction> timing_function)204 std::unique_ptr<SizeKeyframe> SizeKeyframe::Create(
205 base::TimeDelta time,
206 const gfx::SizeF& value,
207 std::unique_ptr<TimingFunction> timing_function) {
208 return base::WrapUnique(
209 new SizeKeyframe(time, value, std::move(timing_function)));
210 }
211
SizeKeyframe(base::TimeDelta time,const gfx::SizeF & value,std::unique_ptr<TimingFunction> timing_function)212 SizeKeyframe::SizeKeyframe(base::TimeDelta time,
213 const gfx::SizeF& value,
214 std::unique_ptr<TimingFunction> timing_function)
215 : Keyframe(time, std::move(timing_function)), value_(value) {}
216
217 SizeKeyframe::~SizeKeyframe() = default;
218
Value() const219 const gfx::SizeF& SizeKeyframe::Value() const {
220 return value_;
221 }
222
Clone() const223 std::unique_ptr<SizeKeyframe> SizeKeyframe::Clone() const {
224 std::unique_ptr<TimingFunction> func;
225 if (timing_function())
226 func = timing_function()->Clone();
227 return SizeKeyframe::Create(Time(), Value(), std::move(func));
228 }
229
230 std::unique_ptr<KeyframedColorAnimationCurve>
Create()231 KeyframedColorAnimationCurve::Create() {
232 return base::WrapUnique(new KeyframedColorAnimationCurve);
233 }
234
KeyframedColorAnimationCurve()235 KeyframedColorAnimationCurve::KeyframedColorAnimationCurve()
236 : scaled_duration_(1.0) {}
237
238 KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() = default;
239
AddKeyframe(std::unique_ptr<ColorKeyframe> keyframe)240 void KeyframedColorAnimationCurve::AddKeyframe(
241 std::unique_ptr<ColorKeyframe> keyframe) {
242 InsertKeyframe(std::move(keyframe), &keyframes_);
243 }
244
Duration() const245 base::TimeDelta KeyframedColorAnimationCurve::Duration() const {
246 return (keyframes_.back()->Time() - keyframes_.front()->Time()) *
247 scaled_duration();
248 }
249
Clone() const250 std::unique_ptr<AnimationCurve> KeyframedColorAnimationCurve::Clone() const {
251 std::unique_ptr<KeyframedColorAnimationCurve> to_return =
252 KeyframedColorAnimationCurve::Create();
253 for (const auto& keyframe : keyframes_)
254 to_return->AddKeyframe(keyframe->Clone());
255
256 if (timing_function_)
257 to_return->SetTimingFunction(timing_function_->Clone());
258
259 to_return->set_scaled_duration(scaled_duration());
260
261 return std::move(to_return);
262 }
263
GetValue(base::TimeDelta t) const264 SkColor KeyframedColorAnimationCurve::GetValue(base::TimeDelta t) const {
265 if (t <= (keyframes_.front()->Time() * scaled_duration()))
266 return keyframes_.front()->Value();
267
268 if (t >= (keyframes_.back()->Time() * scaled_duration()))
269 return keyframes_.back()->Value();
270
271 t = TransformedAnimationTime(keyframes_, timing_function_, scaled_duration(),
272 t);
273 size_t i = GetActiveKeyframe(keyframes_, scaled_duration(), t);
274 double progress =
275 TransformedKeyframeProgress(keyframes_, scaled_duration(), t, i);
276
277 return gfx::Tween::ColorValueBetween(
278 progress, keyframes_[i]->Value(), keyframes_[i + 1]->Value());
279 }
280
281 std::unique_ptr<KeyframedFloatAnimationCurve>
Create()282 KeyframedFloatAnimationCurve::Create() {
283 return base::WrapUnique(new KeyframedFloatAnimationCurve);
284 }
285
KeyframedFloatAnimationCurve()286 KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve()
287 : scaled_duration_(1.0) {}
288
289 KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() = default;
290
AddKeyframe(std::unique_ptr<FloatKeyframe> keyframe)291 void KeyframedFloatAnimationCurve::AddKeyframe(
292 std::unique_ptr<FloatKeyframe> keyframe) {
293 InsertKeyframe(std::move(keyframe), &keyframes_);
294 }
295
Duration() const296 base::TimeDelta KeyframedFloatAnimationCurve::Duration() const {
297 return (keyframes_.back()->Time() - keyframes_.front()->Time()) *
298 scaled_duration();
299 }
300
Clone() const301 std::unique_ptr<AnimationCurve> KeyframedFloatAnimationCurve::Clone() const {
302 std::unique_ptr<KeyframedFloatAnimationCurve> to_return =
303 KeyframedFloatAnimationCurve::Create();
304 for (const auto& keyframe : keyframes_)
305 to_return->AddKeyframe(keyframe->Clone());
306
307 if (timing_function_)
308 to_return->SetTimingFunction(timing_function_->Clone());
309
310 to_return->set_scaled_duration(scaled_duration());
311
312 return std::move(to_return);
313 }
314
GetValue(base::TimeDelta t) const315 float KeyframedFloatAnimationCurve::GetValue(base::TimeDelta t) const {
316 if (t <= (keyframes_.front()->Time() * scaled_duration()))
317 return keyframes_.front()->Value();
318
319 if (t >= (keyframes_.back()->Time() * scaled_duration()))
320 return keyframes_.back()->Value();
321
322 t = TransformedAnimationTime(keyframes_, timing_function_, scaled_duration(),
323 t);
324 size_t i = GetActiveKeyframe(keyframes_, scaled_duration(), t);
325 double progress =
326 TransformedKeyframeProgress(keyframes_, scaled_duration(), t, i);
327
328 return keyframes_[i]->Value() +
329 (keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress;
330 }
331
332 std::unique_ptr<KeyframedTransformAnimationCurve>
Create()333 KeyframedTransformAnimationCurve::Create() {
334 return base::WrapUnique(new KeyframedTransformAnimationCurve);
335 }
336
KeyframedTransformAnimationCurve()337 KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve()
338 : scaled_duration_(1.0) {}
339
340 KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() = default;
341
AddKeyframe(std::unique_ptr<TransformKeyframe> keyframe)342 void KeyframedTransformAnimationCurve::AddKeyframe(
343 std::unique_ptr<TransformKeyframe> keyframe) {
344 InsertKeyframe(std::move(keyframe), &keyframes_);
345 }
346
Duration() const347 base::TimeDelta KeyframedTransformAnimationCurve::Duration() const {
348 return (keyframes_.back()->Time() - keyframes_.front()->Time()) *
349 scaled_duration();
350 }
351
Clone() const352 std::unique_ptr<AnimationCurve> KeyframedTransformAnimationCurve::Clone()
353 const {
354 std::unique_ptr<KeyframedTransformAnimationCurve> to_return =
355 KeyframedTransformAnimationCurve::Create();
356 for (const auto& keyframe : keyframes_)
357 to_return->AddKeyframe(keyframe->Clone());
358
359 if (timing_function_)
360 to_return->SetTimingFunction(timing_function_->Clone());
361
362 to_return->set_scaled_duration(scaled_duration());
363
364 return std::move(to_return);
365 }
366
GetValue(base::TimeDelta t) const367 TransformOperations KeyframedTransformAnimationCurve::GetValue(
368 base::TimeDelta t) const {
369 if (t <= (keyframes_.front()->Time() * scaled_duration()))
370 return keyframes_.front()->Value();
371
372 if (t >= (keyframes_.back()->Time() * scaled_duration()))
373 return keyframes_.back()->Value();
374
375 t = TransformedAnimationTime(keyframes_, timing_function_, scaled_duration(),
376 t);
377 size_t i = GetActiveKeyframe(keyframes_, scaled_duration(), t);
378 double progress =
379 TransformedKeyframeProgress(keyframes_, scaled_duration(), t, i);
380
381 return keyframes_[i + 1]->Value().Blend(keyframes_[i]->Value(), progress);
382 }
383
PreservesAxisAlignment() const384 bool KeyframedTransformAnimationCurve::PreservesAxisAlignment() const {
385 for (const auto& keyframe : keyframes_) {
386 if (!keyframe->Value().PreservesAxisAlignment())
387 return false;
388 }
389 return true;
390 }
391
IsTranslation() const392 bool KeyframedTransformAnimationCurve::IsTranslation() const {
393 for (const auto& keyframe : keyframes_) {
394 if (!keyframe->Value().IsTranslation() && !keyframe->Value().IsIdentity())
395 return false;
396 }
397 return true;
398 }
399
AnimationStartScale(bool forward_direction,float * start_scale) const400 bool KeyframedTransformAnimationCurve::AnimationStartScale(
401 bool forward_direction,
402 float* start_scale) const {
403 DCHECK_GE(keyframes_.size(), 2ul);
404 *start_scale = 0.f;
405 size_t start_location = 0;
406 if (!forward_direction) {
407 start_location = keyframes_.size() - 1;
408 }
409
410 return keyframes_[start_location]->Value().ScaleComponent(start_scale);
411 }
412
MaximumTargetScale(bool forward_direction,float * max_scale) const413 bool KeyframedTransformAnimationCurve::MaximumTargetScale(
414 bool forward_direction,
415 float* max_scale) const {
416 DCHECK_GE(keyframes_.size(), 2ul);
417 *max_scale = 0.f;
418
419 // If |forward_direction| is true, then skip the first frame, otherwise
420 // skip the last frame, since that is the original position in the animation.
421 size_t start = 1;
422 size_t end = keyframes_.size();
423 if (!forward_direction) {
424 --start;
425 --end;
426 }
427
428 for (size_t i = start; i < end; ++i) {
429 float target_scale_for_segment = 0.f;
430 if (!keyframes_[i]->Value().ScaleComponent(&target_scale_for_segment))
431 return false;
432 *max_scale = fmax(*max_scale, target_scale_for_segment);
433 }
434 return true;
435 }
436
437 std::unique_ptr<KeyframedFilterAnimationCurve>
Create()438 KeyframedFilterAnimationCurve::Create() {
439 return base::WrapUnique(new KeyframedFilterAnimationCurve);
440 }
441
KeyframedFilterAnimationCurve()442 KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve()
443 : scaled_duration_(1.0) {}
444
445 KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() = default;
446
AddKeyframe(std::unique_ptr<FilterKeyframe> keyframe)447 void KeyframedFilterAnimationCurve::AddKeyframe(
448 std::unique_ptr<FilterKeyframe> keyframe) {
449 InsertKeyframe(std::move(keyframe), &keyframes_);
450 }
451
Duration() const452 base::TimeDelta KeyframedFilterAnimationCurve::Duration() const {
453 return (keyframes_.back()->Time() - keyframes_.front()->Time()) *
454 scaled_duration();
455 }
456
Clone() const457 std::unique_ptr<AnimationCurve> KeyframedFilterAnimationCurve::Clone() const {
458 std::unique_ptr<KeyframedFilterAnimationCurve> to_return =
459 KeyframedFilterAnimationCurve::Create();
460 for (const auto& keyframe : keyframes_)
461 to_return->AddKeyframe(keyframe->Clone());
462
463 if (timing_function_)
464 to_return->SetTimingFunction(timing_function_->Clone());
465
466 to_return->set_scaled_duration(scaled_duration());
467
468 return std::move(to_return);
469 }
470
GetValue(base::TimeDelta t) const471 FilterOperations KeyframedFilterAnimationCurve::GetValue(
472 base::TimeDelta t) const {
473 if (t <= (keyframes_.front()->Time() * scaled_duration()))
474 return keyframes_.front()->Value();
475
476 if (t >= (keyframes_.back()->Time() * scaled_duration()))
477 return keyframes_.back()->Value();
478
479 t = TransformedAnimationTime(keyframes_, timing_function_, scaled_duration(),
480 t);
481 size_t i = GetActiveKeyframe(keyframes_, scaled_duration(), t);
482 double progress =
483 TransformedKeyframeProgress(keyframes_, scaled_duration(), t, i);
484
485 return keyframes_[i + 1]->Value().Blend(keyframes_[i]->Value(), progress);
486 }
487
HasFilterThatMovesPixels() const488 bool KeyframedFilterAnimationCurve::HasFilterThatMovesPixels() const {
489 for (const auto& keyframe : keyframes_) {
490 if (keyframe->Value().HasFilterThatMovesPixels()) {
491 return true;
492 }
493 }
494 return false;
495 }
496
497 std::unique_ptr<KeyframedSizeAnimationCurve>
Create()498 KeyframedSizeAnimationCurve::Create() {
499 return base::WrapUnique(new KeyframedSizeAnimationCurve);
500 }
501
KeyframedSizeAnimationCurve()502 KeyframedSizeAnimationCurve::KeyframedSizeAnimationCurve()
503 : scaled_duration_(1.0) {}
504
505 KeyframedSizeAnimationCurve::~KeyframedSizeAnimationCurve() = default;
506
AddKeyframe(std::unique_ptr<SizeKeyframe> keyframe)507 void KeyframedSizeAnimationCurve::AddKeyframe(
508 std::unique_ptr<SizeKeyframe> keyframe) {
509 InsertKeyframe(std::move(keyframe), &keyframes_);
510 }
511
Duration() const512 base::TimeDelta KeyframedSizeAnimationCurve::Duration() const {
513 return (keyframes_.back()->Time() - keyframes_.front()->Time()) *
514 scaled_duration();
515 }
516
Clone() const517 std::unique_ptr<AnimationCurve> KeyframedSizeAnimationCurve::Clone() const {
518 std::unique_ptr<KeyframedSizeAnimationCurve> to_return =
519 KeyframedSizeAnimationCurve::Create();
520 for (const auto& keyframe : keyframes_)
521 to_return->AddKeyframe(keyframe->Clone());
522
523 if (timing_function_)
524 to_return->SetTimingFunction(timing_function_->Clone());
525
526 to_return->set_scaled_duration(scaled_duration());
527
528 return std::move(to_return);
529 }
530
GetValue(base::TimeDelta t) const531 gfx::SizeF KeyframedSizeAnimationCurve::GetValue(base::TimeDelta t) const {
532 if (t <= (keyframes_.front()->Time() * scaled_duration()))
533 return keyframes_.front()->Value();
534
535 if (t >= (keyframes_.back()->Time() * scaled_duration()))
536 return keyframes_.back()->Value();
537
538 t = TransformedAnimationTime(keyframes_, timing_function_, scaled_duration(),
539 t);
540 size_t i = GetActiveKeyframe(keyframes_, scaled_duration(), t);
541 double progress =
542 TransformedKeyframeProgress(keyframes_, scaled_duration(), t, i);
543
544 return gfx::Tween::SizeFValueBetween(progress, keyframes_[i]->Value(),
545 keyframes_[i + 1]->Value());
546 }
547
548 } // namespace cc
549