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}
310
311pub use self::GenericLineClamp as LineClamp;
312
313impl<I> LineClamp<I> {
314 pub fn none() -> Self {
316 Self {
317 max_lines: MaxLines::none(),
318 block_ellipsis: BlockEllipsis::Ellipsis,
319 webkit_legacy: false,
320 }
321 }
322
323 pub fn is_none(&self) -> bool {
325 self.max_lines.is_none() && self.block_ellipsis.is_ellipsis()
326 }
327}
328
329impl<I: ToCss> ToCss for LineClamp<I> {
330 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
331 where
332 W: Write,
333 {
334 if self.is_none() {
335 return dest.write_str("none");
336 }
337
338 let mut writer = SequenceWriter::new(dest, " ");
339 if !self.max_lines.is_none() {
340 writer.item(&self.max_lines)?;
341 }
342 if !self.block_ellipsis.is_ellipsis() {
343 writer.item(&self.block_ellipsis)?;
344 }
345 if self.webkit_legacy && crate::pref!("layout.css.line-clamp.enabled") {
346 writer.raw_item("-webkit-legacy")?;
347 }
348 Ok(())
349 }
350}
351
352#[derive(
354 Animate,
355 Clone,
356 ComputeSquaredDistance,
357 Copy,
358 Debug,
359 MallocSizeOf,
360 Parse,
361 PartialEq,
362 SpecifiedValueInfo,
363 ToAnimatedValue,
364 ToAnimatedZero,
365 ToComputedValue,
366 ToCss,
367 ToResolvedValue,
368 ToShmem,
369 ToTyped,
370)]
371#[repr(C, u8)]
372pub enum GenericPerspective<NonNegativeLength> {
373 Length(NonNegativeLength),
375 None,
377}
378
379pub use self::GenericPerspective as Perspective;
380
381impl<L> Perspective<L> {
382 #[inline]
384 pub fn none() -> Self {
385 Perspective::None
386 }
387}
388
389#[derive(
390 Clone,
391 Copy,
392 Debug,
393 MallocSizeOf,
394 Parse,
395 PartialEq,
396 SpecifiedValueInfo,
397 ToComputedValue,
398 ToCss,
399 ToResolvedValue,
400 ToShmem,
401 ToTyped,
402)]
403#[repr(u8)]
404#[allow(missing_docs)]
405pub enum PositionProperty {
406 Static = 0,
407 Relative,
408 Absolute,
409 Fixed,
410 Sticky,
411}
412
413impl PositionProperty {
414 pub fn is_absolutely_positioned(self) -> bool {
416 matches!(self, Self::Absolute | Self::Fixed)
417 }
418}
419
420#[allow(missing_docs)]
424#[derive(
425 Clone,
426 ComputeSquaredDistance,
427 Copy,
428 Debug,
429 Eq,
430 MallocSizeOf,
431 PartialEq,
432 Parse,
433 SpecifiedValueInfo,
434 ToAnimatedValue,
435 ToComputedValue,
436 ToCss,
437 ToResolvedValue,
438 ToShmem,
439 ToTyped,
440)]
441#[repr(u8)]
442pub enum OverflowClipMarginBox {
443 ContentBox,
444 PaddingBox,
445 BorderBox,
446}
447
448#[derive(
450 Animate,
451 Clone,
452 ComputeSquaredDistance,
453 Copy,
454 Debug,
455 Eq,
456 MallocSizeOf,
457 PartialEq,
458 SpecifiedValueInfo,
459 ToAnimatedValue,
460 ToComputedValue,
461 ToAnimatedZero,
462 ToResolvedValue,
463 ToShmem,
464 ToTyped,
465)]
466#[repr(C)]
467pub struct GenericOverflowClipMargin<L> {
468 pub offset: L,
470 #[animation(constant)]
472 pub visual_box: OverflowClipMarginBox,
473}
474
475pub use self::GenericOverflowClipMargin as OverflowClipMargin;
476
477impl<L: Zero> GenericOverflowClipMargin<L> {
478 pub fn zero() -> Self {
480 Self {
481 offset: Zero::zero(),
482 visual_box: OverflowClipMarginBox::PaddingBox,
483 }
484 }
485}
486
487impl<L: Zero + ToCss> ToCss for OverflowClipMargin<L> {
488 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
489 where
490 W: Write,
491 {
492 if self.visual_box == OverflowClipMarginBox::PaddingBox {
493 return self.offset.to_css(dest);
494 }
495 self.visual_box.to_css(dest)?;
496 if !self.offset.is_zero() {
497 dest.write_char(' ')?;
498 self.offset.to_css(dest)?;
499 }
500 Ok(())
501 }
502}
503
504#[derive(
509 Clone,
510 Copy,
511 Debug,
512 MallocSizeOf,
513 PartialEq,
514 SpecifiedValueInfo,
515 ToComputedValue,
516 ToResolvedValue,
517 ToShmem,
518 ToTyped,
519)]
520#[repr(C)]
521pub struct GenericScrollbarInset<L> {
522 pub start: L,
524 pub end: L,
526}
527
528pub use self::GenericScrollbarInset as ScrollbarInset;
529
530impl<L: Zero> ScrollbarInset<L> {
531 pub fn zero() -> Self {
533 Self {
534 start: Zero::zero(),
535 end: Zero::zero(),
536 }
537 }
538}
539
540impl<L: PartialEq + ToCss> ToCss for ScrollbarInset<L> {
541 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
542 where
543 W: Write,
544 {
545 self.start.to_css(dest)?;
546 if self.end != self.start {
547 dest.write_char(' ')?;
548 self.end.to_css(dest)?;
549 }
550 Ok(())
551 }
552}