Auto merge of #6067 - Jinwoo-Song:backgroundclip, r=pcwalton

This property determines the background painting area, which determines the area
within which the background is painted.

Spec: http://dev.w3.org/csswg/css-backgrounds-3/#background-clip

Fixes #6066.

r? @pcwalton 
cc @yichoi

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6067)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-05-15 22:05:05 -05:00
commit 9f2079f6ba
7 changed files with 116 additions and 5 deletions

View file

@ -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),

View file

@ -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;

View file

@ -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(())

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<style>
div {
background: green;
width: 200px;
height: 200px;
padding: 20px;
border-width: 10px 20px 30px 40px;
border-style: dotted;
border-color: red;
}
#foo1 {
background-clip: border-box;
}
#foo2 {
background-clip: padding-box;
}
#foo3 {
background-clip: content-box;
}
</style>
</head>
<body>
<p>background-clip: border-box;</p>
<div id=foo1></div>
<p>background-clip: padding-box;</p>
<div id=foo2></div>
<p>background-clip: content-box;</p>
<div id=foo3></div>
</body>
</html>

View file

@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<style>
#foo1 {
background: green;
}
#foo1, #foo2, #foo3 {
width: 200px;
height: 200px;
padding: 20px;
border-width: 10px 20px 30px 40px;
border-style: dotted;
border-color: red;
}
#foo2-color {
background: green;
width: 240px;
height: 240px;
position: relative;
left: -20px;
top: -20px;
}
#foo3-color {
background: green;
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<p>background-clip: border-box;</p>
<div id=foo1></div>
<p>background-clip: padding-box;</p>
<div id=foo2><div id=foo2-color></div></div>
<p>background-clip: content-box;</p>
<div id=foo3><div id=foo3-color></div></div>
</body>
</html>

View file

@ -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

View file

@ -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),