diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 3999122d537..3c615ed0e9d 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -43,7 +43,7 @@ use std::sync::Arc; use std::sync::mpsc::channel; use style::computed_values::filter::Filter; use style::computed_values::transform::ComputedMatrix; -use style::computed_values::{background_attachment, background_origin, background_repeat, background_size}; +use style::computed_values::{background_attachment, background_clip, background_origin, background_repeat, background_size}; use style::computed_values::{border_style, image_rendering, overflow_x, position, visibility}; use style::properties::ComputedValues; use style::properties::style_structs::Border; @@ -309,8 +309,31 @@ impl FragmentDisplayListBuilding for Fragment { // inefficient. What we really want is something like "nearest ancestor element that // doesn't have a fragment". let background_color = style.resolve_color(style.get_background().background_color); + + // 'background-clip' determines the area within which the background is painted. + // http://dev.w3.org/csswg/css-backgrounds-3/#the-background-clip + let mut bounds = *absolute_bounds; + + match style.get_background().background_clip { + background_clip::T::border_box => {} + background_clip::T::padding_box => { + let border = style.logical_border_width().to_physical(style.writing_mode); + bounds.origin.x = bounds.origin.x + border.left; + bounds.origin.y = bounds.origin.y + border.top; + bounds.size.width = bounds.size.width - border.horizontal(); + bounds.size.height = bounds.size.height - border.vertical(); + } + background_clip::T::content_box => { + let border_padding = self.border_padding.to_physical(style.writing_mode); + bounds.origin.x = bounds.origin.x + border_padding.left; + bounds.origin.y = bounds.origin.y + border_padding.top; + bounds.size.width = bounds.size.width - border_padding.horizontal(); + bounds.size.height = bounds.size.height - border_padding.vertical(); + } + } + display_list.push(DisplayItem::SolidColorClass(box SolidColorDisplayItem { - base: BaseDisplayItem::new(*absolute_bounds, + base: BaseDisplayItem::new(bounds, DisplayItemMetadata::new(self.node, style, Cursor::DefaultCursor), diff --git a/components/script/dom/webidls/CSSStyleDeclaration.webidl b/components/script/dom/webidls/CSSStyleDeclaration.webidl index 57b3e9f43cc..d85dfc8f8ca 100644 --- a/components/script/dom/webidls/CSSStyleDeclaration.webidl +++ b/components/script/dom/webidls/CSSStyleDeclaration.webidl @@ -40,6 +40,7 @@ partial interface CSSStyleDeclaration { [TreatNullAs=EmptyString] attribute DOMString backgroundAttachment; [TreatNullAs=EmptyString] attribute DOMString backgroundSize; [TreatNullAs=EmptyString] attribute DOMString backgroundOrigin; + [TreatNullAs=EmptyString] attribute DOMString backgroundClip; [TreatNullAs=EmptyString] attribute DOMString border; [TreatNullAs=EmptyString] attribute DOMString borderColor; diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs index 639b02d3b88..3edc0a312fa 100644 --- a/components/style/properties.mako.rs +++ b/components/style/properties.mako.rs @@ -1295,6 +1295,8 @@ pub mod longhands { ${single_keyword("background-attachment", "scroll fixed")} + ${single_keyword("background-clip", "border-box padding-box content-box")} + ${single_keyword("background-origin", "padding-box border-box content-box")} <%self:longhand name="background-size"> @@ -4247,9 +4249,9 @@ pub mod shorthands { // TODO: other background-* properties <%self:shorthand name="background" sub_properties="background-color background-position background-repeat background-attachment - background-image background-size background-origin"> - use properties::longhands::{background_color, background_position, background_repeat}; - use properties::longhands::{background_attachment, background_image, background_size, background_origin}; + background-image background-size background-origin background-clip"> + use properties::longhands::{background_color, background_position, background_repeat, background_attachment}; + use properties::longhands::{background_image, background_size, background_origin, background_clip}; let mut color = None; let mut image = None; @@ -4259,6 +4261,7 @@ pub mod shorthands { let mut attachment = None; let mut any = false; let mut origin = None; + let mut clip = None; loop { if position.is_none() { @@ -4310,6 +4313,13 @@ pub mod shorthands { continue } } + if clip.is_none() { + if let Ok(value) = input.try(|input| background_clip::parse(context, input)) { + clip = Some(value); + any = true; + continue + } + } break } @@ -4322,6 +4332,7 @@ pub mod shorthands { background_attachment: attachment, background_size: size, background_origin: origin, + background_clip: clip, }) } else { Err(()) diff --git a/tests/ref/background_clip_a.html b/tests/ref/background_clip_a.html new file mode 100644 index 00000000000..6a95ec7831a --- /dev/null +++ b/tests/ref/background_clip_a.html @@ -0,0 +1,34 @@ + + + + + + +

background-clip: border-box;

+
+

background-clip: padding-box;

+
+

background-clip: content-box;

+
+ + + diff --git a/tests/ref/background_clip_ref.html b/tests/ref/background_clip_ref.html new file mode 100644 index 00000000000..96111ea7955 --- /dev/null +++ b/tests/ref/background_clip_ref.html @@ -0,0 +1,40 @@ + + + + + + +

background-clip: border-box;

+
+

background-clip: padding-box;

+
+

background-clip: content-box;

+
+ + + diff --git a/tests/ref/basic.list b/tests/ref/basic.list index a4a9d5ed254..d4a2b01cb1b 100644 --- a/tests/ref/basic.list +++ b/tests/ref/basic.list @@ -22,6 +22,7 @@ fragment=top != ../html/acid2.html acid2_ref.html flaky_cpu == append_style_a.html append_style_b.html == attr_exists_selector.html attr_exists_selector_ref.html == attr_selector_case_sensitivity.html attr_selector_case_sensitivity_ref.html +== background_clip_a.html background_clip_ref.html == background_external_stylesheet.html background_ref.html == background_image_position_a.html background_image_position_ref.html == background_none_a.html background_none_b.html diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs index 355543e5fd1..0ea58142fc6 100644 --- a/tests/unit/style/stylesheets.rs +++ b/tests/unit/style/stylesheets.rs @@ -116,6 +116,7 @@ fn test_parse_stylesheet() { ], declarations: PropertyDeclarationBlock { normal: Arc::new(vec![ + PropertyDeclaration::BackgroundClip(DeclaredValue::Initial), PropertyDeclaration::BackgroundOrigin(DeclaredValue::Initial), PropertyDeclaration::BackgroundSize(DeclaredValue::Initial), PropertyDeclaration::BackgroundImage(DeclaredValue::Initial),