Changeset 39211 in webkit
- Timestamp:
- Dec 11, 2008, 8:24:32 AM (17 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r39209 r39211 1 2008-12-10 Chris Marrin <cmarrin@apple.com> 2 3 Reviewed by Dave Hyatt. 4 5 Fixed https://bugs.webkit.org/show_bug.cgi?id=22738 6 7 This gets rid of the per-animation timers which were used when an animation 8 started, ended and looped. Their job is now done by the main AnimationController's 9 timer. It is now set to fire as needed. For instance, if there is a delay, it will 10 fire after the delay time and then every 30ms to run the animation. The start, loop 11 and end events are generated as needed during the firing of this timer. 12 13 I had to add one more bit of code. When animation timers used to fire the animation events. 14 This would always happen from the RunLoop, so any style changes that happened in the 15 event handler would get picked up on the next updateRendering() call. But now the start 16 event is generated during the styleIsAvailable() call, which is in the middle of the 17 updateRendering() cycle. And calling an event handler in the middle of updateRendering() 18 is not allowed and causes style changes to get missed. We already have a mechanism in 19 AnimationController to defer updateRendering() calls. So I added logic to defer all 20 event handling to there. Now, I put any request for event handling into a list and ask 21 for a deferred updateRendering() call. When that deferred timer fires, I go through that 22 list, send all the events and then call updateRendering(). 23 24 * page/animation/AnimationBase.cpp: 25 (WebCore::AnimationBase::AnimationBase): 26 (WebCore::AnimationBase::updateStateMachine): 27 (WebCore::AnimationBase::fireAnimationEventsIfNeeded): 28 (WebCore::AnimationBase::willNeedService): 29 (WebCore::AnimationBase::goIntoEndingOrLoopingState): 30 * page/animation/AnimationBase.h: 31 * page/animation/AnimationController.cpp: 32 (WebCore::AnimationControllerPrivate::updateAnimationTimer): 33 (WebCore::AnimationControllerPrivate::updateRenderingDispatcherFired): 34 (WebCore::AnimationControllerPrivate::addEventToDispatch): 35 (WebCore::AnimationControllerPrivate::animationTimerFired): 36 (WebCore::AnimationController::addEventToDispatch): 37 * page/animation/AnimationController.h: 38 * page/animation/CompositeAnimation.cpp: 39 (WebCore::CompositeAnimationPrivate::updateTransitions): 40 (WebCore::CompositeAnimationPrivate::willNeedService): 41 (WebCore::CompositeAnimationPrivate::getAnimationForProperty): 42 (WebCore::CompositeAnimation::willNeedService): 43 (WebCore::CompositeAnimation::getAnimationForProperty): 44 * page/animation/CompositeAnimation.h: 45 * page/animation/ImplicitAnimation.cpp: 46 (WebCore::ImplicitAnimation::animate): 47 (WebCore::ImplicitAnimation::onAnimationEnd): 48 (WebCore::ImplicitAnimation::sendTransitionEvent): 49 * page/animation/ImplicitAnimation.h: 50 * page/animation/KeyframeAnimation.cpp: 51 (WebCore::KeyframeAnimation::animate): 52 (WebCore::KeyframeAnimation::sendAnimationEvent): 53 * page/animation/KeyframeAnimation.h: 54 (WebCore::KeyframeAnimation::setUnanimatedStyle): 55 1 56 2008-12-11 Simon Hausmann <simon.hausmann@nokia.com> 2 57 -
trunk/WebCore/page/animation/AnimationBase.cpp
r39092 r39211 62 62 UnitBezier bezier(p1x, p1y, p2x, p2y); 63 63 return bezier.solve(t, solveEpsilon(duration)); 64 }65 66 void AnimationTimerCallback::timerFired(Timer<AnimationTimerBase>*)67 {68 m_anim->animationTimerCallbackFired(m_eventType, m_elapsedTime);69 64 } 70 65 … … 385 380 , m_startTime(0) 386 381 , m_pauseTime(-1) 382 , m_requestedStartTime(0) 387 383 , m_object(renderer) 388 , m_animationTimerCallback(const_cast<AnimationBase*>(this))389 384 , m_animation(const_cast<Animation*>(transition)) 390 385 , m_compAnim(compAnim) 391 386 , m_transformFunctionListValid(false) 392 { 387 , m_nextIterationDuration(-1) 388 { 389 // Compute the total duration 390 m_totalDuration = -1; 391 if (m_animation->iterationCount() > 0) 392 m_totalDuration = m_animation->duration() * m_animation->iterationCount(); 393 393 } 394 394 … … 499 499 m_startTime = 0; 500 500 m_pauseTime = -1; 501 m_requestedStartTime = 0; 502 m_nextIterationDuration = -1; 501 503 m_waitedForResponse = false; 502 504 endAnimation(false); … … 505 507 506 508 if (input == AnimationStateInputRestartAnimation) { 507 cancelTimers();508 509 if (m_animState == AnimationStateStartWaitStyleAvailable) 509 510 m_compAnim->setWaitingForStyleAvailable(false); … … 511 512 m_startTime = 0; 512 513 m_pauseTime = -1; 514 m_requestedStartTime = 0; 515 m_nextIterationDuration = -1; 513 516 endAnimation(false); 514 517 … … 519 522 520 523 if (input == AnimationStateInputEndAnimation) { 521 cancelTimers();522 524 if (m_animState == AnimationStateStartWaitStyleAvailable) 523 525 m_compAnim->setWaitingForStyleAvailable(false); … … 550 552 ASSERT(input == AnimationStateInputStartAnimation || input == AnimationStateInputPlayStateRunnning || input == AnimationStateInputPlayStatePaused); 551 553 if (input == AnimationStateInputStartAnimation || input == AnimationStateInputPlayStateRunnning) { 552 // Set the start timer to the initial delay (0 if no delay)553 554 m_waitedForResponse = false; 555 m_requestedStartTime = currentTime(); 554 556 m_animState = AnimationStateStartWaitTimer; 555 m_animationTimerCallback.startTimer(m_animation->delay(), eventNames().webkitAnimationStartEvent, m_animation->delay());556 557 } 557 558 break; … … 572 573 // We're waiting for the start timer to fire and we got a pause. Cancel the timer, pause and wait 573 574 m_pauseTime = currentTime(); 574 cancelTimers();575 575 m_animState = AnimationStatePausedWaitTimer; 576 576 } … … 606 606 m_startTime = param; 607 607 608 // Decide whe n the end or loop event needs to fire609 primeEventTimers();608 // Decide whether to go into looping or ending state 609 goIntoEndingOrLoopingState(); 610 610 611 611 // Trigger a render so we can start the animation … … 629 629 // Loop timer fired, loop again or end. 630 630 onAnimationIteration(param); 631 primeEventTimers(); 631 632 // Decide whether to go into looping or ending state 633 goIntoEndingOrLoopingState(); 632 634 } else { 633 635 // We are pausing while running. Cancel the animation and wait 634 636 m_pauseTime = currentTime(); 635 cancelTimers();636 637 endAnimation(false); 637 638 m_animState = AnimationStatePausedRun; … … 658 659 // We are pausing while running. Cancel the animation and wait 659 660 m_pauseTime = currentTime(); 660 cancelTimers();661 661 endAnimation(false); 662 662 m_animState = AnimationStatePausedRun; … … 706 706 } 707 707 708 void AnimationBase::animationTimerCallbackFired(const AtomicString& eventType, double elapsedTime) 709 { 708 void AnimationBase::fireAnimationEventsIfNeeded() 709 { 710 // If we are waiting for the delay time to expire and it has, go to the next state 711 if (m_animState != AnimationStateStartWaitTimer && m_animState != AnimationStateLooping && m_animState != AnimationStateEnding) 712 return; 713 710 714 // We have to make sure to keep a ref to the this pointer, because it could get destroyed 711 715 // during an animation callback that might get called. Since the owner is a CompositeAnimation … … 715 719 RefPtr<CompositeAnimation> compProtector(m_compAnim); 716 720 717 ASSERT(m_object->document() && !m_object->document()->inPageCache()); 718 719 // FIXME: use an enum 720 if (eventType == eventNames().webkitAnimationStartEvent) 721 updateStateMachine(AnimationStateInputStartTimerFired, elapsedTime); 722 else if (eventType == eventNames().webkitAnimationIterationEvent) 723 updateStateMachine(AnimationStateInputLoopTimerFired, elapsedTime); 724 else if (eventType == eventNames().webkitAnimationEndEvent) { 725 updateStateMachine(AnimationStateInputEndTimerFired, elapsedTime); 721 // Check for start timeout 722 if (m_animState == AnimationStateStartWaitTimer) { 723 if (currentTime() - m_requestedStartTime >= m_animation->delay()) 724 updateStateMachine(AnimationStateInputStartTimerFired, 0); 725 return; 726 } 727 728 double elapsedDuration = currentTime() - m_startTime; 729 ASSERT(elapsedDuration >= 0); 730 731 // Check for end timeout 732 if (m_totalDuration > 0 && elapsedDuration >= m_totalDuration) { 733 // Fire an end event 734 updateStateMachine(AnimationStateInputEndTimerFired, m_totalDuration); 735 } 736 else { 737 // Check for iteration timeout 738 if (m_nextIterationDuration < 0) { 739 // Hasn't been set yet, set it 740 double durationLeft = m_animation->duration() - fmod(elapsedDuration, m_animation->duration()); 741 m_nextIterationDuration = elapsedDuration + durationLeft; 742 } 743 744 if (elapsedDuration >= m_nextIterationDuration) { 745 // Set to the next iteration 746 double previous = m_nextIterationDuration; 747 double durationLeft = m_animation->duration() - fmod(elapsedDuration, m_animation->duration()); 748 m_nextIterationDuration = elapsedDuration + durationLeft; 749 750 // Send the event 751 updateStateMachine(AnimationStateInputLoopTimerFired, previous); 752 } 726 753 } 727 754 } … … 731 758 if (paused() == run || isNew()) 732 759 updateStateMachine(run ? AnimationStateInputPlayStateRunnning : AnimationStateInputPlayStatePaused, -1); 760 } 761 762 double AnimationBase::willNeedService() const 763 { 764 // Returns the time at which next service is required. -1 means no service is required. 0 means 765 // service is required now, and > 0 means service is required that many seconds in the future. 766 if (paused() || isNew()) 767 return -1; 768 769 if (m_animState == AnimationStateStartWaitTimer) { 770 double timeFromNow = m_animation->delay() - (currentTime() - m_requestedStartTime); 771 return (float) ((timeFromNow > 0) ? timeFromNow : 0); 772 } 773 774 // In all other cases, we need service right away. 775 return 0; 733 776 } 734 777 … … 777 820 } 778 821 779 void AnimationBase:: primeEventTimers()822 void AnimationBase::goIntoEndingOrLoopingState() 780 823 { 781 824 // Decide when the end or loop event needs to fire 782 double ct = currentTime();783 const double elapsedDuration = ct - m_startTime;784 ASSERT(elapsedDuration >= 0);785 786 825 double totalDuration = -1; 787 826 if (m_animation->iterationCount() > 0) 788 827 totalDuration = m_animation->duration() * m_animation->iterationCount(); 789 828 829 const double elapsedDuration = currentTime() - m_startTime; 830 ASSERT(elapsedDuration >= 0); 790 831 double durationLeft = 0; 791 832 double nextIterationTime = totalDuration; 833 792 834 if (totalDuration < 0 || elapsedDuration < totalDuration) { 793 835 durationLeft = m_animation->duration() - fmod(elapsedDuration, m_animation->duration()); … … 795 837 } 796 838 797 // At this point, we may have 0 durationLeft, if we've gotten the event late and we are already798 // past totalDuration. In this case we still fire an end timer before processing the end.799 // This defers the call to sendAnimationEvents to avoid re-entrant calls that destroy800 // the RenderObject, and therefore |this| before we're done with it.801 839 if (totalDuration < 0 || nextIterationTime < totalDuration) { 802 // We are not at the end yet , send a loop event840 // We are not at the end yet 803 841 ASSERT(nextIterationTime > 0); 804 842 m_animState = AnimationStateLooping; 805 m_animationTimerCallback.startTimer(durationLeft, eventNames().webkitAnimationIterationEvent, nextIterationTime);806 843 } else { 807 // We are at the end , send an end event844 // We are at the end 808 845 m_animState = AnimationStateEnding; 809 m_animationTimerCallback.startTimer(durationLeft, eventNames().webkitAnimationEndEvent, nextIterationTime);810 846 } 811 847 } -
trunk/WebCore/page/animation/AnimationBase.h
r38768 r39211 31 31 32 32 #include "AtomicString.h" 33 #include "Timer.h"34 33 #include <wtf/HashMap.h> 35 34 … … 46 45 class TimingFunction; 47 46 48 class AnimationTimerBase {49 public:50 AnimationTimerBase(AnimationBase* anim)51 : m_timer(this, &AnimationTimerBase::timerFired)52 , m_anim(anim)53 {54 m_timer.startOneShot(0);55 }56 57 virtual ~AnimationTimerBase() { }58 59 void startTimer(double timeout = 0)60 {61 m_timer.startOneShot(timeout);62 }63 64 void cancelTimer()65 {66 m_timer.stop();67 }68 69 virtual void timerFired(Timer<AnimationTimerBase>*) = 0;70 71 private:72 Timer<AnimationTimerBase> m_timer;73 74 protected:75 AnimationBase* m_anim;76 };77 78 class AnimationTimerCallback : public AnimationTimerBase {79 public:80 AnimationTimerCallback(AnimationBase* anim)81 : AnimationTimerBase(anim)82 , m_elapsedTime(0)83 {84 }85 86 virtual ~AnimationTimerCallback() { }87 88 virtual void timerFired(Timer<AnimationTimerBase>*);89 90 void startTimer(double timeout, const AtomicString& eventType, double elapsedTime)91 {92 m_eventType = eventType;93 m_elapsedTime = elapsedTime;94 AnimationTimerBase::startTimer(timeout);95 }96 97 private:98 AtomicString m_eventType;99 double m_elapsedTime;100 };101 102 47 class AnimationBase : public RefCounted<AnimationBase> { 103 48 friend class CompositeAnimationPrivate; … … 112 57 double startTime() const { return m_startTime; } 113 58 double duration() const; 114 115 void cancelTimers()116 {117 m_animationTimerCallback.cancelTimer();118 }119 59 120 60 // Animations and Transitions go through the states below. When entering the STARTED state … … 179 119 // (e.g. a software animation) 180 120 void setAnimating(bool inAnimating = true) { m_isAnimating = inAnimating; } 181 bool isAnimating() const { return m_isAnimating; }121 double willNeedService() const; 182 122 183 123 double progress(double scale, double offset, const TimingFunction*) const; … … 188 128 virtual bool shouldFireEvents() const { return false; } 189 129 190 void animationTimerCallbackFired(const AtomicString& eventType, double elapsedTime);130 void fireAnimationEventsIfNeeded(); 191 131 192 132 bool animationsMatch(const Animation*) const; … … 227 167 virtual void endAnimation(bool reset) { } 228 168 229 void primeEventTimers();169 void goIntoEndingOrLoopingState(); 230 170 231 171 static bool propertiesEqual(int prop, const RenderStyle* a, const RenderStyle* b); … … 245 185 double m_startTime; 246 186 double m_pauseTime; 187 double m_requestedStartTime; 247 188 RenderObject* m_object; 248 189 249 AnimationTimerCallback m_animationTimerCallback;250 190 RefPtr<Animation> m_animation; 251 191 CompositeAnimation* m_compAnim; 252 192 bool m_transformFunctionListValid; 193 double m_totalDuration, m_nextIterationDuration; 253 194 }; 254 195 -
trunk/WebCore/page/animation/AnimationController.cpp
r39059 r39211 31 31 #include "CompositeAnimation.h" 32 32 #include "CSSParser.h" 33 #include "EventNames.h" 33 34 #include "Frame.h" 34 35 #include "Timer.h" … … 47 48 48 49 void animationTimerFired(Timer<AnimationControllerPrivate>*); 49 void updateAnimationTimer( );50 void updateAnimationTimer(bool callSetChanged = false); 50 51 51 52 void updateRenderingDispatcherFired(Timer<AnimationControllerPrivate>*); 52 53 void startUpdateRenderingDispatcher(); 54 void addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime); 53 55 54 56 bool hasAnimations() const { return !m_compositeAnimations.isEmpty(); } … … 71 73 Timer<AnimationControllerPrivate> m_updateRenderingDispatcher; 72 74 Frame* m_frame; 75 76 class EventToDispatch { 77 public: 78 RefPtr<Element> element; 79 AtomicString eventType; 80 String name; 81 double elapsedTime; 82 }; 83 84 Vector<EventToDispatch> m_eventsToDispatch; 73 85 }; 74 86 … … 122 134 } 123 135 124 void AnimationControllerPrivate::updateAnimationTimer() 125 { 126 bool isAnimating = false; 136 void AnimationControllerPrivate::updateAnimationTimer(bool callSetChanged/* = false*/) 137 { 138 double needsService = -1; 139 bool calledSetChanged = false; 127 140 128 141 RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); 129 142 for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { 130 143 RefPtr<CompositeAnimation> compAnim = it->second; 131 if (!compAnim->isSuspended() && compAnim->isAnimating()) { 132 isAnimating = true; 133 break; 144 if (!compAnim->isSuspended()) { 145 double t = compAnim->willNeedService(); 146 if (t != -1 && (t < needsService || needsService == -1)) 147 needsService = t; 148 if (needsService == 0) { 149 if (callSetChanged) { 150 Node* node = it->first->element(); 151 ASSERT(!node || (node->document() && !node->document()->inPageCache())); 152 node->setChanged(AnimationStyleChange); 153 calledSetChanged = true; 154 } 155 else 156 break; 157 } 134 158 } 135 159 } 136 160 137 if (isAnimating) { 138 if (!m_animationTimer.isActive()) 161 if (calledSetChanged) 162 m_frame->document()->updateRendering(); 163 164 // If we want service immediately, we start a repeating timer to reduce the overhead of starting 165 if (needsService == 0) { 166 if (!m_animationTimer.isActive() || m_animationTimer.repeatInterval() == 0) 139 167 m_animationTimer.startRepeating(cAnimationTimerDelay); 140 } else if (m_animationTimer.isActive()) 168 return; 169 } 170 171 // If we don't need service, we want to make sure the timer is no longer running 172 if (needsService < 0) { 173 if (m_animationTimer.isActive()) 174 m_animationTimer.stop(); 175 return; 176 } 177 178 // Otherwise, we want to start a one-shot timer so we get here again 179 if (m_animationTimer.isActive()) 141 180 m_animationTimer.stop(); 181 m_animationTimer.startOneShot(needsService); 142 182 } 143 183 144 184 void AnimationControllerPrivate::updateRenderingDispatcherFired(Timer<AnimationControllerPrivate>*) 145 185 { 186 // fire all the events 187 Vector<EventToDispatch>::const_iterator end = m_eventsToDispatch.end(); 188 for (Vector<EventToDispatch>::const_iterator it = m_eventsToDispatch.begin(); it != end; ++it) { 189 if (it->eventType == eventNames().webkitTransitionEndEvent) 190 it->element->dispatchWebKitTransitionEvent(it->eventType,it->name, it->elapsedTime); 191 else 192 it->element->dispatchWebKitAnimationEvent(it->eventType,it->name, it->elapsedTime); 193 } 194 195 m_eventsToDispatch.clear(); 196 146 197 if (m_frame && m_frame->document()) 147 198 m_frame->document()->updateRendering(); … … 154 205 } 155 206 207 void AnimationControllerPrivate::addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime) 208 { 209 m_eventsToDispatch.grow(m_eventsToDispatch.size()+1); 210 EventToDispatch& event = m_eventsToDispatch[m_eventsToDispatch.size()-1]; 211 event.element = element; 212 event.eventType = eventType; 213 event.name = name; 214 event.elapsedTime = elapsedTime; 215 216 startUpdateRenderingDispatcher(); 217 } 218 156 219 void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPrivate>* timer) 157 220 { 158 221 // When the timer fires, all we do is call setChanged on all DOM nodes with running animations and then do an immediate 159 222 // updateRendering. It will then call back to us with new information. 160 bool isAnimating = false; 161 RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); 162 for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { 163 RefPtr<CompositeAnimation> compAnim = it->second; 164 if (!compAnim->isSuspended() && compAnim->isAnimating()) { 165 isAnimating = true; 166 compAnim->setAnimating(false); 167 168 Node* node = it->first->element(); 169 ASSERT(!node || (node->document() && !node->document()->inPageCache())); 170 node->setChanged(AnimationStyleChange); 171 } 172 } 173 174 m_frame->document()->updateRendering(); 175 176 updateAnimationTimer(); 223 updateAnimationTimer(true); 177 224 } 178 225 … … 343 390 } 344 391 392 void AnimationController::addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime) 393 { 394 m_data->addEventToDispatch(element, eventType, name, elapsedTime); 395 } 396 345 397 void AnimationController::styleAvailable() 346 398 { -
trunk/WebCore/page/animation/AnimationController.h
r38526 r39211 35 35 36 36 class AnimationControllerPrivate; 37 class AtomicString; 37 38 class Document; 39 class Element; 38 40 class Frame; 39 41 class Node; … … 60 62 void suspendAnimations(Document*); 61 63 void resumeAnimations(Document*); 62 void updateAnimationTimer();63 64 64 65 void startUpdateRenderingDispatcher(); 66 void addEventToDispatch(PassRefPtr<Element>, const AtomicString& eventType, const String& name, double elapsedTime); 65 67 66 68 void styleAvailable(); -
trunk/WebCore/page/animation/CompositeAnimation.cpp
r39059 r39211 58 58 59 59 void setAnimating(bool); 60 bool isAnimating() const;61 62 const KeyframeAnimation* getAnimationForProperty(int property) const;60 double willNeedService() const; 61 62 PassRefPtr<KeyframeAnimation> getAnimationForProperty(int property); 63 63 64 64 void cleanupFinishedAnimations(RenderObject*); … … 158 158 // and we have to use the unanimatedStyle from the animation. We do the test 159 159 // against the unanimated style here, but we "override" the transition later. 160 const KeyframeAnimation*keyframeAnim = getAnimationForProperty(prop);160 RefPtr<KeyframeAnimation> keyframeAnim = getAnimationForProperty(prop); 161 161 RenderStyle* fromStyle = keyframeAnim ? keyframeAnim->unanimatedStyle() : currentStyle; 162 162 … … 308 308 } 309 309 310 bool CompositeAnimationPrivate::isAnimating() const 311 { 310 double CompositeAnimationPrivate::willNeedService() const 311 { 312 // Returns the time at which next service is required. -1 means no service is required. 0 means 313 // service is required now, and > 0 means service is required that many seconds in the future. 314 double minT = -1; 315 312 316 CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); 313 317 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { 314 318 ImplicitAnimation* transition = it->second.get(); 315 if (transition && !transition->paused() && transition->isAnimating() && transition->active()) 316 return true; 317 } 318 319 AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); 320 for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { 321 KeyframeAnimation* anim = it->second.get(); 322 if (anim && !anim->paused() && anim->isAnimating() && anim->active()) 323 return true; 324 } 325 326 return false; 327 } 328 329 const KeyframeAnimation* CompositeAnimationPrivate::getAnimationForProperty(int property) const 330 { 331 const KeyframeAnimation* retval = 0; 319 double t = transition ? transition->willNeedService() : -1; 320 if (t < minT || minT == -1) 321 minT = t; 322 if (minT == 0) 323 return 0; 324 } 325 326 AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); 327 for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { 328 KeyframeAnimation* animation = it->second.get(); 329 double t = animation ? animation->willNeedService() : -1; 330 if (t < minT || minT == -1) 331 minT = t; 332 if (minT == 0) 333 return 0; 334 } 335 336 return minT; 337 } 338 339 PassRefPtr<KeyframeAnimation> CompositeAnimationPrivate::getAnimationForProperty(int property) 340 { 341 RefPtr<KeyframeAnimation> retval; 332 342 333 343 // We want to send back the last animation with the property if there are multiples. … … 335 345 AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); 336 346 for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { 337 const KeyframeAnimation* anim = it->second.get();347 RefPtr<KeyframeAnimation> anim = it->second; 338 348 if (anim->hasAnimationForProperty(property)) 339 349 retval = anim; … … 572 582 } 573 583 584 AnimationController* CompositeAnimation::animationController() 585 { 586 return m_data->animationController(); 587 } 588 574 589 void CompositeAnimation::clearRenderer() 575 590 { … … 582 597 } 583 598 584 AnimationController* CompositeAnimation::animationController() 585 { 586 return m_data->animationController(); 587 } 588 589 bool CompositeAnimation::isAnimating() const 590 { 591 return m_data->isAnimating(); 599 double CompositeAnimation::willNeedService() const 600 { 601 return m_data->willNeedService(); 592 602 } 593 603 … … 632 642 } 633 643 644 PassRefPtr<KeyframeAnimation> CompositeAnimation::getAnimationForProperty(int property) 645 { 646 return m_data->getAnimationForProperty(property); 647 } 648 634 649 void CompositeAnimation::setAnimationStartTime(double t) 635 650 { -
trunk/WebCore/page/animation/CompositeAnimation.h
r39059 r39211 39 39 class CompositeAnimationPrivate; 40 40 class AnimationController; 41 class KeyframeAnimation; 41 42 class RenderObject; 42 43 class RenderStyle; … … 56 57 57 58 PassRefPtr<RenderStyle> animate(RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle); 58 bool isAnimating() const;59 double willNeedService() const; 59 60 60 61 AnimationController* animationController(); … … 70 71 void setAnimating(bool); 71 72 bool isAnimatingProperty(int property, bool isRunningNow) const; 73 74 PassRefPtr<KeyframeAnimation> getAnimationForProperty(int property); 75 72 76 73 77 void setAnimationStartTime(double t); -
trunk/WebCore/page/animation/ImplicitAnimation.cpp
r38876 r39211 28 28 29 29 #include "config.h" 30 31 #include "AnimationController.h" 32 #include "CompositeAnimation.h" 30 33 #include "CSSPropertyNames.h" 31 34 #include "EventNames.h" 32 35 #include "ImplicitAnimation.h" 36 #include "KeyframeAnimation.h" 33 37 #include "RenderObject.h" 34 38 … … 76 80 if (blendProperties(this, m_animatingProperty, animatedStyle.get(), m_fromStyle.get(), m_toStyle.get(), progress(1, 0, 0))) 77 81 setAnimating(); 82 83 // Fire the start timeout if needed 84 fireAnimationEventsIfNeeded(); 78 85 } 79 86 80 87 void ImplicitAnimation::onAnimationEnd(double elapsedTime) 81 88 { 89 // If we have a keyframe animation on this property, this transition is being overridden. The keyframe 90 // animation keeps an unanimated style in case a transition starts while the keyframe animation is 91 // running. But now that the transition has completed, we need to update this style with its new 92 // destination. If we didn't, the next time through we would think a transition had started 93 // (comparing the old unanimated style with the new final style of the transition). 94 RefPtr<KeyframeAnimation> keyframeAnim = m_compAnim->getAnimationForProperty(m_animatingProperty); 95 if (keyframeAnim) 96 keyframeAnim->setUnanimatedStyle(m_toStyle); 97 82 98 if (!sendTransitionEvent(eventNames().webkitTransitionEndEvent, elapsedTime)) { 83 99 // We didn't dispatch an event, which would call endAnimation(), so we'll just call it here. … … 105 121 return false; 106 122 107 // Call the event handler108 element->dispatchWebKitTransitionEvent(eventType, propertyName, elapsedTime);123 // Schedule event handling 124 m_object->animation()->addEventToDispatch(element, eventType, propertyName, elapsedTime); 109 125 110 126 // Restore the original (unanimated) style 111 if (eventType == eventNames().webkit AnimationEndEvent && element->renderer())127 if (eventType == eventNames().webkitTransitionEndEvent && element->renderer()) 112 128 setChanged(element.get()); 113 129 -
trunk/WebCore/page/animation/ImplicitAnimation.h
r37637 r39211 55 55 virtual bool overridden() const { return m_overridden; } 56 56 57 virtual bool shouldFireEvents() const { return true; }58 59 57 virtual bool affectsProperty(int) const; 60 58 -
trunk/WebCore/page/animation/KeyframeAnimation.cpp
r39176 r39211 30 30 #include "KeyframeAnimation.h" 31 31 32 #include "AnimationController.h" 32 33 #include "CSSPropertyNames.h" 33 34 #include "CSSStyleSelector.h" … … 63 64 const RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle) 64 65 { 66 // Fire the start timeout if needed 67 fireAnimationEventsIfNeeded(); 68 65 69 // If we have not yet started, we will not have a valid start time, so just start the animation if needed. 66 70 if (isNew() && m_animation->playState() == AnimPlayStatePlaying) … … 201 205 return false; 202 206 203 // Call the event handler204 element->dispatchWebKitAnimationEvent(eventType, m_keyframes.animationName(), elapsedTime);207 // Schedule event handling 208 m_object->animation()->addEventToDispatch(element, eventType, m_keyframes.animationName(), elapsedTime); 205 209 206 210 // Restore the original (unanimated) style -
trunk/WebCore/page/animation/KeyframeAnimation.h
r37637 r39211 52 52 void setIndex(int i) { m_index = i; } 53 53 54 virtual bool shouldFireEvents() const { return true; }55 56 54 bool hasAnimationForProperty(int property) const; 57 55 56 void setUnanimatedStyle(PassRefPtr<RenderStyle> style) { m_unanimatedStyle = style; } 58 57 RenderStyle* unanimatedStyle() const { return m_unanimatedStyle.get(); } 59 58
Note:
See TracChangeset
for help on using the changeset viewer.