diff --git a/components/style/values/computed/animation.rs b/components/style/values/computed/animation.rs new file mode 100644 index 00000000000..c30bc11b08b --- /dev/null +++ b/components/style/values/computed/animation.rs @@ -0,0 +1,66 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +//! Computed values for properties related to animations and transitions + +use crate::values::computed::{Context, LengthPercentage, ToComputedValue}; +use crate::values::generics::animation as generics; +use crate::values::specified::animation as specified; +use std::fmt::{self, Write}; +use style_traits::{CssWriter, ToCss}; + +pub use crate::values::specified::animation::{ + AnimationName, AnimationTimeline, ScrollAxis, ScrollTimelineName, TransitionProperty, +}; + +/// A computed value for the `animation-iteration-count` property. +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToResolvedValue, ToShmem)] +#[repr(C)] +pub struct AnimationIterationCount(pub f32); + +impl ToComputedValue for specified::AnimationIterationCount { + type ComputedValue = AnimationIterationCount; + + #[inline] + fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { + AnimationIterationCount(match *self { + specified::AnimationIterationCount::Number(n) => n.to_computed_value(context).0, + specified::AnimationIterationCount::Infinite => std::f32::INFINITY, + }) + } + + #[inline] + fn from_computed_value(computed: &Self::ComputedValue) -> Self { + use crate::values::specified::NonNegativeNumber; + if computed.0.is_infinite() { + specified::AnimationIterationCount::Infinite + } else { + specified::AnimationIterationCount::Number(NonNegativeNumber::new(computed.0)) + } + } +} + +impl AnimationIterationCount { + /// Returns the value `1.0`. + #[inline] + pub fn one() -> Self { + Self(1.0) + } +} + +impl ToCss for AnimationIterationCount { + fn to_css(&self, dest: &mut CssWriter) -> fmt::Result + where + W: Write, + { + if self.0.is_infinite() { + dest.write_str("infinite") + } else { + self.0.to_css(dest) + } + } +} + +/// A computed value for the `view-timeline-inset` property. +pub type ViewTimelineInset = generics::GenericViewTimelineInset; diff --git a/components/style/values/computed/box.rs b/components/style/values/computed/box.rs index 06f83aa70ad..238bbe8376a 100644 --- a/components/style/values/computed/box.rs +++ b/components/style/values/computed/box.rs @@ -13,68 +13,15 @@ use crate::values::generics::box_::{ use crate::values::specified::box_ as specified; pub use crate::values::specified::box_::{ - AnimationName, AnimationTimeline, Appearance, BreakBetween, BreakWithin, - Clear as SpecifiedClear, Contain, ContainerName, ContainerType, ContentVisibility, Display, - Float as SpecifiedFloat, Overflow, OverflowAnchor, OverflowClipBox, OverscrollBehavior, - ScrollAxis, ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStop, ScrollSnapStrictness, - ScrollSnapType, ScrollTimelineName, ScrollbarGutter, TouchAction, TransitionProperty, - WillChange, + Appearance, BreakBetween, BreakWithin, Clear as SpecifiedClear, Contain, ContainerName, + ContainerType, ContentVisibility, Display, Float as SpecifiedFloat, Overflow, OverflowAnchor, + OverflowClipBox, OverscrollBehavior, ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStop, + ScrollSnapStrictness, ScrollSnapType, ScrollbarGutter, TouchAction, WillChange, }; -use std::fmt::{self, Write}; -use style_traits::{ToCss, CssWriter}; - /// A computed value for the `vertical-align` property. pub type VerticalAlign = GenericVerticalAlign; -/// A computed value for the `animation-iteration-count` property. -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToResolvedValue, ToShmem)] -#[repr(C)] -pub struct AnimationIterationCount(pub f32); - -impl ToComputedValue for specified::AnimationIterationCount { - type ComputedValue = AnimationIterationCount; - - #[inline] - fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { - AnimationIterationCount(match *self { - specified::AnimationIterationCount::Number(n) => n.to_computed_value(context).0, - specified::AnimationIterationCount::Infinite => std::f32::INFINITY, - }) - } - - #[inline] - fn from_computed_value(computed: &Self::ComputedValue) -> Self { - use crate::values::specified::NonNegativeNumber; - if computed.0.is_infinite() { - specified::AnimationIterationCount::Infinite - } else { - specified::AnimationIterationCount::Number(NonNegativeNumber::new(computed.0)) - } - } -} - -impl AnimationIterationCount { - /// Returns the value `1.0`. - #[inline] - pub fn one() -> Self { - Self(1.0) - } -} - -impl ToCss for AnimationIterationCount { - fn to_css(&self, dest: &mut CssWriter) -> fmt::Result - where - W: Write, - { - if self.0.is_infinite() { - dest.write_str("infinite") - } else { - self.0.to_css(dest) - } - } -} - /// A computed value for the `contain-intrinsic-size` property. pub type ContainIntrinsicSize = GenericContainIntrinsicSize; diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 49048711643..ff1e0696bc9 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -47,25 +47,26 @@ pub use self::basic_shape::FillRule; pub use self::border::{BorderCornerRadius, BorderRadius, BorderSpacing}; pub use self::border::{BorderImageRepeat, BorderImageSideWidth}; pub use self::border::{BorderImageSlice, BorderImageWidth}; -pub use self::box_::{ - AnimationIterationCount, AnimationName, AnimationTimeline, Contain, ContainerName, - ContainerType, -}; pub use self::box_::{ Appearance, BreakBetween, BreakWithin, Clear, ContainIntrinsicSize, ContentVisibility, Float, }; -pub use self::box_::{Display, LineClamp, Overflow, OverflowAnchor, TransitionProperty}; +pub use self::box_::{ + Contain, ContainerName, ContainerType, Display, LineClamp, Overflow, OverflowAnchor, +}; pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize, ScrollbarGutter}; -pub use self::box_::{ScrollAxis, ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStop}; -pub use self::box_::{ScrollSnapStrictness, ScrollSnapType, ScrollTimelineName}; +pub use self::box_::{ + ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStop, ScrollSnapStrictness, ScrollSnapType, +}; pub use self::box_::{TouchAction, VerticalAlign, WillChange}; -pub use self::color::{Color, ColorOrAuto, ColorPropertyValue, ColorScheme, PrintColorAdjust, ForcedColorAdjust}; +pub use self::color::{ + Color, ColorOrAuto, ColorPropertyValue, ColorScheme, ForcedColorAdjust, PrintColorAdjust, +}; pub use self::column::ColumnCount; pub use self::counters::{Content, ContentItem, CounterIncrement, CounterReset, CounterSet}; pub use self::easing::TimingFunction; pub use self::effects::{BoxShadow, Filter, SimpleShadow}; pub use self::flex::FlexBasis; -pub use self::font::{FontFamily, FontLanguageOverride, FontStyle, FontPalette}; +pub use self::font::{FontFamily, FontLanguageOverride, FontPalette, FontStyle}; pub use self::font::{FontFeatureSettings, FontVariantLigatures, FontVariantNumeric}; pub use self::font::{FontSize, FontSizeAdjust, FontStretch, FontSynthesis}; pub use self::font::{FontVariantAlternates, FontWeight}; @@ -104,7 +105,9 @@ pub use self::transform::{Rotate, Scale, Transform, TransformOperation}; pub use self::transform::{TransformOrigin, TransformStyle, Translate}; #[cfg(feature = "gecko")] pub use self::ui::CursorImage; -pub use self::ui::{BoolInteger, Cursor, UserSelect, ViewTimelineInset}; +pub use self::ui::{BoolInteger, Cursor, UserSelect}; +pub use self::animation::{AnimationIterationCount, AnimationName, AnimationTimeline}; +pub use self::animation::{ScrollAxis, ScrollTimelineName, TransitionProperty, ViewTimelineInset}; pub use super::specified::TextTransform; pub use super::specified::ViewportVariant; pub use super::specified::{BorderStyle, TextDecorationLine}; @@ -113,6 +116,7 @@ pub use app_units::Au; #[cfg(feature = "gecko")] pub mod align; pub mod angle; +pub mod animation; pub mod background; pub mod basic_shape; pub mod border; diff --git a/components/style/values/computed/ui.rs b/components/style/values/computed/ui.rs index 477050ed657..6fa5137adf0 100644 --- a/components/style/values/computed/ui.rs +++ b/components/style/values/computed/ui.rs @@ -6,7 +6,7 @@ use crate::values::computed::color::Color; use crate::values::computed::image::Image; -use crate::values::computed::{LengthPercentage, Number}; +use crate::values::computed::Number; use crate::values::generics::ui as generics; pub use crate::values::specified::ui::CursorKind; @@ -20,6 +20,3 @@ pub type CursorImage = generics::GenericCursorImage; /// A computed value for `scrollbar-color` property. pub type ScrollbarColor = generics::GenericScrollbarColor; - -/// A computed value for the `view-timeline-inset` property. -pub type ViewTimelineInset = generics::GenericViewTimelineInset; diff --git a/components/style/values/generics/animation.rs b/components/style/values/generics/animation.rs new file mode 100644 index 00000000000..db1e08da1ac --- /dev/null +++ b/components/style/values/generics/animation.rs @@ -0,0 +1,59 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +//! Generic values for properties related to animations and transitions. + +use crate::values::generics::length::GenericLengthPercentageOrAuto; +use std::fmt::{self, Write}; +use style_traits::{CssWriter, ToCss}; + +/// A generic value for the `[ [ auto | ]{1,2} ]`. +/// +/// https://drafts.csswg.org/scroll-animations-1/#view-timeline-inset +#[derive( + Clone, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToResolvedValue, + ToShmem, +)] +#[repr(C)] +pub struct GenericViewTimelineInset { + /// The start inset in the relevant axis. + pub start: GenericLengthPercentageOrAuto, + /// The end inset. + pub end: GenericLengthPercentageOrAuto, +} + +pub use self::GenericViewTimelineInset as ViewTimelineInset; + +impl ToCss for ViewTimelineInset +where + LengthPercent: PartialEq + ToCss, +{ + fn to_css(&self, dest: &mut CssWriter) -> fmt::Result + where + W: Write, + { + self.start.to_css(dest)?; + if self.end != self.start { + dest.write_char(' ')?; + self.end.to_css(dest)?; + } + Ok(()) + } +} + +impl Default for ViewTimelineInset { + fn default() -> Self { + Self { + start: GenericLengthPercentageOrAuto::auto(), + end: GenericLengthPercentageOrAuto::auto(), + } + } +} diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index 58c982f78c6..237d3c16a32 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -13,6 +13,7 @@ use cssparser::Parser; use std::ops::Add; use style_traits::{KeywordsCollectFn, ParseError, SpecifiedValueInfo, StyleParseErrorKind}; +pub mod animation; pub mod background; pub mod basic_shape; pub mod border; diff --git a/components/style/values/generics/ui.rs b/components/style/values/generics/ui.rs index de347435be3..87c8674182c 100644 --- a/components/style/values/generics/ui.rs +++ b/components/style/values/generics/ui.rs @@ -4,7 +4,6 @@ //! Generic values for UI properties. -use crate::values::generics::length::GenericLengthPercentageOrAuto; use crate::values::specified::ui::CursorKind; use std::fmt::{self, Write}; use style_traits::{CssWriter, ToCss}; @@ -128,53 +127,3 @@ impl Default for ScrollbarColor { ScrollbarColor::Auto } } - -/// A generic value for the `[ [ auto | ]{1,2} ]`. -/// -/// https://drafts.csswg.org/scroll-animations-1/#view-timeline-inset -#[derive( - Clone, - Copy, - Debug, - MallocSizeOf, - PartialEq, - SpecifiedValueInfo, - ToComputedValue, - ToResolvedValue, - ToShmem, -)] -#[repr(C)] -pub struct GenericViewTimelineInset { - /// The start inset in the relevant axis. - pub start: GenericLengthPercentageOrAuto, - /// The end inset. - pub end: GenericLengthPercentageOrAuto, -} - -pub use self::GenericViewTimelineInset as ViewTimelineInset; - -impl ToCss for ViewTimelineInset -where - LengthPercent: ToCss + PartialEq, -{ - fn to_css(&self, dest: &mut CssWriter) -> fmt::Result - where - W: Write, - { - self.start.to_css(dest)?; - if self.end != self.start { - dest.write_char(' ')?; - self.end.to_css(dest)?; - } - Ok(()) - } -} - -impl Default for ViewTimelineInset { - fn default() -> Self { - Self { - start: GenericLengthPercentageOrAuto::auto(), - end: GenericLengthPercentageOrAuto::auto(), - } - } -} diff --git a/components/style/values/specified/animation.rs b/components/style/values/specified/animation.rs new file mode 100644 index 00000000000..de1db576151 --- /dev/null +++ b/components/style/values/specified/animation.rs @@ -0,0 +1,355 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +//! Specified types for properties related to animations and transitions. + +use crate::custom_properties::Name as CustomPropertyName; +use crate::parser::{Parse, ParserContext}; +use crate::properties::{LonghandId, PropertyDeclarationId, PropertyId, ShorthandId}; +use crate::values::generics::animation as generics; +use crate::values::specified::{LengthPercentage, NonNegativeNumber}; +use crate::values::{CustomIdent, KeyframesName, TimelineName}; +use crate::Atom; +use cssparser::Parser; +use std::fmt::{self, Write}; +use style_traits::{CssWriter, KeywordsCollectFn, ParseError, SpecifiedValueInfo, ToCss}; + +/// A given transition property, that is either `All`, a longhand or shorthand +/// property, or an unsupported or custom property. +#[derive( + Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem, +)] +pub enum TransitionProperty { + /// A shorthand. + Shorthand(ShorthandId), + /// A longhand transitionable property. + Longhand(LonghandId), + /// A custom property. + Custom(CustomPropertyName), + /// Unrecognized property which could be any non-transitionable, custom property, or + /// unknown property. + Unsupported(CustomIdent), +} + +impl ToCss for TransitionProperty { + fn to_css(&self, dest: &mut CssWriter) -> fmt::Result + where + W: Write, + { + use crate::values::serialize_atom_name; + match *self { + TransitionProperty::Shorthand(ref s) => s.to_css(dest), + TransitionProperty::Longhand(ref l) => l.to_css(dest), + TransitionProperty::Custom(ref name) => { + dest.write_str("--")?; + serialize_atom_name(name, dest) + }, + TransitionProperty::Unsupported(ref i) => i.to_css(dest), + } + } +} + +impl Parse for TransitionProperty { + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + let location = input.current_source_location(); + let ident = input.expect_ident()?; + + let id = match PropertyId::parse_ignoring_rule_type(&ident, context) { + Ok(id) => id, + Err(..) => { + return Ok(TransitionProperty::Unsupported(CustomIdent::from_ident( + location, + ident, + &["none"], + )?)); + }, + }; + + Ok(match id.as_shorthand() { + Ok(s) => TransitionProperty::Shorthand(s), + Err(longhand_or_custom) => match longhand_or_custom { + PropertyDeclarationId::Longhand(id) => TransitionProperty::Longhand(id), + PropertyDeclarationId::Custom(custom) => TransitionProperty::Custom(custom.clone()), + }, + }) + } +} + +impl SpecifiedValueInfo for TransitionProperty { + fn collect_completion_keywords(f: KeywordsCollectFn) { + // `transition-property` can actually accept all properties and + // arbitrary identifiers, but `all` is a special one we'd like + // to list. + f(&["all"]); + } +} + +impl TransitionProperty { + /// Returns `all`. + #[inline] + pub fn all() -> Self { + TransitionProperty::Shorthand(ShorthandId::All) + } + + /// Convert TransitionProperty to nsCSSPropertyID. + #[cfg(feature = "gecko")] + pub fn to_nscsspropertyid( + &self, + ) -> Result { + Ok(match *self { + TransitionProperty::Shorthand(ShorthandId::All) => { + crate::gecko_bindings::structs::nsCSSPropertyID::eCSSPropertyExtra_all_properties + }, + TransitionProperty::Shorthand(ref id) => id.to_nscsspropertyid(), + TransitionProperty::Longhand(ref id) => id.to_nscsspropertyid(), + TransitionProperty::Custom(..) | TransitionProperty::Unsupported(..) => return Err(()), + }) + } +} + +/// https://drafts.csswg.org/css-animations/#animation-iteration-count +#[derive(Clone, Debug, MallocSizeOf, PartialEq, Parse, SpecifiedValueInfo, ToCss, ToShmem)] +pub enum AnimationIterationCount { + /// A `` value. + Number(NonNegativeNumber), + /// The `infinite` keyword. + Infinite, +} + +impl AnimationIterationCount { + /// Returns the value `1.0`. + #[inline] + pub fn one() -> Self { + Self::Number(NonNegativeNumber::new(1.0)) + } +} + +/// A value for the `animation-name` property. +#[derive( + Clone, + Debug, + Eq, + Hash, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, +)] +#[value_info(other_values = "none")] +#[repr(C)] +pub struct AnimationName(pub KeyframesName); + +impl AnimationName { + /// Get the name of the animation as an `Atom`. + pub fn as_atom(&self) -> Option<&Atom> { + if self.is_none() { + return None; + } + Some(self.0.as_atom()) + } + + /// Returns the `none` value. + pub fn none() -> Self { + AnimationName(KeyframesName::none()) + } + + /// Returns whether this is the none value. + pub fn is_none(&self) -> bool { + self.0.is_none() + } +} + +impl Parse for AnimationName { + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + if let Ok(name) = input.try_parse(|input| KeyframesName::parse(context, input)) { + return Ok(AnimationName(name)); + } + + input.expect_ident_matching("none")?; + Ok(AnimationName(KeyframesName::none())) + } +} + +/// A value for the used in scroll(). +/// +/// https://drafts.csswg.org/scroll-animations-1/rewrite#typedef-scroller +#[derive( + Clone, + Debug, + Eq, + Hash, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, +)] +#[repr(u8)] +pub enum Scroller { + /// The nearest ancestor scroll container. (Default.) + Nearest, + /// The document viewport as the scroll container. + Root, + // FIXME: Bug 1764450: Once we support container-name CSS property (Bug 1744224), we may add + // here, based on the result of the spec issue: + // https://github.com/w3c/csswg-drafts/issues/7046 +} + +impl Default for Scroller { + fn default() -> Self { + Self::Nearest + } +} + +/// A value for the used in scroll(), or a value for {scroll|view}-timeline-axis. +/// +/// https://drafts.csswg.org/scroll-animations-1/#typedef-axis +/// https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-axis +/// https://drafts.csswg.org/scroll-animations-1/#view-timeline-axis +#[derive( + Clone, + Debug, + Eq, + Hash, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, +)] +#[repr(u8)] +pub enum ScrollAxis { + /// The block axis of the scroll container. (Default.) + Block = 0, + /// The inline axis of the scroll container. + Inline = 1, + /// The vertical block axis of the scroll container. + Vertical = 2, + /// The horizontal axis of the scroll container. + Horizontal = 3, +} + +impl Default for ScrollAxis { + fn default() -> Self { + Self::Block + } +} + +#[inline] +fn is_default(value: &T) -> bool { + *value == Default::default() +} + +/// A value for the . +/// +/// https://drafts.csswg.org/css-animations-2/#typedef-single-animation-timeline +#[derive( + Clone, + Debug, + Eq, + Hash, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, +)] +#[repr(C, u8)] +pub enum AnimationTimeline { + /// Use default timeline. The animation’s timeline is a DocumentTimeline. + Auto, + /// The scroll-timeline name or view-timeline-name. + /// https://drafts.csswg.org/scroll-animations-1/#scroll-timelines-named + /// https://drafts.csswg.org/scroll-animations-1/#view-timeline-name + Timeline(TimelineName), + /// The scroll() notation. + /// https://drafts.csswg.org/scroll-animations-1/#scroll-notation + #[css(function)] + Scroll( + #[css(skip_if = "is_default")] ScrollAxis, + #[css(skip_if = "is_default")] Scroller, + ), +} + +impl AnimationTimeline { + /// Returns the `auto` value. + pub fn auto() -> Self { + Self::Auto + } + + /// Returns true if it is auto (i.e. the default value). + pub fn is_auto(&self) -> bool { + matches!(self, Self::Auto) + } +} + +impl Parse for AnimationTimeline { + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + if input.try_parse(|i| i.expect_ident_matching("auto")).is_ok() { + return Ok(Self::Auto); + } + + if input.try_parse(|i| i.expect_ident_matching("none")).is_ok() { + return Ok(AnimationTimeline::Timeline(TimelineName::none())); + } + + // https://drafts.csswg.org/scroll-animations-1/#scroll-notation + if input + .try_parse(|i| i.expect_function_matching("scroll")) + .is_ok() + { + return input.parse_nested_block(|i| { + Ok(Self::Scroll( + i.try_parse(ScrollAxis::parse).unwrap_or(ScrollAxis::Block), + i.try_parse(Scroller::parse).unwrap_or(Scroller::Nearest), + )) + }); + } + + TimelineName::parse(context, input).map(AnimationTimeline::Timeline) + } +} + +/// A value for the scroll-timeline-name or view-timeline-name. +pub type ScrollTimelineName = AnimationName; + +/// A specified value for the `view-timeline-inset` property. +pub type ViewTimelineInset = generics::GenericViewTimelineInset; + +impl Parse for ViewTimelineInset { + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + use crate::values::specified::LengthPercentageOrAuto; + + let start = LengthPercentageOrAuto::parse(context, input)?; + let end = match input.try_parse(|input| LengthPercentageOrAuto::parse(context, input)) { + Ok(end) => end, + Err(_) => start.clone(), + }; + + Ok(Self { start, end }) + } +} diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs index ea3e8d5b015..cf62f16162a 100644 --- a/components/style/values/specified/box.rs +++ b/components/style/values/specified/box.rs @@ -4,18 +4,15 @@ //! Specified types for box properties. -use crate::custom_properties::Name as CustomPropertyName; use crate::parser::{Parse, ParserContext}; -use crate::properties::{LonghandId, PropertyDeclarationId}; -use crate::properties::{PropertyId, ShorthandId}; +use crate::properties::{LonghandId, PropertyDeclarationId, PropertyId}; use crate::values::generics::box_::{ GenericLineClamp, GenericPerspective, GenericContainIntrinsicSize, GenericVerticalAlign, VerticalAlignKeyword, }; use crate::values::specified::length::{LengthPercentage, NonNegativeLength}; -use crate::values::specified::{AllowQuirks, Integer, NonNegativeNumber}; -use crate::values::{CustomIdent, KeyframesName, TimelineName}; -use crate::Atom; +use crate::values::specified::{AllowQuirks, Integer}; +use crate::values::CustomIdent; use cssparser::Parser; use num_traits::FromPrimitive; use std::fmt::{self, Debug, Formatter, Write}; @@ -606,229 +603,6 @@ impl Parse for VerticalAlign { } } -/// https://drafts.csswg.org/css-animations/#animation-iteration-count -#[derive(Clone, Debug, MallocSizeOf, PartialEq, Parse, SpecifiedValueInfo, ToCss, ToShmem)] -pub enum AnimationIterationCount { - /// A `` value. - Number(NonNegativeNumber), - /// The `infinite` keyword. - Infinite, -} - -impl AnimationIterationCount { - /// Returns the value `1.0`. - #[inline] - pub fn one() -> Self { - Self::Number(NonNegativeNumber::new(1.0)) - } -} - -/// A value for the `animation-name` property. -#[derive( - Clone, - Debug, - Eq, - Hash, - MallocSizeOf, - PartialEq, - SpecifiedValueInfo, - ToComputedValue, - ToCss, - ToResolvedValue, - ToShmem, -)] -#[value_info(other_values = "none")] -#[repr(C)] -pub struct AnimationName(pub KeyframesName); - -impl AnimationName { - /// Get the name of the animation as an `Atom`. - pub fn as_atom(&self) -> Option<&Atom> { - if self.is_none() { - return None; - } - Some(self.0.as_atom()) - } - - /// Returns the `none` value. - pub fn none() -> Self { - AnimationName(KeyframesName::none()) - } - - /// Returns whether this is the none value. - pub fn is_none(&self) -> bool { - self.0.is_none() - } -} - -impl Parse for AnimationName { - fn parse<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result> { - if let Ok(name) = input.try_parse(|input| KeyframesName::parse(context, input)) { - return Ok(AnimationName(name)); - } - - input.expect_ident_matching("none")?; - Ok(AnimationName(KeyframesName::none())) - } -} - -/// A value for the used in scroll(). -/// -/// https://drafts.csswg.org/scroll-animations-1/rewrite#typedef-scroller -#[derive( - Clone, - Debug, - Eq, - Hash, - MallocSizeOf, - Parse, - PartialEq, - SpecifiedValueInfo, - ToComputedValue, - ToCss, - ToResolvedValue, - ToShmem, -)] -#[repr(u8)] -pub enum Scroller { - /// The nearest ancestor scroll container. (Default.) - Nearest, - /// The document viewport as the scroll container. - Root, - // FIXME: Bug 1764450: Once we support container-name CSS property (Bug 1744224), we may add - // here, based on the result of the spec issue: - // https://github.com/w3c/csswg-drafts/issues/7046 -} - -impl Default for Scroller { - fn default() -> Self { - Self::Nearest - } -} - -/// A value for the used in scroll(), or a value for {scroll|view}-timeline-axis. -/// -/// https://drafts.csswg.org/scroll-animations-1/#typedef-axis -/// https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-axis -/// https://drafts.csswg.org/scroll-animations-1/#view-timeline-axis -#[derive( - Clone, - Debug, - Eq, - Hash, - MallocSizeOf, - Parse, - PartialEq, - SpecifiedValueInfo, - ToComputedValue, - ToCss, - ToResolvedValue, - ToShmem, -)] -#[repr(u8)] -pub enum ScrollAxis { - /// The block axis of the scroll container. (Default.) - Block = 0, - /// The inline axis of the scroll container. - Inline = 1, - /// The vertical block axis of the scroll container. - Vertical = 2, - /// The horizontal axis of the scroll container. - Horizontal = 3, -} - -impl Default for ScrollAxis { - fn default() -> Self { - Self::Block - } -} - -#[inline] -fn is_default(value: &T) -> bool { - *value == Default::default() -} - -/// A value for the . -/// -/// https://drafts.csswg.org/css-animations-2/#typedef-single-animation-timeline -#[derive( - Clone, - Debug, - Eq, - Hash, - MallocSizeOf, - PartialEq, - SpecifiedValueInfo, - ToComputedValue, - ToCss, - ToResolvedValue, - ToShmem, -)] -#[repr(C, u8)] -pub enum AnimationTimeline { - /// Use default timeline. The animation’s timeline is a DocumentTimeline. - Auto, - /// The scroll-timeline name or view-timeline-name. - /// https://drafts.csswg.org/scroll-animations-1/#scroll-timelines-named - /// https://drafts.csswg.org/scroll-animations-1/#view-timeline-name - Timeline(TimelineName), - /// The scroll() notation. - /// https://drafts.csswg.org/scroll-animations-1/#scroll-notation - #[css(function)] - Scroll( - #[css(skip_if = "is_default")] ScrollAxis, - #[css(skip_if = "is_default")] Scroller, - ), -} - -impl AnimationTimeline { - /// Returns the `auto` value. - pub fn auto() -> Self { - Self::Auto - } - - /// Returns true if it is auto (i.e. the default value). - pub fn is_auto(&self) -> bool { - matches!(self, Self::Auto) - } -} - -impl Parse for AnimationTimeline { - fn parse<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result> { - if input.try_parse(|i| i.expect_ident_matching("auto")).is_ok() { - return Ok(Self::Auto); - } - - if input.try_parse(|i| i.expect_ident_matching("none")).is_ok() { - return Ok(AnimationTimeline::Timeline(TimelineName::none())); - } - - // https://drafts.csswg.org/scroll-animations-1/#scroll-notation - if input - .try_parse(|i| i.expect_function_matching("scroll")) - .is_ok() - { - return input.parse_nested_block(|i| { - Ok(Self::Scroll( - i.try_parse(ScrollAxis::parse).unwrap_or(ScrollAxis::Block), - i.try_parse(Scroller::parse).unwrap_or(Scroller::Nearest), - )) - }); - } - - TimelineName::parse(context, input).map(AnimationTimeline::Timeline) - } -} - -/// A value for the scroll-timeline-name or view-timeline-name. -pub type ScrollTimelineName = AnimationName; - /// https://drafts.csswg.org/css-scroll-snap-1/#snap-axis #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] @@ -1501,102 +1275,6 @@ impl Parse for ContainerName { /// A specified value for the `perspective` property. pub type Perspective = GenericPerspective; -/// A given transition property, that is either `All`, a longhand or shorthand -/// property, or an unsupported or custom property. -#[derive( - Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem, -)] -pub enum TransitionProperty { - /// A shorthand. - Shorthand(ShorthandId), - /// A longhand transitionable property. - Longhand(LonghandId), - /// A custom property. - Custom(CustomPropertyName), - /// Unrecognized property which could be any non-transitionable, custom property, or - /// unknown property. - Unsupported(CustomIdent), -} - -impl ToCss for TransitionProperty { - fn to_css(&self, dest: &mut CssWriter) -> fmt::Result - where - W: Write, - { - use crate::values::serialize_atom_name; - match *self { - TransitionProperty::Shorthand(ref s) => s.to_css(dest), - TransitionProperty::Longhand(ref l) => l.to_css(dest), - TransitionProperty::Custom(ref name) => { - dest.write_str("--")?; - serialize_atom_name(name, dest) - }, - TransitionProperty::Unsupported(ref i) => i.to_css(dest), - } - } -} - -impl Parse for TransitionProperty { - fn parse<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result> { - let location = input.current_source_location(); - let ident = input.expect_ident()?; - - let id = match PropertyId::parse_ignoring_rule_type(&ident, context) { - Ok(id) => id, - Err(..) => { - return Ok(TransitionProperty::Unsupported(CustomIdent::from_ident( - location, - ident, - &["none"], - )?)); - }, - }; - - Ok(match id.as_shorthand() { - Ok(s) => TransitionProperty::Shorthand(s), - Err(longhand_or_custom) => match longhand_or_custom { - PropertyDeclarationId::Longhand(id) => TransitionProperty::Longhand(id), - PropertyDeclarationId::Custom(custom) => TransitionProperty::Custom(custom.clone()), - }, - }) - } -} - -impl SpecifiedValueInfo for TransitionProperty { - fn collect_completion_keywords(f: KeywordsCollectFn) { - // `transition-property` can actually accept all properties and - // arbitrary identifiers, but `all` is a special one we'd like - // to list. - f(&["all"]); - } -} - -impl TransitionProperty { - /// Returns `all`. - #[inline] - pub fn all() -> Self { - TransitionProperty::Shorthand(ShorthandId::All) - } - - /// Convert TransitionProperty to nsCSSPropertyID. - #[cfg(feature = "gecko")] - pub fn to_nscsspropertyid( - &self, - ) -> Result { - Ok(match *self { - TransitionProperty::Shorthand(ShorthandId::All) => { - crate::gecko_bindings::structs::nsCSSPropertyID::eCSSPropertyExtra_all_properties - }, - TransitionProperty::Shorthand(ref id) => id.to_nscsspropertyid(), - TransitionProperty::Longhand(ref id) => id.to_nscsspropertyid(), - TransitionProperty::Custom(..) | TransitionProperty::Unsupported(..) => return Err(()), - }) - } -} - #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[derive( diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 1acf622980c..b0c155a81ab 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -36,22 +36,24 @@ pub use self::basic_shape::FillRule; pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth}; pub use self::border::{BorderImageRepeat, BorderImageSideWidth}; pub use self::border::{BorderRadius, BorderSideWidth, BorderSpacing, BorderStyle}; -pub use self::box_::{AnimationIterationCount, AnimationName, AnimationTimeline, Contain, Display}; pub use self::box_::{Appearance, BreakBetween, BreakWithin, ContainerName, ContainerType}; pub use self::box_::{ Clear, ContainIntrinsicSize, ContentVisibility, Float, LineClamp, Overflow, OverflowAnchor, }; +pub use self::box_::{Contain, Display}; pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize, ScrollbarGutter}; -pub use self::box_::{ScrollAxis, ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStop}; -pub use self::box_::{ScrollSnapStrictness, ScrollSnapType, ScrollTimelineName}; -pub use self::box_::{TouchAction, TransitionProperty, VerticalAlign, WillChange}; -pub use self::color::{Color, ColorOrAuto, ColorPropertyValue, ColorScheme, PrintColorAdjust, ForcedColorAdjust}; +pub use self::box_::{ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStop}; +pub use self::box_::{ScrollSnapStrictness, ScrollSnapType}; +pub use self::box_::{TouchAction, VerticalAlign, WillChange}; +pub use self::color::{ + Color, ColorOrAuto, ColorPropertyValue, ColorScheme, ForcedColorAdjust, PrintColorAdjust, +}; pub use self::column::ColumnCount; pub use self::counters::{Content, ContentItem, CounterIncrement, CounterReset, CounterSet}; pub use self::easing::TimingFunction; pub use self::effects::{BoxShadow, Filter, SimpleShadow}; pub use self::flex::FlexBasis; -pub use self::font::{FontFamily, FontLanguageOverride, FontStyle, FontPalette}; +pub use self::font::{FontFamily, FontLanguageOverride, FontPalette, FontStyle}; pub use self::font::{FontFeatureSettings, FontVariantLigatures, FontVariantNumeric}; pub use self::font::{FontSize, FontSizeAdjust, FontSizeKeyword, FontStretch, FontSynthesis}; pub use self::font::{FontVariantAlternates, FontWeight}; @@ -75,10 +77,8 @@ pub use self::outline::OutlineStyle; pub use self::page::{PageName, PageOrientation, PageSize, PageSizeOrientation, PaperSize}; pub use self::percentage::{NonNegativePercentage, Percentage}; pub use self::position::AspectRatio; -pub use self::position::{ - GridAutoFlow, GridTemplateAreas, Position, PositionOrAuto, -}; -pub use self::position::{MasonryAutoFlow, MasonryPlacement, MasonryItemOrder}; +pub use self::position::{GridAutoFlow, GridTemplateAreas, Position, PositionOrAuto}; +pub use self::position::{MasonryAutoFlow, MasonryItemOrder, MasonryPlacement}; pub use self::position::{PositionComponent, ZIndex}; pub use self::ratio::Ratio; pub use self::rect::NonNegativeLengthOrNumberRect; @@ -100,12 +100,15 @@ pub use self::transform::{Rotate, Scale, Transform}; pub use self::transform::{TransformOrigin, TransformStyle, Translate}; #[cfg(feature = "gecko")] pub use self::ui::CursorImage; -pub use self::ui::{BoolInteger, Cursor, UserSelect, ViewTimelineInset}; +pub use self::ui::{BoolInteger, Cursor, UserSelect}; +pub use self::animation::{AnimationIterationCount, AnimationName, AnimationTimeline}; +pub use self::animation::{ScrollAxis, ScrollTimelineName, TransitionProperty, ViewTimelineInset}; pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent; #[cfg(feature = "gecko")] pub mod align; pub mod angle; +pub mod animation; pub mod background; pub mod basic_shape; pub mod border; diff --git a/components/style/values/specified/ui.rs b/components/style/values/specified/ui.rs index c6af7353286..0c656faab20 100644 --- a/components/style/values/specified/ui.rs +++ b/components/style/values/specified/ui.rs @@ -8,7 +8,7 @@ use crate::parser::{Parse, ParserContext}; use crate::values::generics::ui as generics; use crate::values::specified::color::Color; use crate::values::specified::image::Image; -use crate::values::specified::{LengthPercentage, Number}; +use crate::values::specified::Number; use cssparser::Parser; use std::fmt::{self, Write}; use style_traits::{ @@ -230,23 +230,3 @@ pub enum CursorKind { ZoomOut, Auto, } - -/// A specified value for the `view-timeline-inset` property. -pub type ViewTimelineInset = generics::GenericViewTimelineInset; - -impl Parse for ViewTimelineInset { - fn parse<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result> { - use crate::values::specified::LengthPercentageOrAuto; - - let start = LengthPercentageOrAuto::parse(context, input)?; - let end = match input.try_parse(|input| LengthPercentageOrAuto::parse(context, input)) { - Ok(end) => end, - Err(_) => start.clone(), - }; - - Ok(Self { start, end }) - } -}