From f4b18643c2f6184a16d433e17d8de1c3e4acd663 Mon Sep 17 00:00:00 2001 From: Ravi Shankar Date: Wed, 12 Apr 2017 23:47:48 +0530 Subject: [PATCH] Cleanup Polygon and make it generic --- components/style/gecko/conversions.rs | 1 + .../style/values/computed/basic_shape.rs | 35 +----- .../style/values/generics/basic_shape.rs | 110 ++++++++++++++++- .../style/values/specified/basic_shape.rs | 113 +----------------- 4 files changed, 118 insertions(+), 141 deletions(-) diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index 26027db51b5..5f4865179ab 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -329,6 +329,7 @@ pub mod basic_shape { use values::computed::basic_shape::*; use values::computed::position; use values::generics::BorderRadiusSize as GenericBorderRadiusSize; + use values::generics::basic_shape::FillRule; // using Borrow so that we can have a non-moving .into() impl> From for BasicShape { diff --git a/components/style/values/computed/basic_shape.rs b/components/style/values/computed/basic_shape.rs index 40ad1396fe3..8c4256b5632 100644 --- a/components/style/values/computed/basic_shape.rs +++ b/components/style/values/computed/basic_shape.rs @@ -12,9 +12,11 @@ use style_traits::ToCss; use values::computed::LengthOrPercentage; use values::computed::position::Position; use values::generics::basic_shape::{BorderRadius as GenericBorderRadius, ShapeRadius as GenericShapeRadius}; +use values::generics::basic_shape::Polygon as GenericPolygon; use values::specified::url::SpecifiedUrl; -pub use values::specified::basic_shape::{self, FillRule, GeometryBox, ShapeBox}; +pub use values::generics::basic_shape::FillRule; +pub use values::specified::basic_shape::{self, GeometryBox, ShapeBox}; #[derive(Clone, PartialEq, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] @@ -141,35 +143,8 @@ impl ToCss for Ellipse { } } -#[derive(Clone, PartialEq, Debug)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[allow(missing_docs)] -/// https://drafts.csswg.org/css-shapes/#funcdef-polygon -pub struct Polygon { - pub fill: FillRule, - pub coordinates: Vec<(LengthOrPercentage, LengthOrPercentage)>, -} - -impl ToCss for Polygon { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - try!(dest.write_str("polygon(")); - let mut need_space = false; - if self.fill != Default::default() { - try!(self.fill.to_css(dest)); - try!(dest.write_str(", ")); - } - for coord in &self.coordinates { - if need_space { - try!(dest.write_str(", ")); - } - try!(coord.0.to_css(dest)); - try!(dest.write_str(" ")); - try!(coord.1.to_css(dest)); - need_space = true; - } - dest.write_str(")") - } -} +/// The computed value of `Polygon` +pub type Polygon = GenericPolygon; /// The computed value of `BorderRadius` pub type BorderRadius = GenericBorderRadius; diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs index 946d64e6d87..f7c0c0ef748 100644 --- a/components/style/values/generics/basic_shape.rs +++ b/components/style/values/generics/basic_shape.rs @@ -5,11 +5,14 @@ //! CSS handling for the [`basic-shape`](https://drafts.csswg.org/css-shapes/#typedef-basic-shape) //! types that are generic over their `ToCss` implementations. +use cssparser::Parser; use euclid::size::Size2D; +use parser::{Parse, ParserContext}; use properties::shorthands::serialize_four_sides; +use std::ascii::AsciiExt; use std::fmt; use style_traits::ToCss; -use values::computed::{Context, ToComputedValue}; +use values::computed::{ComputedValueAsSpecified, Context, ToComputedValue}; use values::generics::BorderRadiusSize; /// A generic type used for `border-radius`, `outline-radius` and `inset()` values. @@ -126,3 +129,108 @@ impl ToComputedValue for ShapeRadius { } } } + +// 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 +// says that it can also be `inherit` +define_css_keyword_enum!(FillRule: + "nonzero" => NonZero, + "evenodd" => EvenOdd +); + +impl ComputedValueAsSpecified for FillRule {} + +impl Default for FillRule { + #[inline] + fn default() -> Self { FillRule::NonZero } +} + +#[derive(Clone, PartialEq, Debug)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +/// A generic type for representing the `polygon()` function +/// +/// https://drafts.csswg.org/css-shapes/#funcdef-polygon +pub struct Polygon { + /// The filling rule for a polygon. + pub fill: FillRule, + /// A collection of (x, y) coordinates to draw the polygon. + pub coordinates: Vec<(L, L)>, +} + +impl Polygon { + /// Parse the inner arguments of a `polygon` function. + pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result { + let fill = input.try(|i| -> Result<_, ()> { + let fill = FillRule::parse(i)?; + i.expect_comma()?; // only eat the comma if there is something before it + Ok(fill) + }).ok().unwrap_or_default(); + + let buf = input.parse_comma_separated(|i| { + Ok((L::parse(context, i)?, L::parse(context, i)?)) + })?; + + Ok(Polygon { + fill: fill, + coordinates: buf, + }) + } +} + +impl Parse for Polygon { + fn parse(context: &ParserContext, input: &mut Parser) -> Result { + match input.expect_function() { + Ok(ref s) if s.eq_ignore_ascii_case("polygon") => + input.parse_nested_block(|i| Polygon::parse_function_arguments(context, i)), + _ => Err(()) + } + } +} + +impl ToCss for Polygon { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + dest.write_str("polygon(")?; + if self.fill != FillRule::default() { + self.fill.to_css(dest)?; + dest.write_str(", ")?; + } + + for (i, coord) in self.coordinates.iter().enumerate() { + if i > 0 { + dest.write_str(", ")?; + } + + coord.0.to_css(dest)?; + dest.write_str(" ")?; + coord.1.to_css(dest)?; + } + + dest.write_str(")") + } +} + +impl ToComputedValue for Polygon { + type ComputedValue = Polygon; + + #[inline] + fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue { + Polygon { + fill: self.fill.to_computed_value(cx), + coordinates: self.coordinates.iter().map(|c| { + (c.0.to_computed_value(cx), c.1.to_computed_value(cx)) + }).collect(), + } + } + + #[inline] + fn from_computed_value(computed: &Self::ComputedValue) -> Self { + Polygon { + fill: ToComputedValue::from_computed_value(&computed.fill), + coordinates: computed.coordinates.iter().map(|c| { + (ToComputedValue::from_computed_value(&c.0), + ToComputedValue::from_computed_value(&c.1)) + }).collect(), + } + } +} diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs index 6c4b9074e8a..7c75b1a1d12 100644 --- a/components/style/values/specified/basic_shape.rs +++ b/components/style/values/specified/basic_shape.rs @@ -18,6 +18,7 @@ use values::computed::{ComputedValueAsSpecified, Context, ToComputedValue}; use values::computed::basic_shape as computed_basic_shape; use values::generics::BorderRadiusSize; use values::generics::basic_shape::{BorderRadius as GenericBorderRadius, ShapeRadius as GenericShapeRadius}; +use values::generics::basic_shape::Polygon as GenericPolygon; use values::specified::{LengthOrPercentage, Percentage}; use values::specified::position::{Keyword, Position}; use values::specified::url::SpecifiedUrl; @@ -520,99 +521,8 @@ impl ToComputedValue for Ellipse { } } - -#[derive(Clone, PartialEq, Debug)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -/// https://drafts.csswg.org/css-shapes/#funcdef-polygon -#[allow(missing_docs)] -pub struct Polygon { - pub fill: FillRule, - pub coordinates: Vec<(LengthOrPercentage, LengthOrPercentage)>, -} - -impl Polygon { - #[allow(missing_docs)] - pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result { - let fill = input.try(|input| { - let fill = FillRule::parse(input); - // only eat the comma if there is something before it - try!(input.expect_comma()); - fill - }).ok().unwrap_or_else(Default::default); - - let buf = try!(input.parse_comma_separated(|input| { - Ok((try!(LengthOrPercentage::parse(context, input)), - try!(LengthOrPercentage::parse(context, input)))) - })); - - Ok(Polygon { - fill: fill, - coordinates: buf, - }) - } -} - -impl Parse for Polygon { - fn parse(context: &ParserContext, input: &mut Parser) -> Result { - match input.try(|i| i.expect_function()) { - Ok(ref s) if s.eq_ignore_ascii_case("polygon") => - input.parse_nested_block(|i| Polygon::parse_function_arguments(context, i)), - _ => Err(()) - } - } -} - -impl ToCss for Polygon { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - try!(dest.write_str("polygon(")); - let mut need_space = false; - if self.fill != Default::default() { - try!(self.fill.to_css(dest)); - try!(dest.write_str(", ")); - } - - for coord in &self.coordinates { - if need_space { - try!(dest.write_str(", ")); - } - - try!(coord.0.to_css(dest)); - try!(dest.write_str(" ")); - try!(coord.1.to_css(dest)); - need_space = true; - } - - dest.write_str(")") - } -} - -impl ToComputedValue for Polygon { - type ComputedValue = computed_basic_shape::Polygon; - - #[inline] - fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue { - computed_basic_shape::Polygon { - fill: self.fill.to_computed_value(cx), - coordinates: self.coordinates.iter() - .map(|c| { - (c.0.to_computed_value(cx), - c.1.to_computed_value(cx)) - }).collect(), - } - } - - #[inline] - fn from_computed_value(computed: &Self::ComputedValue) -> Self { - Polygon { - fill: ToComputedValue::from_computed_value(&computed.fill), - coordinates: computed.coordinates.iter() - .map(|c| { - (ToComputedValue::from_computed_value(&c.0), - ToComputedValue::from_computed_value(&c.1)) - }).collect(), - } - } -} +/// The specified value of `Polygon` +pub type Polygon = GenericPolygon; /// The specified value of `ShapeRadius` pub type ShapeRadius = GenericShapeRadius; @@ -677,23 +587,6 @@ fn parse_one_set_of_border_values(context: &ParserContext, mut input: &mut Parse } } -// 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 -// says that it can also be `inherit` -define_css_keyword_enum!(FillRule: - "nonzero" => NonZero, - "evenodd" => EvenOdd -); - -impl ComputedValueAsSpecified for FillRule {} - -impl Default for FillRule { - fn default() -> Self { - FillRule::NonZero - } -} - /// https://drafts.fxtf.org/css-masking-1/#typedef-geometry-box #[derive(Clone, PartialEq, Copy, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]