• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
43 }  // namespace
44 
Keyframe(double time,scoped_ptr<TimingFunction> timing_function)45 Keyframe::Keyframe(double time, scoped_ptr<TimingFunction> timing_function)
46     : time_(time),
47       timing_function_(timing_function.Pass()) {}
48 
~Keyframe()49 Keyframe::~Keyframe() {}
50 
Time() const51 double Keyframe::Time() const {
52   return time_;
53 }
54 
Create(double time,SkColor value,scoped_ptr<TimingFunction> timing_function)55 scoped_ptr<ColorKeyframe> ColorKeyframe::Create(
56     double time,
57     SkColor value,
58     scoped_ptr<TimingFunction> timing_function) {
59   return make_scoped_ptr(
60       new ColorKeyframe(time, value, timing_function.Pass()));
61 }
62 
ColorKeyframe(double time,SkColor value,scoped_ptr<TimingFunction> timing_function)63 ColorKeyframe::ColorKeyframe(double time,
64                              SkColor value,
65                              scoped_ptr<TimingFunction> timing_function)
66     : Keyframe(time, timing_function.Pass()),
67       value_(value) {}
68 
~ColorKeyframe()69 ColorKeyframe::~ColorKeyframe() {}
70 
Value() const71 SkColor ColorKeyframe::Value() const { return value_; }
72 
Clone() const73 scoped_ptr<ColorKeyframe> ColorKeyframe::Clone() const {
74   scoped_ptr<TimingFunction> func;
75   if (timing_function())
76     func = timing_function()->Clone();
77   return ColorKeyframe::Create(Time(), Value(), func.Pass());
78 }
79 
Create(double time,float value,scoped_ptr<TimingFunction> timing_function)80 scoped_ptr<FloatKeyframe> FloatKeyframe::Create(
81     double time,
82     float value,
83     scoped_ptr<TimingFunction> timing_function) {
84   return make_scoped_ptr(
85       new FloatKeyframe(time, value, timing_function.Pass()));
86 }
87 
FloatKeyframe(double time,float value,scoped_ptr<TimingFunction> timing_function)88 FloatKeyframe::FloatKeyframe(double time,
89                              float value,
90                              scoped_ptr<TimingFunction> timing_function)
91     : Keyframe(time, timing_function.Pass()),
92       value_(value) {}
93 
~FloatKeyframe()94 FloatKeyframe::~FloatKeyframe() {}
95 
Value() const96 float FloatKeyframe::Value() const {
97   return value_;
98 }
99 
Clone() const100 scoped_ptr<FloatKeyframe> FloatKeyframe::Clone() const {
101   scoped_ptr<TimingFunction> func;
102   if (timing_function())
103     func = timing_function()->Clone();
104   return FloatKeyframe::Create(Time(), Value(), func.Pass());
105 }
106 
Create(double time,const TransformOperations & value,scoped_ptr<TimingFunction> timing_function)107 scoped_ptr<TransformKeyframe> TransformKeyframe::Create(
108     double time,
109     const TransformOperations& value,
110     scoped_ptr<TimingFunction> timing_function) {
111   return make_scoped_ptr(
112       new TransformKeyframe(time, value, timing_function.Pass()));
113 }
114 
TransformKeyframe(double time,const TransformOperations & value,scoped_ptr<TimingFunction> timing_function)115 TransformKeyframe::TransformKeyframe(double time,
116                                      const TransformOperations& value,
117                                      scoped_ptr<TimingFunction> timing_function)
118     : Keyframe(time, timing_function.Pass()),
119       value_(value) {}
120 
~TransformKeyframe()121 TransformKeyframe::~TransformKeyframe() {}
122 
Value() const123 const TransformOperations& TransformKeyframe::Value() const {
124   return value_;
125 }
126 
Clone() const127 scoped_ptr<TransformKeyframe> TransformKeyframe::Clone() const {
128   scoped_ptr<TimingFunction> func;
129   if (timing_function())
130     func = timing_function()->Clone();
131   return TransformKeyframe::Create(Time(), Value(), func.Pass());
132 }
133 
Create(double time,const FilterOperations & value,scoped_ptr<TimingFunction> timing_function)134 scoped_ptr<FilterKeyframe> FilterKeyframe::Create(
135     double time,
136     const FilterOperations& value,
137     scoped_ptr<TimingFunction> timing_function) {
138   return make_scoped_ptr(
139       new FilterKeyframe(time, value, timing_function.Pass()));
140 }
141 
FilterKeyframe(double time,const FilterOperations & value,scoped_ptr<TimingFunction> timing_function)142 FilterKeyframe::FilterKeyframe(double time,
143                                const FilterOperations& value,
144                                scoped_ptr<TimingFunction> timing_function)
145     : Keyframe(time, timing_function.Pass()),
146       value_(value) {}
147 
~FilterKeyframe()148 FilterKeyframe::~FilterKeyframe() {}
149 
Value() const150 const FilterOperations& FilterKeyframe::Value() const {
151   return value_;
152 }
153 
Clone() const154 scoped_ptr<FilterKeyframe> FilterKeyframe::Clone() const {
155   scoped_ptr<TimingFunction> func;
156   if (timing_function())
157     func = timing_function()->Clone();
158   return FilterKeyframe::Create(Time(), Value(), func.Pass());
159 }
160 
161 scoped_ptr<KeyframedColorAnimationCurve> KeyframedColorAnimationCurve::
Create()162     Create() {
163   return make_scoped_ptr(new KeyframedColorAnimationCurve);
164 }
165 
KeyframedColorAnimationCurve()166 KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {}
167 
~KeyframedColorAnimationCurve()168 KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {}
169 
AddKeyframe(scoped_ptr<ColorKeyframe> keyframe)170 void KeyframedColorAnimationCurve::AddKeyframe(
171     scoped_ptr<ColorKeyframe> keyframe) {
172   InsertKeyframe(keyframe.Pass(), keyframes_);
173 }
174 
Duration() const175 double KeyframedColorAnimationCurve::Duration() const {
176   return keyframes_.back()->Time() - keyframes_.front()->Time();
177 }
178 
Clone() const179 scoped_ptr<AnimationCurve> KeyframedColorAnimationCurve::Clone() const {
180   scoped_ptr<KeyframedColorAnimationCurve> to_return(
181       KeyframedColorAnimationCurve::Create());
182   for (size_t i = 0; i < keyframes_.size(); ++i)
183     to_return->AddKeyframe(keyframes_[i]->Clone());
184   return to_return.PassAs<AnimationCurve>();
185 }
186 
GetValue(double t) const187 SkColor KeyframedColorAnimationCurve::GetValue(double t) const {
188   if (t <= keyframes_.front()->Time())
189     return keyframes_.front()->Value();
190 
191   if (t >= keyframes_.back()->Time())
192     return keyframes_.back()->Value();
193 
194   size_t i = 0;
195   for (; i < keyframes_.size() - 1; ++i) {
196     if (t < keyframes_[i + 1]->Time())
197       break;
198   }
199 
200   float progress = GetProgress(t, i, keyframes_);
201 
202   return gfx::Tween::ColorValueBetween(
203       progress, keyframes_[i]->Value(), keyframes_[i + 1]->Value());
204 }
205 
206 // KeyframedFloatAnimationCurve
207 
208 scoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve::
Create()209     Create() {
210   return make_scoped_ptr(new KeyframedFloatAnimationCurve);
211 }
212 
KeyframedFloatAnimationCurve()213 KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {}
214 
~KeyframedFloatAnimationCurve()215 KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {}
216 
AddKeyframe(scoped_ptr<FloatKeyframe> keyframe)217 void KeyframedFloatAnimationCurve::AddKeyframe(
218     scoped_ptr<FloatKeyframe> keyframe) {
219   InsertKeyframe(keyframe.Pass(), keyframes_);
220 }
221 
Duration() const222 double KeyframedFloatAnimationCurve::Duration() const {
223   return keyframes_.back()->Time() - keyframes_.front()->Time();
224 }
225 
Clone() const226 scoped_ptr<AnimationCurve> KeyframedFloatAnimationCurve::Clone() const {
227   scoped_ptr<KeyframedFloatAnimationCurve> to_return(
228       KeyframedFloatAnimationCurve::Create());
229   for (size_t i = 0; i < keyframes_.size(); ++i)
230     to_return->AddKeyframe(keyframes_[i]->Clone());
231   return to_return.PassAs<AnimationCurve>();
232 }
233 
GetValue(double t) const234 float KeyframedFloatAnimationCurve::GetValue(double t) const {
235   if (t <= keyframes_.front()->Time())
236     return keyframes_.front()->Value();
237 
238   if (t >= keyframes_.back()->Time())
239     return keyframes_.back()->Value();
240 
241   size_t i = 0;
242   for (; i < keyframes_.size() - 1; ++i) {
243     if (t < keyframes_[i+1]->Time())
244       break;
245   }
246 
247   float progress = GetProgress(t, i, keyframes_);
248 
249   return keyframes_[i]->Value() +
250       (keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress;
251 }
252 
253 scoped_ptr<KeyframedTransformAnimationCurve> KeyframedTransformAnimationCurve::
Create()254     Create() {
255   return make_scoped_ptr(new KeyframedTransformAnimationCurve);
256 }
257 
KeyframedTransformAnimationCurve()258 KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {}
259 
~KeyframedTransformAnimationCurve()260 KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {}
261 
AddKeyframe(scoped_ptr<TransformKeyframe> keyframe)262 void KeyframedTransformAnimationCurve::AddKeyframe(
263     scoped_ptr<TransformKeyframe> keyframe) {
264   InsertKeyframe(keyframe.Pass(), keyframes_);
265 }
266 
Duration() const267 double KeyframedTransformAnimationCurve::Duration() const {
268   return keyframes_.back()->Time() - keyframes_.front()->Time();
269 }
270 
Clone() const271 scoped_ptr<AnimationCurve> KeyframedTransformAnimationCurve::Clone() const {
272   scoped_ptr<KeyframedTransformAnimationCurve> to_return(
273       KeyframedTransformAnimationCurve::Create());
274   for (size_t i = 0; i < keyframes_.size(); ++i)
275     to_return->AddKeyframe(keyframes_[i]->Clone());
276   return to_return.PassAs<AnimationCurve>();
277 }
278 
279 // Assumes that (*keyframes).front()->Time() < t < (*keyframes).back()-Time().
280 template<typename ValueType, typename KeyframeType>
GetCurveValue(const ScopedPtrVector<KeyframeType> * keyframes,double t)281 static ValueType GetCurveValue(const ScopedPtrVector<KeyframeType>* keyframes,
282                                double t) {
283   size_t i = 0;
284   for (; i < keyframes->size() - 1; ++i) {
285     if (t < (*keyframes)[i+1]->Time())
286       break;
287   }
288 
289   double progress = (t - (*keyframes)[i]->Time()) /
290                     ((*keyframes)[i+1]->Time() - (*keyframes)[i]->Time());
291 
292   if ((*keyframes)[i]->timing_function())
293     progress = (*keyframes)[i]->timing_function()->GetValue(progress);
294 
295   return (*keyframes)[i+1]->Value().Blend((*keyframes)[i]->Value(), progress);
296 }
297 
GetValue(double t) const298 gfx::Transform KeyframedTransformAnimationCurve::GetValue(double t) const {
299   if (t <= keyframes_.front()->Time())
300     return keyframes_.front()->Value().Apply();
301 
302   if (t >= keyframes_.back()->Time())
303     return keyframes_.back()->Value().Apply();
304 
305   return GetCurveValue<gfx::Transform, TransformKeyframe>(&keyframes_, t);
306 }
307 
AnimatedBoundsForBox(const gfx::BoxF & box,gfx::BoxF * bounds) const308 bool KeyframedTransformAnimationCurve::AnimatedBoundsForBox(
309     const gfx::BoxF& box,
310     gfx::BoxF* bounds) const {
311   DCHECK_GE(keyframes_.size(), 2ul);
312   *bounds = gfx::BoxF();
313   for (size_t i = 0; i < keyframes_.size() - 1; ++i) {
314     gfx::BoxF bounds_for_step;
315     float min_progress = 0.0;
316     float max_progress = 1.0;
317     if (keyframes_[i]->timing_function())
318       keyframes_[i]->timing_function()->Range(&min_progress, &max_progress);
319     if (!keyframes_[i+1]->Value().BlendedBoundsForBox(box,
320                                                       keyframes_[i]->Value(),
321                                                       min_progress,
322                                                       max_progress,
323                                                       &bounds_for_step))
324       return false;
325     bounds->Union(bounds_for_step);
326   }
327   return true;
328 }
329 
AffectsScale() const330 bool KeyframedTransformAnimationCurve::AffectsScale() const {
331   for (size_t i = 0; i < keyframes_.size(); ++i) {
332     if (keyframes_[i]->Value().AffectsScale())
333       return true;
334   }
335   return false;
336 }
337 
IsTranslation() const338 bool KeyframedTransformAnimationCurve::IsTranslation() const {
339   for (size_t i = 0; i < keyframes_.size(); ++i) {
340     if (!keyframes_[i]->Value().IsTranslation() &&
341         !keyframes_[i]->Value().IsIdentity())
342       return false;
343   }
344   return true;
345 }
346 
MaximumTargetScale(bool forward_direction,float * max_scale) const347 bool KeyframedTransformAnimationCurve::MaximumTargetScale(
348     bool forward_direction,
349     float* max_scale) const {
350   DCHECK_GE(keyframes_.size(), 2ul);
351   *max_scale = 0.f;
352 
353   // If |forward_direction| is true, then skip the first frame, otherwise
354   // skip the last frame, since that is the original position in the animation.
355   size_t start = 1;
356   size_t end = keyframes_.size();
357   if (!forward_direction) {
358     --start;
359     --end;
360   }
361 
362   for (size_t i = start; i < end; ++i) {
363     gfx::Vector3dF target_scale_for_segment;
364     if (!keyframes_[i]->Value().ScaleComponent(&target_scale_for_segment))
365       return false;
366     float max_scale_for_segment =
367         fmax(std::abs(target_scale_for_segment.x()),
368              fmax(std::abs(target_scale_for_segment.y()),
369                   std::abs(target_scale_for_segment.z())));
370     *max_scale = fmax(*max_scale, max_scale_for_segment);
371   }
372   return true;
373 }
374 
375 scoped_ptr<KeyframedFilterAnimationCurve> KeyframedFilterAnimationCurve::
Create()376     Create() {
377   return make_scoped_ptr(new KeyframedFilterAnimationCurve);
378 }
379 
KeyframedFilterAnimationCurve()380 KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {}
381 
~KeyframedFilterAnimationCurve()382 KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {}
383 
AddKeyframe(scoped_ptr<FilterKeyframe> keyframe)384 void KeyframedFilterAnimationCurve::AddKeyframe(
385     scoped_ptr<FilterKeyframe> keyframe) {
386   InsertKeyframe(keyframe.Pass(), keyframes_);
387 }
388 
Duration() const389 double KeyframedFilterAnimationCurve::Duration() const {
390   return keyframes_.back()->Time() - keyframes_.front()->Time();
391 }
392 
Clone() const393 scoped_ptr<AnimationCurve> KeyframedFilterAnimationCurve::Clone() const {
394   scoped_ptr<KeyframedFilterAnimationCurve> to_return(
395       KeyframedFilterAnimationCurve::Create());
396   for (size_t i = 0; i < keyframes_.size(); ++i)
397     to_return->AddKeyframe(keyframes_[i]->Clone());
398   return to_return.PassAs<AnimationCurve>();
399 }
400 
GetValue(double t) const401 FilterOperations KeyframedFilterAnimationCurve::GetValue(double t) const {
402   if (t <= keyframes_.front()->Time())
403     return keyframes_.front()->Value();
404 
405   if (t >= keyframes_.back()->Time())
406     return keyframes_.back()->Value();
407 
408   return GetCurveValue<FilterOperations, FilterKeyframe>(&keyframes_, t);
409 }
410 
HasFilterThatMovesPixels() const411 bool KeyframedFilterAnimationCurve::HasFilterThatMovesPixels() const {
412   for (size_t i = 0; i < keyframes_.size(); ++i) {
413     if (keyframes_[i]->Value().HasFilterThatMovesPixels()) {
414       return true;
415     }
416   }
417   return false;
418 }
419 
420 }  // namespace cc
421