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