From c50e892a0452e95270539811c3ff9bbb477e9321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jim=C3=A9nez=20Moreno?= Date: Wed, 26 Jul 2017 12:00:15 +0200 Subject: [PATCH] stylo: serialize radial gradients using modern unprefixed style --- components/style/gecko/conversions.rs | 2 +- components/style/values/generics/image.rs | 77 ++++++++++++++++++---- components/style/values/specified/image.rs | 11 ++-- 3 files changed, 70 insertions(+), 20 deletions(-) diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index 2426bef42dc..9e808b5c3a6 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -297,7 +297,7 @@ impl nsStyleImage { Gecko_CreateGradient(gecko_shape, gecko_size, gradient.repeating, - gradient.compat_mode != CompatMode::Modern, + false, gradient.compat_mode == CompatMode::Moz, stop_count as u32) }; diff --git a/components/style/values/generics/image.rs b/components/style/values/generics/image.rs index 874912aeaf8..7b1a182d1ab 100644 --- a/components/style/values/generics/image.rs +++ b/components/style/values/generics/image.rs @@ -7,10 +7,11 @@ //! [images]: https://drafts.csswg.org/css-images/#image-values use Atom; -use cssparser::serialize_identifier; +use cssparser::{serialize_identifier, Parser}; +use parser::{ParserContext, Parse}; +use selectors::parser::SelectorParseError; use std::fmt; -use style_traits::{HasViewportPercentage, ToCss}; -use values::computed::ComputedValueAsSpecified; +use style_traits::{HasViewportPercentage, ParseError, ToCss}; use values::specified::url::SpecifiedUrl; /// An [image]. @@ -101,16 +102,54 @@ pub enum Ellipse { } /// https://drafts.csswg.org/css-images/#typedef-extent-keyword -define_css_keyword_enum!(ShapeExtent: - "closest-side" => ClosestSide, - "farthest-side" => FarthestSide, - "closest-corner" => ClosestCorner, - "farthest-corner" => FarthestCorner, - "contain" => Contain, - "cover" => Cover -); -no_viewport_percentage!(ShapeExtent); -impl ComputedValueAsSpecified for ShapeExtent {} +#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +pub enum ShapeExtent { + /// The gradient's ending shape meets the side of the box closest to its center (for circles) or + /// meets both the vertical and horizontal sides closest to the center (for ellipses). + ClosestSide, + /// Similar to closest-side, except the ending shape is sized to meet the side of the box + /// farthest from its center (or vertical and horizontal sides). + FarthestSide, + /// The gradient's ending shape is sized so that it exactly meets the closest corner of the box + /// from its center. + ClosestCorner, + /// The gradient's ending shape is sized so that it exactly meets the closest corner of the box + /// from its center. + FarthestCorner, + /// Legacy value, equivalent to ClosestSide. + Contain, + /// Legacy value, equivalent to FarthestCorner. + Cover, +} + +impl Parse for ShapeExtent { + fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { + let ident = input.expect_ident()?; + Ok(match_ignore_ascii_case! { &ident, + "closest-side" => ShapeExtent::ClosestSide, + "farthest-side" => ShapeExtent::FarthestSide, + "closest-corner" => ShapeExtent::ClosestCorner, + "farthest-corner" => ShapeExtent::FarthestCorner, + "contain" => ShapeExtent::ClosestSide, + "cover" => ShapeExtent::FarthestCorner, + _ => return Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()), + }) + } +} + +impl ToCss for ShapeExtent { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + match *self { + ShapeExtent::ClosestSide | + ShapeExtent::Contain => dest.write_str("closest-side"), + ShapeExtent::FarthestSide => dest.write_str("farthest-side"), + ShapeExtent::ClosestCorner => dest.write_str("closest-corner"), + ShapeExtent::FarthestCorner | + ShapeExtent::Cover => dest.write_str("farthest-corner"), + } + } +} /// A gradient item. /// https://drafts.csswg.org/css-images-4/#color-stop-syntax @@ -220,7 +259,12 @@ impl ToCss for Gradient { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match self.compat_mode { - CompatMode::WebKit => dest.write_str("-webkit-")?, + CompatMode::WebKit => { + match self.kind { + GradientKind::Radial(_, _, _) => {}, + _ => dest.write_str("-webkit-")? + } + }, CompatMode::Moz => dest.write_str("-moz-")?, _ => {}, } @@ -251,6 +295,11 @@ impl ToCss for Gradient } dest.write_str("at ")?; position.to_css(dest)?; + } else if self.compat_mode == CompatMode::WebKit { + if !omit_shape { + shape.to_css(dest)?; + } + } else { position.to_css(dest)?; if let Some(ref a) = *angle { diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index 840f4ed1cf3..c8b6d45c278 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -751,7 +751,7 @@ impl EndingShape { input: &mut Parser<'i, 't>, compat_mode: CompatMode) -> Result> { - if let Ok(extent) = input.try(|i| ShapeExtent::parse_with_compat_mode(i, compat_mode)) { + if let Ok(extent) = input.try(|i| ShapeExtent::parse_with_compat_mode(context, i, compat_mode)) { if input.try(|i| i.expect_ident_matching("circle")).is_ok() { return Ok(GenericEndingShape::Circle(Circle::Extent(extent))); } @@ -759,7 +759,7 @@ impl EndingShape { return Ok(GenericEndingShape::Ellipse(Ellipse::Extent(extent))); } if input.try(|i| i.expect_ident_matching("circle")).is_ok() { - if let Ok(extent) = input.try(|i| ShapeExtent::parse_with_compat_mode(i, compat_mode)) { + if let Ok(extent) = input.try(|i| ShapeExtent::parse_with_compat_mode(context, i, compat_mode)) { return Ok(GenericEndingShape::Circle(Circle::Extent(extent))); } if compat_mode == CompatMode::Modern { @@ -770,7 +770,7 @@ impl EndingShape { return Ok(GenericEndingShape::Circle(Circle::Extent(ShapeExtent::FarthestCorner))); } if input.try(|i| i.expect_ident_matching("ellipse")).is_ok() { - if let Ok(extent) = input.try(|i| ShapeExtent::parse_with_compat_mode(i, compat_mode)) { + if let Ok(extent) = input.try(|i| ShapeExtent::parse_with_compat_mode(context, i, compat_mode)) { return Ok(GenericEndingShape::Ellipse(Ellipse::Extent(extent))); } if compat_mode == CompatMode::Modern { @@ -828,10 +828,11 @@ impl EndingShape { } impl ShapeExtent { - fn parse_with_compat_mode<'i, 't>(input: &mut Parser<'i, 't>, + fn parse_with_compat_mode<'i, 't>(context: &ParserContext, + input: &mut Parser<'i, 't>, compat_mode: CompatMode) -> Result> { - match Self::parse(input)? { + match Self::parse(context, input)? { ShapeExtent::Contain | ShapeExtent::Cover if compat_mode == CompatMode::Modern => { Err(StyleParseError::UnspecifiedError.into()) },