style/values/generics/
animation.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Generic values for properties related to animations and transitions.
6
7use crate::values::generics::length::GenericLengthPercentageOrAuto;
8use crate::values::specified::animation::{ScrollAxis, ScrollFunction, TimelineName};
9use crate::Zero;
10use std::fmt::{self, Write};
11use style_traits::{CssWriter, ToCss};
12
13/// The `animation-duration` property.
14///
15/// https://drafts.csswg.org/css-animations-2/#animation-duration
16#[derive(
17    Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
18)]
19#[repr(C, u8)]
20pub enum GenericAnimationDuration<T> {
21    /// The initial value. However, we serialize this as 0s if the preference is disabled.
22    Auto,
23    /// The time value, <time [0s,∞]>.
24    Time(T),
25}
26
27pub use self::GenericAnimationDuration as AnimationDuration;
28
29impl<T> AnimationDuration<T> {
30    /// Returns the `auto` value.
31    pub fn auto() -> Self {
32        Self::Auto
33    }
34
35    /// Returns true if it is `auto`.
36    pub fn is_auto(&self) -> bool {
37        matches!(*self, Self::Auto)
38    }
39}
40
41impl<T: Zero> Zero for AnimationDuration<T> {
42    fn zero() -> Self {
43        Self::Time(T::zero())
44    }
45
46    fn is_zero(&self) -> bool {
47        match *self {
48            Self::Time(ref t) => t.is_zero(),
49            _ => false,
50        }
51    }
52}
53
54impl<T: ToCss + Zero> ToCss for AnimationDuration<T> {
55    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
56    where
57        W: Write,
58    {
59        match *self {
60            Self::Auto => {
61                if static_prefs::pref!("layout.css.scroll-driven-animations.enabled") {
62                    dest.write_str("auto")
63                } else {
64                    Self::Time(T::zero()).to_css(dest)
65                }
66            },
67            Self::Time(ref t) => t.to_css(dest),
68        }
69    }
70}
71
72/// The view() notation.
73/// https://drafts.csswg.org/scroll-animations-1/#view-notation
74#[derive(
75    Clone,
76    Debug,
77    MallocSizeOf,
78    PartialEq,
79    SpecifiedValueInfo,
80    ToComputedValue,
81    ToCss,
82    ToResolvedValue,
83    ToShmem,
84)]
85#[css(function = "view")]
86#[repr(C)]
87pub struct GenericViewFunction<LengthPercent> {
88    /// The axis of scrolling that drives the progress of the timeline.
89    #[css(skip_if = "ScrollAxis::is_default")]
90    pub axis: ScrollAxis,
91    /// An adjustment of the view progress visibility range.
92    #[css(skip_if = "GenericViewTimelineInset::is_auto")]
93    #[css(field_bound)]
94    pub inset: GenericViewTimelineInset<LengthPercent>,
95}
96
97pub use self::GenericViewFunction as ViewFunction;
98
99/// A value for the <single-animation-timeline>.
100///
101/// https://drafts.csswg.org/css-animations-2/#typedef-single-animation-timeline
102#[derive(
103    Clone,
104    Debug,
105    MallocSizeOf,
106    PartialEq,
107    SpecifiedValueInfo,
108    ToComputedValue,
109    ToCss,
110    ToResolvedValue,
111    ToShmem,
112)]
113#[repr(C, u8)]
114pub enum GenericAnimationTimeline<LengthPercent> {
115    /// Use default timeline. The animation’s timeline is a DocumentTimeline.
116    Auto,
117    /// The scroll-timeline name or view-timeline-name.
118    /// This also includes `none` value by using an empty atom.
119    /// https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-name
120    /// https://drafts.csswg.org/scroll-animations-1/#view-timeline-name
121    Timeline(TimelineName),
122    /// The scroll() notation.
123    /// https://drafts.csswg.org/scroll-animations-1/#scroll-notation
124    Scroll(ScrollFunction),
125    /// The view() notation.
126    /// https://drafts.csswg.org/scroll-animations-1/#view-notation
127    View(#[css(field_bound)] GenericViewFunction<LengthPercent>),
128}
129
130pub use self::GenericAnimationTimeline as AnimationTimeline;
131
132impl<LengthPercent> AnimationTimeline<LengthPercent> {
133    /// Returns the `auto` value.
134    pub fn auto() -> Self {
135        Self::Auto
136    }
137
138    /// Returns true if it is auto (i.e. the default value).
139    pub fn is_auto(&self) -> bool {
140        matches!(self, Self::Auto)
141    }
142}
143
144/// A generic value for the `[ [ auto | <length-percentage> ]{1,2} ]`.
145///
146/// https://drafts.csswg.org/scroll-animations-1/#view-timeline-inset
147#[derive(
148    Clone,
149    Copy,
150    Debug,
151    MallocSizeOf,
152    PartialEq,
153    SpecifiedValueInfo,
154    ToComputedValue,
155    ToResolvedValue,
156    ToShmem,
157)]
158#[repr(C)]
159pub struct GenericViewTimelineInset<LengthPercent> {
160    /// The start inset in the relevant axis.
161    pub start: GenericLengthPercentageOrAuto<LengthPercent>,
162    /// The end inset.
163    pub end: GenericLengthPercentageOrAuto<LengthPercent>,
164}
165
166pub use self::GenericViewTimelineInset as ViewTimelineInset;
167
168impl<LengthPercent> ViewTimelineInset<LengthPercent> {
169    /// Returns true if it is auto.
170    #[inline]
171    fn is_auto(&self) -> bool {
172        self.start.is_auto() && self.end.is_auto()
173    }
174}
175
176impl<LengthPercent> ToCss for ViewTimelineInset<LengthPercent>
177where
178    LengthPercent: PartialEq + ToCss,
179{
180    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
181    where
182        W: Write,
183    {
184        self.start.to_css(dest)?;
185        if self.end != self.start {
186            dest.write_char(' ')?;
187            self.end.to_css(dest)?;
188        }
189        Ok(())
190    }
191}
192
193impl<LengthPercent> Default for ViewTimelineInset<LengthPercent> {
194    fn default() -> Self {
195        Self {
196            start: GenericLengthPercentageOrAuto::auto(),
197            end: GenericLengthPercentageOrAuto::auto(),
198        }
199    }
200}