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 #include "ui/gfx/animation/tween.h"
7 #include "ui/gfx/box_f.h"
8
9 namespace cc {
10
11 namespace {
12
13 template <class Keyframe>
InsertKeyframe(scoped_ptr<Keyframe> keyframe,ScopedPtrVector<Keyframe> & keyframes)14 void InsertKeyframe(scoped_ptr<Keyframe> keyframe,
15 ScopedPtrVector<Keyframe>& keyframes) {
16 // Usually, the keyframes will be added in order, so this loop would be
17 // unnecessary and we should skip it if possible.
18 if (!keyframes.empty() && keyframe->Time() < keyframes.back()->Time()) {
19 for (size_t i = 0; i < keyframes.size(); ++i) {
20 if (keyframe->Time() < keyframes[i]->Time()) {
21 keyframes.insert(keyframes.begin() + i, keyframe.Pass());
22 return;
23 }
24 }
25 }
26
27 keyframes.push_back(keyframe.Pass());
28 }
29
30 template <class Keyframes>
GetProgress(double t,size_t i,const Keyframes & keyframes)31 float GetProgress(double t, size_t i, const Keyframes& keyframes) {
32 float progress =
33 static_cast<float>((t - keyframes[i]->Time()) /
34 (keyframes[i + 1]->Time() - keyframes[i]->Time()));
35
36 if (keyframes[i]->timing_function())
37 progress = keyframes[i]->timing_function()->GetValue(progress);
38 return progress;
39 }
40
CloneTimingFunction(const TimingFunction * timing_function)41 scoped_ptr<TimingFunction> CloneTimingFunction(
42 const TimingFunction* timing_function) {
43 DCHECK(timing_function);
44 scoped_ptr<AnimationCurve> curve(timing_function->Clone());
45 return scoped_ptr<TimingFunction>(
46 static_cast<TimingFunction*>(curve.release()));
47 }
48
49 } // namespace
50
Keyframe(double time,scoped_ptr<TimingFunction> timing_function)51 Keyframe::Keyframe(double time, scoped_ptr<TimingFunction> timing_function)
52 : time_(time),
53 timing_function_(timing_function.Pass()) {}
54
~Keyframe()55 Keyframe::~Keyframe() {}
56
Time() const57 double Keyframe::Time() const {
58 return time_;
59 }
60
Create(double time,SkColor value,scoped_ptr<TimingFunction> timing_function)61 scoped_ptr<ColorKeyframe> ColorKeyframe::Create(
62 double time,
63 SkColor value,
64 scoped_ptr<TimingFunction> timing_function) {
65 return make_scoped_ptr(
66 new ColorKeyframe(time, value, timing_function.Pass()));
67 }
68
ColorKeyframe(double time,SkColor value,scoped_ptr<TimingFunction> timing_function)69 ColorKeyframe::ColorKeyframe(double time,
70 SkColor value,
71 scoped_ptr<TimingFunction> timing_function)
72 : Keyframe(time, timing_function.Pass()),
73 value_(value) {}
74
~ColorKeyframe()75 ColorKeyframe::~ColorKeyframe() {}
76
Value() const77 SkColor ColorKeyframe::Value() const { return value_; }
78
Clone() const79 scoped_ptr<ColorKeyframe> ColorKeyframe::Clone() const {
80 scoped_ptr<TimingFunction> func;
81 if (timing_function())
82 func = CloneTimingFunction(timing_function());
83 return ColorKeyframe::Create(Time(), Value(), func.Pass());
84 }
85
Create(double time,float value,scoped_ptr<TimingFunction> timing_function)86 scoped_ptr<FloatKeyframe> FloatKeyframe::Create(
87 double time,
88 float value,
89 scoped_ptr<TimingFunction> timing_function) {
90 return make_scoped_ptr(
91 new FloatKeyframe(time, value, timing_function.Pass()));
92 }
93
FloatKeyframe(double time,float value,scoped_ptr<TimingFunction> timing_function)94 FloatKeyframe::FloatKeyframe(double time,
95 float value,
96 scoped_ptr<TimingFunction> timing_function)
97 : Keyframe(time, timing_function.Pass()),
98 value_(value) {}
99
~FloatKeyframe()100 FloatKeyframe::~FloatKeyframe() {}
101
Value() const102 float FloatKeyframe::Value() const {
103 return value_;
104 }
105
Clone() const106 scoped_ptr<FloatKeyframe> FloatKeyframe::Clone() const {
107 scoped_ptr<TimingFunction> func;
108 if (timing_function())
109 func = CloneTimingFunction(timing_function());
110 return FloatKeyframe::Create(Time(), Value(), func.Pass());
111 }
112
Create(double time,const TransformOperations & value,scoped_ptr<TimingFunction> timing_function)113 scoped_ptr<TransformKeyframe> TransformKeyframe::Create(
114 double time,
115 const TransformOperations& value,
116 scoped_ptr<TimingFunction> timing_function) {
117 return make_scoped_ptr(
118 new TransformKeyframe(time, value, timing_function.Pass()));
119 }
120
TransformKeyframe(double time,const TransformOperations & value,scoped_ptr<TimingFunction> timing_function)121 TransformKeyframe::TransformKeyframe(double time,
122 const TransformOperations& value,
123 scoped_ptr<TimingFunction> timing_function)
124 : Keyframe(time, timing_function.Pass()),
125 value_(value) {}
126
~TransformKeyframe()127 TransformKeyframe::~TransformKeyframe() {}
128
Value() const129 const TransformOperations& TransformKeyframe::Value() const {
130 return value_;
131 }
132
Clone() const133 scoped_ptr<TransformKeyframe> TransformKeyframe::Clone() const {
134 scoped_ptr<TimingFunction> func;
135 if (timing_function())
136 func = CloneTimingFunction(timing_function());
137 return TransformKeyframe::Create(Time(), Value(), func.Pass());
138 }
139
Create(double time,const FilterOperations & value,scoped_ptr<TimingFunction> timing_function)140 scoped_ptr<FilterKeyframe> FilterKeyframe::Create(
141 double time,
142 const FilterOperations& value,
143 scoped_ptr<TimingFunction> timing_function) {
144 return make_scoped_ptr(
145 new FilterKeyframe(time, value, timing_function.Pass()));
146 }
147
FilterKeyframe(double time,const FilterOperations & value,scoped_ptr<TimingFunction> timing_function)148 FilterKeyframe::FilterKeyframe(double time,
149 const FilterOperations& value,
150 scoped_ptr<TimingFunction> timing_function)
151 : Keyframe(time, timing_function.Pass()),
152 value_(value) {}
153
~FilterKeyframe()154 FilterKeyframe::~FilterKeyframe() {}
155
Value() const156 const FilterOperations& FilterKeyframe::Value() const {
157 return value_;
158 }
159
Clone() const160 scoped_ptr<FilterKeyframe> FilterKeyframe::Clone() const {
161 scoped_ptr<TimingFunction> func;
162 if (timing_function())
163 func = CloneTimingFunction(timing_function());
164 return FilterKeyframe::Create(Time(), Value(), func.Pass());
165 }
166
167 scoped_ptr<KeyframedColorAnimationCurve> KeyframedColorAnimationCurve::
Create()168 Create() {
169 return make_scoped_ptr(new KeyframedColorAnimationCurve);
170 }
171
KeyframedColorAnimationCurve()172 KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {}
173
~KeyframedColorAnimationCurve()174 KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {}
175
AddKeyframe(scoped_ptr<ColorKeyframe> keyframe)176 void KeyframedColorAnimationCurve::AddKeyframe(
177 scoped_ptr<ColorKeyframe> keyframe) {
178 InsertKeyframe(keyframe.Pass(), keyframes_);
179 }
180
Duration() const181 double KeyframedColorAnimationCurve::Duration() const {
182 return keyframes_.back()->Time() - keyframes_.front()->Time();
183 }
184
Clone() const185 scoped_ptr<AnimationCurve> KeyframedColorAnimationCurve::Clone() const {
186 scoped_ptr<KeyframedColorAnimationCurve> to_return(
187 KeyframedColorAnimationCurve::Create());
188 for (size_t i = 0; i < keyframes_.size(); ++i)
189 to_return->AddKeyframe(keyframes_[i]->Clone());
190 return to_return.PassAs<AnimationCurve>();
191 }
192
GetValue(double t) const193 SkColor KeyframedColorAnimationCurve::GetValue(double t) const {
194 if (t <= keyframes_.front()->Time())
195 return keyframes_.front()->Value();
196
197 if (t >= keyframes_.back()->Time())
198 return keyframes_.back()->Value();
199
200 size_t i = 0;
201 for (; i < keyframes_.size() - 1; ++i) {
202 if (t < keyframes_[i + 1]->Time())
203 break;
204 }
205
206 float progress = GetProgress(t, i, keyframes_);
207
208 return gfx::Tween::ColorValueBetween(
209 progress, keyframes_[i]->Value(), keyframes_[i + 1]->Value());
210 }
211
212 // KeyframedFloatAnimationCurve
213
214 scoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve::
Create()215 Create() {
216 return make_scoped_ptr(new KeyframedFloatAnimationCurve);
217 }
218
KeyframedFloatAnimationCurve()219 KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {}
220
~KeyframedFloatAnimationCurve()221 KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {}
222
AddKeyframe(scoped_ptr<FloatKeyframe> keyframe)223 void KeyframedFloatAnimationCurve::AddKeyframe(
224 scoped_ptr<FloatKeyframe> keyframe) {
225 InsertKeyframe(keyframe.Pass(), keyframes_);
226 }
227
Duration() const228 double KeyframedFloatAnimationCurve::Duration() const {
229 return keyframes_.back()->Time() - keyframes_.front()->Time();
230 }
231
Clone() const232 scoped_ptr<AnimationCurve> KeyframedFloatAnimationCurve::Clone() const {
233 scoped_ptr<KeyframedFloatAnimationCurve> to_return(
234 KeyframedFloatAnimationCurve::Create());
235 for (size_t i = 0; i < keyframes_.size(); ++i)
236 to_return->AddKeyframe(keyframes_[i]->Clone());
237 return to_return.PassAs<AnimationCurve>();
238 }
239
GetValue(double t) const240 float KeyframedFloatAnimationCurve::GetValue(double t) const {
241 if (t <= keyframes_.front()->Time())
242 return keyframes_.front()->Value();
243
244 if (t >= keyframes_.back()->Time())
245 return keyframes_.back()->Value();
246
247 size_t i = 0;
248 for (; i < keyframes_.size() - 1; ++i) {
249 if (t < keyframes_[i+1]->Time())
250 break;
251 }
252
253 float progress = GetProgress(t, i, keyframes_);
254
255 return keyframes_[i]->Value() +
256 (keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress;
257 }
258
259 scoped_ptr<KeyframedTransformAnimationCurve> KeyframedTransformAnimationCurve::
Create()260 Create() {
261 return make_scoped_ptr(new KeyframedTransformAnimationCurve);
262 }
263
KeyframedTransformAnimationCurve()264 KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {}
265
~KeyframedTransformAnimationCurve()266 KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {}
267
AddKeyframe(scoped_ptr<TransformKeyframe> keyframe)268 void KeyframedTransformAnimationCurve::AddKeyframe(
269 scoped_ptr<TransformKeyframe> keyframe) {
270 InsertKeyframe(keyframe.Pass(), keyframes_);
271 }
272
Duration() const273 double KeyframedTransformAnimationCurve::Duration() const {
274 return keyframes_.back()->Time() - keyframes_.front()->Time();
275 }
276
Clone() const277 scoped_ptr<AnimationCurve> KeyframedTransformAnimationCurve::Clone() const {
278 scoped_ptr<KeyframedTransformAnimationCurve> to_return(
279 KeyframedTransformAnimationCurve::Create());
280 for (size_t i = 0; i < keyframes_.size(); ++i)
281 to_return->AddKeyframe(keyframes_[i]->Clone());
282 return to_return.PassAs<AnimationCurve>();
283 }
284
285 // Assumes that (*keyframes).front()->Time() < t < (*keyframes).back()-Time().
286 template<typename ValueType, typename KeyframeType>
GetCurveValue(const ScopedPtrVector<KeyframeType> * keyframes,double t)287 static ValueType GetCurveValue(const ScopedPtrVector<KeyframeType>* keyframes,
288 double t) {
289 size_t i = 0;
290 for (; i < keyframes->size() - 1; ++i) {
291 if (t < (*keyframes)[i+1]->Time())
292 break;
293 }
294
295 double progress = (t - (*keyframes)[i]->Time()) /
296 ((*keyframes)[i+1]->Time() - (*keyframes)[i]->Time());
297
298 if ((*keyframes)[i]->timing_function())
299 progress = (*keyframes)[i]->timing_function()->GetValue(progress);
300
301 return (*keyframes)[i+1]->Value().Blend((*keyframes)[i]->Value(), progress);
302 }
303
GetValue(double t) const304 gfx::Transform KeyframedTransformAnimationCurve::GetValue(double t) const {
305 if (t <= keyframes_.front()->Time())
306 return keyframes_.front()->Value().Apply();
307
308 if (t >= keyframes_.back()->Time())
309 return keyframes_.back()->Value().Apply();
310
311 return GetCurveValue<gfx::Transform, TransformKeyframe>(&keyframes_, t);
312 }
313
AnimatedBoundsForBox(const gfx::BoxF & box,gfx::BoxF * bounds) const314 bool KeyframedTransformAnimationCurve::AnimatedBoundsForBox(
315 const gfx::BoxF& box,
316 gfx::BoxF* bounds) const {
317 DCHECK_GE(keyframes_.size(), 2ul);
318 *bounds = gfx::BoxF();
319 for (size_t i = 0; i < keyframes_.size() - 1; ++i) {
320 gfx::BoxF bounds_for_step;
321 float min_progress = 0.0;
322 float max_progress = 1.0;
323 if (keyframes_[i]->timing_function())
324 keyframes_[i]->timing_function()->Range(&min_progress, &max_progress);
325 if (!keyframes_[i+1]->Value().BlendedBoundsForBox(box,
326 keyframes_[i]->Value(),
327 min_progress,
328 max_progress,
329 &bounds_for_step))
330 return false;
331 bounds->Union(bounds_for_step);
332 }
333 return true;
334 }
335
336 scoped_ptr<KeyframedFilterAnimationCurve> KeyframedFilterAnimationCurve::
Create()337 Create() {
338 return make_scoped_ptr(new KeyframedFilterAnimationCurve);
339 }
340
KeyframedFilterAnimationCurve()341 KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {}
342
~KeyframedFilterAnimationCurve()343 KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {}
344
AddKeyframe(scoped_ptr<FilterKeyframe> keyframe)345 void KeyframedFilterAnimationCurve::AddKeyframe(
346 scoped_ptr<FilterKeyframe> keyframe) {
347 InsertKeyframe(keyframe.Pass(), keyframes_);
348 }
349
Duration() const350 double KeyframedFilterAnimationCurve::Duration() const {
351 return keyframes_.back()->Time() - keyframes_.front()->Time();
352 }
353
Clone() const354 scoped_ptr<AnimationCurve> KeyframedFilterAnimationCurve::Clone() const {
355 scoped_ptr<KeyframedFilterAnimationCurve> to_return(
356 KeyframedFilterAnimationCurve::Create());
357 for (size_t i = 0; i < keyframes_.size(); ++i)
358 to_return->AddKeyframe(keyframes_[i]->Clone());
359 return to_return.PassAs<AnimationCurve>();
360 }
361
GetValue(double t) const362 FilterOperations KeyframedFilterAnimationCurve::GetValue(double t) const {
363 if (t <= keyframes_.front()->Time())
364 return keyframes_.front()->Value();
365
366 if (t >= keyframes_.back()->Time())
367 return keyframes_.back()->Value();
368
369 return GetCurveValue<FilterOperations, FilterKeyframe>(&keyframes_, t);
370 }
371
372 } // namespace cc
373