ImplicitAnimation.cpp [plain text]
#include "config.h"
#include "AnimationControllerPrivate.h"
#include "CSSPropertyAnimation.h"
#include "CompositeAnimation.h"
#include "EventNames.h"
#include "ImplicitAnimation.h"
#include "KeyframeAnimation.h"
#include "RenderBoxModelObject.h"
namespace WebCore {
ImplicitAnimation::ImplicitAnimation(const Animation& transition, CSSPropertyID animatingProperty, RenderElement* renderer, CompositeAnimation* compAnim, RenderStyle* fromStyle)
: AnimationBase(transition, renderer, compAnim)
, m_transitionProperty(transition.property())
, m_animatingProperty(animatingProperty)
, m_overridden(false)
, m_active(true)
, m_fromStyle(fromStyle)
{
ASSERT(animatingProperty != CSSPropertyInvalid);
}
ImplicitAnimation::~ImplicitAnimation()
{
if (!postActive())
endAnimation();
}
bool ImplicitAnimation::shouldSendEventForListener(Document::ListenerType inListenerType) const
{
return m_object->document().hasListenerType(inListenerType);
}
void ImplicitAnimation::animate(CompositeAnimation*, RenderElement*, const RenderStyle*, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle)
{
if (postActive())
return;
if (isNew())
reset(targetStyle);
if (!animatedStyle)
animatedStyle = RenderStyle::clone(targetStyle);
bool needsAnim = CSSPropertyAnimation::blendProperties(this, m_animatingProperty, animatedStyle.get(), m_fromStyle.get(), m_toStyle.get(), progress(1, 0, 0));
if (!needsAnim)
animatedStyle->setIsRunningAcceleratedAnimation();
fireAnimationEventsIfNeeded();
}
void ImplicitAnimation::getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle)
{
if (!animatedStyle)
animatedStyle = RenderStyle::clone(m_toStyle.get());
CSSPropertyAnimation::blendProperties(this, m_animatingProperty, animatedStyle.get(), m_fromStyle.get(), m_toStyle.get(), progress(1, 0, 0));
}
bool ImplicitAnimation::startAnimation(double timeOffset)
{
if (m_object && m_object->isComposited())
return toRenderBoxModelObject(m_object)->startTransition(timeOffset, m_animatingProperty, m_fromStyle.get(), m_toStyle.get());
return false;
}
void ImplicitAnimation::pauseAnimation(double timeOffset)
{
if (!m_object)
return;
if (m_object->isComposited())
toRenderBoxModelObject(m_object)->transitionPaused(timeOffset, m_animatingProperty);
if (!paused())
setNeedsStyleRecalc(m_object->element());
}
void ImplicitAnimation::endAnimation()
{
if (m_object && m_object->isComposited())
toRenderBoxModelObject(m_object)->transitionFinished(m_animatingProperty);
}
void ImplicitAnimation::onAnimationEnd(double elapsedTime)
{
RefPtr<KeyframeAnimation> keyframeAnim = m_compositeAnimation->getAnimationForProperty(m_animatingProperty);
if (keyframeAnim)
keyframeAnim->setUnanimatedStyle(m_toStyle);
sendTransitionEvent(eventNames().transitionendEvent, elapsedTime);
endAnimation();
}
bool ImplicitAnimation::sendTransitionEvent(const AtomicString& eventType, double elapsedTime)
{
if (eventType == eventNames().transitionendEvent) {
Document::ListenerType listenerType = Document::TRANSITIONEND_LISTENER;
if (shouldSendEventForListener(listenerType)) {
String propertyName = getPropertyNameString(m_animatingProperty);
RefPtr<Element> element = m_object->element();
ASSERT(!element || !element->document().inPageCache());
if (!element)
return false;
m_compositeAnimation->animationController()->addEventToDispatch(element, eventType, propertyName, elapsedTime);
if (eventType == eventNames().transitionendEvent && element->renderer())
setNeedsStyleRecalc(element.get());
return true; }
}
return false; }
void ImplicitAnimation::reset(RenderStyle* to)
{
ASSERT(to);
ASSERT(m_fromStyle);
m_toStyle = to;
if (m_fromStyle && m_toStyle)
updateStateMachine(AnimationStateInput::RestartAnimation, -1);
validateTransformFunctionList();
#if ENABLE(CSS_FILTERS)
checkForMatchingFilterFunctionLists();
#endif
}
void ImplicitAnimation::setOverridden(bool b)
{
if (b == m_overridden)
return;
m_overridden = b;
updateStateMachine(m_overridden ? AnimationStateInput::PauseOverride : AnimationStateInput::ResumeOverride, -1);
}
bool ImplicitAnimation::affectsProperty(CSSPropertyID property) const
{
return (m_animatingProperty == property);
}
bool ImplicitAnimation::isTargetPropertyEqual(CSSPropertyID prop, const RenderStyle* targetStyle)
{
if (!m_toStyle)
return false;
return CSSPropertyAnimation::propertiesEqual(prop, m_toStyle.get(), targetStyle);
}
void ImplicitAnimation::blendPropertyValueInStyle(CSSPropertyID prop, RenderStyle* currentStyle)
{
if (!m_toStyle)
return;
CSSPropertyAnimation::blendProperties(this, prop, currentStyle, m_fromStyle.get(), m_toStyle.get(), progress(1, 0, 0));
}
void ImplicitAnimation::validateTransformFunctionList()
{
m_transformFunctionListValid = false;
if (!m_fromStyle || !m_toStyle)
return;
const TransformOperations* val = &m_fromStyle->transform();
const TransformOperations* toVal = &m_toStyle->transform();
if (val->operations().isEmpty())
val = toVal;
if (val->operations().isEmpty())
return;
if (val != toVal && !toVal->operations().isEmpty() && !val->operationsMatch(*toVal))
return;
m_transformFunctionListValid = true;
}
#if ENABLE(CSS_FILTERS)
void ImplicitAnimation::checkForMatchingFilterFunctionLists()
{
m_filterFunctionListsMatch = false;
if (!m_fromStyle || !m_toStyle)
return;
const FilterOperations* val = &m_fromStyle->filter();
const FilterOperations* toVal = &m_toStyle->filter();
if (val->operations().isEmpty())
val = toVal;
if (val->operations().isEmpty())
return;
if (val != toVal && !toVal->operations().isEmpty() && !val->operationsMatch(*toVal))
return;
m_filterFunctionListsMatch = true;
}
#endif
double ImplicitAnimation::timeToNextService()
{
double t = AnimationBase::timeToNextService();
if (t != 0 || preActive())
return t;
if (CSSPropertyAnimation::animationOfPropertyIsAccelerated(m_animatingProperty) && isAccelerated()) {
bool isLooping;
getTimeToNextEvent(t, isLooping);
}
return t;
}
}