animationcontroller.cpp
来自「linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自Web」· C++ 代码 · 共 527 行 · 第 1/2 页
CPP
527 行
/* * Copyright (C) 2007 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include "AnimationController.h"#include "AnimationBase.h"#include "AnimationControllerPrivate.h"#include "CSSParser.h"#include "CompositeAnimation.h"#include "EventNames.h"#include "Frame.h"#include "RenderObject.h"#include <wtf/CurrentTime.h>#include <wtf/UnusedParam.h>namespace WebCore {static const double cAnimationTimerDelay = 0.025;static const double cBeginAnimationUpdateTimeNotSet = -1;AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame) : m_animationTimer(this, &AnimationControllerPrivate::animationTimerFired) , m_updateRenderingDispatcher(this, &AnimationControllerPrivate::updateRenderingDispatcherFired) , m_frame(frame) , m_beginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet) , m_styleAvailableWaiters(0) , m_lastStyleAvailableWaiter(0) , m_responseWaiters(0) , m_lastResponseWaiter(0) , m_waitingForAResponse(false){}AnimationControllerPrivate::~AnimationControllerPrivate(){}PassRefPtr<CompositeAnimation> AnimationControllerPrivate::accessCompositeAnimation(RenderObject* renderer){ RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer); if (!animation) { animation = CompositeAnimation::create(this); m_compositeAnimations.set(renderer, animation); } return animation;}bool AnimationControllerPrivate::clear(RenderObject* renderer){ // Return false if we didn't do anything OR we are suspended (so we don't try to // do a setChanged() when suspended). PassRefPtr<CompositeAnimation> animation = m_compositeAnimations.take(renderer); if (!animation) return false; animation->clearRenderer(); return animation->isSuspended();}void AnimationControllerPrivate::updateAnimationTimer(bool callSetChanged/* = false*/){ double needsService = -1; bool calledSetChanged = false; RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { RefPtr<CompositeAnimation> compAnim = it->second; if (!compAnim->isSuspended() && compAnim->hasAnimations()) { double t = compAnim->willNeedService(); if (t != -1 && (t < needsService || needsService == -1)) needsService = t; if (needsService == 0) { if (callSetChanged) { Node* node = it->first->node(); ASSERT(!node || (node->document() && !node->document()->inPageCache())); node->setChanged(AnimationStyleChange); calledSetChanged = true; } else break; } } } if (calledSetChanged) m_frame->document()->updateRendering(); // If we want service immediately, we start a repeating timer to reduce the overhead of starting if (needsService == 0) { if (!m_animationTimer.isActive() || m_animationTimer.repeatInterval() == 0) m_animationTimer.startRepeating(cAnimationTimerDelay); return; } // If we don't need service, we want to make sure the timer is no longer running if (needsService < 0) { if (m_animationTimer.isActive()) m_animationTimer.stop(); return; } // Otherwise, we want to start a one-shot timer so we get here again if (m_animationTimer.isActive()) m_animationTimer.stop(); m_animationTimer.startOneShot(needsService);}void AnimationControllerPrivate::updateRenderingDispatcherFired(Timer<AnimationControllerPrivate>*){ // fire all the events Vector<EventToDispatch>::const_iterator eventsToDispatchEnd = m_eventsToDispatch.end(); for (Vector<EventToDispatch>::const_iterator it = m_eventsToDispatch.begin(); it != eventsToDispatchEnd; ++it) { if (it->eventType == eventNames().webkitTransitionEndEvent) it->element->dispatchWebKitTransitionEvent(it->eventType,it->name, it->elapsedTime); else it->element->dispatchWebKitAnimationEvent(it->eventType,it->name, it->elapsedTime); } m_eventsToDispatch.clear(); // call setChanged on all the elements Vector<RefPtr<Node> >::const_iterator nodeChangesToDispatchEnd = m_nodeChangesToDispatch.end(); for (Vector<RefPtr<Node> >::const_iterator it = m_nodeChangesToDispatch.begin(); it != nodeChangesToDispatchEnd; ++it) (*it)->setChanged(AnimationStyleChange); m_nodeChangesToDispatch.clear(); if (m_frame) m_frame->document()->updateRendering();}void AnimationControllerPrivate::startUpdateRenderingDispatcher(){ if (!m_updateRenderingDispatcher.isActive()) m_updateRenderingDispatcher.startOneShot(0);}void AnimationControllerPrivate::addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime){ m_eventsToDispatch.grow(m_eventsToDispatch.size()+1); EventToDispatch& event = m_eventsToDispatch[m_eventsToDispatch.size()-1]; event.element = element; event.eventType = eventType; event.name = name; event.elapsedTime = elapsedTime; startUpdateRenderingDispatcher();}void AnimationControllerPrivate::addNodeChangeToDispatch(PassRefPtr<Node> node){ ASSERT(!node || (node->document() && !node->document()->inPageCache())); if (!node) return; m_nodeChangesToDispatch.append(node); startUpdateRenderingDispatcher();}void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPrivate>*){ // Make sure animationUpdateTime is updated, so that it is current even if no // styleChange has happened (e.g. accelerated animations) setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet); // When the timer fires, all we do is call setChanged on all DOM nodes with running animations and then do an immediate // updateRendering. It will then call back to us with new information. updateAnimationTimer(true);}bool AnimationControllerPrivate::isAnimatingPropertyOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const{ RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer); if (!animation) return false; return animation->isAnimatingProperty(property, isRunningNow);}void AnimationControllerPrivate::suspendAnimations(Document* document){ RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { RenderObject* renderer = it->first; RefPtr<CompositeAnimation> compAnim = it->second; if (renderer->document() == document) compAnim->suspendAnimations(); } updateAnimationTimer();}void AnimationControllerPrivate::resumeAnimations(Document* document){ RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { RenderObject* renderer = it->first; RefPtr<CompositeAnimation> compAnim = it->second; if (renderer->document() == document) compAnim->resumeAnimations(); } updateAnimationTimer();}bool AnimationControllerPrivate::pauseAnimationAtTime(RenderObject* renderer, const String& name, double t){ if (!renderer) return false; RefPtr<CompositeAnimation> compAnim = accessCompositeAnimation(renderer); if (!compAnim) return false; if (compAnim->pauseAnimationAtTime(name, t)) { renderer->node()->setChanged(AnimationStyleChange); startUpdateRenderingDispatcher(); return true; } return false;}bool AnimationControllerPrivate::pauseTransitionAtTime(RenderObject* renderer, const String& property, double t){ if (!renderer) return false; RefPtr<CompositeAnimation> compAnim = accessCompositeAnimation(renderer); if (!compAnim) return false; if (compAnim->pauseTransitionAtTime(cssPropertyID(property), t)) { renderer->node()->setChanged(AnimationStyleChange); startUpdateRenderingDispatcher(); return true; } return false;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?