From def92d1b8e9d373e2f6f27c366d578d97d8960c6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 15 May 2024 05:34:50 +0200 Subject: Merging upstream version 126.0. Signed-off-by: Daniel Baumann --- .../style/values/computed/basic_shape.rs | 188 ++++++++++++++++++++- servo/components/style/values/computed/box.rs | 11 +- servo/components/style/values/computed/font.rs | 14 +- servo/components/style/values/computed/length.rs | 23 ++- .../style/values/computed/length_percentage.rs | 20 +++ servo/components/style/values/computed/ratio.rs | 2 +- 6 files changed, 250 insertions(+), 8 deletions(-) (limited to 'servo/components/style/values/computed') diff --git a/servo/components/style/values/computed/basic_shape.rs b/servo/components/style/values/computed/basic_shape.rs index d39110ec1c..21df7baf93 100644 --- a/servo/components/style/values/computed/basic_shape.rs +++ b/servo/components/style/values/computed/basic_shape.rs @@ -7,9 +7,12 @@ //! //! [basic-shape]: https://drafts.csswg.org/css-shapes/#typedef-basic-shape +use crate::values::animated::{Animate, Procedure}; +use crate::values::computed::angle::Angle; use crate::values::computed::url::ComputedUrl; use crate::values::computed::{Image, LengthPercentage, NonNegativeLengthPercentage, Position}; use crate::values::generics::basic_shape as generic; +use crate::values::specified::svg_path::{CoordPair, PathCommand}; /// A computed alias for FillRule. pub use crate::values::generics::basic_shape::FillRule; @@ -21,8 +24,13 @@ pub type ClipPath = generic::GenericClipPath; pub type ShapeOutside = generic::GenericShapeOutside; /// A computed basic shape. -pub type BasicShape = - generic::GenericBasicShape; +pub type BasicShape = generic::GenericBasicShape< + Angle, + Position, + LengthPercentage, + NonNegativeLengthPercentage, + InsetRect, +>; /// The computed value of `inset()`. pub type InsetRect = generic::GenericInsetRect; @@ -35,3 +43,179 @@ pub type Ellipse = generic::Ellipse; /// The computed value of `ShapeRadius`. pub type ShapeRadius = generic::GenericShapeRadius; + +/// The computed value of `shape()`. +pub type Shape = generic::Shape; + +/// The computed value of `ShapeCommand`. +pub type ShapeCommand = generic::GenericShapeCommand; + +/// The computed value of `PathOrShapeFunction`. +pub type PathOrShapeFunction = generic::GenericPathOrShapeFunction; + +/// The computed value of `CoordinatePair`. +pub type CoordinatePair = generic::CoordinatePair; + +/// Animate from `Shape` to `Path`, and vice versa. +macro_rules! animate_shape { + ( + $from:ident, + $to:ident, + $procedure:ident, + $from_as_shape:tt, + $to_as_shape:tt + ) => {{ + // Check fill-rule. + if $from.fill != $to.fill { + return Err(()); + } + + // Check the list of commands. (This is a specialized lists::by_computed_value::animate().) + let from_cmds = $from.commands(); + let to_cmds = $to.commands(); + if from_cmds.len() != to_cmds.len() { + return Err(()); + } + let commands = from_cmds + .iter() + .zip(to_cmds.iter()) + .map(|(from_cmd, to_cmd)| { + $from_as_shape(from_cmd).animate(&$to_as_shape(to_cmd), $procedure) + }) + .collect::, ()>>()?; + + Ok(Shape { + fill: $from.fill, + commands: commands.into(), + }) + }}; +} + +impl Animate for PathOrShapeFunction { + #[inline] + fn animate(&self, other: &Self, procedure: Procedure) -> Result { + // Per spec, commands are "the same" if they use the same command keyword, and use the same + // keyword. For curve and smooth, they also must have the same number of control + // points. Therefore, we don't have to do normalization here. (Note that we do + // normalization if we animate from path() to path(). See svg_path.rs for more details.) + // + // https://drafts.csswg.org/css-shapes-2/#interpolating-shape + match (self, other) { + (Self::Path(ref from), Self::Path(ref to)) => { + from.animate(to, procedure).map(Self::Path) + }, + (Self::Shape(ref from), Self::Shape(ref to)) => { + from.animate(to, procedure).map(Self::Shape) + }, + (Self::Shape(ref from), Self::Path(ref to)) => { + // Animate from shape() to path(). We convert each PathCommand into ShapeCommand, + // and return shape(). + animate_shape!( + from, + to, + procedure, + (|shape_cmd| shape_cmd), + (|path_cmd| ShapeCommand::from(path_cmd)) + ) + .map(Self::Shape) + }, + (Self::Path(ref from), Self::Shape(ref to)) => { + // Animate from path() to shape(). We convert each PathCommand into ShapeCommand, + // and return shape(). + animate_shape!( + from, + to, + procedure, + (|path_cmd| ShapeCommand::from(path_cmd)), + (|shape_cmd| shape_cmd) + ) + .map(Self::Shape) + }, + } + } +} + +impl From<&PathCommand> for ShapeCommand { + #[inline] + fn from(path: &PathCommand) -> Self { + use crate::values::computed::CSSPixelLength; + match path { + &PathCommand::Close => Self::Close, + &PathCommand::Move { by_to, ref point } => Self::Move { + by_to, + point: point.into(), + }, + &PathCommand::Line { by_to, ref point } => Self::Move { + by_to, + point: point.into(), + }, + &PathCommand::HLine { by_to, x } => Self::HLine { + by_to, + x: LengthPercentage::new_length(CSSPixelLength::new(x)), + }, + &PathCommand::VLine { by_to, y } => Self::VLine { + by_to, + y: LengthPercentage::new_length(CSSPixelLength::new(y)), + }, + &PathCommand::CubicCurve { + by_to, + ref point, + ref control1, + ref control2, + } => Self::CubicCurve { + by_to, + point: point.into(), + control1: control1.into(), + control2: control2.into(), + }, + &PathCommand::QuadCurve { + by_to, + ref point, + ref control1, + } => Self::QuadCurve { + by_to, + point: point.into(), + control1: control1.into(), + }, + &PathCommand::SmoothCubic { + by_to, + ref point, + ref control2, + } => Self::SmoothCubic { + by_to, + point: point.into(), + control2: control2.into(), + }, + &PathCommand::SmoothQuad { by_to, ref point } => Self::SmoothQuad { + by_to, + point: point.into(), + }, + &PathCommand::Arc { + by_to, + ref point, + ref radii, + arc_sweep, + arc_size, + rotate, + } => Self::Arc { + by_to, + point: point.into(), + radii: radii.into(), + arc_sweep, + arc_size, + rotate: Angle::from_degrees(rotate), + }, + } + } +} + +impl From<&CoordPair> for CoordinatePair { + #[inline] + fn from(p: &CoordPair) -> Self { + use crate::values::computed::CSSPixelLength; + Self::new( + LengthPercentage::new_length(CSSPixelLength::new(p.x)), + LengthPercentage::new_length(CSSPixelLength::new(p.y)), + ) + } +} diff --git a/servo/components/style/values/computed/box.rs b/servo/components/style/values/computed/box.rs index 62811d9851..0dea1c7ab9 100644 --- a/servo/components/style/values/computed/box.rs +++ b/servo/components/style/values/computed/box.rs @@ -383,6 +383,15 @@ impl Zoom { if self == Self::ONE { return value; } - self.value() * value + value * self.value() + } + + /// Returns the un-zoomed value. + #[inline] + pub fn unzoom(self, value: f32) -> f32 { + if self == Self::ONE { + return value; + } + value / self.value() } } diff --git a/servo/components/style/values/computed/font.rs b/servo/components/style/values/computed/font.rs index de0a5e372b..e492584f75 100644 --- a/servo/components/style/values/computed/font.rs +++ b/servo/components/style/values/computed/font.rs @@ -8,7 +8,7 @@ use crate::parser::{Parse, ParserContext}; use crate::values::animated::ToAnimatedValue; use crate::values::computed::{ Angle, Context, Integer, Length, NonNegativeLength, NonNegativeNumber, Number, Percentage, - ToComputedValue, + ToComputedValue, Zoom, }; use crate::values::generics::font::{ FeatureTagValue, FontSettings, TaggedFontValue, VariationValue, @@ -278,6 +278,16 @@ impl FontSize { self.used_size.0 } + /// Apply zoom to the font-size. This is usually done by ToComputedValue. + #[inline] + pub fn zoom(&self, zoom: Zoom) -> Self { + Self { + computed_size: NonNegative(Length::new(zoom.zoom(self.computed_size.0.px()))), + used_size: NonNegative(Length::new(zoom.zoom(self.used_size.0.px()))), + keyword_info: self.keyword_info, + } + } + #[inline] /// Get default value of font size. pub fn medium() -> Self { @@ -1359,7 +1369,7 @@ impl ToResolvedValue for LineHeight { context.style.get_font(), wm, Some(context.element_info.element), - )) + ).to_resolved_value(context)) } #[inline] diff --git a/servo/components/style/values/computed/length.rs b/servo/components/style/values/computed/length.rs index e75676a76d..881efed126 100644 --- a/servo/components/style/values/computed/length.rs +++ b/servo/components/style/values/computed/length.rs @@ -6,12 +6,13 @@ use super::{Context, Number, ToComputedValue}; use crate::values::animated::ToAnimatedValue; -use crate::values::computed::NonNegativeNumber; +use crate::values::computed::{NonNegativeNumber, Zoom}; use crate::values::generics::length as generics; use crate::values::generics::length::{ GenericLengthOrNumber, GenericLengthPercentageOrNormal, GenericMaxSize, GenericSize, }; use crate::values::generics::NonNegative; +use crate::values::resolved::{Context as ResolvedContext, ToResolvedValue}; use crate::values::specified::length::{AbsoluteLength, FontBaseSize, LineHeightBase}; use crate::values::{specified, CSSFloat}; use crate::Zero; @@ -227,12 +228,24 @@ impl Size { ToAnimatedValue, ToAnimatedZero, ToComputedValue, - ToResolvedValue, ToShmem, )] #[repr(C)] pub struct CSSPixelLength(CSSFloat); +impl ToResolvedValue for CSSPixelLength { + type ResolvedValue = Self; + + fn to_resolved_value(self, context: &ResolvedContext) -> Self::ResolvedValue { + Self(context.style.effective_zoom.unzoom(self.0)) + } + + #[inline] + fn from_resolved_value(value: Self::ResolvedValue) -> Self { + value + } +} + impl fmt::Debug for CSSPixelLength { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f)?; @@ -271,6 +284,12 @@ impl CSSPixelLength { self.0 } + /// Zooms a particular length. + #[inline] + pub fn zoom(self, zoom: Zoom) -> Self { + Self::new(zoom.zoom(self.px())) + } + /// Return the length with app_unit i32 type. #[inline] pub fn to_i32_au(self) -> i32 { diff --git a/servo/components/style/values/computed/length_percentage.rs b/servo/components/style/values/computed/length_percentage.rs index 0dbd2de76d..c448025dd1 100644 --- a/servo/components/style/values/computed/length_percentage.rs +++ b/servo/components/style/values/computed/length_percentage.rs @@ -30,6 +30,7 @@ use crate::values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZer use crate::values::distance::{ComputeSquaredDistance, SquaredDistance}; use crate::values::generics::calc::{CalcUnits, PositivePercentageBasis}; use crate::values::generics::{calc, NonNegative}; +use crate::values::resolved::{Context as ResolvedContext, ToResolvedValue}; use crate::values::specified::length::{FontBaseSize, LineHeightBase}; use crate::values::{specified, CSSFloat}; use crate::{Zero, ZeroNoPercent}; @@ -164,6 +165,25 @@ impl MallocSizeOf for LengthPercentage { } } +impl ToResolvedValue for LengthPercentage { + type ResolvedValue = Self; + + fn to_resolved_value(self, context: &ResolvedContext) -> Self::ResolvedValue { + if context.style.effective_zoom.is_one() { + return self; + } + match self.unpack() { + Unpacked::Length(l) => Self::new_length(l.to_resolved_value(context)), + Unpacked::Percentage(..) | Unpacked::Calc(..) => self, + } + } + + #[inline] + fn from_resolved_value(value: Self::ResolvedValue) -> Self { + value + } +} + /// An unpacked `` that borrows the `calc()` variant. #[derive(Clone, Debug, PartialEq, ToCss)] enum Unpacked<'a> { diff --git a/servo/components/style/values/computed/ratio.rs b/servo/components/style/values/computed/ratio.rs index ae8997cfc0..6964eec3e4 100644 --- a/servo/components/style/values/computed/ratio.rs +++ b/servo/components/style/values/computed/ratio.rs @@ -9,7 +9,7 @@ use crate::values::computed::NonNegativeNumber; use crate::values::distance::{ComputeSquaredDistance, SquaredDistance}; use crate::values::generics::ratio::Ratio as GenericRatio; use crate::{One, Zero}; -use std::cmp::{Ordering, PartialOrd}; +use std::cmp::Ordering; /// A computed value. pub type Ratio = GenericRatio; -- cgit v1.2.3