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