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.
7 #include "CCActiveAnimation.h"
9 #include "CCAnimationCurve.h"
10 #include "TraceEvent.h"
14 #include "base/string_util.h"
19 // This should match the RunState enum.
20 static const char* const s_runStateNames
[] = {
22 "WaitingForTargetAvailability",
23 "WaitingForStartTime",
31 COMPILE_ASSERT(static_cast<int>(cc::CCActiveAnimation::RunStateEnumSize
) == arraysize(s_runStateNames
), RunState_names_match_enum
);
33 // This should match the TargetProperty enum.
34 static const char* const s_targetPropertyNames
[] = {
39 COMPILE_ASSERT(static_cast<int>(cc::CCActiveAnimation::TargetPropertyEnumSize
) == arraysize(s_targetPropertyNames
), TargetProperty_names_match_enum
);
45 PassOwnPtr
<CCActiveAnimation
> CCActiveAnimation::create(PassOwnPtr
<CCAnimationCurve
> curve
, int animationId
, int groupId
, TargetProperty targetProperty
)
47 return adoptPtr(new CCActiveAnimation(curve
, animationId
, groupId
, targetProperty
));
50 CCActiveAnimation::CCActiveAnimation(PassOwnPtr
<CCAnimationCurve
> curve
, int animationId
, int groupId
, TargetProperty targetProperty
)
54 , m_targetProperty(targetProperty
)
55 , m_runState(WaitingForTargetAvailability
)
58 , m_alternatesDirection(false)
60 , m_needsSynchronizedStartTime(false)
63 , m_totalPausedTime(0)
64 , m_isControllingInstance(false)
68 CCActiveAnimation::~CCActiveAnimation()
70 if (m_runState
== Running
|| m_runState
== Paused
)
71 setRunState(Aborted
, 0);
74 void CCActiveAnimation::setRunState(RunState runState
, double monotonicTime
)
80 base::snprintf(nameBuffer
, sizeof(nameBuffer
), "%s-%d%s", s_targetPropertyNames
[m_targetProperty
], m_group
, m_isControllingInstance
? "(impl)" : "");
82 bool isWaitingToStart
= m_runState
== WaitingForNextTick
83 || m_runState
== WaitingForTargetAvailability
84 || m_runState
== WaitingForStartTime
;
86 if (isWaitingToStart
&& runState
== Running
)
87 TRACE_EVENT_ASYNC_BEGIN1("cc", "CCActiveAnimation", this, "Name", TRACE_STR_COPY(nameBuffer
));
89 bool wasFinished
= isFinished();
91 const char* oldRunStateName
= s_runStateNames
[m_runState
];
93 if (runState
== Running
&& m_runState
== Paused
)
94 m_totalPausedTime
+= monotonicTime
- m_pauseTime
;
95 else if (runState
== Paused
)
96 m_pauseTime
= monotonicTime
;
97 m_runState
= runState
;
99 const char* newRunStateName
= s_runStateNames
[runState
];
101 if (!wasFinished
&& isFinished())
102 TRACE_EVENT_ASYNC_END0("cc", "CCActiveAnimation", this);
104 char stateBuffer
[256];
105 base::snprintf(stateBuffer
, sizeof(stateBuffer
), "%s->%s", oldRunStateName
, newRunStateName
);
107 TRACE_EVENT_INSTANT2("cc", "CCLayerAnimationController::setRunState", "Name", TRACE_STR_COPY(nameBuffer
), "State", TRACE_STR_COPY(stateBuffer
));
110 void CCActiveAnimation::suspend(double monotonicTime
)
112 setRunState(Paused
, monotonicTime
);
116 void CCActiveAnimation::resume(double monotonicTime
)
119 setRunState(Running
, monotonicTime
);
122 bool CCActiveAnimation::isFinishedAt(double monotonicTime
) const
127 if (m_needsSynchronizedStartTime
)
130 return m_runState
== Running
132 && m_iterations
* m_curve
->duration() <= monotonicTime
- startTime() - m_totalPausedTime
;
135 double CCActiveAnimation::trimTimeToCurrentIteration(double monotonicTime
) const
137 double trimmed
= monotonicTime
+ m_timeOffset
;
139 // If we're paused, time is 'stuck' at the pause time.
140 if (m_runState
== Paused
)
141 trimmed
= m_pauseTime
;
143 // Returned time should always be relative to the start time and should subtract
144 // all time spent paused.
145 trimmed
-= m_startTime
+ m_totalPausedTime
;
147 // Zero is always the start of the animation.
151 // Always return zero if we have no iterations.
155 // Don't attempt to trim if we have no duration.
156 if (m_curve
->duration() <= 0)
159 // If less than an iteration duration, just return trimmed.
160 if (trimmed
< m_curve
->duration())
163 // If greater than or equal to the total duration, return iteration duration.
164 if (m_iterations
>= 0 && trimmed
>= m_curve
->duration() * m_iterations
) {
165 if (m_alternatesDirection
&& !(m_iterations
% 2))
167 return m_curve
->duration();
170 // We need to know the current iteration if we're alternating.
171 int iteration
= static_cast<int>(trimmed
/ m_curve
->duration());
173 // Calculate x where trimmed = x + n * m_curve->duration() for some positive integer n.
174 trimmed
= fmod(trimmed
, m_curve
->duration());
176 // If we're alternating and on an odd iteration, reverse the direction.
177 if (m_alternatesDirection
&& iteration
% 2 == 1)
178 return m_curve
->duration() - trimmed
;
183 PassOwnPtr
<CCActiveAnimation
> CCActiveAnimation::clone(InstanceType instanceType
) const
185 return cloneAndInitialize(instanceType
, m_runState
, m_startTime
);
188 PassOwnPtr
<CCActiveAnimation
> CCActiveAnimation::cloneAndInitialize(InstanceType instanceType
, RunState initialRunState
, double startTime
) const
190 OwnPtr
<CCActiveAnimation
> toReturn(adoptPtr(new CCActiveAnimation(m_curve
->clone(), m_id
, m_group
, m_targetProperty
)));
191 toReturn
->m_runState
= initialRunState
;
192 toReturn
->m_iterations
= m_iterations
;
193 toReturn
->m_startTime
= startTime
;
194 toReturn
->m_pauseTime
= m_pauseTime
;
195 toReturn
->m_totalPausedTime
= m_totalPausedTime
;
196 toReturn
->m_timeOffset
= m_timeOffset
;
197 toReturn
->m_alternatesDirection
= m_alternatesDirection
;
198 toReturn
->m_isControllingInstance
= instanceType
== ControllingInstance
;
199 return toReturn
.release();
202 void CCActiveAnimation::pushPropertiesTo(CCActiveAnimation
* other
) const
204 // Currently, we only push changes due to pausing and resuming animations on the main thread.
205 if (m_runState
== CCActiveAnimation::Paused
|| other
->m_runState
== CCActiveAnimation::Paused
) {
206 other
->m_runState
= m_runState
;
207 other
->m_pauseTime
= m_pauseTime
;
208 other
->m_totalPausedTime
= m_totalPausedTime
;