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