1use crate::derives::*;
8use crate::values::generics::length::GenericLengthPercentageOrAuto;
9use crate::values::specified::animation::{
10 ScrollAxis, ScrollFunction, TimelineName, TimelineRangeName,
11};
12use crate::values::specified::length::EqualsPercentage;
13use crate::Zero;
14use std::fmt::{self, Write};
15use style_traits::{CssString, CssWriter, KeywordValue, ToCss, ToTyped, TypedValue};
16use thin_vec::ThinVec;
17
18#[derive(
22 Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
23)]
24#[repr(C, u8)]
25pub enum GenericAnimationDuration<T> {
26 Auto,
28 Time(T),
30}
31
32pub use self::GenericAnimationDuration as AnimationDuration;
33
34impl<T> AnimationDuration<T> {
35 pub fn auto() -> Self {
37 Self::Auto
38 }
39
40 pub fn is_auto(&self) -> bool {
42 matches!(*self, Self::Auto)
43 }
44}
45
46impl<T: Zero> Zero for AnimationDuration<T> {
47 fn zero() -> Self {
48 Self::Time(T::zero())
49 }
50
51 fn is_zero(&self) -> bool {
52 match *self {
53 Self::Time(ref t) => t.is_zero(),
54 _ => false,
55 }
56 }
57}
58
59impl<T: ToCss + Zero> ToCss for AnimationDuration<T> {
60 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
61 where
62 W: Write,
63 {
64 match *self {
65 Self::Auto => {
66 if static_prefs::pref!("layout.css.scroll-driven-animations.enabled") {
67 dest.write_str("auto")
68 } else {
69 Self::Time(T::zero()).to_css(dest)
70 }
71 },
72 Self::Time(ref t) => t.to_css(dest),
73 }
74 }
75}
76
77impl<T: ToTyped + Zero> ToTyped for AnimationDuration<T> {
79 fn to_typed(&self, dest: &mut ThinVec<TypedValue>) -> Result<(), ()> {
80 match *self {
81 Self::Auto => {
82 if static_prefs::pref!("layout.css.scroll-driven-animations.enabled") {
83 dest.push(TypedValue::Keyword(KeywordValue(CssString::from("auto"))));
84 Ok(())
85 } else {
86 Self::Time(T::zero()).to_typed(dest)
87 }
88 },
89 Self::Time(ref t) => t.to_typed(dest),
90 }
91 }
92}
93
94#[derive(
97 Clone,
98 Debug,
99 MallocSizeOf,
100 PartialEq,
101 SpecifiedValueInfo,
102 ToComputedValue,
103 ToCss,
104 ToResolvedValue,
105 ToShmem,
106)]
107#[css(function = "view")]
108#[repr(C)]
109pub struct GenericViewFunction<LengthPercent> {
110 #[css(skip_if = "ScrollAxis::is_default")]
112 pub axis: ScrollAxis,
113 #[css(skip_if = "GenericViewTimelineInset::is_auto")]
115 #[css(field_bound)]
116 pub inset: GenericViewTimelineInset<LengthPercent>,
117}
118
119pub use self::GenericViewFunction as ViewFunction;
120
121#[derive(
125 Clone,
126 Debug,
127 MallocSizeOf,
128 PartialEq,
129 SpecifiedValueInfo,
130 ToComputedValue,
131 ToCss,
132 ToResolvedValue,
133 ToShmem,
134 ToTyped,
135)]
136#[repr(C, u8)]
137#[typed(todo_derive_fields)]
138pub enum GenericAnimationTimeline<LengthPercent> {
139 Auto,
141 Timeline(TimelineName),
146 Scroll(ScrollFunction),
149 View(#[css(field_bound)] GenericViewFunction<LengthPercent>),
152}
153
154pub use self::GenericAnimationTimeline as AnimationTimeline;
155
156impl<LengthPercent> AnimationTimeline<LengthPercent> {
157 pub fn auto() -> Self {
159 Self::Auto
160 }
161
162 pub fn is_auto(&self) -> bool {
164 matches!(self, Self::Auto)
165 }
166}
167
168#[derive(
172 Clone,
173 Copy,
174 Debug,
175 MallocSizeOf,
176 PartialEq,
177 SpecifiedValueInfo,
178 ToComputedValue,
179 ToResolvedValue,
180 ToShmem,
181)]
182#[repr(C)]
183pub struct GenericViewTimelineInset<LengthPercent> {
184 pub start: GenericLengthPercentageOrAuto<LengthPercent>,
186 pub end: GenericLengthPercentageOrAuto<LengthPercent>,
188}
189
190pub use self::GenericViewTimelineInset as ViewTimelineInset;
191
192impl<LengthPercent> ViewTimelineInset<LengthPercent> {
193 #[inline]
195 fn is_auto(&self) -> bool {
196 self.start.is_auto() && self.end.is_auto()
197 }
198}
199
200impl<LengthPercent> ToCss for ViewTimelineInset<LengthPercent>
201where
202 LengthPercent: PartialEq + ToCss,
203{
204 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
205 where
206 W: Write,
207 {
208 self.start.to_css(dest)?;
209 if self.end != self.start {
210 dest.write_char(' ')?;
211 self.end.to_css(dest)?;
212 }
213 Ok(())
214 }
215}
216
217impl<LengthPercent> ToTyped for ViewTimelineInset<LengthPercent> where
218 LengthPercent: PartialEq + ToTyped
219{
220}
221
222impl<LengthPercent> Default for ViewTimelineInset<LengthPercent> {
223 fn default() -> Self {
224 Self {
225 start: GenericLengthPercentageOrAuto::auto(),
226 end: GenericLengthPercentageOrAuto::auto(),
227 }
228 }
229}
230
231#[derive(
236 Clone,
237 Debug,
238 MallocSizeOf,
239 PartialEq,
240 SpecifiedValueInfo,
241 ToComputedValue,
242 ToResolvedValue,
243 ToShmem,
244)]
245#[repr(C)]
246pub struct GenericAnimationRangeValue<LengthPercent> {
247 pub name: TimelineRangeName,
250 pub lp: LengthPercent,
252}
253
254pub use self::GenericAnimationRangeValue as AnimationRangeValue;
255
256impl<LengthPercent> AnimationRangeValue<LengthPercent> {
257 #[inline]
259 pub fn normal(lp: LengthPercent) -> Self {
260 Self::new(TimelineRangeName::Normal, lp)
261 }
262
263 #[inline]
265 pub fn length_percentage(lp: LengthPercent) -> Self {
266 Self::new(TimelineRangeName::None, lp)
267 }
268
269 #[inline]
271 pub fn new(name: TimelineRangeName, lp: LengthPercent) -> Self {
272 Self { name, lp }
273 }
274
275 #[inline]
277 pub fn is_normal(&self) -> bool {
278 self.name.is_normal()
279 }
280}
281
282#[derive(
286 Clone,
287 Debug,
288 MallocSizeOf,
289 PartialEq,
290 SpecifiedValueInfo,
291 ToComputedValue,
292 ToResolvedValue,
293 ToShmem,
294 ToTyped,
295)]
296#[repr(transparent)]
297#[typed(todo_derive_fields)]
298pub struct GenericAnimationRangeStart<LengthPercent>(pub GenericAnimationRangeValue<LengthPercent>);
299
300pub use self::GenericAnimationRangeStart as AnimationRangeStart;
301
302fn to_css_with_default<LengthPercent, W>(
303 value: &AnimationRangeValue<LengthPercent>,
304 dest: &mut CssWriter<W>,
305 default: f32,
306) -> fmt::Result
307where
308 LengthPercent: ToCss + EqualsPercentage,
309 W: Write,
310{
311 if matches!(value.name, TimelineRangeName::Normal) {
312 return dest.write_str("normal");
313 }
314 if matches!(value.name, TimelineRangeName::None) {
315 return value.lp.to_css(dest);
316 }
317 value.name.to_css(dest)?;
319 if !value.lp.equals_percentage(default) {
320 dest.write_char(' ')?;
321 value.lp.to_css(dest)?;
322 }
323 Ok(())
324}
325
326impl<LengthPercent: ToCss + EqualsPercentage> ToCss for AnimationRangeStart<LengthPercent> {
327 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
328 where
329 W: Write,
330 {
331 to_css_with_default(&self.0, dest, 0.0)
332 }
333}
334
335#[derive(
339 Clone,
340 Debug,
341 MallocSizeOf,
342 PartialEq,
343 SpecifiedValueInfo,
344 ToComputedValue,
345 ToResolvedValue,
346 ToShmem,
347 ToTyped,
348)]
349#[repr(transparent)]
350#[typed(todo_derive_fields)]
351pub struct GenericAnimationRangeEnd<LengthPercent>(pub GenericAnimationRangeValue<LengthPercent>);
352
353pub use self::GenericAnimationRangeEnd as AnimationRangeEnd;
354
355impl<LengthPercent: ToCss + EqualsPercentage> ToCss for AnimationRangeEnd<LengthPercent> {
356 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
357 where
358 W: Write,
359 {
360 to_css_with_default(&self.0, dest, 1.0)
361 }
362}