/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ //! Generic types for CSS Motion Path. use crate::values::animated::ToAnimatedZero; use crate::values::generics::position::{GenericPosition, GenericPositionOrAuto}; use crate::values::specified::motion::CoordBox; use serde::Deserializer; use std::fmt::{self, Write}; use style_traits::{CssWriter, ToCss}; /// The in ray() function. /// /// https://drafts.fxtf.org/motion-1/#valdef-offsetpath-size #[allow(missing_docs)] #[derive( Animate, Clone, ComputeSquaredDistance, Copy, Debug, Deserialize, MallocSizeOf, Parse, PartialEq, Serialize, SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss, ToResolvedValue, ToShmem, )] #[repr(u8)] pub enum RaySize { ClosestSide, ClosestCorner, FarthestSide, FarthestCorner, Sides, } /// The `ray()` function, `ray( [ && && contain? && [at ]? ] )` /// /// https://drafts.fxtf.org/motion-1/#valdef-offsetpath-ray #[derive( Animate, Clone, ComputeSquaredDistance, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToResolvedValue, ToShmem, )] #[repr(C)] pub struct GenericRayFunction { /// The bearing angle with `0deg` pointing up and positive angles /// representing clockwise rotation. pub angle: Angle, /// Decide the path length used when `offset-distance` is expressed /// as a percentage. pub size: RaySize, /// Clamp `offset-distance` so that the box is entirely contained /// within the path. #[animation(constant)] pub contain: bool, /// The "at " part. If omitted, we use auto to represent it. pub position: GenericPositionOrAuto, } pub use self::GenericRayFunction as RayFunction; impl ToCss for RayFunction where Angle: ToCss, Position: ToCss, { fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where W: Write, { self.angle.to_css(dest)?; if !matches!(self.size, RaySize::ClosestSide) { dest.write_char(' ')?; self.size.to_css(dest)?; } if self.contain { dest.write_str(" contain")?; } if !matches!(self.position, GenericPositionOrAuto::Auto) { dest.write_str(" at ")?; self.position.to_css(dest)?; } Ok(()) } } /// Return error if we try to deserialize the url, for Gecko IPC purposes. // Note: we cannot use #[serde(skip_deserializing)] variant attribute, which may cause the fatal // error when trying to read the parameters because it cannot deserialize the input byte buffer, // even if the type of OffsetPathFunction is not an url(), in our tests. This may be an issue of // #[serde(skip_deserializing)] on enum, at least in the version (1.0) we are using. So we have to // manually implement this deseriailzing function, but return error. // FIXME: Bug 1847620, fiure out this is a serde issue or a gecko bug. fn deserialize_url<'de, D, T>(_deserializer: D) -> Result where D: Deserializer<'de>, { use crate::serde::de::Error; // Return Err() so the IPC will catch it and assert this as a fetal error. Err(::Error::custom( "we don't support the deserializing for url", )) } /// The value. /// = | | /// /// https://drafts.fxtf.org/motion-1/#typedef-offset-path #[derive( Animate, Clone, ComputeSquaredDistance, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss, ToResolvedValue, ToShmem, )] #[animation(no_bound(U))] #[repr(C, u8)] pub enum GenericOffsetPathFunction { /// ray() function, which defines a path in the polar coordinate system. /// Use Box<> to make sure the size of offset-path is not too large. #[css(function)] Ray(RayFunction), /// A URL reference to an SVG shape element. If the URL does not reference a shape element, /// this behaves as path("m 0 0") instead. #[animation(error)] #[serde(deserialize_with = "deserialize_url")] #[serde(skip_serializing)] Url(U), /// The value. Shape(Shapes), } pub use self::GenericOffsetPathFunction as OffsetPathFunction; /// The offset-path property. /// offset-path: none | || /// /// https://drafts.fxtf.org/motion-1/#offset-path-property #[derive( Animate, Clone, ComputeSquaredDistance, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss, ToResolvedValue, ToShmem, )] #[repr(C, u8)] pub enum GenericOffsetPath { /// || . OffsetPath { /// part. // Note: Use Box<> to make sure the size of this property doesn't go over the threshold. path: Box, /// part. #[css(skip_if = "CoordBox::is_default")] coord_box: CoordBox, }, /// Only . This represents that is omitted, so we use the default /// value, inset(0 round X), where X is the value of border-radius on the element that /// establishes the containing block for this element. CoordBox(CoordBox), /// None value. #[animation(error)] None, } pub use self::GenericOffsetPath as OffsetPath; impl OffsetPath { /// Return None. #[inline] pub fn none() -> Self { OffsetPath::None } } impl ToAnimatedZero for OffsetPath { #[inline] fn to_animated_zero(&self) -> Result { Err(()) } } /// The offset-position property, which specifies the offset starting position that is used by the /// functions if they don’t specify their own starting position. /// /// https://drafts.fxtf.org/motion-1/#offset-position-property #[derive( Animate, Clone, ComputeSquaredDistance, Copy, Debug, Deserialize, MallocSizeOf, Parse, PartialEq, Serialize, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss, ToResolvedValue, ToShmem, )] #[repr(C, u8)] pub enum GenericOffsetPosition { /// The element does not have an offset starting position. Normal, /// The offset starting position is the top-left corner of the box. Auto, /// The offset starting position is the result of using the to position a 0x0 object /// area within the box’s containing block. Position( #[css(field_bound)] #[parse(field_bound)] GenericPosition, ), } pub use self::GenericOffsetPosition as OffsetPosition; impl OffsetPosition { /// Returns the initial value, normal. #[inline] pub fn normal() -> Self { Self::Normal } }