mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +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 std::sync::mpsc::channel;
|
||||||
use style::computed_values::filter::Filter;
|
use style::computed_values::filter::Filter;
|
||||||
use style::computed_values::transform::ComputedMatrix;
|
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::computed_values::{border_style, image_rendering, overflow_x, position, visibility};
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::properties::style_structs::Border;
|
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.
|
// TODO: Check the bounds to see if a clip item is actually required.
|
||||||
let clip = clip.clone().intersect_rect(&bounds);
|
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
|
// Use `background-attachment` to get the initial virtual origin
|
||||||
let (virtual_origin_x, virtual_origin_y) = match background.background_attachment {
|
let (virtual_origin_x, virtual_origin_y) = match background.background_attachment {
|
||||||
background_attachment::T::scroll => {
|
background_attachment::T::scroll => {
|
||||||
(absolute_bounds.origin.x, absolute_bounds.origin.y)
|
(absolute_bounds.origin.x, absolute_bounds.origin.y)
|
||||||
}
|
}
|
||||||
background_attachment::T::fixed => {
|
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))
|
(Au(0), Au(0))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -435,11 +455,8 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
let vertical_position = model::specified(background.background_position.vertical,
|
let vertical_position = model::specified(background.background_position.vertical,
|
||||||
bounds.size.height - image_size.height);
|
bounds.size.height - image_size.height);
|
||||||
|
|
||||||
// Background image should be positioned on the padding box basis.
|
let abs_x = border.left + virtual_origin_x + horizontal_position + origin_x;
|
||||||
let border = style.logical_border_width().to_physical(style.writing_mode);
|
let abs_y = border.top + virtual_origin_y + vertical_position + origin_y;
|
||||||
|
|
||||||
let abs_x = border.left + virtual_origin_x + horizontal_position;
|
|
||||||
let abs_y = border.top + virtual_origin_y + vertical_position;
|
|
||||||
|
|
||||||
// Adjust origin and size based on background-repeat
|
// Adjust origin and size based on background-repeat
|
||||||
match background.background_repeat {
|
match background.background_repeat {
|
||||||
|
|
|
@ -39,6 +39,7 @@ partial interface CSSStyleDeclaration {
|
||||||
[TreatNullAs=EmptyString] attribute DOMString backgroundImage;
|
[TreatNullAs=EmptyString] attribute DOMString backgroundImage;
|
||||||
[TreatNullAs=EmptyString] attribute DOMString backgroundAttachment;
|
[TreatNullAs=EmptyString] attribute DOMString backgroundAttachment;
|
||||||
[TreatNullAs=EmptyString] attribute DOMString backgroundSize;
|
[TreatNullAs=EmptyString] attribute DOMString backgroundSize;
|
||||||
|
[TreatNullAs=EmptyString] attribute DOMString backgroundOrigin;
|
||||||
|
|
||||||
[TreatNullAs=EmptyString] attribute DOMString border;
|
[TreatNullAs=EmptyString] attribute DOMString border;
|
||||||
[TreatNullAs=EmptyString] attribute DOMString borderColor;
|
[TreatNullAs=EmptyString] attribute DOMString borderColor;
|
||||||
|
|
|
@ -1295,6 +1295,8 @@ pub mod longhands {
|
||||||
|
|
||||||
${single_keyword("background-attachment", "scroll fixed")}
|
${single_keyword("background-attachment", "scroll fixed")}
|
||||||
|
|
||||||
|
${single_keyword("background-origin", "padding-box border-box content-box")}
|
||||||
|
|
||||||
<%self:longhand name="background-size">
|
<%self:longhand name="background-size">
|
||||||
use cssparser::{ToCss, Token};
|
use cssparser::{ToCss, Token};
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
|
@ -4244,9 +4246,10 @@ pub mod shorthands {
|
||||||
|
|
||||||
// TODO: other background-* properties
|
// TODO: other background-* properties
|
||||||
<%self:shorthand name="background"
|
<%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_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 color = None;
|
||||||
let mut image = None;
|
let mut image = None;
|
||||||
|
@ -4255,6 +4258,7 @@ pub mod shorthands {
|
||||||
let mut size = None;
|
let mut size = None;
|
||||||
let mut attachment = None;
|
let mut attachment = None;
|
||||||
let mut any = false;
|
let mut any = false;
|
||||||
|
let mut origin = None;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if position.is_none() {
|
if position.is_none() {
|
||||||
|
@ -4299,6 +4303,13 @@ pub mod shorthands {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if origin.is_none() {
|
||||||
|
if let Ok(value) = input.try(|input| background_origin::parse(context, input)) {
|
||||||
|
origin = Some(value);
|
||||||
|
any = true;
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4310,6 +4321,7 @@ pub mod shorthands {
|
||||||
background_repeat: repeat,
|
background_repeat: repeat,
|
||||||
background_attachment: attachment,
|
background_attachment: attachment,
|
||||||
background_size: size,
|
background_size: size,
|
||||||
|
background_origin: origin,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
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_external_stylesheet.html background_ref.html
|
||||||
== background_image_position_a.html background_image_position_ref.html
|
== background_image_position_a.html background_image_position_ref.html
|
||||||
== background_none_a.html background_none_b.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_a.html background_position_b.html
|
||||||
== background_position_keyword.html background_position_b.html
|
== background_position_keyword.html background_position_b.html
|
||||||
== background_position_percent.html background_position_b.html
|
== background_position_percent.html background_position_b.html
|
||||||
|
|
|
@ -116,6 +116,7 @@ fn test_parse_stylesheet() {
|
||||||
],
|
],
|
||||||
declarations: PropertyDeclarationBlock {
|
declarations: PropertyDeclarationBlock {
|
||||||
normal: Arc::new(vec![
|
normal: Arc::new(vec![
|
||||||
|
PropertyDeclaration::BackgroundOrigin(DeclaredValue::Initial),
|
||||||
PropertyDeclaration::BackgroundSize(DeclaredValue::Initial),
|
PropertyDeclaration::BackgroundSize(DeclaredValue::Initial),
|
||||||
PropertyDeclaration::BackgroundImage(DeclaredValue::Initial),
|
PropertyDeclaration::BackgroundImage(DeclaredValue::Initial),
|
||||||
PropertyDeclaration::BackgroundAttachment(DeclaredValue::Initial),
|
PropertyDeclaration::BackgroundAttachment(DeclaredValue::Initial),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue