diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index b77bbf01324..3999122d537 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_repeat, background_size}; +use style::computed_values::{background_attachment, 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; @@ -419,12 +419,32 @@ impl FragmentDisplayListBuilding for Fragment { // TODO: Check the bounds to see if a clip item is actually required. let clip = clip.clone().intersect_rect(&bounds); + // Background image should be positioned on the padding box basis. + let border = style.logical_border_width().to_physical(style.writing_mode); + + // Use 'background-origin' to get the origin value. + let (mut origin_x, mut origin_y) = match background.background_origin { + background_origin::T::padding_box => { + (Au(0), Au(0)) + } + background_origin::T::border_box => { + (-border.left, -border.top) + } + background_origin::T::content_box => { + let border_padding = (self.border_padding).to_physical(self.style.writing_mode); + (border_padding.left - border.left, border_padding.top - border.top) + } + }; + // Use `background-attachment` to get the initial virtual origin let (virtual_origin_x, virtual_origin_y) = match background.background_attachment { background_attachment::T::scroll => { (absolute_bounds.origin.x, absolute_bounds.origin.y) } background_attachment::T::fixed => { + // If the ‘background-attachment’ value for this image is ‘fixed’, then 'background-origin' has no effect. + origin_x = Au(0); + origin_y = Au(0); (Au(0), Au(0)) } }; @@ -435,11 +455,8 @@ impl FragmentDisplayListBuilding for Fragment { let vertical_position = model::specified(background.background_position.vertical, bounds.size.height - image_size.height); - // Background image should be positioned on the padding box basis. - let border = style.logical_border_width().to_physical(style.writing_mode); - - let abs_x = border.left + virtual_origin_x + horizontal_position; - let abs_y = border.top + virtual_origin_y + vertical_position; + let abs_x = border.left + virtual_origin_x + horizontal_position + origin_x; + let abs_y = border.top + virtual_origin_y + vertical_position + origin_y; // Adjust origin and size based on background-repeat match background.background_repeat { diff --git a/components/script/dom/webidls/CSSStyleDeclaration.webidl b/components/script/dom/webidls/CSSStyleDeclaration.webidl index 8ed0805f432..57b3e9f43cc 100644 --- a/components/script/dom/webidls/CSSStyleDeclaration.webidl +++ b/components/script/dom/webidls/CSSStyleDeclaration.webidl @@ -39,6 +39,7 @@ partial interface CSSStyleDeclaration { [TreatNullAs=EmptyString] attribute DOMString backgroundImage; [TreatNullAs=EmptyString] attribute DOMString backgroundAttachment; [TreatNullAs=EmptyString] attribute DOMString backgroundSize; + [TreatNullAs=EmptyString] attribute DOMString backgroundOrigin; [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 fdcbb8b9a59..ef1885f8f8c 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-origin", "padding-box border-box content-box")} + <%self:longhand name="background-size"> use cssparser::{ToCss, Token}; use std::ascii::AsciiExt; @@ -4244,9 +4246,10 @@ 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"> + 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}; + use properties::longhands::{background_attachment, background_image, background_size, background_origin}; let mut color = None; let mut image = None; @@ -4255,6 +4258,7 @@ pub mod shorthands { let mut size = None; let mut attachment = None; let mut any = false; + let mut origin = None; loop { if position.is_none() { @@ -4299,6 +4303,13 @@ pub mod shorthands { continue } } + if origin.is_none() { + if let Ok(value) = input.try(|input| background_origin::parse(context, input)) { + origin = Some(value); + any = true; + continue + } + } break } @@ -4310,6 +4321,7 @@ pub mod shorthands { background_repeat: repeat, background_attachment: attachment, background_size: size, + background_origin: origin, }) } else { Err(()) diff --git a/tests/ref/background_origin_a.html b/tests/ref/background_origin_a.html new file mode 100644 index 00000000000..753bacc9145 --- /dev/null +++ b/tests/ref/background_origin_a.html @@ -0,0 +1,40 @@ + + + + + + +
+
+
+ + + diff --git a/tests/ref/background_origin_ref.html b/tests/ref/background_origin_ref.html new file mode 100644 index 00000000000..0394fc673de --- /dev/null +++ b/tests/ref/background_origin_ref.html @@ -0,0 +1,39 @@ + + + + + + +
+
+
+ + + diff --git a/tests/ref/basic.list b/tests/ref/basic.list index 33a55901bea..cd40a802439 100644 --- a/tests/ref/basic.list +++ b/tests/ref/basic.list @@ -25,6 +25,7 @@ flaky_cpu == append_style_a.html append_style_b.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 +== background_origin_a.html background_origin_ref.html == background_position_a.html background_position_b.html == background_position_keyword.html background_position_b.html == background_position_percent.html background_position_b.html diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs index 6d7a3814394..355543e5fd1 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::BackgroundOrigin(DeclaredValue::Initial), PropertyDeclaration::BackgroundSize(DeclaredValue::Initial), PropertyDeclaration::BackgroundImage(DeclaredValue::Initial), PropertyDeclaration::BackgroundAttachment(DeclaredValue::Initial),