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
CloneTimingFunction(const TimingFunction * timing_function)43 scoped_ptr<TimingFunction> CloneTimingFunction(
44 const TimingFunction* timing_function) {
45 DCHECK(timing_function);
46 scoped_ptr<AnimationCurve> curve(timing_function->Clone());
47 return scoped_ptr<TimingFunction>(
48 static_cast<TimingFunction*>(curve.release()));
49 }
50
51 } // namespace
52
Keyframe(double time,scoped_ptr<TimingFunction> timing_function)53 Keyframe::Keyframe(double time, scoped_ptr<TimingFunction> timing_function)
54 : time_(time),
55 timing_function_(timing_function.Pass()) {}
56
~Keyframe()57 Keyframe::~Keyframe() {}
58
Time() const59 double Keyframe::Time() const {
60 return time_;
61 }
62
Create(double time,SkColor value,scoped_ptr<TimingFunction> timing_function)63 scoped_ptr<ColorKeyframe> ColorKeyframe::Create(
64 double time,
65 SkColor value,
66 scoped_ptr<TimingFunction> timing_function) {
67 return make_scoped_ptr(
68 new ColorKeyframe(time, value, timing_function.Pass()));
69 }
70
ColorKeyframe(double time,SkColor value,scoped_ptr<TimingFunction> timing_function)71 ColorKeyframe::ColorKeyframe(double time,
72 SkColor value,
73 scoped_ptr<TimingFunction> timing_function)
74 : Keyframe(time, timing_function.Pass()),
75 value_(value) {}
76
~ColorKeyframe()77 ColorKeyframe::~ColorKeyframe() {}
78
Value() const79 SkColor ColorKeyframe::Value() const { return value_; }
80
Clone() const81 scoped_ptr<ColorKeyframe> ColorKeyframe::Clone() const {
82 scoped_ptr<TimingFunction> func;
83 if (timing_function())
84 func = CloneTimingFunction(timing_function());
85 return ColorKeyframe::Create(Time(), Value(), func.Pass());
86 }
87
Create(double time,float value,scoped_ptr<TimingFunction> timing_function)88 scoped_ptr<FloatKeyframe> FloatKeyframe::Create(
89 double time,
90 float value,
91 scoped_ptr<TimingFunction> timing_function) {
92 return make_scoped_ptr(
93 new FloatKeyframe(time, value, timing_function.Pass()));
94 }
95
FloatKeyframe(double time,float value,scoped_ptr<TimingFunction> timing_function)96 FloatKeyframe::FloatKeyframe(double time,
97 float value,
98 scoped_ptr<TimingFunction> timing_function)
99 : Keyframe(time, timing_function.Pass()),
100 value_(value) {}
101
~FloatKeyframe()102 FloatKeyframe::~FloatKeyframe() {}
103
Value() const104 float FloatKeyframe::Value() const {
105 return value_;
106 }
107
Clone() const108 scoped_ptr<FloatKeyframe> FloatKeyframe::Clone() const {
109 scoped_ptr<TimingFunction> func;
110 if (timing_function())
111 func = CloneTimingFunction(timing_function());
112 return FloatKeyframe::Create(Time(), Value(), func.Pass());
113 }
114
Create(double time,const TransformOperations & value,scoped_ptr<TimingFunction> timing_function)115 scoped_ptr<TransformKeyframe> TransformKeyframe::Create(
116 double time,
117 const TransformOperations& value,
118 scoped_ptr<TimingFunction> timing_function) {
119 return make_scoped_ptr(
120 new TransformKeyframe(time, value, timing_function.Pass()));
121 }
122
TransformKeyframe(double time,const TransformOperations & value,scoped_ptr<TimingFunction> timing_function)123 TransformKeyframe::TransformKeyframe(double time,
124 const TransformOperations& value,
125 scoped_ptr<TimingFunction> timing_function)
126 : Keyframe(time, timing_function.Pass()),
127 value_(value) {}
128
~TransformKeyframe()129 TransformKeyframe::~TransformKeyframe() {}
130
Value() const131 const TransformOperations& TransformKeyframe::Value() const {
132 return value_;
133 }
134
Clone() const135 scoped_ptr<TransformKeyframe> TransformKeyframe::Clone() const {
136 scoped_ptr<TimingFunction> func;
137 if (timing_function())
138 func = CloneTimingFunction(timing_function());
139 return TransformKeyframe::Create(Time(), Value(), func.Pass());
140 }
141
Create(double time,const FilterOperations & value,scoped_ptr<TimingFunction> timing_function)142 scoped_ptr<FilterKeyframe> FilterKeyframe::Create(
143 double time,
144 const FilterOperations& value,
145 scoped_ptr<TimingFunction> timing_function) {
146 return make_scoped_ptr(
147 new FilterKeyframe(time, value, timing_function.Pass()));
148 }
149
FilterKeyframe(double time,const FilterOperations & value,scoped_ptr<TimingFunction> timing_function)150 FilterKeyframe::FilterKeyframe(double time,
151 const FilterOperations& value,
152 scoped_ptr<TimingFunction> timing_function)
153 : Keyframe(time, timing_function.Pass()),
154 value_(value) {}
155
~FilterKeyframe()156 FilterKeyframe::~FilterKeyframe() {}
157
Value() const158 const FilterOperations& FilterKeyframe::Value() const {
159 return value_;
160 }
161
Clone() const162 scoped_ptr<FilterKeyframe> FilterKeyframe::Clone() const {
163 scoped_ptr<TimingFunction> func;
164 if (timing_function())
165 func = CloneTimingFunction(timing_function());
166 return FilterKeyframe::Create(Time(), Value(), func.Pass());
167 }
168
169 scoped_ptr<KeyframedColorAnimationCurve> KeyframedColorAnimationCurve::
Create()170 Create() {
171 return make_scoped_ptr(new KeyframedColorAnimationCurve);
172 }
173
KeyframedColorAnimationCurve()174 KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {}
175
~KeyframedColorAnimationCurve()176 KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {}
177
AddKeyframe(scoped_ptr<ColorKeyframe> keyframe)178 void KeyframedColorAnimationCurve::AddKeyframe(
179 scoped_ptr<ColorKeyframe> keyframe) {
180 InsertKeyframe(keyframe.Pass(), keyframes_);
181 }
182
Duration() const183 double KeyframedColorAnimationCurve::Duration() const {
184 return keyframes_.back()->Time() - keyframes_.front()->Time();
185 }
186
Clone() const187 scoped_ptr<AnimationCurve> KeyframedColorAnimationCurve::Clone() const {
188 scoped_ptr<KeyframedColorAnimationCurve> to_return(
189 KeyframedColorAnimationCurve::Create());
190 for (size_t i = 0; i < keyframes_.size(); ++i)
191 to_return->AddKeyframe(keyframes_[i]->Clone());
192 return to_return.PassAs<AnimationCurve>();
193 }
194
GetValue(double t) const195 SkColor KeyframedColorAnimationCurve::GetValue(double t) const {
196 if (t <= keyframes_.front()->Time())
197 return keyframes_.front()->Value();
198
199 if (t >= keyframes_.back()->Time())
200 return keyframes_.back()->Value();
201
202 size_t i = 0;
203 for (; i < keyframes_.size() - 1; ++i) {
204 if (t < keyframes_[i + 1]->Time())
205 break;
206 }
207
208 float progress = GetProgress(t, i, keyframes_);
209
210 return gfx::Tween::ColorValueBetween(
211 progress, keyframes_[i]->Value(), keyframes_[i + 1]->Value());
212 }
213
214 // KeyframedFloatAnimationCurve
215
216 scoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve::
Create()217 Create() {
218 return make_scoped_ptr(new KeyframedFloatAnimationCurve);
219 }
220
KeyframedFloatAnimationCurve()221 KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {}
222
~KeyframedFloatAnimationCurve()223 KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {}
224
AddKeyframe(scoped_ptr<FloatKeyframe> keyframe)225 void KeyframedFloatAnimationCurve::AddKeyframe(
226 scoped_ptr<FloatKeyframe> keyframe) {
227 InsertKeyframe(keyframe.Pass(), keyframes_);
228 }
229
Duration() const230 double KeyframedFloatAnimationCurve::Duration() const {
231 return keyframes_.back()->Time() - keyframes_.front()->Time();
232 }
233
Clone() const234 scoped_ptr<AnimationCurve> KeyframedFloatAnimationCurve::Clone() const {
235 scoped_ptr<KeyframedFloatAnimationCurve> to_return(
236 KeyframedFloatAnimationCurve::Create());
237 for (size_t i = 0; i < keyframes_.size(); ++i)
238 to_return->AddKeyframe(keyframes_[i]->Clone());
239 return to_return.PassAs<AnimationCurve>();
240 }
241
GetValue(double t) const242 float KeyframedFloatAnimationCurve::GetValue(double t) const {
243 if (t <= keyframes_.front()->Time())
244 return keyframes_.front()->Value();
245
246 if (t >= keyframes_.back()->Time())
247 return keyframes_.back()->Value();
248
249 size_t i = 0;
250 for (; i < keyframes_.size() - 1; ++i) {
251 if (t < keyframes_[i+1]->Time())
252 break;
253 }
254
255 float progress = GetProgress(t, i, keyframes_);
256
257 return keyframes_[i]->Value() +
258 (keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress;
259 }
260
261 scoped_ptr<KeyframedTransformAnimationCurve> KeyframedTransformAnimationCurve::
Create()262 Create() {
263 return make_scoped_ptr(new KeyframedTransformAnimationCurve);
264 }
265
KeyframedTransformAnimationCurve()266 KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {}
267
~KeyframedTransformAnimationCurve()268 KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {}
269
AddKeyframe(scoped_ptr<TransformKeyframe> keyframe)270 void KeyframedTransformAnimationCurve::AddKeyframe(
271 scoped_ptr<TransformKeyframe> keyframe) {
272 InsertKeyframe(keyframe.Pass(), keyframes_);
273 }
274
Duration() const275 double KeyframedTransformAnimationCurve::Duration() const {
276 return keyframes_.back()->Time() - keyframes_.front()->Time();
277 }
278
Clone() const279 scoped_ptr<AnimationCurve> KeyframedTransformAnimationCurve::Clone() const {
280 scoped_ptr<KeyframedTransformAnimationCurve> to_return(
281 KeyframedTransformAnimationCurve::Create());
282 for (size_t i = 0; i < keyframes_.size(); ++i)
283 to_return->AddKeyframe(keyframes_[i]->Clone());
284 return to_return.PassAs<AnimationCurve>();
285 }
286
287 // Assumes that (*keyframes).front()->Time() < t < (*keyframes).back()-Time().
288 template<typename ValueType, typename KeyframeType>
GetCurveValue(const ScopedPtrVector<KeyframeType> * keyframes,double t)289 static ValueType GetCurveValue(const ScopedPtrVector<KeyframeType>* keyframes,
290 double t) {
291 size_t i = 0;
292 for (; i < keyframes->size() - 1; ++i) {
293 if (t < (*keyframes)[i+1]->Time())
294 break;
295 }
296
297 double progress = (t - (*keyframes)[i]->Time()) /
298 ((*keyframes)[i+1]->Time() - (*keyframes)[i]->Time());
299
300 if ((*keyframes)[i]->timing_function())
301 progress = (*keyframes)[i]->timing_function()->GetValue(progress);
302
303 return (*keyframes)[i+1]->Value().Blend((*keyframes)[i]->Value(), progress);
304 }
305
GetValue(double t) const306 gfx::Transform KeyframedTransformAnimationCurve::GetValue(double t) const {
307 if (t <= keyframes_.front()->Time())
308 return keyframes_.front()->Value().Apply();
309
310 if (t >= keyframes_.back()->Time())
311 return keyframes_.back()->Value().Apply();
312
313 return GetCurveValue<gfx::Transform, TransformKeyframe>(&keyframes_, t);
314 }
315
AnimatedBoundsForBox(const gfx::BoxF & box,gfx::BoxF * bounds) const316 bool KeyframedTransformAnimationCurve::AnimatedBoundsForBox(
317 const gfx::BoxF& box,
318 gfx::BoxF* bounds) const {
319 DCHECK_GE(keyframes_.size(), 2ul);
320 *bounds = gfx::BoxF();
321 for (size_t i = 0; i < keyframes_.size() - 1; ++i) {
322 gfx::BoxF bounds_for_step;
323 float min_progress = 0.0;
324 float max_progress = 1.0;
325 if (keyframes_[i]->timing_function())
326 keyframes_[i]->timing_function()->Range(&min_progress, &max_progress);
327 if (!keyframes_[i+1]->Value().BlendedBoundsForBox(box,
328 keyframes_[i]->Value(),
329 min_progress,
330 max_progress,
331 &bounds_for_step))
332 return false;
333 bounds->Union(bounds_for_step);
334 }
335 return true;
336 }
337
AffectsScale() const338 bool KeyframedTransformAnimationCurve::AffectsScale() const {
339 for (size_t i = 0; i < keyframes_.size(); ++i) {
340 if (keyframes_[i]->Value().AffectsScale())
341 return true;
342 }
343 return false;
344 }
345
IsTranslation() const346 bool KeyframedTransformAnimationCurve::IsTranslation() const {
347 for (size_t i = 0; i < keyframes_.size(); ++i) {
348 if (!keyframes_[i]->Value().IsTranslation() &&
349 !keyframes_[i]->Value().IsIdentity())
350 return false;
351 }
352 return true;
353 }
354
MaximumScale(float * max_scale) const355 bool KeyframedTransformAnimationCurve::MaximumScale(float* max_scale) const {
356 DCHECK_GE(keyframes_.size(), 2ul);
357 *max_scale = 0.f;
358 for (size_t i = 1; i < keyframes_.size(); ++i) {
359 float min_progress = 0.f;
360 float max_progress = 1.f;
361 if (keyframes_[i - 1]->timing_function())
362 keyframes_[i - 1]->timing_function()->Range(&min_progress, &max_progress);
363
364 float max_scale_for_segment = 0.f;
365 if (!keyframes_[i]->Value().MaximumScale(keyframes_[i - 1]->Value(),
366 min_progress,
367 max_progress,
368 &max_scale_for_segment))
369 return false;
370
371 *max_scale = std::max(*max_scale, max_scale_for_segment);
372 }
373 return true;
374 }
375
376 scoped_ptr<KeyframedFilterAnimationCurve> KeyframedFilterAnimationCurve::
Create()377 Create() {
378 return make_scoped_ptr(new KeyframedFilterAnimationCurve);
379 }
380
KeyframedFilterAnimationCurve()381 KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {}
382
~KeyframedFilterAnimationCurve()383 KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {}
384
AddKeyframe(scoped_ptr<FilterKeyframe> keyframe)385 void KeyframedFilterAnimationCurve::AddKeyframe(
386 scoped_ptr<FilterKeyframe> keyframe) {
387 InsertKeyframe(keyframe.Pass(), keyframes_);
388 }
389
Duration() const390 double KeyframedFilterAnimationCurve::Duration() const {
391 return keyframes_.back()->Time() - keyframes_.front()->Time();
392 }
393
Clone() const394 scoped_ptr<AnimationCurve> KeyframedFilterAnimationCurve::Clone() const {
395 scoped_ptr<KeyframedFilterAnimationCurve> to_return(
396 KeyframedFilterAnimationCurve::Create());
397 for (size_t i = 0; i < keyframes_.size(); ++i)
398 to_return->AddKeyframe(keyframes_[i]->Clone());
399 return to_return.PassAs<AnimationCurve>();
400 }
401
GetValue(double t) const402 FilterOperations KeyframedFilterAnimationCurve::GetValue(double t) const {
403 if (t <= keyframes_.front()->Time())
404 return keyframes_.front()->Value();
405
406 if (t >= keyframes_.back()->Time())
407 return keyframes_.back()->Value();
408
409 return GetCurveValue<FilterOperations, FilterKeyframe>(&keyframes_, t);
410 }
411
HasFilterThatMovesPixels() const412 bool KeyframedFilterAnimationCurve::HasFilterThatMovesPixels() const {
413 for (size_t i = 0; i < keyframes_.size(); ++i) {
414 if (keyframes_[i]->Value().HasFilterThatMovesPixels()) {
415 return true;
416 }
417 }
418 return false;
419 }
420
421 } // namespace cc
422