From 77f345476f480fe1b7e2e74cfffd4510725d866b Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 1 Aug 2016 16:10:17 +0530 Subject: [PATCH] Add Circle to basic_shape.rs --- .../style/values/computed/basic_shape.rs | 27 +++++++- .../style/values/specified/basic_shape.rs | 63 ++++++++++++++++++- components/style/values/specified/position.rs | 2 +- 3 files changed, 88 insertions(+), 4 deletions(-) diff --git a/components/style/values/computed/basic_shape.rs b/components/style/values/computed/basic_shape.rs index 462234b7b75..abf60198f7e 100644 --- a/components/style/values/computed/basic_shape.rs +++ b/components/style/values/computed/basic_shape.rs @@ -9,6 +9,7 @@ use values::computed::{Length, LengthOrPercentage}; use values::computed::BorderRadiusSize; +use values::computed::position::Position; use std::fmt; use cssparser::{self, Parser, ToCss, Token}; @@ -16,11 +17,20 @@ use cssparser::{self, Parser, ToCss, Token}; #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum BasicShape { Inset(InsetRect), - // Circle(Circle), + Circle(Circle), // Ellipse(Ellipse), // Polygon(Polygon), } +impl ToCss for BasicShape { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + match *self { + BasicShape::Inset(rect) => rect.to_css(dest), + BasicShape::Circle(circle) => circle.to_css(dest), + } + } +} + #[derive(Clone, PartialEq, Copy, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct InsetRect { @@ -50,6 +60,21 @@ impl ToCss for InsetRect { } } +#[derive(Clone, PartialEq, Copy, Debug)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +pub struct Circle { + pub radius: ShapeRadius, + pub position: Position, +} + +impl ToCss for Circle { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + try!(self.radius.to_css(dest)); + try!(dest.write_str(" at ")); + self.position.to_css(dest) + } +} + /// https://drafts.csswg.org/css-shapes/#typedef-shape-radius #[derive(Clone, PartialEq, Copy, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs index c7bd7dea837..8cba77ef412 100644 --- a/components/style/values/specified/basic_shape.rs +++ b/components/style/values/specified/basic_shape.rs @@ -16,6 +16,7 @@ use url::Url; use properties::shorthands::parse_four_sides; use values::specified::{Length, LengthOrPercentage}; use values::specified::BorderRadiusSize; +use values::specified::position::{Position, PositionComponent}; use values::computed::{Context, ToComputedValue}; use values::computed::basic_shape as computed_basic_shape; @@ -23,7 +24,7 @@ use values::computed::basic_shape as computed_basic_shape; #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum BasicShape { Inset(InsetRect), - // Circle(Circle), + Circle(Circle), // Ellipse(Ellipse), // Polygon(Polygon), } @@ -32,6 +33,8 @@ impl BasicShape { pub fn parse(input: &mut Parser) -> Result { if let Ok(result) = input.try(InsetRect::parse) { Ok(BasicShape::Inset(result)) + } else if let Ok(result) = input.try(Circle::parse) { + Ok(BasicShape::Circle(result)) } else { Err(()) } @@ -42,6 +45,7 @@ impl ToCss for BasicShape { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match *self { BasicShape::Inset(rect) => rect.to_css(dest), + BasicShape::Circle(circle) => circle.to_css(dest), } } } @@ -53,6 +57,7 @@ impl ToComputedValue for BasicShape { fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue { match *self { BasicShape::Inset(rect) => computed_basic_shape::BasicShape::Inset(rect.to_computed_value(cx)), + BasicShape::Circle(circle) => computed_basic_shape::BasicShape::Circle(circle.to_computed_value(cx)), } } } @@ -85,7 +90,7 @@ impl InsetRect { left: l, round: None, }; - if let Ok(_) = input.expect_ident_matching("round") { + if let Ok(_) = input.try(|input| input.expect_ident_matching("round")) { rect.round = Some(try!(BorderRadius::parse(input))); } Ok(rect) @@ -126,6 +131,60 @@ impl ToComputedValue for InsetRect { } } +#[derive(Clone, PartialEq, Copy, Debug)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +pub struct Circle { + pub radius: ShapeRadius, + pub position: Position, +} + +impl Circle { + pub fn parse(input: &mut Parser) -> Result { + match_ignore_ascii_case! { try!(input.expect_function()), + "circle" => { + Ok(try!(input.parse_nested_block(Circle::parse_function))) + }, + _ => Err(()) + } + } + pub fn parse_function(input: &mut Parser) -> Result { + let radius = input.try(ShapeRadius::parse).ok().unwrap_or_else(Default::default); + let position = if let Ok(_) = input.try(|input| input.expect_ident_matching("at")) { + try!(Position::parse(input)) + } else { + // Defaults to origin + try!(Position::new(PositionComponent::Center, PositionComponent::Center)) + }; + Ok(Circle { + radius: radius, + position: position, + }) + } +} + +impl ToCss for Circle { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + if ShapeRadius::ClosestSide != self.radius { + try!(self.radius.to_css(dest)); + try!(dest.write_str(" ")); + } + try!(dest.write_str("at ")); + self.position.to_css(dest) + } +} + +impl ToComputedValue for Circle { + type ComputedValue = computed_basic_shape::Circle; + + #[inline] + fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue { + computed_basic_shape::Circle { + radius: self.radius.to_computed_value(cx), + position: self.position.to_computed_value(cx), + } + } +} + /// https://drafts.csswg.org/css-shapes/#typedef-shape-radius #[derive(Clone, PartialEq, Copy, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] diff --git a/components/style/values/specified/position.rs b/components/style/values/specified/position.rs index add352491c6..13fb7d014ab 100644 --- a/components/style/values/specified/position.rs +++ b/components/style/values/specified/position.rs @@ -49,7 +49,7 @@ pub enum PositionComponent { } impl Position { - fn new(first: PositionComponent, second: PositionComponent) + pub fn new(first: PositionComponent, second: PositionComponent) -> Result { let (horiz, vert) = match (category(first), category(second)) { // Don't allow two vertical keywords or two horizontal keywords.