Home | History | Annotate | Download | only in animation
      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>
     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>
     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 
     45 Keyframe::Keyframe(double time, scoped_ptr<TimingFunction> timing_function)
     46     : time_(time),
     47       timing_function_(timing_function.Pass()) {}
     48 
     49 Keyframe::~Keyframe() {}
     50 
     51 double Keyframe::Time() const {
     52   return time_;
     53 }
     54 
     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 
     63 ColorKeyframe::ColorKeyframe(double time,
     64                              SkColor value,
     65                              scoped_ptr<TimingFunction> timing_function)
     66     : Keyframe(time, timing_function.Pass()),
     67       value_(value) {}
     68 
     69 ColorKeyframe::~ColorKeyframe() {}
     70 
     71 SkColor ColorKeyframe::Value() const { return value_; }
     72 
     73 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 
     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 
     88 FloatKeyframe::FloatKeyframe(double time,
     89                              float value,
     90                              scoped_ptr<TimingFunction> timing_function)
     91     : Keyframe(time, timing_function.Pass()),
     92       value_(value) {}
     93 
     94 FloatKeyframe::~FloatKeyframe() {}
     95 
     96 float FloatKeyframe::Value() const {
     97   return value_;
     98 }
     99 
    100 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 
    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 
    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 
    121 TransformKeyframe::~TransformKeyframe() {}
    122 
    123 const TransformOperations& TransformKeyframe::Value() const {
    124   return value_;
    125 }
    126 
    127 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 
    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 
    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 
    148 FilterKeyframe::~FilterKeyframe() {}
    149 
    150 const FilterOperations& FilterKeyframe::Value() const {
    151   return value_;
    152 }
    153 
    154 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::
    162     Create() {
    163   return make_scoped_ptr(new KeyframedColorAnimationCurve);
    164 }
    165 
    166 KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {}
    167 
    168 KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {}
    169 
    170 void KeyframedColorAnimationCurve::AddKeyframe(
    171     scoped_ptr<ColorKeyframe> keyframe) {
    172   InsertKeyframe(keyframe.Pass(), keyframes_);
    173 }
    174 
    175 double KeyframedColorAnimationCurve::Duration() const {
    176   return keyframes_.back()->Time() - keyframes_.front()->Time();
    177 }
    178 
    179 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 
    187 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::
    209     Create() {
    210   return make_scoped_ptr(new KeyframedFloatAnimationCurve);
    211 }
    212 
    213 KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {}
    214 
    215 KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {}
    216 
    217 void KeyframedFloatAnimationCurve::AddKeyframe(
    218     scoped_ptr<FloatKeyframe> keyframe) {
    219   InsertKeyframe(keyframe.Pass(), keyframes_);
    220 }
    221 
    222 double KeyframedFloatAnimationCurve::Duration() const {
    223   return keyframes_.back()->Time() - keyframes_.front()->Time();
    224 }
    225 
    226 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 
    234 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::
    254     Create() {
    255   return make_scoped_ptr(new KeyframedTransformAnimationCurve);
    256 }
    257 
    258 KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {}
    259 
    260 KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {}
    261 
    262 void KeyframedTransformAnimationCurve::AddKeyframe(
    263     scoped_ptr<TransformKeyframe> keyframe) {
    264   InsertKeyframe(keyframe.Pass(), keyframes_);
    265 }
    266 
    267 double KeyframedTransformAnimationCurve::Duration() const {
    268   return keyframes_.back()->Time() - keyframes_.front()->Time();
    269 }
    270 
    271 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>
    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 
    298 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 
    308 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 
    330 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 
    338 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 
    347 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::
    376     Create() {
    377   return make_scoped_ptr(new KeyframedFilterAnimationCurve);
    378 }
    379 
    380 KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {}
    381 
    382 KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {}
    383 
    384 void KeyframedFilterAnimationCurve::AddKeyframe(
    385     scoped_ptr<FilterKeyframe> keyframe) {
    386   InsertKeyframe(keyframe.Pass(), keyframes_);
    387 }
    388 
    389 double KeyframedFilterAnimationCurve::Duration() const {
    390   return keyframes_.back()->Time() - keyframes_.front()->Time();
    391 }
    392 
    393 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 
    401 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 
    411 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