1use crate::derives::*;
8use crate::values::animated::ToAnimatedZero;
9use crate::values::generics::Optional;
10use crate::Zero;
11use std::fmt::{self, Write};
12use style_traits::values::SequenceWriter;
13use style_traits::{CssWriter, ToCss};
14
15#[derive(
16 Animate,
17 Clone,
18 ComputeSquaredDistance,
19 Copy,
20 Debug,
21 FromPrimitive,
22 MallocSizeOf,
23 Parse,
24 PartialEq,
25 SpecifiedValueInfo,
26 ToAnimatedValue,
27 ToComputedValue,
28 ToCss,
29 ToResolvedValue,
30 ToShmem,
31 ToTyped,
32)]
33#[repr(u8)]
34#[allow(missing_docs)]
35pub enum BaselineShiftKeyword {
36 Sub,
40 Super,
44 Top,
46 Center,
48 Bottom,
50}
51
52#[derive(
55 Animate,
56 Clone,
57 ComputeSquaredDistance,
58 Copy,
59 Debug,
60 MallocSizeOf,
61 PartialEq,
62 SpecifiedValueInfo,
63 ToAnimatedValue,
64 ToComputedValue,
65 ToCss,
66 ToResolvedValue,
67 ToShmem,
68 ToTyped,
69)]
70#[repr(C, u8)]
71pub enum GenericBaselineShift<LengthPercentage> {
72 Keyword(BaselineShiftKeyword),
74 Length(LengthPercentage),
76}
77
78pub use self::GenericBaselineShift as BaselineShift;
79
80impl<L: Zero> BaselineShift<L> {
81 #[inline]
83 pub fn zero() -> Self {
84 BaselineShift::Length(Zero::zero())
85 }
86}
87
88impl<L> ToAnimatedZero for BaselineShift<L> {
89 fn to_animated_zero(&self) -> Result<Self, ()> {
90 Err(())
91 }
92}
93
94#[derive(
96 Animate,
97 Clone,
98 ComputeSquaredDistance,
99 Debug,
100 MallocSizeOf,
101 PartialEq,
102 SpecifiedValueInfo,
103 ToComputedValue,
104 ToAnimatedValue,
105 ToAnimatedZero,
106 ToResolvedValue,
107 ToShmem,
108 ToTyped,
109)]
110#[value_info(other_values = "auto")]
111#[repr(C, u8)]
112pub enum GenericContainIntrinsicSize<L> {
113 None,
115 AutoNone,
117 Length(L),
119 AutoLength(L),
121}
122
123pub use self::GenericContainIntrinsicSize as ContainIntrinsicSize;
124
125impl<L: ToCss> ToCss for ContainIntrinsicSize<L> {
126 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
127 where
128 W: Write,
129 {
130 match *self {
131 Self::None => dest.write_str("none"),
132 Self::AutoNone => dest.write_str("auto none"),
133 Self::Length(ref l) => l.to_css(dest),
134 Self::AutoLength(ref l) => {
135 dest.write_str("auto ")?;
136 l.to_css(dest)
137 },
138 }
139 }
140}
141
142#[derive(
144 Clone,
145 Debug,
146 Eq,
147 MallocSizeOf,
148 PartialEq,
149 Parse,
150 SpecifiedValueInfo,
151 ToAnimatedValue,
152 ToComputedValue,
153 ToCss,
154 ToResolvedValue,
155 ToShmem,
156)]
157#[repr(C, u8)]
158pub enum BlockEllipsis {
159 Ellipsis,
161 NoEllipsis,
163 String(crate::values::AtomString),
165}
166
167impl BlockEllipsis {
168 pub fn is_ellipsis(&self) -> bool {
170 matches!(self, Self::Ellipsis)
171 }
172}
173
174#[derive(
176 Animate,
177 Clone,
178 Debug,
179 Eq,
180 MallocSizeOf,
181 PartialEq,
182 Parse,
183 SpecifiedValueInfo,
184 ToAnimatedValue,
185 ToComputedValue,
186 ToCss,
187 ToResolvedValue,
188 ToShmem,
189)]
190#[repr(u8)]
191pub enum MaxLinesKeyword {
192 None,
194 Auto,
196}
197
198impl MaxLinesKeyword {
199 pub fn is_none(&self) -> bool {
201 matches!(self, Self::None)
202 }
203}
204
205#[derive(
208 Animate,
209 Clone,
210 ComputeSquaredDistance,
211 Debug,
212 MallocSizeOf,
213 PartialEq,
214 SpecifiedValueInfo,
215 ToAnimatedValue,
216 ToAnimatedZero,
217 ToComputedValue,
218 ToCss,
219 ToResolvedValue,
220 ToShmem,
221 ToTyped,
222)]
223#[repr(C)]
224#[typed(todo_derive_fields)]
225pub struct GenericMaxLines<I> {
226 pub lines: Optional<I>,
228 #[css(skip_if = "MaxLinesKeyword::is_none")]
230 #[animation(constant)]
231 pub kw: MaxLinesKeyword,
232}
233
234pub use self::GenericMaxLines as MaxLines;
235
236impl<I> MaxLines<I> {
237 pub fn none() -> Self {
239 Self {
240 lines: Optional::None,
241 kw: MaxLinesKeyword::None,
242 }
243 }
244
245 pub fn auto() -> Self {
247 Self {
248 lines: Optional::None,
249 kw: MaxLinesKeyword::Auto,
250 }
251 }
252
253 pub fn lines(lines: I, auto: bool) -> Self {
255 Self {
256 lines: Optional::Some(lines),
257 kw: if auto {
258 MaxLinesKeyword::Auto
259 } else {
260 MaxLinesKeyword::None
261 },
262 }
263 }
264
265 pub fn is_none(&self) -> bool {
267 self.lines.is_none() && matches!(self.kw, MaxLinesKeyword::None)
268 }
269
270 pub fn is_auto(&self) -> bool {
272 self.lines.is_none() && matches!(self.kw, MaxLinesKeyword::Auto)
273 }
274
275 pub fn lines_value(&self) -> Option<&I> {
277 self.lines.as_ref()
278 }
279}
280
281#[derive(
283 Animate,
284 Clone,
285 ComputeSquaredDistance,
286 Debug,
287 MallocSizeOf,
288 PartialEq,
289 SpecifiedValueInfo,
290 ToAnimatedValue,
291 ToAnimatedZero,
292 ToComputedValue,
293 ToResolvedValue,
294 ToShmem,
295 ToTyped,
296)]
297#[repr(C)]
298#[typed(todo_derive_fields)]
299#[value_info(other_values = "none")]
300pub struct GenericLineClamp<I> {
301 pub max_lines: GenericMaxLines<I>,
303 #[animation(constant)]
305 pub block_ellipsis: BlockEllipsis,
306 #[animation(constant)]
308 pub webkit_legacy: bool,
309 #[animation(constant)]
311 pub serialize_webkit_legacy: bool,
312}
313
314pub use self::GenericLineClamp as LineClamp;
315
316impl<I> LineClamp<I> {
317 pub fn none() -> Self {
319 Self {
320 max_lines: MaxLines::none(),
321 block_ellipsis: BlockEllipsis::Ellipsis,
322 webkit_legacy: false,
323 serialize_webkit_legacy: false,
324 }
325 }
326
327 pub fn is_none(&self) -> bool {
329 self.max_lines.is_none() && self.block_ellipsis.is_ellipsis()
330 }
331}
332
333impl<I: ToCss> ToCss for LineClamp<I> {
334 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
335 where
336 W: Write,
337 {
338 if self.is_none() {
339 return dest.write_str("none");
340 }
341
342 let mut writer = SequenceWriter::new(dest, " ");
343 if !self.max_lines.is_none() {
344 writer.item(&self.max_lines)?;
345 }
346 if !self.block_ellipsis.is_ellipsis() {
347 writer.item(&self.block_ellipsis)?;
348 }
349 if self.webkit_legacy
350 && self.serialize_webkit_legacy
351 && static_prefs::pref!("layout.css.line-clamp.enabled")
352 {
353 writer.raw_item("-webkit-legacy")?;
354 }
355 Ok(())
356 }
357}
358
359#[derive(
361 Animate,
362 Clone,
363 ComputeSquaredDistance,
364 Copy,
365 Debug,
366 MallocSizeOf,
367 Parse,
368 PartialEq,
369 SpecifiedValueInfo,
370 ToAnimatedValue,
371 ToAnimatedZero,
372 ToComputedValue,
373 ToCss,
374 ToResolvedValue,
375 ToShmem,
376 ToTyped,
377)]
378#[repr(C, u8)]
379pub enum GenericPerspective<NonNegativeLength> {
380 Length(NonNegativeLength),
382 None,
384}
385
386pub use self::GenericPerspective as Perspective;
387
388impl<L> Perspective<L> {
389 #[inline]
391 pub fn none() -> Self {
392 Perspective::None
393 }
394}
395
396#[derive(
397 Clone,
398 Copy,
399 Debug,
400 MallocSizeOf,
401 Parse,
402 PartialEq,
403 SpecifiedValueInfo,
404 ToComputedValue,
405 ToCss,
406 ToResolvedValue,
407 ToShmem,
408 ToTyped,
409)]
410#[repr(u8)]
411#[allow(missing_docs)]
412pub enum PositionProperty {
413 Static = 0,
414 Relative,
415 Absolute,
416 Fixed,
417 Sticky,
418}
419
420impl PositionProperty {
421 pub fn is_absolutely_positioned(self) -> bool {
423 matches!(self, Self::Absolute | Self::Fixed)
424 }
425}
426
427#[allow(missing_docs)]
431#[derive(
432 Clone,
433 ComputeSquaredDistance,
434 Copy,
435 Debug,
436 Eq,
437 MallocSizeOf,
438 PartialEq,
439 Parse,
440 SpecifiedValueInfo,
441 ToAnimatedValue,
442 ToComputedValue,
443 ToCss,
444 ToResolvedValue,
445 ToShmem,
446 ToTyped,
447)]
448#[repr(u8)]
449pub enum OverflowClipMarginBox {
450 ContentBox,
451 PaddingBox,
452 BorderBox,
453}
454
455#[derive(
457 Animate,
458 Clone,
459 ComputeSquaredDistance,
460 Copy,
461 Debug,
462 Eq,
463 MallocSizeOf,
464 PartialEq,
465 SpecifiedValueInfo,
466 ToAnimatedValue,
467 ToComputedValue,
468 ToAnimatedZero,
469 ToResolvedValue,
470 ToShmem,
471 ToTyped,
472)]
473#[repr(C)]
474pub struct GenericOverflowClipMargin<L> {
475 pub offset: L,
477 #[animation(constant)]
479 pub visual_box: OverflowClipMarginBox,
480}
481
482pub use self::GenericOverflowClipMargin as OverflowClipMargin;
483
484impl<L: Zero> GenericOverflowClipMargin<L> {
485 pub fn zero() -> Self {
487 Self {
488 offset: Zero::zero(),
489 visual_box: OverflowClipMarginBox::PaddingBox,
490 }
491 }
492}
493
494impl<L: Zero + ToCss> ToCss for OverflowClipMargin<L> {
495 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
496 where
497 W: Write,
498 {
499 if self.visual_box == OverflowClipMarginBox::PaddingBox {
500 return self.offset.to_css(dest);
501 }
502 self.visual_box.to_css(dest)?;
503 if !self.offset.is_zero() {
504 dest.write_char(' ')?;
505 self.offset.to_css(dest)?;
506 }
507 Ok(())
508 }
509}