Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(118)

Side by Side Diff: Source/core/frame/animation/AnimationBase.cpp

Issue 139273007: Web Animations: Remove legacy animations engine. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fix TestExpectations. Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "config.h"
30 #include "core/frame/animation/AnimationBase.h"
31
32 #include "core/frame/animation/AnimationControllerPrivate.h"
33 #include "core/frame/animation/CompositeAnimation.h"
34 #include "core/rendering/RenderBox.h"
35 #include "platform/animation/AnimationUtilities.h"
36 #include "platform/animation/TimingFunction.h"
37 #include <algorithm>
38
39 using namespace std;
40
41 namespace WebCore {
42
43 AnimationBase::AnimationBase(const CSSAnimationData* transition, RenderObject& r enderer, CompositeAnimation* compAnim)
44 : m_animState(AnimationStateNew)
45 , m_isAccelerated(false)
46 , m_transformFunctionListValid(false)
47 , m_filterFunctionListsMatch(false)
48 , m_startTime(0)
49 , m_pauseTime(-1)
50 , m_requestedStartTime(0)
51 , m_totalDuration(-1)
52 , m_nextIterationDuration(-1)
53 , m_object(&renderer)
54 , m_animation(const_cast<CSSAnimationData*>(transition))
55 , m_compAnim(compAnim)
56 {
57 // Compute the total duration
58 if (m_animation->iterationCount() > 0)
59 m_totalDuration = m_animation->duration() * m_animation->iterationCount( );
60 }
61
62 void AnimationBase::setNeedsStyleRecalc(Node* node)
63 {
64 if (node)
65 node->setNeedsStyleRecalc(LocalStyleChange);
66 }
67
68 double AnimationBase::duration() const
69 {
70 return m_animation->duration();
71 }
72
73 bool AnimationBase::playStatePlaying() const
74 {
75 return m_animation->playState() == AnimPlayStatePlaying;
76 }
77
78 void AnimationBase::updateStateMachine(AnimStateInput input, double param)
79 {
80 if (!m_compAnim)
81 return;
82
83 // If we get AnimationStateInputRestartAnimation then we force a new animati on, regardless of state.
84 if (input == AnimationStateInputMakeNew) {
85 if (m_animState == AnimationStateStartWaitStyleAvailable)
86 m_compAnim->animationController()->removeFromAnimationsWaitingForSty le(this);
87 m_animState = AnimationStateNew;
88 m_startTime = 0;
89 m_pauseTime = -1;
90 m_requestedStartTime = 0;
91 m_nextIterationDuration = -1;
92 endAnimation();
93 return;
94 }
95
96 if (input == AnimationStateInputRestartAnimation) {
97 if (m_animState == AnimationStateStartWaitStyleAvailable)
98 m_compAnim->animationController()->removeFromAnimationsWaitingForSty le(this);
99 m_animState = AnimationStateNew;
100 m_startTime = 0;
101 m_pauseTime = -1;
102 m_requestedStartTime = 0;
103 m_nextIterationDuration = -1;
104 endAnimation();
105
106 if (!paused())
107 updateStateMachine(AnimationStateInputStartAnimation, -1);
108 return;
109 }
110
111 if (input == AnimationStateInputEndAnimation) {
112 if (m_animState == AnimationStateStartWaitStyleAvailable)
113 m_compAnim->animationController()->removeFromAnimationsWaitingForSty le(this);
114 m_animState = AnimationStateDone;
115 endAnimation();
116 return;
117 }
118
119 if (input == AnimationStateInputPauseOverride) {
120 if (m_animState == AnimationStateStartWaitResponse) {
121 // If we are in AnimationStateStartWaitResponse, the animation will get canceled before
122 // we get a response, so move to the next state.
123 endAnimation();
124 updateStateMachine(AnimationStateInputStartTimeSet, beginAnimationUp dateTime());
125 }
126 return;
127 }
128
129 if (input == AnimationStateInputResumeOverride) {
130 if (m_animState == AnimationStateLooping || m_animState == AnimationStat eEnding) {
131 // Start the animation
132 startAnimation(beginAnimationUpdateTime() - m_startTime);
133 }
134 return;
135 }
136
137 // Execute state machine
138 switch (m_animState) {
139 case AnimationStateNew:
140 ASSERT(input == AnimationStateInputStartAnimation || input == Animat ionStateInputPlayStateRunning || input == AnimationStateInputPlayStatePaused);
141 if (input == AnimationStateInputStartAnimation || input == Animation StateInputPlayStateRunning) {
142 m_requestedStartTime = beginAnimationUpdateTime();
143 m_animState = AnimationStateStartWaitTimer;
144 }
145 break;
146 case AnimationStateStartWaitTimer:
147 ASSERT(input == AnimationStateInputStartTimerFired || input == Anima tionStateInputPlayStatePaused);
148
149 if (input == AnimationStateInputStartTimerFired) {
150 ASSERT(param >= 0);
151 // Start timer has fired, tell the animation to start and wait f or it to respond with start time
152 m_animState = AnimationStateStartWaitStyleAvailable;
153 m_compAnim->animationController()->addToAnimationsWaitingForStyl e(this);
154
155 // Trigger a render so we can start the animation
156 if (m_object)
157 m_compAnim->animationController()->addNodeChangeToDispatch(m _object->node());
158 } else {
159 ASSERT(!paused());
160 // We're waiting for the start timer to fire and we got a pause. Cancel the timer, pause and wait
161 m_pauseTime = beginAnimationUpdateTime();
162 m_animState = AnimationStatePausedWaitTimer;
163 }
164 break;
165 case AnimationStateStartWaitStyleAvailable:
166 ASSERT(input == AnimationStateInputStyleAvailable || input == Animat ionStateInputPlayStatePaused);
167
168 if (input == AnimationStateInputStyleAvailable) {
169 // Start timer has fired, tell the animation to start and wait f or it to respond with start time
170 m_animState = AnimationStateStartWaitResponse;
171
172 overrideAnimations();
173
174 // Start the animation
175 if (overridden()) {
176 m_animState = AnimationStateStartWaitResponse;
177 updateStateMachine(AnimationStateInputStartTimeSet, beginAni mationUpdateTime());
178 } else {
179 double timeOffset = 0;
180 // If the value for 'animation-delay' is negative then the a nimation appears to have started in the past.
181 if (m_animation->delay() < 0)
182 timeOffset = -m_animation->delay();
183 startAnimation(timeOffset);
184 m_compAnim->animationController()->addToAnimationsWaitingFor StartTimeResponse(this, isAccelerated());
185 }
186 } else {
187 // We're waiting for the style to be available and we got a paus e. Pause and wait
188 m_pauseTime = beginAnimationUpdateTime();
189 m_animState = AnimationStatePausedWaitStyleAvailable;
190 }
191 break;
192 case AnimationStateStartWaitResponse:
193 ASSERT(input == AnimationStateInputStartTimeSet || input == Animatio nStateInputPlayStatePaused);
194
195 if (input == AnimationStateInputStartTimeSet) {
196 ASSERT(param >= 0);
197 // We have a start time, set it, unless the startTime is already set
198 if (m_startTime <= 0) {
199 m_startTime = param;
200 // If the value for 'animation-delay' is negative then the a nimation appears to have started in the past.
201 if (m_animation->delay() < 0)
202 m_startTime += m_animation->delay();
203 }
204
205 // Now that we know the start time, fire the start event.
206 onAnimationStart(0); // The elapsedTime is 0.
207
208 // Decide whether to go into looping or ending state
209 goIntoEndingOrLoopingState();
210
211 // Dispatch updateStyleIfNeeded so we can start the animation
212 if (m_object)
213 m_compAnim->animationController()->addNodeChangeToDispatch(m _object->node());
214 } else {
215 // We are pausing while waiting for a start response. Cancel the animation and wait. When
216 // we unpause, we will act as though the start timer just fired
217 m_pauseTime = beginAnimationUpdateTime();
218 pauseAnimation(beginAnimationUpdateTime() - m_startTime);
219 m_animState = AnimationStatePausedWaitResponse;
220 }
221 break;
222 case AnimationStateLooping:
223 ASSERT(input == AnimationStateInputLoopTimerFired || input == Animat ionStateInputPlayStatePaused);
224
225 if (input == AnimationStateInputLoopTimerFired) {
226 ASSERT(param >= 0);
227 // Loop timer fired, loop again or end.
228 onAnimationIteration(param);
229
230 // Decide whether to go into looping or ending state
231 goIntoEndingOrLoopingState();
232 } else {
233 // We are pausing while running. Cancel the animation and wait
234 m_pauseTime = beginAnimationUpdateTime();
235 pauseAnimation(beginAnimationUpdateTime() - m_startTime);
236 m_animState = AnimationStatePausedRun;
237 }
238 break;
239 case AnimationStateEnding:
240 #if !LOG_DISABLED
241 if (input != AnimationStateInputEndTimerFired && input != AnimationS tateInputPlayStatePaused)
242 WTF_LOG_ERROR("State is AnimationStateEnding, but input is not A nimationStateInputEndTimerFired or AnimationStateInputPlayStatePaused. It is %d. ", input);
243 #endif
244 if (input == AnimationStateInputEndTimerFired) {
245
246 ASSERT(param >= 0);
247 // End timer fired, finish up
248 onAnimationEnd(param);
249
250 m_animState = AnimationStateDone;
251
252 if (m_object) {
253 if (m_animation->fillsForwards())
254 m_animState = AnimationStateFillingForwards;
255 else
256 resumeOverriddenAnimations();
257
258 // Fire off another style change so we can set the final val ue
259 m_compAnim->animationController()->addNodeChangeToDispatch(m _object->node());
260 }
261 } else {
262 // We are pausing while running. Cancel the animation and wait
263 m_pauseTime = beginAnimationUpdateTime();
264 pauseAnimation(beginAnimationUpdateTime() - m_startTime);
265 m_animState = AnimationStatePausedRun;
266 }
267 // |this| may be deleted here
268 break;
269 case AnimationStatePausedWaitTimer:
270 ASSERT(input == AnimationStateInputPlayStateRunning);
271 ASSERT(paused());
272 // Update the times
273 m_startTime += beginAnimationUpdateTime() - m_pauseTime;
274 m_pauseTime = -1;
275
276 // we were waiting for the start timer to fire, go back and wait aga in
277 m_animState = AnimationStateNew;
278 updateStateMachine(AnimationStateInputStartAnimation, 0);
279 break;
280 case AnimationStatePausedWaitResponse:
281 case AnimationStatePausedWaitStyleAvailable:
282 case AnimationStatePausedRun:
283 // We treat these two cases the same. The only difference is that, w hen we are in
284 // AnimationStatePausedWaitResponse, we don't yet have a valid start Time, so we send 0 to startAnimation.
285 // When the AnimationStateInputStartTimeSet comes in and we were in AnimationStatePausedRun, we will notice
286 // that we have already set the startTime and will ignore it.
287 ASSERT(input == AnimationStateInputPlayStateRunning || input == Anim ationStateInputStartTimeSet || input == AnimationStateInputStyleAvailable);
288 ASSERT(paused());
289
290 if (input == AnimationStateInputPlayStateRunning) {
291 // Update the times
292 if (m_animState == AnimationStatePausedRun)
293 m_startTime += beginAnimationUpdateTime() - m_pauseTime;
294 else
295 m_startTime = 0;
296 m_pauseTime = -1;
297
298 if (m_animState == AnimationStatePausedWaitStyleAvailable)
299 m_animState = AnimationStateStartWaitStyleAvailable;
300 else {
301 // We were either running or waiting for a begin time respon se from the animation.
302 // Either way we need to restart the animation (possibly wit h an offset if we
303 // had already been running) and wait for it to start.
304 m_animState = AnimationStateStartWaitResponse;
305
306 // Start the animation
307 if (overridden()) {
308 updateStateMachine(AnimationStateInputStartTimeSet, begi nAnimationUpdateTime());
309 } else {
310 startAnimation(beginAnimationUpdateTime() - m_startTime) ;
311 m_compAnim->animationController()->addToAnimationsWaitin gForStartTimeResponse(this, isAccelerated());
312 }
313 }
314 break;
315 }
316
317 if (input == AnimationStateInputStartTimeSet) {
318 ASSERT(m_animState == AnimationStatePausedWaitResponse);
319
320 // We are paused but we got the callback that notifies us that a n accelerated animation started.
321 // We ignore the start time and just move into the paused-run st ate.
322 m_animState = AnimationStatePausedRun;
323 ASSERT(m_startTime == 0);
324 m_startTime = param;
325 m_pauseTime += m_startTime;
326 break;
327 }
328
329 ASSERT(m_animState == AnimationStatePausedWaitStyleAvailable);
330 // We are paused but we got the callback that notifies us that style has been updated.
331 // We move to the AnimationStatePausedWaitResponse state
332 m_animState = AnimationStatePausedWaitResponse;
333 overrideAnimations();
334 break;
335 case AnimationStateFillingForwards:
336 case AnimationStateDone:
337 // We're done. Stay in this state until we are deleted
338 break;
339 }
340 }
341
342 void AnimationBase::fireAnimationEventsIfNeeded()
343 {
344 if (!m_compAnim)
345 return;
346
347 // If we are waiting for the delay time to expire and it has, go to the next state
348 if (m_animState != AnimationStateStartWaitTimer && m_animState != AnimationS tateLooping && m_animState != AnimationStateEnding)
349 return;
350
351 // We have to make sure to keep a ref to the this pointer, because it could get destroyed
352 // during an animation callback that might get called. Since the owner is a CompositeAnimation
353 // and it ref counts this object, we will keep a ref to that instead. That w ay the AnimationBase
354 // can still access the resources of its CompositeAnimation as needed.
355 RefPtr<AnimationBase> protector(this);
356 RefPtr<CompositeAnimation> compProtector(m_compAnim);
357
358 // Check for start timeout
359 if (m_animState == AnimationStateStartWaitTimer) {
360 if (beginAnimationUpdateTime() - m_requestedStartTime >= m_animation->de lay())
361 updateStateMachine(AnimationStateInputStartTimerFired, 0);
362 return;
363 }
364
365 double elapsedDuration = getElapsedTime();
366
367 // Check for end timeout
368 if (m_totalDuration >= 0 && elapsedDuration >= m_totalDuration) {
369 // We may still be in AnimationStateLooping if we've managed to skip a
370 // whole iteration, in which case we should jump to the end state.
371 m_animState = AnimationStateEnding;
372
373 // Fire an end event
374 updateStateMachine(AnimationStateInputEndTimerFired, m_totalDuration);
375 } else {
376 // Check for iteration timeout
377 if (m_nextIterationDuration < 0) {
378 // Hasn't been set yet, set it
379 double durationLeft = m_animation->duration() - fmod(elapsedDuration , m_animation->duration());
380 m_nextIterationDuration = elapsedDuration + durationLeft;
381 }
382
383 if (elapsedDuration >= m_nextIterationDuration) {
384 // Set to the next iteration
385 double previous = m_nextIterationDuration;
386 double durationLeft = m_animation->duration() - fmod(elapsedDuration , m_animation->duration());
387 m_nextIterationDuration = elapsedDuration + durationLeft;
388
389 // Send the event
390 updateStateMachine(AnimationStateInputLoopTimerFired, previous);
391 }
392 }
393 }
394
395 void AnimationBase::updatePlayState(EAnimPlayState playState)
396 {
397 if (!m_compAnim)
398 return;
399
400 // Set the state machine to the desired state.
401 bool pause = playState == AnimPlayStatePaused;
402
403 if (pause == paused() && !isNew())
404 return;
405
406 updateStateMachine(pause ? AnimationStateInputPlayStatePaused : AnimationSt ateInputPlayStateRunning, -1);
407 }
408
409 double AnimationBase::timeToNextService()
410 {
411 // Returns the time at which next service is required. -1 means no service i s required. 0 means
412 // service is required now, and > 0 means service is required that many seco nds in the future.
413 if (paused() || isNew() || m_animState == AnimationStateFillingForwards)
414 return -1;
415
416 if (m_animState == AnimationStateStartWaitTimer) {
417 double timeFromNow = m_animation->delay() - (beginAnimationUpdateTime() - m_requestedStartTime);
418 return max(timeFromNow, 0.0);
419 }
420
421 fireAnimationEventsIfNeeded();
422
423 // In all other cases, we need service right away.
424 return 0;
425 }
426
427 // Compute the fractional time, taking into account direction.
428 // There is no need to worry about iterations, we assume that we would have
429 // short circuited above if we were done.
430
431 double AnimationBase::fractionalTime(double scale, double elapsedTime, double of fset) const
432 {
433 double fractionalTime = m_animation->duration() ? (elapsedTime / m_animation ->duration()) : 1;
434 // FIXME: startTime can be before the current animation "frame" time. This i s to sync with the frame time
435 // concept in AnimationTimeController. So we need to somehow sync the two. U ntil then, the possible
436 // error is small and will probably not be noticeable. Until we fix this, re move the assert.
437 // https://bugs.webkit.org/show_bug.cgi?id=52037
438 // ASSERT(fractionalTime >= 0);
439 if (fractionalTime < 0)
440 fractionalTime = 0;
441
442 int integralTime = static_cast<int>(fractionalTime);
443 const int integralIterationCount = static_cast<int>(m_animation->iterationCo unt());
444 const bool iterationCountHasFractional = m_animation->iterationCount() - int egralIterationCount;
445 if (m_animation->iterationCount() != CSSAnimationData::IterationCountInfinit e && !iterationCountHasFractional)
446 integralTime = min(integralTime, integralIterationCount - 1);
447
448 fractionalTime -= integralTime;
449
450 // Thie method can be called with an elapsedTime which very slightly
451 // exceeds the end of the animation. In this case, clamp the
452 // fractionalTime.
453 if (fractionalTime > 1)
454 fractionalTime = 1;
455 ASSERT(fractionalTime >= 0 && fractionalTime <= 1);
456
457 if (((m_animation->direction() == CSSAnimationData::AnimationDirectionAltern ate) && (integralTime & 1))
458 || ((m_animation->direction() == CSSAnimationData::AnimationDirectionAlt ernateReverse) && !(integralTime & 1))
459 || m_animation->direction() == CSSAnimationData::AnimationDirectionRever se)
460 fractionalTime = 1 - fractionalTime;
461
462 fractionalTime -= offset;
463 // Note that if fractionalTime == 0 here, scale may be infinity, but in
464 // this case we don't need to apply scale anyway.
465 if (scale != 1.0 && fractionalTime) {
466 ASSERT(scale >= 0 && !std::isinf(scale));
467 fractionalTime *= scale;
468 }
469
470 ASSERT(fractionalTime >= 0 && fractionalTime <= 1);
471 return fractionalTime;
472 }
473
474 double AnimationBase::progress(double scale, double offset, const TimingFunction * timingFunction) const
475 {
476 if (preActive())
477 return 0;
478
479 double dur = m_animation->duration();
480 if (m_animation->iterationCount() > 0)
481 dur *= m_animation->iterationCount();
482
483 if (postActive() || !m_animation->duration())
484 return 1.0;
485
486 double elapsedTime = getElapsedTime();
487 if (m_animation->iterationCount() > 0 && elapsedTime >= dur) {
488 const int integralIterationCount = static_cast<int>(m_animation->iterati onCount());
489 const bool iterationCountHasFractional = m_animation->iterationCount() - integralIterationCount;
490 return (integralIterationCount % 2 || iterationCountHasFractional) ? 1.0 : 0.0;
491 }
492
493 const double fractionalTime = this->fractionalTime(scale, elapsedTime, offse t);
494
495 if (!timingFunction)
496 timingFunction = m_animation->timingFunction();
497
498 return timingFunction->evaluate(fractionalTime, accuracyForDuration(m_animat ion->duration()));
499 }
500
501 void AnimationBase::getTimeToNextEvent(double& time, bool& isLooping) const
502 {
503 if (postActive()) {
504 time = -1;
505 isLooping = false;
506 return;
507 }
508
509 // Decide when the end or loop event needs to fire
510 const double elapsedDuration = getElapsedTime();
511 double durationLeft = 0;
512 double nextIterationTime = m_totalDuration;
513
514 if (m_totalDuration < 0 || elapsedDuration < m_totalDuration) {
515 durationLeft = m_animation->duration() > 0 ? (m_animation->duration() - fmod(elapsedDuration, m_animation->duration())) : 0;
516 nextIterationTime = elapsedDuration + durationLeft;
517 }
518
519 if (m_totalDuration < 0 || nextIterationTime < m_totalDuration) {
520 // We are not at the end yet
521 ASSERT(m_totalDuration < 0 || nextIterationTime > 0);
522 isLooping = true;
523 } else {
524 // We are at the end
525 isLooping = false;
526 }
527
528 time = durationLeft;
529 }
530
531 void AnimationBase::goIntoEndingOrLoopingState()
532 {
533 double t;
534 bool isLooping;
535 getTimeToNextEvent(t, isLooping);
536 m_animState = isLooping ? AnimationStateLooping : AnimationStateEnding;
537 }
538
539 void AnimationBase::freezeAtTime(double t)
540 {
541 if (!m_compAnim)
542 return;
543
544 if (!m_startTime) {
545 // If we haven't started yet, make it as if we started.
546 m_animState = AnimationStateStartWaitResponse;
547 onAnimationStartResponse(beginAnimationUpdateTime());
548 }
549
550 ASSERT(m_startTime); // if m_startTime is zero, we haven't started ye t, so we'll get a bad pause time.
551 if (t <= m_animation->delay())
552 m_pauseTime = m_startTime;
553 else
554 m_pauseTime = m_startTime + t - m_animation->delay();
555
556 // It is possible that m_isAccelerated is true and m_object->compositingStat e() is NotComposited, because of style change.
557 // So, both conditions need to be checked.
558 if (m_object && m_object->compositingState() == PaintsIntoOwnBacking && isAc celerated())
559 pauseAnimation(t);
560 }
561
562 double AnimationBase::beginAnimationUpdateTime() const
563 {
564 if (!m_compAnim)
565 return 0;
566
567 return m_compAnim->animationController()->beginAnimationUpdateTime();
568 }
569
570 double AnimationBase::getElapsedTime() const
571 {
572 ASSERT(!postActive());
573 if (paused())
574 return m_pauseTime - m_startTime;
575 if (m_startTime <= 0)
576 return 0;
577
578 double elapsedTime = beginAnimationUpdateTime() - m_startTime;
579 // It's possible for the start time to be ahead of the last update time
580 // if the compositor has just sent notification for the start of an
581 // accelerated animation.
582 return max(elapsedTime, 0.0);
583 }
584
585 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/frame/animation/AnimationBase.h ('k') | Source/core/frame/animation/AnimationController.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698