WebKit Bugzilla
Attachment 357670 Details for
Bug 192850
: [Web Animations] Compute animation effect timing properties in batch
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-192850-20181219150147.patch (text/plain), 61.16 KB, created by
Antoine Quint
on 2018-12-19 06:01:49 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Antoine Quint
Created:
2018-12-19 06:01:49 PST
Size:
61.16 KB
patch
obsolete
>Subversion Revision: 239373 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index af174d42b4bd45472d02745ca9a623e1115589bb..f85c17f48865f9cf6170a7583f548adcc2c5e24d 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,67 @@ >+2018-12-19 Antoine Quint <graouts@apple.com> >+ >+ [Web Animations] Compute animation effect timing properties in batch >+ https://bugs.webkit.org/show_bug.cgi?id=192850 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ 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): >+ > 2018-12-19 Xabier Rodriguez Calvar <calvaris@igalia.com> > > [EME] MediaKeySystemConfiguration distinctiveIdentifier and persistentState should default to optional >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index 63e9a683ffa6e1a496c09746f73457f6df1b0485..03077b365f3b65505302fb5c09738ca4f1a11bc4 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -2092,6 +2092,7 @@ > 71537A01146BD9D7008BD615 /* SVGPathData.h in Headers */ = {isa = PBXBuildFile; fileRef = 715379FF146BD9D6008BD615 /* SVGPathData.h */; }; > 71556CB41F9F09BA00E78D08 /* KeyframeEffect.h in Headers */ = {isa = PBXBuildFile; fileRef = 71556CAA1F9F099B00E78D08 /* KeyframeEffect.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 71556CBE1F9F0A4900E78D08 /* JSKeyframeEffect.h in Headers */ = {isa = PBXBuildFile; fileRef = 71556CB71F9F09FC00E78D08 /* JSKeyframeEffect.h */; }; >+ 7156BCA121CA350F00534397 /* BasicEffectTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 7156BC9F21CA350600534397 /* BasicEffectTiming.h */; }; > 715AD7202050513200D592DC /* DeclarativeAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 715AD71D2050512400D592DC /* DeclarativeAnimation.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 715AD7212050513F00D592DC /* CSSTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 7123C186204739BA00789392 /* CSSTransition.h */; }; > 716E55B020DBABF100F0CF29 /* DocumentAnimationScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 716E55AD20DBABDC00F0CF29 /* DocumentAnimationScheduler.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -2104,6 +2105,7 @@ > 71C916081D1483A300ACA47D /* UserInterfaceLayoutDirection.h in Headers */ = {isa = PBXBuildFile; fileRef = 71C916071D1483A300ACA47D /* UserInterfaceLayoutDirection.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 71DCB7021568197600862271 /* JSSVGZoomAndPan.h in Headers */ = {isa = PBXBuildFile; fileRef = 71DCB7001568197600862271 /* JSSVGZoomAndPan.h */; }; > 71E2183A17359FB8006E6E4D /* PlugInsResources.h in Headers */ = {isa = PBXBuildFile; fileRef = 71E2183817359FB8006E6E4D /* PlugInsResources.h */; }; >+ 71E2C42621C935280024F8C8 /* AnimationEffectPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 71E2C42421C9351D0024F8C8 /* AnimationEffectPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 71E623D1151F72A60036E2F4 /* SVGAnimatedIntegerOptionalInteger.h in Headers */ = {isa = PBXBuildFile; fileRef = 71E623CF151F72A60036E2F4 /* SVGAnimatedIntegerOptionalInteger.h */; }; > 71EFCEDC202B38A900D7C411 /* AnimationEffect.h in Headers */ = {isa = PBXBuildFile; fileRef = 71EFCED7202B388D00D7C411 /* AnimationEffect.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 71FB967B1383D64600AC8A4C /* SVGAnimatedEnumerationPropertyTearOff.h in Headers */ = {isa = PBXBuildFile; fileRef = 71FB967A1383D64600AC8A4C /* SVGAnimatedEnumerationPropertyTearOff.h */; }; >@@ -9264,6 +9266,7 @@ > 71556CAB1F9F099C00E78D08 /* KeyframeEffect.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = KeyframeEffect.idl; sourceTree = "<group>"; }; > 71556CB61F9F09FC00E78D08 /* JSKeyframeEffect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSKeyframeEffect.cpp; sourceTree = "<group>"; }; > 71556CB71F9F09FC00E78D08 /* JSKeyframeEffect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSKeyframeEffect.h; sourceTree = "<group>"; }; >+ 7156BC9F21CA350600534397 /* BasicEffectTiming.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BasicEffectTiming.h; sourceTree = "<group>"; }; > 7157E3D11DC1EE4B0094550E /* scrubbing-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "scrubbing-support.js"; sourceTree = "<group>"; }; > 7157F061150B6564006EAABD /* SVGAnimatedTransformList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGAnimatedTransformList.cpp; sourceTree = "<group>"; }; > 715AD71D2050512400D592DC /* DeclarativeAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeclarativeAnimation.h; sourceTree = "<group>"; }; >@@ -9353,6 +9356,7 @@ > 71DE2794203A9C1C0058CB51 /* compact-media-controls.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "compact-media-controls.js"; sourceTree = "<group>"; }; > 71E2183817359FB8006E6E4D /* PlugInsResources.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = PlugInsResources.h; path = DerivedSources/WebCore/PlugInsResources.h; sourceTree = BUILT_PRODUCTS_DIR; }; > 71E2183917359FB8006E6E4D /* PlugInsResourcesData.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = PlugInsResourcesData.cpp; path = DerivedSources/WebCore/PlugInsResourcesData.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; >+ 71E2C42421C9351D0024F8C8 /* AnimationEffectPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationEffectPhase.h; sourceTree = "<group>"; }; > 71E623CE151F72A60036E2F4 /* SVGAnimatedIntegerOptionalInteger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGAnimatedIntegerOptionalInteger.cpp; sourceTree = "<group>"; }; > 71E623CF151F72A60036E2F4 /* SVGAnimatedIntegerOptionalInteger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAnimatedIntegerOptionalInteger.h; sourceTree = "<group>"; }; > 71EFCED6202B388C00D7C411 /* AnimationEffect.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = AnimationEffect.idl; sourceTree = "<group>"; }; >@@ -20162,6 +20166,7 @@ > 71EFCEDA202B388F00D7C411 /* AnimationEffect.cpp */, > 71EFCED7202B388D00D7C411 /* AnimationEffect.h */, > 71EFCED6202B388C00D7C411 /* AnimationEffect.idl */, >+ 71E2C42421C9351D0024F8C8 /* AnimationEffectPhase.h */, > 714C7C601FDAD27900F2BEE1 /* AnimationPlaybackEvent.cpp */, > 714C7C651FDAD27B00F2BEE1 /* AnimationPlaybackEvent.h */, > 714C7C641FDAD27B00F2BEE1 /* AnimationPlaybackEvent.idl */, >@@ -20170,6 +20175,7 @@ > 71025EC61F99F096004A250C /* AnimationTimeline.cpp */, > 71025EC71F99F096004A250C /* AnimationTimeline.h */, > 71025EC91F99F096004A250C /* AnimationTimeline.idl */, >+ 7156BC9F21CA350600534397 /* BasicEffectTiming.h */, > 71247E351FEA5F81008C08CE /* CompositeOperation.h */, > 71247E361FEA5F81008C08CE /* CompositeOperation.idl */, > 7111243B216FA6E000EB7B67 /* CompositeOperationOrAuto.h */, >@@ -27833,6 +27839,7 @@ > 49E912AB0EFAC906009D0CAF /* Animation.h in Headers */, > 316FE1120E6E1DA700BF6088 /* AnimationBase.h in Headers */, > 71EFCEDC202B38A900D7C411 /* AnimationEffect.h in Headers */, >+ 71E2C42621C935280024F8C8 /* AnimationEffectPhase.h in Headers */, > 319848011A1D817B00A13318 /* AnimationEvent.h in Headers */, > 49E912AD0EFAC906009D0CAF /* AnimationList.h in Headers */, > 714C7C661FDAD2A100F2BEE1 /* AnimationPlaybackEvent.h in Headers */, >@@ -27980,6 +27987,7 @@ > F59C96001255B23F000623C0 /* BaseDateAndTimeInputType.h in Headers */, > F55B3DAE1251F12D003EF269 /* BaseTextInputType.h in Headers */, > 57C7A68C1E56967500C67D71 /* BasicCredential.h in Headers */, >+ 7156BCA121CA350F00534397 /* BasicEffectTiming.h in Headers */, > FBD6AF8A15EF25DF008B7110 /* BasicShapeFunctions.h in Headers */, > FBD6AF8C15EF2604008B7110 /* BasicShapes.h in Headers */, > BC9462D8107A7B4C00857193 /* BeforeLoadEvent.h in Headers */, >diff --git a/Source/WebCore/animation/AnimationEffect.cpp b/Source/WebCore/animation/AnimationEffect.cpp >index 2b8c538313f1ec16ab6f4bc7df91a95aee783dd2..0cd322bce3dc895b20008728fd710dccef991fec 100644 >--- a/Source/WebCore/animation/AnimationEffect.cpp >+++ b/Source/WebCore/animation/AnimationEffect.cpp >@@ -41,283 +41,309 @@ AnimationEffect::~AnimationEffect() > { > } > >-std::optional<Seconds> AnimationEffect::localTime() const >+EffectTiming AnimationEffect::getTiming() const > { >- if (m_animation) >- return m_animation->currentTime(); >- return std::nullopt; >-} >- >-auto AnimationEffect::phase() const -> Phase >-{ >- // 3.5.5. Animation effect phases and states >- // https://drafts.csswg.org/web-animations-1/#animation-effect-phases-and-states >- >- bool animationIsBackwards = m_animation && m_animation->playbackRate() < 0; >- auto beforeActiveBoundaryTime = std::max(std::min(m_delay, endTime()), 0_s); >- auto activeAfterBoundaryTime = std::max(std::min(m_delay + activeDuration(), endTime()), 0_s); >- >- // (This should be the last statement, but it's more efficient to cache the local time and return right away if it's not resolved.) >- // Furthermore, it is often convenient to refer to the case when an animation effect is in none of the above phases >- // as being in the idle phase. >- auto effectLocalTime = localTime(); >- if (!effectLocalTime) >- return Phase::Idle; >- >- auto localTimeValue = effectLocalTime.value(); >- >- // An animation effect is in the before phase if the animation effectâs local time is not unresolved and >- // either of the following conditions are met: >- // 1. the local time is less than the before-active boundary time, or >- // 2. the animation direction is âbackwardsâ and the local time is equal to the before-active boundary time. >- if ((localTimeValue + timeEpsilon) < beforeActiveBoundaryTime || (animationIsBackwards && std::abs(localTimeValue.microseconds() - beforeActiveBoundaryTime.microseconds()) < timeEpsilon.microseconds())) >- return Phase::Before; >- >- // An animation effect is in the after phase if the animation effectâs local time is not unresolved and >- // either of the following conditions are met: >- // 1. the local time is greater than the active-after boundary time, or >- // 2. the animation direction is âforwardsâ and the local time is equal to the active-after boundary time. >- if ((localTimeValue - timeEpsilon) > activeAfterBoundaryTime || (!animationIsBackwards && std::abs(localTimeValue.microseconds() - activeAfterBoundaryTime.microseconds()) < timeEpsilon.microseconds())) >- return Phase::After; >- >- // An animation effect is in the active phase if the animation effectâs local time is not unresolved and it is not >- // in either the before phase nor the after phase. >- // (No need to check, we've already established that local time was resolved). >- return Phase::Active; >+ EffectTiming timing; >+ timing.delay = secondsToWebAnimationsAPITime(m_delay); >+ timing.endDelay = secondsToWebAnimationsAPITime(m_endDelay); >+ timing.fill = m_fill; >+ timing.iterationStart = m_iterationStart; >+ timing.iterations = m_iterations; >+ if (m_iterationDuration == 0_s) >+ timing.duration = "auto"; >+ else >+ timing.duration = secondsToWebAnimationsAPITime(m_iterationDuration); >+ timing.direction = m_direction; >+ timing.easing = m_timingFunction->cssText(); >+ return timing; > } > >-std::optional<Seconds> AnimationEffect::activeTime() const >+BasicEffectTiming AnimationEffect::getBasicTiming() const > { >- // 3.8.3.1. Calculating the active time >- // https://drafts.csswg.org/web-animations-1/#calculating-the-active-time >- >- // The active time is based on the local time and start delay. However, it is only defined >- // when the animation effect should produce an output and hence depends on its fill mode >- // and phase as follows, >- >- auto effectPhase = phase(); >- >- // If the animation effect is in the before phase, the result depends on the first matching >- // condition from the following, >- if (effectPhase == Phase::Before) { >- // If the fill mode is backwards or both, return the result of evaluating >- // max(local time - start delay, 0). >- if (m_fill == FillMode::Backwards || m_fill == FillMode::Both) >- return std::max(localTime().value() - m_delay, 0_s); >- // Otherwise, return an unresolved time value. >+ // The Web Animations spec introduces a number of animation effect time-related definitions that refer >+ // to each other a fair bit, so rather than implementing them as individual methods, it's more efficient >+ // to return them all as a single BasicEffectTiming. >+ >+ auto activeDuration = [this]() -> Seconds { >+ // 3.8.2. Calculating the active duration >+ // https://drafts.csswg.org/web-animations-1/#calculating-the-active-duration >+ >+ // The active duration is calculated as follows: >+ // active duration = iteration duration à iteration count >+ // If either the iteration duration or iteration count are zero, the active duration is zero. >+ if (!m_iterationDuration || !m_iterations) >+ return 0_s; >+ return m_iterationDuration * m_iterations; >+ }(); >+ >+ auto endTime = [this, activeDuration]() -> Seconds { >+ // 3.5.3 The active interval >+ // https://drafts.csswg.org/web-animations-1/#end-time >+ >+ // The end time of an animation effect is the result of evaluating max(start delay + active duration + end delay, 0). >+ auto endTime = m_delay + activeDuration + m_endDelay; >+ return endTime > 0_s ? endTime : 0_s; >+ }(); >+ >+ auto localTime = [this]() -> std::optional<Seconds> { >+ // 4.5.4. Local time >+ // https://drafts.csswg.org/web-animations-1/#local-time-section >+ >+ // The local time of an animation effect at a given moment is based on the first matching condition from the following: >+ // If the animation effect is associated with an animation, the local time is the current time of the animation. >+ // Otherwise, the local time is unresolved. >+ if (m_animation) >+ return m_animation->currentTime(); > return std::nullopt; >- } >- >- // If the animation effect is in the active phase, return the result of evaluating local time - start delay. >- if (effectPhase == Phase::Active) >- return localTime().value() - m_delay; >- >- // If the animation effect is in the after phase, the result depends on the first matching >- // condition from the following, >- if (effectPhase == Phase::After) { >- // If the fill mode is forwards or both, return the result of evaluating >- // max(min(local time - start delay, active duration), 0). >- if (m_fill == FillMode::Forwards || m_fill == FillMode::Both) >- return std::max(std::min(localTime().value() - m_delay, activeDuration()), 0_s); >- // Otherwise, return an unresolved time value. >- return std::nullopt; >- } >- >- // Otherwise (the local time is unresolved), return an unresolved time value. >- return std::nullopt; >-} >- >-std::optional<double> AnimationEffect::overallProgress() const >-{ >- // 3.8.3.2. Calculating the overall progress >- // https://drafts.csswg.org/web-animations-1/#calculating-the-overall-progress >+ }(); >+ >+ auto phase = [this, endTime, localTime, activeDuration]() -> AnimationEffectPhase { >+ // 3.5.5. Animation effect phases and states >+ // https://drafts.csswg.org/web-animations-1/#animation-effect-phases-and-states >+ >+ bool animationIsBackwards = m_animation && m_animation->playbackRate() < 0; >+ auto beforeActiveBoundaryTime = std::max(std::min(m_delay, endTime), 0_s); >+ auto activeAfterBoundaryTime = std::max(std::min(m_delay + activeDuration, endTime), 0_s); >+ >+ // (This should be the last statement, but it's more efficient to cache the local time and return right away if it's not resolved.) >+ // Furthermore, it is often convenient to refer to the case when an animation effect is in none of the above phases >+ // as being in the idle phase. >+ if (!localTime) >+ return AnimationEffectPhase::Idle; >+ >+ // An animation effect is in the before phase if the animation effectâs local time is not unresolved and >+ // either of the following conditions are met: >+ // 1. the local time is less than the before-active boundary time, or >+ // 2. the animation direction is âbackwardsâ and the local time is equal to the before-active boundary time. >+ if ((*localTime + timeEpsilon) < beforeActiveBoundaryTime || (animationIsBackwards && std::abs(localTime->microseconds() - beforeActiveBoundaryTime.microseconds()) < timeEpsilon.microseconds())) >+ return AnimationEffectPhase::Before; >+ >+ // An animation effect is in the after phase if the animation effectâs local time is not unresolved and >+ // either of the following conditions are met: >+ // 1. the local time is greater than the active-after boundary time, or >+ // 2. the animation direction is âforwardsâ and the local time is equal to the active-after boundary time. >+ if ((*localTime - timeEpsilon) > activeAfterBoundaryTime || (!animationIsBackwards && std::abs(localTime->microseconds() - activeAfterBoundaryTime.microseconds()) < timeEpsilon.microseconds())) >+ return AnimationEffectPhase::After; >+ >+ // An animation effect is in the active phase if the animation effectâs local time is not unresolved and it is not >+ // in either the before phase nor the after phase. >+ // (No need to check, we've already established that local time was resolved). >+ return AnimationEffectPhase::Active; >+ }(); >+ >+ auto activeTime = [this, localTime, phase, activeDuration]() -> std::optional<Seconds> { >+ // 3.8.3.1. Calculating the active time >+ // https://drafts.csswg.org/web-animations-1/#calculating-the-active-time >+ >+ // The active time is based on the local time and start delay. However, it is only defined >+ // when the animation effect should produce an output and hence depends on its fill mode >+ // and phase as follows, >+ >+ // If the animation effect is in the before phase, the result depends on the first matching >+ // condition from the following, >+ if (phase == AnimationEffectPhase::Before) { >+ // If the fill mode is backwards or both, return the result of evaluating >+ // max(local time - start delay, 0). >+ if (m_fill == FillMode::Backwards || m_fill == FillMode::Both) >+ return std::max(*localTime - m_delay, 0_s); >+ // Otherwise, return an unresolved time value. >+ return std::nullopt; >+ } > >- // The overall progress describes the number of iterations that have completed (including partial iterations) and is defined as follows: >+ // If the animation effect is in the active phase, return the result of evaluating local time - start delay. >+ if (phase == AnimationEffectPhase::Active) >+ return *localTime - m_delay; >+ >+ // If the animation effect is in the after phase, the result depends on the first matching >+ // condition from the following, >+ if (phase == AnimationEffectPhase::After) { >+ // If the fill mode is forwards or both, return the result of evaluating >+ // max(min(local time - start delay, active duration), 0). >+ if (m_fill == FillMode::Forwards || m_fill == FillMode::Both) >+ return std::max(std::min(*localTime - m_delay, activeDuration), 0_s); >+ // Otherwise, return an unresolved time value. >+ return std::nullopt; >+ } > >- // 1. If the active time is unresolved, return unresolved. >- auto effectActiveTime = activeTime(); >- if (!effectActiveTime) >+ // Otherwise (the local time is unresolved), return an unresolved time value. > return std::nullopt; >- >- // 2. Calculate an initial value for overall progress based on the first matching condition from below, >- double overallProgress; >- >- if (!m_iterationDuration) { >- // If the iteration duration is zero, if the animation effect is in the before phase, let overall progress be zero, >- // otherwise, let it be equal to the iteration count. >- overallProgress = phase() == Phase::Before ? 0 : m_iterations; >- } else { >- // Otherwise, let overall progress be the result of calculating active time / iteration duration. >- overallProgress = secondsToWebAnimationsAPITime(effectActiveTime.value()) / secondsToWebAnimationsAPITime(m_iterationDuration); >- } >- >- // 3. Return the result of calculating overall progress + iteration start. >- overallProgress += m_iterationStart; >- return std::abs(overallProgress); >+ }(); >+ >+ BasicEffectTiming basicEffectTiming; >+ basicEffectTiming.localTime = localTime; >+ basicEffectTiming.endTime = endTime; >+ basicEffectTiming.activeDuration = activeDuration; >+ basicEffectTiming.activeTime = activeTime; >+ basicEffectTiming.phase = phase; >+ return basicEffectTiming; > } > >-std::optional<double> AnimationEffect::simpleIterationProgress() const >+ComputedEffectTiming AnimationEffect::getComputedTiming() const > { >- // 3.8.3.3. Calculating the simple iteration progress >- // https://drafts.csswg.org/web-animations-1/#calculating-the-simple-iteration-progress >+ // The Web Animations spec introduces a number of animation effect time-related definitions that refer >+ // to each other a fair bit, so rather than implementing them as individual methods, it's more efficient >+ // to return them all as a single ComputedEffectTiming. > >- // The simple iteration progress is a fraction of the progress through the current iteration that >- // ignores transformations to the time introduced by the playback direction or timing functions >- // applied to the effect, and is calculated as follows: >+ auto basicEffectTiming = getBasicTiming(); >+ auto activeTime = basicEffectTiming.activeTime; >+ auto activeDuration = basicEffectTiming.activeDuration; >+ auto phase = basicEffectTiming.phase; > >- // 1. If the overall progress is unresolved, return unresolved. >- auto effectOverallProgress = overallProgress(); >- if (!effectOverallProgress) >- return std::nullopt; >+ auto overallProgress = [this, phase, activeTime]() -> std::optional<double> { >+ // 3.8.3.2. Calculating the overall progress >+ // https://drafts.csswg.org/web-animations-1/#calculating-the-overall-progress > >- // 2. If overall progress is infinity, let the simple iteration progress be iteration start % 1.0, >- // otherwise, let the simple iteration progress be overall progress % 1.0. >- double overallProgressValue = effectOverallProgress.value(); >- double simpleIterationProgress = std::isinf(overallProgressValue) ? fmod(m_iterationStart, 1) : fmod(overallProgressValue, 1); >+ // The overall progress describes the number of iterations that have completed (including partial iterations) and is defined as follows: > >- // 3. If all of the following conditions are true, >- // >- // the simple iteration progress calculated above is zero, and >- // the animation effect is in the active phase or the after phase, and >- // the active time is equal to the active duration, and >- // the iteration count is not equal to zero. >- // let the simple iteration progress be 1.0. >- auto effectPhase = phase(); >- if (!simpleIterationProgress && (effectPhase == Phase::Active || effectPhase == Phase::After) && std::abs(activeTime().value().microseconds() - activeDuration().microseconds()) < timeEpsilon.microseconds() && m_iterations) >- return 1; >- >- return simpleIterationProgress; >-} >+ // 1. If the active time is unresolved, return unresolved. >+ if (!activeTime) >+ return std::nullopt; > >-std::optional<double> AnimationEffect::currentIteration() const >-{ >- // 3.8.4. Calculating the current iteration >- // https://drafts.csswg.org/web-animations-1/#calculating-the-current-iteration >+ // 2. Calculate an initial value for overall progress based on the first matching condition from below, >+ double overallProgress; > >- // The current iteration can be calculated using the following steps: >- >- // 1. If the active time is unresolved, return unresolved. >- if (!activeTime()) >- return std::nullopt; >- >- // 2. If the animation effect is in the after phase and the iteration count is infinity, return infinity. >- if (phase() == Phase::After && std::isinf(m_iterations)) >- return std::numeric_limits<double>::infinity(); >- >- // 3. If the simple iteration progress is 1.0, return floor(overall progress) - 1. >- if (simpleIterationProgress().value() == 1) >- return floor(overallProgress().value()) - 1; >- >- // 4. Otherwise, return floor(overall progress). >- return floor(overallProgress().value()); >-} >+ if (!m_iterationDuration) { >+ // If the iteration duration is zero, if the animation effect is in the before phase, let overall progress be zero, >+ // otherwise, let it be equal to the iteration count. >+ overallProgress = phase == AnimationEffectPhase::Before ? 0 : m_iterations; >+ } else { >+ // Otherwise, let overall progress be the result of calculating active time / iteration duration. >+ overallProgress = secondsToWebAnimationsAPITime(*activeTime) / secondsToWebAnimationsAPITime(m_iterationDuration); >+ } > >-AnimationEffect::ComputedDirection AnimationEffect::currentDirection() const >-{ >- // 3.9.1. Calculating the directed progress >- // https://drafts.csswg.org/web-animations-1/#calculating-the-directed-progress >+ // 3. Return the result of calculating overall progress + iteration start. >+ overallProgress += m_iterationStart; >+ return std::abs(overallProgress); >+ }(); >+ >+ auto simpleIterationProgress = [this, overallProgress, phase, activeTime, activeDuration]() -> std::optional<double> { >+ // 3.8.3.3. Calculating the simple iteration progress >+ // https://drafts.csswg.org/web-animations-1/#calculating-the-simple-iteration-progress >+ >+ // The simple iteration progress is a fraction of the progress through the current iteration that >+ // ignores transformations to the time introduced by the playback direction or timing functions >+ // applied to the effect, and is calculated as follows: >+ >+ // 1. If the overall progress is unresolved, return unresolved. >+ if (!overallProgress) >+ return std::nullopt; >+ >+ // 2. If overall progress is infinity, let the simple iteration progress be iteration start % 1.0, >+ // otherwise, let the simple iteration progress be overall progress % 1.0. >+ double simpleIterationProgress = std::isinf(*overallProgress) ? fmod(m_iterationStart, 1) : fmod(*overallProgress, 1); >+ >+ // 3. If all of the following conditions are true, >+ // >+ // the simple iteration progress calculated above is zero, and >+ // the animation effect is in the active phase or the after phase, and >+ // the active time is equal to the active duration, and >+ // the iteration count is not equal to zero. >+ // let the simple iteration progress be 1.0. >+ if (!simpleIterationProgress && (phase == AnimationEffectPhase::Active || phase == AnimationEffectPhase::After) && std::abs(activeTime->microseconds() - activeDuration.microseconds()) < timeEpsilon.microseconds() && m_iterations) >+ return 1; >+ >+ return simpleIterationProgress; >+ }(); >+ >+ auto currentIteration = [this, activeTime, phase, simpleIterationProgress, overallProgress]() -> std::optional<double> { >+ // 3.8.4. Calculating the current iteration >+ // https://drafts.csswg.org/web-animations-1/#calculating-the-current-iteration >+ >+ // The current iteration can be calculated using the following steps: >+ >+ // 1. If the active time is unresolved, return unresolved. >+ if (!activeTime) >+ return std::nullopt; >+ >+ // 2. If the animation effect is in the after phase and the iteration count is infinity, return infinity. >+ if (phase == AnimationEffectPhase::After && std::isinf(m_iterations)) >+ return std::numeric_limits<double>::infinity(); >+ >+ // 3. If the simple iteration progress is 1.0, return floor(overall progress) - 1. >+ if (*simpleIterationProgress == 1) >+ return floor(*overallProgress) - 1; >+ >+ // 4. Otherwise, return floor(overall progress). >+ return floor(*overallProgress); >+ }(); >+ >+ auto currentDirection = [this, currentIteration]() -> AnimationEffect::ComputedDirection { >+ // 3.9.1. Calculating the directed progress >+ // https://drafts.csswg.org/web-animations-1/#calculating-the-directed-progress >+ >+ // If playback direction is normal, let the current direction be forwards. >+ if (m_direction == PlaybackDirection::Normal) >+ return AnimationEffect::ComputedDirection::Forwards; >+ >+ // If playback direction is reverse, let the current direction be reverse. >+ if (m_direction == PlaybackDirection::Reverse) >+ return AnimationEffect::ComputedDirection::Reverse; > >- // If playback direction is normal, let the current direction be forwards. >- if (m_direction == PlaybackDirection::Normal) >- return AnimationEffect::ComputedDirection::Forwards; >+ if (!currentIteration) >+ return AnimationEffect::ComputedDirection::Forwards; > >- // If playback direction is reverse, let the current direction be reverse. >- if (m_direction == PlaybackDirection::Reverse) >+ // Otherwise, let d be the current iteration. >+ auto d = *currentIteration; >+ // If playback direction is alternate-reverse increment d by 1. >+ if (m_direction == PlaybackDirection::AlternateReverse) >+ d++; >+ // If d % 2 == 0, let the current direction be forwards, otherwise let the current direction be reverse. >+ // If d is infinity, let the current direction be forwards. >+ if (std::isinf(d) || !fmod(d, 2)) >+ return AnimationEffect::ComputedDirection::Forwards; > return AnimationEffect::ComputedDirection::Reverse; >- >- // Otherwise, let d be the current iteration. >- auto d = currentIteration().value(); >- // If playback direction is alternate-reverse increment d by 1. >- if (m_direction == PlaybackDirection::AlternateReverse) >- d++; >- // If d % 2 == 0, let the current direction be forwards, otherwise let the current direction be reverse. >- // If d is infinity, let the current direction be forwards. >- if (std::isinf(d) || !fmod(d, 2)) >- return AnimationEffect::ComputedDirection::Forwards; >- return AnimationEffect::ComputedDirection::Reverse; >-} >- >-std::optional<double> AnimationEffect::directedProgress() const >-{ >- // 3.9.1. Calculating the directed progress >- // https://drafts.csswg.org/web-animations-1/#calculating-the-directed-progress >- >- // The directed progress is calculated from the simple iteration progress using the following steps: >- >- // 1. If the simple iteration progress is unresolved, return unresolved. >- auto effectSimpleIterationProgress = simpleIterationProgress(); >- if (!effectSimpleIterationProgress) >- return std::nullopt; >- >- // 2. Calculate the current direction (we implement this as a separate method). >- >- // 3. If the current direction is forwards then return the simple iteration progress. >- if (currentDirection() == AnimationEffect::ComputedDirection::Forwards) >- return effectSimpleIterationProgress.value(); >- >- // Otherwise, return 1.0 - simple iteration progress. >- return 1 - effectSimpleIterationProgress.value(); >-} >- >-std::optional<double> AnimationEffect::transformedProgress() const >-{ >- // 3.10.1. Calculating the transformed progress >- // https://drafts.csswg.org/web-animations-1/#calculating-the-transformed-progress >- >- // The transformed progress is calculated from the directed progress using the following steps: >- // >- // 1. If the directed progress is unresolved, return unresolved. >- auto effectDirectedProgress = directedProgress(); >- if (!effectDirectedProgress) >- return std::nullopt; >- >- auto effectDirectedProgressValue = effectDirectedProgress.value(); >- >- if (auto iterationDuration = m_iterationDuration.seconds()) { >- bool before = false; >- // 2. Calculate the value of the before flag as follows: >- if (is<StepsTimingFunction>(m_timingFunction)) { >- // 1. Determine the current direction using the procedure defined in §3.9.1 Calculating the directed progress. >- // 2. If the current direction is forwards, let going forwards be true, otherwise it is false. >- bool goingForwards = currentDirection() == AnimationEffect::ComputedDirection::Forwards; >- // 3. The before flag is set if the animation effect is in the before phase and going forwards is true; >- // or if the animation effect is in the after phase and going forwards is false. >- auto effectPhase = phase(); >- before = (effectPhase == Phase::Before && goingForwards) || (effectPhase == Phase::After && !goingForwards); >+ }(); >+ >+ auto directedProgress = [simpleIterationProgress, currentDirection]() -> std::optional<double> { >+ // 3.9.1. Calculating the directed progress >+ // https://drafts.csswg.org/web-animations-1/#calculating-the-directed-progress >+ >+ // The directed progress is calculated from the simple iteration progress using the following steps: >+ >+ // 1. If the simple iteration progress is unresolved, return unresolved. >+ if (!simpleIterationProgress) >+ return std::nullopt; >+ >+ // 2. Calculate the current direction (we implement this as a separate method). >+ >+ // 3. If the current direction is forwards then return the simple iteration progress. >+ if (currentDirection == AnimationEffect::ComputedDirection::Forwards) >+ return *simpleIterationProgress; >+ >+ // Otherwise, return 1.0 - simple iteration progress. >+ return 1 - *simpleIterationProgress; >+ }(); >+ >+ auto transformedProgress = [this, directedProgress, currentDirection, phase]() -> std::optional<double> { >+ // 3.10.1. Calculating the transformed progress >+ // https://drafts.csswg.org/web-animations-1/#calculating-the-transformed-progress >+ >+ // The transformed progress is calculated from the directed progress using the following steps: >+ // >+ // 1. If the directed progress is unresolved, return unresolved. >+ if (!directedProgress) >+ return std::nullopt; >+ >+ if (auto iterationDuration = m_iterationDuration.seconds()) { >+ bool before = false; >+ // 2. Calculate the value of the before flag as follows: >+ if (is<StepsTimingFunction>(m_timingFunction)) { >+ // 1. Determine the current direction using the procedure defined in §3.9.1 Calculating the directed progress. >+ // 2. If the current direction is forwards, let going forwards be true, otherwise it is false. >+ bool goingForwards = currentDirection == AnimationEffect::ComputedDirection::Forwards; >+ // 3. The before flag is set if the animation effect is in the before phase and going forwards is true; >+ // or if the animation effect is in the after phase and going forwards is false. >+ before = (phase == AnimationEffectPhase::Before && goingForwards) || (phase == AnimationEffectPhase::After && !goingForwards); >+ } >+ >+ // 3. Return the result of evaluating the animation effectâs timing function passing directed progress as the >+ // input progress value and before flag as the before flag. >+ return m_timingFunction->transformTime(*directedProgress, iterationDuration, before); > } > >- // 3. Return the result of evaluating the animation effectâs timing function passing directed progress as the >- // input progress value and before flag as the before flag. >- return m_timingFunction->transformTime(effectDirectedProgressValue, iterationDuration, before); >- } >- >- return effectDirectedProgressValue; >-} >- >-std::optional<double> AnimationEffect::iterationProgress() const >-{ >- return transformedProgress(); >-} >- >-EffectTiming AnimationEffect::getTiming() >-{ >- EffectTiming timing; >- timing.delay = secondsToWebAnimationsAPITime(m_delay); >- timing.endDelay = secondsToWebAnimationsAPITime(m_endDelay); >- timing.fill = m_fill; >- timing.iterationStart = m_iterationStart; >- timing.iterations = m_iterations; >- if (m_iterationDuration == 0_s) >- timing.duration = "auto"; >- else >- timing.duration = secondsToWebAnimationsAPITime(m_iterationDuration); >- timing.direction = m_direction; >- timing.easing = m_timingFunction->cssText(); >- return timing; >-} >+ return *directedProgress; >+ }(); > >-ComputedEffectTiming AnimationEffect::getComputedTiming() >-{ > ComputedEffectTiming computedTiming; > computedTiming.delay = secondsToWebAnimationsAPITime(m_delay); > computedTiming.endDelay = secondsToWebAnimationsAPITime(m_endDelay); >@@ -327,12 +353,14 @@ ComputedEffectTiming AnimationEffect::getComputedTiming() > computedTiming.duration = secondsToWebAnimationsAPITime(m_iterationDuration); > computedTiming.direction = m_direction; > computedTiming.easing = m_timingFunction->cssText(); >- computedTiming.endTime = secondsToWebAnimationsAPITime(endTime()); >- computedTiming.activeDuration = secondsToWebAnimationsAPITime(activeDuration()); >- if (auto effectLocalTime = localTime()) >- computedTiming.localTime = secondsToWebAnimationsAPITime(effectLocalTime.value()); >- computedTiming.progress = iterationProgress(); >- computedTiming.currentIteration = currentIteration(); >+ computedTiming.endTime = secondsToWebAnimationsAPITime(basicEffectTiming.endTime); >+ computedTiming.activeDuration = secondsToWebAnimationsAPITime(activeDuration); >+ if (basicEffectTiming.localTime) >+ computedTiming.localTime = secondsToWebAnimationsAPITime(*basicEffectTiming.localTime); >+ computedTiming.simpleIterationProgress = simpleIterationProgress; >+ computedTiming.progress = transformedProgress; >+ computedTiming.currentIteration = currentIteration; >+ computedTiming.phase = phase; > return computedTiming; > } > >@@ -448,16 +476,6 @@ ExceptionOr<void> AnimationEffect::setIterations(double iterations) > return { }; > } > >-Seconds AnimationEffect::endTime() const >-{ >- // 3.5.3 The active interval >- // https://drafts.csswg.org/web-animations-1/#end-time >- >- // The end time of an animation effect is the result of evaluating max(start delay + active duration + end delay, 0). >- auto endTime = m_delay + activeDuration() + m_endDelay; >- return endTime > 0_s ? endTime : 0_s; >-} >- > void AnimationEffect::setDelay(const Seconds& delay) > { > if (m_delay == delay) >@@ -503,17 +521,4 @@ void AnimationEffect::setTimingFunction(const RefPtr<TimingFunction>& timingFunc > m_timingFunction = timingFunction; > } > >-Seconds AnimationEffect::activeDuration() const >-{ >- // 3.8.2. Calculating the active duration >- // https://drafts.csswg.org/web-animations-1/#calculating-the-active-duration >- >- // The active duration is calculated as follows: >- // active duration = iteration duration à iteration count >- // If either the iteration duration or iteration count are zero, the active duration is zero. >- if (!m_iterationDuration || !m_iterations) >- return 0_s; >- return m_iterationDuration * m_iterations; >-} >- > } // namespace WebCore >diff --git a/Source/WebCore/animation/AnimationEffect.h b/Source/WebCore/animation/AnimationEffect.h >index 8584db2b9d78d987c878f8ac47d2b46d42314bf6..1bddd88b12791d11aad0d90b33728d1ec47c5cb9 100644 >--- a/Source/WebCore/animation/AnimationEffect.h >+++ b/Source/WebCore/animation/AnimationEffect.h >@@ -26,6 +26,8 @@ > #pragma once > > #include "AnimationEffect.h" >+#include "AnimationEffectPhase.h" >+#include "BasicEffectTiming.h" > #include "ComputedEffectTiming.h" > #include "ExceptionOr.h" > #include "FillMode.h" >@@ -51,8 +53,9 @@ public: > > virtual bool isKeyframeEffect() const { return false; } > >- EffectTiming getTiming(); >- ComputedEffectTiming getComputedTiming(); >+ EffectTiming getTiming() const; >+ BasicEffectTiming getBasicTiming() const; >+ ComputedEffectTiming getComputedTiming() const; > ExceptionOr<void> updateTiming(std::optional<OptionalEffectTiming>); > > virtual void apply(RenderStyle&) = 0; >@@ -87,28 +90,12 @@ public: > TimingFunction* timingFunction() const { return m_timingFunction.get(); } > void setTimingFunction(const RefPtr<TimingFunction>&); > >- std::optional<Seconds> localTime() const; >- std::optional<Seconds> activeTime() const; >- Seconds endTime() const; >- std::optional<double> simpleIterationProgress() const; >- std::optional<double> iterationProgress() const; >- std::optional<double> currentIteration() const; >- Seconds activeDuration() const; >- >- enum class Phase { Before, Active, After, Idle }; >- Phase phase() const; >- > protected: > explicit AnimationEffect(); > > private: > enum class ComputedDirection { Forwards, Reverse }; > >- std::optional<double> overallProgress() const; >- AnimationEffect::ComputedDirection currentDirection() const; >- std::optional<double> directedProgress() const; >- std::optional<double> transformedProgress() const; >- > Seconds m_delay { 0_s }; > Seconds m_endDelay { 0_s }; > FillMode m_fill { FillMode::Auto }; >diff --git a/Source/WebCore/animation/AnimationEffectPhase.h b/Source/WebCore/animation/AnimationEffectPhase.h >new file mode 100644 >index 0000000000000000000000000000000000000000..0d050f8784d370910864810d4ff3d04b5b3ce3e8 >--- /dev/null >+++ b/Source/WebCore/animation/AnimationEffectPhase.h >@@ -0,0 +1,32 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * 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 >+ >+namespace WebCore { >+ >+enum class AnimationEffectPhase { Before, Active, After, Idle }; >+ >+} // namespace WebCore >diff --git a/Source/WebCore/animation/AnimationTimeline.cpp b/Source/WebCore/animation/AnimationTimeline.cpp >index 67a6f3f85b0d7a5107b39a9a8e27a7a498941a76..83748e11ca7a67d878271f5127f0436f0189eb86 100644 >--- a/Source/WebCore/animation/AnimationTimeline.cpp >+++ b/Source/WebCore/animation/AnimationTimeline.cpp >@@ -460,7 +460,7 @@ void AnimationTimeline::updateCSSTransitionsForElement(Element& element, const R > auto& reversingAdjustedStartStyle = previouslyRunningTransition->targetStyle(); > double transformedProgress = 1; > if (auto* effect = previouslyRunningTransition->effect()) >- transformedProgress = effect->iterationProgress().value_or(transformedProgress); >+ transformedProgress = effect->getComputedTiming().progress.value_or(transformedProgress); > auto reversingShorteningFactor = std::max(std::min(((transformedProgress * previouslyRunningTransition->reversingShorteningFactor()) + (1 - previouslyRunningTransition->reversingShorteningFactor())), 1.0), 0.0); > auto delay = matchingBackingAnimation->delay() < 0 ? Seconds(matchingBackingAnimation->delay()) * reversingShorteningFactor : Seconds(matchingBackingAnimation->delay()); > auto duration = Seconds(matchingBackingAnimation->duration()) * reversingShorteningFactor; >diff --git a/Source/WebCore/animation/AnimationTimeline.h b/Source/WebCore/animation/AnimationTimeline.h >index 896eb553dc62e30c430a772f59b35641b8948271..dfe712e1aaafbd078c9228badf634822378f9f4b 100644 >--- a/Source/WebCore/animation/AnimationTimeline.h >+++ b/Source/WebCore/animation/AnimationTimeline.h >@@ -27,6 +27,7 @@ > #pragma once > > #include "CSSValue.h" >+#include "ComputedEffectTiming.h" > #include "RenderStyle.h" > #include "WebAnimation.h" > #include <wtf/Forward.h> >diff --git a/Source/WebCore/animation/BasicEffectTiming.h b/Source/WebCore/animation/BasicEffectTiming.h >new file mode 100644 >index 0000000000000000000000000000000000000000..21eb7c3544b39f372715fecb250447232df81dbe >--- /dev/null >+++ b/Source/WebCore/animation/BasicEffectTiming.h >@@ -0,0 +1,42 @@ >+/* >+ * Copyright (C) 2018 Apple Inc. All rights reserved. >+ * >+ * 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 >+ >+#include "AnimationEffectPhase.h" >+#include <wtf/Optional.h> >+#include <wtf/Seconds.h> >+ >+namespace WebCore { >+ >+struct BasicEffectTiming { >+ std::optional<Seconds> localTime; >+ Seconds endTime; >+ Seconds activeDuration; >+ std::optional<Seconds> activeTime; >+ AnimationEffectPhase phase; >+}; >+ >+} // namespace WebCore >diff --git a/Source/WebCore/animation/ComputedEffectTiming.h b/Source/WebCore/animation/ComputedEffectTiming.h >index eb9fe9384963b5cd4620100471ebc2e7185a4f58..3af0a232a219e8a69b83e7e022fd293870cdcdba 100644 >--- a/Source/WebCore/animation/ComputedEffectTiming.h >+++ b/Source/WebCore/animation/ComputedEffectTiming.h >@@ -25,15 +25,18 @@ > > #pragma once > >+#include "AnimationEffectPhase.h" > #include "EffectTiming.h" > #include <wtf/Optional.h> > > namespace WebCore { > > struct ComputedEffectTiming : EffectTiming { >+ AnimationEffectPhase phase { AnimationEffectPhase::Idle }; > double endTime; > double activeDuration; > std::optional<double> localTime; >+ std::optional<double> simpleIterationProgress; > std::optional<double> progress; > std::optional<double> currentIteration; > }; >diff --git a/Source/WebCore/animation/DeclarativeAnimation.cpp b/Source/WebCore/animation/DeclarativeAnimation.cpp >index 87a75235c00b397f907a3b7b40051762d35db570..31e0a202e49df0533c959870193ae05fb12e5be9 100644 >--- a/Source/WebCore/animation/DeclarativeAnimation.cpp >+++ b/Source/WebCore/animation/DeclarativeAnimation.cpp >@@ -198,8 +198,8 @@ void DeclarativeAnimation::setTimeline(RefPtr<AnimationTimeline>&& newTimeline) > void DeclarativeAnimation::cancel() > { > auto cancelationTime = 0_s; >- if (auto animationEffect = effect()) >- cancelationTime = animationEffect->activeTime().value_or(0_s); >+ if (auto* animationEffect = effect()) >+ cancelationTime = animationEffect->getBasicTiming().activeTime.value_or(0_s); > > WebAnimation::cancel(); > >@@ -212,17 +212,17 @@ void DeclarativeAnimation::cancelFromStyle() > disassociateFromOwningElement(); > } > >-AnimationEffect::Phase DeclarativeAnimation::phaseWithoutEffect() const >+AnimationEffectPhase DeclarativeAnimation::phaseWithoutEffect() const > { > // This shouldn't be called if we actually have an effect. > ASSERT(!effect()); > > auto animationCurrentTime = currentTime(); > if (!animationCurrentTime) >- return AnimationEffect::Phase::Idle; >+ return AnimationEffectPhase::Idle; > > // Since we don't have an effect, the duration will be zero so the phase is 'before' if the current time is less than zero. >- return animationCurrentTime.value() < 0_s ? AnimationEffect::Phase::Before : AnimationEffect::Phase::After; >+ return *animationCurrentTime < 0_s ? AnimationEffectPhase::Before : AnimationEffectPhase::After; > } > > void DeclarativeAnimation::invalidateDOMEvents(Seconds elapsedTime) >@@ -230,27 +230,38 @@ void DeclarativeAnimation::invalidateDOMEvents(Seconds elapsedTime) > if (!m_owningElement) > return; > >- auto* animationEffect = effect(); >- > auto isPending = pending(); > if (isPending && m_wasPending) > return; > >- auto iteration = animationEffect ? animationEffect->currentIteration().value_or(0) : 0; >- auto currentPhase = animationEffect ? animationEffect->phase() : phaseWithoutEffect(); >+ double iteration; >+ AnimationEffectPhase currentPhase; >+ Seconds intervalStart; >+ Seconds intervalEnd; > >- bool wasActive = m_previousPhase == AnimationEffect::Phase::Active; >- bool wasAfter = m_previousPhase == AnimationEffect::Phase::After; >- bool wasBefore = m_previousPhase == AnimationEffect::Phase::Before; >- bool wasIdle = m_previousPhase == AnimationEffect::Phase::Idle; >+ auto* animationEffect = effect(); >+ if (animationEffect) { >+ auto timing = animationEffect->getComputedTiming(); >+ iteration = timing.currentIteration.value_or(0); >+ currentPhase = timing.phase; >+ intervalStart = std::max(0_s, Seconds::fromMilliseconds(std::min(-timing.delay, timing.activeDuration))); >+ intervalEnd = std::max(0_s, Seconds::fromMilliseconds(std::min(timing.endTime - timing.delay, timing.activeDuration))); >+ } else { >+ iteration = 0; >+ currentPhase = phaseWithoutEffect(); >+ intervalStart = 0_s; >+ intervalEnd = 0_s; >+ } > >- bool isActive = currentPhase == AnimationEffect::Phase::Active; >- bool isAfter = currentPhase == AnimationEffect::Phase::After; >- bool isBefore = currentPhase == AnimationEffect::Phase::Before; >- bool isIdle = currentPhase == AnimationEffect::Phase::Idle; >+ bool wasActive = m_previousPhase == AnimationEffectPhase::Active; >+ bool wasAfter = m_previousPhase == AnimationEffectPhase::After; >+ bool wasBefore = m_previousPhase == AnimationEffectPhase::Before; >+ bool wasIdle = m_previousPhase == AnimationEffectPhase::Idle; > >- auto intervalStart = animationEffect ? std::max(0_s, std::min(-animationEffect->delay(), animationEffect->activeDuration())) : 0_s; >- auto intervalEnd = animationEffect ? std::max(0_s, std::min(animationEffect->endTime() - animationEffect->delay(), animationEffect->activeDuration())) : 0_s; >+ bool isActive = currentPhase == AnimationEffectPhase::Active; >+ bool isAfter = currentPhase == AnimationEffectPhase::After; >+ bool isBefore = currentPhase == AnimationEffectPhase::Before; >+ bool isIdle = currentPhase == AnimationEffectPhase::Idle; > > if (is<CSSAnimation>(this)) { > // https://drafts.csswg.org/css-animations-2/#events >diff --git a/Source/WebCore/animation/DeclarativeAnimation.h b/Source/WebCore/animation/DeclarativeAnimation.h >index b27a5462c825e8549bef431c05dc22ad6a3423b8..051de8f8d77c163e56033db510abb863cafa970e 100644 >--- a/Source/WebCore/animation/DeclarativeAnimation.h >+++ b/Source/WebCore/animation/DeclarativeAnimation.h >@@ -26,6 +26,7 @@ > #pragma once > > #include "AnimationEffect.h" >+#include "AnimationEffectPhase.h" > #include "GenericEventQueue.h" > #include "WebAnimation.h" > #include <wtf/Ref.h> >@@ -74,7 +75,7 @@ protected: > private: > void disassociateFromOwningElement(); > void flushPendingStyleChanges() const; >- AnimationEffect::Phase phaseWithoutEffect() const; >+ AnimationEffectPhase phaseWithoutEffect() const; > void enqueueDOMEvent(const AtomicString&, Seconds); > void remove() final; > >@@ -86,7 +87,7 @@ private: > Element* m_owningElement; > Ref<Animation> m_backingAnimation; > bool m_wasPending { false }; >- AnimationEffect::Phase m_previousPhase { AnimationEffect::Phase::Idle }; >+ AnimationEffectPhase m_previousPhase { AnimationEffectPhase::Idle }; > double m_previousIteration; > GenericEventQueue m_eventQueue; > }; >diff --git a/Source/WebCore/animation/KeyframeEffect.cpp b/Source/WebCore/animation/KeyframeEffect.cpp >index 95daf9123e5106f73d4677bdae48dcf2981f75e3..bfc57a4fe1c22fb3c554dd9e8ae78fd535d1e800 100644 >--- a/Source/WebCore/animation/KeyframeEffect.cpp >+++ b/Source/WebCore/animation/KeyframeEffect.cpp >@@ -1008,7 +1008,7 @@ void KeyframeEffect::apply(RenderStyle& targetStyle) > > updateAcceleratedAnimationState(); > >- auto progress = iterationProgress(); >+ auto progress = getComputedTiming().progress; > if (!progress) > return; > >@@ -1042,7 +1042,7 @@ void KeyframeEffect::getAnimatedStyle(std::unique_ptr<RenderStyle>& animatedStyl > if (!m_target || !animation()) > return; > >- auto progress = iterationProgress(); >+ auto progress = getComputedTiming().progress; > if (!progress) > return; > >diff --git a/Source/WebCore/animation/WebAnimation.cpp b/Source/WebCore/animation/WebAnimation.cpp >index f65df1e5647c9d4c99e7d25a7e33063514c9bc93..c6381fa4ec3135659fc748b28085630d08c8b296 100644 >--- a/Source/WebCore/animation/WebAnimation.cpp >+++ b/Source/WebCore/animation/WebAnimation.cpp >@@ -538,7 +538,7 @@ Seconds WebAnimation::effectEndTime() const > { > // The target effect end of an animation is equal to the end time of the animation's target effect. > // If the animation has no target effect, the target effect end is zero. >- return m_effect ? m_effect->endTime() : 0_s; >+ return m_effect ? m_effect->getBasicTiming().endTime : 0_s; > } > > void WebAnimation::cancel() >@@ -1173,8 +1173,10 @@ bool WebAnimation::computeRelevance() > if (!m_effect) > return false; > >+ auto timing = m_effect->getBasicTiming(); >+ > // An animation effect is in effect if its active time is not unresolved. >- if (m_effect->activeTime()) >+ if (timing.activeTime) > return true; > > // An animation effect is current if either of the following conditions is true: >@@ -1184,8 +1186,7 @@ bool WebAnimation::computeRelevance() > // An animation effect is in play if all of the following conditions are met: > // - the animation effect is in the active phase, and > // - the animation effect is associated with an animation that is not finished. >- auto phase = m_effect->phase(); >- return phase == AnimationEffect::Phase::Before || (phase == AnimationEffect::Phase::Active && playState() != PlayState::Finished); >+ return timing.phase == AnimationEffectPhase::Before || (timing.phase == AnimationEffectPhase::Active && playState() != PlayState::Finished); > } > > Seconds WebAnimation::timeToNextTick() const >@@ -1202,9 +1203,11 @@ Seconds WebAnimation::timeToNextTick() const > // CSS Animations dispatch events for each iteration, so compute the time until > // the end of this iteration. Any other animation only cares about remaning total time. > if (isCSSAnimation()) { >+ auto* animationEffect = effect(); >+ auto timing = animationEffect->getComputedTiming(); > // If we're actively running, we need the time until the next iteration. >- if (auto iterationProgress = effect()->simpleIterationProgress()) >- return effect()->iterationDuration() * (1 - iterationProgress.value()); >+ if (auto iterationProgress = timing.simpleIterationProgress) >+ return animationEffect->iterationDuration() * (1 - *iterationProgress); > > // Otherwise we're probably in the before phase waiting to reach our start time. > if (auto animationCurrentTime = currentTime()) { >@@ -1214,11 +1217,11 @@ Seconds WebAnimation::timeToNextTick() const > auto localTime = animationCurrentTime.value(); > if (localTime < 0_s) > return -localTime; >- if (localTime < effect()->delay()) >- return effect()->delay() - localTime; >+ if (localTime < animationEffect->delay()) >+ return animationEffect->delay() - localTime; > } > } else if (auto animationCurrentTime = currentTime()) >- return effect()->endTime() - animationCurrentTime.value(); >+ return effect()->getBasicTiming().endTime - *animationCurrentTime; > > ASSERT_NOT_REACHED(); > return Seconds::infinity();
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
dino
:
review+
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 192850
: 357670