#include "core/animation/KeyframeEffectModel.h"
#include "core/animation/css/CSSAnimatableValueFactory.h"
#include "core/animation/css/CSSAnimationDataList.h"
+#include "core/animation/css/CSSPropertyAnimation.h"
#include "core/css/CSSKeyframeRule.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/Element.h"
#include "core/events/TransitionEvent.h"
#include "core/events/WebKitAnimationEvent.h"
#include "core/frame/UseCounter.h"
+#include "core/rendering/RenderLayer.h"
#include "core/rendering/RenderObject.h"
#include "core/rendering/style/KeyframeList.h"
#include "platform/animation/TimingFunction.h"
static void resolveKeyframes(StyleResolver* resolver, Element* element, const Element& parentElement, const RenderStyle& style, RenderStyle* parentStyle, const AtomicString& name, TimingFunction* defaultTimingFunction,
Vector<std::pair<KeyframeEffectModel::KeyframeVector, RefPtr<TimingFunction> > >& keyframesAndTimingFunctions)
{
- ASSERT(RuntimeEnabledFeatures::webAnimationsCSSEnabled());
// When the element is null, use its parent for scoping purposes.
const Element* elementForScoping = element ? element : &parentElement;
const StyleRuleKeyframes* keyframesRule = CSSAnimations::matchScopedKeyframesRule(resolver, elementForScoping, name.impl());
{
if (animationData->isDelaySet())
timing.startDelay = animationData->delay();
- if (animationData->isDurationSet()) {
+ if (animationData->isDurationSet())
timing.iterationDuration = animationData->duration();
- timing.hasIterationDuration = true;
- }
if (animationData->isIterationCountSet()) {
if (animationData->iterationCount() == CSSAnimationData::IterationCountInfinite)
timing.iterationCount = std::numeric_limits<double>::infinity();
timing.assertValid();
ASSERT(!timing.iterationStart);
ASSERT(timing.playbackRate == 1);
- ASSERT(timing.iterationDuration >= 0 && std::isfinite(timing.iterationDuration));
+ ASSERT(!std::isinf(timing.iterationDuration));
isPaused = animationData->isPlayStateSet() && animationData->playState() == AnimPlayStatePaused;
return animationData->isTimingFunctionSet() ? animationData->timingFunction() : CSSAnimationData::initialAnimationTimingFunction();
PassOwnPtr<CSSAnimationUpdate> CSSAnimations::calculateUpdate(Element* element, const Element& parentElement, const RenderStyle& style, RenderStyle* parentStyle, StyleResolver* resolver)
{
- ASSERT(RuntimeEnabledFeatures::webAnimationsCSSEnabled());
OwnPtr<CSSAnimationUpdate> update = adoptPtr(new CSSAnimationUpdate());
calculateAnimationUpdate(update.get(), element, parentElement, style, parentStyle, resolver);
calculateAnimationCompositableValues(update.get(), element);
m_previousCompositableValuesForAnimations.swap(update->compositableValuesForAnimations());
+ // FIXME: cancelling, pausing, unpausing animations all query compositingState, which is not necessarily up to date here
+ // since we call this from recalc style.
+ // https://code.google.com/p/chromium/issues/detail?id=339847
+ DisableCompositingQueryAsserts disabler;
+
for (Vector<AtomicString>::const_iterator iter = update->cancelledAnimationNames().begin(); iter != update->cancelledAnimationNames().end(); ++iter) {
const HashSet<RefPtr<Player> >& players = m_animations.take(*iter);
for (HashSet<RefPtr<Player> >::const_iterator iter = players.begin(); iter != players.end(); ++iter)
for (HashSet<RefPtr<Player> >::const_iterator iter = players.begin(); iter != players.end(); ++iter) {
Player* player = iter->get();
ASSERT(player->paused() == isFirstPlayerPaused);
- player->setPaused(!isFirstPlayerPaused);
+ if (isFirstPlayerPaused)
+ player->unpause();
+ else
+ player->pause();
}
}
const InertAnimation* inertAnimation = animationsIter->get();
// The event delegate is set on the the first animation only. We
// rely on the behavior of OwnPtr::release() to achieve this.
- RefPtr<Animation> animation = Animation::create(element, inertAnimation->effect(), inertAnimation->specified(), Animation::DefaultPriority, eventDelegate.release());
+ RefPtr<Animation> animation = Animation::create(element, inertAnimation->effect(), inertAnimation->specifiedTiming(), Animation::DefaultPriority, eventDelegate.release());
Player* player = element->document().timeline()->createPlayer(animation.get());
- player->setPaused(inertAnimation->paused());
+ if (inertAnimation->paused())
+ player->pause();
element->document().cssPendingAnimations().add(player);
player->update();
players.add(player);
newFrames.append(frames[1]->clone());
effect = KeyframeEffectModel::create(newFrames);
}
- RefPtr<Animation> transition = Animation::create(element, effect, inertAnimation->specified(), Animation::TransitionPriority, eventDelegate.release());
+ RefPtr<Animation> transition = Animation::create(element, effect, inertAnimation->specifiedTiming(), Animation::TransitionPriority, eventDelegate.release());
RefPtr<Player> player = element->document().transitionTimeline()->createPlayer(transition.get());
player->update();
element->document().cssPendingAnimations().add(player.get());
ASSERT(!element->activeAnimations() || !element->activeAnimations()->isAnimationStyleChange());
}
}
+
+ if (anim->duration() + anim->delay() <= 0)
+ return;
+
+ if (CSSPropertyAnimation::propertiesEqual(id, &oldStyle, &style))
+ return;
if (!to)
to = CSSAnimatableValueFactory::create(id, style);
- RefPtr<AnimatableValue> from = CSSAnimatableValueFactory::create(id, oldStyle);
- if (to->equals(from.get()))
- return;
+ RefPtr<AnimatableValue> from = CSSAnimatableValueFactory::create(id, oldStyle);
// If we have multiple transitions on the same property, we will use the
// last one since we iterate over them in order.
if (AnimatableValue::usesDefaultInterpolation(to.get(), from.get()))
for (size_t i = 0; i < style.transitions()->size(); ++i) {
const CSSAnimationData* anim = style.transitions()->animation(i);
CSSAnimationData::AnimationMode mode = anim->animationMode();
- if (anim->duration() + anim->delay() <= 0 || mode == CSSAnimationData::AnimateNone)
+ if (mode == CSSAnimationData::AnimateNone)
continue;
bool animateAll = mode == CSSAnimationData::AnimateAll;
// between a single pair of samples. See http://crbug.com/275263. For
// compatibility with the existing implementation, this event uses
// the elapsedTime for the first iteration in question.
- ASSERT(timedItem->specified().hasIterationDuration);
- const double elapsedTime = timedItem->specified().iterationDuration * (previousIteration + 1);
+ ASSERT(!std::isnan(timedItem->specifiedTiming().iterationDuration));
+ const double elapsedTime = timedItem->specifiedTiming().iterationDuration * (previousIteration + 1);
maybeDispatch(Document::ANIMATIONITERATION_LISTENER, EventTypeNames::animationiteration, elapsedTime);
return;
}
if ((isFirstSample || previousPhase == TimedItem::PhaseBefore) && isLaterPhase(currentPhase, TimedItem::PhaseBefore)) {
- ASSERT(timedItem->specified().startDelay > 0 || isFirstSample);
+ ASSERT(timedItem->specifiedTiming().startDelay > 0 || isFirstSample);
// The spec states that the elapsed time should be
// 'delay < 0 ? -delay : 0', but we always use 0 to match the existing
// implementation. See crbug.com/279611
const TimedItem::Phase currentPhase = timedItem->phase();
if (currentPhase == TimedItem::PhaseAfter && (isFirstSample || previousPhase != currentPhase) && m_target->document().hasListenerType(Document::TRANSITIONEND_LISTENER)) {
String propertyName = getPropertyNameString(m_property);
- const Timing& timing = timedItem->specified();
+ const Timing& timing = timedItem->specifiedTiming();
double elapsedTime = timing.iterationDuration;
const AtomicString& eventType = EventTypeNames::transitionend;
String pseudoElement = PseudoElement::pseudoElementNameForEvents(m_target->pseudoId());
case CSSPropertyZIndex:
case CSSPropertyZoom:
return true;
- // FIXME: Shorthands should not be present in this list, but
- // CSSPropertyAnimation implements animation of these shorthands
- // directly and makes use of this method.
- case CSSPropertyFlex:
- return !RuntimeEnabledFeatures::webAnimationsCSSEnabled();
default:
return false;
}