diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index cca1bd540f9..1c8fb3121b3 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -463,27 +463,22 @@ def set_gecko_property(ffi_name, expr): // set on mContextFlags, and the length field is set to the initial value. pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { - use crate::values::generics::svg::{SVGLength, SvgLengthPercentageOrNumber}; + use crate::values::generics::svg::SVGLength; use crate::gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE; let length = match v { - SVGLength::Length(length) => { + SVGLength::LengthPercentage(length) => { self.gecko.mContextFlags &= !CONTEXT_VALUE; length } SVGLength::ContextValue => { self.gecko.mContextFlags |= CONTEXT_VALUE; match longhands::${ident}::get_initial_value() { - SVGLength::Length(length) => length, + SVGLength::LengthPercentage(length) => length, _ => unreachable!("Initial value should not be context-value"), } } }; - match length { - SvgLengthPercentageOrNumber::LengthPercentage(lp) => - self.gecko.${gecko_ffi_name}.set(lp), - SvgLengthPercentageOrNumber::Number(num) => - self.gecko.${gecko_ffi_name}.set_value(CoordDataValue::Factor(num.into())), - } + self.gecko.${gecko_ffi_name}.set(length) } pub fn copy_${ident}_from(&mut self, other: &Self) { @@ -499,32 +494,16 @@ def set_gecko_property(ffi_name, expr): } pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { - use crate::values::generics::svg::{SVGLength, SvgLengthPercentageOrNumber}; + use crate::values::generics::svg::SVGLength; use crate::values::computed::LengthPercentage; use crate::gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE; if (self.gecko.mContextFlags & CONTEXT_VALUE) != 0 { return SVGLength::ContextValue; } - let length = match self.gecko.${gecko_ffi_name}.as_value() { - CoordDataValue::Factor(number) => { - SvgLengthPercentageOrNumber::Number(number) - }, - CoordDataValue::Coord(coord) => { - SvgLengthPercentageOrNumber::LengthPercentage( - LengthPercentage::new(Au(coord).into(), None) - ) - }, - CoordDataValue::Percent(p) => { - SvgLengthPercentageOrNumber::LengthPercentage( - LengthPercentage::new(Au(0).into(), Some(Percentage(p))) - ) - }, - CoordDataValue::Calc(calc) => { - SvgLengthPercentageOrNumber::LengthPercentage(calc.into()) - }, - _ => unreachable!("Unexpected coordinate in ${ident}"), - }; - SVGLength::Length(length.into()) + // TODO(emilio): Use the Rust representation instead. + let length = + LengthPercentage::from_gecko_style_coord(&self.gecko.${gecko_ffi_name}).unwrap(); + SVGLength::LengthPercentage(length.into()) } @@ -4718,7 +4697,7 @@ clip-path pub fn set_stroke_dasharray(&mut self, v: longhands::stroke_dasharray::computed_value::T) { use crate::gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE; - use crate::values::generics::svg::{SVGStrokeDashArray, SvgLengthPercentageOrNumber}; + use crate::values::generics::svg::SVGStrokeDashArray; match v { SVGStrokeDashArray::Values(v) => { @@ -4728,12 +4707,7 @@ clip-path bindings::Gecko_nsStyleSVG_SetDashArrayLength(&mut self.gecko, v.len() as u32); } for (gecko, servo) in self.gecko.mStrokeDasharray.iter_mut().zip(v) { - match servo { - SvgLengthPercentageOrNumber::LengthPercentage(lp) => - gecko.set(lp), - SvgLengthPercentageOrNumber::Number(num) => - gecko.set_value(CoordDataValue::Factor(num.into())), - } + gecko.set(servo) } } SVGStrokeDashArray::ContextValue => { @@ -4761,30 +4735,17 @@ clip-path pub fn clone_stroke_dasharray(&self) -> longhands::stroke_dasharray::computed_value::T { use crate::gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE; - use crate::values::computed::LengthPercentage; - use crate::values::generics::NonNegative; - use crate::values::generics::svg::{SVGStrokeDashArray, SvgLengthPercentageOrNumber}; + use crate::values::computed::NonNegativeLengthPercentage; + use crate::values::generics::svg::SVGStrokeDashArray; if self.gecko.mContextFlags & CONTEXT_VALUE != 0 { debug_assert_eq!(self.gecko.mStrokeDasharray.len(), 0); return SVGStrokeDashArray::ContextValue; } + // TODO(emilio): Use the rust representation instead. let mut vec = vec![]; for gecko in self.gecko.mStrokeDasharray.iter() { - match gecko.as_value() { - CoordDataValue::Factor(number) => - vec.push(SvgLengthPercentageOrNumber::Number(number.into())), - CoordDataValue::Coord(coord) => - vec.push(SvgLengthPercentageOrNumber::LengthPercentage( - NonNegative(LengthPercentage::new(Au(coord).into(), None).into()))), - CoordDataValue::Percent(p) => - vec.push(SvgLengthPercentageOrNumber::LengthPercentage( - NonNegative(LengthPercentage::new_percent(Percentage(p)).into()))), - CoordDataValue::Calc(calc) => - vec.push(SvgLengthPercentageOrNumber::LengthPercentage( - NonNegative(LengthPercentage::from(calc).clamp_to_non_negative()))), - _ => unreachable!(), - } + vec.push(NonNegativeLengthPercentage::from_gecko_style_coord(gecko).unwrap()); } SVGStrokeDashArray::Values(vec) } diff --git a/components/style/values/animated/mod.rs b/components/style/values/animated/mod.rs index 6bc7f624e34..3b83c71e6e2 100644 --- a/components/style/values/animated/mod.rs +++ b/components/style/values/animated/mod.rs @@ -16,7 +16,7 @@ use crate::values::computed::Image; use crate::values::specified::SVGPathData; use crate::values::CSSFloat; use app_units::Au; -use euclid::{Point2D, Size2D}; +use euclid::Point2D; use smallvec::SmallVec; use std::cmp; @@ -241,19 +241,6 @@ impl Animate for Au { } } -impl Animate for Size2D -where - T: Animate, -{ - #[inline] - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(Size2D::new( - self.width.animate(&other.width, procedure)?, - self.height.animate(&other.height, procedure)?, - )) - } -} - impl Animate for Point2D where T: Animate, @@ -397,16 +384,13 @@ where } } -impl ToAnimatedZero for Size2D +impl ToAnimatedZero for Vec where T: ToAnimatedZero, { #[inline] fn to_animated_zero(&self) -> Result { - Ok(Size2D::new( - self.width.to_animated_zero()?, - self.height.to_animated_zero()?, - )) + self.iter().map(|v| v.to_animated_zero()).collect() } } diff --git a/components/style/values/animated/svg.rs b/components/style/values/animated/svg.rs index 4564b787c6d..15c6580cd74 100644 --- a/components/style/values/animated/svg.rs +++ b/components/style/values/animated/svg.rs @@ -8,10 +8,8 @@ use super::{Animate, Procedure, ToAnimatedZero}; use crate::properties::animated_properties::ListAnimation; use crate::values::animated::color::Color as AnimatedColor; use crate::values::computed::url::ComputedUrl; -use crate::values::computed::{LengthPercentage, Number, NumberOrPercentage}; -use crate::values::distance::{ComputeSquaredDistance, SquaredDistance}; -use crate::values::generics::svg::{SVGLength, SVGPaint, SvgLengthPercentageOrNumber}; -use crate::values::generics::svg::{SVGOpacity, SVGStrokeDashArray}; +use crate::values::distance::{SquaredDistance, ComputeSquaredDistance}; +use crate::values::generics::svg::{SVGPaint, SVGStrokeDashArray}; /// Animated SVGPaint. pub type IntermediateSVGPaint = SVGPaint; @@ -26,67 +24,6 @@ impl ToAnimatedZero for IntermediateSVGPaint { } } -// FIXME: We need to handle calc here properly, see -// https://bugzilla.mozilla.org/show_bug.cgi?id=1386967 -fn to_number_or_percentage( - value: &SvgLengthPercentageOrNumber, -) -> Result { - Ok(match *value { - SvgLengthPercentageOrNumber::LengthPercentage(ref l) => match l.specified_percentage() { - Some(p) => { - if l.unclamped_length().px() != 0. { - return Err(()); - } - NumberOrPercentage::Percentage(p) - }, - None => NumberOrPercentage::Number(l.length().px()), - }, - SvgLengthPercentageOrNumber::Number(ref n) => NumberOrPercentage::Number(*n), - }) -} - -impl Animate for SvgLengthPercentageOrNumber { - #[inline] - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - let this = to_number_or_percentage(self)?; - let other = to_number_or_percentage(other)?; - - match (this, other) { - (NumberOrPercentage::Number(ref this), NumberOrPercentage::Number(ref other)) => Ok( - SvgLengthPercentageOrNumber::Number(this.animate(other, procedure)?), - ), - ( - NumberOrPercentage::Percentage(ref this), - NumberOrPercentage::Percentage(ref other), - ) => Ok(SvgLengthPercentageOrNumber::LengthPercentage( - LengthPercentage::new_percent(this.animate(other, procedure)?), - )), - _ => Err(()), - } - } -} - -impl ComputeSquaredDistance for SvgLengthPercentageOrNumber { - fn compute_squared_distance(&self, other: &Self) -> Result { - to_number_or_percentage(self)?.compute_squared_distance(&to_number_or_percentage(other)?) - } -} - -impl Animate for SVGLength -where - L: Animate + Clone, -{ - #[inline] - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - match (self, other) { - (&SVGLength::Length(ref this), &SVGLength::Length(ref other)) => { - Ok(SVGLength::Length(this.animate(other, procedure)?)) - }, - _ => Err(()), - } - } -} - /// impl Animate for SVGStrokeDashArray where @@ -121,36 +58,3 @@ where } } } - -impl ToAnimatedZero for SVGStrokeDashArray -where - L: ToAnimatedZero, -{ - #[inline] - fn to_animated_zero(&self) -> Result { - match *self { - SVGStrokeDashArray::Values(ref values) => Ok(SVGStrokeDashArray::Values( - values - .iter() - .map(ToAnimatedZero::to_animated_zero) - .collect::, _>>()?, - )), - SVGStrokeDashArray::ContextValue => Ok(SVGStrokeDashArray::ContextValue), - } - } -} - -impl Animate for SVGOpacity -where - O: Animate + Clone, -{ - #[inline] - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - match (self, other) { - (&SVGOpacity::Opacity(ref this), &SVGOpacity::Opacity(ref other)) => { - Ok(SVGOpacity::Opacity(this.animate(other, procedure)?)) - }, - _ => Err(()), - } - } -} diff --git a/components/style/values/computed/svg.rs b/components/style/values/computed/svg.rs index 3d47df32ab8..27d4dd6adc3 100644 --- a/components/style/values/computed/svg.rs +++ b/components/style/values/computed/svg.rs @@ -6,8 +6,7 @@ use crate::values::computed::color::Color; use crate::values::computed::url::ComputedUrl; -use crate::values::computed::{LengthPercentage, NonNegativeLengthPercentage}; -use crate::values::computed::{NonNegativeNumber, Number, Opacity}; +use crate::values::computed::{LengthPercentage, NonNegativeLengthPercentage, Opacity}; use crate::values::generics::svg as generic; use crate::values::RGBA; use crate::Zero; @@ -41,58 +40,31 @@ impl SVGPaint { } } -/// A value of | | for stroke-dashoffset. -/// -pub type SvgLengthPercentageOrNumber = - generic::SvgLengthPercentageOrNumber; - /// | | | context-value -pub type SVGLength = generic::SVGLength; +pub type SVGLength = generic::SVGLength; impl SVGLength { /// `0px` pub fn zero() -> Self { - generic::SVGLength::Length(generic::SvgLengthPercentageOrNumber::LengthPercentage( - LengthPercentage::zero(), - )) - } -} - -/// A value of | | for stroke-width/stroke-dasharray. -/// -pub type NonNegativeSvgLengthPercentageOrNumber = - generic::SvgLengthPercentageOrNumber; - -// FIXME(emilio): This is really hacky, and can go away with a bit of work on -// the clone_stroke_width code in gecko.mako.rs. -impl Into for SvgLengthPercentageOrNumber { - fn into(self) -> NonNegativeSvgLengthPercentageOrNumber { - match self { - generic::SvgLengthPercentageOrNumber::LengthPercentage(lop) => { - generic::SvgLengthPercentageOrNumber::LengthPercentage(lop.into()) - }, - generic::SvgLengthPercentageOrNumber::Number(num) => { - generic::SvgLengthPercentageOrNumber::Number(num.into()) - }, - } + generic::SVGLength::LengthPercentage(LengthPercentage::zero()) } } /// An non-negative wrapper of SVGLength. -pub type SVGWidth = generic::SVGLength; +pub type SVGWidth = generic::SVGLength; impl SVGWidth { /// `1px`. pub fn one() -> Self { use crate::values::generics::NonNegative; - generic::SVGLength::Length(generic::SvgLengthPercentageOrNumber::LengthPercentage( + generic::SVGLength::LengthPercentage( NonNegative(LengthPercentage::one()), - )) + ) } } /// [ | | ]# | context-value -pub type SVGStrokeDashArray = generic::SVGStrokeDashArray; +pub type SVGStrokeDashArray = generic::SVGStrokeDashArray; impl Default for SVGStrokeDashArray { fn default() -> Self { diff --git a/components/style/values/generics/svg.rs b/components/style/values/generics/svg.rs index 7f52126a748..6a4d2411e76 100644 --- a/components/style/values/generics/svg.rs +++ b/components/style/values/generics/svg.rs @@ -128,64 +128,26 @@ impl Parse for SVGPaint | | for svg which allow unitless length. -/// -#[derive( - Clone, - Copy, - Debug, - MallocSizeOf, - PartialEq, - Parse, - SpecifiedValueInfo, - ToAnimatedValue, - ToAnimatedZero, - ToComputedValue, - ToCss, -)] -pub enum SvgLengthPercentageOrNumber { - /// - /// - /// Note that this needs to be before, so it gets parsed before the length, - /// to handle `0` correctly as a number instead of a ``. - Number(Number), - /// | - LengthPercentage(LengthPercentage), -} - -/// Whether the `context-value` value is enabled. -#[cfg(feature = "gecko")] -pub fn is_context_value_enabled(_: &ParserContext) -> bool { - use crate::gecko_bindings::structs::mozilla; - unsafe { mozilla::StaticPrefs_sVarCache_gfx_font_rendering_opentype_svg_enabled } -} - -/// Whether the `context-value` value is enabled. -#[cfg(not(feature = "gecko"))] -pub fn is_context_value_enabled(_: &ParserContext) -> bool { - false -} - /// An SVG length value supports `context-value` in addition to length. #[derive( + Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, - Parse, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss, )] -pub enum SVGLength { +pub enum SVGLength { /// ` | | ` - Length(LengthType), + LengthPercentage(L), /// `context-value` - #[parse(condition = "is_context_value_enabled")] + #[animation(error)] ContextValue, } @@ -197,13 +159,14 @@ pub enum SVGLength { PartialEq, SpecifiedValueInfo, ToAnimatedValue, + ToAnimatedZero, ToComputedValue, ToCss, )] -pub enum SVGStrokeDashArray { +pub enum SVGStrokeDashArray { /// `[ | | ]#` #[css(comma)] - Values(#[css(if_empty = "none", iterable)] Vec), + Values(#[css(if_empty = "none", iterable)] Vec), /// `context-value` ContextValue, } @@ -211,6 +174,7 @@ pub enum SVGStrokeDashArray { /// An SVG opacity value accepts `context-{fill,stroke}-opacity` in /// addition to opacity value. #[derive( + Animate, Clone, ComputeSquaredDistance, Copy, @@ -227,7 +191,9 @@ pub enum SVGOpacity { /// `` Opacity(OpacityType), /// `context-fill-opacity` + #[animation(error)] ContextFillOpacity, /// `context-stroke-opacity` + #[animation(error)] ContextStrokeOpacity, } diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index fabc595c416..d82a3246a13 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -782,16 +782,22 @@ impl ClipRectOrAuto { /// Whether quirks are allowed in this context. #[derive(Clone, Copy, PartialEq)] pub enum AllowQuirks { - /// Quirks are allowed. - Yes, /// Quirks are not allowed. No, + /// Quirks are allowed, in quirks mode. + Yes, + /// Quirks are always allowed, used for SVG lengths. + Always, } impl AllowQuirks { /// Returns `true` if quirks are allowed in this context. pub fn allowed(self, quirks_mode: QuirksMode) -> bool { - self == AllowQuirks::Yes && quirks_mode == QuirksMode::Quirks + match self { + AllowQuirks::Always => true, + AllowQuirks::No => false, + AllowQuirks::Yes => quirks_mode == QuirksMode::Quirks, + } } } diff --git a/components/style/values/specified/svg.rs b/components/style/values/specified/svg.rs index 98db273e61c..fa54b5338b4 100644 --- a/components/style/values/specified/svg.rs +++ b/components/style/values/specified/svg.rs @@ -6,11 +6,11 @@ use crate::parser::{Parse, ParserContext}; use crate::values::generics::svg as generic; +use crate::values::specified::AllowQuirks; use crate::values::specified::color::Color; use crate::values::specified::url::SpecifiedUrl; use crate::values::specified::LengthPercentage; -use crate::values::specified::{NonNegativeLengthPercentage, NonNegativeNumber}; -use crate::values::specified::{Number, Opacity}; +use crate::values::specified::{NonNegativeLengthPercentage, Opacity}; use crate::values::CustomIdent; use cssparser::Parser; use std::fmt::{self, Write}; @@ -23,36 +23,53 @@ pub type SVGPaint = generic::SVGPaint; /// Specified SVG Paint Kind value pub type SVGPaintKind = generic::SVGPaintKind; -/// A value of | | for stroke-dashoffset. -/// -pub type SvgLengthPercentageOrNumber = - generic::SvgLengthPercentageOrNumber; - /// | | | context-value -pub type SVGLength = generic::SVGLength; - -impl From for SVGLength { - fn from(length: SvgLengthPercentageOrNumber) -> Self { - generic::SVGLength::Length(length) - } -} - -/// A value of | | for stroke-width/stroke-dasharray. -/// -pub type NonNegativeSvgLengthPercentageOrNumber = - generic::SvgLengthPercentageOrNumber; +pub type SVGLength = generic::SVGLength; /// A non-negative version of SVGLength. -pub type SVGWidth = generic::SVGLength; +pub type SVGWidth = generic::SVGLength; -impl From for SVGWidth { - fn from(length: NonNegativeSvgLengthPercentageOrNumber) -> Self { - generic::SVGLength::Length(length) +/// [ | | ]# | context-value +pub type SVGStrokeDashArray = generic::SVGStrokeDashArray; + +/// Whether the `context-value` value is enabled. +#[cfg(feature = "gecko")] +pub fn is_context_value_enabled() -> bool { + use crate::gecko_bindings::structs::mozilla; + unsafe { mozilla::StaticPrefs_sVarCache_gfx_font_rendering_opentype_svg_enabled } +} + +/// Whether the `context-value` value is enabled. +#[cfg(not(feature = "gecko"))] +pub fn is_context_value_enabled() -> bool { + false +} + +macro_rules! parse_svg_length { + ($ty:ty, $lp:ty) => { + impl Parse for $ty { + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + if let Ok(lp) = input.try(|i| { + <$lp>::parse_quirky(context, i, AllowQuirks::Always) + }) { + return Ok(generic::SVGLength::LengthPercentage(lp)) + } + + try_match_ident_ignore_ascii_case! { input, + "context-value" if is_context_value_enabled() => { + Ok(generic::SVGLength::ContextValue) + }, + } + } + } } } -/// [ | | ]# | context-value -pub type SVGStrokeDashArray = generic::SVGStrokeDashArray; +parse_svg_length!(SVGLength, LengthPercentage); +parse_svg_length!(SVGWidth, NonNegativeLengthPercentage); impl Parse for SVGStrokeDashArray { fn parse<'i, 't>( @@ -61,14 +78,18 @@ impl Parse for SVGStrokeDashArray { ) -> Result> { if let Ok(values) = input.try(|i| { CommaWithSpace::parse(i, |i| { - NonNegativeSvgLengthPercentageOrNumber::parse(context, i) + NonNegativeLengthPercentage::parse_quirky( + context, + i, + AllowQuirks::Always, + ) }) }) { return Ok(generic::SVGStrokeDashArray::Values(values)); } try_match_ident_ignore_ascii_case! { input, - "context-value" if generic::is_context_value_enabled(context) => { + "context-value" if is_context_value_enabled() => { Ok(generic::SVGStrokeDashArray::ContextValue) }, "none" => Ok(generic::SVGStrokeDashArray::Values(vec![])),