Skip to content

Commit

Permalink
Maintain Corner type, add None type to AngleOrCorner
Browse files Browse the repository at this point in the history
  • Loading branch information
DominoTree committed Dec 16, 2016
1 parent 0530e64 commit 5d56946
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 49 deletions.
4 changes: 2 additions & 2 deletions components/layout/display_list_builder.rs
Expand Up @@ -53,8 +53,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 util::opts;
Expand Down
5 changes: 2 additions & 3 deletions components/style/gecko/conversions.rs
Expand Up @@ -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 {
Expand Down
79 changes: 76 additions & 3 deletions components/style/values/computed/image.rs
Expand Up @@ -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;


Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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(())
}
}
}
}
2 changes: 1 addition & 1 deletion components/style/values/computed/mod.rs
Expand Up @@ -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, Time, UrlOrNone};
Expand Down
53 changes: 25 additions & 28 deletions components/style/values/specified/image.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -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("));
Expand All @@ -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(")")
Expand Down Expand Up @@ -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(())
}
}
Expand All @@ -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)]
Expand Down
19 changes: 7 additions & 12 deletions tests/unit/style/parsing/image.rs
Expand Up @@ -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)");
Expand All @@ -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]
Expand Down

0 comments on commit 5d56946

Please sign in to comment.