Changeset 229530 in webkit
- Timestamp:
- Mar 12, 2018 5:56:14 AM (6 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 45 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r229505 r229530 1 2018-03-12 Antoine Quint <graouts@apple.com> 2 3 [Web Animations] Implement CSS Animations and CSS Transitions as Web Animations 4 https://bugs.webkit.org/show_bug.cgi?id=183504 5 <rdar://problem/38372965> 6 7 Reviewed by Dean Jackson and Jon Lee. 8 9 Add a series of new tests to check CSSAnimation and CSSTransition objects are correctly created 10 as CSS animation-* and CSS transition-* properties are used. We also update some existing tests 11 to use a more concise API since we've implement Element.animate() since their creation. 12 13 * webanimations/animation-opacity-animation-crash.html: 14 * webanimations/css-animations-expected.txt: Added. 15 * webanimations/css-animations.html: Added. 16 * webanimations/css-transitions-expected.txt: Added. 17 * webanimations/css-transitions.html: Added. 18 * webanimations/opacity-animation-no-longer-composited-upon-completion.html: 19 * webanimations/opacity-animation-yields-compositing.html: 20 1 21 2018-03-09 Zalan Bujtas <zalan@apple.com> 2 22 -
trunk/LayoutTests/imported/w3c/ChangeLog
r229181 r229530 1 2018-03-12 Antoine Quint <graouts@apple.com> 2 3 [Web Animations] Implement CSS Animations and CSS Transitions as Web Animations 4 https://bugs.webkit.org/show_bug.cgi?id=183504 5 <rdar://problem/38372965> 6 7 Reviewed by Dean Jackson and Jon Lee. 8 9 Since we've improved our implementation of getAnimations() we updated the expectations to mark 10 the progressions. Both tests for getAnimations() now pass 100%. Another test now fails at a later 11 stage and needed its expectation updated. 12 13 * web-platform-tests/web-animations/interfaces/Animatable/animate-expected.txt: 14 * web-platform-tests/web-animations/interfaces/Animatable/getAnimations-expected.txt: 15 * web-platform-tests/web-animations/interfaces/Document/getAnimations-expected.txt: 16 1 17 2018-03-02 Youenn Fablet <youenn@apple.com> 2 18 -
trunk/LayoutTests/imported/w3c/web-platform-tests/web-animations/interfaces/Animatable/animate-expected.txt
r228702 r229530 119 119 PASS Element.animate() correctly sets the Animation's timeline when triggered on an element in a different document 120 120 PASS Element.animate() calls play on the Animation 121 FAIL CSSPseudoElement.animate() creates an Animation object assert_ equals: expected Element node <div class="pseudo"></div> but got null122 FAIL CSSPseudoElement.animate() creates an Animation object targeting to the correct CSSPseudoElement object assert_ equals: expected Element node <div class="pseudo"></div> but got null121 FAIL CSSPseudoElement.animate() creates an Animation object assert_true: expected true got false 122 FAIL CSSPseudoElement.animate() creates an Animation object targeting to the correct CSSPseudoElement object assert_true: expected true got false 123 123 -
trunk/LayoutTests/imported/w3c/web-platform-tests/web-animations/interfaces/Animatable/getAnimations-expected.txt
r227598 r229530 4 4 PASS Returns only the animations specific to each sibling element 5 5 PASS Returns only the animations specific to each parent/child element 6 FAIL Does not return finished animations that do not fill forwards assert_array_equals: lengths differ, expected 0 got 1 6 PASS Does not return finished animations that do not fill forwards 7 7 PASS Returns finished animations that fill forwards 8 8 PASS Returns animations in their delay phase 9 FAIL Returns animations based on dynamic changes to individual animations' duration assert_array_equals: Animation should not be returned when it is finished lengths differ, expected 0 got 1 10 FAIL Returns animations based on dynamic changes to individual animations' end delay assert_array_equals: Animation should not be returned after setting a negative end delay such that the end time is less than the current time lengths differ, expected 0 got 1 11 FAIL Returns animations based on dynamic changes to individual animations' iteration count assert_array_equals: Animation should not be returned when it is finished lengths differ, expected 0 got 1 12 FAIL Returns animations based on dynamic changes to individual animations' current time assert_array_equals: Animation should not be returned after seeking to the clipped end of the active interval lengths differ, expected 0 got 1 9 PASS Returns animations based on dynamic changes to individual animations' duration 10 PASS Returns animations based on dynamic changes to individual animations' end delay 11 PASS Returns animations based on dynamic changes to individual animations' iteration count 12 PASS Returns animations based on dynamic changes to individual animations' current time 13 13 -
trunk/LayoutTests/imported/w3c/web-platform-tests/web-animations/interfaces/Document/getAnimations-expected.txt
r228333 r229530 1 1 2 2 PASS Test document.getAnimations for non-animated content 3 FAIL Test document.getAnimations for script-generated animations assert_equals: getAnimation only returns running animations expected 0 but got 2 4 FAIL Test the order of document.getAnimations with script generated animations assert_array_equals: getAnimations() returns running animations lengths differ, expected 2 got 4 5 FAIL Test document.getAnimations with null target assert_equals: document.getAnimations() only returns animations targeting elements in this document expected 0 but got 5 3 PASS Test document.getAnimations for script-generated animations 4 PASS Test the order of document.getAnimations with script generated animations 5 PASS Test document.getAnimations with null target 6 6 -
trunk/LayoutTests/webanimations/animation-opacity-animation-crash.html
r224968 r229530 2 2 <script> 3 3 4 const animation = new Animation(new KeyframeEffect(document.getElementById("target"),[4 document.getElementById("target").animate([ 5 5 { opacity: 1 }, 6 6 { opacity: 0 } 7 ])); 8 animation.startTime = 0; 9 animation.effect.timing.duration = 1000; 7 ], 1000); 10 8 11 9 </script> -
trunk/LayoutTests/webanimations/opacity-animation-no-longer-composited-upon-completion.html
r225128 r229530 3 3 <script> 4 4 5 const animation = new Animation(new KeyframeEffect(document.getElementById("target"),[5 const animation = document.getElementById("target").animate([ 6 6 { opacity: 1 }, 7 7 { opacity: 0 } 8 ])); 9 animation.startTime = 0; 10 animation.effect.timing.duration = 100; 8 ], 100); 11 9 12 10 testRunner.waitUntilDone(); -
trunk/LayoutTests/webanimations/opacity-animation-yields-compositing.html
r225128 r229530 3 3 <script> 4 4 5 const animation = new Animation(new KeyframeEffect(document.getElementById("target"),[5 document.getElementById("target").animate([ 6 6 { opacity: 1 }, 7 7 { opacity: 0 } 8 ])); 9 animation.startTime = 0; 10 animation.effect.timing.duration = 1000; 8 ], 1000); 11 9 12 10 testRunner.dumpAsText(); -
trunk/Source/WebCore/ChangeLog
r229525 r229530 1 2018-03-12 Antoine Quint <graouts@apple.com> 2 3 [Web Animations] Implement CSS Animations and CSS Transitions as Web Animations 4 https://bugs.webkit.org/show_bug.cgi?id=183504 5 <rdar://problem/38372965> 6 7 Reviewed by Dean Jackson and Jon Lee. 8 9 Tests: webanimations/css-animations.html 10 webanimations/css-transitions.html 11 12 This patch implements CSS Animations and CSS Transitions as Web Animations. The main changes are: 13 14 * StyleTreeResolver: StyleTreeResolver now has a code path to add CSSAnimation and CSSTransition objects onto the DocumentTimeline 15 to be picked up by the Web Animations engine. The previous CSSAnimationController code path is preserved if the runtime flag is disabled. 16 17 * AnimationTimeline: we add two new methods, updateCSSAnimationsForElement() and updateCSSTransitionsForElement() which are called from 18 TreeResolver::createAnimatedElementUpdate(). These look at the AnimationList for the old and new RenderStyle objects and create, update 19 and remove matching CSSAnimation and CSSTransition instances. 20 21 * DeclarativeAnimation: a new superclass to both CSSAnimation and CSSTransition which introduces the concept of a backingAnimation(), 22 which is an Animation held by the RenderStyle objects, and two virtual methods with base implementations, initialize() which is called 23 upon creating by create() methods in subclasses, and syncPropertiesWithBackingAnimation() which ensures that properties on the 24 DeclarativeAnimation objects (Web Animations side) match the backing animation (CSS side). 25 26 * KeyframeEffectReadOnly: two new important methods to create blending keyframes (KeyframeList) based on backing Animation objects, 27 computeCSSAnimationBlendingKeyframes() and computeCSSTransitionBlendingKeyframes(). 28 29 * Sources.txt: 30 * WebCore.xcodeproj/project.pbxproj: 31 * animation/AnimationEffectReadOnly.h: 32 (WebCore::AnimationEffectReadOnly::isKeyframeEffectReadOnly const): We fix this method such that calling it on a KeyframeEffect, which 33 is a subclass of KeyframeEffectReadOnly, returns true. 34 * animation/AnimationEffectTimingReadOnly.cpp: In order for DeclarativeAnimation::syncPropertiesWithBackingAnimation() to set the timing 35 function for a declarative animation's effect, we need a public method to set an effect's timing function outside of just the "easing" 36 property setter exposed via the JS API. So we introduce a setTimingFunction() method and call it from setEasing(). 37 (WebCore::AnimationEffectTimingReadOnly::setEasing): 38 (WebCore::AnimationEffectTimingReadOnly::setTimingFunction): 39 * animation/AnimationEffectTimingReadOnly.h: 40 * animation/AnimationTimeline.cpp: 41 (WebCore::AnimationTimeline::~AnimationTimeline): Clear all maps and sets containing WebAnimation references to ensure these get destructed 42 when the AnimationTimeline is being destructed and should no longer hold a reference to them. 43 (WebCore::AnimationTimeline::relevantMapForAnimation): We store various subclasses of WebAnimation in dedicated maps so we can composite 44 animations in the correct order when animating. This function returns the correct map for a given animation such that animationWasAddedToElement() 45 and animationWasRemovedFromElement() mutate the right map. 46 (WebCore::AnimationTimeline::animationWasAddedToElement): 47 (WebCore::AnimationTimeline::animationWasRemovedFromElement): 48 (WebCore::AnimationTimeline::animationsForElement): Make sure to look for animations in the lists of CSS Animations and CSS Transitions as well 49 as Web Animations. 50 (WebCore::AnimationTimeline::updateCSSAnimationsForElement): This method is called by TreeResolver::createAnimatedElementUpdate() during style 51 resolution. It compares the AnimationList of the previous style and the new style for a given element, checks that animations with a given name 52 that were not present in the old AnimationList have a new matching CSSAnimation object for them added to the AnimationTimeline, that animations 53 with a given name that are no longer present in the new AnimationList have their matching CSSAnimation object removed from the AnimationTimeline, 54 and that animations with a given name that are present in both the old and new AnimationList have their matching CSSAnimation updated to match 55 the current state of the animation in the AnimationList. 56 (WebCore::AnimationTimeline::updateCSSTransitionsForElement): Similarly to updateCSSAnimationsForElement(), this method is called during style 57 resolution by TreeResolver::createAnimatedElementUpdate(). Its role is to create or remove CSSTransition objects based on the AnimationList found 58 in the old and new styles for a given element. It follows a slightly different logic than updateCSSAnimationsForElement() since for CSS Transitions, 59 there is no need to update CSSTransition objects for a CSS property existing in both the old and new AnimationList, since when a CSS transitions 60 property is changed, a whole new transition is initiated. However, it's important to check that different Animation objects and styles would actually 61 result in different timing properties and blending keyframes, so check for this as well before creating new CSSTransition objects. 62 * animation/AnimationTimeline.h: 63 (WebCore::AnimationTimeline::animations const): Change the m_animations type from HashSet to ListHashSet to guarantee we preserve the insertion order which is 64 required by getAnimations(). 65 (WebCore::AnimationTimeline::hasElementAnimations const): Indicates to DocumentTimeline::updateAnimations() that there are animations targeting the provided element. 66 (WebCore::AnimationTimeline::elementToAnimationsMap): 67 (WebCore::AnimationTimeline::elementToCSSAnimationsMap): 68 (WebCore::AnimationTimeline::elementToCSSTransitionsMap): 69 * animation/CSSAnimation.cpp: CSSAnimation is now a subclass of DeclarativeAnimation and subclasses initialize() and syncPropertiesWithBackingAnimation() 70 to perform work specific to CSS Animations. 71 (WebCore::CSSAnimation::create): Set the animationName property based on the provided backing animation. 72 (WebCore::CSSAnimation::CSSAnimation): 73 (WebCore::CSSAnimation::initialize): Create the blending keyframes for this CSSAnimation. 74 (WebCore::CSSAnimation::syncPropertiesWithBackingAnimation): Reflect the animation-fill-mode, animation-direction, animation-iteration-count and 75 animation-play-state CSS properties on the AnimationEffectTimingReadOnly object associated with this CSSAnimation. 76 * animation/CSSAnimation.h: 77 * animation/CSSTransition.cpp: CSSTransition is now a subclass of DeclarativeAnimation. 78 (WebCore::CSSTransition::create): Set the transitionProperty property based on the provided backing animation. 79 (WebCore::CSSTransition::CSSTransition): 80 (WebCore::CSSTransition::matchesBackingAnimationAndStyles const): 81 (WebCore::CSSTransition::canBeListed const): Subclass this method such that we also check that we have blending keyframes for a CSSTransition to be 82 listed by calls to getAnimations(). 83 * animation/CSSTransition.h: 84 * animation/DeclarativeAnimation.cpp: Added. This new WebAnimation subclass now is the common base class for both CSSAnimation and CSSTransition. 85 It establishes a relationship with a "backing animation", which is an Animation obtained from a style's AnimationList while resolving styles. 86 These backing animations contain all of the parsed CSS styles related to CSS Animations and CSS Transitions and we use those to set matching properties 87 of the Web Animations timing model in the new syncPropertiesWithBackingAnimation() virtual method, which subclasses can override to perform further 88 work that is specific to a given declarative animation type. The initialize() method is called during create() methods to perform common animation 89 setup work. Note that while both initialize() and syncPropertiesWithBackingAnimation() are called, we suspend invalidation to that animation's effect 90 since these methods are meant to be called during style invalidation and we would hit an assertion if we followed the usual route of calling 91 updateStyleIfNeeded() on the target's document during invalidation. 92 (WebCore::DeclarativeAnimation::DeclarativeAnimation): 93 (WebCore::DeclarativeAnimation::setBackingAnimation): 94 (WebCore::DeclarativeAnimation::initialize): Create a KeyframeEffectReadOnly for this animation and set the provided element as its target, set that 95 element's document's timeline and play the animation if the backing animation's play state is playing. 96 (WebCore::DeclarativeAnimation::syncPropertiesWithBackingAnimation): Reflect the {animation|transition}-delay, {animation|transition}-duration and 97 {animation|transition}-timing-function properties as set on the backing animation. 98 * animation/DeclarativeAnimation.h: Added. 99 (WebCore::DeclarativeAnimation::backingAnimation const): 100 * animation/DocumentTimeline.cpp: 101 (WebCore::DocumentTimeline::updateAnimations): Trigger style invalidation for elements targeted not just by WebAnimation instances, but also by any 102 of the DeclarativeAnimation subclasses. We also remove the call to updateFinishedState() which should have been removed when we implemented correct 103 support for asynchronous WebAnimation operations. 104 (WebCore::DocumentTimeline::animatedStyleForRenderer): Declarative animations are backed by KeyframeEffectReadOnly effects, so make sure we check 105 for KeyframeEffectReadOnly or one of its subclasses and not just KeyframeEffect since there now are animation types that use the ReadOnly variant. 106 (WebCore::DocumentTimeline::runningAnimationsForElementAreAllAccelerated): Same as for animatedStyleForRenderer, check for KeyframeEffectReadOnly 107 and not simply KeyframeEffect. 108 * animation/KeyframeEffectReadOnly.cpp: 109 (WebCore::invalidateElement): Stop forcing a style resolution as we invalidate element, marking them as dirty is sufficient. Calls to getAnimations() 110 already force a style resolution as needed. 111 (WebCore::KeyframeEffectReadOnly::create): Add a new create() method that only provides a target and which is used by DeclarativeAnimation::initialize(). 112 (WebCore::KeyframeEffectReadOnly::getKeyframes): The previous implementation of getKeyframes() used the ParsedKeyframe list held as m_parsedKeyframes 113 to compute keyframes. In the case of declarative animations, there are no ParsedKeyframe since the JS API was not involved, so we use the blending keyframes 114 to look for keyframe data. 115 (WebCore::KeyframeEffectReadOnly::computeCSSAnimationBlendingKeyframes): Called by CSSAnimation::initialize(), this function creates blending keyframes by 116 looking up the keyframes date obtained from the @keyframes rule with this backing animation's name. 117 (WebCore::KeyframeEffectReadOnly::computeCSSTransitionBlendingKeyframes): Called by CSSTransition::create(), this function creates blending keyframes by 118 creating a 0-offset keyframe with the old style and a 1-offset keyframe with the new style as provided during TreeResolver::createAnimatedElementUpdate(). 119 (WebCore::KeyframeEffectReadOnly::stylesWouldYieldNewCSSTransitionsBlendingKeyframes const): Called by AnimationTimeline::updateCSSTransitionsForElement() 120 to check that a provided backing Animation and a pair of old and new RenderStyles that may be different objects actually would yield different timing 121 properties and keyframe CSS values for a given CSS transition to avoid the deletion and creation of CSSTransition objects. 122 (WebCore::KeyframeEffectReadOnly::shouldRunAccelerated): We mistakenly assumed we always had blending keyframes, which is not always the case with a 123 CSSTransition where the transition style itself might be set first, but the target value after. So we should only run accelerated provided there are blending 124 keyframes at least, the function already returning false if it finds a blending keyframe animating a non-accelerated CSS property. 125 (WebCore::KeyframeEffectReadOnly::setAnimatedPropertiesInStyle): Check that there actually is a matching ParsedKeyframe to read the timing function from. 126 * animation/KeyframeEffectReadOnly.h: 127 (WebCore::KeyframeEffectReadOnly::hasBlendingKeyframes const): 128 * animation/WebAnimation.cpp: 129 (WebCore::WebAnimation::~WebAnimation): We used to do something very wrong when a WebAnimation was destroyed which uncovered crashes when dealing with 130 declarative animations. In AnimationTimeline's updateCSSAnimationsForElement() and updateCSSTransitionsForElement(), when we identify that a DeclarativeAnimation 131 no longer matches an Animation from the current style's AnimationList, we set that DeclarativeAnimation's effect to null and call removeAnimation() on 132 the timeline. This removes all references from AnimationTimeline to this DeclarativeAnimation and leads to ~WebAnimation being called. Calling removeAnimation() 133 again in the destructor means that we'd hit ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun) in ref(). It was also meaningless to perform this work in 134 the WebAnimation destructor since an animation could never be destroyed if it were still registered on a timeline. 135 (WebCore::WebAnimation::suspendEffectInvalidation): DeclarativeAnimation instances have their timing model properties set during style invalidation, so we need 136 a mechanism to allow the usual effect invalidation to be suspended in this case. We now maintain a simple m_suspendCount count that increases and decreases with 137 calls to this method and unsuspendEffectInvalidation() and a isEffectInvalidationSuspended() method returning true whenever that count is positive. 138 (WebCore::WebAnimation::unsuspendEffectInvalidation): 139 (WebCore::WebAnimation::timingModelDidChange): Check that effect invalidation is not suspended before proceeding with invalidating the effect. 140 (WebCore::WebAnimation::setEffect): Check for KeyframeEffectReadOnly and not just KeyframeEffect since declarative animations have ReadOnly effects. 141 (WebCore::WebAnimation::setTimeline): Check for KeyframeEffectReadOnly and not just KeyframeEffect since declarative animations have ReadOnly effects. 142 (WebCore::WebAnimation::scheduleMicrotaskIfNeeded): Ensure that the WebAnimation's lifecycle is extended at least to the completion of the scheduled microtask. 143 This would otherwise cause crashes after declarative animations were destroyed when they were no longer applied. 144 (WebCore::WebAnimation::runPendingPlayTask): Only fulfill the "ready" promise if it hasn't already been, which might have been the case if multiple calls to play() 145 are made as a result of updating the animation play state in CSSAnimation::syncPropertiesWithBackingAnimation(). 146 (WebCore::WebAnimation::runPendingPauseTask): Same as above but with multiple pause() calls. 147 (WebCore::WebAnimation::startOrStopAccelerated): Check for KeyframeEffectReadOnly and not just KeyframeEffect since declarative animations have ReadOnly effects. 148 (WebCore::WebAnimation::canBeListed const): This new method is called by {Document|Element}::getAnimations() to check that an animation is in the correct state to 149 be listed. The Web Animations spec explains that only animations "that have an associated target effect which is current or in effect" can be listed. We implement 150 this behavior as specified. 151 * animation/WebAnimation.h: 152 (WebCore::WebAnimation::isDeclarativeAnimation const): 153 (WebCore::WebAnimation::isEffectInvalidationSuspended): 154 * dom/Document.cpp: 155 (WebCore::Document::getAnimations): Ensure that the document's pending styles are resolved before returning animations to ensure that any pending declarative 156 animations are created. Additionally, we ensure that we only list qualifying animations that have effects targeting elements that are children of thi document. 157 * dom/Element.cpp: 158 (WebCore::Element::getAnimations): Same as Document::getAnimations(). 159 * style/StyleTreeResolver.cpp: 160 (WebCore::Style::TreeResolver::createAnimatedElementUpdate): When resolving styles, call into the AnimationTimeline if the runtime flag to enable CSS Animations and 161 CSS Transitions as Web Animations is on. Otherwise, use CSSAnimationController. 162 1 163 2018-03-12 Michael Catanzaro <mcatanzaro@igalia.com> 2 164 -
trunk/Source/WebCore/Sources.txt
r229417 r229530 339 339 animation/CSSAnimation.cpp 340 340 animation/CSSTransition.cpp 341 animation/DeclarativeAnimation.cpp 341 342 animation/DocumentTimeline.cpp 342 343 animation/KeyframeEffect.cpp -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r229421 r229530 1985 1985 71556CBD1F9F0A4900E78D08 /* JSAnimationEffectTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 71556CB91F9F09FD00E78D08 /* JSAnimationEffectTiming.h */; }; 1986 1986 71556CBE1F9F0A4900E78D08 /* JSKeyframeEffect.h in Headers */ = {isa = PBXBuildFile; fileRef = 71556CB71F9F09FC00E78D08 /* JSKeyframeEffect.h */; }; 1987 715AD7202050513200D592DC /* DeclarativeAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 715AD71D2050512400D592DC /* DeclarativeAnimation.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1988 715AD7212050513F00D592DC /* CSSTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 7123C186204739BA00789392 /* CSSTransition.h */; }; 1987 1989 71A1B6081DEE5AD70073BCFB /* modern-media-controls-localized-strings.js in Resources */ = {isa = PBXBuildFile; fileRef = 71A1B6061DEE5A820073BCFB /* modern-media-controls-localized-strings.js */; }; 1988 1990 71A57DF2154BE25C0009D120 /* SVGPathUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 71A57DF0154BE25C0009D120 /* SVGPathUtilities.h */; }; … … 8902 8904 7157E3D11DC1EE4B0094550E /* scrubbing-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "scrubbing-support.js"; sourceTree = "<group>"; }; 8903 8905 7157F061150B6564006EAABD /* SVGAnimatedTransformList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGAnimatedTransformList.cpp; sourceTree = "<group>"; }; 8906 715AD71D2050512400D592DC /* DeclarativeAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeclarativeAnimation.h; sourceTree = "<group>"; }; 8907 715AD71F2050512400D592DC /* DeclarativeAnimation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeclarativeAnimation.cpp; sourceTree = "<group>"; }; 8904 8908 715DA5D3201BB902002EF2B0 /* JSWebAnimationCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebAnimationCustom.cpp; sourceTree = "<group>"; }; 8905 8909 716C8DF11E48B269005BD0DA /* volume-down-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "volume-down-support.js"; sourceTree = "<group>"; }; … … 19213 19217 7123C186204739BA00789392 /* CSSTransition.h */, 19214 19218 7123C185204739B900789392 /* CSSTransition.idl */, 19219 715AD71F2050512400D592DC /* DeclarativeAnimation.cpp */, 19220 715AD71D2050512400D592DC /* DeclarativeAnimation.h */, 19215 19221 71025EC41F99F096004A250C /* DocumentTimeline.cpp */, 19216 19222 71025EC51F99F096004A250C /* DocumentTimeline.h */, … … 27217 27223 9AB1F38018E2489A00534743 /* CSSToLengthConversionData.h in Headers */, 27218 27224 A882DA231593848D000115ED /* CSSToStyleMap.h in Headers */, 27225 715AD7212050513F00D592DC /* CSSTransition.h in Headers */, 27219 27226 371F53E90D2704F900ECE0D5 /* CSSUnicodeRangeValue.h in Headers */, 27220 27227 DD7CDF250A23CF9800069928 /* CSSUnknownRule.h in Headers */, … … 27265 27272 0F6A12BE1A00923700C6DE72 /* DebugPageOverlays.h in Headers */, 27266 27273 45FEA5D0156DDE8C00654101 /* Decimal.h in Headers */, 27274 715AD7202050513200D592DC /* DeclarativeAnimation.h in Headers */, 27267 27275 A8C228A111D5722E00D5A7D3 /* DecodedDataDocumentParser.h in Headers */, 27268 27276 CECCFC3B141973D5002A0AC1 /* DecodeEscapeSequences.h in Headers */, -
trunk/Source/WebCore/animation/AnimationEffectReadOnly.h
r228537 r229530 42 42 43 43 bool isKeyframeEffect() const { return m_classType == KeyframeEffectClass; } 44 bool isKeyframeEffectReadOnly() const { return m_classType == KeyframeEffectReadOnlyClass; }44 bool isKeyframeEffectReadOnly() const { return isKeyframeEffect() || m_classType == KeyframeEffectReadOnlyClass; } 45 45 AnimationEffectTimingReadOnly* timing() const { return m_timing.get(); } 46 46 ComputedTimingProperties getComputedTiming(); -
trunk/Source/WebCore/animation/AnimationEffectTimingReadOnly.cpp
r228537 r229530 171 171 if (timingFunctionResult.hasException()) 172 172 return timingFunctionResult.releaseException(); 173 m_timingFunction = timingFunctionResult.returnValue(); 174 propertyDidChange(); 173 setTimingFunction(timingFunctionResult.returnValue()); 175 174 return { }; 176 175 } … … 228 227 229 228 m_direction = direction; 229 propertyDidChange(); 230 } 231 232 void AnimationEffectTimingReadOnly::setTimingFunction(const RefPtr<TimingFunction>& timingFunction) 233 { 234 m_timingFunction = timingFunction; 230 235 propertyDidChange(); 231 236 } -
trunk/Source/WebCore/animation/AnimationEffectTimingReadOnly.h
r228537 r229530 88 88 89 89 TimingFunction* timingFunction() const { return m_timingFunction.get(); } 90 void setTimingFunction(const RefPtr<TimingFunction>&); 91 90 92 Seconds endTime() const; 91 93 Seconds activeDuration() const; -
trunk/Source/WebCore/animation/AnimationTimeline.cpp
r228537 r229530 28 28 #include "AnimationTimeline.h" 29 29 30 #include "Animation.h" 31 #include "AnimationList.h" 32 #include "CSSAnimation.h" 33 #include "CSSPropertyAnimation.h" 34 #include "CSSTransition.h" 30 35 #include "DocumentTimeline.h" 36 #include "Element.h" 37 #include "KeyframeEffectReadOnly.h" 38 #include "RenderStyle.h" 39 #include "RenderView.h" 31 40 #include "WebAnimationUtilities.h" 32 41 #include <wtf/text/TextStream.h> … … 42 51 AnimationTimeline::~AnimationTimeline() 43 52 { 53 m_animations.clear(); 54 m_elementToAnimationsMap.clear(); 55 m_elementToCSSAnimationsMap.clear(); 56 m_elementToCSSTransitionsMap.clear(); 57 m_elementToCSSAnimationByName.clear(); 58 m_elementToCSSTransitionByCSSPropertyID.clear(); 44 59 } 45 60 … … 70 85 } 71 86 87 HashMap<Element*, Vector<RefPtr<WebAnimation>>>& AnimationTimeline::relevantMapForAnimation(WebAnimation& animation) 88 { 89 if (animation.isCSSAnimation()) 90 return m_elementToCSSAnimationsMap; 91 if (animation.isCSSTransition()) 92 return m_elementToCSSTransitionsMap; 93 return m_elementToAnimationsMap; 94 } 95 72 96 void AnimationTimeline::animationWasAddedToElement(WebAnimation& animation, Element& element) 73 97 { 74 auto result = m_elementToAnimationsMap.ensure(&element, [] {75 return Vector<RefPtr<WebAnimation>> ();98 auto result = relevantMapForAnimation(animation).ensure(&element, [] { 99 return Vector<RefPtr<WebAnimation>> { }; 76 100 }); 77 101 result.iterator->value.append(&animation); … … 80 104 void AnimationTimeline::animationWasRemovedFromElement(WebAnimation& animation, Element& element) 81 105 { 82 auto iterator = m_elementToAnimationsMap.find(&element); 83 if (iterator == m_elementToAnimationsMap.end()) 106 auto& map = relevantMapForAnimation(animation); 107 auto iterator = map.find(&element); 108 if (iterator == map.end()) 84 109 return; 85 110 … … 87 112 animations.removeFirst(&animation); 88 113 if (!animations.size()) 89 m _elementToAnimationsMap.remove(iterator);114 map.remove(iterator); 90 115 } 91 116 … … 93 118 { 94 119 Vector<RefPtr<WebAnimation>> animations; 120 if (m_elementToCSSAnimationsMap.contains(&element)) 121 animations.appendVector(m_elementToCSSAnimationsMap.get(&element)); 122 if (m_elementToCSSTransitionsMap.contains(&element)) 123 animations.appendVector(m_elementToCSSTransitionsMap.get(&element)); 95 124 if (m_elementToAnimationsMap.contains(&element)) 96 animations = m_elementToAnimationsMap.get(&element);125 animations.appendVector(m_elementToAnimationsMap.get(&element)); 97 126 return animations; 127 } 128 129 void AnimationTimeline::updateCSSAnimationsForElement(Element& element, const RenderStyle& newStyle, const RenderStyle* oldStyle) 130 { 131 if (element.document().pageCacheState() != Document::NotInPageCache) 132 return; 133 134 if (element.document().renderView()->printing()) 135 return; 136 137 // First, compile the list of animation names that were applied to this element up to this point. 138 HashSet<String> namesOfPreviousAnimations; 139 if (oldStyle && oldStyle->hasAnimations()) { 140 auto* previousAnimations = oldStyle->animations(); 141 for (size_t i = 0; i < previousAnimations->size(); ++i) { 142 auto& previousAnimation = previousAnimations->animation(i); 143 if (previousAnimation.isValidAnimation()) 144 namesOfPreviousAnimations.add(previousAnimation.name()); 145 } 146 } 147 148 // Create or get the CSSAnimations by animation name map for this element. 149 auto& cssAnimationsByName = m_elementToCSSAnimationByName.ensure(&element, [] { 150 return HashMap<String, RefPtr<CSSAnimation>> { }; 151 }).iterator->value; 152 153 if (auto* currentAnimations = newStyle.animations()) { 154 for (size_t i = 0; i < currentAnimations->size(); ++i) { 155 auto& currentAnimation = currentAnimations->animation(i); 156 auto& name = currentAnimation.name(); 157 if (namesOfPreviousAnimations.contains(name)) { 158 // We've found the name of this animation in our list of previous animations, this means we've already 159 // created a CSSAnimation object for it and need to ensure that this CSSAnimation is backed by the current 160 // animation object for this animation name. 161 cssAnimationsByName.get(name)->setBackingAnimation(currentAnimation); 162 } else if (currentAnimation.isValidAnimation()) { 163 // Otherwise we are dealing with a new animation name and must create a CSSAnimation for it. 164 cssAnimationsByName.set(name, CSSAnimation::create(element, currentAnimation)); 165 } 166 // Remove the name of this animation from our list since it's now known to be current. 167 namesOfPreviousAnimations.remove(name); 168 } 169 } 170 171 // The animations names left in namesOfPreviousAnimations are now known to no longer apply so we need to 172 // remove the CSSAnimation object created for them. 173 for (const auto& nameOfAnimationToRemove : namesOfPreviousAnimations) { 174 auto cssAnimationToRemove = cssAnimationsByName.take(nameOfAnimationToRemove); 175 cssAnimationToRemove->setEffect(nullptr); 176 removeAnimation(cssAnimationToRemove.releaseNonNull()); 177 } 178 179 // Remove the map of CSSAnimations by animation name for this element if it's now empty. 180 if (cssAnimationsByName.isEmpty()) 181 m_elementToCSSAnimationByName.remove(&element); 182 } 183 184 void AnimationTimeline::updateCSSTransitionsForElement(Element& element, const RenderStyle& newStyle, const RenderStyle* oldStyle) 185 { 186 if (element.document().pageCacheState() != Document::NotInPageCache) 187 return; 188 189 if (element.document().renderView()->printing()) 190 return; 191 192 // FIXME: We do not handle "all" transitions yet. 193 194 // First, compile the list of backing animations and properties that were applied to this element up to this point. 195 HashSet<CSSPropertyID> previousProperties; 196 HashSet<const Animation*> previousBackingAnimations; 197 if (oldStyle && oldStyle->hasTransitions()) { 198 auto* previousTransitions = oldStyle->transitions(); 199 for (size_t i = 0; i < previousTransitions->size(); ++i) { 200 auto& animation = previousTransitions->animation(i); 201 auto previousTransitionProperty = animation.property(); 202 if (previousTransitionProperty != CSSPropertyInvalid) { 203 previousProperties.add(previousTransitionProperty); 204 previousBackingAnimations.add(&animation); 205 } 206 } 207 } 208 209 // Create or get the CSSTransitions by CSS property name map for this element. 210 auto& cssTransitionsByProperty = m_elementToCSSTransitionByCSSPropertyID.ensure(&element, [] { 211 return HashMap<CSSPropertyID, RefPtr<CSSTransition>> { }; 212 }).iterator->value; 213 214 if (auto* currentTransitions = newStyle.transitions()) { 215 for (size_t i = 0; i < currentTransitions->size(); ++i) { 216 auto& backingAnimation = currentTransitions->animation(i); 217 auto property = backingAnimation.property(); 218 if (property == CSSPropertyInvalid) 219 continue; 220 previousProperties.remove(property); 221 // We've found a backing animation that we didn't know about for a valid property. 222 if (!previousBackingAnimations.contains(&backingAnimation)) { 223 // If we already had a CSSTransition for this property, check whether its timing properties match the current backing 224 // animation's properties and whether its blending keyframes match the old and new styles. If they do, move on to the 225 // next transition, otherwise delete the previous CSSTransition object, and create a new one. 226 if (cssTransitionsByProperty.contains(property)) { 227 if (cssTransitionsByProperty.get(property)->matchesBackingAnimationAndStyles(backingAnimation, oldStyle, newStyle)) 228 continue; 229 auto cssTransitionToRemove = cssTransitionsByProperty.take(property); 230 cssTransitionToRemove->setEffect(nullptr); 231 removeAnimation(cssTransitionToRemove.releaseNonNull()); 232 } 233 // Now we can create a new CSSTransition with the new backing animation provided it has a valid 234 // duration and the from and to values are distinct. 235 if (backingAnimation.duration() > 0 && oldStyle && !CSSPropertyAnimation::propertiesEqual(property, oldStyle, &newStyle)) 236 cssTransitionsByProperty.set(property, CSSTransition::create(element, backingAnimation, oldStyle, newStyle)); 237 } 238 } 239 } 240 241 // Remaining properties are no longer current and must be removed. 242 for (const auto transitionPropertyToRemove : previousProperties) { 243 if (!cssTransitionsByProperty.contains(transitionPropertyToRemove)) 244 continue; 245 auto cssTransitionToRemove = cssTransitionsByProperty.take(transitionPropertyToRemove); 246 cssTransitionToRemove->setEffect(nullptr); 247 removeAnimation(cssTransitionToRemove.releaseNonNull()); 248 } 249 250 // Remove the map of CSSTransitions by property for this element if it's now empty. 251 if (cssTransitionsByProperty.isEmpty()) 252 m_elementToCSSTransitionByCSSPropertyID.remove(&element); 98 253 } 99 254 -
trunk/Source/WebCore/animation/AnimationTimeline.h
r228537 r229530 27 27 #pragma once 28 28 29 #include "CSSValue.h" 30 #include "RenderStyle.h" 29 31 #include "WebAnimation.h" 30 32 #include <wtf/Forward.h> 31 33 #include <wtf/HashMap.h> 32 #include <wtf/ HashSet.h>34 #include <wtf/ListHashSet.h> 33 35 #include <wtf/Optional.h> 34 36 #include <wtf/Ref.h> … … 38 40 namespace WebCore { 39 41 42 class CSSAnimation; 43 class CSSTransition; 40 44 class Element; 41 class WebAnimation;42 45 43 46 class AnimationTimeline : public RefCounted<AnimationTimeline> { … … 54 57 virtual void timingModelDidChange() { }; 55 58 56 const HashSet<RefPtr<WebAnimation>>& animations() const { return m_animations; }59 const ListHashSet<RefPtr<WebAnimation>>& animations() const { return m_animations; } 57 60 Vector<RefPtr<WebAnimation>> animationsForElement(Element&); 58 61 void animationWasAddedToElement(WebAnimation&, Element&); 59 62 void animationWasRemovedFromElement(WebAnimation&, Element&); 63 64 void updateCSSAnimationsForElement(Element&, const RenderStyle& newStyle, const RenderStyle* oldStyle); 65 void updateCSSTransitionsForElement(Element&, const RenderStyle& newStyle, const RenderStyle* oldStyle); 60 66 61 67 virtual ~AnimationTimeline(); … … 70 76 explicit AnimationTimeline(ClassType); 71 77 72 const HashMap<RefPtr<Element>, Vector<RefPtr<WebAnimation>>>& elementToAnimationsMap() { return m_elementToAnimationsMap; } 78 bool hasElementAnimations() const { return !m_elementToAnimationsMap.isEmpty() || !m_elementToCSSAnimationsMap.isEmpty() || !m_elementToCSSTransitionsMap.isEmpty(); } 79 80 const HashMap<Element*, Vector<RefPtr<WebAnimation>>>& elementToAnimationsMap() { return m_elementToAnimationsMap; } 81 const HashMap<Element*, Vector<RefPtr<WebAnimation>>>& elementToCSSAnimationsMap() { return m_elementToCSSAnimationsMap; } 82 const HashMap<Element*, Vector<RefPtr<WebAnimation>>>& elementToCSSTransitionsMap() { return m_elementToCSSTransitionsMap; } 73 83 74 84 private: 85 HashMap<Element*, Vector<RefPtr<WebAnimation>>>& relevantMapForAnimation(WebAnimation&); 86 75 87 ClassType m_classType; 76 88 std::optional<Seconds> m_currentTime; 77 HashMap<RefPtr<Element>, Vector<RefPtr<WebAnimation>>> m_elementToAnimationsMap; 78 HashSet<RefPtr<WebAnimation>> m_animations; 89 HashMap<Element*, Vector<RefPtr<WebAnimation>>> m_elementToAnimationsMap; 90 HashMap<Element*, Vector<RefPtr<WebAnimation>>> m_elementToCSSAnimationsMap; 91 HashMap<Element*, Vector<RefPtr<WebAnimation>>> m_elementToCSSTransitionsMap; 92 ListHashSet<RefPtr<WebAnimation>> m_animations; 93 94 HashMap<Element*, HashMap<String, RefPtr<CSSAnimation>>> m_elementToCSSAnimationByName; 95 HashMap<Element*, HashMap<CSSPropertyID, RefPtr<CSSTransition>>> m_elementToCSSTransitionByCSSPropertyID; 79 96 }; 80 97 -
trunk/Source/WebCore/animation/CSSAnimation.cpp
r229327 r229530 32 32 namespace WebCore { 33 33 34 Ref<CSSAnimation> CSSAnimation::create(Element& target, const Animation& )34 Ref<CSSAnimation> CSSAnimation::create(Element& target, const Animation& backingAnimation) 35 35 { 36 auto& document = target.document(); 37 38 auto result = adoptRef(*new CSSAnimation(document)); 39 36 auto result = adoptRef(*new CSSAnimation(target.document(), backingAnimation)); 37 result->m_animationName = backingAnimation.name(); 38 result->initialize(target); 40 39 return result; 41 40 } 42 41 43 CSSAnimation::CSSAnimation(Document& document )44 : WebAnimation(document)42 CSSAnimation::CSSAnimation(Document& document, const Animation& backingAnimation) 43 : DeclarativeAnimation(document, backingAnimation) 45 44 { 46 45 } 47 46 47 void CSSAnimation::initialize(const Element& target) 48 { 49 DeclarativeAnimation::initialize(target); 50 51 downcast<KeyframeEffectReadOnly>(effect())->computeCSSAnimationBlendingKeyframes(); 52 } 53 54 void CSSAnimation::syncPropertiesWithBackingAnimation() 55 { 56 DeclarativeAnimation::syncPropertiesWithBackingAnimation(); 57 58 suspendEffectInvalidation(); 59 60 auto& animation = backingAnimation(); 61 auto* timing = effect()->timing(); 62 63 switch (animation.fillMode()) { 64 case AnimationFillModeNone: 65 timing->setFill(FillMode::None); 66 break; 67 case AnimationFillModeBackwards: 68 timing->setFill(FillMode::Backwards); 69 break; 70 case AnimationFillModeForwards: 71 timing->setFill(FillMode::Forwards); 72 break; 73 case AnimationFillModeBoth: 74 timing->setFill(FillMode::Both); 75 break; 76 } 77 78 switch (animation.direction()) { 79 case Animation::AnimationDirectionNormal: 80 timing->setDirection(PlaybackDirection::Normal); 81 break; 82 case Animation::AnimationDirectionAlternate: 83 timing->setDirection(PlaybackDirection::Alternate); 84 break; 85 case Animation::AnimationDirectionReverse: 86 timing->setDirection(PlaybackDirection::Reverse); 87 break; 88 case Animation::AnimationDirectionAlternateReverse: 89 timing->setDirection(PlaybackDirection::AlternateReverse); 90 break; 91 } 92 93 timing->setIterations(animation.iterationCount()); 94 95 // Synchronize the play state 96 if (backingAnimation().playState() == AnimPlayStatePlaying && playState() == WebAnimation::PlayState::Paused) 97 play(); 98 else if (backingAnimation().playState() == AnimPlayStatePaused && playState() == WebAnimation::PlayState::Running) 99 pause(); 100 101 unsuspendEffectInvalidation(); 102 } 48 103 49 104 } // namespace WebCore -
trunk/Source/WebCore/animation/CSSAnimation.h
r229327 r229530 26 26 #pragma once 27 27 28 #include " WebAnimation.h"28 #include "DeclarativeAnimation.h" 29 29 #include <wtf/Ref.h> 30 30 … … 34 34 class Element; 35 35 36 class CSSAnimation final : public WebAnimation {36 class CSSAnimation final : public DeclarativeAnimation { 37 37 public: 38 38 static Ref<CSSAnimation> create(Element&, const Animation&); … … 42 42 const String& animationName() const { return m_animationName; } 43 43 44 protected: 45 void initialize(const Element&) final; 46 void syncPropertiesWithBackingAnimation() final; 47 44 48 private: 45 CSSAnimation(Document& );49 CSSAnimation(Document&, const Animation&); 46 50 47 51 String m_animationName; -
trunk/Source/WebCore/animation/CSSTransition.cpp
r229340 r229530 29 29 #include "Animation.h" 30 30 #include "Element.h" 31 #include "KeyframeEffectReadOnly.h" 31 32 32 33 namespace WebCore { 33 34 34 Ref<CSSTransition> CSSTransition::create(Element& target, const Animation& )35 Ref<CSSTransition> CSSTransition::create(Element& target, const Animation& backingAnimation, const RenderStyle* oldStyle, const RenderStyle& newStyle) 35 36 { 36 auto & document = target.document();37 38 auto result = adoptRef(*new CSSTransition(document));39 37 auto result = adoptRef(*new CSSTransition(target.document(), backingAnimation)); 38 result->m_transitionProperty = backingAnimation.property(); 39 result->initialize(target); 40 downcast<KeyframeEffectReadOnly>(result->effect())->computeCSSTransitionBlendingKeyframes(oldStyle, newStyle); 40 41 return result; 41 42 } 42 43 43 CSSTransition::CSSTransition(Document& document )44 : WebAnimation(document)44 CSSTransition::CSSTransition(Document& document, const Animation& backingAnimation) 45 : DeclarativeAnimation(document, backingAnimation) 45 46 { 46 47 } 47 48 49 bool CSSTransition::matchesBackingAnimationAndStyles(const Animation& newBackingAnimation, const RenderStyle* oldStyle, const RenderStyle& newStyle) const 50 { 51 bool backingAnimationsMatch = backingAnimation() == newBackingAnimation; 52 if (!oldStyle) 53 return backingAnimationsMatch; 54 return backingAnimationsMatch && !downcast<KeyframeEffectReadOnly>(effect())->stylesWouldYieldNewCSSTransitionsBlendingKeyframes(*oldStyle, newStyle); 55 } 56 57 bool CSSTransition::canBeListed() const 58 { 59 if (!downcast<KeyframeEffectReadOnly>(effect())->hasBlendingKeyframes()) 60 return false; 61 return WebAnimation::canBeListed(); 62 } 63 48 64 } // namespace WebCore -
trunk/Source/WebCore/animation/CSSTransition.h
r229340 r229530 27 27 28 28 #include "CSSPropertyNames.h" 29 #include " WebAnimation.h"29 #include "DeclarativeAnimation.h" 30 30 #include <wtf/Ref.h> 31 31 … … 34 34 class Animation; 35 35 class Element; 36 class RenderStyle; 36 37 37 class CSSTransition final : public WebAnimation {38 class CSSTransition final : public DeclarativeAnimation { 38 39 public: 39 static Ref<CSSTransition> create(Element&, const Animation& );40 static Ref<CSSTransition> create(Element&, const Animation&, const RenderStyle* oldStyle, const RenderStyle& newStyle); 40 41 ~CSSTransition() = default; 41 42 … … 43 44 String transitionProperty() const { return getPropertyNameString(m_transitionProperty); } 44 45 46 bool matchesBackingAnimationAndStyles(const Animation&, const RenderStyle* oldStyle, const RenderStyle& newStyle) const; 47 bool canBeListed() const final; 48 45 49 private: 46 CSSTransition(Document& );50 CSSTransition(Document&, const Animation&); 47 51 48 52 CSSPropertyID m_transitionProperty; -
trunk/Source/WebCore/animation/DeclarativeAnimation.cpp
r229527 r229530 25 25 26 26 #include "config.h" 27 #include " CSSAnimation.h"27 #include "DeclarativeAnimation.h" 28 28 29 29 #include "Animation.h" 30 #include "AnimationEffectTimingReadOnly.h" 30 31 #include "Element.h" 32 #include "KeyframeEffectReadOnly.h" 31 33 32 34 namespace WebCore { 33 35 34 Ref<CSSAnimation> CSSAnimation::create(Element& target, const Animation&) 35 { 36 auto& document = target.document(); 37 38 auto result = adoptRef(*new CSSAnimation(document)); 39 40 return result; 41 } 42 43 CSSAnimation::CSSAnimation(Document& document) 36 DeclarativeAnimation::DeclarativeAnimation(Document& document, const Animation& backingAnimation) 44 37 : WebAnimation(document) 38 , m_backingAnimation(const_cast<Animation&>(backingAnimation)) 45 39 { 46 40 } 47 41 42 void DeclarativeAnimation::setBackingAnimation(const Animation& backingAnimation) 43 { 44 m_backingAnimation = const_cast<Animation&>(backingAnimation); 45 syncPropertiesWithBackingAnimation(); 46 } 47 48 void DeclarativeAnimation::initialize(const Element& target) 49 { 50 // We need to suspend invalidation of the animation's keyframe effect during its creation 51 // as it would otherwise trigger invalidation of the document's style and this would be 52 // incorrect since it would happen during style invalidation. 53 suspendEffectInvalidation(); 54 55 setEffect(KeyframeEffectReadOnly::create(target)); 56 setTimeline(&target.document().timeline()); 57 syncPropertiesWithBackingAnimation(); 58 if (backingAnimation().playState() == AnimPlayStatePlaying) 59 play(); 60 61 unsuspendEffectInvalidation(); 62 } 63 64 void DeclarativeAnimation::syncPropertiesWithBackingAnimation() 65 { 66 suspendEffectInvalidation(); 67 68 auto* timing = effect()->timing(); 69 timing->setDelay(Seconds(m_backingAnimation->delay())); 70 timing->setIterationDuration(Seconds(m_backingAnimation->duration())); 71 timing->setTimingFunction(m_backingAnimation->timingFunction()); 72 73 unsuspendEffectInvalidation(); 74 } 48 75 49 76 } // namespace WebCore -
trunk/Source/WebCore/animation/DeclarativeAnimation.h
r229527 r229530 34 34 class Element; 35 35 36 class CSSAnimation final: public WebAnimation {36 class DeclarativeAnimation : public WebAnimation { 37 37 public: 38 static Ref<CSSAnimation> create(Element&, const Animation&); 39 ~CSSAnimation() = default; 38 ~DeclarativeAnimation() = default; 40 39 41 bool isCSSAnimation() const override { return true; } 42 const String& animationName() const { return m_animationName; } 40 bool isDeclarativeAnimation() const final { return true; } 41 42 const Animation& backingAnimation() const { return m_backingAnimation; } 43 void setBackingAnimation(const Animation&); 44 45 protected: 46 DeclarativeAnimation(Document&, const Animation&); 47 48 virtual void initialize(const Element&); 49 virtual void syncPropertiesWithBackingAnimation(); 43 50 44 51 private: 45 CSSAnimation(Document&); 46 47 String m_animationName; 52 Ref<Animation> m_backingAnimation; 48 53 49 54 }; … … 51 56 } // namespace WebCore 52 57 53 SPECIALIZE_TYPE_TRAITS_WEB_ANIMATION( CSSAnimation, isCSSAnimation())58 SPECIALIZE_TYPE_TRAITS_WEB_ANIMATION(DeclarativeAnimation, isDeclarativeAnimation()) -
trunk/Source/WebCore/animation/DocumentTimeline.cpp
r228537 r229530 27 27 #include "DocumentTimeline.h" 28 28 29 #include "AnimationPlaybackEvent.h" 29 30 #include "Chrome.h" 30 31 #include "ChromeClient.h" … … 163 164 void DocumentTimeline::updateAnimations() 164 165 { 165 if (m_document && !elementToAnimationsMap().isEmpty()) {166 if (m_document && hasElementAnimations()) { 166 167 for (const auto& elementToAnimationsMapItem : elementToAnimationsMap()) 167 168 elementToAnimationsMapItem.key->invalidateStyleAndLayerComposition(); 169 for (const auto& elementToCSSAnimationsMapItem : elementToCSSAnimationsMap()) 170 elementToCSSAnimationsMapItem.key->invalidateStyleAndLayerComposition(); 171 for (const auto& elementToCSSTransitionsMapItem : elementToCSSTransitionsMap()) 172 elementToCSSTransitionsMapItem.key->invalidateStyleAndLayerComposition(); 168 173 m_document->updateStyleIfNeeded(); 169 174 } … … 173 178 m_acceleratedAnimationsPendingRunningStateChange.clear(); 174 179 175 for (const auto& animation : animations())176 animation->updateFinishedState(WebAnimation::DidSeek::No, WebAnimation::SynchronouslyNotify::No);177 178 180 // Time has advanced, the timing model requires invalidation now. 179 181 timingModelDidChange(); … … 186 188 if (auto* element = renderer.element()) { 187 189 for (auto animation : animationsForElement(*element)) { 188 if ( animation->effect() && animation->effect()->isKeyframeEffect())189 downcast<KeyframeEffect >(animation->effect())->getAnimatedStyle(result);190 if (is<KeyframeEffectReadOnly>(animation->effect())) 191 downcast<KeyframeEffectReadOnly>(animation->effect())->getAnimatedStyle(result); 190 192 } 191 193 } … … 209 211 auto animations = animationsForElement(element); 210 212 for (const auto& animation : animations) { 211 if ( animation->effect() && animation->effect()->isKeyframeEffect() && !downcast<KeyframeEffect>(animation->effect())->isRunningAccelerated())213 if (is<KeyframeEffectReadOnly>(animation->effect()) && !downcast<KeyframeEffectReadOnly>(animation->effect())->isRunningAccelerated()) 212 214 return false; 213 215 } -
trunk/Source/WebCore/animation/KeyframeEffectReadOnly.cpp
r229327 r229530 29 29 #include "Animation.h" 30 30 #include "AnimationEffectTimingReadOnly.h" 31 #include "CSSAnimation.h" 31 32 #include "CSSComputedStyleDeclaration.h" 32 33 #include "CSSPropertyAnimation.h" … … 34 35 #include "CSSStyleDeclaration.h" 35 36 #include "CSSTimingFunctionValue.h" 37 #include "CSSTransition.h" 36 38 #include "Element.h" 37 39 #include "FontCascade.h" … … 41 43 #include "RenderElement.h" 42 44 #include "RenderStyle.h" 45 #include "StylePendingResources.h" 43 46 #include "StyleResolver.h" 44 47 #include "TimingFunction.h" … … 51 54 static inline void invalidateElement(Element* element) 52 55 { 53 if (!element) 54 return; 55 56 element->invalidateStyleAndLayerComposition(); 57 element->document().updateStyleIfNeeded(); 56 if (element) 57 element->invalidateStyleAndLayerComposition(); 58 58 } 59 59 … … 447 447 } 448 448 449 Ref<KeyframeEffectReadOnly> KeyframeEffectReadOnly::create(const Element& target) 450 { 451 return adoptRef(*new KeyframeEffectReadOnly(KeyframeEffectReadOnlyClass, AnimationEffectTimingReadOnly::create(), const_cast<Element*>(&target))); 452 } 453 449 454 KeyframeEffectReadOnly::KeyframeEffectReadOnly(ClassType classType, Ref<AnimationEffectTimingReadOnly>&& timing, Element* target) 450 455 : AnimationEffectReadOnly(classType, WTFMove(timing)) … … 501 506 502 507 // 3. For each keyframe in keyframes perform the following steps: 503 for (auto& parsedKeyframe : m_parsedKeyframes) { 504 // 1. Initialize a dictionary object, output keyframe, using the following definition: 505 // 506 // dictionary BaseComputedKeyframe { 507 // double? offset = null; 508 // double computedOffset; 509 // DOMString easing = "linear"; 510 // CompositeOperation? composite = null; 511 // }; 512 513 // 2. Set offset, computedOffset, easing, composite members of output keyframe to the respective values keyframe offset, computed keyframe 514 // offset, keyframe-specific timing function and keyframe-specific composite operation of keyframe. 515 BaseComputedKeyframe computedKeyframe; 516 computedKeyframe.offset = parsedKeyframe.offset; 517 computedKeyframe.computedOffset = parsedKeyframe.computedOffset; 518 computedKeyframe.easing = parsedKeyframe.timingFunction->cssText(); 519 computedKeyframe.composite = parsedKeyframe.composite; 520 521 auto outputKeyframe = convertDictionaryToJS(state, *jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()), computedKeyframe); 522 523 // 3. For each animation property-value pair specified on keyframe, declaration, perform the following steps: 524 for (auto it = parsedKeyframe.unparsedStyle.begin(), end = parsedKeyframe.unparsedStyle.end(); it != end; ++it) { 525 // 1. Let property name be the result of applying the animation property name to IDL attribute name algorithm to the property name of declaration. 526 auto propertyName = CSSPropertyIDToIDLAttributeName(it->key); 527 // 2. Let IDL value be the result of serializing the property value of declaration by passing declaration to the algorithm to serialize a CSS value. 528 // 3. Let value be the result of converting IDL value to an ECMAScript String value. 529 auto value = toJS<IDLDOMString>(state, it->value); 530 // 4. Call the [[DefineOwnProperty]] internal method on output keyframe with property name property name, 531 // Property Descriptor { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true, [[Value]]: value } and Boolean flag false. 532 JSObject::defineOwnProperty(outputKeyframe, &state, AtomicString(propertyName).impl(), PropertyDescriptor(value, 0), false); 533 } 534 535 // 4. Append output keyframe to result. 536 result.append(JSC::Strong<JSC::JSObject> { state.vm(), outputKeyframe }); 508 if (is<DeclarativeAnimation>(animation())) { 509 auto computedStyleExtractor = ComputedStyleExtractor(m_target.get()); 510 for (size_t i = 0; i < m_blendingKeyframes.size(); ++i) { 511 // 1. Initialize a dictionary object, output keyframe, using the following definition: 512 // 513 // dictionary BaseComputedKeyframe { 514 // double? offset = null; 515 // double computedOffset; 516 // DOMString easing = "linear"; 517 // CompositeOperation? composite = null; 518 // }; 519 520 auto& keyframe = m_blendingKeyframes[i]; 521 522 // 2. Set offset, computedOffset, easing members of output keyframe to the respective values keyframe offset, computed keyframe offset, 523 // and keyframe-specific timing function of keyframe. 524 BaseComputedKeyframe computedKeyframe; 525 computedKeyframe.offset = keyframe.key(); 526 computedKeyframe.computedOffset = keyframe.key(); 527 528 auto outputKeyframe = convertDictionaryToJS(state, *jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()), computedKeyframe); 529 530 // 3. For each animation property-value pair specified on keyframe, declaration, perform the following steps: 531 auto& style = *keyframe.style(); 532 for (auto cssPropertyId : keyframe.properties()) { 533 // 1. Let property name be the result of applying the animation property name to IDL attribute name algorithm to the property name of declaration. 534 auto propertyName = CSSPropertyIDToIDLAttributeName(cssPropertyId); 535 // 2. Let IDL value be the result of serializing the property value of declaration by passing declaration to the algorithm to serialize a CSS value. 536 auto idlValue = computedStyleExtractor.valueForPropertyinStyle(style, cssPropertyId)->cssText(); 537 // 3. Let value be the result of converting IDL value to an ECMAScript String value. 538 auto value = toJS<IDLDOMString>(state, idlValue); 539 // 4. Call the [[DefineOwnProperty]] internal method on output keyframe with property name property name, 540 // Property Descriptor { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true, [[Value]]: value } and Boolean flag false. 541 JSObject::defineOwnProperty(outputKeyframe, &state, AtomicString(propertyName).impl(), PropertyDescriptor(value, 0), false); 542 } 543 544 // 5. Append output keyframe to result. 545 result.append(JSC::Strong<JSC::JSObject> { state.vm(), outputKeyframe }); 546 } 547 } else { 548 for (auto& parsedKeyframe : m_parsedKeyframes) { 549 // 1. Initialize a dictionary object, output keyframe, using the following definition: 550 // 551 // dictionary BaseComputedKeyframe { 552 // double? offset = null; 553 // double computedOffset; 554 // DOMString easing = "linear"; 555 // CompositeOperation? composite = null; 556 // }; 557 558 // 2. Set offset, computedOffset, easing, composite members of output keyframe to the respective values keyframe offset, computed keyframe 559 // offset, keyframe-specific timing function and keyframe-specific composite operation of keyframe. 560 BaseComputedKeyframe computedKeyframe; 561 computedKeyframe.offset = parsedKeyframe.offset; 562 computedKeyframe.computedOffset = parsedKeyframe.computedOffset; 563 computedKeyframe.easing = parsedKeyframe.timingFunction->cssText(); 564 computedKeyframe.composite = parsedKeyframe.composite; 565 566 auto outputKeyframe = convertDictionaryToJS(state, *jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject()), computedKeyframe); 567 568 // 3. For each animation property-value pair specified on keyframe, declaration, perform the following steps: 569 for (auto it = parsedKeyframe.unparsedStyle.begin(), end = parsedKeyframe.unparsedStyle.end(); it != end; ++it) { 570 // 1. Let property name be the result of applying the animation property name to IDL attribute name algorithm to the property name of declaration. 571 auto propertyName = CSSPropertyIDToIDLAttributeName(it->key); 572 // 2. Let IDL value be the result of serializing the property value of declaration by passing declaration to the algorithm to serialize a CSS value. 573 // 3. Let value be the result of converting IDL value to an ECMAScript String value. 574 auto value = toJS<IDLDOMString>(state, it->value); 575 // 4. Call the [[DefineOwnProperty]] internal method on output keyframe with property name property name, 576 // Property Descriptor { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true, [[Value]]: value } and Boolean flag false. 577 JSObject::defineOwnProperty(outputKeyframe, &state, AtomicString(propertyName).impl(), PropertyDescriptor(value, 0), false); 578 } 579 580 // 4. Append output keyframe to result. 581 result.append(JSC::Strong<JSC::JSObject> { state.vm(), outputKeyframe }); 582 } 537 583 } 538 584 … … 642 688 } 643 689 690 void KeyframeEffectReadOnly::computeCSSAnimationBlendingKeyframes() 691 { 692 ASSERT(is<CSSAnimation>(animation())); 693 694 auto& backingAnimation = downcast<CSSAnimation>(animation())->backingAnimation(); 695 if (backingAnimation.name().isEmpty()) 696 return; 697 698 auto renderStyle = RenderStyle::createPtr(); 699 // We need to call update() on the FontCascade or we'll hit an ASSERT when parsing font-related properties. 700 renderStyle->fontCascade().update(nullptr); 701 702 KeyframeList keyframeList(backingAnimation.name()); 703 if (auto* styleScope = Style::Scope::forOrdinal(*m_target, backingAnimation.nameStyleScopeOrdinal())) 704 styleScope->resolver().keyframeStylesForAnimation(*m_target, renderStyle.get(), keyframeList); 705 706 // Ensure resource loads for all the frames. 707 for (auto& keyframe : keyframeList.keyframes()) { 708 if (auto* style = const_cast<RenderStyle*>(keyframe.style())) 709 Style::loadPendingResources(*style, m_target->document(), m_target.get()); 710 } 711 712 m_blendingKeyframes = WTFMove(keyframeList); 713 714 computeStackingContextImpact(); 715 } 716 717 void KeyframeEffectReadOnly::computeCSSTransitionBlendingKeyframes(const RenderStyle* oldStyle, const RenderStyle& newStyle) 718 { 719 ASSERT(is<CSSTransition>(animation())); 720 721 if (!oldStyle || m_blendingKeyframes.size()) 722 return; 723 724 auto& backingAnimation = downcast<CSSTransition>(animation())->backingAnimation(); 725 726 auto toStyle = RenderStyle::clonePtr(newStyle); 727 if (m_target) 728 Style::loadPendingResources(*toStyle, m_target->document(), m_target.get()); 729 730 KeyframeList keyframeList("keyframe-effect-" + createCanonicalUUIDString()); 731 keyframeList.addProperty(backingAnimation.property()); 732 733 KeyframeValue fromKeyframeValue(0, RenderStyle::clonePtr(*oldStyle)); 734 fromKeyframeValue.addProperty(backingAnimation.property()); 735 keyframeList.insert(WTFMove(fromKeyframeValue)); 736 737 KeyframeValue toKeyframeValue(1, WTFMove(toStyle)); 738 toKeyframeValue.addProperty(backingAnimation.property()); 739 keyframeList.insert(WTFMove(toKeyframeValue)); 740 741 m_blendingKeyframes = WTFMove(keyframeList); 742 743 computeStackingContextImpact(); 744 } 745 746 bool KeyframeEffectReadOnly::stylesWouldYieldNewCSSTransitionsBlendingKeyframes(const RenderStyle& oldStyle, const RenderStyle& newStyle) const 747 { 748 ASSERT(is<CSSTransition>(animation())); 749 auto property = downcast<CSSTransition>(animation())->backingAnimation().property(); 750 751 // If we didn't have blending keyframes yet, we would create new blending keyframes provided 752 // the start and end styles hold different values for this property. 753 if (!hasBlendingKeyframes()) 754 return !CSSPropertyAnimation::propertiesEqual(property, &oldStyle, &newStyle); 755 756 // Otherwise, we would create new blending keyframes provided the current start keyframe holds 757 // a different value than the new start style or the current end keyframe holds a different value 758 // than the new end style for this property. 759 return !CSSPropertyAnimation::propertiesEqual(property, m_blendingKeyframes[0].style(), &oldStyle) || !CSSPropertyAnimation::propertiesEqual(property, m_blendingKeyframes[1].style(), &newStyle); 760 } 761 644 762 void KeyframeEffectReadOnly::computeStackingContextImpact() 645 763 { … … 719 837 return false; 720 838 } 721 return true;839 return hasBlendingKeyframes(); 722 840 } 723 841 … … 862 980 // passing interval distance as the input progress. 863 981 auto transformedDistance = intervalDistance; 864 if (startKeyframeIndex) { 982 // In case we're backing a CSSAnimation or CSSTransition we won't actually have parsed keyframes. 983 if (startKeyframeIndex && startKeyframeIndex.value() + 1 <= m_parsedKeyframes.size()) { 865 984 if (auto iterationDuration = timing()->iterationDuration()) { 866 985 auto rangeDuration = (endOffset - startOffset) * iterationDuration.seconds(); -
trunk/Source/WebCore/animation/KeyframeEffectReadOnly.h
r228717 r229530 47 47 static ExceptionOr<Ref<KeyframeEffectReadOnly>> create(JSC::ExecState&, Element*, JSC::Strong<JSC::JSObject>&&, std::optional<Variant<double, KeyframeEffectOptions>>&&); 48 48 static ExceptionOr<Ref<KeyframeEffectReadOnly>> create(JSC::ExecState&, Ref<KeyframeEffectReadOnly>&&); 49 static Ref<KeyframeEffectReadOnly> create(const Element&); 49 50 ~KeyframeEffectReadOnly() { } 50 51 … … 110 111 #endif 111 112 113 void computeCSSAnimationBlendingKeyframes(); 114 void computeCSSTransitionBlendingKeyframes(const RenderStyle* oldStyle, const RenderStyle& newStyle); 115 bool stylesWouldYieldNewCSSTransitionsBlendingKeyframes(const RenderStyle& oldStyle, const RenderStyle& newStyle) const; 116 bool hasBlendingKeyframes() const { return m_blendingKeyframes.size(); } 117 112 118 protected: 113 119 void copyPropertiesFromSource(Ref<KeyframeEffectReadOnly>&&); -
trunk/Source/WebCore/animation/WebAnimation.cpp
r229069 r229530 69 69 WebAnimation::~WebAnimation() 70 70 { 71 if (m_timeline) 72 m_timeline->removeAnimation(*this); 71 } 72 73 void WebAnimation::suspendEffectInvalidation() 74 { 75 ++m_suspendCount; 76 } 77 78 void WebAnimation::unsuspendEffectInvalidation() 79 { 80 ASSERT(m_suspendCount > 0); 81 --m_suspendCount; 73 82 } 74 83 75 84 void WebAnimation::timingModelDidChange() 76 85 { 77 if ( m_effect)86 if (!isEffectInvalidationSuspended() && m_effect) 78 87 m_effect->invalidate(); 79 88 if (m_timeline) … … 120 129 if (oldEffect) { 121 130 oldEffect->setAnimation(nullptr); 122 if (m_timeline && is<KeyframeEffect >(oldEffect)) {123 if (auto* target = downcast<KeyframeEffect >(oldEffect.get())->target())131 if (m_timeline && is<KeyframeEffectReadOnly>(oldEffect)) { 132 if (auto* target = downcast<KeyframeEffectReadOnly>(oldEffect.get())->target()) 124 133 m_timeline->animationWasRemovedFromElement(*this, *target); 125 134 } … … 128 137 if (m_effect) { 129 138 m_effect->setAnimation(this); 130 if (m_timeline && is<KeyframeEffect >(m_effect)) {131 if (auto* target = downcast<KeyframeEffect >(m_effect.get())->target())139 if (m_timeline && is<KeyframeEffectReadOnly>(m_effect)) { 140 if (auto* target = downcast<KeyframeEffectReadOnly>(m_effect.get())->target()) 132 141 m_timeline->animationWasAddedToElement(*this, *target); 133 142 } … … 156 165 timeline->addAnimation(*this); 157 166 158 if (is<KeyframeEffect >(m_effect)) {159 auto* keyframeEffect = downcast<KeyframeEffect >(m_effect.get());167 if (is<KeyframeEffectReadOnly>(m_effect)) { 168 auto* keyframeEffect = downcast<KeyframeEffectReadOnly>(m_effect.get()); 160 169 auto* target = keyframeEffect->target(); 161 170 if (target) { … … 662 671 663 672 m_scheduledMicrotask = true; 664 MicrotaskQueue::mainThreadQueue().append(std::make_unique<VoidMicrotask>(std::bind(&WebAnimation::performMicrotask, this))); 673 MicrotaskQueue::mainThreadQueue().append(std::make_unique<VoidMicrotask>([this, protectedThis = makeRef(*this)] () { 674 this->performMicrotask(); 675 })); 665 676 } 666 677 … … 806 817 807 818 // 4. Resolve animation's current ready promise with animation. 808 m_readyPromise->resolve(*this); 819 if (!m_readyPromise->isFulfilled()) 820 m_readyPromise->resolve(*this); 809 821 810 822 // 5. Run the procedure to update an animation's finished state for animation with the did seek flag set to false, and the synchronously notify flag set to false. … … 925 937 926 938 // 4. Resolve animation's current ready promise with animation. 927 m_readyPromise->resolve(*this); 939 if (!m_readyPromise->isFulfilled()) 940 m_readyPromise->resolve(*this); 928 941 929 942 // 5. Run the procedure to update an animation's finished state for animation with the did seek flag set to false, and the … … 991 1004 void WebAnimation::startOrStopAccelerated() 992 1005 { 993 if (is<KeyframeEffect >(m_effect))994 downcast<KeyframeEffect >(*m_effect).startOrStopAccelerated();1006 if (is<KeyframeEffectReadOnly>(m_effect)) 1007 downcast<KeyframeEffectReadOnly>(*m_effect).startOrStopAccelerated(); 995 1008 } 996 1009 … … 1026 1039 } 1027 1040 1041 bool WebAnimation::canBeListed() const 1042 { 1043 // To be listed in getAnimations() an animation needs a target effect which is current or in effect. 1044 if (!m_effect) 1045 return false; 1046 1047 // An animation effect is in effect if its active time is not unresolved. 1048 if (m_effect->activeTime()) 1049 return true; 1050 1051 // An animation effect is current if either of the following conditions is true: 1052 // - the animation effect is in the before phase, or 1053 // - the animation effect is in play. 1054 1055 // An animation effect is in play if all of the following conditions are met: 1056 // - the animation effect is in the active phase, and 1057 // - the animation effect is associated with an animation that is not finished. 1058 auto phase = m_effect->phase(); 1059 return phase == AnimationEffectReadOnly::Phase::Before || (phase == AnimationEffectReadOnly::Phase::Active && playState() != PlayState::Finished); 1060 } 1061 1028 1062 } // namespace WebCore -
trunk/Source/WebCore/animation/WebAnimation.h
r229340 r229530 53 53 ~WebAnimation(); 54 54 55 virtual bool isDeclarativeAnimation() const { return false; } 55 56 virtual bool isCSSAnimation() const { return false; } 56 57 virtual bool isCSSTransition() const { return false; } 58 59 virtual bool canBeListed() const; 57 60 58 61 const String& id() const { return m_id; } … … 106 109 107 110 void timingModelDidChange(); 111 void suspendEffectInvalidation(); 112 void unsuspendEffectInvalidation(); 108 113 109 114 String description(); … … 114 119 protected: 115 120 explicit WebAnimation(Document&); 121 122 bool isEffectInvalidationSuspended() { return m_suspendCount; } 116 123 117 124 private: … … 146 153 std::optional<Seconds> m_startTime; 147 154 std::optional<Seconds> m_holdTime; 155 int m_suspendCount { 0 }; 148 156 double m_playbackRate { 1 }; 149 157 bool m_isStopped { false }; -
trunk/Source/WebCore/dom/Document.cpp
r229505 r229530 112 112 #include "JSLazyEventListener.h" 113 113 #include "KeyboardEvent.h" 114 #include "KeyframeEffectReadOnly.h" 114 115 #include "LayoutDisallowedScope.h" 115 116 #include "LoaderStrategy.h" … … 7644 7645 Vector<RefPtr<WebAnimation>> Document::getAnimations() 7645 7646 { 7647 // FIXME: Filter and order the list as specified (webkit.org/b/179535). 7648 7649 // For the list of animations to be current, we need to account for any pending CSS changes, 7650 // such as updates to CSS Animations and CSS Transitions. 7651 updateStyleIfNeeded(); 7652 7646 7653 Vector<RefPtr<WebAnimation>> animations; 7647 7654 if (m_timeline) { 7648 // FIXME: Filter and order the list as specified (webkit.org/b/179535). 7649 for (auto& animation : m_timeline->animations()) 7650 animations.append(animation); 7655 for (auto& animation : m_timeline->animations()) { 7656 if (animation->canBeListed() && is<KeyframeEffectReadOnly>(animation->effect())) { 7657 if (auto* target = downcast<KeyframeEffectReadOnly>(animation->effect())->target()) { 7658 if (target->isDescendantOf(this)) 7659 animations.append(animation); 7660 } 7661 } 7662 } 7651 7663 } 7652 7664 return animations; -
trunk/Source/WebCore/dom/Element.cpp
r229372 r229530 3769 3769 { 3770 3770 // FIXME: Filter and order the list as specified (webkit.org/b/179535). 3771 if (auto timeline = document().existingTimeline()) 3772 return timeline->animationsForElement(*this); 3773 return { }; 3771 3772 // For the list of animations to be current, we need to account for any pending CSS changes, 3773 // such as updates to CSS Animations and CSS Transitions. 3774 // FIXME: We might be able to use ComputedStyleExtractor which is more optimized. 3775 document().updateStyleIfNeeded(); 3776 3777 Vector<RefPtr<WebAnimation>> animations; 3778 if (auto timeline = document().existingTimeline()) { 3779 for (auto& animation : timeline->animationsForElement(*this)) { 3780 if (animation->canBeListed()) 3781 animations.append(animation); 3782 } 3783 } 3784 return animations; 3774 3785 } 3775 3786 -
trunk/Source/WebCore/style/StyleTreeResolver.cpp
r228497 r229530 45 45 #include "RenderElement.h" 46 46 #include "RenderView.h" 47 #include "RuntimeEnabledFeatures.h" 47 48 #include "Settings.h" 48 49 #include "ShadowRoot.h" … … 287 288 auto* oldStyle = renderOrDisplayContentsStyle(element); 288 289 289 if (auto timeline = element.document().existingTimeline()) { 290 // New code path for CSS Animations and CSS Transitions. 291 if (RuntimeEnabledFeatures::sharedFeatures().cssAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled()) { 292 // First, we need to make sure that any new CSS animation occuring on this element has a matching WebAnimation 293 // on the document timeline. Note that we get timeline() on the Document here because we need a timeline created 294 // in case no Web Animations have been created through the JS API. 295 if ((oldStyle && oldStyle->hasAnimations()) || newStyle->hasAnimations()) 296 m_document.timeline().updateCSSAnimationsForElement(element, *newStyle, oldStyle); 297 298 if ((oldStyle && oldStyle->hasTransitions()) || newStyle->hasTransitions()) 299 m_document.timeline().updateCSSTransitionsForElement(element, *newStyle, oldStyle); 300 } 301 302 if (auto timeline = m_document.existingTimeline()) { 303 // Now we can update all Web animations, which will include CSS Animations as well 304 // as animations created via the JS API. 290 305 auto webAnimations = timeline->animationsForElement(element); 291 306 if (!webAnimations.isEmpty()) { … … 297 312 } 298 313 299 auto& animationController = m_document.frame()->animation(); 300 301 auto animationUpdate = animationController.updateAnimations(element, *newStyle, oldStyle); 302 303 if (animationUpdate.style) 304 newStyle = WTFMove(animationUpdate.style); 314 bool shouldRecompositeLayer = false; 315 316 // Old code path for CSS Animations and CSS Transitions. 317 if (!RuntimeEnabledFeatures::sharedFeatures().cssAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled()) { 318 auto& animationController = m_document.frame()->animation(); 319 320 auto animationUpdate = animationController.updateAnimations(element, *newStyle, oldStyle); 321 shouldRecompositeLayer = animationUpdate.stateChanged; 322 323 if (animationUpdate.style) 324 newStyle = WTFMove(animationUpdate.style); 325 } 305 326 306 327 auto change = oldStyle ? determineChange(*oldStyle, *newStyle) : Detach; … … 310 331 change = Detach; 311 332 312 bool shouldRecompositeLayer = element.styleResolutionShouldRecompositeLayer() || animationUpdate.stateChanged;333 shouldRecompositeLayer |= element.styleResolutionShouldRecompositeLayer(); 313 334 314 335 return { WTFMove(newStyle), change, shouldRecompositeLayer }; -
trunk/Source/WebKitLegacy/mac/ChangeLog
r229511 r229530 1 2018-03-12 Antoine Quint <graouts@apple.com> 2 3 [Web Animations] Implement CSS Animations and CSS Transitions as Web Animations 4 https://bugs.webkit.org/show_bug.cgi?id=183504 5 <rdar://problem/38372965> 6 7 Reviewed by Dean Jackson and Jon Lee. 8 9 Add the missing WebKitLegacy support the cssAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled flag 10 which is required for the matching <!-- webkit-test-runner --> flag to work in DumpRenderTree. 11 12 * WebView/WebPreferenceKeysPrivate.h: 13 * WebView/WebPreferences.mm: 14 (+[WebPreferences initialize]): 15 (-[WebPreferences setModernMediaControlsEnabled:]): 16 (-[WebPreferences cssAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled]): 17 (-[WebPreferences setCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled:]): 18 * WebView/WebPreferencesPrivate.h: 19 * WebView/WebView.mm: 20 (-[WebView _preferencesChanged:]): 21 1 22 2018-03-10 Megan Gardner <megan_gardner@apple.com> 2 23 -
trunk/Source/WebKitLegacy/mac/WebView/WebPreferenceKeysPrivate.h
r228486 r229530 196 196 #define WebKitConstantPropertiesEnabledPreferenceKey @"WebKitConstantPropertiesEnabled" 197 197 #define WebKitFetchAPIKeepAliveEnabledPreferenceKey @"WebKitFetchAPIKeepAliveEnabled" 198 #define WebKitCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabledPreferenceKey @"WebKitCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled" 198 199 199 200 #if !TARGET_OS_IPHONE -
trunk/Source/WebKitLegacy/mac/WebView/WebPreferences.mm
r228486 r229530 623 623 [NSNumber numberWithBool:NO], WebKitCustomPasteboardDataEnabledPreferenceKey, 624 624 [NSNumber numberWithBool:YES], WebKitModernMediaControlsEnabledPreferenceKey, 625 [NSNumber numberWithBool:NO], WebKitCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabledPreferenceKey, 626 625 627 #if ENABLE(WEBGL2) 626 628 [NSNumber numberWithBool:NO], WebKitWebGL2EnabledPreferenceKey, … … 3116 3118 } 3117 3119 3120 - (BOOL)cssAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled 3121 { 3122 return [self _boolValueForKey:WebKitCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabledPreferenceKey]; 3123 } 3124 3125 - (void)setCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled:(BOOL)flag 3126 { 3127 [self _setBoolValue:flag forKey:WebKitCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabledPreferenceKey]; 3128 } 3129 3118 3130 - (BOOL)intersectionObserverEnabled 3119 3131 { -
trunk/Source/WebKitLegacy/mac/WebView/WebPreferencesPrivate.h
r228486 r229530 571 571 - (BOOL)modernMediaControlsEnabled; 572 572 573 - (void)setCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled:(BOOL)flag; 574 - (BOOL)cssAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled; 575 573 576 - (void)setWebAuthenticationEnabled:(BOOL)flag; 574 577 - (BOOL)webAuthenticationEnabled; -
trunk/Source/WebKitLegacy/mac/WebView/WebView.mm
r229511 r229530 3006 3006 RuntimeEnabledFeatures::sharedFeatures().setInteractiveFormValidationEnabled([self interactiveFormValidationEnabled]); 3007 3007 RuntimeEnabledFeatures::sharedFeatures().setModernMediaControlsEnabled([preferences modernMediaControlsEnabled]); 3008 RuntimeEnabledFeatures::sharedFeatures().setCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled([preferences cssAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled]); 3008 3009 3009 3010 RuntimeEnabledFeatures::sharedFeatures().setCacheAPIEnabled([preferences cacheAPIEnabled]); -
trunk/Source/WebKitLegacy/win/ChangeLog
r229410 r229530 1 2018-03-12 Antoine Quint <graouts@apple.com> 2 3 [Web Animations] Implement CSS Animations and CSS Transitions as Web Animations 4 https://bugs.webkit.org/show_bug.cgi?id=183504 5 <rdar://problem/38372965> 6 7 Reviewed by Dean Jackson and Jon Lee. 8 9 Add the missing WebKitLegacy support the cssAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled flag 10 which is required for the matching <!-- webkit-test-runner --> flag to work in DumpRenderTree. 11 12 * Interfaces/IWebPreferencesPrivate.idl: 13 * WebPreferences.cpp: 14 (WebPreferences::cssAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled): 15 (WebPreferences::setCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled): 16 * WebPreferenceKeysPrivate.h 17 * WebPreferences.h: 18 * WebView.cpp: 19 (WebView::notifyPreferencesChanged): 20 1 21 2018-03-08 Yusuke Suzuki <utatane.tea@gmail.com> 2 22 -
trunk/Source/WebKitLegacy/win/Interfaces/IWebPreferencesPrivate.idl
r229143 r229530 184 184 HRESULT modernMediaControlsEnabled([out, retval] BOOL* enabled); 185 185 HRESULT setModernMediaControlsEnabled([in] BOOL enabled); 186 HRESULT cssAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled([out, retval] BOOL* enabled); 187 HRESULT setCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled([in] BOOL enabled); 186 188 } 187 189 -
trunk/Source/WebKitLegacy/win/WebPreferenceKeysPrivate.h
r229143 r229530 183 183 #define WebKitWebAnimationsEnabledPreferenceKey "WebKitWebAnimationsEnabled" 184 184 185 #define WebKitCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabledPreferenceKey "WebKitCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled" 186 185 187 #define WebKitUserTimingEnabledPreferenceKey "WebKitUserTimingEnabled" 186 188 -
trunk/Source/WebKitLegacy/win/WebPreferences.cpp
r229309 r229530 2030 2030 } 2031 2031 2032 HRESULT WebPreferences::cssAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled(_Out_ BOOL* enabled) 2033 { 2034 if (!enabled) 2035 return E_POINTER; 2036 *enabled = boolValueForKey(WebKitCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabledPreferenceKey); 2037 return S_OK; 2038 } 2039 2040 HRESULT WebPreferences::setCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled(BOOL enabled) 2041 { 2042 setBoolValue(WebKitCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabledPreferenceKey, enabled); 2043 return S_OK; 2044 } 2045 2032 2046 HRESULT WebPreferences::fetchAPIKeepAliveEnabled(_Out_ BOOL* enabled) 2033 2047 { -
trunk/Source/WebKitLegacy/win/WebPreferences.h
r229143 r229530 241 241 virtual HRESULT STDMETHODCALLTYPE modernMediaControlsEnabled(_Out_ BOOL*); 242 242 virtual HRESULT STDMETHODCALLTYPE setModernMediaControlsEnabled(BOOL); 243 243 virtual HRESULT STDMETHODCALLTYPE cssAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled(_Out_ BOOL*); 244 virtual HRESULT STDMETHODCALLTYPE setCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled(BOOL); 245 244 246 // IWebPreferencesPrivate4 245 247 virtual HRESULT STDMETHODCALLTYPE setApplicationId(BSTR); -
trunk/Source/WebKitLegacy/win/WebView.cpp
r229309 r229530 5218 5218 RuntimeEnabledFeatures::sharedFeatures().setWebAnimationsEnabled(!!enabled); 5219 5219 5220 hr = prefsPrivate->cssAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled(&enabled); 5221 if (FAILED(hr)) 5222 return hr; 5223 RuntimeEnabledFeatures::sharedFeatures().setCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled(!!enabled); 5224 5220 5225 hr = prefsPrivate->userTimingEnabled(&enabled); 5221 5226 if (FAILED(hr)) -
trunk/Tools/ChangeLog
r229522 r229530 1 2018-03-12 Antoine Quint <graouts@apple.com> 2 3 [Web Animations] Implement CSS Animations and CSS Transitions as Web Animations 4 https://bugs.webkit.org/show_bug.cgi?id=183504 5 <rdar://problem/38372965> 6 7 Reviewed by Jon Lee. 8 9 Add a new <!-- webkit-test-runner --> flag to enable the CSS Animations and CSS Transitions 10 as Web Animations runtime flag in the new tests we've created for this feature. 11 12 * DumpRenderTree/TestOptions.h: 13 * DumpRenderTree/TestOptions.mm: 14 (TestOptions::TestOptions): 15 * DumpRenderTree/mac/DumpRenderTree.mm: 16 (setWebPreferencesForTestOptions): 17 * WebKitTestRunner/TestController.cpp: 18 (WTR::TestController::resetPreferencesToConsistentValues): 19 (WTR::updateTestOptionsFromTestHeader): 20 * WebKitTestRunner/TestOptions.h: 21 (WTR::TestOptions::hasSameInitializationOptions const): 22 1 23 2018-03-11 Zalan Bujtas <zalan@apple.com> 2 24 -
trunk/Tools/DumpRenderTree/TestOptions.h
r228486 r229530 31 31 struct TestOptions { 32 32 bool enableAttachmentElement { false }; 33 bool enableCSSAnimationsAndCSSTransitionsBackedByWebAnimations { false }; 33 34 bool useAcceleratedDrawing { false }; 34 35 bool enableIntersectionObserver { false }; -
trunk/Tools/DumpRenderTree/TestOptions.mm
r228486 r229530 105 105 else if (key == "allowCrossOriginSubresourcesToAskForCredentials") 106 106 this->allowCrossOriginSubresourcesToAskForCredentials = parseBooleanTestHeaderValue(value); 107 else if (key == "enableCSSAnimationsAndCSSTransitionsBackedByWebAnimations") 108 this->enableCSSAnimationsAndCSSTransitionsBackedByWebAnimations = parseBooleanTestHeaderValue(value); 107 109 pairStart = pairEnd + 1; 108 110 } -
trunk/Tools/DumpRenderTree/mac/DumpRenderTree.mm
r229297 r229530 996 996 preferences.inspectorAdditionsEnabled = options.enableInspectorAdditions; 997 997 preferences.allowCrossOriginSubresourcesToAskForCredentials = options.allowCrossOriginSubresourcesToAskForCredentials; 998 preferences.CSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled = options.enableCSSAnimationsAndCSSTransitionsBackedByWebAnimations; 998 999 } 999 1000 -
trunk/Tools/WebKitTestRunner/TestController.cpp
r229390 r229530 694 694 WKPreferencesSetIsSecureContextAttributeEnabled(preferences, options.enableIsSecureContextAttribute); 695 695 WKPreferencesSetAllowCrossOriginSubresourcesToAskForCredentials(preferences, options.allowCrossOriginSubresourcesToAskForCredentials); 696 WKPreferencesSetCSSAnimationsAndCSSTransitionsBackedByWebAnimationsEnabled(preferences, options.enableCSSAnimationsAndCSSTransitionsBackedByWebAnimations); 696 697 697 698 static WKStringRef defaultTextEncoding = WKStringCreateWithUTF8CString("ISO-8859-1"); … … 1088 1089 if (key == "allowCrossOriginSubresourcesToAskForCredentials") 1089 1090 testOptions.allowCrossOriginSubresourcesToAskForCredentials = parseBooleanTestHeaderValue(value); 1091 if (key == "enableCSSAnimationsAndCSSTransitionsBackedByWebAnimations") 1092 testOptions.enableCSSAnimationsAndCSSTransitionsBackedByWebAnimations = parseBooleanTestHeaderValue(value); 1090 1093 pairStart = pairEnd + 1; 1091 1094 } -
trunk/Tools/WebKitTestRunner/TestOptions.h
r228486 r229530 56 56 bool dumpJSConsoleLogInStdErr { false }; 57 57 bool allowCrossOriginSubresourcesToAskForCredentials { false }; 58 bool enableCSSAnimationsAndCSSTransitionsBackedByWebAnimations { false }; 58 59 59 60 float deviceScaleFactor { 1 }; … … 85 86 || dumpJSConsoleLogInStdErr != options.dumpJSConsoleLogInStdErr 86 87 || applicationManifest != options.applicationManifest 87 || allowCrossOriginSubresourcesToAskForCredentials != options.allowCrossOriginSubresourcesToAskForCredentials) 88 || allowCrossOriginSubresourcesToAskForCredentials != options.allowCrossOriginSubresourcesToAskForCredentials 89 || enableCSSAnimationsAndCSSTransitionsBackedByWebAnimations != options.enableCSSAnimationsAndCSSTransitionsBackedByWebAnimations) 88 90 return false; 89 91
Note: See TracChangeset
for help on using the changeset viewer.