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)]
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)]
66#[typed(todo_derive_fields)]
67pub struct GenericBorderImageSlice<NumberOrPercentage> {
68    /// The offsets.
69    #[css(field_bound)]
70    pub offsets: Rect<NumberOrPercentage>,
71    /// Whether to fill the middle part.
72    #[animation(constant)]
73    #[css(represents_keyword)]
74    pub fill: bool,
75}
76
77pub use self::GenericBorderImageSlice as BorderImageSlice;
78
79/// A generic value for the `border-*-radius` longhand properties.
80#[derive(
81    Animate,
82    Clone,
83    ComputeSquaredDistance,
84    Copy,
85    Debug,
86    Deserialize,
87    MallocSizeOf,
88    PartialEq,
89    SpecifiedValueInfo,
90    Serialize,
91    ToAnimatedValue,
92    ToAnimatedZero,
93    ToComputedValue,
94    ToCss,
95    ToResolvedValue,
96    ToShmem,
97    ToTyped,
98)]
99#[repr(C)]
100#[typed(todo_derive_fields)]
101pub struct GenericBorderCornerRadius<L>(
102    #[css(field_bound)]
103    #[shmem(field_bound)]
104    pub Size2D<L>,
105);
106
107pub use self::GenericBorderCornerRadius as BorderCornerRadius;
108
109impl<L> BorderCornerRadius<L> {
110    /// Trivially create a `BorderCornerRadius`.
111    pub fn new(w: L, h: L) -> Self {
112        BorderCornerRadius(Size2D::new(w, h))
113    }
114}
115
116impl<L: Zero> Zero for BorderCornerRadius<L> {
117    fn zero() -> Self {
118        BorderCornerRadius(Size2D::zero())
119    }
120
121    fn is_zero(&self) -> bool {
122        self.0.is_zero()
123    }
124}
125
126/// A generic value for the `border-spacing` property.
127#[derive(
128    Animate,
129    Clone,
130    ComputeSquaredDistance,
131    Copy,
132    Debug,
133    MallocSizeOf,
134    PartialEq,
135    SpecifiedValueInfo,
136    ToAnimatedValue,
137    ToAnimatedZero,
138    ToComputedValue,
139    ToCss,
140    ToResolvedValue,
141    ToShmem,
142    ToTyped,
143)]
144#[repr(transparent)]
145#[typed(todo_derive_fields)]
146pub struct GenericBorderSpacing<L>(
147    #[css(field_bound)]
148    #[shmem(field_bound)]
149    pub Size2D<L>,
150);
151
152pub use self::GenericBorderSpacing as BorderSpacing;
153impl<L> BorderSpacing<L> {
154    /// Trivially create a `BorderCornerRadius`.
155    pub fn new(w: L, h: L) -> Self {
156        BorderSpacing(Size2D::new(w, h))
157    }
158}
159
160/// A generic value for `border-radius` and `inset()`.
161///
162/// <https://drafts.csswg.org/css-backgrounds-3/#border-radius>
163#[derive(
164    Animate,
165    Clone,
166    ComputeSquaredDistance,
167    Copy,
168    Debug,
169    Deserialize,
170    MallocSizeOf,
171    PartialEq,
172    SpecifiedValueInfo,
173    Serialize,
174    ToAnimatedValue,
175    ToComputedValue,
176    ToResolvedValue,
177    ToShmem,
178)]
179#[repr(C)]
180pub struct GenericBorderRadius<LengthPercentage> {
181    /// The top left radius.
182    #[shmem(field_bound)]
183    pub top_left: GenericBorderCornerRadius<LengthPercentage>,
184    /// The top right radius.
185    pub top_right: GenericBorderCornerRadius<LengthPercentage>,
186    /// The bottom right radius.
187    pub bottom_right: GenericBorderCornerRadius<LengthPercentage>,
188    /// The bottom left radius.
189    pub bottom_left: GenericBorderCornerRadius<LengthPercentage>,
190}
191
192pub use self::GenericBorderRadius as BorderRadius;
193
194impl<L> BorderRadius<L> {
195    /// Returns a new `BorderRadius<L>`.
196    #[inline]
197    pub fn new(
198        tl: BorderCornerRadius<L>,
199        tr: BorderCornerRadius<L>,
200        br: BorderCornerRadius<L>,
201        bl: BorderCornerRadius<L>,
202    ) -> Self {
203        BorderRadius {
204            top_left: tl,
205            top_right: tr,
206            bottom_right: br,
207            bottom_left: bl,
208        }
209    }
210
211    /// Serialises two given rects following the syntax of the `border-radius``
212    /// property.
213    pub fn serialize_rects<W>(
214        widths: Rect<&L>,
215        heights: Rect<&L>,
216        dest: &mut CssWriter<W>,
217    ) -> fmt::Result
218    where
219        L: PartialEq + ToCss,
220        W: Write,
221    {
222        widths.to_css(dest)?;
223        if widths != heights {
224            dest.write_str(" / ")?;
225            heights.to_css(dest)?;
226        }
227        Ok(())
228    }
229}
230
231impl<L: Zero> Zero for BorderRadius<L> {
232    fn zero() -> Self {
233        Self::new(
234            BorderCornerRadius::<L>::zero(),
235            BorderCornerRadius::<L>::zero(),
236            BorderCornerRadius::<L>::zero(),
237            BorderCornerRadius::<L>::zero(),
238        )
239    }
240
241    fn is_zero(&self) -> bool {
242        self.top_left.is_zero()
243            && self.top_right.is_zero()
244            && self.bottom_right.is_zero()
245            && self.bottom_left.is_zero()
246    }
247}
248
249impl<L> ToCss for BorderRadius<L>
250where
251    L: PartialEq + ToCss,
252{
253    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
254    where
255        W: Write,
256    {
257        let BorderRadius {
258            top_left: BorderCornerRadius(ref tl),
259            top_right: BorderCornerRadius(ref tr),
260            bottom_right: BorderCornerRadius(ref br),
261            bottom_left: BorderCornerRadius(ref bl),
262        } = *self;
263
264        let widths = Rect::new(&tl.width, &tr.width, &br.width, &bl.width);
265        let heights = Rect::new(&tl.height, &tr.height, &br.height, &bl.height);
266
267        Self::serialize_rects(widths, heights, dest)
268    }
269}