diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 4b500b926aa7..ab3636fdbc50 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -1259,8 +1259,10 @@ impl FragmentDisplayListBuilding for Fragment { }; // FIXME(pcwalton, #2795): Get the real container size. - let clip_origin = Point2D::new(stacking_relative_border_box.origin.x + style_clip_rect.left, - stacking_relative_border_box.origin.y + style_clip_rect.top); + let clip_origin = Point2D::new(stacking_relative_border_box.origin.x + + style_clip_rect.left.unwrap_or(Au(0)), + stacking_relative_border_box.origin.y + + style_clip_rect.top.unwrap_or(Au(0))); let right = style_clip_rect.right.unwrap_or(stacking_relative_border_box.size.width); let bottom = style_clip_rect.bottom.unwrap_or(stacking_relative_border_box.size.height); let clip_size = Size2D::new(right - clip_origin.x, bottom - clip_origin.y); diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 37f9bf7988a7..c50c51e75b99 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -2286,8 +2286,8 @@ fn static_assert() { self.gecko.mImageRegion.height = 0; } Either::First(rect) => { - self.gecko.mImageRegion.x = rect.left.0; - self.gecko.mImageRegion.y = rect.top.0; + self.gecko.mImageRegion.x = rect.left.unwrap_or(Au(0)).0; + self.gecko.mImageRegion.y = rect.top.unwrap_or(Au(0)).0; self.gecko.mImageRegion.height = rect.bottom.unwrap_or(Au(0)).0 - self.gecko.mImageRegion.y; self.gecko.mImageRegion.width = rect.right.unwrap_or(Au(0)).0 - self.gecko.mImageRegion.x; } @@ -2356,6 +2356,8 @@ fn static_assert() { pub fn set_clip(&mut self, v: longhands::clip::computed_value::T) { use gecko_bindings::structs::NS_STYLE_CLIP_AUTO; use gecko_bindings::structs::NS_STYLE_CLIP_RECT; + use gecko_bindings::structs::NS_STYLE_CLIP_LEFT_AUTO; + use gecko_bindings::structs::NS_STYLE_CLIP_TOP_AUTO; use gecko_bindings::structs::NS_STYLE_CLIP_RIGHT_AUTO; use gecko_bindings::structs::NS_STYLE_CLIP_BOTTOM_AUTO; use values::Either; @@ -2363,8 +2365,19 @@ fn static_assert() { match v { Either::First(rect) => { self.gecko.mClipFlags = NS_STYLE_CLIP_RECT as u8; - self.gecko.mClip.x = rect.left.0; - self.gecko.mClip.y = rect.top.0; + if let Some(left) = rect.left { + self.gecko.mClip.x = left.0; + } else { + self.gecko.mClip.x = 0; + self.gecko.mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO as u8; + } + + if let Some(top) = rect.top { + self.gecko.mClip.y = top.0; + } else { + self.gecko.mClip.y = 0; + self.gecko.mClipFlags |= NS_STYLE_CLIP_TOP_AUTO as u8; + } if let Some(bottom) = rect.bottom { self.gecko.mClip.height = bottom.0 - self.gecko.mClip.y; diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index bacb11be0126..dbc537c621a3 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -294,17 +294,22 @@ pub type LoPOrNumber = Either; #[allow(missing_docs)] /// A computed cliprect for clip and image-region pub struct ClipRect { - pub top: Au, + pub top: Option, pub right: Option, pub bottom: Option, - pub left: Au, + pub left: Option, } impl ToCss for ClipRect { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { try!(dest.write_str("rect(")); - try!(self.top.to_css(dest)); - try!(dest.write_str(", ")); + if let Some(top) = self.top { + try!(top.to_css(dest)); + try!(dest.write_str(", ")); + } else { + try!(dest.write_str("auto, ")); + } + if let Some(right) = self.right { try!(right.to_css(dest)); try!(dest.write_str(", ")); @@ -319,7 +324,11 @@ impl ToCss for ClipRect { try!(dest.write_str("auto, ")); } - try!(self.left.to_css(dest)); + if let Some(left) = self.left { + try!(left.to_css(dest)); + } else { + try!(dest.write_str("auto")); + } dest.write_str(")") } } diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 1d58af7cf068..d440636138c4 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -849,10 +849,10 @@ impl LoPOrNumber { impl HasViewportPercentage for ClipRect { fn has_viewport_percentage(&self) -> bool { - self.top.has_viewport_percentage() || + self.top.as_ref().map_or(false, |x| x.has_viewport_percentage()) || self.right.as_ref().map_or(false, |x| x.has_viewport_percentage()) || self.bottom.as_ref().map_or(false, |x| x.has_viewport_percentage()) || - self.left.has_viewport_percentage() + self.left.as_ref().map_or(false, |x| x.has_viewport_percentage()) } } @@ -860,14 +860,14 @@ impl HasViewportPercentage for ClipRect { #[cfg_attr(feature = "servo", derive(HeapSizeOf))] /// rect(, , , ) used by clip and image-region pub struct ClipRect { - /// ( | ). Auto maps to 0 - pub top: Length, + /// ( | ) + pub top: Option, /// ( | ) pub right: Option, /// ( | ) pub bottom: Option, - /// ( | ). Auto maps to 0 - pub left: Length, + /// ( | ) + pub left: Option, } @@ -875,8 +875,12 @@ impl ToCss for ClipRect { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { try!(dest.write_str("rect(")); - try!(self.top.to_css(dest)); - try!(dest.write_str(", ")); + if let Some(ref top) = self.top { + try!(top.to_css(dest)); + try!(dest.write_str(", ")); + } else { + try!(dest.write_str("auto, ")); + } if let Some(ref right) = self.right { try!(right.to_css(dest)); @@ -892,7 +896,11 @@ impl ToCss for ClipRect { try!(dest.write_str("auto, ")); } - try!(self.left.to_css(dest)); + if let Some(ref left) = self.left { + try!(left.to_css(dest)); + } else { + try!(dest.write_str("auto")); + } try!(dest.write_str(")")); Ok(()) @@ -905,20 +913,20 @@ impl ToComputedValue for ClipRect { #[inline] fn to_computed_value(&self, context: &Context) -> super::computed::ClipRect { super::computed::ClipRect { - top: self.top.to_computed_value(context), + top: self.top.as_ref().map(|top| top.to_computed_value(context)), right: self.right.as_ref().map(|right| right.to_computed_value(context)), bottom: self.bottom.as_ref().map(|bottom| bottom.to_computed_value(context)), - left: self.left.to_computed_value(context), + left: self.left.as_ref().map(|left| left.to_computed_value(context)), } } #[inline] fn from_computed_value(computed: &super::computed::ClipRect) -> Self { ClipRect { - top: ToComputedValue::from_computed_value(&computed.top), + top: computed.top.map(|top| ToComputedValue::from_computed_value(&top)), right: computed.right.map(|right| ToComputedValue::from_computed_value(&right)), bottom: computed.bottom.map(|bottom| ToComputedValue::from_computed_value(&bottom)), - left: ToComputedValue::from_computed_value(&computed.left), + left: computed.left.map(|left| ToComputedValue::from_computed_value(&left)), } } } @@ -939,7 +947,6 @@ impl Parse for ClipRect { return Err(()) } - // NB: `top` and `left` are 0 if `auto` per CSS 2.1 11.1.2. input.parse_nested_block(|input| { let top = try!(parse_argument(context, input)); let right; @@ -958,10 +965,10 @@ impl Parse for ClipRect { left = try!(parse_argument(context, input)); } Ok(ClipRect { - top: top.unwrap_or(Length::zero()), + top: top, right: right, bottom: bottom, - left: left.unwrap_or(Length::zero()), + left: left, }) }) } diff --git a/tests/unit/style/parsing/effects.rs b/tests/unit/style/parsing/effects.rs new file mode 100644 index 000000000000..d335604773b9 --- /dev/null +++ b/tests/unit/style/parsing/effects.rs @@ -0,0 +1,35 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use cssparser::Parser; +use media_queries::CSSErrorReporterTest; +use servo_url::ServoUrl; +use style::parser::ParserContext; +use style::stylesheets::Origin; +use style_traits::ToCss; + +#[test] +fn test_clip() { + use style::properties::longhands::clip; + + assert_roundtrip_with_context!(clip::parse, "auto"); + assert_roundtrip_with_context!(clip::parse, "rect(1px, 2px, 3px, 4px)"); + assert_roundtrip_with_context!(clip::parse, "rect(1px, auto, auto, 4px)"); + assert_roundtrip_with_context!(clip::parse, "rect(auto, auto, auto, auto)"); + + // Non-standard syntax + assert_roundtrip_with_context!(clip::parse, + "rect(1px 2px 3px 4px)", + "rect(1px, 2px, 3px, 4px)"); + assert_roundtrip_with_context!(clip::parse, + "rect(auto 2px 3px auto)", + "rect(auto, 2px, 3px, auto)"); + assert_roundtrip_with_context!(clip::parse, + "rect(1px auto auto 4px)", + "rect(1px, auto, auto, 4px)"); + assert_roundtrip_with_context!(clip::parse, + "rect(auto auto auto auto)", + "rect(auto, auto, auto, auto)"); +} + diff --git a/tests/unit/style/parsing/mod.rs b/tests/unit/style/parsing/mod.rs index 72684bccc50f..f4bd0fad6441 100644 --- a/tests/unit/style/parsing/mod.rs +++ b/tests/unit/style/parsing/mod.rs @@ -82,6 +82,7 @@ mod background; mod basic_shape; mod border; mod column; +mod effects; mod font; mod image; mod inherited_box;