border.rs (6323B)
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 7 use crate::derives::*; 8 use crate::values::generics::rect::Rect; 9 use crate::values::generics::size::Size2D; 10 use crate::Zero; 11 use std::fmt::{self, Write}; 12 use 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)] 33 pub 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 45 pub 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 pub 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 76 pub 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 pub struct GenericBorderCornerRadius<L>( 100 #[css(field_bound)] 101 #[shmem(field_bound)] 102 pub Size2D<L>, 103 ); 104 105 pub use self::GenericBorderCornerRadius as BorderCornerRadius; 106 107 impl<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 114 impl<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)] 143 pub struct GenericBorderSpacing<L>( 144 #[css(field_bound)] 145 #[shmem(field_bound)] 146 pub Size2D<L>, 147 ); 148 149 pub use self::GenericBorderSpacing as BorderSpacing; 150 impl<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)] 177 pub 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 189 pub use self::GenericBorderRadius as BorderRadius; 190 191 impl<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 228 impl<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 246 impl<L> ToCss for BorderRadius<L> 247 where 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 }