OLD | NEW |
| (Empty) |
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 "cc/base/time_util.h" | |
9 #include "ui/gfx/animation/tween.h" | |
10 #include "ui/gfx/geometry/box_f.h" | |
11 | |
12 namespace cc { | |
13 | |
14 namespace { | |
15 | |
16 template <class KeyframeType> | |
17 void InsertKeyframe(scoped_ptr<KeyframeType> keyframe, | |
18 ScopedPtrVector<KeyframeType>* keyframes) { | |
19 // Usually, the keyframes will be added in order, so this loop would be | |
20 // unnecessary and we should skip it if possible. | |
21 if (!keyframes->empty() && keyframe->Time() < keyframes->back()->Time()) { | |
22 for (size_t i = 0; i < keyframes->size(); ++i) { | |
23 if (keyframe->Time() < keyframes->at(i)->Time()) { | |
24 keyframes->insert(keyframes->begin() + i, keyframe.Pass()); | |
25 return; | |
26 } | |
27 } | |
28 } | |
29 | |
30 keyframes->push_back(keyframe.Pass()); | |
31 } | |
32 | |
33 template <typename KeyframeType> | |
34 base::TimeDelta TransformedAnimationTime( | |
35 const ScopedPtrVector<KeyframeType>& keyframes, | |
36 const scoped_ptr<TimingFunction>& timing_function, | |
37 base::TimeDelta time) { | |
38 if (timing_function) { | |
39 base::TimeDelta start_time = keyframes.front()->Time(); | |
40 base::TimeDelta duration = | |
41 keyframes.back()->Time() - keyframes.front()->Time(); | |
42 double progress = TimeUtil::Divide(time - start_time, duration); | |
43 | |
44 time = TimeUtil::Scale(duration, timing_function->GetValue(progress)) + | |
45 start_time; | |
46 } | |
47 | |
48 return time; | |
49 } | |
50 | |
51 template <typename KeyframeType> | |
52 size_t GetActiveKeyframe(const ScopedPtrVector<KeyframeType>& keyframes, | |
53 base::TimeDelta time) { | |
54 DCHECK_GE(keyframes.size(), 2ul); | |
55 size_t i = 0; | |
56 for (; i < keyframes.size() - 2; ++i) { // Last keyframe is never active. | |
57 if (time < keyframes[i + 1]->Time()) | |
58 break; | |
59 } | |
60 | |
61 return i; | |
62 } | |
63 | |
64 template <typename KeyframeType> | |
65 double TransformedKeyframeProgress( | |
66 const ScopedPtrVector<KeyframeType>& keyframes, | |
67 base::TimeDelta time, | |
68 size_t i) { | |
69 double progress = | |
70 TimeUtil::Divide(time - keyframes[i]->Time(), | |
71 keyframes[i + 1]->Time() - keyframes[i]->Time()); | |
72 | |
73 if (keyframes[i]->timing_function()) { | |
74 progress = keyframes[i]->timing_function()->GetValue(progress); | |
75 } | |
76 | |
77 return progress; | |
78 } | |
79 | |
80 } // namespace | |
81 | |
82 Keyframe::Keyframe(base::TimeDelta time, | |
83 scoped_ptr<TimingFunction> timing_function) | |
84 : time_(time), timing_function_(timing_function.Pass()) { | |
85 } | |
86 | |
87 Keyframe::~Keyframe() {} | |
88 | |
89 base::TimeDelta Keyframe::Time() const { | |
90 return time_; | |
91 } | |
92 | |
93 scoped_ptr<ColorKeyframe> ColorKeyframe::Create( | |
94 base::TimeDelta time, | |
95 SkColor value, | |
96 scoped_ptr<TimingFunction> timing_function) { | |
97 return make_scoped_ptr( | |
98 new ColorKeyframe(time, value, timing_function.Pass())); | |
99 } | |
100 | |
101 ColorKeyframe::ColorKeyframe(base::TimeDelta time, | |
102 SkColor value, | |
103 scoped_ptr<TimingFunction> timing_function) | |
104 : Keyframe(time, timing_function.Pass()), value_(value) { | |
105 } | |
106 | |
107 ColorKeyframe::~ColorKeyframe() {} | |
108 | |
109 SkColor ColorKeyframe::Value() const { return value_; } | |
110 | |
111 scoped_ptr<ColorKeyframe> ColorKeyframe::Clone() const { | |
112 scoped_ptr<TimingFunction> func; | |
113 if (timing_function()) | |
114 func = timing_function()->Clone(); | |
115 return ColorKeyframe::Create(Time(), Value(), func.Pass()); | |
116 } | |
117 | |
118 scoped_ptr<FloatKeyframe> FloatKeyframe::Create( | |
119 base::TimeDelta time, | |
120 float value, | |
121 scoped_ptr<TimingFunction> timing_function) { | |
122 return make_scoped_ptr( | |
123 new FloatKeyframe(time, value, timing_function.Pass())); | |
124 } | |
125 | |
126 FloatKeyframe::FloatKeyframe(base::TimeDelta time, | |
127 float value, | |
128 scoped_ptr<TimingFunction> timing_function) | |
129 : Keyframe(time, timing_function.Pass()), value_(value) { | |
130 } | |
131 | |
132 FloatKeyframe::~FloatKeyframe() {} | |
133 | |
134 float FloatKeyframe::Value() const { | |
135 return value_; | |
136 } | |
137 | |
138 scoped_ptr<FloatKeyframe> FloatKeyframe::Clone() const { | |
139 scoped_ptr<TimingFunction> func; | |
140 if (timing_function()) | |
141 func = timing_function()->Clone(); | |
142 return FloatKeyframe::Create(Time(), Value(), func.Pass()); | |
143 } | |
144 | |
145 scoped_ptr<TransformKeyframe> TransformKeyframe::Create( | |
146 base::TimeDelta time, | |
147 const TransformOperations& value, | |
148 scoped_ptr<TimingFunction> timing_function) { | |
149 return make_scoped_ptr( | |
150 new TransformKeyframe(time, value, timing_function.Pass())); | |
151 } | |
152 | |
153 TransformKeyframe::TransformKeyframe(base::TimeDelta time, | |
154 const TransformOperations& value, | |
155 scoped_ptr<TimingFunction> timing_function) | |
156 : Keyframe(time, timing_function.Pass()), value_(value) { | |
157 } | |
158 | |
159 TransformKeyframe::~TransformKeyframe() {} | |
160 | |
161 const TransformOperations& TransformKeyframe::Value() const { | |
162 return value_; | |
163 } | |
164 | |
165 scoped_ptr<TransformKeyframe> TransformKeyframe::Clone() const { | |
166 scoped_ptr<TimingFunction> func; | |
167 if (timing_function()) | |
168 func = timing_function()->Clone(); | |
169 return TransformKeyframe::Create(Time(), Value(), func.Pass()); | |
170 } | |
171 | |
172 scoped_ptr<FilterKeyframe> FilterKeyframe::Create( | |
173 base::TimeDelta time, | |
174 const FilterOperations& value, | |
175 scoped_ptr<TimingFunction> timing_function) { | |
176 return make_scoped_ptr( | |
177 new FilterKeyframe(time, value, timing_function.Pass())); | |
178 } | |
179 | |
180 FilterKeyframe::FilterKeyframe(base::TimeDelta time, | |
181 const FilterOperations& value, | |
182 scoped_ptr<TimingFunction> timing_function) | |
183 : Keyframe(time, timing_function.Pass()), value_(value) { | |
184 } | |
185 | |
186 FilterKeyframe::~FilterKeyframe() {} | |
187 | |
188 const FilterOperations& FilterKeyframe::Value() const { | |
189 return value_; | |
190 } | |
191 | |
192 scoped_ptr<FilterKeyframe> FilterKeyframe::Clone() const { | |
193 scoped_ptr<TimingFunction> func; | |
194 if (timing_function()) | |
195 func = timing_function()->Clone(); | |
196 return FilterKeyframe::Create(Time(), Value(), func.Pass()); | |
197 } | |
198 | |
199 scoped_ptr<KeyframedColorAnimationCurve> KeyframedColorAnimationCurve:: | |
200 Create() { | |
201 return make_scoped_ptr(new KeyframedColorAnimationCurve); | |
202 } | |
203 | |
204 KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {} | |
205 | |
206 KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {} | |
207 | |
208 void KeyframedColorAnimationCurve::AddKeyframe( | |
209 scoped_ptr<ColorKeyframe> keyframe) { | |
210 InsertKeyframe(keyframe.Pass(), &keyframes_); | |
211 } | |
212 | |
213 base::TimeDelta KeyframedColorAnimationCurve::Duration() const { | |
214 return keyframes_.back()->Time() - keyframes_.front()->Time(); | |
215 } | |
216 | |
217 scoped_ptr<AnimationCurve> KeyframedColorAnimationCurve::Clone() const { | |
218 scoped_ptr<KeyframedColorAnimationCurve> to_return = | |
219 KeyframedColorAnimationCurve::Create(); | |
220 for (size_t i = 0; i < keyframes_.size(); ++i) | |
221 to_return->AddKeyframe(keyframes_[i]->Clone()); | |
222 | |
223 if (timing_function_) | |
224 to_return->SetTimingFunction(timing_function_->Clone()); | |
225 | |
226 return to_return.Pass(); | |
227 } | |
228 | |
229 SkColor KeyframedColorAnimationCurve::GetValue(base::TimeDelta t) const { | |
230 if (t <= keyframes_.front()->Time()) | |
231 return keyframes_.front()->Value(); | |
232 | |
233 if (t >= keyframes_.back()->Time()) | |
234 return keyframes_.back()->Value(); | |
235 | |
236 t = TransformedAnimationTime(keyframes_, timing_function_, t); | |
237 size_t i = GetActiveKeyframe(keyframes_, t); | |
238 double progress = TransformedKeyframeProgress(keyframes_, t, i); | |
239 | |
240 return gfx::Tween::ColorValueBetween( | |
241 progress, keyframes_[i]->Value(), keyframes_[i + 1]->Value()); | |
242 } | |
243 | |
244 // KeyframedFloatAnimationCurve | |
245 | |
246 scoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve:: | |
247 Create() { | |
248 return make_scoped_ptr(new KeyframedFloatAnimationCurve); | |
249 } | |
250 | |
251 KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {} | |
252 | |
253 KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {} | |
254 | |
255 void KeyframedFloatAnimationCurve::AddKeyframe( | |
256 scoped_ptr<FloatKeyframe> keyframe) { | |
257 InsertKeyframe(keyframe.Pass(), &keyframes_); | |
258 } | |
259 | |
260 base::TimeDelta KeyframedFloatAnimationCurve::Duration() const { | |
261 return keyframes_.back()->Time() - keyframes_.front()->Time(); | |
262 } | |
263 | |
264 scoped_ptr<AnimationCurve> KeyframedFloatAnimationCurve::Clone() const { | |
265 scoped_ptr<KeyframedFloatAnimationCurve> to_return = | |
266 KeyframedFloatAnimationCurve::Create(); | |
267 for (size_t i = 0; i < keyframes_.size(); ++i) | |
268 to_return->AddKeyframe(keyframes_[i]->Clone()); | |
269 | |
270 if (timing_function_) | |
271 to_return->SetTimingFunction(timing_function_->Clone()); | |
272 | |
273 return to_return.Pass(); | |
274 } | |
275 | |
276 float KeyframedFloatAnimationCurve::GetValue(base::TimeDelta t) const { | |
277 if (t <= keyframes_.front()->Time()) | |
278 return keyframes_.front()->Value(); | |
279 | |
280 if (t >= keyframes_.back()->Time()) | |
281 return keyframes_.back()->Value(); | |
282 | |
283 t = TransformedAnimationTime(keyframes_, timing_function_, t); | |
284 size_t i = GetActiveKeyframe(keyframes_, t); | |
285 double progress = TransformedKeyframeProgress(keyframes_, t, i); | |
286 | |
287 return keyframes_[i]->Value() + | |
288 (keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress; | |
289 } | |
290 | |
291 scoped_ptr<KeyframedTransformAnimationCurve> KeyframedTransformAnimationCurve:: | |
292 Create() { | |
293 return make_scoped_ptr(new KeyframedTransformAnimationCurve); | |
294 } | |
295 | |
296 KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {} | |
297 | |
298 KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {} | |
299 | |
300 void KeyframedTransformAnimationCurve::AddKeyframe( | |
301 scoped_ptr<TransformKeyframe> keyframe) { | |
302 InsertKeyframe(keyframe.Pass(), &keyframes_); | |
303 } | |
304 | |
305 base::TimeDelta KeyframedTransformAnimationCurve::Duration() const { | |
306 return keyframes_.back()->Time() - keyframes_.front()->Time(); | |
307 } | |
308 | |
309 scoped_ptr<AnimationCurve> KeyframedTransformAnimationCurve::Clone() const { | |
310 scoped_ptr<KeyframedTransformAnimationCurve> to_return = | |
311 KeyframedTransformAnimationCurve::Create(); | |
312 for (size_t i = 0; i < keyframes_.size(); ++i) | |
313 to_return->AddKeyframe(keyframes_[i]->Clone()); | |
314 | |
315 if (timing_function_) | |
316 to_return->SetTimingFunction(timing_function_->Clone()); | |
317 | |
318 return to_return.Pass(); | |
319 } | |
320 | |
321 gfx::Transform KeyframedTransformAnimationCurve::GetValue( | |
322 base::TimeDelta t) const { | |
323 if (t <= keyframes_.front()->Time()) | |
324 return keyframes_.front()->Value().Apply(); | |
325 | |
326 if (t >= keyframes_.back()->Time()) | |
327 return keyframes_.back()->Value().Apply(); | |
328 | |
329 t = TransformedAnimationTime(keyframes_, timing_function_, t); | |
330 size_t i = GetActiveKeyframe(keyframes_, t); | |
331 double progress = TransformedKeyframeProgress(keyframes_, t, i); | |
332 | |
333 return keyframes_[i + 1]->Value().Blend(keyframes_[i]->Value(), progress); | |
334 } | |
335 | |
336 bool KeyframedTransformAnimationCurve::AnimatedBoundsForBox( | |
337 const gfx::BoxF& box, | |
338 gfx::BoxF* bounds) const { | |
339 DCHECK_GE(keyframes_.size(), 2ul); | |
340 *bounds = gfx::BoxF(); | |
341 for (size_t i = 0; i < keyframes_.size() - 1; ++i) { | |
342 gfx::BoxF bounds_for_step; | |
343 float min_progress = 0.0; | |
344 float max_progress = 1.0; | |
345 if (keyframes_[i]->timing_function()) | |
346 keyframes_[i]->timing_function()->Range(&min_progress, &max_progress); | |
347 if (!keyframes_[i+1]->Value().BlendedBoundsForBox(box, | |
348 keyframes_[i]->Value(), | |
349 min_progress, | |
350 max_progress, | |
351 &bounds_for_step)) | |
352 return false; | |
353 bounds->Union(bounds_for_step); | |
354 } | |
355 return true; | |
356 } | |
357 | |
358 bool KeyframedTransformAnimationCurve::AffectsScale() const { | |
359 for (size_t i = 0; i < keyframes_.size(); ++i) { | |
360 if (keyframes_[i]->Value().AffectsScale()) | |
361 return true; | |
362 } | |
363 return false; | |
364 } | |
365 | |
366 bool KeyframedTransformAnimationCurve::PreservesAxisAlignment() const { | |
367 for (size_t i = 0; i < keyframes_.size(); ++i) { | |
368 if (!keyframes_[i]->Value().PreservesAxisAlignment()) | |
369 return false; | |
370 } | |
371 return true; | |
372 } | |
373 | |
374 bool KeyframedTransformAnimationCurve::IsTranslation() const { | |
375 for (size_t i = 0; i < keyframes_.size(); ++i) { | |
376 if (!keyframes_[i]->Value().IsTranslation() && | |
377 !keyframes_[i]->Value().IsIdentity()) | |
378 return false; | |
379 } | |
380 return true; | |
381 } | |
382 | |
383 bool KeyframedTransformAnimationCurve::MaximumTargetScale( | |
384 bool forward_direction, | |
385 float* max_scale) const { | |
386 DCHECK_GE(keyframes_.size(), 2ul); | |
387 *max_scale = 0.f; | |
388 | |
389 // If |forward_direction| is true, then skip the first frame, otherwise | |
390 // skip the last frame, since that is the original position in the animation. | |
391 size_t start = 1; | |
392 size_t end = keyframes_.size(); | |
393 if (!forward_direction) { | |
394 --start; | |
395 --end; | |
396 } | |
397 | |
398 for (size_t i = start; i < end; ++i) { | |
399 gfx::Vector3dF target_scale_for_segment; | |
400 if (!keyframes_[i]->Value().ScaleComponent(&target_scale_for_segment)) | |
401 return false; | |
402 float max_scale_for_segment = | |
403 fmax(std::abs(target_scale_for_segment.x()), | |
404 fmax(std::abs(target_scale_for_segment.y()), | |
405 std::abs(target_scale_for_segment.z()))); | |
406 *max_scale = fmax(*max_scale, max_scale_for_segment); | |
407 } | |
408 return true; | |
409 } | |
410 | |
411 scoped_ptr<KeyframedFilterAnimationCurve> KeyframedFilterAnimationCurve:: | |
412 Create() { | |
413 return make_scoped_ptr(new KeyframedFilterAnimationCurve); | |
414 } | |
415 | |
416 KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {} | |
417 | |
418 KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {} | |
419 | |
420 void KeyframedFilterAnimationCurve::AddKeyframe( | |
421 scoped_ptr<FilterKeyframe> keyframe) { | |
422 InsertKeyframe(keyframe.Pass(), &keyframes_); | |
423 } | |
424 | |
425 base::TimeDelta KeyframedFilterAnimationCurve::Duration() const { | |
426 return keyframes_.back()->Time() - keyframes_.front()->Time(); | |
427 } | |
428 | |
429 scoped_ptr<AnimationCurve> KeyframedFilterAnimationCurve::Clone() const { | |
430 scoped_ptr<KeyframedFilterAnimationCurve> to_return = | |
431 KeyframedFilterAnimationCurve::Create(); | |
432 for (size_t i = 0; i < keyframes_.size(); ++i) | |
433 to_return->AddKeyframe(keyframes_[i]->Clone()); | |
434 | |
435 if (timing_function_) | |
436 to_return->SetTimingFunction(timing_function_->Clone()); | |
437 | |
438 return to_return.Pass(); | |
439 } | |
440 | |
441 FilterOperations KeyframedFilterAnimationCurve::GetValue( | |
442 base::TimeDelta t) const { | |
443 if (t <= keyframes_.front()->Time()) | |
444 return keyframes_.front()->Value(); | |
445 | |
446 if (t >= keyframes_.back()->Time()) | |
447 return keyframes_.back()->Value(); | |
448 | |
449 t = TransformedAnimationTime(keyframes_, timing_function_, t); | |
450 size_t i = GetActiveKeyframe(keyframes_, t); | |
451 double progress = TransformedKeyframeProgress(keyframes_, t, i); | |
452 | |
453 return keyframes_[i + 1]->Value().Blend(keyframes_[i]->Value(), progress); | |
454 } | |
455 | |
456 bool KeyframedFilterAnimationCurve::HasFilterThatMovesPixels() const { | |
457 for (size_t i = 0; i < keyframes_.size(); ++i) { | |
458 if (keyframes_[i]->Value().HasFilterThatMovesPixels()) { | |
459 return true; | |
460 } | |
461 } | |
462 return false; | |
463 } | |
464 | |
465 } // namespace cc | |
OLD | NEW |