- add sources.
[platform/framework/web/crosswalk.git] / src / cc / animation / animation.cc
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 "cc/animation/animation.h"
6
7 #include <cmath>
8
9 #include "base/debug/trace_event.h"
10 #include "base/strings/string_util.h"
11 #include "cc/animation/animation_curve.h"
12
13 namespace {
14
15 // This should match the RunState enum.
16 static const char* const s_runStateNames[] = {
17   "WaitingForNextTick",
18   "WaitingForTargetAvailability",
19   "WaitingForStartTime",
20   "WaitingForDeletion",
21   "Starting",
22   "Running",
23   "Paused",
24   "Finished",
25   "Aborted"
26 };
27
28 COMPILE_ASSERT(static_cast<int>(cc::Animation::RunStateEnumSize) ==
29                arraysize(s_runStateNames),
30                RunState_names_match_enum);
31
32 // This should match the TargetProperty enum.
33 static const char* const s_targetPropertyNames[] = {
34   "Transform",
35   "Opacity",
36   "Filter",
37   "BackgroundColor"
38 };
39
40 COMPILE_ASSERT(static_cast<int>(cc::Animation::TargetPropertyEnumSize) ==
41                arraysize(s_targetPropertyNames),
42                TargetProperty_names_match_enum);
43
44 }  // namespace
45
46 namespace cc {
47
48 scoped_ptr<Animation> Animation::Create(
49     scoped_ptr<AnimationCurve> curve,
50     int animation_id,
51     int group_id,
52     TargetProperty target_property) {
53   return make_scoped_ptr(new Animation(curve.Pass(),
54                                        animation_id,
55                                        group_id,
56                                        target_property)); }
57
58 Animation::Animation(scoped_ptr<AnimationCurve> curve,
59                      int animation_id,
60                      int group_id,
61                      TargetProperty target_property)
62     : curve_(curve.Pass()),
63       id_(animation_id),
64       group_(group_id),
65       target_property_(target_property),
66       run_state_(WaitingForTargetAvailability),
67       iterations_(1),
68       start_time_(0),
69       alternates_direction_(false),
70       time_offset_(0),
71       needs_synchronized_start_time_(false),
72       received_finished_event_(false),
73       suspended_(false),
74       pause_time_(0),
75       total_paused_time_(0),
76       is_controlling_instance_(false),
77       is_impl_only_(false) {}
78
79 Animation::~Animation() {
80   if (run_state_ == Running || run_state_ == Paused)
81     SetRunState(Aborted, 0);
82 }
83
84 void Animation::SetRunState(RunState run_state, double monotonic_time) {
85   if (suspended_)
86     return;
87
88   char name_buffer[256];
89   base::snprintf(name_buffer,
90                  sizeof(name_buffer),
91                  "%s-%d%s",
92                  s_targetPropertyNames[target_property_],
93                  group_,
94                  is_controlling_instance_ ? "(impl)" : "");
95
96   bool is_waiting_to_start = run_state_ == WaitingForNextTick ||
97                              run_state_ == WaitingForTargetAvailability ||
98                              run_state_ == WaitingForStartTime ||
99                              run_state_ == Starting;
100
101   if (is_waiting_to_start && run_state == Running) {
102     TRACE_EVENT_ASYNC_BEGIN1(
103         "cc", "Animation", this, "Name", TRACE_STR_COPY(name_buffer));
104   }
105
106   bool was_finished = is_finished();
107
108   const char* old_run_state_name = s_runStateNames[run_state_];
109
110   if (run_state == Running && run_state_ == Paused)
111     total_paused_time_ += monotonic_time - pause_time_;
112   else if (run_state == Paused)
113     pause_time_ = monotonic_time;
114   run_state_ = run_state;
115
116   const char* new_run_state_name = s_runStateNames[run_state];
117
118   if (!was_finished && is_finished())
119     TRACE_EVENT_ASYNC_END0("cc", "Animation", this);
120
121   char state_buffer[256];
122   base::snprintf(state_buffer,
123                  sizeof(state_buffer),
124                  "%s->%s",
125                  old_run_state_name,
126                  new_run_state_name);
127
128   TRACE_EVENT_INSTANT2("cc",
129                        "LayerAnimationController::SetRunState",
130                        TRACE_EVENT_SCOPE_THREAD,
131                        "Name",
132                        TRACE_STR_COPY(name_buffer),
133                        "State",
134                        TRACE_STR_COPY(state_buffer));
135 }
136
137 void Animation::Suspend(double monotonic_time) {
138   SetRunState(Paused, monotonic_time);
139   suspended_ = true;
140 }
141
142 void Animation::Resume(double monotonic_time) {
143   suspended_ = false;
144   SetRunState(Running, monotonic_time);
145 }
146
147 bool Animation::IsFinishedAt(double monotonic_time) const {
148   if (is_finished())
149     return true;
150
151   if (needs_synchronized_start_time_)
152     return false;
153
154   return run_state_ == Running &&
155          iterations_ >= 0 &&
156          iterations_ * curve_->Duration() <= (monotonic_time -
157                                               start_time() -
158                                               total_paused_time_);
159 }
160
161 double Animation::TrimTimeToCurrentIteration(double monotonic_time) const {
162   double trimmed = monotonic_time + time_offset_;
163
164   // If we're paused, time is 'stuck' at the pause time.
165   if (run_state_ == Paused)
166     trimmed = pause_time_;
167
168   // Returned time should always be relative to the start time and should
169   // subtract all time spent paused.
170   trimmed -= start_time_ + total_paused_time_;
171
172   // If we're just starting or we're waiting on receiving a start time,
173   // time is 'stuck' at the initial state.
174   if ((run_state_ == Starting && !has_set_start_time()) ||
175       needs_synchronized_start_time())
176     trimmed = time_offset_;
177
178   // Zero is always the start of the animation.
179   if (trimmed <= 0)
180     return 0;
181
182   // Always return zero if we have no iterations.
183   if (!iterations_)
184     return 0;
185
186   // Don't attempt to trim if we have no duration.
187   if (curve_->Duration() <= 0)
188     return 0;
189
190   // If less than an iteration duration, just return trimmed.
191   if (trimmed < curve_->Duration())
192     return trimmed;
193
194   // If greater than or equal to the total duration, return iteration duration.
195   if (iterations_ >= 0 && trimmed >= curve_->Duration() * iterations_) {
196     if (alternates_direction_ && !(iterations_ % 2))
197       return 0;
198     return curve_->Duration();
199   }
200
201   // We need to know the current iteration if we're alternating.
202   int iteration = static_cast<int>(trimmed / curve_->Duration());
203
204   // Calculate x where trimmed = x + n * curve_->Duration() for some positive
205   // integer n.
206   trimmed = fmod(trimmed, curve_->Duration());
207
208   // If we're alternating and on an odd iteration, reverse the direction.
209   if (alternates_direction_ && iteration % 2 == 1)
210     return curve_->Duration() - trimmed;
211
212   return trimmed;
213 }
214
215 scoped_ptr<Animation> Animation::Clone() const {
216   return CloneAndInitialize(run_state_, start_time_);
217 }
218
219 scoped_ptr<Animation> Animation::CloneAndInitialize(RunState initial_run_state,
220                                                     double start_time) const {
221   scoped_ptr<Animation> to_return(
222       new Animation(curve_->Clone(), id_, group_, target_property_));
223   to_return->run_state_ = initial_run_state;
224   to_return->iterations_ = iterations_;
225   to_return->start_time_ = start_time;
226   to_return->pause_time_ = pause_time_;
227   to_return->total_paused_time_ = total_paused_time_;
228   to_return->time_offset_ = time_offset_;
229   to_return->alternates_direction_ = alternates_direction_;
230   DCHECK(!to_return->is_controlling_instance_);
231   to_return->is_controlling_instance_ = true;
232   return to_return.Pass();
233 }
234
235 void Animation::PushPropertiesTo(Animation* other) const {
236   // Currently, we only push changes due to pausing and resuming animations on
237   // the main thread.
238   if (run_state_ == Animation::Paused ||
239       other->run_state_ == Animation::Paused) {
240     other->run_state_ = run_state_;
241     other->pause_time_ = pause_time_;
242     other->total_paused_time_ = total_paused_time_;
243   }
244 }
245
246 }  // namespace cc