diff options
-rw-r--r-- | components/layout/display_list_builder.rs | 4 | ||||
-rw-r--r-- | components/style/gecko/conversions.rs | 5 | ||||
-rw-r--r-- | components/style/values/computed/image.rs | 79 | ||||
-rw-r--r-- | components/style/values/computed/mod.rs | 2 | ||||
-rw-r--r-- | components/style/values/specified/image.rs | 53 | ||||
-rw-r--r-- | tests/unit/style/parsing/image.rs | 19 |
6 files changed, 113 insertions, 49 deletions
diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 5f66f5f5259..be11ba66edd 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -54,8 +54,8 @@ use style::properties::{self, ServoComputedValues}; use style::properties::style_structs; use style::servo::restyle_damage::REPAINT; use style::values::{self, Either, RGBA, computed}; -use style::values::computed::{Gradient, GradientKind, LengthOrPercentage, LengthOrPercentageOrAuto}; -use style::values::specified::{AngleOrCorner, HorizontalDirection, VerticalDirection}; +use style::values::computed::{AngleOrCorner, Gradient, GradientKind, LengthOrPercentage, LengthOrPercentageOrAuto}; +use style::values::specified::{HorizontalDirection, VerticalDirection}; use style_traits::cursor::Cursor; use table_cell::CollapsedBordersForCell; use webrender_traits::{ColorF, GradientStop}; diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index e32168a436d..e336dee635e 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -160,10 +160,9 @@ impl nsStyleImage { use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE, NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE}; use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER, NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE}; use gecko_bindings::structs::nsStyleCoord; - use values::computed::{GradientKind, GradientShape, LengthOrKeyword}; + use values::computed::{AngleOrCorner, GradientKind, GradientShape, LengthOrKeyword}; use values::computed::LengthOrPercentageOrKeyword; - use values::specified::{AngleOrCorner, HorizontalDirection}; - use values::specified::{SizeKeyword, VerticalDirection}; + use values::specified::{HorizontalDirection, SizeKeyword, VerticalDirection}; let stop_count = gradient.stops.len(); if stop_count >= ::std::u32::MAX as usize { diff --git a/components/style/values/computed/image.rs b/components/style/values/computed/image.rs index f99ed74ac5e..007cbdad9df 100644 --- a/components/style/values/computed/image.rs +++ b/components/style/values/computed/image.rs @@ -8,11 +8,12 @@ //! [image]: https://drafts.csswg.org/css-images/#image-values use cssparser::Color as CSSColor; +use std::f32::consts::PI; use std::fmt; use style_traits::ToCss; -use values::computed::{Context, Length, LengthOrPercentage, ToComputedValue}; +use values::computed::{Angle, Context, Length, LengthOrPercentage, ToComputedValue}; use values::computed::position::Position; -use values::specified::{self, AngleOrCorner, SizeKeyword}; +use values::specified::{self, HorizontalDirection, SizeKeyword, VerticalDirection}; use values::specified::url::SpecifiedUrl; @@ -185,7 +186,7 @@ impl ToComputedValue for specified::GradientKind { fn to_computed_value(&self, context: &Context) -> GradientKind { match *self { specified::GradientKind::Linear(angle_or_corner) => { - GradientKind::Linear(angle_or_corner) + GradientKind::Linear(angle_or_corner.to_computed_value(context)) }, specified::GradientKind::Radial(ref shape, position) => { GradientKind::Radial(shape.to_computed_value(context), @@ -454,3 +455,75 @@ impl ToComputedValue for specified::LengthOrPercentageOrKeyword { } } } + +#[derive(Clone, Copy, Debug, PartialEq)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +pub enum AngleOrCorner { + Angle(Angle), + Corner(HorizontalDirection, VerticalDirection) +} + +impl ToComputedValue for specified::AngleOrCorner { + type ComputedValue = AngleOrCorner; + + #[inline] + fn to_computed_value(&self, _: &Context) -> AngleOrCorner { + match *self { + specified::AngleOrCorner::None => { + AngleOrCorner::Angle(Angle(0.0)) + }, + specified::AngleOrCorner::Angle(angle) => { + AngleOrCorner::Angle(angle) + }, + specified::AngleOrCorner::Corner(horizontal, vertical) => { + match (horizontal, vertical) { + (None, Some(VerticalDirection::Top)) => { + AngleOrCorner::Angle(Angle(0.0)) + }, + (Some(HorizontalDirection::Right), None) => { + AngleOrCorner::Angle(Angle(PI * 0.5)) + }, + (None, Some(VerticalDirection::Bottom)) => { + AngleOrCorner::Angle(Angle(PI)) + }, + (Some(HorizontalDirection::Left), None) => { + AngleOrCorner::Angle(Angle(PI * 1.5)) + }, + (Some(horizontal), Some(vertical)) => { + AngleOrCorner::Corner(horizontal, vertical) + }, + (None, None) => { + unreachable!() + } + } + } + } + } + + #[inline] + fn from_computed_value(computed: &AngleOrCorner) -> Self { + match *computed { + AngleOrCorner::Angle(angle) => { + specified::AngleOrCorner::Angle(angle) + }, + AngleOrCorner::Corner(horizontal, vertical) => { + specified::AngleOrCorner::Corner(Some(horizontal), Some(vertical)) + } + } + } +} + +impl ToCss for AngleOrCorner { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + match *self { + AngleOrCorner::Angle(angle) => angle.to_css(dest), + AngleOrCorner::Corner(horizontal, vertical) => { + try!(dest.write_str("to ")); + try!(horizontal.to_css(dest)); + try!(dest.write_str(" ")); + try!(vertical.to_css(dest)); + Ok(()) + } + } + } +} diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 8a31d59ce10..a22a799206f 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -11,7 +11,7 @@ use style_traits::ToCss; use super::{CSSFloat, specified}; pub use cssparser::Color as CSSColor; -pub use self::image::{EndingShape as GradientShape, Gradient, GradientKind, Image}; +pub use self::image::{AngleOrCorner, EndingShape as GradientShape, Gradient, GradientKind, Image}; pub use self::image::{LengthOrKeyword, LengthOrPercentageOrKeyword}; pub use super::{Either, None_}; pub use super::specified::{Angle, BorderStyle, GridLine, Time, UrlOrNone}; diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index 94a56d73541..479d378a680 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -10,10 +10,8 @@ use cssparser::Parser; use parser::{Parse, ParserContext}; use servo_url::ServoUrl; -use std::f32::consts::PI; use std::fmt; use style_traits::ToCss; -use values::computed::ComputedValueAsSpecified; use values::specified::{Angle, CSSColor, Length, LengthOrPercentage}; use values::specified::position::Position; use values::specified::url::{SpecifiedUrl, UrlExtraData}; @@ -70,10 +68,14 @@ impl ToCss for Gradient { if self.repeating { try!(dest.write_str("repeating-")); } + let mut skipcomma = false; match self.gradient_kind { GradientKind::Linear(angle_or_corner) => { try!(dest.write_str("linear-gradient(")); try!(angle_or_corner.to_css(dest)); + if angle_or_corner == AngleOrCorner::None { + skipcomma = true; + } }, GradientKind::Radial(ref shape, position) => { try!(dest.write_str("radial-gradient(")); @@ -83,7 +85,11 @@ impl ToCss for Gradient { }, } for stop in &self.stops { - try!(dest.write_str(", ")); + if !skipcomma { + try!(dest.write_str(", ")); + } else { + skipcomma = false; + } try!(stop.to_css(dest)); } dest.write_str(")") @@ -230,18 +236,28 @@ fn parse_position(context: &ParserContext, input: &mut Parser) -> Result<Positio #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum AngleOrCorner { Angle(Angle), - Corner(HorizontalDirection, VerticalDirection), + Corner(Option<HorizontalDirection>, Option<VerticalDirection>), + None, } impl ToCss for AngleOrCorner { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match *self { + AngleOrCorner::None => Ok(()), AngleOrCorner::Angle(angle) => angle.to_css(dest), AngleOrCorner::Corner(horizontal, vertical) => { try!(dest.write_str("to ")); - try!(horizontal.to_css(dest)); - try!(dest.write_str(" ")); - try!(vertical.to_css(dest)); + let mut horizontal_present = false; + if let Some(horizontal) = horizontal { + try!(horizontal.to_css(dest)); + horizontal_present = true; + } + if let Some(vertical) = vertical { + if horizontal_present { + try!(dest.write_str(" ")); + } + try!(vertical.to_css(dest)); + } Ok(()) } } @@ -259,35 +275,16 @@ impl Parse for AngleOrCorner { (input.try(HorizontalDirection::parse).ok(), Some(value)) }; try!(input.expect_comma()); - match (horizontal, vertical) { - (None, Some(VerticalDirection::Top)) => { - Ok(AngleOrCorner::Angle(Angle(0.0))) - }, - (Some(HorizontalDirection::Right), None) => { - Ok(AngleOrCorner::Angle(Angle(PI * 0.5))) - }, - (None, Some(VerticalDirection::Bottom)) => { - Ok(AngleOrCorner::Angle(Angle(PI))) - }, - (Some(HorizontalDirection::Left), None) => { - Ok(AngleOrCorner::Angle(Angle(PI * 1.5))) - }, - (Some(horizontal), Some(vertical)) => { - Ok(AngleOrCorner::Corner(horizontal, vertical)) - } - (None, None) => unreachable!(), - } + Ok(AngleOrCorner::Corner(horizontal, vertical)) } else if let Ok(angle) = input.try(|i| Angle::parse(context, i)) { try!(input.expect_comma()); Ok(AngleOrCorner::Angle(angle)) } else { - Ok(AngleOrCorner::Angle(Angle(PI))) + Ok(AngleOrCorner::None) } } } -impl ComputedValueAsSpecified for AngleOrCorner {} - /// Specified values for one color stop in a linear gradient. /// https://drafts.csswg.org/css-images/#typedef-color-stop-list #[derive(Clone, PartialEq, Debug)] diff --git a/tests/unit/style/parsing/image.rs b/tests/unit/style/parsing/image.rs index 5565a72dc3e..16eb63b6725 100644 --- a/tests/unit/style/parsing/image.rs +++ b/tests/unit/style/parsing/image.rs @@ -12,12 +12,10 @@ use style_traits::ToCss; #[test] fn test_linear_gradient() { // Parsing from the right - assert_roundtrip_with_context!(Image::parse, "linear-gradient(to left, red, green)", - "linear-gradient(4.712389rad, red, green)"); + assert_roundtrip_with_context!(Image::parse, "linear-gradient(to left, red, green)"); // Parsing from the left - assert_roundtrip_with_context!(Image::parse, "linear-gradient(to right, red, green)", - "linear-gradient(1.5707964rad, red, green)"); + assert_roundtrip_with_context!(Image::parse, "linear-gradient(to right, red, green)"); // Parsing with two values for <side-or-corner> assert_roundtrip_with_context!(Image::parse, "linear-gradient(to right top, red, green)"); @@ -26,17 +24,14 @@ fn test_linear_gradient() { assert_roundtrip_with_context!(Image::parse, "linear-gradient(45deg, red, green)", "linear-gradient(0.7853982rad, red, green)"); - // Parsing with more than two entries in <color-stop-list> - assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, yellow, green)", - "linear-gradient(3.1415927rad, red, yellow, green)"); + // Parsing with more than two entries in <color-stop-list> + assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, yellow, green)"); - // Parsing with percentage in the <color-stop-list> - assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, green, yellow 50%)", - "linear-gradient(3.1415927rad, red, green, yellow 50%)"); + // Parsing with percentage in the <color-stop-list> + assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, green, yellow 50%)"); // Parsing without <angle> and <side-or-corner> - assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, green)", - "linear-gradient(3.1415927rad, red, green)"); + assert_roundtrip_with_context!(Image::parse, "linear-gradient(red, green)"); } #[test] |