Cleanup specified basic shape code

This commit is contained in:
Ravi Shankar 2017-04-12 17:04:09 +05:30
parent 26fda04888
commit 6bd3469e28

View file

@ -11,12 +11,13 @@ use cssparser::Parser;
use euclid::size::Size2D; use euclid::size::Size2D;
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use properties::shorthands::{parse_four_sides, serialize_four_sides}; use properties::shorthands::{parse_four_sides, serialize_four_sides};
use std::ascii::AsciiExt;
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::computed::{ComputedValueAsSpecified, Context, ToComputedValue}; use values::computed::{ComputedValueAsSpecified, Context, ToComputedValue};
use values::computed::basic_shape as computed_basic_shape; use values::computed::basic_shape as computed_basic_shape;
use values::specified::{BorderRadiusSize, LengthOrPercentage, Percentage}; use values::specified::{BorderRadiusSize, LengthOrPercentage, Percentage};
use values::specified::position::{Keyword, Position, HorizontalPosition, VerticalPosition}; use values::specified::position::{Keyword, Position};
use values::specified::url::SpecifiedUrl; use values::specified::url::SpecifiedUrl;
/// A shape source, for some reference box /// A shape source, for some reference box
@ -56,36 +57,41 @@ impl<T: ToCss> ToCss for ShapeSource<T> {
} }
} }
impl<T: Parse + PartialEq + Copy> ShapeSource<T> { impl<T: Parse> Parse for ShapeSource<T> {
#[allow(missing_docs)] fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { if input.try(|input| input.expect_ident_matching("none")).is_ok() {
if let Ok(_) = input.try(|input| input.expect_ident_matching("none")) { return Ok(ShapeSource::None)
Ok(ShapeSource::None) }
} else if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
Ok(ShapeSource::Url(url)) if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
} else { return Ok(ShapeSource::Url(url))
fn parse_component<U: Parse>(context: &ParserContext, input: &mut Parser, }
component: &mut Option<U>) -> bool {
if component.is_some() { fn parse_component<U: Parse>(context: &ParserContext, input: &mut Parser,
return false; // already parsed this component component: &mut Option<U>) -> bool {
} if component.is_some() {
*component = input.try(|i| U::parse(context, i)).ok(); return false // already parsed this component
component.is_some()
} }
let mut shape = None; *component = input.try(|i| U::parse(context, i)).ok();
let mut reference = None; component.is_some()
loop { }
if !parse_component(context, input, &mut shape) &&
!parse_component(context, input, &mut reference) { let mut shape = None;
break; let mut reference = None;
}
} while parse_component(context, input, &mut shape) ||
match (shape, reference) { parse_component(context, input, &mut reference) {
(Some(shape), _) => Ok(ShapeSource::Shape(shape, reference)), //
(None, Some(reference)) => Ok(ShapeSource::Box(reference)), }
(None, None) => Err(()),
} if let Some(shp) = shape {
return Ok(ShapeSource::Shape(shp, reference))
}
match reference {
Some(r) => Ok(ShapeSource::Box(r)),
None => Err(())
} }
} }
} }
@ -96,17 +102,14 @@ impl<T: ToComputedValue> ToComputedValue for ShapeSource<T> {
#[inline] #[inline]
fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue { fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue {
match *self { match *self {
ShapeSource::Url(ref url) => { ShapeSource::Url(ref url) => computed_basic_shape::ShapeSource::Url(url.to_computed_value(cx)),
computed_basic_shape::ShapeSource::Url(url.to_computed_value(cx))
}
ShapeSource::Shape(ref shape, ref reference) => { ShapeSource::Shape(ref shape, ref reference) => {
computed_basic_shape::ShapeSource::Shape( computed_basic_shape::ShapeSource::Shape(
shape.to_computed_value(cx), shape.to_computed_value(cx),
reference.as_ref().map(|ref r| r.to_computed_value(cx))) reference.as_ref().map(|ref r| r.to_computed_value(cx)))
} },
ShapeSource::Box(ref reference) => { ShapeSource::Box(ref reference) =>
computed_basic_shape::ShapeSource::Box(reference.to_computed_value(cx)) computed_basic_shape::ShapeSource::Box(reference.to_computed_value(cx)),
}
ShapeSource::None => computed_basic_shape::ShapeSource::None, ShapeSource::None => computed_basic_shape::ShapeSource::None,
} }
} }
@ -114,17 +117,15 @@ impl<T: ToComputedValue> ToComputedValue for ShapeSource<T> {
#[inline] #[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self { fn from_computed_value(computed: &Self::ComputedValue) -> Self {
match *computed { match *computed {
computed_basic_shape::ShapeSource::Url(ref url) => { computed_basic_shape::ShapeSource::Url(ref url) =>
ShapeSource::Url(SpecifiedUrl::from_computed_value(url)) ShapeSource::Url(SpecifiedUrl::from_computed_value(url)),
}
computed_basic_shape::ShapeSource::Shape(ref shape, ref reference) => { computed_basic_shape::ShapeSource::Shape(ref shape, ref reference) => {
ShapeSource::Shape( ShapeSource::Shape(
ToComputedValue::from_computed_value(shape), ToComputedValue::from_computed_value(shape),
reference.as_ref().map(|r| ToComputedValue::from_computed_value(r))) reference.as_ref().map(|r| ToComputedValue::from_computed_value(r)))
} }
computed_basic_shape::ShapeSource::Box(ref reference) => { computed_basic_shape::ShapeSource::Box(ref reference) =>
ShapeSource::Box(ToComputedValue::from_computed_value(reference)) ShapeSource::Box(ToComputedValue::from_computed_value(reference)),
}
computed_basic_shape::ShapeSource::None => ShapeSource::None, computed_basic_shape::ShapeSource::None => ShapeSource::None,
} }
} }
@ -142,23 +143,19 @@ pub enum BasicShape {
impl Parse for BasicShape { impl Parse for BasicShape {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<BasicShape, ()> { fn parse(context: &ParserContext, input: &mut Parser) -> Result<BasicShape, ()> {
match_ignore_ascii_case! { &try!(input.expect_function()), match_ignore_ascii_case! { &input.try(|i| i.expect_function())?,
"inset" => { "inset" =>
Ok(BasicShape::Inset( input.parse_nested_block(|i| InsetRect::parse_function_arguments(context, i))
try!(input.parse_nested_block(|i| InsetRect::parse_function_arguments(context, i))))) .map(BasicShape::Inset),
}, "circle" =>
"circle" => { input.parse_nested_block(|i| Circle::parse_function_arguments(context, i))
Ok(BasicShape::Circle( .map(BasicShape::Circle),
try!(input.parse_nested_block(|i| Circle::parse_function_arguments(context, i))))) "ellipse" =>
}, input.parse_nested_block(|i| Ellipse::parse_function_arguments(context, i))
"ellipse" => { .map(BasicShape::Ellipse),
Ok(BasicShape::Ellipse( "polygon" =>
try!(input.parse_nested_block(|i| Ellipse::parse_function_arguments(context, i))))) input.parse_nested_block(|i| Polygon::parse_function_arguments(context, i))
}, .map(BasicShape::Polygon),
"polygon" => {
Ok(BasicShape::Polygon(
try!(input.parse_nested_block(|i| Polygon::parse_function_arguments(context, i)))))
},
_ => Err(()) _ => Err(())
} }
} }
@ -190,18 +187,14 @@ impl ToComputedValue for BasicShape {
#[inline] #[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self { fn from_computed_value(computed: &Self::ComputedValue) -> Self {
match *computed { match *computed {
computed_basic_shape::BasicShape::Inset(ref rect) => { computed_basic_shape::BasicShape::Inset(ref rect) =>
BasicShape::Inset(ToComputedValue::from_computed_value(rect)) BasicShape::Inset(ToComputedValue::from_computed_value(rect)),
} computed_basic_shape::BasicShape::Circle(ref circle) =>
computed_basic_shape::BasicShape::Circle(ref circle) => { BasicShape::Circle(ToComputedValue::from_computed_value(circle)),
BasicShape::Circle(ToComputedValue::from_computed_value(circle)) computed_basic_shape::BasicShape::Ellipse(ref e) =>
} BasicShape::Ellipse(ToComputedValue::from_computed_value(e)),
computed_basic_shape::BasicShape::Ellipse(ref e) => { computed_basic_shape::BasicShape::Polygon(ref poly) =>
BasicShape::Ellipse(ToComputedValue::from_computed_value(e)) BasicShape::Polygon(ToComputedValue::from_computed_value(poly)),
}
computed_basic_shape::BasicShape::Polygon(ref poly) => {
BasicShape::Polygon(ToComputedValue::from_computed_value(poly))
}
} }
} }
} }
@ -229,20 +222,21 @@ impl InsetRect {
left: l, left: l,
round: None, round: None,
}; };
if let Ok(_) = input.try(|input| input.expect_ident_matching("round")) {
rect.round = Some(try!(BorderRadius::parse(context, input))); if input.try(|i| i.expect_ident_matching("round")).is_ok() {
rect.round = Some(BorderRadius::parse(context, input)?);
} }
Ok(rect) Ok(rect)
} }
} }
impl Parse for InsetRect { impl Parse for InsetRect {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
match_ignore_ascii_case! { &try!(input.expect_function()), match input.try(|i| i.expect_function()) {
"inset" => { Ok(ref s) if s.eq_ignore_ascii_case("inset") =>
input.parse_nested_block(|i| InsetRect::parse_function_arguments(context, i)) input.parse_nested_block(|i| InsetRect::parse_function_arguments(context, i)),
}, _ => Err(())
_ => Err(())
} }
} }
} }
@ -262,6 +256,7 @@ impl ToCss for InsetRect {
try!(dest.write_str(" round ")); try!(dest.write_str(" round "));
try!(radius.to_css(dest)); try!(radius.to_css(dest));
} }
dest.write_str(")") dest.write_str(")")
} }
} }
@ -298,83 +293,80 @@ impl ToComputedValue for InsetRect {
/// are converted to percentages where possible. Only the two or four /// are converted to percentages where possible. Only the two or four
/// value forms are used. In case of two keyword-percentage pairs, /// value forms are used. In case of two keyword-percentage pairs,
/// the keywords are folded into the percentages /// the keywords are folded into the percentages
fn serialize_basicshape_position<W>(position: &Position, dest: &mut W) fn serialize_basicshape_position<W>(position: &Position, dest: &mut W) -> fmt::Result
-> fmt::Result where W: fmt::Write { where W: fmt::Write
use values::specified::position::Keyword; {
// 0 length should be replaced with 0%
// keyword-percentage pairs can be folded into a single percentage fn replace_with_percent(input: LengthOrPercentage) -> LengthOrPercentage {
fn fold_keyword(keyword: Option<Keyword>, length: Option<LengthOrPercentage>) match input {
-> Option<LengthOrPercentage> { LengthOrPercentage::Length(ref l) if l.is_zero() =>
let none = length.is_none(); LengthOrPercentage::Percentage(Percentage(0.0)),
let pc = match length.map(replace_with_percent) { _ => input
None => Percentage(0.0), // unspecified length = 0%
Some(LengthOrPercentage::Percentage(pc)) => pc,
_ => return None
};
let percent = match keyword {
Some(Keyword::Center) => {
// center cannot pair with lengths
assert!(none);
Percentage(0.5)
},
Some(Keyword::Left) | Some(Keyword::Top) | None => pc,
Some(Keyword::Right) | Some(Keyword::Bottom) => Percentage(1.0 - pc.0),
_ => return None,
};
Some(LengthOrPercentage::Percentage(percent))
} }
}
// 0 length should be replaced with 0% // keyword-percentage pairs can be folded into a single percentage
fn replace_with_percent(input: LengthOrPercentage) -> LengthOrPercentage { fn fold_keyword(keyword: Option<Keyword>,
match input { length: Option<LengthOrPercentage>) -> Option<LengthOrPercentage> {
LengthOrPercentage::Length(ref l) if l.is_zero() => { let is_length_none = length.is_none();
LengthOrPercentage::Percentage(Percentage(0.0)) let pc = match length.map(replace_with_percent) {
} Some(LengthOrPercentage::Percentage(pc)) => pc,
_ => { None => Percentage(0.0), // unspecified length = 0%
input _ => return None
} };
}
} let percent = match keyword {
Some(Keyword::Center) => {
fn serialize_position_pair<W>(x: LengthOrPercentage, y: LengthOrPercentage, assert!(is_length_none); // center cannot pair with lengths
dest: &mut W) -> fmt::Result where W: fmt::Write { Percentage(0.5)
try!(replace_with_percent(x).to_css(dest)); },
try!(dest.write_str(" ")); Some(Keyword::Left) | Some(Keyword::Top) | None => pc,
replace_with_percent(y).to_css(dest) Some(Keyword::Right) | Some(Keyword::Bottom) => Percentage(1.0 - pc.0),
} _ => return None,
};
match (position.horizontal.keyword, position.horizontal.position.clone(),
position.vertical.keyword, position.vertical.position.clone()) { Some(LengthOrPercentage::Percentage(percent))
(Some(hk), None, Some(vk), None) => { }
// two keywords: serialize as two lengths
serialize_position_pair(hk.to_length_or_percentage(), fn serialize_position_pair<W>(x: LengthOrPercentage, y: LengthOrPercentage,
vk.to_length_or_percentage(), dest: &mut W) -> fmt::Result where W: fmt::Write {
dest) replace_with_percent(x).to_css(dest)?;
} dest.write_str(" ")?;
(None, Some(hp), None, Some(vp)) => { replace_with_percent(y).to_css(dest)
// two lengths: just serialize regularly }
serialize_position_pair(hp, vp, dest)
} match (position.horizontal.keyword, position.horizontal.position.clone(),
(hk, hp, vk, vp) => { position.vertical.keyword, position.vertical.position.clone()) {
// only fold if both fold; the three-value form isn't (Some(hk), None, Some(vk), None) => {
// allowed here. // two keywords: serialize as two lengths
if let (Some(x), Some(y)) = (fold_keyword(hk, hp.clone()), serialize_position_pair(hk.to_length_or_percentage(),
fold_keyword(vk, vp.clone())) { vk.to_length_or_percentage(),
serialize_position_pair(x, y, dest) dest)
} else { }
// We failed to reduce it to a two-value form, (None, Some(hp), None, Some(vp)) => {
// so we expand it to 4-value // two lengths: just serialize regularly
let zero = LengthOrPercentage::Percentage(Percentage(0.0)); serialize_position_pair(hp, vp, dest)
try!(hk.unwrap_or(Keyword::Left).to_css(dest)); }
try!(dest.write_str(" ")); (hk, hp, vk, vp) => {
try!(replace_with_percent(hp.unwrap_or(zero.clone())).to_css(dest)); // only fold if both fold; the three-value form isn't
try!(dest.write_str(" ")); // allowed here.
try!(vk.unwrap_or(Keyword::Top).to_css(dest)); if let (Some(x), Some(y)) = (fold_keyword(hk, hp.clone()),
try!(dest.write_str(" ")); fold_keyword(vk, vp.clone())) {
replace_with_percent(vp.unwrap_or(zero)).to_css(dest) serialize_position_pair(x, y, dest)
} } else {
// We failed to reduce it to a two-value form,
// so we expand it to 4-value
let zero = LengthOrPercentage::Percentage(Percentage(0.0));
hk.unwrap_or(Keyword::Left).to_css(dest)?;
dest.write_str(" ")?;
replace_with_percent(hp.unwrap_or(zero.clone())).to_css(dest)?;
dest.write_str(" ")?;
vk.unwrap_or(Keyword::Top).to_css(dest)?;
dest.write_str(" ")?;
replace_with_percent(vp.unwrap_or(zero)).to_css(dest)
} }
} }
}
} }
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
@ -389,22 +381,13 @@ pub struct Circle {
impl Circle { impl Circle {
#[allow(missing_docs)] #[allow(missing_docs)]
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Circle, ()> { pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Circle, ()> {
let radius = input.try(|i| ShapeRadius::parse(context, i)).ok().unwrap_or_else(Default::default); let radius = input.try(|i| ShapeRadius::parse(context, i)).ok().unwrap_or_default();
let position = if let Ok(_) = input.try(|input| input.expect_ident_matching("at")) { let position = if input.try(|i| i.expect_ident_matching("at")).is_ok() {
try!(Position::parse(context, input)) Position::parse(context, input)?
} else { } else {
// Defaults to origin Position::center() // Defaults to origin
Position {
horizontal: HorizontalPosition {
keyword: Some(Keyword::Center),
position: None,
},
vertical: VerticalPosition {
keyword: Some(Keyword::Center),
position: None,
},
}
}; };
Ok(Circle { Ok(Circle {
radius: radius, radius: radius,
position: position, position: position,
@ -430,6 +413,7 @@ impl ToCss for Circle {
try!(self.radius.to_css(dest)); try!(self.radius.to_css(dest));
try!(dest.write_str(" ")); try!(dest.write_str(" "));
} }
try!(dest.write_str("at ")); try!(dest.write_str("at "));
try!(serialize_basicshape_position(&self.position, dest)); try!(serialize_basicshape_position(&self.position, dest));
dest.write_str(")") dest.write_str(")")
@ -466,28 +450,18 @@ pub struct Ellipse {
pub position: Position, pub position: Position,
} }
impl Ellipse { impl Ellipse {
#[allow(missing_docs)] #[allow(missing_docs)]
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Ellipse, ()> { pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Ellipse, ()> {
let (a, b) = input.try(|input| -> Result<_, ()> { let (a, b) = input.try(|i| -> Result<_, ()> {
Ok((try!(ShapeRadius::parse(context, input)), try!(ShapeRadius::parse(context, input)))) Ok((ShapeRadius::parse(context, i)?, ShapeRadius::parse(context, i)?))
}).ok().unwrap_or_default(); }).ok().unwrap_or_default();
let position = if let Ok(_) = input.try(|input| input.expect_ident_matching("at")) { let position = if input.try(|i| i.expect_ident_matching("at")).is_ok() {
try!(Position::parse(context, input)) Position::parse(context, input)?
} else { } else {
// Defaults to origin Position::center() // Defaults to origin
Position {
horizontal: HorizontalPosition {
keyword: Some(Keyword::Center),
position: None,
},
vertical: VerticalPosition {
keyword: Some(Keyword::Center),
position: None,
},
}
}; };
Ok(Ellipse { Ok(Ellipse {
semiaxis_x: a, semiaxis_x: a,
semiaxis_y: b, semiaxis_y: b,
@ -498,11 +472,10 @@ impl Ellipse {
impl Parse for Ellipse { impl Parse for Ellipse {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
match_ignore_ascii_case! { &try!(input.expect_function()), match input.try(|i| i.expect_function()) {
"ellipse" => { Ok(ref s) if s.eq_ignore_ascii_case("ellipse") =>
input.parse_nested_block(|i| Ellipse::parse_function_arguments(context, i)) input.parse_nested_block(|i| Ellipse::parse_function_arguments(context, i)),
}, _ => Err(())
_ => Err(())
} }
} }
} }
@ -516,6 +489,7 @@ impl ToCss for Ellipse {
try!(self.semiaxis_y.to_css(dest)); try!(self.semiaxis_y.to_css(dest));
try!(dest.write_str(" ")); try!(dest.write_str(" "));
} }
try!(dest.write_str("at ")); try!(dest.write_str("at "));
try!(serialize_basicshape_position(&self.position, dest)); try!(serialize_basicshape_position(&self.position, dest));
dest.write_str(")") dest.write_str(")")
@ -558,15 +532,17 @@ impl Polygon {
#[allow(missing_docs)] #[allow(missing_docs)]
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Polygon, ()> { pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Polygon, ()> {
let fill = input.try(|input| { let fill = input.try(|input| {
let fill = FillRule::parse(context, input); let fill = FillRule::parse(input);
// only eat the comma if there is something before it // only eat the comma if there is something before it
try!(input.expect_comma()); try!(input.expect_comma());
fill fill
}).ok().unwrap_or_else(Default::default); }).ok().unwrap_or_else(Default::default);
let buf = try!(input.parse_comma_separated(|input| { let buf = try!(input.parse_comma_separated(|input| {
Ok((try!(LengthOrPercentage::parse(context, input)), Ok((try!(LengthOrPercentage::parse(context, input)),
try!(LengthOrPercentage::parse(context, input)))) try!(LengthOrPercentage::parse(context, input))))
})); }));
Ok(Polygon { Ok(Polygon {
fill: fill, fill: fill,
coordinates: buf, coordinates: buf,
@ -576,11 +552,10 @@ impl Polygon {
impl Parse for Polygon { impl Parse for Polygon {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
match_ignore_ascii_case! { &try!(input.expect_function()), match input.try(|i| i.expect_function()) {
"polygon" => { Ok(ref s) if s.eq_ignore_ascii_case("polygon") =>
input.parse_nested_block(|i| Polygon::parse_function_arguments(context, i)) input.parse_nested_block(|i| Polygon::parse_function_arguments(context, i)),
}, _ => Err(())
_ => Err(())
} }
} }
} }
@ -593,15 +568,18 @@ impl ToCss for Polygon {
try!(self.fill.to_css(dest)); try!(self.fill.to_css(dest));
try!(dest.write_str(", ")); try!(dest.write_str(", "));
} }
for coord in &self.coordinates { for coord in &self.coordinates {
if need_space { if need_space {
try!(dest.write_str(", ")); try!(dest.write_str(", "));
} }
try!(coord.0.to_css(dest)); try!(coord.0.to_css(dest));
try!(dest.write_str(" ")); try!(dest.write_str(" "));
try!(coord.1.to_css(dest)); try!(coord.1.to_css(dest));
need_space = true; need_space = true;
} }
dest.write_str(")") dest.write_str(")")
} }
} }
@ -617,8 +595,7 @@ impl ToComputedValue for Polygon {
.map(|c| { .map(|c| {
(c.0.to_computed_value(cx), (c.0.to_computed_value(cx),
c.1.to_computed_value(cx)) c.1.to_computed_value(cx))
}) }).collect(),
.collect(),
} }
} }
@ -630,8 +607,7 @@ impl ToComputedValue for Polygon {
.map(|c| { .map(|c| {
(ToComputedValue::from_computed_value(&c.0), (ToComputedValue::from_computed_value(&c.0),
ToComputedValue::from_computed_value(&c.1)) ToComputedValue::from_computed_value(&c.1))
}) }).collect(),
.collect(),
} }
} }
} }
@ -648,11 +624,7 @@ pub enum ShapeRadius {
impl ShapeRadius { impl ShapeRadius {
fn is_default(&self) -> bool { fn is_default(&self) -> bool {
if let ShapeRadius::ClosestSide = *self { *self == ShapeRadius::ClosestSide
true
} else {
false
}
} }
} }
@ -691,9 +663,8 @@ impl ToComputedValue for ShapeRadius {
#[inline] #[inline]
fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue { fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue {
match *self { match *self {
ShapeRadius::Length(ref lop) => { ShapeRadius::Length(ref lop) =>
computed_basic_shape::ShapeRadius::Length(lop.to_computed_value(cx)) computed_basic_shape::ShapeRadius::Length(lop.to_computed_value(cx)),
}
ShapeRadius::ClosestSide => computed_basic_shape::ShapeRadius::ClosestSide, ShapeRadius::ClosestSide => computed_basic_shape::ShapeRadius::ClosestSide,
ShapeRadius::FarthestSide => computed_basic_shape::ShapeRadius::FarthestSide, ShapeRadius::FarthestSide => computed_basic_shape::ShapeRadius::FarthestSide,
} }
@ -702,9 +673,8 @@ impl ToComputedValue for ShapeRadius {
#[inline] #[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self { fn from_computed_value(computed: &Self::ComputedValue) -> Self {
match *computed { match *computed {
computed_basic_shape::ShapeRadius::Length(ref lop) => { computed_basic_shape::ShapeRadius::Length(ref lop) =>
ShapeRadius::Length(ToComputedValue::from_computed_value(lop)) ShapeRadius::Length(ToComputedValue::from_computed_value(lop)),
}
computed_basic_shape::ShapeRadius::ClosestSide => ShapeRadius::ClosestSide, computed_basic_shape::ShapeRadius::ClosestSide => ShapeRadius::ClosestSide,
computed_basic_shape::ShapeRadius::FarthestSide => ShapeRadius::FarthestSide, computed_basic_shape::ShapeRadius::FarthestSide => ShapeRadius::FarthestSide,
} }
@ -827,45 +797,23 @@ impl ToComputedValue for BorderRadius {
} }
} }
/// https://drafts.csswg.org/css-shapes/#typedef-fill-rule // https://drafts.csswg.org/css-shapes/#typedef-fill-rule
#[derive(Clone, PartialEq, Copy, Debug)] // NOTE: Basic shapes spec says that these are the only two values, however
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] // https://www.w3.org/TR/SVG/painting.html#FillRuleProperty
#[allow(missing_docs)] // says that it can also be `inherit`
pub enum FillRule { define_css_keyword_enum!(FillRule:
NonZero, "nonzero" => NonZero,
EvenOdd, "evenodd" => EvenOdd
// 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`
}
impl ComputedValueAsSpecified for FillRule {} impl ComputedValueAsSpecified for FillRule {}
impl Parse for FillRule {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<FillRule, ()> {
match_ignore_ascii_case! { &try!(input.expect_ident()),
"nonzero" => Ok(FillRule::NonZero),
"evenodd" => Ok(FillRule::EvenOdd),
_ => Err(())
}
}
}
impl Default for FillRule { impl Default for FillRule {
fn default() -> Self { fn default() -> Self {
FillRule::NonZero FillRule::NonZero
} }
} }
impl ToCss for FillRule {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
FillRule::NonZero => dest.write_str("nonzero"),
FillRule::EvenOdd => dest.write_str("evenodd"),
}
}
}
/// https://drafts.fxtf.org/css-masking-1/#typedef-geometry-box /// https://drafts.fxtf.org/css-masking-1/#typedef-geometry-box
#[derive(Clone, PartialEq, Copy, Debug)] #[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -878,16 +826,16 @@ pub enum GeometryBox {
} }
impl Parse for GeometryBox { impl Parse for GeometryBox {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
if let Ok(shape_box) = input.try(|i| ShapeBox::parse(context, i)) { if let Ok(shape_box) = input.try(|i| ShapeBox::parse(i)) {
Ok(GeometryBox::ShapeBox(shape_box)) return Ok(GeometryBox::ShapeBox(shape_box))
} else { }
match_ignore_ascii_case! { &try!(input.expect_ident()),
"fill-box" => Ok(GeometryBox::FillBox), match_ignore_ascii_case! { &input.expect_ident()?,
"stroke-box" => Ok(GeometryBox::StrokeBox), "fill-box" => Ok(GeometryBox::FillBox),
"view-box" => Ok(GeometryBox::ViewBox), "stroke-box" => Ok(GeometryBox::StrokeBox),
_ => Err(()) "view-box" => Ok(GeometryBox::ViewBox),
} _ => Err(())
} }
} }
} }
@ -906,38 +854,11 @@ impl ToCss for GeometryBox {
impl ComputedValueAsSpecified for GeometryBox {} impl ComputedValueAsSpecified for GeometryBox {}
// https://drafts.csswg.org/css-shapes-1/#typedef-shape-box // https://drafts.csswg.org/css-shapes-1/#typedef-shape-box
#[derive(Clone, PartialEq, Copy, Debug)] define_css_keyword_enum!(ShapeBox:
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] "margin-box" => MarginBox,
#[allow(missing_docs)] "border-box" => BorderBox,
pub enum ShapeBox { "padding-box" => PaddingBox,
MarginBox, "content-box" => ContentBox
// https://drafts.csswg.org/css-backgrounds-3/#box );
BorderBox,
PaddingBox,
ContentBox,
}
impl Parse for ShapeBox {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
match_ignore_ascii_case! { &try!(input.expect_ident()),
"margin-box" => Ok(ShapeBox::MarginBox),
"border-box" => Ok(ShapeBox::BorderBox),
"padding-box" => Ok(ShapeBox::PaddingBox),
"content-box" => Ok(ShapeBox::ContentBox),
_ => Err(())
}
}
}
impl ToCss for ShapeBox {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
ShapeBox::MarginBox => dest.write_str("margin-box"),
ShapeBox::BorderBox => dest.write_str("border-box"),
ShapeBox::PaddingBox => dest.write_str("padding-box"),
ShapeBox::ContentBox => dest.write_str("content-box"),
}
}
}
impl ComputedValueAsSpecified for ShapeBox {} impl ComputedValueAsSpecified for ShapeBox {}