diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:35:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:35:49 +0000 |
commit | d8bbc7858622b6d9c278469aab701ca0b609cddf (patch) | |
tree | eff41dc61d9f714852212739e6b3738b82a2af87 /servo/components/style/values/generics | |
parent | Releasing progress-linux version 125.0.3-1~progress7.99u1. (diff) | |
download | firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip |
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
4 files changed, 528 insertions, 23 deletions
diff --git a/servo/components/style/values/generics/basic_shape.rs b/servo/components/style/values/generics/basic_shape.rs index 13d27995c1..ca7646fb13 100644 --- a/servo/components/style/values/generics/basic_shape.rs +++ b/servo/components/style/values/generics/basic_shape.rs @@ -10,7 +10,7 @@ use crate::values::distance::{ComputeSquaredDistance, SquaredDistance}; use crate::values::generics::border::GenericBorderRadius; use crate::values::generics::position::GenericPositionOrAuto; use crate::values::generics::rect::Rect; -use crate::values::specified::SVGPathData; +use crate::values::specified::svg_path::{PathCommand, SVGPathData}; use crate::Zero; use std::fmt::{self, Write}; use style_traits::{CssWriter, ToCss}; @@ -181,8 +181,13 @@ pub use self::GenericShapeOutside as ShapeOutside; ToShmem, )] #[repr(C, u8)] -pub enum GenericBasicShape<Position, LengthPercentage, NonNegativeLengthPercentage, BasicShapeRect> -{ +pub enum GenericBasicShape< + Angle, + Position, + LengthPercentage, + NonNegativeLengthPercentage, + BasicShapeRect, +> { /// The <basic-shape-rect>. Rect(BasicShapeRect), /// Defines a circle with a center and a radius. @@ -199,10 +204,11 @@ pub enum GenericBasicShape<Position, LengthPercentage, NonNegativeLengthPercenta ), /// Defines a polygon with pair arguments. Polygon(GenericPolygon<LengthPercentage>), - /// Defines a path with SVG path syntax. - Path(Path), - // TODO: Bug 1823463. Add shape(). - // https://drafts.csswg.org/css-shapes-2/#shape-function + /// Defines a path() or shape(). + PathOrShape( + #[animation(field_bound)] + #[css(field_bound)] + GenericPathOrShapeFunction<Angle, LengthPercentage>), } pub use self::GenericBasicShape as BasicShape; @@ -366,6 +372,30 @@ pub use self::GenericPolygon as Polygon; #[repr(C)] pub struct PolygonCoord<LengthPercentage>(pub LengthPercentage, pub LengthPercentage); +/// path() function or shape() function. +#[derive( + Clone, + ComputeSquaredDistance, + Debug, + Deserialize, + MallocSizeOf, + PartialEq, + Serialize, + SpecifiedValueInfo, + ToAnimatedValue, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, +)] +#[repr(C, u8)] +pub enum GenericPathOrShapeFunction<Angle, LengthPercentage> { + /// Defines a path with SVG path syntax. + Path(Path), + /// Defines a shape function, which is identical to path() but it uses the CSS syntax. + Shape(#[css(field_bound)] Shape<Angle, LengthPercentage>), +} + // https://drafts.csswg.org/css-shapes/#typedef-fill-rule // NOTE: Basic shapes spec says that these are the only two values, however // https://www.w3.org/TR/SVG/painting.html#FillRuleProperty @@ -397,9 +427,9 @@ pub enum FillRule { Evenodd, } -/// The path function defined in css-shape-2. +/// The path function. /// -/// https://drafts.csswg.org/css-shapes-2/#funcdef-path +/// https://drafts.csswg.org/css-shapes-1/#funcdef-basic-shape-path #[derive( Animate, Clone, @@ -426,6 +456,14 @@ pub struct Path { pub path: SVGPathData, } +impl Path { + /// Returns the slice of PathCommand. + #[inline] + pub fn commands(&self) -> &[PathCommand] { + self.path.commands() + } +} + impl<B, U> ToAnimatedZero for ClipPath<B, U> { fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) @@ -565,3 +603,479 @@ impl Default for FillRule { fn is_default<T: Default + PartialEq>(fill: &T) -> bool { *fill == Default::default() } + +/// The shape function defined in css-shape-2. +/// shape() = shape(<fill-rule>? from <coordinate-pair>, <shape-command>#) +/// +/// https://drafts.csswg.org/css-shapes-2/#shape-function +#[derive( + Clone, + Debug, + Deserialize, + MallocSizeOf, + PartialEq, + Serialize, + SpecifiedValueInfo, + ToAnimatedValue, + ToComputedValue, + ToResolvedValue, + ToShmem, +)] +#[repr(C)] +pub struct Shape<Angle, LengthPercentage> { + /// The filling rule for this shape. + pub fill: FillRule, + /// The shape command data. Note that the starting point will be the first command in this + /// slice. + // Note: The first command is always GenericShapeCommand::Move. + pub commands: crate::OwnedSlice<GenericShapeCommand<Angle, LengthPercentage>>, +} + +impl<Angle, LengthPercentage> Shape<Angle, LengthPercentage> { + /// Returns the slice of GenericShapeCommand<..>. + #[inline] + pub fn commands(&self) -> &[GenericShapeCommand<Angle, LengthPercentage>] { + &self.commands + } +} + +impl<Angle, LengthPercentage> Animate for Shape<Angle, LengthPercentage> +where + Angle: Animate, + LengthPercentage: Animate, +{ + fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> { + if self.fill != other.fill { + return Err(()); + } + let commands = + lists::by_computed_value::animate(&self.commands, &other.commands, procedure)?; + Ok(Self { + fill: self.fill, + commands, + }) + } +} + +impl<Angle, LengthPercentage> ComputeSquaredDistance for Shape<Angle, LengthPercentage> +where + Angle: ComputeSquaredDistance, + LengthPercentage: ComputeSquaredDistance, +{ + fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { + if self.fill != other.fill { + return Err(()); + } + lists::by_computed_value::squared_distance(&self.commands, &other.commands) + } +} + +impl<Angle, LengthPercentage> ToCss for Shape<Angle, LengthPercentage> +where + Angle: ToCss + Zero, + LengthPercentage: PartialEq + ToCss, +{ + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result + where + W: Write, + { + use style_traits::values::SequenceWriter; + + // Per spec, we must have the first move command and at least one following command. + debug_assert!(self.commands.len() > 1); + + dest.write_str("shape(")?; + if !is_default(&self.fill) { + self.fill.to_css(dest)?; + dest.write_char(' ')?; + } + dest.write_str("from ")?; + match self.commands[0] { + ShapeCommand::Move { + by_to: _, + ref point, + } => point.to_css(dest)?, + _ => unreachable!("The first command must be move"), + } + dest.write_str(", ")?; + { + let mut writer = SequenceWriter::new(dest, ", "); + for command in self.commands.iter().skip(1) { + writer.item(command)?; + } + } + dest.write_char(')') + } +} + +/// This is a more general shape(path) command type, for both shape() and path(). +/// +/// https://www.w3.org/TR/SVG11/paths.html#PathData +/// https://drafts.csswg.org/css-shapes-2/#shape-function +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + Deserialize, + MallocSizeOf, + PartialEq, + Serialize, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToResolvedValue, + ToShmem, +)] +#[allow(missing_docs)] +#[repr(C, u8)] +pub enum GenericShapeCommand<Angle, LengthPercentage> { + /// The move command. + Move { + by_to: ByTo, + point: CoordinatePair<LengthPercentage>, + }, + /// The line command. + Line { + by_to: ByTo, + point: CoordinatePair<LengthPercentage>, + }, + /// The hline command. + HLine { by_to: ByTo, x: LengthPercentage }, + /// The vline command. + VLine { by_to: ByTo, y: LengthPercentage }, + /// The cubic Bézier curve command. + CubicCurve { + by_to: ByTo, + point: CoordinatePair<LengthPercentage>, + control1: CoordinatePair<LengthPercentage>, + control2: CoordinatePair<LengthPercentage>, + }, + /// The quadratic Bézier curve command. + QuadCurve { + by_to: ByTo, + point: CoordinatePair<LengthPercentage>, + control1: CoordinatePair<LengthPercentage>, + }, + /// The smooth command. + SmoothCubic { + by_to: ByTo, + point: CoordinatePair<LengthPercentage>, + control2: CoordinatePair<LengthPercentage>, + }, + /// The smooth quadratic Bézier curve command. + SmoothQuad { + by_to: ByTo, + point: CoordinatePair<LengthPercentage>, + }, + /// The arc command. + Arc { + by_to: ByTo, + point: CoordinatePair<LengthPercentage>, + radii: CoordinatePair<LengthPercentage>, + arc_sweep: ArcSweep, + arc_size: ArcSize, + rotate: Angle, + }, + /// The closepath command. + Close, +} + +pub use self::GenericShapeCommand as ShapeCommand; + +impl<Angle, LengthPercentage> ToCss for ShapeCommand<Angle, LengthPercentage> +where + Angle: ToCss + Zero, + LengthPercentage: PartialEq + ToCss, +{ + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result + where + W: fmt::Write, + { + use self::ShapeCommand::*; + match *self { + Move { by_to, ref point } => { + dest.write_str("move ")?; + by_to.to_css(dest)?; + dest.write_char(' ')?; + point.to_css(dest) + }, + Line { by_to, ref point } => { + dest.write_str("line ")?; + by_to.to_css(dest)?; + dest.write_char(' ')?; + point.to_css(dest) + }, + HLine { by_to, ref x } => { + dest.write_str("hline ")?; + by_to.to_css(dest)?; + dest.write_char(' ')?; + x.to_css(dest) + }, + VLine { by_to, ref y } => { + dest.write_str("vline ")?; + by_to.to_css(dest)?; + dest.write_char(' ')?; + y.to_css(dest) + }, + CubicCurve { + by_to, + ref point, + ref control1, + ref control2, + } => { + dest.write_str("curve ")?; + by_to.to_css(dest)?; + dest.write_char(' ')?; + point.to_css(dest)?; + dest.write_str(" via ")?; + control1.to_css(dest)?; + dest.write_char(' ')?; + control2.to_css(dest) + }, + QuadCurve { + by_to, + ref point, + ref control1, + } => { + dest.write_str("curve ")?; + by_to.to_css(dest)?; + dest.write_char(' ')?; + point.to_css(dest)?; + dest.write_str(" via ")?; + control1.to_css(dest) + }, + SmoothCubic { + by_to, + ref point, + ref control2, + } => { + dest.write_str("smooth ")?; + by_to.to_css(dest)?; + dest.write_char(' ')?; + point.to_css(dest)?; + dest.write_str(" via ")?; + control2.to_css(dest) + }, + SmoothQuad { by_to, ref point } => { + dest.write_str("smooth ")?; + by_to.to_css(dest)?; + dest.write_char(' ')?; + point.to_css(dest) + }, + Arc { + by_to, + ref point, + ref radii, + arc_sweep, + arc_size, + ref rotate, + } => { + dest.write_str("arc ")?; + by_to.to_css(dest)?; + dest.write_char(' ')?; + point.to_css(dest)?; + dest.write_str(" of ")?; + radii.x.to_css(dest)?; + if radii.x != radii.y { + dest.write_char(' ')?; + radii.y.to_css(dest)?; + } + + if matches!(arc_sweep, ArcSweep::Cw) { + dest.write_str(" cw")?; + } + + if matches!(arc_size, ArcSize::Large) { + dest.write_str(" large")?; + } + + if !rotate.is_zero() { + dest.write_str(" rotate ")?; + rotate.to_css(dest)?; + } + Ok(()) + }, + Close => dest.write_str("close"), + } + } +} + +/// This indicates the command is absolute or relative. +/// https://drafts.csswg.org/css-shapes-2/#typedef-shape-by-to +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + Deserialize, + MallocSizeOf, + Parse, + PartialEq, + Serialize, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, +)] +#[repr(u8)] +pub enum ByTo { + /// This indicates that the <coordinate-pair>s are relative to the command’s starting point. + By, + /// This relative to the top-left corner of the reference box. + To, +} + +impl ByTo { + /// Return true if it is absolute, i.e. it is To. + #[inline] + pub fn is_abs(&self) -> bool { + matches!(self, ByTo::To) + } + + /// Create ByTo based on the flag if it is absolute. + #[inline] + pub fn new(is_abs: bool) -> Self { + if is_abs { + Self::To + } else { + Self::By + } + } +} + +/// Defines a pair of coordinates, representing a rightward and downward offset, respectively, from +/// a specified reference point. Percentages are resolved against the width or height, +/// respectively, of the reference box. +/// https://drafts.csswg.org/css-shapes-2/#typedef-shape-coordinate-pair +#[allow(missing_docs)] +#[derive( + AddAssign, + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + Deserialize, + MallocSizeOf, + PartialEq, + Serialize, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, +)] +#[repr(C)] +pub struct CoordinatePair<LengthPercentage> { + pub x: LengthPercentage, + pub y: LengthPercentage, +} + +impl<LengthPercentage> CoordinatePair<LengthPercentage> { + /// Create a CoordinatePair. + #[inline] + pub fn new(x: LengthPercentage, y: LengthPercentage) -> Self { + Self { x, y } + } +} + +/// This indicates that the arc that is traced around the ellipse clockwise or counter-clockwise +/// from the center. +/// https://drafts.csswg.org/css-shapes-2/#typedef-shape-arc-sweep +#[derive( + Clone, + Copy, + Debug, + Deserialize, + FromPrimitive, + MallocSizeOf, + Parse, + PartialEq, + Serialize, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, +)] +#[repr(u8)] +pub enum ArcSweep { + /// Counter-clockwise. The default value. (This also represents 0 in the svg path.) + Ccw = 0, + /// Clockwise. (This also represents 1 in the svg path.) + Cw = 1, +} + +impl Animate for ArcSweep { + fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> { + use num_traits::FromPrimitive; + // If an arc command has different <arc-sweep> between its starting and ending list, then + // the interpolated result uses cw for any progress value between 0 and 1. + (*self as i32) + .animate(&(*other as i32), procedure) + .map(|v| ArcSweep::from_u8((v > 0) as u8).unwrap_or(ArcSweep::Ccw)) + } +} + +impl ComputeSquaredDistance for ArcSweep { + fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { + (*self as i32).compute_squared_distance(&(*other as i32)) + } +} + +/// This indicates that the larger or smaller, respectively, of the two possible arcs must be +/// chosen. +/// https://drafts.csswg.org/css-shapes-2/#typedef-shape-arc-size +#[derive( + Clone, + Copy, + Debug, + Deserialize, + FromPrimitive, + MallocSizeOf, + Parse, + PartialEq, + Serialize, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, +)] +#[repr(u8)] +pub enum ArcSize { + /// Choose the small one. The default value. (This also represents 0 in the svg path.) + Small = 0, + /// Choose the large one. (This also represents 1 in the svg path.) + Large = 1, +} + +impl Animate for ArcSize { + fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> { + use num_traits::FromPrimitive; + // If it has different <arc-size> keywords, then the interpolated result uses large for any + // progress value between 0 and 1. + (*self as i32) + .animate(&(*other as i32), procedure) + .map(|v| ArcSize::from_u8((v > 0) as u8).unwrap_or(ArcSize::Small)) + } +} + +impl ComputeSquaredDistance for ArcSize { + fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> { + (*self as i32).compute_squared_distance(&(*other as i32)) + } +} diff --git a/servo/components/style/values/generics/counters.rs b/servo/components/style/values/generics/counters.rs index 1d4518c57b..3f23c74b33 100644 --- a/servo/components/style/values/generics/counters.rs +++ b/servo/components/style/values/generics/counters.rs @@ -4,11 +4,10 @@ //! Generic types for counters-related CSS values. -#[cfg(feature = "servo-layout-2013")] +#[cfg(feature = "servo")] use crate::computed_values::list_style_type::T as ListStyleType; #[cfg(feature = "gecko")] use crate::values::generics::CounterStyle; -#[cfg(any(feature = "gecko", feature = "servo-layout-2020"))] use crate::values::specified::Attr; use crate::values::CustomIdent; use std::fmt::{self, Write}; @@ -186,13 +185,13 @@ pub struct GenericCounters<I>( ); pub use self::GenericCounters as Counters; -#[cfg(feature = "servo-layout-2013")] +#[cfg(feature = "servo")] type CounterStyleType = ListStyleType; #[cfg(feature = "gecko")] type CounterStyleType = CounterStyle; -#[cfg(feature = "servo-layout-2013")] +#[cfg(feature = "servo")] #[inline] fn is_decimal(counter_type: &CounterStyleType) -> bool { *counter_type == ListStyleType::Decimal @@ -254,11 +253,9 @@ pub enum GenericContentItem<I> { /// Literal string content. String(crate::OwnedStr), /// `counter(name, style)`. - #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))] #[css(comma, function)] Counter(CustomIdent, #[css(skip_if = "is_decimal")] CounterStyleType), /// `counters(name, separator, style)`. - #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))] #[css(comma, function)] Counters( CustomIdent, @@ -266,16 +263,12 @@ pub enum GenericContentItem<I> { #[css(skip_if = "is_decimal")] CounterStyleType, ), /// `open-quote`. - #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))] OpenQuote, /// `close-quote`. - #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))] CloseQuote, /// `no-open-quote`. - #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))] NoOpenQuote, /// `no-close-quote`. - #[cfg(any(feature = "gecko", feature = "servo-layout-2013"))] NoCloseQuote, /// `-moz-alt-content`. #[cfg(feature = "gecko")] @@ -286,7 +279,6 @@ pub enum GenericContentItem<I> { #[cfg(feature = "gecko")] MozLabelContent, /// `attr([namespace? `|`]? ident)` - #[cfg(any(feature = "gecko", feature = "servo-layout-2020"))] Attr(Attr), /// image-set(url) | url(url) Image(I), diff --git a/servo/components/style/values/generics/image.rs b/servo/components/style/values/generics/image.rs index 6fc0870e15..ca1c716052 100644 --- a/servo/components/style/values/generics/image.rs +++ b/servo/components/style/values/generics/image.rs @@ -41,7 +41,7 @@ pub enum GenericImage<G, ImageUrl, Color, Percentage, Resolution> { /// A paint worklet image. /// <https://drafts.css-houdini.org/css-paint-api/> - #[cfg(feature = "servo-layout-2013")] + #[cfg(feature = "servo")] PaintWorklet(PaintWorklet), /// A `<cross-fade()>` image. Storing this directly inside of @@ -416,7 +416,7 @@ where Image::None => dest.write_str("none"), Image::Url(ref url) => url.to_css(dest), Image::Gradient(ref gradient) => gradient.to_css(dest), - #[cfg(feature = "servo-layout-2013")] + #[cfg(feature = "servo")] Image::PaintWorklet(ref paint_worklet) => paint_worklet.to_css(dest), #[cfg(feature = "gecko")] Image::Element(ref selector) => { diff --git a/servo/components/style/values/generics/transform.rs b/servo/components/style/values/generics/transform.rs index 3a65c460a7..4d70e4465c 100644 --- a/servo/components/style/values/generics/transform.rs +++ b/servo/components/style/values/generics/transform.rs @@ -11,7 +11,6 @@ use crate::values::specified::length::Length as SpecifiedLength; use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercentage; use crate::values::{computed, CSSFloat}; use crate::{Zero, ZeroNoPercent}; -use euclid; use euclid::default::{Rect, Transform3D}; use std::fmt::{self, Write}; use style_traits::{CssWriter, ToCss}; |