зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #16383 - Cleanup basic shape code (from Wafflespeanut:clean); r=emilio
<!-- Please describe your changes on the following line: --> I began with isolating serialization stuff for `BorderRadius` to help #16340 and #16352, but ended up cleaning a lot of code in `basic_shape.rs` (it's just a cleanup, should be easy to review) --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors <!-- Either: --> - [x] These changes do not require tests because it's a cleanup Source-Repo: https://github.com/servo/servo Source-Revision: a52d5fbcedfa2796cc0d30e85cd5791031747380 --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : b74345aacb8669155e5b941ee0ec240ae6ee6391
This commit is contained in:
Родитель
a81cfadca0
Коммит
b8d1d42a17
|
@ -7,14 +7,13 @@
|
|||
//!
|
||||
//! [basic-shape]: https://drafts.csswg.org/css-shapes/#typedef-basic-shape
|
||||
|
||||
use properties::shorthands::serialize_four_sides;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::computed::{BorderRadiusSize, LengthOrPercentage};
|
||||
use values::computed::position::Position;
|
||||
use values::specified::url::SpecifiedUrl;
|
||||
|
||||
pub use values::specified::basic_shape::{FillRule, GeometryBox, ShapeBox};
|
||||
pub use values::specified::basic_shape::{self, FillRule, GeometryBox, ShapeBox};
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
|
@ -209,28 +208,9 @@ pub struct BorderRadius {
|
|||
}
|
||||
|
||||
impl ToCss for BorderRadius {
|
||||
#[inline]
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
if self.top_left.0.width == self.top_left.0.height &&
|
||||
self.top_right.0.width == self.top_right.0.height &&
|
||||
self.bottom_right.0.width == self.bottom_right.0.height &&
|
||||
self.bottom_left.0.width == self.bottom_left.0.height {
|
||||
serialize_four_sides(dest,
|
||||
&self.top_left.0.width,
|
||||
&self.top_right.0.width,
|
||||
&self.bottom_right.0.width,
|
||||
&self.bottom_left.0.width)
|
||||
} else {
|
||||
try!(serialize_four_sides(dest,
|
||||
&self.top_left.0.width,
|
||||
&self.top_right.0.width,
|
||||
&self.bottom_right.0.width,
|
||||
&self.bottom_left.0.width));
|
||||
try!(dest.write_str(" / "));
|
||||
serialize_four_sides(dest,
|
||||
&self.top_left.0.height,
|
||||
&self.top_right.0.height,
|
||||
&self.bottom_right.0.height,
|
||||
&self.bottom_left.0.height)
|
||||
}
|
||||
basic_shape::serialize_radius_values(dest, &self.top_left.0, &self.top_right.0,
|
||||
&self.bottom_right.0, &self.bottom_left.0)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,27 @@ macro_rules! no_viewport_percentage {
|
|||
};
|
||||
}
|
||||
|
||||
/// A macro for implementing `ComputedValueAsSpecified`, `Parse`
|
||||
/// and `HasViewportPercentage` traits for the enums defined
|
||||
/// using `define_css_keyword_enum` macro.
|
||||
///
|
||||
/// NOTE: We should either move `Parse` trait to `style_traits`
|
||||
/// or `define_css_keyword_enum` macro to this crate, but that
|
||||
/// may involve significant cleanup in both the crates.
|
||||
macro_rules! add_impls_for_keyword_enum {
|
||||
($name:ident) => {
|
||||
impl Parse for $name {
|
||||
#[inline]
|
||||
fn parse(_context: &ParserContext, input: &mut ::cssparser::Parser) -> Result<Self, ()> {
|
||||
$name::parse(input)
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputedValueAsSpecified for $name {}
|
||||
no_viewport_percentage!($name);
|
||||
};
|
||||
}
|
||||
|
||||
pub mod computed;
|
||||
pub mod specified;
|
||||
|
||||
|
|
|
@ -8,14 +8,17 @@
|
|||
//! [basic-shape]: https://drafts.csswg.org/css-shapes/#typedef-basic-shape
|
||||
|
||||
use cssparser::Parser;
|
||||
use euclid::size::Size2D;
|
||||
use parser::{Parse, ParserContext};
|
||||
use properties::shorthands::{parse_four_sides, serialize_four_sides};
|
||||
use std::ascii::AsciiExt;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::HasViewportPercentage;
|
||||
use values::computed::{ComputedValueAsSpecified, Context, ToComputedValue};
|
||||
use values::computed::basic_shape as computed_basic_shape;
|
||||
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;
|
||||
|
||||
/// A shape source, for some reference box
|
||||
|
@ -55,36 +58,41 @@ impl<T: ToCss> ToCss for ShapeSource<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Parse + PartialEq + Copy> ShapeSource<T> {
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
if let Ok(_) = input.try(|input| input.expect_ident_matching("none")) {
|
||||
Ok(ShapeSource::None)
|
||||
} else if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
|
||||
Ok(ShapeSource::Url(url))
|
||||
} else {
|
||||
impl<T: Parse> Parse for ShapeSource<T> {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(ShapeSource::None)
|
||||
}
|
||||
|
||||
if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
|
||||
return Ok(ShapeSource::Url(url))
|
||||
}
|
||||
|
||||
fn parse_component<U: Parse>(context: &ParserContext, input: &mut Parser,
|
||||
component: &mut Option<U>) -> bool {
|
||||
if component.is_some() {
|
||||
return false; // already parsed this component
|
||||
return false // already parsed this component
|
||||
}
|
||||
|
||||
*component = input.try(|i| U::parse(context, i)).ok();
|
||||
component.is_some()
|
||||
}
|
||||
|
||||
let mut shape = None;
|
||||
let mut reference = None;
|
||||
loop {
|
||||
if !parse_component(context, input, &mut shape) &&
|
||||
!parse_component(context, input, &mut reference) {
|
||||
break;
|
||||
|
||||
while parse_component(context, input, &mut shape) ||
|
||||
parse_component(context, input, &mut reference) {
|
||||
//
|
||||
}
|
||||
|
||||
if let Some(shp) = shape {
|
||||
return Ok(ShapeSource::Shape(shp, reference))
|
||||
}
|
||||
match (shape, reference) {
|
||||
(Some(shape), _) => Ok(ShapeSource::Shape(shape, reference)),
|
||||
(None, Some(reference)) => Ok(ShapeSource::Box(reference)),
|
||||
(None, None) => Err(()),
|
||||
}
|
||||
|
||||
match reference {
|
||||
Some(r) => Ok(ShapeSource::Box(r)),
|
||||
None => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,17 +103,14 @@ impl<T: ToComputedValue> ToComputedValue for ShapeSource<T> {
|
|||
#[inline]
|
||||
fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue {
|
||||
match *self {
|
||||
ShapeSource::Url(ref url) => {
|
||||
computed_basic_shape::ShapeSource::Url(url.to_computed_value(cx))
|
||||
}
|
||||
ShapeSource::Url(ref url) => computed_basic_shape::ShapeSource::Url(url.to_computed_value(cx)),
|
||||
ShapeSource::Shape(ref shape, ref reference) => {
|
||||
computed_basic_shape::ShapeSource::Shape(
|
||||
shape.to_computed_value(cx),
|
||||
reference.as_ref().map(|ref r| r.to_computed_value(cx)))
|
||||
}
|
||||
ShapeSource::Box(ref reference) => {
|
||||
computed_basic_shape::ShapeSource::Box(reference.to_computed_value(cx))
|
||||
}
|
||||
},
|
||||
ShapeSource::Box(ref reference) =>
|
||||
computed_basic_shape::ShapeSource::Box(reference.to_computed_value(cx)),
|
||||
ShapeSource::None => computed_basic_shape::ShapeSource::None,
|
||||
}
|
||||
}
|
||||
|
@ -113,17 +118,15 @@ impl<T: ToComputedValue> ToComputedValue for ShapeSource<T> {
|
|||
#[inline]
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
match *computed {
|
||||
computed_basic_shape::ShapeSource::Url(ref url) => {
|
||||
ShapeSource::Url(SpecifiedUrl::from_computed_value(url))
|
||||
}
|
||||
computed_basic_shape::ShapeSource::Url(ref url) =>
|
||||
ShapeSource::Url(SpecifiedUrl::from_computed_value(url)),
|
||||
computed_basic_shape::ShapeSource::Shape(ref shape, ref reference) => {
|
||||
ShapeSource::Shape(
|
||||
ToComputedValue::from_computed_value(shape),
|
||||
reference.as_ref().map(|r| ToComputedValue::from_computed_value(r)))
|
||||
}
|
||||
computed_basic_shape::ShapeSource::Box(ref reference) => {
|
||||
ShapeSource::Box(ToComputedValue::from_computed_value(reference))
|
||||
}
|
||||
computed_basic_shape::ShapeSource::Box(ref reference) =>
|
||||
ShapeSource::Box(ToComputedValue::from_computed_value(reference)),
|
||||
computed_basic_shape::ShapeSource::None => ShapeSource::None,
|
||||
}
|
||||
}
|
||||
|
@ -141,23 +144,19 @@ pub enum BasicShape {
|
|||
|
||||
impl Parse for BasicShape {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<BasicShape, ()> {
|
||||
match_ignore_ascii_case! { &try!(input.expect_function()),
|
||||
"inset" => {
|
||||
Ok(BasicShape::Inset(
|
||||
try!(input.parse_nested_block(|i| InsetRect::parse_function_arguments(context, i)))))
|
||||
},
|
||||
"circle" => {
|
||||
Ok(BasicShape::Circle(
|
||||
try!(input.parse_nested_block(|i| Circle::parse_function_arguments(context, i)))))
|
||||
},
|
||||
"ellipse" => {
|
||||
Ok(BasicShape::Ellipse(
|
||||
try!(input.parse_nested_block(|i| Ellipse::parse_function_arguments(context, i)))))
|
||||
},
|
||||
"polygon" => {
|
||||
Ok(BasicShape::Polygon(
|
||||
try!(input.parse_nested_block(|i| Polygon::parse_function_arguments(context, i)))))
|
||||
},
|
||||
match_ignore_ascii_case! { &input.try(|i| i.expect_function())?,
|
||||
"inset" =>
|
||||
input.parse_nested_block(|i| InsetRect::parse_function_arguments(context, i))
|
||||
.map(BasicShape::Inset),
|
||||
"circle" =>
|
||||
input.parse_nested_block(|i| Circle::parse_function_arguments(context, i))
|
||||
.map(BasicShape::Circle),
|
||||
"ellipse" =>
|
||||
input.parse_nested_block(|i| Ellipse::parse_function_arguments(context, i))
|
||||
.map(BasicShape::Ellipse),
|
||||
"polygon" =>
|
||||
input.parse_nested_block(|i| Polygon::parse_function_arguments(context, i))
|
||||
.map(BasicShape::Polygon),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
@ -189,18 +188,14 @@ impl ToComputedValue for BasicShape {
|
|||
#[inline]
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
match *computed {
|
||||
computed_basic_shape::BasicShape::Inset(ref rect) => {
|
||||
BasicShape::Inset(ToComputedValue::from_computed_value(rect))
|
||||
}
|
||||
computed_basic_shape::BasicShape::Circle(ref 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::Polygon(ref poly) => {
|
||||
BasicShape::Polygon(ToComputedValue::from_computed_value(poly))
|
||||
}
|
||||
computed_basic_shape::BasicShape::Inset(ref rect) =>
|
||||
BasicShape::Inset(ToComputedValue::from_computed_value(rect)),
|
||||
computed_basic_shape::BasicShape::Circle(ref 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::Polygon(ref poly) =>
|
||||
BasicShape::Polygon(ToComputedValue::from_computed_value(poly)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -228,19 +223,20 @@ impl InsetRect {
|
|||
left: l,
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for InsetRect {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
match_ignore_ascii_case! { &try!(input.expect_function()),
|
||||
"inset" => {
|
||||
input.parse_nested_block(|i| InsetRect::parse_function_arguments(context, i))
|
||||
},
|
||||
match input.try(|i| i.expect_function()) {
|
||||
Ok(ref s) if s.eq_ignore_ascii_case("inset") =>
|
||||
input.parse_nested_block(|i| InsetRect::parse_function_arguments(context, i)),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
@ -261,6 +257,7 @@ impl ToCss for InsetRect {
|
|||
try!(dest.write_str(" round "));
|
||||
try!(radius.to_css(dest));
|
||||
}
|
||||
|
||||
dest.write_str(")")
|
||||
}
|
||||
}
|
||||
|
@ -297,48 +294,45 @@ impl ToComputedValue for InsetRect {
|
|||
/// are converted to percentages where possible. Only the two or four
|
||||
/// value forms are used. In case of two keyword-percentage pairs,
|
||||
/// the keywords are folded into the percentages
|
||||
fn serialize_basicshape_position<W>(position: &Position, dest: &mut W)
|
||||
-> fmt::Result where W: fmt::Write {
|
||||
use values::specified::position::Keyword;
|
||||
fn serialize_basicshape_position<W>(position: &Position, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write
|
||||
{
|
||||
// 0 length should be replaced with 0%
|
||||
fn replace_with_percent(input: LengthOrPercentage) -> LengthOrPercentage {
|
||||
match input {
|
||||
LengthOrPercentage::Length(ref l) if l.is_zero() =>
|
||||
LengthOrPercentage::Percentage(Percentage(0.0)),
|
||||
_ => input
|
||||
}
|
||||
}
|
||||
|
||||
// keyword-percentage pairs can be folded into a single percentage
|
||||
fn fold_keyword(keyword: Option<Keyword>, length: Option<LengthOrPercentage>)
|
||||
-> Option<LengthOrPercentage> {
|
||||
let none = length.is_none();
|
||||
fn fold_keyword(keyword: Option<Keyword>,
|
||||
length: Option<LengthOrPercentage>) -> Option<LengthOrPercentage> {
|
||||
let is_length_none = length.is_none();
|
||||
let pc = match length.map(replace_with_percent) {
|
||||
None => Percentage(0.0), // unspecified length = 0%
|
||||
Some(LengthOrPercentage::Percentage(pc)) => pc,
|
||||
None => Percentage(0.0), // unspecified length = 0%
|
||||
_ => return None
|
||||
};
|
||||
|
||||
let percent = match keyword {
|
||||
Some(Keyword::Center) => {
|
||||
// center cannot pair with lengths
|
||||
assert!(none);
|
||||
assert!(is_length_none); // center cannot pair with lengths
|
||||
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%
|
||||
fn replace_with_percent(input: LengthOrPercentage) -> LengthOrPercentage {
|
||||
match input {
|
||||
LengthOrPercentage::Length(ref l) if l.is_zero() => {
|
||||
LengthOrPercentage::Percentage(Percentage(0.0))
|
||||
}
|
||||
_ => {
|
||||
input
|
||||
}
|
||||
}
|
||||
Some(LengthOrPercentage::Percentage(percent))
|
||||
}
|
||||
|
||||
fn serialize_position_pair<W>(x: LengthOrPercentage, y: LengthOrPercentage,
|
||||
dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
try!(replace_with_percent(x).to_css(dest));
|
||||
try!(dest.write_str(" "));
|
||||
replace_with_percent(x).to_css(dest)?;
|
||||
dest.write_str(" ")?;
|
||||
replace_with_percent(y).to_css(dest)
|
||||
}
|
||||
|
||||
|
@ -364,12 +358,12 @@ fn serialize_basicshape_position<W>(position: &Position, dest: &mut W)
|
|||
// We failed to reduce it to a two-value form,
|
||||
// so we expand it to 4-value
|
||||
let zero = LengthOrPercentage::Percentage(Percentage(0.0));
|
||||
try!(hk.unwrap_or(Keyword::Left).to_css(dest));
|
||||
try!(dest.write_str(" "));
|
||||
try!(replace_with_percent(hp.unwrap_or(zero.clone())).to_css(dest));
|
||||
try!(dest.write_str(" "));
|
||||
try!(vk.unwrap_or(Keyword::Top).to_css(dest));
|
||||
try!(dest.write_str(" "));
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -388,22 +382,13 @@ pub struct Circle {
|
|||
impl Circle {
|
||||
#[allow(missing_docs)]
|
||||
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 position = if let Ok(_) = input.try(|input| input.expect_ident_matching("at")) {
|
||||
try!(Position::parse(context, input))
|
||||
let radius = input.try(|i| ShapeRadius::parse(context, i)).ok().unwrap_or_default();
|
||||
let position = if input.try(|i| i.expect_ident_matching("at")).is_ok() {
|
||||
Position::parse(context, input)?
|
||||
} else {
|
||||
// Defaults to origin
|
||||
Position {
|
||||
horizontal: HorizontalPosition {
|
||||
keyword: Some(Keyword::Center),
|
||||
position: None,
|
||||
},
|
||||
vertical: VerticalPosition {
|
||||
keyword: Some(Keyword::Center),
|
||||
position: None,
|
||||
},
|
||||
}
|
||||
Position::center() // Defaults to origin
|
||||
};
|
||||
|
||||
Ok(Circle {
|
||||
radius: radius,
|
||||
position: position,
|
||||
|
@ -429,6 +414,7 @@ impl ToCss for Circle {
|
|||
try!(self.radius.to_css(dest));
|
||||
try!(dest.write_str(" "));
|
||||
}
|
||||
|
||||
try!(dest.write_str("at "));
|
||||
try!(serialize_basicshape_position(&self.position, dest));
|
||||
dest.write_str(")")
|
||||
|
@ -465,28 +451,18 @@ pub struct Ellipse {
|
|||
pub position: Position,
|
||||
}
|
||||
|
||||
|
||||
impl Ellipse {
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Ellipse, ()> {
|
||||
let (a, b) = input.try(|input| -> Result<_, ()> {
|
||||
Ok((try!(ShapeRadius::parse(context, input)), try!(ShapeRadius::parse(context, input))))
|
||||
let (a, b) = input.try(|i| -> Result<_, ()> {
|
||||
Ok((ShapeRadius::parse(context, i)?, ShapeRadius::parse(context, i)?))
|
||||
}).ok().unwrap_or_default();
|
||||
let position = if let Ok(_) = input.try(|input| input.expect_ident_matching("at")) {
|
||||
try!(Position::parse(context, input))
|
||||
let position = if input.try(|i| i.expect_ident_matching("at")).is_ok() {
|
||||
Position::parse(context, input)?
|
||||
} else {
|
||||
// Defaults to origin
|
||||
Position {
|
||||
horizontal: HorizontalPosition {
|
||||
keyword: Some(Keyword::Center),
|
||||
position: None,
|
||||
},
|
||||
vertical: VerticalPosition {
|
||||
keyword: Some(Keyword::Center),
|
||||
position: None,
|
||||
},
|
||||
}
|
||||
Position::center() // Defaults to origin
|
||||
};
|
||||
|
||||
Ok(Ellipse {
|
||||
semiaxis_x: a,
|
||||
semiaxis_y: b,
|
||||
|
@ -497,10 +473,9 @@ impl Ellipse {
|
|||
|
||||
impl Parse for Ellipse {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
match_ignore_ascii_case! { &try!(input.expect_function()),
|
||||
"ellipse" => {
|
||||
input.parse_nested_block(|i| Ellipse::parse_function_arguments(context, i))
|
||||
},
|
||||
match input.try(|i| i.expect_function()) {
|
||||
Ok(ref s) if s.eq_ignore_ascii_case("ellipse") =>
|
||||
input.parse_nested_block(|i| Ellipse::parse_function_arguments(context, i)),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
@ -515,6 +490,7 @@ impl ToCss for Ellipse {
|
|||
try!(self.semiaxis_y.to_css(dest));
|
||||
try!(dest.write_str(" "));
|
||||
}
|
||||
|
||||
try!(dest.write_str("at "));
|
||||
try!(serialize_basicshape_position(&self.position, dest));
|
||||
dest.write_str(")")
|
||||
|
@ -557,15 +533,17 @@ impl Polygon {
|
|||
#[allow(missing_docs)]
|
||||
pub fn parse_function_arguments(context: &ParserContext, input: &mut Parser) -> Result<Polygon, ()> {
|
||||
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
|
||||
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,
|
||||
|
@ -575,10 +553,9 @@ impl Polygon {
|
|||
|
||||
impl Parse for Polygon {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
match_ignore_ascii_case! { &try!(input.expect_function()),
|
||||
"polygon" => {
|
||||
input.parse_nested_block(|i| Polygon::parse_function_arguments(context, i))
|
||||
},
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
@ -592,15 +569,18 @@ impl ToCss for Polygon {
|
|||
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(")")
|
||||
}
|
||||
}
|
||||
|
@ -616,8 +596,7 @@ impl ToComputedValue for Polygon {
|
|||
.map(|c| {
|
||||
(c.0.to_computed_value(cx),
|
||||
c.1.to_computed_value(cx))
|
||||
})
|
||||
.collect(),
|
||||
}).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -629,8 +608,7 @@ impl ToComputedValue for Polygon {
|
|||
.map(|c| {
|
||||
(ToComputedValue::from_computed_value(&c.0),
|
||||
ToComputedValue::from_computed_value(&c.1))
|
||||
})
|
||||
.collect(),
|
||||
}).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -647,11 +625,7 @@ pub enum ShapeRadius {
|
|||
|
||||
impl ShapeRadius {
|
||||
fn is_default(&self) -> bool {
|
||||
if let ShapeRadius::ClosestSide = *self {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
*self == ShapeRadius::ClosestSide
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -690,9 +664,8 @@ impl ToComputedValue for ShapeRadius {
|
|||
#[inline]
|
||||
fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue {
|
||||
match *self {
|
||||
ShapeRadius::Length(ref lop) => {
|
||||
computed_basic_shape::ShapeRadius::Length(lop.to_computed_value(cx))
|
||||
}
|
||||
ShapeRadius::Length(ref lop) =>
|
||||
computed_basic_shape::ShapeRadius::Length(lop.to_computed_value(cx)),
|
||||
ShapeRadius::ClosestSide => computed_basic_shape::ShapeRadius::ClosestSide,
|
||||
ShapeRadius::FarthestSide => computed_basic_shape::ShapeRadius::FarthestSide,
|
||||
}
|
||||
|
@ -701,9 +674,8 @@ impl ToComputedValue for ShapeRadius {
|
|||
#[inline]
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
match *computed {
|
||||
computed_basic_shape::ShapeRadius::Length(ref lop) => {
|
||||
ShapeRadius::Length(ToComputedValue::from_computed_value(lop))
|
||||
}
|
||||
computed_basic_shape::ShapeRadius::Length(ref lop) =>
|
||||
ShapeRadius::Length(ToComputedValue::from_computed_value(lop)),
|
||||
computed_basic_shape::ShapeRadius::ClosestSide => ShapeRadius::ClosestSide,
|
||||
computed_basic_shape::ShapeRadius::FarthestSide => ShapeRadius::FarthestSide,
|
||||
}
|
||||
|
@ -721,30 +693,41 @@ pub struct BorderRadius {
|
|||
pub bottom_left: BorderRadiusSize,
|
||||
}
|
||||
|
||||
impl ToCss for BorderRadius {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
if self.top_left.0.width == self.top_left.0.height &&
|
||||
self.top_right.0.width == self.top_right.0.height &&
|
||||
self.bottom_right.0.width == self.bottom_right.0.height &&
|
||||
self.bottom_left.0.width == self.bottom_left.0.height {
|
||||
/// Serialization helper for types of longhands like `border-radius` and `outline-radius`
|
||||
pub fn serialize_radius_values<L, W>(dest: &mut W, top_left: &Size2D<L>,
|
||||
top_right: &Size2D<L>, bottom_right: &Size2D<L>,
|
||||
bottom_left: &Size2D<L>) -> fmt::Result
|
||||
where L: ToCss + PartialEq, W: fmt::Write
|
||||
{
|
||||
if top_left.width == top_left.height &&
|
||||
top_right.width == top_right.height &&
|
||||
bottom_right.width == bottom_right.height &&
|
||||
bottom_left.width == bottom_left.height {
|
||||
serialize_four_sides(dest,
|
||||
&self.top_left.0.width,
|
||||
&self.top_right.0.width,
|
||||
&self.bottom_right.0.width,
|
||||
&self.bottom_left.0.width)
|
||||
&top_left.width,
|
||||
&top_right.width,
|
||||
&bottom_right.width,
|
||||
&bottom_left.width)
|
||||
} else {
|
||||
try!(serialize_four_sides(dest,
|
||||
&self.top_left.0.width,
|
||||
&self.top_right.0.width,
|
||||
&self.bottom_right.0.width,
|
||||
&self.bottom_left.0.width));
|
||||
try!(dest.write_str(" / "));
|
||||
serialize_four_sides(dest,
|
||||
&self.top_left.0.height,
|
||||
&self.top_right.0.height,
|
||||
&self.bottom_right.0.height,
|
||||
&self.bottom_left.0.height)
|
||||
&top_left.width,
|
||||
&top_right.width,
|
||||
&bottom_right.width,
|
||||
&bottom_left.width)?;
|
||||
dest.write_str(" / ")?;
|
||||
serialize_four_sides(dest,
|
||||
&top_left.height,
|
||||
&top_right.height,
|
||||
&bottom_right.height,
|
||||
&bottom_left.height)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for BorderRadius {
|
||||
#[inline]
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
serialize_radius_values(dest, &self.top_left.0, &self.top_right.0,
|
||||
&self.bottom_right.0, &self.bottom_left.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -815,45 +798,23 @@ impl ToComputedValue for BorderRadius {
|
|||
}
|
||||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-shapes/#typedef-fill-rule
|
||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[allow(missing_docs)]
|
||||
pub enum FillRule {
|
||||
NonZero,
|
||||
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`
|
||||
}
|
||||
// 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 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 {
|
||||
fn default() -> Self {
|
||||
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
|
||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
|
@ -866,18 +827,18 @@ pub enum GeometryBox {
|
|||
}
|
||||
|
||||
impl Parse for GeometryBox {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
if let Ok(shape_box) = input.try(|i| ShapeBox::parse(context, i)) {
|
||||
Ok(GeometryBox::ShapeBox(shape_box))
|
||||
} else {
|
||||
match_ignore_ascii_case! { &try!(input.expect_ident()),
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
if let Ok(shape_box) = input.try(|i| ShapeBox::parse(i)) {
|
||||
return Ok(GeometryBox::ShapeBox(shape_box))
|
||||
}
|
||||
|
||||
match_ignore_ascii_case! { &input.expect_ident()?,
|
||||
"fill-box" => Ok(GeometryBox::FillBox),
|
||||
"stroke-box" => Ok(GeometryBox::StrokeBox),
|
||||
"view-box" => Ok(GeometryBox::ViewBox),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for GeometryBox {
|
||||
|
@ -894,38 +855,11 @@ impl ToCss for GeometryBox {
|
|||
impl ComputedValueAsSpecified for GeometryBox {}
|
||||
|
||||
// https://drafts.csswg.org/css-shapes-1/#typedef-shape-box
|
||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[allow(missing_docs)]
|
||||
pub enum ShapeBox {
|
||||
MarginBox,
|
||||
// https://drafts.csswg.org/css-backgrounds-3/#box
|
||||
BorderBox,
|
||||
PaddingBox,
|
||||
ContentBox,
|
||||
}
|
||||
define_css_keyword_enum!(ShapeBox:
|
||||
"margin-box" => MarginBox,
|
||||
"border-box" => BorderBox,
|
||||
"padding-box" => PaddingBox,
|
||||
"content-box" => 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 {}
|
||||
add_impls_for_keyword_enum!(ShapeBox);
|
||||
|
|
Загрузка…
Ссылка в новой задаче