This source file includes following definitions.
- create
- create
- create
- create
- create
- create
- create
- m_priority
- didAttach
- willDetach
- ensureAnimationStack
- applyEffects
- clearEffects
- updateChildrenAndEffects
- calculateTimeToEffectChange
- isCandidateForAnimationOnCompositor
- maybeStartAnimationOnCompositor
- hasActiveAnimationsOnCompositor
- hasActiveAnimationsOnCompositor
- affects
- cancelAnimationOnCompositor
- pauseAnimationForTestingOnCompositor
#include "config.h"
#include "core/animation/Animation.h"
#include "bindings/v8/Dictionary.h"
#include "bindings/v8/ExceptionState.h"
#include "core/animation/ActiveAnimations.h"
#include "core/animation/AnimationHelpers.h"
#include "core/animation/AnimationPlayer.h"
#include "core/animation/CompositorAnimations.h"
#include "core/animation/DocumentTimeline.h"
#include "core/animation/Interpolation.h"
#include "core/animation/KeyframeEffectModel.h"
#include "core/dom/Element.h"
#include "core/frame/UseCounter.h"
#include "core/rendering/RenderLayer.h"
namespace WebCore {
PassRefPtr<Animation> Animation::create(PassRefPtr<Element> target, PassRefPtrWillBeRawPtr<AnimationEffect> effect, const Timing& timing, Priority priority, PassOwnPtr<EventDelegate> eventDelegate)
{
return adoptRef(new Animation(target, effect, timing, priority, eventDelegate));
}
PassRefPtr<Animation> Animation::create(Element* element, PassRefPtrWillBeRawPtr<AnimationEffect> effect, const Dictionary& timingInputDictionary)
{
ASSERT(RuntimeEnabledFeatures::webAnimationsAPIEnabled());
return create(element, effect, TimingInput::convert(timingInputDictionary));
}
PassRefPtr<Animation> Animation::create(Element* element, PassRefPtrWillBeRawPtr<AnimationEffect> effect, double duration)
{
ASSERT(RuntimeEnabledFeatures::webAnimationsAPIEnabled());
return create(element, effect, TimingInput::convert(duration));
}
PassRefPtr<Animation> Animation::create(Element* element, PassRefPtrWillBeRawPtr<AnimationEffect> effect)
{
ASSERT(RuntimeEnabledFeatures::webAnimationsAPIEnabled());
return create(element, effect, Timing());
}
PassRefPtr<Animation> Animation::create(Element* element, const Vector<Dictionary>& keyframeDictionaryVector, const Dictionary& timingInputDictionary, ExceptionState& exceptionState)
{
ASSERT(RuntimeEnabledFeatures::webAnimationsAPIEnabled());
UseCounter::count(element->document(), UseCounter::AnimationConstructorKeyframeListEffectObjectTiming);
return create(element, EffectInput::convert(element, keyframeDictionaryVector, exceptionState), TimingInput::convert(timingInputDictionary));
}
PassRefPtr<Animation> Animation::create(Element* element, const Vector<Dictionary>& keyframeDictionaryVector, double duration, ExceptionState& exceptionState)
{
ASSERT(RuntimeEnabledFeatures::webAnimationsAPIEnabled());
UseCounter::count(element->document(), UseCounter::AnimationConstructorKeyframeListEffectDoubleTiming);
return create(element, EffectInput::convert(element, keyframeDictionaryVector, exceptionState), TimingInput::convert(duration));
}
PassRefPtr<Animation> Animation::create(Element* element, const Vector<Dictionary>& keyframeDictionaryVector, ExceptionState& exceptionState)
{
ASSERT(RuntimeEnabledFeatures::webAnimationsAPIEnabled());
UseCounter::count(element->document(), UseCounter::AnimationConstructorKeyframeListEffectNoTiming);
return create(element, EffectInput::convert(element, keyframeDictionaryVector, exceptionState), Timing());
}
Animation::Animation(PassRefPtr<Element> target, PassRefPtrWillBeRawPtr<AnimationEffect> effect, const Timing& timing, Priority priority, PassOwnPtr<EventDelegate> eventDelegate)
: TimedItem(timing, eventDelegate)
, m_target(target)
, m_effect(effect)
, m_activeInAnimationStack(false)
, m_priority(priority)
{
}
void Animation::didAttach()
{
if (m_target)
m_target->ensureActiveAnimations().players().add(player());
}
void Animation::willDetach()
{
if (m_target)
m_target->activeAnimations()->players().remove(player());
if (m_activeInAnimationStack)
clearEffects();
}
static AnimationStack& ensureAnimationStack(Element* element)
{
return element->ensureActiveAnimations().defaultStack();
}
void Animation::applyEffects(bool previouslyInEffect)
{
ASSERT(isInEffect());
if (!m_target || !m_effect)
return;
if (player() && !previouslyInEffect) {
ensureAnimationStack(m_target.get()).add(this);
m_activeInAnimationStack = true;
}
double iteration = currentIteration();
ASSERT(iteration >= 0);
m_activeInterpolations = m_effect->sample(static_cast<int>(iteration), timeFraction(), duration());
if (player())
m_target->setNeedsAnimationStyleRecalc();
}
void Animation::clearEffects()
{
ASSERT(player());
ASSERT(m_activeInAnimationStack);
ensureAnimationStack(m_target.get()).remove(this);
{
DisableCompositingQueryAsserts disabler;
cancelAnimationOnCompositor();
}
m_activeInAnimationStack = false;
m_activeInterpolations.clear();
m_target->setNeedsAnimationStyleRecalc();
invalidate();
}
void Animation::updateChildrenAndEffects() const
{
if (!m_effect)
return;
if (isInEffect())
const_cast<Animation*>(this)->applyEffects(m_activeInAnimationStack);
else if (m_activeInAnimationStack)
const_cast<Animation*>(this)->clearEffects();
}
double Animation::calculateTimeToEffectChange(bool forwards, double localTime, double timeToNextIteration) const
{
const double start = startTime() + specifiedTiming().startDelay;
const double end = start + activeDuration();
switch (phase()) {
case PhaseBefore:
ASSERT(start >= localTime);
return forwards
? start - localTime
: std::numeric_limits<double>::infinity();
case PhaseActive:
if (forwards && hasActiveAnimationsOnCompositor()) {
ASSERT(specifiedTiming().playbackRate == 1);
return std::min(end - localTime, timeToNextIteration);
}
return 0;
case PhaseAfter:
ASSERT(localTime >= end);
return forwards
? std::numeric_limits<double>::infinity()
: localTime - end;
case PhaseNone:
ASSERT(player() && player()->timeline() && !player()->timeline()->hasStarted());
return std::numeric_limits<double>::infinity();
default:
ASSERT_NOT_REACHED();
return std::numeric_limits<double>::infinity();
}
}
bool Animation::isCandidateForAnimationOnCompositor() const
{
if (!effect() || !m_target)
return false;
return CompositorAnimations::instance()->isCandidateForAnimationOnCompositor(specifiedTiming(), *effect());
}
bool Animation::maybeStartAnimationOnCompositor()
{
ASSERT(!hasActiveAnimationsOnCompositor());
if (!isCandidateForAnimationOnCompositor())
return false;
if (!CompositorAnimations::instance()->canStartAnimationOnCompositor(*m_target.get()))
return false;
if (!CompositorAnimations::instance()->startAnimationOnCompositor(*m_target.get(), specifiedTiming(), *effect(), m_compositorAnimationIds))
return false;
ASSERT(!m_compositorAnimationIds.isEmpty());
return true;
}
bool Animation::hasActiveAnimationsOnCompositor() const
{
return !m_compositorAnimationIds.isEmpty();
}
bool Animation::hasActiveAnimationsOnCompositor(CSSPropertyID property) const
{
return hasActiveAnimationsOnCompositor() && affects(property);
}
bool Animation::affects(CSSPropertyID property) const
{
return m_effect && m_effect->affects(property);
}
void Animation::cancelAnimationOnCompositor()
{
if (!hasActiveAnimationsOnCompositor())
return;
if (!m_target || !m_target->renderer())
return;
for (size_t i = 0; i < m_compositorAnimationIds.size(); ++i)
CompositorAnimations::instance()->cancelAnimationOnCompositor(*m_target.get(), m_compositorAnimationIds[i]);
m_compositorAnimationIds.clear();
}
void Animation::pauseAnimationForTestingOnCompositor(double pauseTime)
{
ASSERT(hasActiveAnimationsOnCompositor());
if (!m_target || !m_target->renderer())
return;
for (size_t i = 0; i < m_compositorAnimationIds.size(); ++i)
CompositorAnimations::instance()->pauseAnimationForTestingOnCompositor(*m_target.get(), m_compositorAnimationIds[i], pauseTime);
}
}