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