mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Implement 'background-origin' property in CSS3 Background
This property determines the background positioning area, that is the position of the origin of an image specified using the 'background-image' CSS property. 'background-origin' is ignored when background-attachment is fixed. Spec: http://dev.w3.org/csswg/css-backgrounds-3/#background-origin Fixes #6045.
This commit is contained in:
parent
b05c3fc0c0
commit
b1b22c0c53
7 changed files with 119 additions and 8 deletions
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(())
|
||||
|
|
40
tests/ref/background_origin_a.html
Normal file
40
tests/ref/background_origin_a.html
Normal file
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
#foo1 {
|
||||
background: url(400x400_green.png);
|
||||
background-origin: padding-box;
|
||||
background-repeat: no-repeat;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
padding: 20px;
|
||||
border: 20px dotted red;
|
||||
}
|
||||
#foo2 {
|
||||
background: url(400x400_green.png);
|
||||
background-origin: border-box;
|
||||
background-repeat: no-repeat;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
padding: 20px;
|
||||
border: 20px dotted red;
|
||||
}
|
||||
#foo3 {
|
||||
background: url(400x400_green.png);
|
||||
background-origin: content-box;
|
||||
background-repeat: no-repeat;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
padding: 20px;
|
||||
border: 20px dotted red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id=foo1></div>
|
||||
<div id=foo2></div>
|
||||
<div id=foo3></div>
|
||||
</body>
|
||||
</html>
|
||||
|
39
tests/ref/background_origin_ref.html
Normal file
39
tests/ref/background_origin_ref.html
Normal file
|
@ -0,0 +1,39 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
#foo1 {
|
||||
background: url(400x400_green.png);
|
||||
background-repeat: no-repeat;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
padding: 20px;
|
||||
border: 20px dotted red;
|
||||
}
|
||||
#foo2 {
|
||||
background: url(400x400_green.png);
|
||||
background-position: -20px -20px;
|
||||
background-repeat: no-repeat;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
padding: 20px;
|
||||
border: 20px dotted red;
|
||||
}
|
||||
#foo3 {
|
||||
background: url(400x400_green.png);
|
||||
background-position: 20px 20px;
|
||||
background-repeat: no-repeat;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
padding: 20px;
|
||||
border: 20px dotted red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id=foo1></div>
|
||||
<div id=foo2></div>
|
||||
<div id=foo3></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue