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)]
137pub enum GenericAnimationTimeline<LengthPercent> {
138 Auto,
140 Timeline(TimelineName),
145 Scroll(ScrollFunction),
148 View(#[css(field_bound)] GenericViewFunction<LengthPercent>),
151}
152
153pub use self::GenericAnimationTimeline as AnimationTimeline;
154
155impl<LengthPercent> AnimationTimeline<LengthPercent> {
156 pub fn auto() -> Self {
158 Self::Auto
159 }
160
161 pub fn is_auto(&self) -> bool {
163 matches!(self, Self::Auto)
164 }
165}
166
167#[derive(
171 Clone,
172 Copy,
173 Debug,
174 MallocSizeOf,
175 PartialEq,
176 SpecifiedValueInfo,
177 ToComputedValue,
178 ToResolvedValue,
179 ToShmem,
180)]
181#[repr(C)]
182pub struct GenericViewTimelineInset<LengthPercent> {
183 pub start: GenericLengthPercentageOrAuto<LengthPercent>,
185 pub end: GenericLengthPercentageOrAuto<LengthPercent>,
187}
188
189pub use self::GenericViewTimelineInset as ViewTimelineInset;
190
191impl<LengthPercent> ViewTimelineInset<LengthPercent> {
192 #[inline]
194 fn is_auto(&self) -> bool {
195 self.start.is_auto() && self.end.is_auto()
196 }
197}
198
199impl<LengthPercent> ToCss for ViewTimelineInset<LengthPercent>
200where
201 LengthPercent: PartialEq + ToCss,
202{
203 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
204 where
205 W: Write,
206 {
207 self.start.to_css(dest)?;
208 if self.end != self.start {
209 dest.write_char(' ')?;
210 self.end.to_css(dest)?;
211 }
212 Ok(())
213 }
214}
215
216impl<LengthPercent> ToTyped for ViewTimelineInset<LengthPercent> where
217 LengthPercent: PartialEq + ToTyped
218{
219}
220
221impl<LengthPercent> Default for ViewTimelineInset<LengthPercent> {
222 fn default() -> Self {
223 Self {
224 start: GenericLengthPercentageOrAuto::auto(),
225 end: GenericLengthPercentageOrAuto::auto(),
226 }
227 }
228}
229
230#[derive(
235 Clone,
236 Debug,
237 MallocSizeOf,
238 PartialEq,
239 SpecifiedValueInfo,
240 ToComputedValue,
241 ToResolvedValue,
242 ToShmem,
243)]
244#[repr(C)]
245pub struct GenericAnimationRangeValue<LengthPercent> {
246 pub name: TimelineRangeName,
249 pub lp: LengthPercent,
251}
252
253pub use self::GenericAnimationRangeValue as AnimationRangeValue;
254
255impl<LengthPercent> AnimationRangeValue<LengthPercent> {
256 #[inline]
258 pub fn normal(lp: LengthPercent) -> Self {
259 Self::new(TimelineRangeName::Normal, lp)
260 }
261
262 #[inline]
264 pub fn length_percentage(lp: LengthPercent) -> Self {
265 Self::new(TimelineRangeName::None, lp)
266 }
267
268 #[inline]
270 pub fn new(name: TimelineRangeName, lp: LengthPercent) -> Self {
271 Self { name, lp }
272 }
273
274 #[inline]
276 pub fn is_normal(&self) -> bool {
277 self.name.is_normal()
278 }
279}
280
281#[derive(
285 Clone,
286 Debug,
287 MallocSizeOf,
288 PartialEq,
289 SpecifiedValueInfo,
290 ToComputedValue,
291 ToResolvedValue,
292 ToShmem,
293 ToTyped,
294)]
295#[repr(transparent)]
296pub struct GenericAnimationRangeStart<LengthPercent>(pub GenericAnimationRangeValue<LengthPercent>);
297
298pub use self::GenericAnimationRangeStart as AnimationRangeStart;
299
300fn to_css_with_default<LengthPercent, W>(
301 value: &AnimationRangeValue<LengthPercent>,
302 dest: &mut CssWriter<W>,
303 default: f32,
304) -> fmt::Result
305where
306 LengthPercent: ToCss + EqualsPercentage,
307 W: Write,
308{
309 if matches!(value.name, TimelineRangeName::Normal) {
310 return dest.write_str("normal");
311 }
312 if matches!(value.name, TimelineRangeName::None) {
313 return value.lp.to_css(dest);
314 }
315 value.name.to_css(dest)?;
317 if !value.lp.equals_percentage(default) {
318 dest.write_char(' ')?;
319 value.lp.to_css(dest)?;
320 }
321 Ok(())
322}
323
324impl<LengthPercent: ToCss + EqualsPercentage> ToCss for AnimationRangeStart<LengthPercent> {
325 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
326 where
327 W: Write,
328 {
329 to_css_with_default(&self.0, dest, 0.0)
330 }
331}
332
333#[derive(
337 Clone,
338 Debug,
339 MallocSizeOf,
340 PartialEq,
341 SpecifiedValueInfo,
342 ToComputedValue,
343 ToResolvedValue,
344 ToShmem,
345 ToTyped,
346)]
347#[repr(transparent)]
348pub struct GenericAnimationRangeEnd<LengthPercent>(pub GenericAnimationRangeValue<LengthPercent>);
349
350pub use self::GenericAnimationRangeEnd as AnimationRangeEnd;
351
352impl<LengthPercent: ToCss + EqualsPercentage> ToCss for AnimationRangeEnd<LengthPercent> {
353 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
354 where
355 W: Write,
356 {
357 to_css_with_default(&self.0, dest, 1.0)
358 }
359}