Remove ui::LayerAnimationSequence::duration and ui::LayerAnimationElement::duration.

This change is in preparation for threading certain ui animations. When we do
this, the actual duration of an element will not be known ahead of time, since 
dispatching the element to the compositor thread will involve a small delay.

BUG=164206

Review URL: https://chromiumcodereview.appspot.com/11316315

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171112 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/ui/compositor/layer_animation_element.cc b/ui/compositor/layer_animation_element.cc
index 2b41e84a..ef18104e 100644
--- a/ui/compositor/layer_animation_element.cc
+++ b/ui/compositor/layer_animation_element.cc
@@ -405,15 +405,31 @@
 LayerAnimationElement::~LayerAnimationElement() {
 }
 
-bool LayerAnimationElement::Progress(double t,
+bool LayerAnimationElement::Progress(base::TimeDelta elapsed,
                                      LayerAnimationDelegate* delegate) {
   if (first_frame_)
     OnStart(delegate);
+  double t = 1.0;
+  if ((duration_ > base::TimeDelta()) && (elapsed < duration_))
+    t = elapsed.InMillisecondsF() / duration_.InMillisecondsF();
   bool need_draw = OnProgress(Tween::CalculateValue(tween_type_, t), delegate);
   first_frame_ = t == 1.0;
   return need_draw;
 }
 
+bool LayerAnimationElement::IsFinished(base::TimeDelta elapsed,
+                                       base::TimeDelta* total_duration) {
+  if (elapsed >= duration_) {
+    *total_duration = duration_;
+    return true;
+  }
+  return false;
+}
+
+bool LayerAnimationElement::ProgressToEnd(LayerAnimationDelegate* delegate) {
+  return Progress(duration_, delegate);
+}
+
 void LayerAnimationElement::GetTargetValue(TargetValue* target) const {
   OnGetTarget(target);
 }
diff --git a/ui/compositor/layer_animation_element.h b/ui/compositor/layer_animation_element.h
index 46aedb7..2a80698 100644
--- a/ui/compositor/layer_animation_element.h
+++ b/ui/compositor/layer_animation_element.h
@@ -113,11 +113,18 @@
       SkColor color,
       base::TimeDelta duration);
 
-  // Updates the delegate to the appropriate value for |t|, which is in the
-  // range [0, 1] (0 for initial, and 1 for final). If the animation is not
-  // aborted, it is guaranteed that Progress will eventually be called with
-  // t = 1.0. Returns true if a redraw is required.
-  bool Progress(double t, LayerAnimationDelegate* delegate);
+  // Updates the delegate to the appropriate value for |elapsed|. Returns true
+  // if a redraw is required.
+  bool Progress(base::TimeDelta elapsed, LayerAnimationDelegate* delegate);
+
+  // If calling Progress now, with the given elapsed time, will finish the
+  // animation, returns true and sets |total_duration| to the actual duration
+  // for this animation, incuding any queueing delays.
+  bool IsFinished(base::TimeDelta elapsed, base::TimeDelta* total_duration);
+
+  // Updates the delegate to the end of the animation. Returns true if a
+  // redraw is required.
+  bool ProgressToEnd(LayerAnimationDelegate* delegate);
 
   // Called if the animation is not allowed to complete. This may be called
   // before OnStarted or Progress.
@@ -129,9 +136,6 @@
   // The properties that the element modifies.
   const AnimatableProperties& properties() const { return properties_; }
 
-  // The duration of the animation
-  base::TimeDelta duration() const { return duration_; }
-
   Tween::Type tween_type() const { return tween_type_; }
   void set_tween_type(Tween::Type tween_type) { tween_type_ = tween_type; }
 
diff --git a/ui/compositor/layer_animation_element_unittest.cc b/ui/compositor/layer_animation_element_unittest.cc
index df9635d..41f9a47 100644
--- a/ui/compositor/layer_animation_element_unittest.cc
+++ b/ui/compositor/layer_animation_element_unittest.cc
@@ -33,13 +33,13 @@
 
   for (int i = 0; i < 2; ++i) {
     delegate.SetTransformFromAnimation(start_transform);
-    element->Progress(0.0, &delegate);
+    element->Progress(base::TimeDelta(), &delegate);
     CheckApproximatelyEqual(start_transform,
                             delegate.GetTransformForAnimation());
-    element->Progress(0.5, &delegate);
+    element->Progress(delta/2, &delegate);
     CheckApproximatelyEqual(middle_transform,
                             delegate.GetTransformForAnimation());
-    element->Progress(1.0, &delegate);
+    element->Progress(delta, &delegate);
     CheckApproximatelyEqual(target_transform,
                             delegate.GetTransformForAnimation());
   }
@@ -48,7 +48,9 @@
   element->GetTargetValue(&target_value);
   CheckApproximatelyEqual(target_transform, target_value.transform);
 
-  EXPECT_EQ(delta, element->duration());
+  base::TimeDelta element_duration;
+  EXPECT_TRUE(element->IsFinished(delta, &element_duration));
+  EXPECT_EQ(delta, element_duration);
 }
 
 // Check that the bounds element progresses the delegate as expected and
@@ -66,11 +68,11 @@
 
   for (int i = 0; i < 2; ++i) {
     delegate.SetBoundsFromAnimation(start);
-    element->Progress(0.0, &delegate);
+    element->Progress(base::TimeDelta(), &delegate);
     CheckApproximatelyEqual(start, delegate.GetBoundsForAnimation());
-    element->Progress(0.5, &delegate);
+    element->Progress(delta/2, &delegate);
     CheckApproximatelyEqual(middle, delegate.GetBoundsForAnimation());
-    element->Progress(1.0, &delegate);
+    element->Progress(delta, &delegate);
     CheckApproximatelyEqual(target, delegate.GetBoundsForAnimation());
   }
 
@@ -78,7 +80,9 @@
   element->GetTargetValue(&target_value);
   CheckApproximatelyEqual(target, target_value.bounds);
 
-  EXPECT_EQ(delta, element->duration());
+  base::TimeDelta element_duration;
+  EXPECT_TRUE(element->IsFinished(delta, &element_duration));
+  EXPECT_EQ(delta, element_duration);
 }
 
 // Check that the opacity element progresses the delegate as expected and
@@ -94,11 +98,11 @@
 
   for (int i = 0; i < 2; ++i) {
     delegate.SetOpacityFromAnimation(start);
-    element->Progress(0.0, &delegate);
+    element->Progress(base::TimeDelta(), &delegate);
     EXPECT_FLOAT_EQ(start, delegate.GetOpacityForAnimation());
-    element->Progress(0.5, &delegate);
+    element->Progress(delta/2, &delegate);
     EXPECT_FLOAT_EQ(middle, delegate.GetOpacityForAnimation());
-    element->Progress(1.0, &delegate);
+    element->Progress(delta, &delegate);
     EXPECT_FLOAT_EQ(target, delegate.GetOpacityForAnimation());
   }
 
@@ -106,7 +110,9 @@
   element->GetTargetValue(&target_value);
   EXPECT_FLOAT_EQ(target, target_value.opacity);
 
-  EXPECT_EQ(delta, element->duration());
+  base::TimeDelta element_duration;
+  EXPECT_TRUE(element->IsFinished(delta, &element_duration));
+  EXPECT_EQ(delta, element_duration);
 }
 
 // Check that the visibility element progresses the delegate as expected and
@@ -121,11 +127,11 @@
 
   for (int i = 0; i < 2; ++i) {
     delegate.SetVisibilityFromAnimation(start);
-    element->Progress(0.0, &delegate);
+    element->Progress(base::TimeDelta(), &delegate);
     EXPECT_TRUE(delegate.GetVisibilityForAnimation());
-    element->Progress(0.5, &delegate);
+    element->Progress(delta/2, &delegate);
     EXPECT_TRUE(delegate.GetVisibilityForAnimation());
-    element->Progress(1.0, &delegate);
+    element->Progress(delta, &delegate);
     EXPECT_FALSE(delegate.GetVisibilityForAnimation());
   }
 
@@ -133,7 +139,9 @@
   element->GetTargetValue(&target_value);
   EXPECT_FALSE(target_value.visibility);
 
-  EXPECT_EQ(delta, element->duration());
+  base::TimeDelta element_duration;
+  EXPECT_TRUE(element->IsFinished(delta, &element_duration));
+  EXPECT_EQ(delta, element_duration);
 }
 
 // Check that the Brightness element progresses the delegate as expected and
@@ -149,11 +157,11 @@
 
   for (int i = 0; i < 2; ++i) {
     delegate.SetBrightnessFromAnimation(start);
-    element->Progress(0.0, &delegate);
+    element->Progress(base::TimeDelta(), &delegate);
     EXPECT_FLOAT_EQ(start, delegate.GetBrightnessForAnimation());
-    element->Progress(0.5, &delegate);
+    element->Progress(delta/2, &delegate);
     EXPECT_FLOAT_EQ(middle, delegate.GetBrightnessForAnimation());
-    element->Progress(1.0, &delegate);
+    element->Progress(delta, &delegate);
     EXPECT_FLOAT_EQ(target, delegate.GetBrightnessForAnimation());
   }
 
@@ -161,7 +169,9 @@
   element->GetTargetValue(&target_value);
   EXPECT_FLOAT_EQ(target, target_value.brightness);
 
-  EXPECT_EQ(delta, element->duration());
+  base::TimeDelta element_duration;
+  EXPECT_TRUE(element->IsFinished(delta, &element_duration));
+  EXPECT_EQ(delta, element_duration);
 }
 
 // Check that the Grayscale element progresses the delegate as expected and
@@ -177,11 +187,11 @@
 
   for (int i = 0; i < 2; ++i) {
     delegate.SetGrayscaleFromAnimation(start);
-    element->Progress(0.0, &delegate);
+    element->Progress(base::TimeDelta(), &delegate);
     EXPECT_FLOAT_EQ(start, delegate.GetGrayscaleForAnimation());
-    element->Progress(0.5, &delegate);
+    element->Progress(delta/2, &delegate);
     EXPECT_FLOAT_EQ(middle, delegate.GetGrayscaleForAnimation());
-    element->Progress(1.0, &delegate);
+    element->Progress(delta, &delegate);
     EXPECT_FLOAT_EQ(target, delegate.GetGrayscaleForAnimation());
   }
 
@@ -189,7 +199,9 @@
   element->GetTargetValue(&target_value);
   EXPECT_FLOAT_EQ(target, target_value.grayscale);
 
-  EXPECT_EQ(delta, element->duration());
+  base::TimeDelta element_duration;
+  EXPECT_TRUE(element->IsFinished(delta, &element_duration));
+  EXPECT_EQ(delta, element_duration);
 }
 
 // Check that the pause element progresses the delegate as expected and
@@ -209,7 +221,7 @@
   TestLayerAnimationDelegate delegate;
   TestLayerAnimationDelegate copy = delegate;
 
-  element->Progress(1.0, &delegate);
+  element->Progress(delta, &delegate);
 
   // Nothing should have changed.
   CheckApproximatelyEqual(delegate.GetBoundsForAnimation(),
@@ -224,7 +236,9 @@
                   copy.GetGrayscaleForAnimation());
 
   // Pause should last for |delta|.
-  EXPECT_EQ(delta, element->duration());
+  base::TimeDelta element_duration;
+  EXPECT_TRUE(element->IsFinished(delta, &element_duration));
+  EXPECT_EQ(delta, element_duration);
 }
 
 } // namespace
diff --git a/ui/compositor/layer_animation_sequence.cc b/ui/compositor/layer_animation_sequence.cc
index 2a58e1f..8850fe08 100644
--- a/ui/compositor/layer_animation_sequence.cc
+++ b/ui/compositor/layer_animation_sequence.cc
@@ -38,34 +38,21 @@
   if (elements_.empty())
     return;
 
-  if (is_cyclic_ && duration_ > base::TimeDelta()) {
-    // If delta = elapsed - last_start_ is huge, we can skip ahead by complete
-    // loops to save time.
-    base::TimeDelta delta = elapsed - last_start_;
-    int64 k = delta.ToInternalValue() / duration_.ToInternalValue() - 1;
-
-    last_start_ += base::TimeDelta::FromInternalValue(
-      k * duration_.ToInternalValue());
-  }
-
   size_t current_index = last_element_ % elements_.size();
+  base::TimeDelta element_duration;
   while ((is_cyclic_ || last_element_ < elements_.size()) &&
-         (last_start_ + elements_[current_index]->duration() < elapsed)) {
+         elements_[current_index]->IsFinished(elapsed - last_start_,
+                                              &element_duration)) {
     // Let the element we're passing finish.
-    if (elements_[current_index]->Progress(1.0, delegate))
+    if (elements_[current_index]->Progress(elapsed - last_start_, delegate))
       redraw_required = true;
-    last_start_ += elements_[current_index]->duration();
+    last_start_ += element_duration;
     ++last_element_;
     current_index = last_element_ % elements_.size();
   }
 
   if (is_cyclic_ || last_element_ < elements_.size()) {
-    double t = 1.0;
-    if (elements_[current_index]->duration() > base::TimeDelta()) {
-      t = (elapsed - last_start_).InMillisecondsF() /
-          elements_[current_index]->duration().InMillisecondsF();
-    }
-    if (elements_[current_index]->Progress(t, delegate))
+    if (elements_[current_index]->Progress(elapsed - last_start_, delegate))
       redraw_required = true;
   }
 
@@ -74,7 +61,51 @@
   if (redraw_required)
     delegate->ScheduleDrawForAnimation();
 
-  if (!is_cyclic_ && elapsed == duration_) {
+  if (!is_cyclic_ && last_element_ == elements_.size()) {
+    last_element_ = 0;
+    last_start_ = base::TimeDelta::FromMilliseconds(0);
+    NotifyEnded();
+  }
+}
+
+bool LayerAnimationSequence::IsFinished(base::TimeDelta elapsed) {
+  if (is_cyclic_)
+    return false;
+
+  if (elements_.empty())
+    return true;
+
+  base::TimeDelta current_start = last_start_;
+  size_t current_index = last_element_;
+  base::TimeDelta element_duration;
+  while ((current_index < elements_.size()) &&
+          elements_[current_index]->IsFinished(elapsed - current_start,
+                                               &element_duration)) {
+    current_start += element_duration;
+    ++current_index;
+  }
+
+  return (current_index == elements_.size());
+}
+
+void LayerAnimationSequence::ProgressToEnd(LayerAnimationDelegate* delegate) {
+  bool redraw_required = false;
+
+  if (elements_.empty())
+    return;
+
+  size_t current_index = last_element_ % elements_.size();
+  while (current_index < elements_.size()) {
+    if (elements_[current_index]->ProgressToEnd(delegate))
+      redraw_required = true;
+    ++current_index;
+    ++last_element_;
+  }
+
+  if (redraw_required)
+    delegate->ScheduleDrawForAnimation();
+
+  if (!is_cyclic_) {
     last_element_ = 0;
     last_start_ = base::TimeDelta::FromMilliseconds(0);
     NotifyEnded();
@@ -102,8 +133,6 @@
 }
 
 void LayerAnimationSequence::AddElement(LayerAnimationElement* element) {
-  // Update duration and properties.
-  duration_ += element->duration();
   properties_.insert(element->properties().begin(),
                      element->properties().end());
   elements_.push_back(make_linked_ptr(element));
diff --git a/ui/compositor/layer_animation_sequence.h b/ui/compositor/layer_animation_sequence.h
index b05db20..dcf5b63 100644
--- a/ui/compositor/layer_animation_sequence.h
+++ b/ui/compositor/layer_animation_sequence.h
@@ -41,12 +41,18 @@
   explicit LayerAnimationSequence(LayerAnimationElement* element);
   virtual ~LayerAnimationSequence();
 
-  // Updates the delegate to the appropriate value for |elapsed|, which is in
-  // the range [0, Duration()].  If the animation is not aborted, it is
-  // guaranteed that Animate will be called with elapsed = Duration(). Requests
-  // a redraw if it is required.
+  // Updates the delegate to the appropriate value for |elapsed|. Requests a
+  // redraw if it is required.
   void Progress(base::TimeDelta elapsed, LayerAnimationDelegate* delegate);
 
+  // Returns true if calling Progress now, with the given elapsed time, will
+  // finish the animation.
+  bool IsFinished(base::TimeDelta elapsed);
+
+  // Updates the delegate to the end of the animation; if this sequence is
+  // cyclic, updates the delegate to the end of one cycle of the sequence.
+  void ProgressToEnd(LayerAnimationDelegate* delegate);
+
   // Sets the target value to the value that would have been set had
   // the sequence completed. Does nothing if the sequence is cyclic.
   void GetTargetValue(LayerAnimationElement::TargetValue* target) const;
@@ -59,11 +65,6 @@
     return properties_;
   }
 
-  // The total, finite duration of one cycle of the sequence.
-  base::TimeDelta duration() const {
-    return duration_;
-  }
-
   // Adds an element to the sequence. The sequences takes ownership of this
   // element.
   void AddElement(LayerAnimationElement* element);
@@ -103,9 +104,6 @@
   // Notifies the observers that this sequence has been aborted.
   void NotifyAborted();
 
-  // The sum of the durations of all the elements in the sequence.
-  base::TimeDelta duration_;
-
   // The union of all the properties modified by all elements in the sequence.
   LayerAnimationElement::AnimatableProperties properties_;
 
diff --git a/ui/compositor/layer_animation_sequence_unittest.cc b/ui/compositor/layer_animation_sequence_unittest.cc
index 827c4495..233dea3 100644
--- a/ui/compositor/layer_animation_sequence_unittest.cc
+++ b/ui/compositor/layer_animation_sequence_unittest.cc
@@ -24,7 +24,7 @@
 // Check that the sequence behaves sanely when it contains no elements.
 TEST(LayerAnimationSequenceTest, NoElement) {
   LayerAnimationSequence sequence;
-  EXPECT_EQ(sequence.duration(), base::TimeDelta());
+  EXPECT_TRUE(sequence.IsFinished(base::TimeDelta()));
   EXPECT_TRUE(sequence.properties().size() == 0);
   LayerAnimationElement::AnimatableProperties properties;
   EXPECT_FALSE(sequence.HasCommonProperty(properties));
@@ -55,7 +55,7 @@
   EXPECT_TRUE(sequence.properties().size() == 1);
   EXPECT_TRUE(sequence.properties().find(LayerAnimationElement::OPACITY) !=
               sequence.properties().end());
-  EXPECT_EQ(delta, sequence.duration());
+  EXPECT_TRUE(sequence.IsFinished(delta));
 }
 
 // Check that the sequences progresses the delegate as expected when it contains
@@ -124,7 +124,7 @@
               sequence.properties().end());
   EXPECT_TRUE(sequence.properties().find(LayerAnimationElement::BOUNDS) !=
               sequence.properties().end());
-  EXPECT_EQ(delta + delta + delta, sequence.duration());
+  EXPECT_TRUE(sequence.IsFinished(delta + delta + delta));
 }
 
 // Check that a sequence can still be aborted if it has cycled many times.
diff --git a/ui/compositor/layer_animator.cc b/ui/compositor/layer_animator.cc
index a6fcd7d..98261fe 100644
--- a/ui/compositor/layer_animator.cc
+++ b/ui/compositor/layer_animator.cc
@@ -333,7 +333,10 @@
 }
 
 void LayerAnimator::ProgressAnimationToEnd(LayerAnimationSequence* sequence) {
-  ProgressAnimation(sequence, sequence->duration());
+  if (!delegate())
+    return;
+
+  sequence->ProgressToEnd(delegate());
 }
 
 
@@ -365,8 +368,7 @@
       continue;
 
     base::TimeDelta delta = now - running_animations_copy[i].start_time();
-    if (delta >= running_animations_copy[i].sequence()->duration() &&
-        !running_animations_copy[i].sequence()->is_cyclic()) {
+    if (running_animations_copy[i].sequence()->IsFinished(delta)) {
       SAFE_INVOKE_VOID(FinishAnimation, running_animations_copy[i]);
     } else
       SAFE_INVOKE_VOID(ProgressAnimation, running_animations_copy[i], delta);
@@ -423,8 +425,7 @@
 void LayerAnimator::FinishAnimation(LayerAnimationSequence* sequence) {
   scoped_refptr<LayerAnimator> retain(this);
   scoped_ptr<LayerAnimationSequence> removed(RemoveAnimation(sequence));
-  if (delegate())
-    sequence->Progress(sequence->duration(), delegate());
+  ProgressAnimationToEnd(sequence);
   ProcessQueue();
   UpdateAnimationState();
 }
@@ -439,8 +440,7 @@
     if (!SAFE_INVOKE_BOOL(HasAnimation, running_animations_copy[i]))
       continue;
 
-    if (running_animations_copy[i].sequence()->duration() ==
-        base::TimeDelta()) {
+    if (running_animations_copy[i].sequence()->IsFinished(base::TimeDelta())) {
       SAFE_INVOKE_VOID(ProgressAnimationToEnd, running_animations_copy[i]);
       scoped_ptr<LayerAnimationSequence> removed(
           SAFE_INVOKE_PTR(RemoveAnimation, running_animations_copy[i]));
@@ -540,7 +540,7 @@
   if (!weak_sequence_ptr)
     return;
 
-  ProgressAnimation(sequence, sequence->duration());
+  ProgressAnimationToEnd(sequence);
   if (!weak_sequence_ptr)
     return;