From a90a5cba08fdf6c0ceb95101c275108a152a3aed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 12 Jun 2024 07:35:37 +0200 Subject: Merging upstream version 127.0. Signed-off-by: Daniel Baumann --- servo/components/style/values/specified/calc.rs | 82 +++++++++++++++++-------- 1 file changed, 55 insertions(+), 27 deletions(-) (limited to 'servo/components/style/values/specified/calc.rs') diff --git a/servo/components/style/values/specified/calc.rs b/servo/components/style/values/specified/calc.rs index 17f043ac58..a354963ce1 100644 --- a/servo/components/style/values/specified/calc.rs +++ b/servo/components/style/values/specified/calc.rs @@ -6,6 +6,7 @@ //! //! [calc]: https://drafts.csswg.org/css-values/#calc-notation +use crate::color::parsing::ChannelKeyword; use crate::parser::ParserContext; use crate::values::generics::calc::{ self as generic, CalcNodeLeaf, CalcUnits, MinMaxOp, ModRemOp, PositivePercentageBasis, @@ -80,6 +81,8 @@ pub enum Leaf { Time(Time), /// `` Resolution(Resolution), + /// A component of a color. + ColorComponent(ChannelKeyword), /// `` Percentage(CSSFloat), /// `` @@ -107,6 +110,7 @@ impl ToCss for Leaf { Self::Percentage(p) => serialize_percentage(p, dest), Self::Angle(ref a) => a.to_css(dest), Self::Time(ref t) => t.to_css(dest), + Self::ColorComponent(ref s) => s.to_css(dest), } } } @@ -152,19 +156,21 @@ impl generic::CalcNodeLeaf for Leaf { Leaf::Angle(_) => CalcUnits::ANGLE, Leaf::Time(_) => CalcUnits::TIME, Leaf::Resolution(_) => CalcUnits::RESOLUTION, + Leaf::ColorComponent(_) => CalcUnits::COLOR_COMPONENT, Leaf::Percentage(_) => CalcUnits::PERCENTAGE, Leaf::Number(_) => CalcUnits::empty(), } } - fn unitless_value(&self) -> f32 { - match *self { + fn unitless_value(&self) -> Option { + Some(match *self { Self::Length(ref l) => l.unitless_value(), Self::Percentage(n) | Self::Number(n) => n, Self::Resolution(ref r) => r.dppx(), Self::Angle(ref a) => a.degrees(), Self::Time(ref t) => t.seconds(), - } + Self::ColorComponent(_) => return None, + }) } fn new_number(value: f32) -> Self { @@ -182,8 +188,8 @@ impl generic::CalcNodeLeaf for Leaf { return None; } - let self_negative = self.is_negative(); - if self_negative != other.is_negative() { + let self_negative = self.is_negative().unwrap_or(false); + if self_negative != other.is_negative().unwrap_or(false) { return Some(if self_negative { cmp::Ordering::Less } else { @@ -198,10 +204,11 @@ impl generic::CalcNodeLeaf for Leaf { (&Time(ref one), &Time(ref other)) => one.seconds().partial_cmp(&other.seconds()), (&Resolution(ref one), &Resolution(ref other)) => one.dppx().partial_cmp(&other.dppx()), (&Number(ref one), &Number(ref other)) => one.partial_cmp(other), + (&ColorComponent(ref one), &ColorComponent(ref other)) => one.partial_cmp(other), _ => { match *self { Length(..) | Percentage(..) | Angle(..) | Time(..) | Number(..) | - Resolution(..) => {}, + Resolution(..) | ColorComponent(..) => {}, } unsafe { debug_unreachable!("Forgot a branch?"); @@ -216,14 +223,15 @@ impl generic::CalcNodeLeaf for Leaf { Leaf::Angle(_) | Leaf::Time(_) | Leaf::Resolution(_) | - Leaf::Percentage(_) => None, + Leaf::Percentage(_) | + Leaf::ColorComponent(_) => None, Leaf::Number(value) => Some(value), } } fn sort_key(&self) -> SortKey { match *self { - Self::Number(..) => SortKey::Number, + Self::Number(..) | Self::ColorComponent(..) => SortKey::Number, Self::Percentage(..) => SortKey::Percentage, Self::Time(..) => SortKey::Sec, Self::Resolution(..) => SortKey::Dppx, @@ -316,7 +324,7 @@ impl generic::CalcNodeLeaf for Leaf { _ => { match *other { Number(..) | Percentage(..) | Angle(..) | Time(..) | Resolution(..) | - Length(..) => {}, + Length(..) | ColorComponent(..) => {}, } unsafe { debug_unreachable!(); @@ -336,15 +344,17 @@ impl generic::CalcNodeLeaf for Leaf { } else { // The right side is not a number, so the result should be in the units of the right // side. - other.map(|v| v * *left); - std::mem::swap(self, other); - true + if other.map(|v| v * *left).is_ok() { + std::mem::swap(self, other); + true + } else { + false + } } } else if let Self::Number(ref right) = *other { // The left side is not a number, but the right side is, so the result is the left // side unit. - self.map(|v| v * *right); - true + self.map(|v| v * *right).is_ok() } else { // Neither side is a number, so a product is not possible. false @@ -392,7 +402,7 @@ impl generic::CalcNodeLeaf for Leaf { _ => { match *other { Number(..) | Percentage(..) | Angle(..) | Time(..) | Length(..) | - Resolution(..) => {}, + Resolution(..) | ColorComponent(..) => {}, } unsafe { debug_unreachable!(); @@ -401,15 +411,16 @@ impl generic::CalcNodeLeaf for Leaf { } } - fn map(&mut self, mut op: impl FnMut(f32) -> f32) { - match self { + fn map(&mut self, mut op: impl FnMut(f32) -> f32) -> Result<(), ()> { + Ok(match self { Leaf::Length(one) => *one = one.map(op), Leaf::Angle(one) => *one = specified::Angle::from_calc(op(one.degrees())), Leaf::Time(one) => *one = specified::Time::from_seconds(op(one.seconds())), Leaf::Resolution(one) => *one = specified::Resolution::from_dppx(op(one.dppx())), Leaf::Percentage(one) => *one = op(*one), Leaf::Number(one) => *one = op(*one), - } + Leaf::ColorComponent(..) => return Err(()), + }) } } @@ -468,15 +479,30 @@ impl CalcNode { CalcNode::parse(context, input, function, allowed_units) }, &Token::Ident(ref ident) => { - let number = match_ignore_ascii_case! { &**ident, - "e" => std::f32::consts::E, - "pi" => std::f32::consts::PI, - "infinity" => f32::INFINITY, - "-infinity" => f32::NEG_INFINITY, - "nan" => f32::NAN, - _ => return Err(location.new_unexpected_token_error(Token::Ident(ident.clone()))), + let leaf = match_ignore_ascii_case! { &**ident, + "e" => Leaf::Number(std::f32::consts::E), + "pi" => Leaf::Number(std::f32::consts::PI), + "infinity" => Leaf::Number(f32::INFINITY), + "-infinity" => Leaf::Number(f32::NEG_INFINITY), + "nan" => Leaf::Number(f32::NAN), + _ => { + if crate::color::parsing::rcs_enabled() && + allowed_units.intersects(CalcUnits::COLOR_COMPONENT) + { + if let Ok(channel_keyword) = ChannelKeyword::from_ident(&ident) { + Leaf::ColorComponent(channel_keyword) + } else { + return Err(location + .new_unexpected_token_error(Token::Ident(ident.clone()))); + } + } else { + return Err( + location.new_unexpected_token_error(Token::Ident(ident.clone())) + ); + } + }, }; - Ok(CalcNode::Leaf(Leaf::Number(number))) + Ok(CalcNode::Leaf(leaf)) }, t => Err(location.new_unexpected_token_error(t.clone())), } @@ -817,7 +843,9 @@ impl CalcNode { if let Ok(resolved) = right.resolve() { if let Some(number) = resolved.as_number() { if number != 1.0 && left.is_product_distributive() { - left.map(|l| l / number); + if left.map(|l| l / number).is_err() { + return InPlaceDivisionResult::Invalid; + } return InPlaceDivisionResult::Merged; } } else { -- cgit v1.2.3