Skip to main content

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