style/values/generics/
box.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Generic types for box properties.
6
7use crate::derives::*;
8use crate::values::animated::ToAnimatedZero;
9use crate::Zero;
10use std::fmt::{self, Write};
11use style_traits::{CssWriter, ToCss};
12
13#[derive(
14    Animate,
15    Clone,
16    ComputeSquaredDistance,
17    Copy,
18    Debug,
19    FromPrimitive,
20    MallocSizeOf,
21    Parse,
22    PartialEq,
23    SpecifiedValueInfo,
24    ToAnimatedValue,
25    ToComputedValue,
26    ToCss,
27    ToResolvedValue,
28    ToShmem,
29)]
30#[repr(u8)]
31#[allow(missing_docs)]
32pub enum VerticalAlignKeyword {
33    Baseline,
34    Sub,
35    Super,
36    Top,
37    TextTop,
38    Middle,
39    Bottom,
40    TextBottom,
41    #[cfg(feature = "gecko")]
42    MozMiddleWithBaseline,
43}
44
45/// A generic value for the `vertical-align` property.
46#[derive(
47    Animate,
48    Clone,
49    ComputeSquaredDistance,
50    Copy,
51    Debug,
52    MallocSizeOf,
53    PartialEq,
54    SpecifiedValueInfo,
55    ToAnimatedValue,
56    ToComputedValue,
57    ToCss,
58    ToResolvedValue,
59    ToShmem,
60    ToTyped,
61)]
62#[repr(C, u8)]
63pub enum GenericVerticalAlign<LengthPercentage> {
64    /// One of the vertical-align keywords.
65    Keyword(VerticalAlignKeyword),
66    /// `<length-percentage>`
67    Length(LengthPercentage),
68}
69
70pub use self::GenericVerticalAlign as VerticalAlign;
71
72impl<L> VerticalAlign<L> {
73    /// Returns `baseline`.
74    #[inline]
75    pub fn baseline() -> Self {
76        VerticalAlign::Keyword(VerticalAlignKeyword::Baseline)
77    }
78}
79
80impl<L> ToAnimatedZero for VerticalAlign<L> {
81    fn to_animated_zero(&self) -> Result<Self, ()> {
82        Err(())
83    }
84}
85
86/// https://drafts.csswg.org/css-sizing-4/#intrinsic-size-override
87#[derive(
88    Animate,
89    Clone,
90    ComputeSquaredDistance,
91    Debug,
92    MallocSizeOf,
93    PartialEq,
94    SpecifiedValueInfo,
95    ToComputedValue,
96    ToAnimatedValue,
97    ToAnimatedZero,
98    ToResolvedValue,
99    ToShmem,
100    ToTyped,
101)]
102#[value_info(other_values = "auto")]
103#[repr(C, u8)]
104pub enum GenericContainIntrinsicSize<L> {
105    /// The keyword `none`.
106    None,
107    /// The keywords 'auto none',
108    AutoNone,
109    /// A non-negative length.
110    Length(L),
111    /// "auto <Length>"
112    AutoLength(L),
113}
114
115pub use self::GenericContainIntrinsicSize as ContainIntrinsicSize;
116
117impl<L: ToCss> ToCss for ContainIntrinsicSize<L> {
118    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
119    where
120        W: Write,
121    {
122        match *self {
123            Self::None => dest.write_str("none"),
124            Self::AutoNone => dest.write_str("auto none"),
125            Self::Length(ref l) => l.to_css(dest),
126            Self::AutoLength(ref l) => {
127                dest.write_str("auto ")?;
128                l.to_css(dest)
129            },
130        }
131    }
132}
133
134/// Note that we only implement -webkit-line-clamp as a single, longhand
135/// property for now, but the spec defines line-clamp as a shorthand for
136/// separate max-lines, block-ellipsis, and continue properties.
137///
138/// https://drafts.csswg.org/css-overflow-3/#line-clamp
139#[derive(
140    Clone,
141    ComputeSquaredDistance,
142    Copy,
143    Debug,
144    MallocSizeOf,
145    PartialEq,
146    SpecifiedValueInfo,
147    ToComputedValue,
148    ToAnimatedValue,
149    ToAnimatedZero,
150    ToResolvedValue,
151    ToShmem,
152    ToTyped,
153)]
154#[repr(transparent)]
155#[value_info(other_values = "none")]
156pub struct GenericLineClamp<I>(pub I);
157
158pub use self::GenericLineClamp as LineClamp;
159
160impl<I: Zero> LineClamp<I> {
161    /// Returns the `none` value.
162    pub fn none() -> Self {
163        Self(crate::Zero::zero())
164    }
165
166    /// Returns whether we're the `none` value.
167    pub fn is_none(&self) -> bool {
168        self.0.is_zero()
169    }
170}
171
172impl<I: Zero + ToCss> ToCss for LineClamp<I> {
173    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
174    where
175        W: Write,
176    {
177        if self.is_none() {
178            return dest.write_str("none");
179        }
180        self.0.to_css(dest)
181    }
182}
183
184/// A generic value for the `perspective` property.
185#[derive(
186    Animate,
187    Clone,
188    ComputeSquaredDistance,
189    Copy,
190    Debug,
191    MallocSizeOf,
192    Parse,
193    PartialEq,
194    SpecifiedValueInfo,
195    ToAnimatedValue,
196    ToAnimatedZero,
197    ToComputedValue,
198    ToCss,
199    ToResolvedValue,
200    ToShmem,
201    ToTyped,
202)]
203#[repr(C, u8)]
204#[typed_value(derive_fields)]
205pub enum GenericPerspective<NonNegativeLength> {
206    /// A non-negative length.
207    Length(NonNegativeLength),
208    /// The keyword `none`.
209    None,
210}
211
212pub use self::GenericPerspective as Perspective;
213
214impl<L> Perspective<L> {
215    /// Returns `none`.
216    #[inline]
217    pub fn none() -> Self {
218        Perspective::None
219    }
220}
221
222#[derive(
223    Clone,
224    Copy,
225    Debug,
226    MallocSizeOf,
227    Parse,
228    PartialEq,
229    SpecifiedValueInfo,
230    ToComputedValue,
231    ToCss,
232    ToResolvedValue,
233    ToShmem,
234    ToTyped,
235)]
236#[repr(u8)]
237#[allow(missing_docs)]
238pub enum PositionProperty {
239    Static = 0,
240    Relative,
241    Absolute,
242    Fixed,
243    Sticky,
244}
245
246impl PositionProperty {
247    /// Is the box absolutely positioned?
248    pub fn is_absolutely_positioned(self) -> bool {
249        matches!(self, Self::Absolute | Self::Fixed)
250    }
251}
252
253/// https://drafts.csswg.org/css-overflow-4/#overflow-clip-margin's <visual-box>. Note that the
254/// spec has special behavior for the omitted keyword, but that's rather odd, see:
255/// https://github.com/w3c/csswg-drafts/issues/13185
256#[allow(missing_docs)]
257#[derive(
258    Clone,
259    ComputeSquaredDistance,
260    Copy,
261    Debug,
262    Eq,
263    MallocSizeOf,
264    PartialEq,
265    Parse,
266    SpecifiedValueInfo,
267    ToAnimatedValue,
268    ToComputedValue,
269    ToCss,
270    ToResolvedValue,
271    ToShmem,
272    ToTyped,
273)]
274#[repr(u8)]
275pub enum OverflowClipMarginBox {
276    ContentBox,
277    PaddingBox,
278    BorderBox,
279}
280
281/// https://drafts.csswg.org/css-overflow-4/#overflow-clip-margin
282#[derive(
283    Animate,
284    Clone,
285    ComputeSquaredDistance,
286    Copy,
287    Debug,
288    Eq,
289    MallocSizeOf,
290    PartialEq,
291    SpecifiedValueInfo,
292    ToAnimatedValue,
293    ToComputedValue,
294    ToAnimatedZero,
295    ToResolvedValue,
296    ToShmem,
297    ToTyped,
298)]
299#[repr(C)]
300pub struct GenericOverflowClipMargin<L> {
301    /// The offset of the clip.
302    pub offset: L,
303    /// The box that we're clipping to.
304    #[animation(constant)]
305    pub visual_box: OverflowClipMarginBox,
306}
307
308pub use self::GenericOverflowClipMargin as OverflowClipMargin;
309
310impl<L: Zero> GenericOverflowClipMargin<L> {
311    /// Returns the `none` value.
312    pub fn zero() -> Self {
313        Self {
314            offset: Zero::zero(),
315            visual_box: OverflowClipMarginBox::PaddingBox,
316        }
317    }
318}
319
320impl<L: Zero + ToCss> ToCss for OverflowClipMargin<L> {
321    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
322    where
323        W: Write,
324    {
325        if self.visual_box == OverflowClipMarginBox::PaddingBox {
326            return self.offset.to_css(dest);
327        }
328        self.visual_box.to_css(dest)?;
329        if !self.offset.is_zero() {
330            dest.write_char(' ')?;
331            self.offset.to_css(dest)?;
332        }
333        Ok(())
334    }
335}