Skip to main content

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    ToTyped,
32)]
33#[repr(C, u8)]
34pub enum GenericBorderImageSideWidth<LP, N> {
35    /// `<number>`
36    ///
37    /// NOTE: Numbers need to be before length-percentagess, in order to parse
38    /// them first, since `0` should be a number, not the `0px` length.
39    Number(N),
40    /// `<length-or-percentage>`
41    LengthPercentage(LP),
42    /// `auto`
43    Auto,
44}
45
46pub use self::GenericBorderImageSideWidth as BorderImageSideWidth;
47
48/// A generic value for the `border-image-slice` property.
49#[derive(
50    Animate,
51    Clone,
52    ComputeSquaredDistance,
53    Copy,
54    Debug,
55    MallocSizeOf,
56    PartialEq,
57    SpecifiedValueInfo,
58    ToAnimatedValue,
59    ToAnimatedZero,
60    ToComputedValue,
61    ToCss,
62    ToResolvedValue,
63    ToShmem,
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)]
99#[typed(todo_derive_fields)]
100pub struct GenericBorderCornerRadius<L>(
101    #[css(field_bound)]
102    #[shmem(field_bound)]
103    pub Size2D<L>,
104);
105
106pub use self::GenericBorderCornerRadius as BorderCornerRadius;
107
108impl<L> BorderCornerRadius<L> {
109    /// Trivially create a `BorderCornerRadius`.
110    pub fn new(w: L, h: L) -> Self {
111        BorderCornerRadius(Size2D::new(w, h))
112    }
113}
114
115impl<L: Zero> Zero for BorderCornerRadius<L> {
116    fn zero() -> Self {
117        BorderCornerRadius(Size2D::zero())
118    }
119
120    fn is_zero(&self) -> bool {
121        self.0.is_zero()
122    }
123}
124
125/// A generic value for the `border-spacing` property.
126#[derive(
127    Animate,
128    Clone,
129    ComputeSquaredDistance,
130    Copy,
131    Debug,
132    MallocSizeOf,
133    PartialEq,
134    SpecifiedValueInfo,
135    ToAnimatedValue,
136    ToAnimatedZero,
137    ToComputedValue,
138    ToCss,
139    ToResolvedValue,
140    ToShmem,
141    ToTyped,
142)]
143#[repr(transparent)]
144#[typed(todo_derive_fields)]
145pub struct GenericBorderSpacing<L>(
146    #[css(field_bound)]
147    #[shmem(field_bound)]
148    pub Size2D<L>,
149);
150
151pub use self::GenericBorderSpacing as BorderSpacing;
152impl<L> BorderSpacing<L> {
153    /// Trivially create a `BorderCornerRadius`.
154    pub fn new(w: L, h: L) -> Self {
155        BorderSpacing(Size2D::new(w, h))
156    }
157}
158
159/// A generic value for `border-radius` and `inset()`.
160///
161/// <https://drafts.csswg.org/css-backgrounds-3/#border-radius>
162#[derive(
163    Animate,
164    Clone,
165    ComputeSquaredDistance,
166    Copy,
167    Debug,
168    Deserialize,
169    MallocSizeOf,
170    PartialEq,
171    SpecifiedValueInfo,
172    Serialize,
173    ToAnimatedValue,
174    ToComputedValue,
175    ToResolvedValue,
176    ToShmem,
177)]
178#[repr(C)]
179pub struct GenericBorderRadius<LengthPercentage> {
180    /// The top left radius.
181    #[shmem(field_bound)]
182    pub top_left: GenericBorderCornerRadius<LengthPercentage>,
183    /// The top right radius.
184    pub top_right: GenericBorderCornerRadius<LengthPercentage>,
185    /// The bottom right radius.
186    pub bottom_right: GenericBorderCornerRadius<LengthPercentage>,
187    /// The bottom left radius.
188    pub bottom_left: GenericBorderCornerRadius<LengthPercentage>,
189}
190
191pub use self::GenericBorderRadius as BorderRadius;
192
193impl<L> BorderRadius<L> {
194    /// Returns a new `BorderRadius<L>`.
195    #[inline]
196    pub fn new(
197        tl: BorderCornerRadius<L>,
198        tr: BorderCornerRadius<L>,
199        br: BorderCornerRadius<L>,
200        bl: BorderCornerRadius<L>,
201    ) -> Self {
202        BorderRadius {
203            top_left: tl,
204            top_right: tr,
205            bottom_right: br,
206            bottom_left: bl,
207        }
208    }
209
210    /// Serialises two given rects following the syntax of the `border-radius``
211    /// property.
212    pub fn serialize_rects<W>(
213        widths: Rect<&L>,
214        heights: Rect<&L>,
215        dest: &mut CssWriter<W>,
216    ) -> fmt::Result
217    where
218        L: PartialEq + ToCss,
219        W: Write,
220    {
221        widths.to_css(dest)?;
222        if widths != heights {
223            dest.write_str(" / ")?;
224            heights.to_css(dest)?;
225        }
226        Ok(())
227    }
228}
229
230impl<L: Zero> Zero for BorderRadius<L> {
231    fn zero() -> Self {
232        Self::new(
233            BorderCornerRadius::<L>::zero(),
234            BorderCornerRadius::<L>::zero(),
235            BorderCornerRadius::<L>::zero(),
236            BorderCornerRadius::<L>::zero(),
237        )
238    }
239
240    fn is_zero(&self) -> bool {
241        self.top_left.is_zero()
242            && self.top_right.is_zero()
243            && self.bottom_right.is_zero()
244            && self.bottom_left.is_zero()
245    }
246}
247
248impl<L> ToCss for BorderRadius<L>
249where
250    L: PartialEq + ToCss,
251{
252    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
253    where
254        W: Write,
255    {
256        let BorderRadius {
257            top_left: BorderCornerRadius(ref tl),
258            top_right: BorderCornerRadius(ref tr),
259            bottom_right: BorderCornerRadius(ref br),
260            bottom_left: BorderCornerRadius(ref bl),
261        } = *self;
262
263        let widths = Rect::new(&tl.width, &tr.width, &br.width, &bl.width);
264        let heights = Rect::new(&tl.height, &tr.height, &br.height, &bl.height);
265
266        Self::serialize_rects(widths, heights, dest)
267    }
268}
269
270/// A generic value for the four corners of `corner-shape`.
271///
272/// This mirrors the per-corner layout of `BorderRadius` so it can be used as
273/// the underlying storage for the four `corner-*-*-shape` longhands and their
274/// shorthand `corner-shape`.
275///
276/// <https://drafts.csswg.org/css-borders-4/#corner-shaping>
277#[derive(Clone)]
278#[repr(C)]
279pub struct GenericCornerShapeRect<S> {
280    /// The top-left corner shape.
281    pub top_left: S,
282    /// The top-right corner shape.
283    pub top_right: S,
284    /// The bottom-right corner shape.
285    pub bottom_right: S,
286    /// The bottom-left corner shape.
287    pub bottom_left: S,
288}
289
290pub use self::GenericCornerShapeRect as CornerShapeRect;
291
292impl<S: Clone> CornerShapeRect<S> {
293    /// Construct from a single value applied to all four corners.
294    #[inline]
295    pub fn all(s: S) -> Self {
296        Self {
297            top_left: s.clone(),
298            top_right: s.clone(),
299            bottom_right: s.clone(),
300            bottom_left: s,
301        }
302    }
303}