2017-10-24 07:51:59 +00:00
|
|
|
/*
|
[Web Animations] Refactor AnimationEffect and KeyframeEffect into AnimationEffectReadOnly, KeyframeEffectReadOnly and KeyframeEffect
https://bugs.webkit.org/show_bug.cgi?id=182608
Reviewed by Dean Jackson.
LayoutTests/imported/w3c:
Update WPT expectations with progressions and updated failure points for all tests that involved
either AnimationEffectReadOnly or KeyframeEffectReadOnly.
* web-platform-tests/web-animations/interfaces/Animation/constructor-expected.txt:
* web-platform-tests/web-animations/interfaces/Animation/effect-expected.txt:
* web-platform-tests/web-animations/interfaces/AnimationEffectTiming/idlharness-expected.txt:
* web-platform-tests/web-animations/interfaces/Document/getAnimations-expected.txt:
* web-platform-tests/web-animations/interfaces/KeyframeEffect/constructor-expected.txt:
* web-platform-tests/web-animations/interfaces/KeyframeEffect/copy-constructor-expected.txt:
* web-platform-tests/web-animations/interfaces/KeyframeEffect/idlharness-expected.txt:
Source/WebCore:
Currently, we have an AnimationEffect class with read-write members and a KeyframeEffect subclass with read-write
members. The spec has an AnimationEffectReadOnly class, with read-only members, a KeyframeEffectReadOnly subclass,
with read-only members, and then the KeyframeEffect subclass (of KeyframeEffectReadOnly) with read-write members.
Likewise, currently we have an AnimationEffectTiming class with read-write members. While the spec has this class
as well, it also specifies a read-only AnimationEffectTimingReadOnly superclass.
In this patch we refactor the code to match the spec, which gives us a big boost in our WPT pass rate. The vast
majority of the code is just copied from one class to another verbatim. The limited actual code changes, all related
to the new subclassing, are:
- AnimationEffectTimingReadOnly is not actually read-only as far as WebCore is concerned, it actually exposes setters
for all of its properties, but the IDL for this class specifies all properties as read-only, so we match the spec. The
reason for this is that it is necessary to be able to set members of an AnimationEffectTimingReadOnly object based on
a Variant<double, KeyframeEffectOptions> provided to Element.animate() or the KeyframeEffectReadOnly and KeyframeEffect
constructors, and the logic to handle properties in such dictionaries is the same as the logic required to set individual
members in AnimationEffectTiming. So in essence, the sole role of AnimationTimingEffect is to provide an IDL interface
with read-write members, but the parent class is itself read-write as far as WebCore is concerned.
- AnimationEffectTimingReadOnly exposes a new setProperties() method which takes in a nullable Variant<double, KeyframeEffectOptions>
so that code that was previously specific to KeyframeEffect can be factored into this method and both the constructors of
KeyframeEffectReadOnly and KeyframeEffect can make use of it without code duplication.
- The AnimationEffectReadOnly constructor now takes an AnimationEffectTimingReadOnly as input since that class and
KeyframeEffectReadOnly expose an AnimationEffectTimingReadOnly object, while KeyframeEffect exposes an
AnimationEffectTiming read-write object. This allows the KeyframeEffect constructor to provide the right object type.
* CMakeLists.txt:
* DerivedSources.make:
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* animation/AnimationEffectReadOnly.cpp: Renamed from Source/WebCore/animation/AnimationEffect.cpp.
(WebCore::AnimationEffectReadOnly::AnimationEffectReadOnly):
(WebCore::AnimationEffectReadOnly::localTime const):
(WebCore::AnimationEffectReadOnly::phase const):
(WebCore::AnimationEffectReadOnly::activeTime const):
(WebCore::AnimationEffectReadOnly::overallProgress const):
(WebCore::AnimationEffectReadOnly::simpleIterationProgress const):
(WebCore::AnimationEffectReadOnly::currentIteration const):
(WebCore::AnimationEffectReadOnly::currentDirection const):
(WebCore::AnimationEffectReadOnly::directedProgress const):
(WebCore::AnimationEffectReadOnly::transformedProgress const):
(WebCore::AnimationEffectReadOnly::iterationProgress const):
(WebCore::AnimationEffectReadOnly::getComputedTiming):
* animation/AnimationEffectReadOnly.h: Renamed from Source/WebCore/animation/AnimationEffect.h.
(WebCore::AnimationEffectReadOnly::isKeyframeEffectReadOnly const):
(WebCore::AnimationEffectReadOnly::timing const):
* animation/AnimationEffectReadOnly.idl: Copied from Source/WebCore/animation/AnimationEffect.idl.
* animation/AnimationEffectTiming.cpp:
(WebCore::AnimationEffectTiming::AnimationEffectTiming):
(WebCore::AnimationEffectTiming::setIterationStart): Deleted.
(WebCore::AnimationEffectTiming::setIterations): Deleted.
(WebCore::AnimationEffectTiming::bindingsDuration const): Deleted.
(WebCore::AnimationEffectTiming::setBindingsDuration): Deleted.
(WebCore::AnimationEffectTiming::endTime const): Deleted.
(WebCore::AnimationEffectTiming::activeDuration const): Deleted.
(WebCore::AnimationEffectTiming::setEasing): Deleted.
* animation/AnimationEffectTiming.h:
(): Deleted.
* animation/AnimationEffectTiming.idl:
* animation/AnimationEffectTimingReadOnly.cpp: Copied from Source/WebCore/animation/AnimationEffectTiming.cpp.
(WebCore::AnimationEffectTimingReadOnly::create):
(WebCore::AnimationEffectTimingReadOnly::AnimationEffectTimingReadOnly):
(WebCore::AnimationEffectTimingReadOnly::~AnimationEffectTimingReadOnly):
(WebCore::AnimationEffectTimingReadOnly::setProperties):
(WebCore::AnimationEffectTimingReadOnly::setIterationStart):
(WebCore::AnimationEffectTimingReadOnly::setIterations):
(WebCore::AnimationEffectTimingReadOnly::bindingsDuration const):
(WebCore::AnimationEffectTimingReadOnly::setBindingsDuration):
(WebCore::AnimationEffectTimingReadOnly::setEasing):
(WebCore::AnimationEffectTimingReadOnly::endTime const):
(WebCore::AnimationEffectTimingReadOnly::activeDuration const):
* animation/AnimationEffectTimingReadOnly.h: Copied from Source/WebCore/animation/AnimationEffectTiming.h.
(WebCore::AnimationEffectTimingReadOnly::isAnimationEffectTiming const):
(WebCore::AnimationEffectTimingReadOnly::bindingsDelay const):
(WebCore::AnimationEffectTimingReadOnly::setBindingsDelay):
(WebCore::AnimationEffectTimingReadOnly::bindingsEndDelay const):
(WebCore::AnimationEffectTimingReadOnly::setBindingsEndDelay):
(WebCore::AnimationEffectTimingReadOnly::delay const):
(WebCore::AnimationEffectTimingReadOnly::setDelay):
(WebCore::AnimationEffectTimingReadOnly::endDelay const):
(WebCore::AnimationEffectTimingReadOnly::setEndDelay):
(WebCore::AnimationEffectTimingReadOnly::fill const):
(WebCore::AnimationEffectTimingReadOnly::setFill):
(WebCore::AnimationEffectTimingReadOnly::iterationStart const):
(WebCore::AnimationEffectTimingReadOnly::iterations const):
(WebCore::AnimationEffectTimingReadOnly::iterationDuration const):
(WebCore::AnimationEffectTimingReadOnly::setIterationDuration):
(WebCore::AnimationEffectTimingReadOnly::direction const):
(WebCore::AnimationEffectTimingReadOnly::setDirection):
(WebCore::AnimationEffectTimingReadOnly::easing const):
(WebCore::AnimationEffectTimingReadOnly::timingFunction const):
(WebCore::AnimationEffectTimingReadOnly::classType const):
* animation/AnimationEffectTimingReadOnly.idl: Renamed from Source/WebCore/animation/AnimationEffect.idl.
* animation/AnimationTimeline.h:
* animation/KeyframeEffect.cpp:
(WebCore::KeyframeEffect::create):
(WebCore::KeyframeEffect::KeyframeEffect):
(WebCore::IDLAttributeNameToAnimationPropertyName): Deleted.
(WebCore::CSSPropertyIDToIDLAttributeName): Deleted.
(WebCore::computeMissingKeyframeOffsets): Deleted.
(WebCore::processIterableKeyframes): Deleted.
(WebCore::processKeyframeLikeObject): Deleted.
(WebCore::processPropertyIndexedKeyframes): Deleted.
(WebCore::KeyframeEffect::getKeyframes): Deleted.
(WebCore::KeyframeEffect::processKeyframes): Deleted.
(WebCore::KeyframeEffect::computeStackingContextImpact): Deleted.
(WebCore::KeyframeEffect::apply): Deleted.
(WebCore::KeyframeEffect::shouldRunAccelerated): Deleted.
(WebCore::KeyframeEffect::getAnimatedStyle): Deleted.
(WebCore::KeyframeEffect::setAnimatedPropertiesInStyle): Deleted.
(WebCore::KeyframeEffect::startOrStopAccelerated): Deleted.
(WebCore::KeyframeEffect::renderer const): Deleted.
(WebCore::KeyframeEffect::currentStyle const): Deleted.
* animation/KeyframeEffect.h:
* animation/KeyframeEffect.idl:
* animation/KeyframeEffectReadOnly.cpp: Copied from Source/WebCore/animation/KeyframeEffect.cpp.
(WebCore::IDLAttributeNameToAnimationPropertyName):
(WebCore::CSSPropertyIDToIDLAttributeName):
(WebCore::computeMissingKeyframeOffsets):
(WebCore::processIterableKeyframes):
(WebCore::processKeyframeLikeObject):
(WebCore::processPropertyIndexedKeyframes):
(WebCore::KeyframeEffectReadOnly::create):
(WebCore::KeyframeEffectReadOnly::KeyframeEffectReadOnly):
(WebCore::KeyframeEffectReadOnly::getKeyframes):
(WebCore::KeyframeEffectReadOnly::processKeyframes):
(WebCore::KeyframeEffectReadOnly::computeStackingContextImpact):
(WebCore::KeyframeEffectReadOnly::apply):
(WebCore::KeyframeEffectReadOnly::shouldRunAccelerated):
(WebCore::KeyframeEffectReadOnly::getAnimatedStyle):
(WebCore::KeyframeEffectReadOnly::setAnimatedPropertiesInStyle):
(WebCore::KeyframeEffectReadOnly::startOrStopAccelerated):
(WebCore::KeyframeEffectReadOnly::renderer const):
(WebCore::KeyframeEffectReadOnly::currentStyle const):
* animation/KeyframeEffectReadOnly.h: Copied from Source/WebCore/animation/KeyframeEffect.h.
(WebCore::KeyframeEffectReadOnly::~KeyframeEffectReadOnly):
(WebCore::KeyframeEffectReadOnly::target const):
(WebCore::KeyframeEffectReadOnly::iterationComposite const):
(WebCore::KeyframeEffectReadOnly::composite const):
(WebCore::KeyframeEffectReadOnly::isRunningAccelerated const):
* animation/KeyframeEffectReadOnly.idl: Copied from Source/WebCore/animation/KeyframeEffect.idl.
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::create):
(WebCore::WebAnimation::setEffect):
* animation/WebAnimation.h:
* animation/WebAnimation.idl:
* bindings/js/JSAnimationEffectReadOnlyCustom.cpp: Copied from Source/WebCore/bindings/js/JSAnimationEffectCustom.cpp.
(WebCore::toJSNewlyCreated):
(WebCore::toJS):
* bindings/js/JSAnimationEffectTimingReadOnlyCustom.cpp: Renamed from Source/WebCore/bindings/js/JSAnimationEffectCustom.cpp.
(WebCore::toJSNewlyCreated):
(WebCore::toJS):
* bindings/js/JSCustomEventCustom.cpp:
(WebCore::JSCustomEvent::detail const): Fix an error introduced in webkit.org/b/179591.
* bindings/js/JSWebAnimationCustom.cpp:
(WebCore::constructJSWebAnimation):
* bindings/js/WebCoreBuiltinNames.h:
Canonical link: https://commits.webkit.org/198463@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@228333 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-02-09 19:11:32 +00:00
|
|
|
* Copyright (C) 2017-2018 Apple Inc. All rights reserved.
|
2017-10-24 07:51:59 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2018-11-06 11:15:30 +00:00
|
|
|
#include "AnimationEffect.h"
|
[Web Animations] Compute animation effect timing properties in batch
https://bugs.webkit.org/show_bug.cgi?id=192850
Reviewed by Dean Jackson.
We remove a host of functions from AnimationEffect that would allow the computation of various timing properties
defined by the Web Animations specification: phase, progress, current iteration, etc. Indeed, a lot of these functions
would call each other in a chain, and we would re-compute a lot of the earlier properties in those chains several times
when doing something like querying the animation progress. Additionally, some functions, such as WebAnimation::computeRelevance()
and WebAnimation::timeToNextTick() would yield the computation of several such properties numerous times. All of those
functions are called during each animation frame and are ripe for optimizations.
We now compute all timing properties across two functions:
1. the new AnimationEffect::getBasicTiming() which computes the local time, end time, active duration, active time and phase,
2. the existing AnimationEffect::getComputedTiming() which now also exposes the phase and simple iteration progress.
To support this we introduce a new BasicEffectTiming struct to contain the values computed in AnimationEffect::getBasicTiming()
and spun the AnimationEffect::Phase struct as AnimationEffectPhase so that it may be used across BasicEffectTiming and
ComputedEffectTiming.
No new test since there is no user-observable change.
* WebCore.xcodeproj/project.pbxproj:
* animation/AnimationEffect.cpp:
(WebCore::AnimationEffect::getTiming const):
(WebCore::AnimationEffect::getBasicTiming const):
(WebCore::AnimationEffect::getComputedTiming const):
(WebCore::AnimationEffect::localTime const): Deleted.
(WebCore::AnimationEffect::phase const): Deleted.
(WebCore::AnimationEffect::activeTime const): Deleted.
(WebCore::AnimationEffect::overallProgress const): Deleted.
(WebCore::AnimationEffect::simpleIterationProgress const): Deleted.
(WebCore::AnimationEffect::currentIteration const): Deleted.
(WebCore::AnimationEffect::currentDirection const): Deleted.
(WebCore::AnimationEffect::directedProgress const): Deleted.
(WebCore::AnimationEffect::transformedProgress const): Deleted.
(WebCore::AnimationEffect::iterationProgress const): Deleted.
(WebCore::AnimationEffect::getTiming): Deleted.
(WebCore::AnimationEffect::getComputedTiming): Deleted.
(WebCore::AnimationEffect::endTime const): Deleted.
(WebCore::AnimationEffect::activeDuration const): Deleted.
* animation/AnimationEffect.h:
* animation/AnimationEffectPhase.h: Copied from Source/WebCore/animation/ComputedEffectTiming.h.
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::updateCSSTransitionsForElement):
* animation/AnimationTimeline.h:
* animation/BasicEffectTiming.h: Copied from Source/WebCore/animation/ComputedEffectTiming.h.
* animation/ComputedEffectTiming.h:
* animation/DeclarativeAnimation.cpp:
(WebCore::DeclarativeAnimation::cancel):
(WebCore::DeclarativeAnimation::phaseWithoutEffect const):
(WebCore::DeclarativeAnimation::invalidateDOMEvents):
* animation/DeclarativeAnimation.h:
* animation/KeyframeEffect.cpp:
(WebCore::KeyframeEffect::apply):
(WebCore::KeyframeEffect::getAnimatedStyle):
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::effectEndTime const):
(WebCore::WebAnimation::computeRelevance):
(WebCore::WebAnimation::timeToNextTick const):
Canonical link: https://commits.webkit.org/207736@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239723 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-01-08 11:31:55 +00:00
|
|
|
#include "AnimationEffectPhase.h"
|
|
|
|
#include "BasicEffectTiming.h"
|
2018-11-06 11:15:15 +00:00
|
|
|
#include "ComputedEffectTiming.h"
|
2018-11-06 11:15:30 +00:00
|
|
|
#include "ExceptionOr.h"
|
|
|
|
#include "FillMode.h"
|
|
|
|
#include "KeyframeEffectOptions.h"
|
|
|
|
#include "OptionalEffectTiming.h"
|
|
|
|
#include "PlaybackDirection.h"
|
|
|
|
#include "TimingFunction.h"
|
[Web Animations] Implement getAnimations()
https://bugs.webkit.org/show_bug.cgi?id=179535
<rdar://problem/34932475>
Reviewed by Simon Fraser.
Source/WebCore:
We now allow a list of animations for a document, with Document.getAnimations(), or for an
element, with Animatable.getAnimations(), to be returned. In order to support this, we maintain
a map on AnimationTimeline of all animations for a given element. This map is invalidated
when an animation's timeline changes and when an animation's effect changes. Note that the
Web Animations spec mandates that an AnimationEffect can only be a single animation's effect.
Tests: http/wpt/wk-web-animations/interfaces/document-get-animations.html
http/wpt/wk-web-animations/interfaces/element-get-animations.html
http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship.html
* CMakeLists.txt: Add Animatable.idl.
* DerivedSources.make: Add Animatable.idl.
* WebCore.xcodeproj/project.pbxproj: Add Animatable.idl.
* animation/Animatable.idl: A new interface that Element implements and which currently only exposes
getAnimations(), the animate() method will be added later.
* animation/AnimationEffect.h: Add a new m_animation member to reference the animation using this
effect. This relationship is required so we guarantee that an effect is associated with a single
animation at most.
(WebCore::AnimationEffect::animation const):
(WebCore::AnimationEffect::setAnimation):
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::animationWasAddedToElement): New method to notify the timeline that an
animation registered with this timeline has been associated with a new element through its effect.
(WebCore::AnimationTimeline::animationWasRemovedFromElement): New method to notify the timeline that an
animation registered with this timeline has been disassociated with an element through its effect.
(WebCore::AnimationTimeline::animationsForElement): New method returning all animations registered with
this timeline for a given element.
* animation/AnimationTimeline.h:
(WebCore::AnimationTimeline::animations const): All animations registered with this timeline.
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::DocumentTimeline):
(WebCore::DocumentTimeline::detachFromDocument): Clear the reference between this timeline and its document.
(WebCore::DocumentTimeline::currentTime): Protect against a null Document reference.
(WebCore::DocumentTimeline::createDisplayRefreshMonitor const): Protect against a null Document reference.
* animation/DocumentTimeline.h:
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::create):
(WebCore::WebAnimation::setEffect): As an animation's effect changes, we need to ensure that the old
effect no longer has an associated animation, and that the new effect is associated with this animation.
Additionally, we update the element-to-animations map on the animation's timeline.
(WebCore::WebAnimation::setTimeline): Update the element-to-animations map on the former and new timeline.
* dom/Document.cpp:
(WebCore::Document::prepareForDestruction): Clear the relationship between this document and its timeline.
(WebCore::Document::getAnimations): Obtain all animations associated with this document's timeline.
* dom/Document.h:
* dom/Document.idl:
* dom/Element.cpp:
(WebCore::Element::getAnimations): Obtain all animations associated with this element.
* dom/Element.h:
* dom/Element.idl:
* testing/Internals.cpp:
* CMakeLists.txt:
* DerivedSources.make:
* WebCore.xcodeproj/project.pbxproj:
* animation/Animatable.idl:
* animation/AnimationEffect.h:
(WebCore::AnimationEffect::animation const):
(WebCore::AnimationEffect::setAnimation):
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::animationWasAddedToElement):
(WebCore::AnimationTimeline::animationWasRemovedFromElement):
(WebCore::AnimationTimeline::animationsForElement):
* animation/AnimationTimeline.h:
(WebCore::AnimationTimeline::animations const):
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::DocumentTimeline):
(WebCore::DocumentTimeline::detachFromDocument):
(WebCore::DocumentTimeline::currentTime):
(WebCore::DocumentTimeline::createDisplayRefreshMonitor const):
* animation/DocumentTimeline.h:
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::create):
(WebCore::WebAnimation::setEffect):
(WebCore::WebAnimation::setTimeline):
* dom/Document.cpp:
(WebCore::Document::prepareForDestruction):
(WebCore::Document::getAnimations):
* dom/Document.h:
* dom/Document.idl:
* dom/Element.cpp:
(WebCore::Element::getAnimations):
* dom/Element.h:
* dom/Element.idl:
* testing/Internals.cpp:
LayoutTests:
Update WPT expectations per new progressions and add three new tests that check the behavior of
Document.getAnimations(), Element.getAnimations() and the unique relationship between an Animation
and an AnimationEffect.
* http/wpt/web-animations/interfaces/Animatable/animate-expected.txt:
* http/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt:
* http/wpt/web-animations/interfaces/Document/getAnimations-expected.txt:
* http/wpt/wk-web-animations/interfaces/document-get-animations-expected.txt: Added.
* http/wpt/wk-web-animations/interfaces/document-get-animations.html: Added.
* http/wpt/wk-web-animations/interfaces/element-get-animations-expected.txt: Added.
* http/wpt/wk-web-animations/interfaces/element-get-animations.html: Added.
* http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship-expected.txt: Added.
* http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship.html: Added.
Canonical link: https://commits.webkit.org/195647@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@224760 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-11-13 19:14:47 +00:00
|
|
|
#include "WebAnimation.h"
|
2018-11-06 11:15:30 +00:00
|
|
|
#include "WebAnimationUtilities.h"
|
2017-10-24 07:51:59 +00:00
|
|
|
#include <wtf/Forward.h>
|
|
|
|
#include <wtf/Ref.h>
|
|
|
|
#include <wtf/RefCounted.h>
|
|
|
|
#include <wtf/RefPtr.h>
|
2018-11-06 11:15:30 +00:00
|
|
|
#include <wtf/Seconds.h>
|
|
|
|
#include <wtf/Variant.h>
|
[Web Animations] Querying the current time of a finished CSSAnimation after removing its target leads to a crash
https://bugs.webkit.org/show_bug.cgi?id=187906
Reviewed by Dean Jackson.
Source/WebCore:
Test: webanimations/accessing-current-time-after-finished-css-animation-target-removal.html
Because we carelessly look at a CSSAnimation's effect's timing in DeclarativeAnimation::bindingsCurrentTime
without checking that the effect is non-null, we can crash in the case where the animation is finished and
its target element has been removed, which caused the effect to be set to null.
We do not actually fix the lack of a null check, which will be the scope of a different patch, but instead
ensure that we do _not_ set the animation's effect to null when its target is removed, which used to be
performed via a call to WebAnimation::remove(). Instead, we introduce AnimationTimeline::elementWasRemoved()
which notifies the timeline of an element being removed such that we may stop referencing any animation
targeting this element from the various data structures holding strong references to the animation in question,
and we then cancel the animation silently, which is a new option that ensures promises aren't resolved or
rejected as a result.
Finally, the WebAnimation and AnimationEffectReadOnly classes established a ref-cycle as WebAnimation has
`RefPtr<AnimationEffectReadOnly> m_effect` and AnimationEffectReadOnly has `RefPtr<WebAnimation> m_animation`.
While it is correct that WebAnimation owns its effect, which is established by the DOM API, the
reverse is not correct since we only hold the reverse internally for the benefit of our implementation.
As such, we change AnimationEffectReadOnly's m_animation to be a WeakPtr<WebAnimation>. This means not
calling WebAnimation::remove() and simply removing the animation from the animation maps on the timeline
is sufficient to guarantee that the document timeline will not leak (and with it the document).
* animation/AnimationEffectReadOnly.h:
(WebCore::AnimationEffectReadOnly::setAnimation):
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::elementWasRemoved):
* animation/AnimationTimeline.h:
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::cancel):
(WebCore::WebAnimation::resetPendingTasks):
* animation/WebAnimation.h:
* dom/Element.cpp:
(WebCore::Element::removedFromAncestor):
* rendering/updating/RenderTreeUpdater.cpp:
(WebCore::RenderTreeUpdater::tearDownRenderers):
LayoutTests:
Add a new test that checks the behavior of a CSSAnimation instance after its completion and removal of its target.
* webanimations/accessing-current-time-after-finished-css-animation-target-removal-expected.txt: Added.
* webanimations/accessing-current-time-after-finished-css-animation-target-removal.html: Added.
Canonical link: https://commits.webkit.org/203089@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@234109 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-07-23 20:23:18 +00:00
|
|
|
#include <wtf/WeakPtr.h>
|
2017-10-24 07:51:59 +00:00
|
|
|
|
|
|
|
namespace WebCore {
|
|
|
|
|
[Web Animations] Use a keyframe effect stack to resolve animations on an element
https://bugs.webkit.org/show_bug.cgi?id=204010
Reviewed by Dean Jackson.
Until now, when resolving animations for an element, we would call animationsForElement() during each resolution which
means doing several hash table lookups to locate the various classes of animations for that given element, sorting each
of those animations and inserting them into a new Vector.
We now use a KeyframeEffectStack which keeps a list of KeyframeEffect objects that apply to a given target, provided the
effect also has a valid animation and that animation has a valid timeline, all pre-conditions for that effect to produce
an animated value. Any time one of those pre-conditions change, we update the membership of that effect in the stack.
The KeyframeEffectStack is a new member of ElementRareData.
Now, each time we resolve an animation for an element, we iterate over the KeyframeEffect objects returned by calling
sortEffects() on the KeyframeEffectStack which will sort the stack's effects only if a new effect had been added since
the last iteration, which means that simple animations that are not mutated will require sorting of the stack just once,
and the addition of several animations in a single animation frame will require sorting just once as well.
It was also found while doing this work that Style::TreeResolver::createAnimatedElementUpdate would call RenderStyle::clonePtr()
for any element that was part of a document containing a timeline, regardless of whether that element had any animations. Now
we check whether that element's KeyframeEffectStack contains any effects prior to cloning the style.
No tests or changes to existed test expectations as this should not yield any change in behavior.
* Sources.txt: Add the new KeyframeEffectStack.
* WebCore.xcodeproj/project.pbxproj:
* animation/AnimationEffect.h:
(WebCore::AnimationEffect::setAnimation):
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::removeAnimation):
(WebCore::AnimationTimeline::updateCSSAnimationsForElement): Since we need to know the order of CSS @keyframes rules listed in animation-name
when sorting effects, we must compile the ordered list of those @keyframe rules as we update CSS animations for an element and store it on its
KeyframeEffectStack.
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::resolveAnimationsForElement): Deleted. Replaced by Element::applyKeyframeEffects().
* animation/DocumentTimeline.h:
* animation/KeyframeEffect.cpp:
(WebCore::KeyframeEffect::animationTimelineDidChange):
(WebCore::KeyframeEffect::setAnimation):
(WebCore::KeyframeEffect::setTarget):
* animation/KeyframeEffect.h:
* animation/KeyframeEffectStack.cpp: Added.
(WebCore::KeyframeEffectStack::KeyframeEffectStack):
(WebCore::KeyframeEffectStack::~KeyframeEffectStack):
(WebCore::KeyframeEffectStack::addEffect):
(WebCore::KeyframeEffectStack::removeEffect):
(WebCore::KeyframeEffectStack::sortedEffects):
(WebCore::KeyframeEffectStack::ensureEffectsAreSorted):
(WebCore::KeyframeEffectStack::setCSSAnimationNames):
* animation/KeyframeEffectStack.h: Added.
(WebCore::KeyframeEffectStack::hasEffects const):
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::setTimelineInternal):
(WebCore::WebAnimation::persist):
* dom/Element.cpp:
(WebCore::Element::ensureKeyframeEffectStack):
(WebCore::Element::hasKeyframeEffects const):
(WebCore::Element::applyKeyframeEffects):
* dom/Element.h:
* dom/ElementRareData.cpp:
* dom/ElementRareData.h:
(WebCore::ElementRareData::keyframeEffectStack):
(WebCore::ElementRareData::setKeyframeEffectStack):
* style/StyleTreeResolver.cpp:
(WebCore::Style::TreeResolver::createAnimatedElementUpdate):
Canonical link: https://commits.webkit.org/217343@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@252253 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-11-08 20:40:57 +00:00
|
|
|
class AnimationEffect : public RefCounted<AnimationEffect>, public CanMakeWeakPtr<AnimationEffect> {
|
2017-10-24 07:51:59 +00:00
|
|
|
public:
|
2018-11-06 11:15:15 +00:00
|
|
|
virtual ~AnimationEffect();
|
[Web Animations] Implement basic to-from animations
https://bugs.webkit.org/show_bug.cgi?id=179707
<rdar://problem/34932456>
Source/WebCore:
We can now actually perform an animation, in software only, when provided two keyframes on an AnimationEffect.
To parse a keyframes object from JS, we use the StyleResolver to create RenderStyle objects based on the strings
provided for the property names and values. Then, when the DocumentTimeline indicates that animations are ready
to be updated, we invalidate the style of elements with animations, so that during style resolution we can perform
blending between the RenderStyles for each keyframe.
Reviewed by Dean Jackson.
* animation/AnimationEffect.h:
(WebCore::AnimationEffect::~AnimationEffect): Deleted.
* animation/AnimationTimeline.h:
(WebCore::AnimationTimeline::elementToAnimationsMap const):
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::animationResolutionTimerFired):
(WebCore::DocumentTimeline::updateAnimations): Renamed from resolveAnimations() since we're not
actually resolving animations, merely invalidating styles in preparation for resolution.
(WebCore::DocumentTimeline::resolveAnimations): Deleted.
* animation/DocumentTimeline.h:
* animation/KeyframeEffect.cpp:
(WebCore::KeyframeEffect::create): Pass the keyframes argument to setKeyframes() and forward the
exception in case one was raised in the setter.
(WebCore::KeyframeEffect::setKeyframes): Pass the keyframes argument to processKeyframes() and
forward the exception in case one was raised during processing.
(WebCore::KeyframeEffect::processKeyframes): Deal with exactly two keyframes, set at 0 and 1 offsets,
specified in array forms for the keyframes object. As we parse the content of the provided JS object,
we create RenderStyle objects using the element's StyleResolver from a CSS text string we create
based on the property and values as strings.
(WebCore::KeyframeEffect::applyAtLocalTime): Compute the progress based on the local time and duration,
using the existing CSSPropertyAnimation::blendProperties() mechanics to perform the blend between the
from and to keyframes.
* animation/KeyframeEffect.h:
* animation/KeyframeEffect.idl:
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::resolve):
* animation/WebAnimation.h:
* bindings/IDLTypes.h:
(WebCore::IDLObject::nullValue): Make JSC::Strong an optional type.
* dom/Document.h:
(WebCore::Document::existingTimeline const): Provide an explicit method for call sites to check existence
of a timeline before forcing one to be created if missing by calling timeline().
* dom/Element.cpp:
(WebCore::Element::getAnimations): Do not force the creation of a timeline if one isn't already created.
* style/StyleTreeResolver.cpp:
(WebCore::Style::TreeResolver::createAnimatedElementUpdate): When applying styles, account for any Web
Animation applied to the provided element.
LayoutTests:
Reviewed by Dean Jackson.
Update existing tests to explicitly pass null for keyframes and update WPT expectations.
* http/wpt/web-animations/interfaces/AnimationTimeline/document-timeline-expected.txt:
* http/wpt/web-animations/interfaces/KeyframeEffect/constructor-expected.txt:
* http/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001-expected.txt:
* http/wpt/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002-expected.txt:
* http/wpt/web-animations/interfaces/KeyframeEffect/setKeyframes-expected.txt:
* http/wpt/wk-web-animations/interfaces/element-get-animations.html:
* http/wpt/wk-web-animations/timing-model/animation-creation-basic.html:
* http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship.html:
* http/wpt/wk-web-animations/timing-model/animation-interface-effect-property.html:
* http/wpt/wk-web-animations/timing-model/keyframe-effect-expected.txt:
* http/wpt/wk-web-animations/timing-model/keyframe-effect-interface-timing-duration.html:
* http/wpt/wk-web-animations/timing-model/keyframe-effect.html:
Canonical link: https://commits.webkit.org/195776@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@224897 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-11-15 21:35:38 +00:00
|
|
|
|
2018-11-06 11:15:15 +00:00
|
|
|
virtual bool isKeyframeEffect() const { return false; }
|
2018-11-06 11:15:30 +00:00
|
|
|
|
2020-04-24 21:42:50 +00:00
|
|
|
EffectTiming getBindingsTiming() const;
|
[Web Animations] Compute animation effect timing properties in batch
https://bugs.webkit.org/show_bug.cgi?id=192850
Reviewed by Dean Jackson.
We remove a host of functions from AnimationEffect that would allow the computation of various timing properties
defined by the Web Animations specification: phase, progress, current iteration, etc. Indeed, a lot of these functions
would call each other in a chain, and we would re-compute a lot of the earlier properties in those chains several times
when doing something like querying the animation progress. Additionally, some functions, such as WebAnimation::computeRelevance()
and WebAnimation::timeToNextTick() would yield the computation of several such properties numerous times. All of those
functions are called during each animation frame and are ripe for optimizations.
We now compute all timing properties across two functions:
1. the new AnimationEffect::getBasicTiming() which computes the local time, end time, active duration, active time and phase,
2. the existing AnimationEffect::getComputedTiming() which now also exposes the phase and simple iteration progress.
To support this we introduce a new BasicEffectTiming struct to contain the values computed in AnimationEffect::getBasicTiming()
and spun the AnimationEffect::Phase struct as AnimationEffectPhase so that it may be used across BasicEffectTiming and
ComputedEffectTiming.
No new test since there is no user-observable change.
* WebCore.xcodeproj/project.pbxproj:
* animation/AnimationEffect.cpp:
(WebCore::AnimationEffect::getTiming const):
(WebCore::AnimationEffect::getBasicTiming const):
(WebCore::AnimationEffect::getComputedTiming const):
(WebCore::AnimationEffect::localTime const): Deleted.
(WebCore::AnimationEffect::phase const): Deleted.
(WebCore::AnimationEffect::activeTime const): Deleted.
(WebCore::AnimationEffect::overallProgress const): Deleted.
(WebCore::AnimationEffect::simpleIterationProgress const): Deleted.
(WebCore::AnimationEffect::currentIteration const): Deleted.
(WebCore::AnimationEffect::currentDirection const): Deleted.
(WebCore::AnimationEffect::directedProgress const): Deleted.
(WebCore::AnimationEffect::transformedProgress const): Deleted.
(WebCore::AnimationEffect::iterationProgress const): Deleted.
(WebCore::AnimationEffect::getTiming): Deleted.
(WebCore::AnimationEffect::getComputedTiming): Deleted.
(WebCore::AnimationEffect::endTime const): Deleted.
(WebCore::AnimationEffect::activeDuration const): Deleted.
* animation/AnimationEffect.h:
* animation/AnimationEffectPhase.h: Copied from Source/WebCore/animation/ComputedEffectTiming.h.
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::updateCSSTransitionsForElement):
* animation/AnimationTimeline.h:
* animation/BasicEffectTiming.h: Copied from Source/WebCore/animation/ComputedEffectTiming.h.
* animation/ComputedEffectTiming.h:
* animation/DeclarativeAnimation.cpp:
(WebCore::DeclarativeAnimation::cancel):
(WebCore::DeclarativeAnimation::phaseWithoutEffect const):
(WebCore::DeclarativeAnimation::invalidateDOMEvents):
* animation/DeclarativeAnimation.h:
* animation/KeyframeEffect.cpp:
(WebCore::KeyframeEffect::apply):
(WebCore::KeyframeEffect::getAnimatedStyle):
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::effectEndTime const):
(WebCore::WebAnimation::computeRelevance):
(WebCore::WebAnimation::timeToNextTick const):
Canonical link: https://commits.webkit.org/207736@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239723 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-01-08 11:31:55 +00:00
|
|
|
EffectTiming getTiming() const;
|
2021-05-30 16:11:40 +00:00
|
|
|
BasicEffectTiming getBasicTiming(std::optional<Seconds> = std::nullopt) const;
|
2020-04-24 21:42:50 +00:00
|
|
|
ComputedEffectTiming getBindingsComputedTiming() const;
|
2021-05-30 16:11:40 +00:00
|
|
|
ComputedEffectTiming getComputedTiming(std::optional<Seconds> = std::nullopt) const;
|
|
|
|
ExceptionOr<void> bindingsUpdateTiming(std::optional<OptionalEffectTiming>);
|
|
|
|
ExceptionOr<void> updateTiming(std::optional<OptionalEffectTiming>);
|
2018-11-06 11:15:30 +00:00
|
|
|
|
2021-05-30 16:11:40 +00:00
|
|
|
virtual void apply(RenderStyle& targetStyle, const RenderStyle* parentElementStyle, std::optional<Seconds> = std::nullopt) = 0;
|
2018-02-15 23:33:44 +00:00
|
|
|
virtual void invalidate() = 0;
|
2020-02-10 17:24:49 +00:00
|
|
|
virtual void animationDidTick() = 0;
|
|
|
|
virtual void animationDidPlay() = 0;
|
2020-05-13 19:26:58 +00:00
|
|
|
virtual void animationDidChangeTimingProperties() = 0;
|
2019-11-16 17:11:44 +00:00
|
|
|
virtual void animationWasCanceled() = 0;
|
[Web Animations] Handle relative length units
https://bugs.webkit.org/show_bug.cgi?id=186047
Reviewed by Dean Jackson.
LayoutTests/imported/w3c:
Record WPT test progressions.
* web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-context-expected.txt:
Source/WebCore:
In order to correctly handle relative units, such as "em", "vw" and "vh", we need to do two things.
First, because we need to apply the cascade to correctly compute relative lengths, we need to delay the computation of
"blending keyframes" to when we have both keyframes data and a valid target. This also means that we need to reset blending
keyframes when the target changes. As a result, old call sites of updateBlendingKeyframes() have been replaced by a call to
m_blendingKeyframes.clear() and the method now gets called as part of apply() with the RenderStyle of the targeted element
as a parameter.
Second, and as a result of the first change, we need to update the accelerated animation state based on animation
progress rather than when calling specific methods, such as Animation.play() and Animation.pause(), since blending
keyframes may not be available at those more specific call sites. We now have a new updateAcceleratedAnimationState()
method that gets called as part of apply(). We also rename animationPlayStateDidChange() to animationSuspensionStateDidChange()
since this method was specific to suspension and had a confusing name.
* animation/AnimationEffectReadOnly.h: Rename animationPlayStateDidChange() to animationSuspensionStateDidChange().
* animation/KeyframeEffectReadOnly.cpp:
(WebCore::KeyframeEffectReadOnly::getKeyframes): Fix a crash that revealed itself after other changes in this patch. We would later
call into ComputedStyleExtractor::animationSuspensionStateDidChange() and this would yield an assertion because we'd call potentially
call it with a custom CSS property.
(WebCore::KeyframeEffectReadOnly::processKeyframes): Reset blending keyframes instead of calling updateBlendingKeyframes() since
blending keyframes is now performed asynchronously upon style resolution.
(WebCore::KeyframeEffectReadOnly::updateBlendingKeyframes): Take the target's RenderStyle as a parameter and use it to reset the
associated StyleResolver's state, just like we do in StyleResolver::keyframeStylesForAnimation(), so that the CSS cascade is correctly
accounted for when computing values using relative length units. Since blending keyframes can now be computed several times for a
given set of keyframes, since the effect's target may change, we also need to create a copy of the MutableStyleProperties to pass
to StyleRuleKeyframe::create().
(WebCore::KeyframeEffectReadOnly::setTarget): Reset blending keyframes instead of calling updateBlendingKeyframes() since
blending keyframes is now performed asynchronously upon style resolution.
(WebCore::KeyframeEffectReadOnly::apply): Update blending keyframes and the accelerated animation state.
(WebCore::KeyframeEffectReadOnly::getAnimatedStyle): Make sure we have blending keyframes with a call to updateBlendingKeyframes()
in case the animation hasn't naturally progressed when this method is called.
(WebCore::KeyframeEffectReadOnly::setAnimatedPropertiesInStyle): Make sure we have blending keyframes with a call to
updateBlendingKeyframes() in case the animation hasn't naturally progressed when this method is called.
(WebCore::KeyframeEffectReadOnly::updateAcceleratedAnimationState): Account for the animation's local time and play state to update
the accelerated animation state.
(WebCore::KeyframeEffectReadOnly::addPendingAcceleratedAction): Record the last accelerated action in a member variable which we can
use to determine if we're running accelerated accounting for uncommited changes.
(WebCore::KeyframeEffectReadOnly::animationDidSeek): Only record an AcceleratedAction::Seek action if we're already running accelerated.
(WebCore::KeyframeEffectReadOnly::animationSuspensionStateDidChange): Only record an AcceleratedAction::Pause or AcceleratedAction::Play
action if we're already running accelerated.
(WebCore::KeyframeEffectReadOnly::applyPendingAcceleratedActions): Ensure we clone and clear the list of accelerated actions and check that
we have any cloned actions before proceeding any further. Then we can stop accounting for m_startedAccelerated since the list of accelerated
actions already account for animation state changes.
(WebCore::KeyframeEffectReadOnly::animationPlayStateDidChange): Deleted.
* animation/KeyframeEffectReadOnly.h:
(WebCore::KeyframeEffectReadOnly::isRunningAccelerated const): Account for the m_lastRecordedAcceleratedAction to identify whether we're running.
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::play): Stop calling animationPlayStateDidChange() directly since the accelerated animation state is now updated when
the animation's effect is applied.
(WebCore::WebAnimation::pause): Stop calling animationPlayStateDidChange() directly since the accelerated animation state is now updated when
the animation's effect is applied.
(WebCore::WebAnimation::resolve): Make sure we update the finished state prior to applying the animation's effect since the play state can
change when updating the finished state and KeyframeEffectReadOnly::updateAcceleratedAnimationState(), which is called when calling into
KeyframeEffectReadOnly::apply(), relies on it to correctly update the accelerated animation state.
(WebCore::WebAnimation::setSuspended): Rename animationPlayStateDidChange() to animationSuspensionStateDidChange().
* css/StyleResolver.cpp:
(WebCore::StyleResolver::setNewStateWithElement): Add a new public method to reset a StyleResolver's state such that we can call it when creating
blending keyframes for JS-originated animations just like we do when creating blending keyframes for CSS Animations in keyframeStylesForAnimation().
(WebCore::StyleResolver::keyframeStylesForAnimation): Use the new setNewStateWithElement() method.
* css/StyleResolver.h:
LayoutTests:
Record WPT test progressions and updated failures.
* platform/ios/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property-expected.txt:
* platform/ios/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property-expected.txt:
* platform/ios/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/interpolation-per-property-expected.txt:
* platform/mac/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property-expected.txt:
* platform/mac/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property-expected.txt:
* platform/mac/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/interpolation-per-property-expected.txt:
* platform/mac-sierra/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property-expected.txt:
* platform/mac-sierra/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property-expected.txt:
* platform/mac-sierra/imported/w3c/web-platform-tests/web-animations/animation-model/animation-types/interpolation-per-property-expected.txt:
Canonical link: https://commits.webkit.org/201479@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232255 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-05-29 11:59:56 +00:00
|
|
|
virtual void animationSuspensionStateDidChange(bool) = 0;
|
[Web Animations] Use a keyframe effect stack to resolve animations on an element
https://bugs.webkit.org/show_bug.cgi?id=204010
Reviewed by Dean Jackson.
Until now, when resolving animations for an element, we would call animationsForElement() during each resolution which
means doing several hash table lookups to locate the various classes of animations for that given element, sorting each
of those animations and inserting them into a new Vector.
We now use a KeyframeEffectStack which keeps a list of KeyframeEffect objects that apply to a given target, provided the
effect also has a valid animation and that animation has a valid timeline, all pre-conditions for that effect to produce
an animated value. Any time one of those pre-conditions change, we update the membership of that effect in the stack.
The KeyframeEffectStack is a new member of ElementRareData.
Now, each time we resolve an animation for an element, we iterate over the KeyframeEffect objects returned by calling
sortEffects() on the KeyframeEffectStack which will sort the stack's effects only if a new effect had been added since
the last iteration, which means that simple animations that are not mutated will require sorting of the stack just once,
and the addition of several animations in a single animation frame will require sorting just once as well.
It was also found while doing this work that Style::TreeResolver::createAnimatedElementUpdate would call RenderStyle::clonePtr()
for any element that was part of a document containing a timeline, regardless of whether that element had any animations. Now
we check whether that element's KeyframeEffectStack contains any effects prior to cloning the style.
No tests or changes to existed test expectations as this should not yield any change in behavior.
* Sources.txt: Add the new KeyframeEffectStack.
* WebCore.xcodeproj/project.pbxproj:
* animation/AnimationEffect.h:
(WebCore::AnimationEffect::setAnimation):
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::removeAnimation):
(WebCore::AnimationTimeline::updateCSSAnimationsForElement): Since we need to know the order of CSS @keyframes rules listed in animation-name
when sorting effects, we must compile the ordered list of those @keyframe rules as we update CSS animations for an element and store it on its
KeyframeEffectStack.
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::resolveAnimationsForElement): Deleted. Replaced by Element::applyKeyframeEffects().
* animation/DocumentTimeline.h:
* animation/KeyframeEffect.cpp:
(WebCore::KeyframeEffect::animationTimelineDidChange):
(WebCore::KeyframeEffect::setAnimation):
(WebCore::KeyframeEffect::setTarget):
* animation/KeyframeEffect.h:
* animation/KeyframeEffectStack.cpp: Added.
(WebCore::KeyframeEffectStack::KeyframeEffectStack):
(WebCore::KeyframeEffectStack::~KeyframeEffectStack):
(WebCore::KeyframeEffectStack::addEffect):
(WebCore::KeyframeEffectStack::removeEffect):
(WebCore::KeyframeEffectStack::sortedEffects):
(WebCore::KeyframeEffectStack::ensureEffectsAreSorted):
(WebCore::KeyframeEffectStack::setCSSAnimationNames):
* animation/KeyframeEffectStack.h: Added.
(WebCore::KeyframeEffectStack::hasEffects const):
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::setTimelineInternal):
(WebCore::WebAnimation::persist):
* dom/Element.cpp:
(WebCore::Element::ensureKeyframeEffectStack):
(WebCore::Element::hasKeyframeEffects const):
(WebCore::Element::applyKeyframeEffects):
* dom/Element.h:
* dom/ElementRareData.cpp:
* dom/ElementRareData.h:
(WebCore::ElementRareData::keyframeEffectStack):
(WebCore::ElementRareData::setKeyframeEffectStack):
* style/StyleTreeResolver.cpp:
(WebCore::Style::TreeResolver::createAnimatedElementUpdate):
Canonical link: https://commits.webkit.org/217343@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@252253 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-11-08 20:40:57 +00:00
|
|
|
virtual void animationTimelineDidChange(AnimationTimeline*) = 0;
|
2017-10-24 07:51:59 +00:00
|
|
|
|
[Web Animations] Implement getAnimations()
https://bugs.webkit.org/show_bug.cgi?id=179535
<rdar://problem/34932475>
Reviewed by Simon Fraser.
Source/WebCore:
We now allow a list of animations for a document, with Document.getAnimations(), or for an
element, with Animatable.getAnimations(), to be returned. In order to support this, we maintain
a map on AnimationTimeline of all animations for a given element. This map is invalidated
when an animation's timeline changes and when an animation's effect changes. Note that the
Web Animations spec mandates that an AnimationEffect can only be a single animation's effect.
Tests: http/wpt/wk-web-animations/interfaces/document-get-animations.html
http/wpt/wk-web-animations/interfaces/element-get-animations.html
http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship.html
* CMakeLists.txt: Add Animatable.idl.
* DerivedSources.make: Add Animatable.idl.
* WebCore.xcodeproj/project.pbxproj: Add Animatable.idl.
* animation/Animatable.idl: A new interface that Element implements and which currently only exposes
getAnimations(), the animate() method will be added later.
* animation/AnimationEffect.h: Add a new m_animation member to reference the animation using this
effect. This relationship is required so we guarantee that an effect is associated with a single
animation at most.
(WebCore::AnimationEffect::animation const):
(WebCore::AnimationEffect::setAnimation):
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::animationWasAddedToElement): New method to notify the timeline that an
animation registered with this timeline has been associated with a new element through its effect.
(WebCore::AnimationTimeline::animationWasRemovedFromElement): New method to notify the timeline that an
animation registered with this timeline has been disassociated with an element through its effect.
(WebCore::AnimationTimeline::animationsForElement): New method returning all animations registered with
this timeline for a given element.
* animation/AnimationTimeline.h:
(WebCore::AnimationTimeline::animations const): All animations registered with this timeline.
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::DocumentTimeline):
(WebCore::DocumentTimeline::detachFromDocument): Clear the reference between this timeline and its document.
(WebCore::DocumentTimeline::currentTime): Protect against a null Document reference.
(WebCore::DocumentTimeline::createDisplayRefreshMonitor const): Protect against a null Document reference.
* animation/DocumentTimeline.h:
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::create):
(WebCore::WebAnimation::setEffect): As an animation's effect changes, we need to ensure that the old
effect no longer has an associated animation, and that the new effect is associated with this animation.
Additionally, we update the element-to-animations map on the animation's timeline.
(WebCore::WebAnimation::setTimeline): Update the element-to-animations map on the former and new timeline.
* dom/Document.cpp:
(WebCore::Document::prepareForDestruction): Clear the relationship between this document and its timeline.
(WebCore::Document::getAnimations): Obtain all animations associated with this document's timeline.
* dom/Document.h:
* dom/Document.idl:
* dom/Element.cpp:
(WebCore::Element::getAnimations): Obtain all animations associated with this element.
* dom/Element.h:
* dom/Element.idl:
* testing/Internals.cpp:
* CMakeLists.txt:
* DerivedSources.make:
* WebCore.xcodeproj/project.pbxproj:
* animation/Animatable.idl:
* animation/AnimationEffect.h:
(WebCore::AnimationEffect::animation const):
(WebCore::AnimationEffect::setAnimation):
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::animationWasAddedToElement):
(WebCore::AnimationTimeline::animationWasRemovedFromElement):
(WebCore::AnimationTimeline::animationsForElement):
* animation/AnimationTimeline.h:
(WebCore::AnimationTimeline::animations const):
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::DocumentTimeline):
(WebCore::DocumentTimeline::detachFromDocument):
(WebCore::DocumentTimeline::currentTime):
(WebCore::DocumentTimeline::createDisplayRefreshMonitor const):
* animation/DocumentTimeline.h:
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::create):
(WebCore::WebAnimation::setEffect):
(WebCore::WebAnimation::setTimeline):
* dom/Document.cpp:
(WebCore::Document::prepareForDestruction):
(WebCore::Document::getAnimations):
* dom/Document.h:
* dom/Document.idl:
* dom/Element.cpp:
(WebCore::Element::getAnimations):
* dom/Element.h:
* dom/Element.idl:
* testing/Internals.cpp:
LayoutTests:
Update WPT expectations per new progressions and add three new tests that check the behavior of
Document.getAnimations(), Element.getAnimations() and the unique relationship between an Animation
and an AnimationEffect.
* http/wpt/web-animations/interfaces/Animatable/animate-expected.txt:
* http/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt:
* http/wpt/web-animations/interfaces/Document/getAnimations-expected.txt:
* http/wpt/wk-web-animations/interfaces/document-get-animations-expected.txt: Added.
* http/wpt/wk-web-animations/interfaces/document-get-animations.html: Added.
* http/wpt/wk-web-animations/interfaces/element-get-animations-expected.txt: Added.
* http/wpt/wk-web-animations/interfaces/element-get-animations.html: Added.
* http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship-expected.txt: Added.
* http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship.html: Added.
Canonical link: https://commits.webkit.org/195647@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@224760 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-11-13 19:14:47 +00:00
|
|
|
WebAnimation* animation() const { return m_animation.get(); }
|
[Web Animations] Use a keyframe effect stack to resolve animations on an element
https://bugs.webkit.org/show_bug.cgi?id=204010
Reviewed by Dean Jackson.
Until now, when resolving animations for an element, we would call animationsForElement() during each resolution which
means doing several hash table lookups to locate the various classes of animations for that given element, sorting each
of those animations and inserting them into a new Vector.
We now use a KeyframeEffectStack which keeps a list of KeyframeEffect objects that apply to a given target, provided the
effect also has a valid animation and that animation has a valid timeline, all pre-conditions for that effect to produce
an animated value. Any time one of those pre-conditions change, we update the membership of that effect in the stack.
The KeyframeEffectStack is a new member of ElementRareData.
Now, each time we resolve an animation for an element, we iterate over the KeyframeEffect objects returned by calling
sortEffects() on the KeyframeEffectStack which will sort the stack's effects only if a new effect had been added since
the last iteration, which means that simple animations that are not mutated will require sorting of the stack just once,
and the addition of several animations in a single animation frame will require sorting just once as well.
It was also found while doing this work that Style::TreeResolver::createAnimatedElementUpdate would call RenderStyle::clonePtr()
for any element that was part of a document containing a timeline, regardless of whether that element had any animations. Now
we check whether that element's KeyframeEffectStack contains any effects prior to cloning the style.
No tests or changes to existed test expectations as this should not yield any change in behavior.
* Sources.txt: Add the new KeyframeEffectStack.
* WebCore.xcodeproj/project.pbxproj:
* animation/AnimationEffect.h:
(WebCore::AnimationEffect::setAnimation):
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::removeAnimation):
(WebCore::AnimationTimeline::updateCSSAnimationsForElement): Since we need to know the order of CSS @keyframes rules listed in animation-name
when sorting effects, we must compile the ordered list of those @keyframe rules as we update CSS animations for an element and store it on its
KeyframeEffectStack.
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::resolveAnimationsForElement): Deleted. Replaced by Element::applyKeyframeEffects().
* animation/DocumentTimeline.h:
* animation/KeyframeEffect.cpp:
(WebCore::KeyframeEffect::animationTimelineDidChange):
(WebCore::KeyframeEffect::setAnimation):
(WebCore::KeyframeEffect::setTarget):
* animation/KeyframeEffect.h:
* animation/KeyframeEffectStack.cpp: Added.
(WebCore::KeyframeEffectStack::KeyframeEffectStack):
(WebCore::KeyframeEffectStack::~KeyframeEffectStack):
(WebCore::KeyframeEffectStack::addEffect):
(WebCore::KeyframeEffectStack::removeEffect):
(WebCore::KeyframeEffectStack::sortedEffects):
(WebCore::KeyframeEffectStack::ensureEffectsAreSorted):
(WebCore::KeyframeEffectStack::setCSSAnimationNames):
* animation/KeyframeEffectStack.h: Added.
(WebCore::KeyframeEffectStack::hasEffects const):
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::setTimelineInternal):
(WebCore::WebAnimation::persist):
* dom/Element.cpp:
(WebCore::Element::ensureKeyframeEffectStack):
(WebCore::Element::hasKeyframeEffects const):
(WebCore::Element::applyKeyframeEffects):
* dom/Element.h:
* dom/ElementRareData.cpp:
* dom/ElementRareData.h:
(WebCore::ElementRareData::keyframeEffectStack):
(WebCore::ElementRareData::setKeyframeEffectStack):
* style/StyleTreeResolver.cpp:
(WebCore::Style::TreeResolver::createAnimatedElementUpdate):
Canonical link: https://commits.webkit.org/217343@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@252253 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2019-11-08 20:40:57 +00:00
|
|
|
virtual void setAnimation(WebAnimation* animation) { m_animation = makeWeakPtr(animation); }
|
[Web Animations] Implement getAnimations()
https://bugs.webkit.org/show_bug.cgi?id=179535
<rdar://problem/34932475>
Reviewed by Simon Fraser.
Source/WebCore:
We now allow a list of animations for a document, with Document.getAnimations(), or for an
element, with Animatable.getAnimations(), to be returned. In order to support this, we maintain
a map on AnimationTimeline of all animations for a given element. This map is invalidated
when an animation's timeline changes and when an animation's effect changes. Note that the
Web Animations spec mandates that an AnimationEffect can only be a single animation's effect.
Tests: http/wpt/wk-web-animations/interfaces/document-get-animations.html
http/wpt/wk-web-animations/interfaces/element-get-animations.html
http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship.html
* CMakeLists.txt: Add Animatable.idl.
* DerivedSources.make: Add Animatable.idl.
* WebCore.xcodeproj/project.pbxproj: Add Animatable.idl.
* animation/Animatable.idl: A new interface that Element implements and which currently only exposes
getAnimations(), the animate() method will be added later.
* animation/AnimationEffect.h: Add a new m_animation member to reference the animation using this
effect. This relationship is required so we guarantee that an effect is associated with a single
animation at most.
(WebCore::AnimationEffect::animation const):
(WebCore::AnimationEffect::setAnimation):
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::animationWasAddedToElement): New method to notify the timeline that an
animation registered with this timeline has been associated with a new element through its effect.
(WebCore::AnimationTimeline::animationWasRemovedFromElement): New method to notify the timeline that an
animation registered with this timeline has been disassociated with an element through its effect.
(WebCore::AnimationTimeline::animationsForElement): New method returning all animations registered with
this timeline for a given element.
* animation/AnimationTimeline.h:
(WebCore::AnimationTimeline::animations const): All animations registered with this timeline.
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::DocumentTimeline):
(WebCore::DocumentTimeline::detachFromDocument): Clear the reference between this timeline and its document.
(WebCore::DocumentTimeline::currentTime): Protect against a null Document reference.
(WebCore::DocumentTimeline::createDisplayRefreshMonitor const): Protect against a null Document reference.
* animation/DocumentTimeline.h:
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::create):
(WebCore::WebAnimation::setEffect): As an animation's effect changes, we need to ensure that the old
effect no longer has an associated animation, and that the new effect is associated with this animation.
Additionally, we update the element-to-animations map on the animation's timeline.
(WebCore::WebAnimation::setTimeline): Update the element-to-animations map on the former and new timeline.
* dom/Document.cpp:
(WebCore::Document::prepareForDestruction): Clear the relationship between this document and its timeline.
(WebCore::Document::getAnimations): Obtain all animations associated with this document's timeline.
* dom/Document.h:
* dom/Document.idl:
* dom/Element.cpp:
(WebCore::Element::getAnimations): Obtain all animations associated with this element.
* dom/Element.h:
* dom/Element.idl:
* testing/Internals.cpp:
* CMakeLists.txt:
* DerivedSources.make:
* WebCore.xcodeproj/project.pbxproj:
* animation/Animatable.idl:
* animation/AnimationEffect.h:
(WebCore::AnimationEffect::animation const):
(WebCore::AnimationEffect::setAnimation):
* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::animationWasAddedToElement):
(WebCore::AnimationTimeline::animationWasRemovedFromElement):
(WebCore::AnimationTimeline::animationsForElement):
* animation/AnimationTimeline.h:
(WebCore::AnimationTimeline::animations const):
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::DocumentTimeline):
(WebCore::DocumentTimeline::detachFromDocument):
(WebCore::DocumentTimeline::currentTime):
(WebCore::DocumentTimeline::createDisplayRefreshMonitor const):
* animation/DocumentTimeline.h:
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::create):
(WebCore::WebAnimation::setEffect):
(WebCore::WebAnimation::setTimeline):
* dom/Document.cpp:
(WebCore::Document::prepareForDestruction):
(WebCore::Document::getAnimations):
* dom/Document.h:
* dom/Document.idl:
* dom/Element.cpp:
(WebCore::Element::getAnimations):
* dom/Element.h:
* dom/Element.idl:
* testing/Internals.cpp:
LayoutTests:
Update WPT expectations per new progressions and add three new tests that check the behavior of
Document.getAnimations(), Element.getAnimations() and the unique relationship between an Animation
and an AnimationEffect.
* http/wpt/web-animations/interfaces/Animatable/animate-expected.txt:
* http/wpt/web-animations/interfaces/Animatable/getAnimations-expected.txt:
* http/wpt/web-animations/interfaces/Document/getAnimations-expected.txt:
* http/wpt/wk-web-animations/interfaces/document-get-animations-expected.txt: Added.
* http/wpt/wk-web-animations/interfaces/document-get-animations.html: Added.
* http/wpt/wk-web-animations/interfaces/element-get-animations-expected.txt: Added.
* http/wpt/wk-web-animations/interfaces/element-get-animations.html: Added.
* http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship-expected.txt: Added.
* http/wpt/wk-web-animations/timing-model/animation-effect-unique-relationship.html: Added.
Canonical link: https://commits.webkit.org/195647@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@224760 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-11-13 19:14:47 +00:00
|
|
|
|
2018-11-06 11:15:30 +00:00
|
|
|
Seconds delay() const { return m_delay; }
|
|
|
|
void setDelay(const Seconds&);
|
|
|
|
|
|
|
|
Seconds endDelay() const { return m_endDelay; }
|
|
|
|
void setEndDelay(const Seconds&);
|
|
|
|
|
|
|
|
FillMode fill() const { return m_fill; }
|
|
|
|
void setFill(FillMode);
|
|
|
|
|
|
|
|
double iterationStart() const { return m_iterationStart; }
|
|
|
|
ExceptionOr<void> setIterationStart(double);
|
|
|
|
|
|
|
|
double iterations() const { return m_iterations; }
|
|
|
|
ExceptionOr<void> setIterations(double);
|
|
|
|
|
|
|
|
Seconds iterationDuration() const { return m_iterationDuration; }
|
|
|
|
void setIterationDuration(const Seconds&);
|
|
|
|
|
|
|
|
PlaybackDirection direction() const { return m_direction; }
|
|
|
|
void setDirection(PlaybackDirection);
|
|
|
|
|
|
|
|
TimingFunction* timingFunction() const { return m_timingFunction.get(); }
|
|
|
|
void setTimingFunction(const RefPtr<TimingFunction>&);
|
|
|
|
|
2019-10-30 18:29:56 +00:00
|
|
|
Seconds activeDuration() const { return m_activeDuration; }
|
|
|
|
Seconds endTime() const { return m_endTime; }
|
|
|
|
|
|
|
|
void updateStaticTimingProperties();
|
|
|
|
|
2020-11-17 19:04:10 +00:00
|
|
|
virtual Seconds timeToNextTick() const { return Seconds::infinity(); }
|
2020-05-20 16:26:16 +00:00
|
|
|
|
2017-10-24 07:51:59 +00:00
|
|
|
protected:
|
2018-11-06 11:15:30 +00:00
|
|
|
explicit AnimationEffect();
|
2017-10-24 07:51:59 +00:00
|
|
|
|
2021-05-30 16:11:40 +00:00
|
|
|
virtual std::optional<double> progressUntilNextStep(double) const;
|
2020-11-17 19:04:10 +00:00
|
|
|
|
2017-10-24 07:51:59 +00:00
|
|
|
private:
|
2019-01-10 08:19:39 +00:00
|
|
|
enum class ComputedDirection : uint8_t { Forwards, Reverse };
|
2018-01-24 19:29:53 +00:00
|
|
|
|
2018-11-06 11:15:30 +00:00
|
|
|
FillMode m_fill { FillMode::Auto };
|
2019-01-10 08:19:39 +00:00
|
|
|
PlaybackDirection m_direction { PlaybackDirection::Normal };
|
|
|
|
|
|
|
|
WeakPtr<WebAnimation> m_animation;
|
|
|
|
RefPtr<TimingFunction> m_timingFunction;
|
|
|
|
|
2018-11-06 11:15:30 +00:00
|
|
|
double m_iterationStart { 0 };
|
|
|
|
double m_iterations { 1 };
|
2019-01-10 08:19:39 +00:00
|
|
|
|
|
|
|
Seconds m_delay { 0_s };
|
|
|
|
Seconds m_endDelay { 0_s };
|
2018-11-06 11:15:30 +00:00
|
|
|
Seconds m_iterationDuration { 0_s };
|
2019-10-30 18:29:56 +00:00
|
|
|
Seconds m_activeDuration { 0_s };
|
|
|
|
Seconds m_endTime { 0_s };
|
2017-10-24 07:51:59 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace WebCore
|
|
|
|
|
|
|
|
#define SPECIALIZE_TYPE_TRAITS_ANIMATION_EFFECT(ToValueTypeName, predicate) \
|
|
|
|
SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \
|
2018-11-06 11:15:15 +00:00
|
|
|
static bool isType(const WebCore::AnimationEffect& value) { return value.predicate; } \
|
2017-10-24 07:51:59 +00:00
|
|
|
SPECIALIZE_TYPE_TRAITS_END()
|