animation.cc revision f2477e01787aa58f445919b809d89e252beef54f
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",
351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "BackgroundColor"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)COMPILE_ASSERT(static_cast<int>(cc::Animation::TargetPropertyEnumSize) ==
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               arraysize(s_targetPropertyNames),
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               TargetProperty_names_match_enum);
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<Animation> Animation::Create(
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<AnimationCurve> curve,
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int animation_id,
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int group_id,
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TargetProperty target_property) {
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return make_scoped_ptr(new Animation(curve.Pass(),
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       animation_id,
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       group_id,
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       target_property)); }
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Animation::Animation(scoped_ptr<AnimationCurve> curve,
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     int animation_id,
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     int group_id,
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     TargetProperty target_property)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : curve_(curve.Pass()),
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      id_(animation_id),
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      group_(group_id),
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      target_property_(target_property),
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      run_state_(WaitingForTargetAvailability),
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      iterations_(1),
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      start_time_(0),
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      alternates_direction_(false),
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      time_offset_(0),
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      needs_synchronized_start_time_(false),
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      received_finished_event_(false),
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      suspended_(false),
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pause_time_(0),
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      total_paused_time_(0),
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      is_controlling_instance_(false),
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      is_impl_only_(false) {}
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Animation::~Animation() {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (run_state_ == Running || run_state_ == Paused)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SetRunState(Aborted, 0);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Animation::SetRunState(RunState run_state, double monotonic_time) {
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (suspended_)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char name_buffer[256];
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::snprintf(name_buffer,
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 sizeof(name_buffer),
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "%s-%d%s",
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 s_targetPropertyNames[target_property_],
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 group_,
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 is_controlling_instance_ ? "(impl)" : "");
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool is_waiting_to_start = run_state_ == WaitingForTargetAvailability ||
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             run_state_ == Starting;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_waiting_to_start && run_state == Running) {
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_EVENT_ASYNC_BEGIN1(
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "cc", "Animation", this, "Name", TRACE_STR_COPY(name_buffer));
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool was_finished = is_finished();
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* old_run_state_name = s_runStateNames[run_state_];
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (run_state == Running && run_state_ == Paused)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    total_paused_time_ += monotonic_time - pause_time_;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else if (run_state == Paused)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pause_time_ = monotonic_time;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  run_state_ = run_state;
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* new_run_state_name = s_runStateNames[run_state];
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!was_finished && is_finished())
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_EVENT_ASYNC_END0("cc", "Animation", this);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char state_buffer[256];
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::snprintf(state_buffer,
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 sizeof(state_buffer),
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "%s->%s",
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 old_run_state_name,
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 new_run_state_name);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT_INSTANT2("cc",
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       "LayerAnimationController::SetRunState",
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       TRACE_EVENT_SCOPE_THREAD,
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       "Name",
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       TRACE_STR_COPY(name_buffer),
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       "State",
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       TRACE_STR_COPY(state_buffer));
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Animation::Suspend(double monotonic_time) {
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetRunState(Paused, monotonic_time);
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  suspended_ = true;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Animation::Resume(double monotonic_time) {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  suspended_ = false;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetRunState(Running, monotonic_time);
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Animation::IsFinishedAt(double monotonic_time) const {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_finished())
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (needs_synchronized_start_time_)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return run_state_ == Running &&
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         iterations_ >= 0 &&
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         iterations_ * curve_->Duration() <= (monotonic_time -
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              start_time() -
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              total_paused_time_);
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)double Animation::TrimTimeToCurrentIteration(double monotonic_time) const {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double trimmed = monotonic_time + time_offset_;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If we're paused, time is 'stuck' at the pause time.
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (run_state_ == Paused)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    trimmed = pause_time_;
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returned time should always be relative to the start time and should
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // subtract all time spent paused.
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  trimmed -= start_time_ + total_paused_time_;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // If we're just starting or we're waiting on receiving a start time,
16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // time is 'stuck' at the initial state.
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if ((run_state_ == Starting && !has_set_start_time()) ||
17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      needs_synchronized_start_time())
17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    trimmed = time_offset_;
17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Zero is always the start of the animation.
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (trimmed <= 0)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Always return zero if we have no iterations.
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!iterations_)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't attempt to trim if we have no duration.
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (curve_->Duration() <= 0)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If less than an iteration duration, just return trimmed.
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (trimmed < curve_->Duration())
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return trimmed;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If greater than or equal to the total duration, return iteration duration.
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iterations_ >= 0 && trimmed >= curve_->Duration() * iterations_) {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (alternates_direction_ && !(iterations_ % 2))
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return 0;
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return curve_->Duration();
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We need to know the current iteration if we're alternating.
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int iteration = static_cast<int>(trimmed / curve_->Duration());
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Calculate x where trimmed = x + n * curve_->Duration() for some positive
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // integer n.
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  trimmed = fmod(trimmed, curve_->Duration());
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If we're alternating and on an odd iteration, reverse the direction.
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (alternates_direction_ && iteration % 2 == 1)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return curve_->Duration() - trimmed;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return trimmed;
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)scoped_ptr<Animation> Animation::Clone() const {
2128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return CloneAndInitialize(run_state_, start_time_);
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)scoped_ptr<Animation> Animation::CloneAndInitialize(RunState initial_run_state,
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                    double start_time) const {
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Animation> to_return(
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new Animation(curve_->Clone(), id_, group_, target_property_));
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_return->run_state_ = initial_run_state;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_return->iterations_ = iterations_;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_return->start_time_ = start_time;
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_return->pause_time_ = pause_time_;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_return->total_paused_time_ = total_paused_time_;
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_return->time_offset_ = time_offset_;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_return->alternates_direction_ = alternates_direction_;
2268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(!to_return->is_controlling_instance_);
2278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  to_return->is_controlling_instance_ = true;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return to_return.Pass();
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Animation::PushPropertiesTo(Animation* other) const {
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Currently, we only push changes due to pausing and resuming animations on
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the main thread.
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (run_state_ == Animation::Paused ||
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      other->run_state_ == Animation::Paused) {
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    other->run_state_ = run_state_;
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    other->pause_time_ = pause_time_;
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    other->total_paused_time_ = total_paused_time_;
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
243