style/values/generics/
border.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 CSS values related to borders.
6
7use crate::derives::*;
8use crate::values::generics::rect::Rect;
9use crate::values::generics::size::Size2D;
10use crate::Zero;
11use std::fmt::{self, Write};
12use style_traits::{CssWriter, ToCss};
13
14/// A generic value for a single side of a `border-image-width` property.
15#[derive(
16    Animate,
17    Clone,
18    ComputeSquaredDistance,
19    Copy,
20    Debug,
21    MallocSizeOf,
22    Parse,
23    PartialEq,
24    SpecifiedValueInfo,
25    ToAnimatedValue,
26    ToAnimatedZero,
27    ToComputedValue,
28    ToCss,
29    ToResolvedValue,
30    ToShmem,
31)]
32#[repr(C, u8)]
33pub enum GenericBorderImageSideWidth<LP, N> {
34    /// `<number>`
35    ///
36    /// NOTE: Numbers need to be before length-percentagess, in order to parse
37    /// them first, since `0` should be a number, not the `0px` length.
38    Number(N),
39    /// `<length-or-percentage>`
40    LengthPercentage(LP),
41    /// `auto`
42    Auto,
43}
44
45pub use self::GenericBorderImageSideWidth as BorderImageSideWidth;
46
47/// A generic value for the `border-image-slice` property.
48#[derive(
49    Animate,
50    Clone,
51    ComputeSquaredDistance,
52    Copy,
53    Debug,
54    MallocSizeOf,
55    PartialEq,
56    SpecifiedValueInfo,
57    ToAnimatedValue,
58    ToAnimatedZero,
59    ToComputedValue,
60    ToCss,
61    ToResolvedValue,
62    ToShmem,
63    ToTyped,
64)]
65#[repr(C)]
66pub struct GenericBorderImageSlice<NumberOrPercentage> {
67    /// The offsets.
68    #[css(field_bound)]
69    pub offsets: Rect<NumberOrPercentage>,
70    /// Whether to fill the middle part.
71    #[animation(constant)]
72    #[css(represents_keyword)]
73    pub fill: bool,
74}
75
76pub use self::GenericBorderImageSlice as BorderImageSlice;
77
78/// A generic value for the `border-*-radius` longhand properties.
79#[derive(
80    Animate,
81    Clone,
82    ComputeSquaredDistance,
83    Copy,
84    Debug,
85    Deserialize,
86    MallocSizeOf,
87    PartialEq,
88    SpecifiedValueInfo,
89    Serialize,
90    ToAnimatedValue,
91    ToAnimatedZero,
92    ToComputedValue,
93    ToCss,
94    ToResolvedValue,
95    ToShmem,
96    ToTyped,
97)]
98#[repr(C)]
99pub struct GenericBorderCornerRadius<L>(
100    #[css(field_bound)]
101    #[shmem(field_bound)]
102    pub Size2D<L>,
103);
104
105pub use self::GenericBorderCornerRadius as BorderCornerRadius;
106
107impl<L> BorderCornerRadius<L> {
108    /// Trivially create a `BorderCornerRadius`.
109    pub fn new(w: L, h: L) -> Self {
110        BorderCornerRadius(Size2D::new(w, h))
111    }
112}
113
114impl<L: Zero> Zero for BorderCornerRadius<L> {
115    fn zero() -> Self {
116        BorderCornerRadius(Size2D::zero())
117    }
118
119    fn is_zero(&self) -> bool {
120        self.0.is_zero()
121    }
122}
123
124/// A generic value for the `border-spacing` property.
125#[derive(
126    Animate,
127    Clone,
128    ComputeSquaredDistance,
129    Copy,
130    Debug,
131    MallocSizeOf,
132    PartialEq,
133    SpecifiedValueInfo,
134    ToAnimatedValue,
135    ToAnimatedZero,
136    ToComputedValue,
137    ToCss,
138    ToResolvedValue,
139    ToShmem,
140    ToTyped,
141)]
142#[repr(transparent)]
143pub struct GenericBorderSpacing<L>(
144    #[css(field_bound)]
145    #[shmem(field_bound)]
146    pub Size2D<L>,
147);
148
149pub use self::GenericBorderSpacing as BorderSpacing;
150impl<L> BorderSpacing<L> {
151    /// Trivially create a `BorderCornerRadius`.
152    pub fn new(w: L, h: L) -> Self {
153        BorderSpacing(Size2D::new(w, h))
154    }
155}
156
157/// A generic value for `border-radius` and `inset()`.
158///
159/// <https://drafts.csswg.org/css-backgrounds-3/#border-radius>
160#[derive(
161    Animate,
162    Clone,
163    ComputeSquaredDistance,
164    Copy,
165    Debug,
166    Deserialize,
167    MallocSizeOf,
168    PartialEq,
169    SpecifiedValueInfo,
170    Serialize,
171    ToAnimatedValue,
172    ToComputedValue,
173    ToResolvedValue,
174    ToShmem,
175)]
176#[repr(C)]
177pub struct GenericBorderRadius<LengthPercentage> {
178    /// The top left radius.
179    #[shmem(field_bound)]
180    pub top_left: GenericBorderCornerRadius<LengthPercentage>,
181    /// The top right radius.
182    pub top_right: GenericBorderCornerRadius<LengthPercentage>,
183    /// The bottom right radius.
184    pub bottom_right: GenericBorderCornerRadius<LengthPercentage>,
185    /// The bottom left radius.
186    pub bottom_left: GenericBorderCornerRadius<LengthPercentage>,
187}
188
189pub use self::GenericBorderRadius as BorderRadius;
190
191impl<L> BorderRadius<L> {
192    /// Returns a new `BorderRadius<L>`.
193    #[inline]
194    pub fn new(
195        tl: BorderCornerRadius<L>,
196        tr: BorderCornerRadius<L>,
197        br: BorderCornerRadius<L>,
198        bl: BorderCornerRadius<L>,
199    ) -> Self {
200        BorderRadius {
201            top_left: tl,
202            top_right: tr,
203            bottom_right: br,
204            bottom_left: bl,
205        }
206    }
207
208    /// Serialises two given rects following the syntax of the `border-radius``
209    /// property.
210    pub fn serialize_rects<W>(
211        widths: Rect<&L>,
212        heights: Rect<&L>,
213        dest: &mut CssWriter<W>,
214    ) -> fmt::Result
215    where
216        L: PartialEq + ToCss,
217        W: Write,
218    {
219        widths.to_css(dest)?;
220        if widths != heights {
221            dest.write_str(" / ")?;
222            heights.to_css(dest)?;
223        }
224        Ok(())
225    }
226}
227
228impl<L: Zero> Zero for BorderRadius<L> {
229    fn zero() -> Self {
230        Self::new(
231            BorderCornerRadius::<L>::zero(),
232            BorderCornerRadius::<L>::zero(),
233            BorderCornerRadius::<L>::zero(),
234            BorderCornerRadius::<L>::zero(),
235        )
236    }
237
238    fn is_zero(&self) -> bool {
239        self.top_left.is_zero()
240            && self.top_right.is_zero()
241            && self.bottom_right.is_zero()
242            && self.bottom_left.is_zero()
243    }
244}
245
246impl<L> ToCss for BorderRadius<L>
247where
248    L: PartialEq + ToCss,
249{
250    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
251    where
252        W: Write,
253    {
254        let BorderRadius {
255            top_left: BorderCornerRadius(ref tl),
256            top_right: BorderCornerRadius(ref tr),
257            bottom_right: BorderCornerRadius(ref br),
258            bottom_left: BorderCornerRadius(ref bl),
259        } = *self;
260
261        let widths = Rect::new(&tl.width, &tr.width, &br.width, &bl.width);
262        let heights = Rect::new(&tl.height, &tr.height, &br.height, &bl.height);
263
264        Self::serialize_rects(widths, heights, dest)
265    }
266}