12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/animation/animation.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <cmath>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/debug/trace_event.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/animation/animation_curve.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This should match the RunState enum.
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const char* const s_runStateNames[] = {
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "WaitingForTargetAvailability",
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "WaitingForDeletion",
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "Starting",
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "Running",
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "Paused",
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "Finished",
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "Aborted"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)COMPILE_ASSERT(static_cast<int>(cc::Animation::RunStateEnumSize) ==
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               arraysize(s_runStateNames),
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               RunState_names_match_enum);
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This should match the TargetProperty enum.
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const char* const s_targetPropertyNames[] = {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "Transform",
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  "Opacity",
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "Filter",
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  "ScrollOffset",
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  "BackgroundColor"
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)COMPILE_ASSERT(static_cast<int>(cc::Animation::TargetPropertyEnumSize) ==
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               arraysize(s_targetPropertyNames),
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               TargetProperty_names_match_enum);
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<Animation> Animation::Create(
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<AnimationCurve> curve,
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int animation_id,
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int group_id,
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TargetProperty target_property) {
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return make_scoped_ptr(new Animation(curve.Pass(),
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       animation_id,
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       group_id,
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       target_property)); }
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Animation::Animation(scoped_ptr<AnimationCurve> curve,
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     int animation_id,
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     int group_id,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     TargetProperty target_property)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : curve_(curve.Pass()),
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      id_(animation_id),
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      group_(group_id),
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      target_property_(target_property),
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      run_state_(WaitingForTargetAvailability),
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      iterations_(1),
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      iteration_start_(0),
68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      direction_(Normal),
6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      playback_rate_(1),
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      fill_mode_(FillModeBoth),
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      needs_synchronized_start_time_(false),
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      received_finished_event_(false),
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      suspended_(false),
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      is_controlling_instance_(false),
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      is_impl_only_(false),
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      affects_active_observers_(true),
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      affects_pending_observers_(true) {
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Animation::~Animation() {
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (run_state_ == Running || run_state_ == Paused)
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SetRunState(Aborted, base::TimeTicks());
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Animation::SetRunState(RunState run_state,
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                            base::TimeTicks monotonic_time) {
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (suspended_)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char name_buffer[256];
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::snprintf(name_buffer,
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 sizeof(name_buffer),
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "%s-%d%s",
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 s_targetPropertyNames[target_property_],
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 group_,
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 is_controlling_instance_ ? "(impl)" : "");
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool is_waiting_to_start = run_state_ == WaitingForTargetAvailability ||
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             run_state_ == Starting;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_waiting_to_start && run_state == Running) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_EVENT_ASYNC_BEGIN1(
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "cc", "Animation", this, "Name", TRACE_STR_COPY(name_buffer));
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool was_finished = is_finished();
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* old_run_state_name = s_runStateNames[run_state_];
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (run_state == Running && run_state_ == Paused)
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    total_paused_time_ += (monotonic_time - pause_time_);
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else if (run_state == Paused)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pause_time_ = monotonic_time;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  run_state_ = run_state;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* new_run_state_name = s_runStateNames[run_state];
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!was_finished && is_finished())
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_EVENT_ASYNC_END0("cc", "Animation", this);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char state_buffer[256];
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::snprintf(state_buffer,
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 sizeof(state_buffer),
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "%s->%s",
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 old_run_state_name,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 new_run_state_name);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT_INSTANT2("cc",
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       "LayerAnimationController::SetRunState",
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       TRACE_EVENT_SCOPE_THREAD,
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       "Name",
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       TRACE_STR_COPY(name_buffer),
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       "State",
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       TRACE_STR_COPY(state_buffer));
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Animation::Suspend(base::TimeTicks monotonic_time) {
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetRunState(Paused, monotonic_time);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  suspended_ = true;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Animation::Resume(base::TimeTicks monotonic_time) {
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  suspended_ = false;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetRunState(Running, monotonic_time);
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool Animation::IsFinishedAt(base::TimeTicks monotonic_time) const {
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_finished())
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (needs_synchronized_start_time_)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (playback_rate_ == 0)
15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return run_state_ == Running && iterations_ >= 0 &&
15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         iterations_ * curve_->Duration() / std::abs(playback_rate_) <=
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)             (monotonic_time + time_offset_ - start_time_ - total_paused_time_)
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 .InSecondsF();
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool Animation::InEffect(base::TimeTicks monotonic_time) const {
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return ConvertToActiveTime(monotonic_time) >= 0 ||
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci         (fill_mode_ == FillModeBoth || fill_mode_ == FillModeBackwards);
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidouble Animation::ConvertToActiveTime(base::TimeTicks monotonic_time) const {
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::TimeTicks trimmed = monotonic_time + time_offset_;
17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If we're paused, time is 'stuck' at the pause time.
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (run_state_ == Paused)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    trimmed = pause_time_;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returned time should always be relative to the start time and should
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // subtract all time spent paused.
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  trimmed -= (start_time_ - base::TimeTicks()) + total_paused_time_;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // If we're just starting or we're waiting on receiving a start time,
18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // time is 'stuck' at the initial state.
18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if ((run_state_ == Starting && !has_set_start_time()) ||
18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      needs_synchronized_start_time())
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    trimmed = base::TimeTicks() + time_offset_;
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return (trimmed - base::TimeTicks()).InSecondsF();
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidouble Animation::TrimTimeToCurrentIteration(
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::TimeTicks monotonic_time) const {
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Check for valid parameters
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(playback_rate_);
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_GE(iteration_start_, 0);
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  double active_time = ConvertToActiveTime(monotonic_time);
195ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch  double start_offset = iteration_start_ * curve_->Duration();
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
197ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch  // Return start offset if we are before the start of the animation
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (active_time < 0)
199ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch    return start_offset;
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Always return zero if we have no iterations.
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!iterations_)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't attempt to trim if we have no duration.
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (curve_->Duration() <= 0)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  double repeated_duration = iterations_ * curve_->Duration();
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  double active_duration = repeated_duration / std::abs(playback_rate_);
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Check if we are past active duration
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (iterations_ > 0 && active_time >= active_duration)
2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    active_time = active_duration;
215010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Calculate the scaled active time
2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  double scaled_active_time;
2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (playback_rate_ < 0)
2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scaled_active_time =
2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        (active_time - active_duration) * playback_rate_ + start_offset;
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  else
2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scaled_active_time = active_time * playback_rate_ + start_offset;
2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Calculate the iteration time
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  double iteration_time;
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (scaled_active_time - start_offset == repeated_duration &&
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      fmod(iterations_ + iteration_start_, 1) == 0)
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    iteration_time = curve_->Duration();
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  else
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    iteration_time = fmod(scaled_active_time, curve_->Duration());
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Calculate the current iteration
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int iteration;
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (scaled_active_time <= 0)
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    iteration = 0;
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  else if (iteration_time == curve_->Duration())
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    iteration = ceil(iteration_start_ + iterations_ - 1);
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  else
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    iteration = static_cast<int>(scaled_active_time / curve_->Duration());
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Check if we are running the animation in reverse direction for the current
242010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // iteration
243010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  bool reverse = (direction_ == Reverse) ||
244010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 (direction_ == Alternate && iteration % 2 == 1) ||
245010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                 (direction_ == AlternateReverse && iteration % 2 == 0);
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // If we are running the animation in reverse direction, reverse the result
248010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (reverse)
2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    iteration_time = curve_->Duration() - iteration_time;
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return iteration_time;
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
254c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochscoped_ptr<Animation> Animation::CloneAndInitialize(
255c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    RunState initial_run_state) const {
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Animation> to_return(
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new Animation(curve_->Clone(), id_, group_, target_property_));
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_return->run_state_ = initial_run_state;
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_return->iterations_ = iterations_;
2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  to_return->iteration_start_ = iteration_start_;
261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  to_return->start_time_ = start_time_;
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_return->pause_time_ = pause_time_;
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_return->total_paused_time_ = total_paused_time_;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_return->time_offset_ = time_offset_;
265010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  to_return->direction_ = direction_;
26603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  to_return->playback_rate_ = playback_rate_;
2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  to_return->fill_mode_ = fill_mode_;
2688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(!to_return->is_controlling_instance_);
2698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  to_return->is_controlling_instance_ = true;
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return to_return.Pass();
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Animation::PushPropertiesTo(Animation* other) const {
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Currently, we only push changes due to pausing and resuming animations on
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the main thread.
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (run_state_ == Animation::Paused ||
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      other->run_state_ == Animation::Paused) {
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    other->run_state_ = run_state_;
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    other->pause_time_ = pause_time_;
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    other->total_paused_time_ = total_paused_time_;
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
285