style/values/generics/
motion.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 Motion Path.
6
7use crate::derives::*;
8use crate::values::animated::ToAnimatedZero;
9use crate::values::generics::position::{GenericPosition, GenericPositionOrAuto};
10use crate::values::specified::motion::CoordBox;
11use serde::Deserializer;
12use std::fmt::{self, Write};
13use 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)]
38pub 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)]
65pub 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
80pub use self::GenericRayFunction as RayFunction;
81
82impl<Angle, Position> ToCss for RayFunction<Angle, Position>
83where
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.
118fn deserialize_url<'de, D, T>(_deserializer: D) -> Result<T, D::Error>
119where
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)]
151pub 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
166pub 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)]
190pub 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
209pub use self::GenericOffsetPath as OffsetPath;
210
211impl<Function> OffsetPath<Function> {
212    /// Return None.
213    #[inline]
214    pub fn none() -> Self {
215        OffsetPath::None
216    }
217}
218
219impl<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)]
251pub 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
265pub use self::GenericOffsetPosition as OffsetPosition;
266
267impl<H, V> OffsetPosition<H, V> {
268    /// Returns the initial value, normal.
269    #[inline]
270    pub fn normal() -> Self {
271        Self::Normal
272    }
273}