diff --git a/layout/style/ServoBindings.toml b/layout/style/ServoBindings.toml index 4b55fae13e4e..4b1da708c238 100644 --- a/layout/style/ServoBindings.toml +++ b/layout/style/ServoBindings.toml @@ -421,6 +421,7 @@ cbindgen-types = [ { gecko = "StyleAnimationFillMode", servo = "crate::values::computed::AnimationFillMode" }, { gecko = "StyleAnimationPlayState", servo = "crate::values::computed::AnimationPlayState" }, { gecko = "StyleAnimationComposition", servo = "crate::values::computed::AnimationComposition" }, + { gecko = "StyleAnimationDuration", servo = "crate::values::computed::AnimationDuration" }, { gecko = "StyleTimelineName", servo = "crate::values::computed::TimelineName" }, { gecko = "StyleScrollAxis", servo = "crate::values::computed::ScrollAxis" }, { gecko = "StyleViewTimelineInset", servo = "crate::values::computed::ViewTimelineInset" }, diff --git a/layout/style/nsAnimationManager.cpp b/layout/style/nsAnimationManager.cpp index 8c59bc2c0036..13f4f43dae17 100644 --- a/layout/style/nsAnimationManager.cpp +++ b/layout/style/nsAnimationManager.cpp @@ -300,8 +300,9 @@ static already_AddRefed BuildAnimation( return nullptr; } + const StyleAnimationDuration& duration = aStyle.GetAnimationDuration(animIdx); TimingParams timing = TimingParamsFromCSSParams( - aStyle.GetAnimationDuration(animIdx).ToMilliseconds(), + duration.IsAuto() ? 0.0f : duration.AsTime().ToMilliseconds(), aStyle.GetAnimationDelay(animIdx).ToMilliseconds(), aStyle.GetAnimationIterationCount(animIdx), aStyle.GetAnimationDirection(animIdx), diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 17112f265560..f6977ac5a522 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1132,7 +1132,7 @@ struct StyleAnimation { return mTimingFunction; } const StyleTime& GetDelay() const { return mDelay; } - const StyleTime& GetDuration() const { return mDuration; } + const StyleAnimationDuration& GetDuration() const { return mDuration; } nsAtom* GetName() const { return mName._0.AsAtom(); } StyleAnimationDirection GetDirection() const { return mDirection; } StyleAnimationFillMode GetFillMode() const { return mFillMode; } @@ -1149,7 +1149,7 @@ struct StyleAnimation { private: StyleComputedTimingFunction mTimingFunction{ StyleComputedTimingFunction::Keyword(StyleTimingKeyword::Ease)}; - StyleTime mDuration{0.0f}; + StyleAnimationDuration mDuration = StyleAnimationDuration::Auto(); StyleTime mDelay{0.0f}; StyleAnimationName mName; StyleAnimationDirection mDirection = StyleAnimationDirection::Normal; @@ -1157,7 +1157,7 @@ struct StyleAnimation { StyleAnimationPlayState mPlayState = StyleAnimationPlayState::Running; StyleAnimationIterationCount mIterationCount{1.0f}; StyleAnimationComposition mComposition = StyleAnimationComposition::Replace; - StyleAnimationTimeline mTimeline{StyleAnimationTimeline::Auto()}; + StyleAnimationTimeline mTimeline = StyleAnimationTimeline::Auto(); }; struct StyleScrollTimeline { @@ -1665,7 +1665,8 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUIReset { const mozilla::StyleTime& GetAnimationDelay(uint32_t aIndex) const { return mAnimations[aIndex % mAnimationDelayCount].GetDelay(); } - const mozilla::StyleTime& GetAnimationDuration(uint32_t aIndex) const { + const mozilla::StyleAnimationDuration& GetAnimationDuration( + uint32_t aIndex) const { return mAnimations[aIndex % mAnimationDurationCount].GetDuration(); } mozilla::StyleAnimationDirection GetAnimationDirection( diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index b052fcadf873..df9a52d8100d 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -13958,6 +13958,8 @@ if (IsCSSPropertyPrefEnabled("layout.css.scroll-driven-animations.enabled")) { gCSSProperties["-moz-animation"].subproperties.push("animation-timeline"); gCSSProperties["-webkit-animation"].subproperties.push("animation-timeline"); + gCSSProperties["animation-duration"].initial_values.push("auto"); + gCSSProperties["animation-timeline"] = { domProp: "animationTimeline", inherited: false, diff --git a/servo/components/style/properties/gecko.mako.rs b/servo/components/style/properties/gecko.mako.rs index 414054a2eca7..c38374aca3be 100644 --- a/servo/components/style/properties/gecko.mako.rs +++ b/servo/components/style/properties/gecko.mako.rs @@ -1452,6 +1452,12 @@ mask-mode mask-repeat mask-clip mask-origin mask-composite mask-position-x mask- self.mTransitionPropertyCount > 0 } + /// Returns whether animation-timeline is initial value. We need this information to resolve + /// animation-duration. + pub fn has_initial_animation_timeline(&self) -> bool { + self.mAnimationTimelineCount == 1 && self.animation_timeline_at(0).is_auto() + } + pub fn animations_equals(&self, other: &Self) -> bool { return self.mAnimationNameCount == other.mAnimationNameCount && self.mAnimationDelayCount == other.mAnimationDelayCount diff --git a/servo/components/style/properties/longhands/ui.mako.rs b/servo/components/style/properties/longhands/ui.mako.rs index c8ac791d88c4..54480f636834 100644 --- a/servo/components/style/properties/longhands/ui.mako.rs +++ b/servo/components/style/properties/longhands/ui.mako.rs @@ -224,16 +224,15 @@ ${helpers.predefined_type( ${helpers.predefined_type( "animation-duration", - "Time", - "computed::Time::zero()", + "AnimationDuration", + "computed::AnimationDuration::auto()", engines="gecko servo", - initial_specified_value="specified::Time::zero()", - parse_method="parse_non_negative", + initial_specified_value="specified::AnimationDuration::auto()", vector=True, need_index=True, animation_type="none", extra_prefixes=animation_extra_prefixes, - spec="https://drafts.csswg.org/css-transitions/#propdef-transition-duration", + spec="https://drafts.csswg.org/css-animations-2/#animation-duration", affects="", )} diff --git a/servo/components/style/properties/properties.mako.rs b/servo/components/style/properties/properties.mako.rs index d3bf3d769963..a1bb4f13a16d 100644 --- a/servo/components/style/properties/properties.mako.rs +++ b/servo/components/style/properties/properties.mako.rs @@ -1614,6 +1614,13 @@ pub mod style_structs { }) } + /// Returns whether animation-timeline is initial value. We need this information to + /// resolve animation-duration. + #[cfg(feature = "servo")] + pub fn has_initial_animation_timeline(&self) -> bool { + self.animation_timeline_count() == 1 && self.animation_timeline_at(0).is_auto() + } + /// Returns whether there is any named progress timeline specified with /// scroll-timeline-name other than `none`. #[cfg(feature = "gecko")] diff --git a/servo/components/style/properties/shorthands/ui.mako.rs b/servo/components/style/properties/shorthands/ui.mako.rs index 97bd2aec9bda..28726bcbb543 100644 --- a/servo/components/style/properties/shorthands/ui.mako.rs +++ b/servo/components/style/properties/shorthands/ui.mako.rs @@ -351,9 +351,11 @@ macro_rules! try_parse_one { // // https://drafts.csswg.org/css-animations-2/#animation-shorthand // - // FIXME: Bug 1804574. The initial value of duration should be auto, per - // css-animations-2. - let has_duration = !self.animation_duration.0[i].is_zero(); + // Note: animation-timeline is not serialized for now because it is always the + // initial value in this loop. + let has_duration = !self.animation_duration.0[i].is_auto() + && (static_prefs::pref!("layout.css.scroll-driven-animations.enabled") + || !self.animation_duration.0[i].is_zero()); let has_timing_function = !self.animation_timing_function.0[i].is_ease(); let has_delay = !self.animation_delay.0[i].is_zero(); let has_iteration_count = !self.animation_iteration_count.0[i].is_one(); @@ -368,7 +370,7 @@ macro_rules! try_parse_one { let mut writer = SequenceWriter::new(dest, " "); - // To avoid ambiguity, we have to serialize duration if both duration is initial + // To avoid ambiguity, we have to serialize duration if duration is initial // but delay is not. (In other words, it's ambiguous if we serialize delay only.) if has_duration || has_delay { writer.item(&self.animation_duration.0[i])?; diff --git a/servo/components/style/values/computed/animation.rs b/servo/components/style/values/computed/animation.rs index 041167623b2b..118ac8bd6bfe 100644 --- a/servo/components/style/values/computed/animation.rs +++ b/servo/components/style/values/computed/animation.rs @@ -4,9 +4,10 @@ //! Computed values for properties related to animations and transitions -use crate::values::computed::{Context, LengthPercentage, ToComputedValue}; +use crate::values::computed::{Context, LengthPercentage, Time, ToComputedValue}; use crate::values::generics::animation as generics; use crate::values::specified::animation as specified; +use crate::values::CSSFloat; use std::fmt::{self, Write}; use style_traits::{CssWriter, ToCss}; @@ -15,6 +16,20 @@ pub use crate::values::specified::animation::{ ScrollAxis, TimelineName, TransitionBehavior, TransitionProperty, }; +/// A computed value for the `animation-duration` property. +pub type AnimationDuration = generics::GenericAnimationDuration