summaryrefslogtreecommitdiffstats
path: root/servo/components/style/values/generics
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
commitd8bbc7858622b6d9c278469aab701ca0b609cddf (patch)
treeeff41dc61d9f714852212739e6b3738b82a2af87 /servo/components/style/values/generics
parentReleasing progress-linux version 125.0.3-1~progress7.99u1. (diff)
downloadfirefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz
firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--servo/components/style/values/generics/basic_shape.rs532
-rw-r--r--servo/components/style/values/generics/counters.rs14
-rw-r--r--servo/components/style/values/generics/image.rs4
-rw-r--r--servo/components/style/values/generics/transform.rs1
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};