motion.rs (7404B)
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 Motion Path. 6 7 use crate::derives::*; 8 use crate::values::animated::ToAnimatedZero; 9 use crate::values::generics::position::{GenericPosition, GenericPositionOrAuto}; 10 use crate::values::specified::motion::CoordBox; 11 use serde::Deserializer; 12 use std::fmt::{self, Write}; 13 use style_traits::{CssWriter, ToCss}; 14 15 /// The <size> in ray() function. 16 /// 17 /// https://drafts.fxtf.org/motion-1/#valdef-offsetpath-size 18 #[allow(missing_docs)] 19 #[derive( 20 Animate, 21 Clone, 22 ComputeSquaredDistance, 23 Copy, 24 Debug, 25 Deserialize, 26 MallocSizeOf, 27 Parse, 28 PartialEq, 29 Serialize, 30 SpecifiedValueInfo, 31 ToAnimatedValue, 32 ToComputedValue, 33 ToCss, 34 ToResolvedValue, 35 ToShmem, 36 )] 37 #[repr(u8)] 38 pub enum RaySize { 39 ClosestSide, 40 ClosestCorner, 41 FarthestSide, 42 FarthestCorner, 43 Sides, 44 } 45 46 /// The `ray()` function, `ray( [ <angle> && <size> && contain? && [at <position>]? ] )` 47 /// 48 /// https://drafts.fxtf.org/motion-1/#valdef-offsetpath-ray 49 #[derive( 50 Animate, 51 Clone, 52 ComputeSquaredDistance, 53 Debug, 54 Deserialize, 55 MallocSizeOf, 56 PartialEq, 57 Serialize, 58 SpecifiedValueInfo, 59 ToAnimatedValue, 60 ToComputedValue, 61 ToResolvedValue, 62 ToShmem, 63 )] 64 #[repr(C)] 65 pub struct GenericRayFunction<Angle, Position> { 66 /// The bearing angle with `0deg` pointing up and positive angles 67 /// representing clockwise rotation. 68 pub angle: Angle, 69 /// Decide the path length used when `offset-distance` is expressed 70 /// as a percentage. 71 pub size: RaySize, 72 /// Clamp `offset-distance` so that the box is entirely contained 73 /// within the path. 74 #[animation(constant)] 75 pub contain: bool, 76 /// The "at <position>" part. If omitted, we use auto to represent it. 77 pub position: GenericPositionOrAuto<Position>, 78 } 79 80 pub use self::GenericRayFunction as RayFunction; 81 82 impl<Angle, Position> ToCss for RayFunction<Angle, Position> 83 where 84 Angle: ToCss, 85 Position: ToCss, 86 { 87 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result 88 where 89 W: Write, 90 { 91 self.angle.to_css(dest)?; 92 93 if !matches!(self.size, RaySize::ClosestSide) { 94 dest.write_char(' ')?; 95 self.size.to_css(dest)?; 96 } 97 98 if self.contain { 99 dest.write_str(" contain")?; 100 } 101 102 if !matches!(self.position, GenericPositionOrAuto::Auto) { 103 dest.write_str(" at ")?; 104 self.position.to_css(dest)?; 105 } 106 107 Ok(()) 108 } 109 } 110 111 /// Return error if we try to deserialize the url, for Gecko IPC purposes. 112 // Note: we cannot use #[serde(skip_deserializing)] variant attribute, which may cause the fatal 113 // error when trying to read the parameters because it cannot deserialize the input byte buffer, 114 // even if the type of OffsetPathFunction is not an url(), in our tests. This may be an issue of 115 // #[serde(skip_deserializing)] on enum, at least in the version (1.0) we are using. So we have to 116 // manually implement this deseriailzing function, but return error. 117 // FIXME: Bug 1847620, fiure out this is a serde issue or a gecko bug. 118 fn deserialize_url<'de, D, T>(_deserializer: D) -> Result<T, D::Error> 119 where 120 D: Deserializer<'de>, 121 { 122 use crate::serde::de::Error; 123 // Return Err() so the IPC will catch it and assert this as a fetal error. 124 Err(<D as Deserializer>::Error::custom( 125 "we don't support the deserializing for url", 126 )) 127 } 128 129 /// The <offset-path> value. 130 /// <offset-path> = <ray()> | <url> | <basic-shape> 131 /// 132 /// https://drafts.fxtf.org/motion-1/#typedef-offset-path 133 #[derive( 134 Animate, 135 Clone, 136 ComputeSquaredDistance, 137 Debug, 138 Deserialize, 139 MallocSizeOf, 140 PartialEq, 141 Serialize, 142 SpecifiedValueInfo, 143 ToAnimatedValue, 144 ToComputedValue, 145 ToCss, 146 ToResolvedValue, 147 ToShmem, 148 )] 149 #[animation(no_bound(U))] 150 #[repr(C, u8)] 151 pub enum GenericOffsetPathFunction<Shapes, RayFunction, U> { 152 /// ray() function, which defines a path in the polar coordinate system. 153 /// Use Box<> to make sure the size of offset-path is not too large. 154 #[css(function)] 155 Ray(RayFunction), 156 /// A URL reference to an SVG shape element. If the URL does not reference a shape element, 157 /// this behaves as path("m 0 0") instead. 158 #[animation(error)] 159 #[serde(deserialize_with = "deserialize_url")] 160 #[serde(skip_serializing)] 161 Url(U), 162 /// The <basic-shape> value. 163 Shape(Shapes), 164 } 165 166 pub use self::GenericOffsetPathFunction as OffsetPathFunction; 167 168 /// The offset-path property. 169 /// offset-path: none | <offset-path> || <coord-box> 170 /// 171 /// https://drafts.fxtf.org/motion-1/#offset-path-property 172 #[derive( 173 Animate, 174 Clone, 175 ComputeSquaredDistance, 176 Debug, 177 Deserialize, 178 MallocSizeOf, 179 PartialEq, 180 Serialize, 181 SpecifiedValueInfo, 182 ToAnimatedValue, 183 ToComputedValue, 184 ToCss, 185 ToResolvedValue, 186 ToShmem, 187 ToTyped, 188 )] 189 #[repr(C, u8)] 190 pub enum GenericOffsetPath<Function> { 191 /// <offset-path> || <coord-box>. 192 OffsetPath { 193 /// <offset-path> part. 194 // Note: Use Box<> to make sure the size of this property doesn't go over the threshold. 195 path: Box<Function>, 196 /// <coord-box> part. 197 #[css(skip_if = "CoordBox::is_default")] 198 coord_box: CoordBox, 199 }, 200 /// Only <coord-box>. This represents that <offset-path> is omitted, so we use the default 201 /// value, inset(0 round X), where X is the value of border-radius on the element that 202 /// establishes the containing block for this element. 203 CoordBox(CoordBox), 204 /// None value. 205 #[animation(error)] 206 None, 207 } 208 209 pub use self::GenericOffsetPath as OffsetPath; 210 211 impl<Function> OffsetPath<Function> { 212 /// Return None. 213 #[inline] 214 pub fn none() -> Self { 215 OffsetPath::None 216 } 217 } 218 219 impl<Function> ToAnimatedZero for OffsetPath<Function> { 220 #[inline] 221 fn to_animated_zero(&self) -> Result<Self, ()> { 222 Err(()) 223 } 224 } 225 226 /// The offset-position property, which specifies the offset starting position that is used by the 227 /// <offset-path> functions if they don’t specify their own starting position. 228 /// 229 /// https://drafts.fxtf.org/motion-1/#offset-position-property 230 #[derive( 231 Animate, 232 Clone, 233 ComputeSquaredDistance, 234 Copy, 235 Debug, 236 Deserialize, 237 MallocSizeOf, 238 Parse, 239 PartialEq, 240 Serialize, 241 SpecifiedValueInfo, 242 ToAnimatedValue, 243 ToAnimatedZero, 244 ToComputedValue, 245 ToCss, 246 ToResolvedValue, 247 ToShmem, 248 ToTyped, 249 )] 250 #[repr(C, u8)] 251 pub enum GenericOffsetPosition<H, V> { 252 /// The element does not have an offset starting position. 253 Normal, 254 /// The offset starting position is the top-left corner of the box. 255 Auto, 256 /// The offset starting position is the result of using the <position> to position a 0x0 object 257 /// area within the box’s containing block. 258 Position( 259 #[css(field_bound)] 260 #[parse(field_bound)] 261 GenericPosition<H, V>, 262 ), 263 } 264 265 pub use self::GenericOffsetPosition as OffsetPosition; 266 267 impl<H, V> OffsetPosition<H, V> { 268 /// Returns the initial value, normal. 269 #[inline] 270 pub fn normal() -> Self { 271 Self::Normal 272 } 273 }