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