Diff
Modified: trunk/Source/WebCore/ChangeLog (239722 => 239723)
--- trunk/Source/WebCore/ChangeLog 2019-01-08 09:00:28 UTC (rev 239722)
+++ trunk/Source/WebCore/ChangeLog 2019-01-08 11:31:55 UTC (rev 239723)
@@ -1,3 +1,67 @@
+2018-12-19 Antoine Quint <[email protected]>
+
+ [Web Animations] Compute animation effect timing properties in batch
+ https://bugs.webkit.org/show_bug.cgi?id=192850
+
+ Reviewed by Dean Jackson.
+
+ We remove a host of functions from AnimationEffect that would allow the computation of various timing properties
+ defined by the Web Animations specification: phase, progress, current iteration, etc. Indeed, a lot of these functions
+ would call each other in a chain, and we would re-compute a lot of the earlier properties in those chains several times
+ when doing something like querying the animation progress. Additionally, some functions, such as WebAnimation::computeRelevance()
+ and WebAnimation::timeToNextTick() would yield the computation of several such properties numerous times. All of those
+ functions are called during each animation frame and are ripe for optimizations.
+
+ We now compute all timing properties across two functions:
+
+ 1. the new AnimationEffect::getBasicTiming() which computes the local time, end time, active duration, active time and phase,
+ 2. the existing AnimationEffect::getComputedTiming() which now also exposes the phase and simple iteration progress.
+
+ To support this we introduce a new BasicEffectTiming struct to contain the values computed in AnimationEffect::getBasicTiming()
+ and spun the AnimationEffect::Phase struct as AnimationEffectPhase so that it may be used across BasicEffectTiming and
+ ComputedEffectTiming.
+
+ No new test since there is no user-observable change.
+
+ * WebCore.xcodeproj/project.pbxproj:
+ * animation/AnimationEffect.cpp:
+ (WebCore::AnimationEffect::getTiming const):
+ (WebCore::AnimationEffect::getBasicTiming const):
+ (WebCore::AnimationEffect::getComputedTiming const):
+ (WebCore::AnimationEffect::localTime const): Deleted.
+ (WebCore::AnimationEffect::phase const): Deleted.
+ (WebCore::AnimationEffect::activeTime const): Deleted.
+ (WebCore::AnimationEffect::overallProgress const): Deleted.
+ (WebCore::AnimationEffect::simpleIterationProgress const): Deleted.
+ (WebCore::AnimationEffect::currentIteration const): Deleted.
+ (WebCore::AnimationEffect::currentDirection const): Deleted.
+ (WebCore::AnimationEffect::directedProgress const): Deleted.
+ (WebCore::AnimationEffect::transformedProgress const): Deleted.
+ (WebCore::AnimationEffect::iterationProgress const): Deleted.
+ (WebCore::AnimationEffect::getTiming): Deleted.
+ (WebCore::AnimationEffect::getComputedTiming): Deleted.
+ (WebCore::AnimationEffect::endTime const): Deleted.
+ (WebCore::AnimationEffect::activeDuration const): Deleted.
+ * animation/AnimationEffect.h:
+ * animation/AnimationEffectPhase.h: Copied from Source/WebCore/animation/ComputedEffectTiming.h.
+ * animation/AnimationTimeline.cpp:
+ (WebCore::AnimationTimeline::updateCSSTransitionsForElement):
+ * animation/AnimationTimeline.h:
+ * animation/BasicEffectTiming.h: Copied from Source/WebCore/animation/ComputedEffectTiming.h.
+ * animation/ComputedEffectTiming.h:
+ * animation/DeclarativeAnimation.cpp:
+ (WebCore::DeclarativeAnimation::cancel):
+ (WebCore::DeclarativeAnimation::phaseWithoutEffect const):
+ (WebCore::DeclarativeAnimation::invalidateDOMEvents):
+ * animation/DeclarativeAnimation.h:
+ * animation/KeyframeEffect.cpp:
+ (WebCore::KeyframeEffect::apply):
+ (WebCore::KeyframeEffect::getAnimatedStyle):
+ * animation/WebAnimation.cpp:
+ (WebCore::WebAnimation::effectEndTime const):
+ (WebCore::WebAnimation::computeRelevance):
+ (WebCore::WebAnimation::timeToNextTick const):
+
2019-01-07 Youenn Fablet <[email protected]>
Crash in SWServer::Connection::resolveRegistrationReadyRequests
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (239722 => 239723)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2019-01-08 09:00:28 UTC (rev 239722)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2019-01-08 11:31:55 UTC (rev 239723)
@@ -2095,6 +2095,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, ); }; };
@@ -2107,6 +2108,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 */; };
@@ -9272,6 +9274,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>"; };
@@ -9361,6 +9364,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>"; };
@@ -20201,6 +20205,7 @@
71EFCEDA202B388F00D7C411 /* AnimationEffect.cpp */,
71EFCED7202B388D00D7C411 /* AnimationEffect.h */,
71EFCED6202B388C00D7C411 /* AnimationEffect.idl */,
+ 71E2C42421C9351D0024F8C8 /* AnimationEffectPhase.h */,
714C7C601FDAD27900F2BEE1 /* AnimationPlaybackEvent.cpp */,
714C7C651FDAD27B00F2BEE1 /* AnimationPlaybackEvent.h */,
714C7C641FDAD27B00F2BEE1 /* AnimationPlaybackEvent.idl */,
@@ -20209,6 +20214,7 @@
71025EC61F99F096004A250C /* AnimationTimeline.cpp */,
71025EC71F99F096004A250C /* AnimationTimeline.h */,
71025EC91F99F096004A250C /* AnimationTimeline.idl */,
+ 7156BC9F21CA350600534397 /* BasicEffectTiming.h */,
71247E351FEA5F81008C08CE /* CompositeOperation.h */,
71247E361FEA5F81008C08CE /* CompositeOperation.idl */,
7111243B216FA6E000EB7B67 /* CompositeOperationOrAuto.h */,
@@ -27887,6 +27893,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 */,
@@ -28036,6 +28043,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 */,
Modified: trunk/Source/WebCore/animation/AnimationEffect.cpp (239722 => 239723)
--- trunk/Source/WebCore/animation/AnimationEffect.cpp 2019-01-08 09:00:28 UTC (rev 239722)
+++ trunk/Source/WebCore/animation/AnimationEffect.cpp 2019-01-08 11:31:55 UTC (rev 239723)
@@ -41,283 +41,303 @@
{
}
-Optional<Seconds> AnimationEffect::localTime() const
+EffectTiming AnimationEffect::getTiming() const
{
- if (m_animation)
- return m_animation->currentTime();
- return WTF::nullopt;
+ 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;
}
-auto AnimationEffect::phase() const -> Phase
+BasicEffectTiming AnimationEffect::getBasicTiming() const
{
- // 3.5.5. Animation effect phases and states
- // https://drafts.csswg.org/web-animations-1/#animation-effect-phases-and-states
+ // 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.
- 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);
+ auto activeDuration = [this]() -> Seconds {
+ // 3.8.2. Calculating the active duration
+ // https://drafts.csswg.org/web-animations-1/#calculating-the-active-duration
- // (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;
+ // 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 localTimeValue = effectLocalTime.value();
+ auto endTime = [this, activeDuration]() -> Seconds {
+ // 3.5.3 The active interval
+ // https://drafts.csswg.org/web-animations-1/#end-time
- // 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;
+ // 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;
+ }();
- // 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;
+ auto localTime = [this]() -> Optional<Seconds> {
+ // 4.5.4. Local time
+ // https://drafts.csswg.org/web-animations-1/#local-time-section
- // 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;
-}
+ // 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 WTF::nullopt;
+ }();
-Optional<Seconds> AnimationEffect::activeTime() const
-{
- // 3.8.3.1. Calculating the active time
- // https://drafts.csswg.org/web-animations-1/#calculating-the-active-time
+ 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
- // 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,
+ 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);
- auto effectPhase = phase();
+ // (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;
- // 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.
- return WTF::nullopt;
- }
+ // 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;
- // 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;
+ // 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;
- // 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.
+ // 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]() -> 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 WTF::nullopt;
+ }
+
+ // 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 WTF::nullopt;
+ }
+
+ // Otherwise (the local time is unresolved), return an unresolved time value.
return WTF::nullopt;
- }
+ }();
- // Otherwise (the local time is unresolved), return an unresolved time value.
- return WTF::nullopt;
+ return { localTime, activeTime, endTime, activeDuration, phase };
}
-Optional<double> AnimationEffect::overallProgress() const
+ComputedEffectTiming AnimationEffect::getComputedTiming() const
{
- // 3.8.3.2. Calculating the overall progress
- // https://drafts.csswg.org/web-animations-1/#calculating-the-overall-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 overall progress describes the number of iterations that have completed (including partial iterations) and is defined as follows:
+ auto basicEffectTiming = getBasicTiming();
+ auto activeTime = basicEffectTiming.activeTime;
+ auto activeDuration = basicEffectTiming.activeDuration;
+ auto phase = basicEffectTiming.phase;
- // 1. If the active time is unresolved, return unresolved.
- auto effectActiveTime = activeTime();
- if (!effectActiveTime)
- return WTF::nullopt;
+ auto overallProgress = [this, phase, activeTime]() -> Optional<double> {
+ // 3.8.3.2. Calculating the overall progress
+ // https://drafts.csswg.org/web-animations-1/#calculating-the-overall-progress
- // 2. Calculate an initial value for overall progress based on the first matching condition from below,
- double overallProgress;
+ // The overall progress describes the number of iterations that have completed (including partial iterations) and is defined as follows:
- 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);
- }
+ // 1. If the active time is unresolved, return unresolved.
+ if (!activeTime)
+ return WTF::nullopt;
- // 3. Return the result of calculating overall progress + iteration start.
- overallProgress += m_iterationStart;
- return std::abs(overallProgress);
-}
+ // 2. Calculate an initial value for overall progress based on the first matching condition from below,
+ double overallProgress;
-Optional<double> AnimationEffect::simpleIterationProgress() const
-{
- // 3.8.3.3. Calculating the simple iteration progress
- // https://drafts.csswg.org/web-animations-1/#calculating-the-simple-iteration-progress
+ 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);
+ }
- // 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:
+ // 3. Return the result of calculating overall progress + iteration start.
+ overallProgress += m_iterationStart;
+ return std::abs(overallProgress);
+ }();
- // 1. If the overall progress is unresolved, return unresolved.
- auto effectOverallProgress = overallProgress();
- if (!effectOverallProgress)
- return WTF::nullopt;
+ auto simpleIterationProgress = [this, overallProgress, phase, activeTime, activeDuration]() -> Optional<double> {
+ // 3.8.3.3. Calculating the simple iteration progress
+ // https://drafts.csswg.org/web-animations-1/#calculating-the-simple-iteration-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 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:
- // 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;
+ // 1. If the overall progress is unresolved, return unresolved.
+ if (!overallProgress)
+ return WTF::nullopt;
- return simpleIterationProgress;
-}
+ // 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);
-Optional<double> AnimationEffect::currentIteration() const
-{
- // 3.8.4. Calculating the current iteration
- // https://drafts.csswg.org/web-animations-1/#calculating-the-current-iteration
+ // 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;
- // The current iteration can be calculated using the following steps:
+ return simpleIterationProgress;
+ }();
- // 1. If the active time is unresolved, return unresolved.
- if (!activeTime())
- return WTF::nullopt;
+ auto currentIteration = [this, activeTime, phase, simpleIterationProgress, overallProgress]() -> Optional<double> {
+ // 3.8.4. Calculating the current iteration
+ // https://drafts.csswg.org/web-animations-1/#calculating-the-current-iteration
- // 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();
+ // The current iteration can be calculated using the following steps:
- // 3. If the simple iteration progress is 1.0, return floor(overall progress) - 1.
- if (simpleIterationProgress().value() == 1)
- return floor(overallProgress().value()) - 1;
+ // 1. If the active time is unresolved, return unresolved.
+ if (!activeTime)
+ return WTF::nullopt;
- // 4. Otherwise, return floor(overall progress).
- return floor(overallProgress().value());
-}
+ // 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();
-AnimationEffect::ComputedDirection AnimationEffect::currentDirection() const
-{
- // 3.9.1. Calculating the directed progress
- // https://drafts.csswg.org/web-animations-1/#calculating-the-directed-progress
+ // 3. If the simple iteration progress is 1.0, return floor(overall progress) - 1.
+ if (*simpleIterationProgress == 1)
+ return floor(*overallProgress) - 1;
- // If playback direction is normal, let the current direction be forwards.
- if (m_direction == PlaybackDirection::Normal)
- return AnimationEffect::ComputedDirection::Forwards;
+ // 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)
+ // If playback direction is reverse, let the current direction be reverse.
+ if (m_direction == PlaybackDirection::Reverse)
+ return AnimationEffect::ComputedDirection::Reverse;
+
+ if (!currentIteration)
+ return AnimationEffect::ComputedDirection::Forwards;
+
+ // 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;
-}
+ }();
-Optional<double> AnimationEffect::directedProgress() const
-{
- // 3.9.1. Calculating the directed progress
- // https://drafts.csswg.org/web-animations-1/#calculating-the-directed-progress
+ auto directedProgress = [simpleIterationProgress, currentDirection]() -> 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:
+ // 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 WTF::nullopt;
+ // 1. If the simple iteration progress is unresolved, return unresolved.
+ if (!simpleIterationProgress)
+ return WTF::nullopt;
- // 2. Calculate the current direction (we implement this as a separate method).
+ // 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();
+ // 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 - effectSimpleIterationProgress.value();
-}
+ // Otherwise, return 1.0 - simple iteration progress.
+ return 1 - *simpleIterationProgress;
+ }();
-Optional<double> AnimationEffect::transformedProgress() const
-{
- // 3.10.1. Calculating the transformed progress
- // https://drafts.csswg.org/web-animations-1/#calculating-the-transformed-progress
+ auto transformedProgress = [this, directedProgress, currentDirection, phase]() -> 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.
- auto effectDirectedProgress = directedProgress();
- if (!effectDirectedProgress)
- return WTF::nullopt;
+ // 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 WTF::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.
+ before = (phase == AnimationEffectPhase::Before && goingForwards) || (phase == AnimationEffectPhase::After && !goingForwards);
+ }
- 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);
+ // 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 *directedProgress;
+ }();
- return effectDirectedProgressValue;
-}
-
-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;
-}
-
-ComputedEffectTiming AnimationEffect::getComputedTiming()
-{
ComputedEffectTiming computedTiming;
computedTiming.delay = secondsToWebAnimationsAPITime(m_delay);
computedTiming.endDelay = secondsToWebAnimationsAPITime(m_endDelay);
@@ -327,12 +347,14 @@
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 +470,6 @@
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 +515,4 @@
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
Modified: trunk/Source/WebCore/animation/AnimationEffect.h (239722 => 239723)
--- trunk/Source/WebCore/animation/AnimationEffect.h 2019-01-08 09:00:28 UTC (rev 239722)
+++ trunk/Source/WebCore/animation/AnimationEffect.h 2019-01-08 11:31:55 UTC (rev 239723)
@@ -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 @@
virtual bool isKeyframeEffect() const { return false; }
- EffectTiming getTiming();
- ComputedEffectTiming getComputedTiming();
+ EffectTiming getTiming() const;
+ BasicEffectTiming getBasicTiming() const;
+ ComputedEffectTiming getComputedTiming() const;
ExceptionOr<void> updateTiming(Optional<OptionalEffectTiming>);
virtual void apply(RenderStyle&) = 0;
@@ -87,17 +90,6 @@
TimingFunction* timingFunction() const { return m_timingFunction.get(); }
void setTimingFunction(const RefPtr<TimingFunction>&);
- Optional<Seconds> localTime() const;
- Optional<Seconds> activeTime() const;
- Seconds endTime() const;
- Optional<double> simpleIterationProgress() const;
- Optional<double> iterationProgress() const;
- Optional<double> currentIteration() const;
- Seconds activeDuration() const;
-
- enum class Phase { Before, Active, After, Idle };
- Phase phase() const;
-
protected:
explicit AnimationEffect();
@@ -104,11 +96,6 @@
private:
enum class ComputedDirection { Forwards, Reverse };
- Optional<double> overallProgress() const;
- AnimationEffect::ComputedDirection currentDirection() const;
- Optional<double> directedProgress() const;
- Optional<double> transformedProgress() const;
-
Seconds m_delay { 0_s };
Seconds m_endDelay { 0_s };
FillMode m_fill { FillMode::Auto };
Copied: trunk/Source/WebCore/animation/AnimationEffectPhase.h (from rev 239721, trunk/Source/WebCore/animation/ComputedEffectTiming.h) (0 => 239723)
--- trunk/Source/WebCore/animation/AnimationEffectPhase.h (rev 0)
+++ trunk/Source/WebCore/animation/AnimationEffectPhase.h 2019-01-08 11:31:55 UTC (rev 239723)
@@ -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 : uint8_t { Before, Active, After, Idle };
+
+} // namespace WebCore
Modified: trunk/Source/WebCore/animation/AnimationTimeline.cpp (239722 => 239723)
--- trunk/Source/WebCore/animation/AnimationTimeline.cpp 2019-01-08 09:00:28 UTC (rev 239722)
+++ trunk/Source/WebCore/animation/AnimationTimeline.cpp 2019-01-08 11:31:55 UTC (rev 239723)
@@ -460,7 +460,7 @@
auto& reversingAdjustedStartStyle = previouslyRunningTransition->targetStyle();
double transformedProgress = 1;
if (auto* effect = previouslyRunningTransition->effect())
- transformedProgress = effect->iterationProgress().valueOr(transformedProgress);
+ transformedProgress = effect->getComputedTiming().progress.valueOr(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;
Modified: trunk/Source/WebCore/animation/AnimationTimeline.h (239722 => 239723)
--- trunk/Source/WebCore/animation/AnimationTimeline.h 2019-01-08 09:00:28 UTC (rev 239722)
+++ trunk/Source/WebCore/animation/AnimationTimeline.h 2019-01-08 11:31:55 UTC (rev 239723)
@@ -27,6 +27,7 @@
#pragma once
#include "CSSValue.h"
+#include "ComputedEffectTiming.h"
#include "RenderStyle.h"
#include "WebAnimation.h"
#include <wtf/Forward.h>
Copied: trunk/Source/WebCore/animation/BasicEffectTiming.h (from rev 239721, trunk/Source/WebCore/animation/ComputedEffectTiming.h) (0 => 239723)
--- trunk/Source/WebCore/animation/BasicEffectTiming.h (rev 0)
+++ trunk/Source/WebCore/animation/BasicEffectTiming.h 2019-01-08 11:31:55 UTC (rev 239723)
@@ -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/Markable.h>
+#include <wtf/Seconds.h>
+
+namespace WebCore {
+
+struct BasicEffectTiming {
+ Markable<Seconds, Seconds::MarkableTraits> localTime;
+ Markable<Seconds, Seconds::MarkableTraits> activeTime;
+ Seconds endTime;
+ Seconds activeDuration;
+ AnimationEffectPhase phase;
+};
+
+} // namespace WebCore
Modified: trunk/Source/WebCore/animation/ComputedEffectTiming.h (239722 => 239723)
--- trunk/Source/WebCore/animation/ComputedEffectTiming.h 2019-01-08 09:00:28 UTC (rev 239722)
+++ trunk/Source/WebCore/animation/ComputedEffectTiming.h 2019-01-08 11:31:55 UTC (rev 239723)
@@ -25,6 +25,7 @@
#pragma once
+#include "AnimationEffectPhase.h"
#include "EffectTiming.h"
#include <wtf/Optional.h>
@@ -31,9 +32,11 @@
namespace WebCore {
struct ComputedEffectTiming : EffectTiming {
+ AnimationEffectPhase phase { AnimationEffectPhase::Idle };
double endTime;
double activeDuration;
Optional<double> localTime;
+ Optional<double> simpleIterationProgress;
Optional<double> progress;
Optional<double> currentIteration;
};
Modified: trunk/Source/WebCore/animation/DeclarativeAnimation.cpp (239722 => 239723)
--- trunk/Source/WebCore/animation/DeclarativeAnimation.cpp 2019-01-08 09:00:28 UTC (rev 239722)
+++ trunk/Source/WebCore/animation/DeclarativeAnimation.cpp 2019-01-08 11:31:55 UTC (rev 239723)
@@ -198,8 +198,10 @@
void DeclarativeAnimation::cancel()
{
auto cancelationTime = 0_s;
- if (auto animationEffect = effect())
- cancelationTime = animationEffect->activeTime().valueOr(0_s);
+ if (auto* animationEffect = effect()) {
+ if (auto activeTime = animationEffect->getBasicTiming().activeTime)
+ cancelationTime = *activeTime;
+ }
WebAnimation::cancel();
@@ -212,7 +214,7 @@
disassociateFromOwningElement();
}
-AnimationEffect::Phase DeclarativeAnimation::phaseWithoutEffect() const
+AnimationEffectPhase DeclarativeAnimation::phaseWithoutEffect() const
{
// This shouldn't be called if we actually have an effect.
ASSERT(!effect());
@@ -219,10 +221,10 @@
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 +232,38 @@
if (!m_owningElement)
return;
- auto* animationEffect = effect();
-
auto isPending = pending();
if (isPending && m_wasPending)
return;
- auto iteration = animationEffect ? animationEffect->currentIteration().valueOr(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.valueOr(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
Modified: trunk/Source/WebCore/animation/DeclarativeAnimation.h (239722 => 239723)
--- trunk/Source/WebCore/animation/DeclarativeAnimation.h 2019-01-08 09:00:28 UTC (rev 239722)
+++ trunk/Source/WebCore/animation/DeclarativeAnimation.h 2019-01-08 11:31:55 UTC (rev 239723)
@@ -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 @@
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 @@
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;
};
Modified: trunk/Source/WebCore/animation/KeyframeEffect.cpp (239722 => 239723)
--- trunk/Source/WebCore/animation/KeyframeEffect.cpp 2019-01-08 09:00:28 UTC (rev 239722)
+++ trunk/Source/WebCore/animation/KeyframeEffect.cpp 2019-01-08 11:31:55 UTC (rev 239723)
@@ -1008,7 +1008,7 @@
updateAcceleratedAnimationState();
- auto progress = iterationProgress();
+ auto progress = getComputedTiming().progress;
if (!progress)
return;
@@ -1042,7 +1042,7 @@
if (!m_target || !animation())
return;
- auto progress = iterationProgress();
+ auto progress = getComputedTiming().progress;
if (!progress)
return;
Modified: trunk/Source/WebCore/animation/WebAnimation.cpp (239722 => 239723)
--- trunk/Source/WebCore/animation/WebAnimation.cpp 2019-01-08 09:00:28 UTC (rev 239722)
+++ trunk/Source/WebCore/animation/WebAnimation.cpp 2019-01-08 11:31:55 UTC (rev 239723)
@@ -538,7 +538,7 @@
{
// 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 @@
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 @@
// 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 @@
// 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 @@
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();