From 3b55a5fca09d6dc8475b4a84f75f27c3f362f21b Mon Sep 17 00:00:00 2001 From: Youngmin Yoo Date: Wed, 5 Feb 2014 11:24:08 +0900 Subject: [PATCH 1/5] Add background-image property --- src/components/style/properties.rs.mako | 53 ++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/src/components/style/properties.rs.mako b/src/components/style/properties.rs.mako index be73277dd3d..e8325110d1d 100644 --- a/src/components/style/properties.rs.mako +++ b/src/components/style/properties.rs.mako @@ -5,8 +5,10 @@ // This file is a Mako template: http://www.makotemplates.org/ use std::ascii::StrAsciiExt; +pub use servo_util::url::parse_url; pub use extra::arc::Arc; use servo_util::cowarc::CowArc; + pub use cssparser::*; pub use cssparser::ast::*; @@ -470,10 +472,31 @@ pub mod longhands { // CSS 2.1, Section 14 - Colors and Backgrounds ${new_style_struct("Background", is_inherited=False)} - ${predefined_type("background-color", "CSSColor", "RGBA(RGBA { red: 0., green: 0., blue: 0., alpha: 0. }) /* transparent */")} + <%self:single_component_value name="background-image"> + // The computed value is the same as the specified value. + pub use to_computed_value = super::computed_as_specified; + pub mod computed_value { + pub use extra::url::Url; + pub type T = Option; + } + pub type SpecifiedValue = computed_value::T; + #[inline] pub fn get_initial_value() -> SpecifiedValue { + None + } + pub fn from_component_value(component_value: &ComponentValue) -> Option { + match component_value { + &ast::URL(ref url) => { + let image_url = parse_url(url.as_slice(), None); + Some(Some(image_url)) + }, + _ => None, + } + } + + ${new_style_struct("Color", is_inherited=True)} @@ -809,12 +832,30 @@ pub mod shorthands { - // TODO: other background-* properties - <%self:shorthand name="background" sub_properties="background-color"> - one_component_value(input).and_then(specified::CSSColor::parse).map(|color| { - Longhands { background_color: Some(color) } - }) + <%self:shorthand name="background" sub_properties="background-color background-image"> + let mut color = None; + let mut image = None; + let mut any = false; + + for component_value in input.skip_whitespace() { + if color.is_none() { + match background_color::from_component_value(component_value) { + Some(v) => { color = Some(v); any = true; continue }, + None => () + } + } + + if image.is_none() { + match background_image::from_component_value(component_value) { + Some(v) => { image = Some(v); any = true; continue }, + None => (), + } + } + return None; + } + if any { Some(Longhands { background_color: color, background_image: image }) } + else { None } ${four_sides_shorthand("margin", "margin-%s", "margin_top::from_component_value")} From 7eabcbb8fe2bde54448c1255497aed4f7378e6d1 Mon Sep 17 00:00:00 2001 From: Youngmin Yoo Date: Wed, 5 Feb 2014 16:42:35 +0900 Subject: [PATCH 2/5] Impl background-image support. --- src/components/main/layout/box_.rs | 38 ++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/components/main/layout/box_.rs b/src/components/main/layout/box_.rs index bcbb0ccebd1..d50d76ccb0a 100644 --- a/src/components/main/layout/box_.rs +++ b/src/components/main/layout/box_.rs @@ -22,6 +22,7 @@ use servo_util::geometry::Au; use servo_util::geometry; use servo_util::range::*; use servo_util::namespace; + use std::cast; use std::cell::RefCell; use std::cmp::ApproxEq; @@ -937,6 +938,7 @@ impl Box { /// necessary. pub fn paint_background_if_applicable( &self, + builder: &DisplayListBuilder, index: uint, lists: &RefCell>, absolute_bounds: &Rect) { @@ -959,6 +961,39 @@ impl Box { lists.lists[index].append_item(SolidColorDisplayItemClass(solid_color_display_item)) }); } + + // The background image is painted on top of the background color. + // Implements background image, per spec: + // http://www.w3.org/TR/CSS21/colors.html#background + match style.Background.get().background_image { + Some(ref image_url) => { + let mut holder = ImageHolder::new(image_url.clone(), builder.ctx.image_cache.clone()); + match holder.get_image() { + Some(image) => { + debug!("(building display list) building background image"); + + // Place the image into the display list. + lists.with_mut(|lists| { + let image_display_item = ~ImageDisplayItem { + base: BaseDisplayItem { + bounds: *absolute_bounds, + extra: ExtraDisplayListData::new(self), + }, + image: image.clone(), + }; + lists.lists[index].append_item(ImageDisplayItemClass(image_display_item)); + }); + } + None => { + // No image data at all? Do nothing. + // + // TODO: Add some kind of placeholder background image. + debug!("(building display list) no background image :("); + } + } + } + None => {} + } } /// Adds the display items necessary to paint the borders of this box to a display list if @@ -1052,7 +1087,7 @@ impl Box { self.paint_inline_background_border_if_applicable(index, lists, &absolute_box_bounds, &offset); // Add the background to the list, if applicable. - self.paint_background_if_applicable(index, lists, &absolute_box_bounds); + self.paint_background_if_applicable(builder, index, lists, &absolute_box_bounds); match self.specific { UnscannedTextBox(_) => fail!("Shouldn't see unscanned boxes here."), @@ -1259,7 +1294,6 @@ impl Box { // // TODO: Outlines. self.paint_borders_if_applicable(index, lists, &absolute_box_bounds); - } /// Returns the *minimum width* and *preferred width* of this box as defined by CSS 2.1. From 49952241ad1444256118ee42f6b2ab7e8704cd8c Mon Sep 17 00:00:00 2001 From: Youngmin Yoo Date: Thu, 6 Feb 2014 15:44:20 +0900 Subject: [PATCH 3/5] Add background test file --- src/test/html/background.html | 20 ++++++++++++++++++++ src/test/ref/rust-0.png | Bin 0 -> 4399 bytes 2 files changed, 20 insertions(+) create mode 100644 src/test/html/background.html create mode 100644 src/test/ref/rust-0.png diff --git a/src/test/html/background.html b/src/test/html/background.html new file mode 100644 index 00000000000..c3bb0df99ab --- /dev/null +++ b/src/test/html/background.html @@ -0,0 +1,20 @@ + + + + + + + +
+ background: url(rust-0.png) gray; width:200px; height:200px; +
+
+ background-image: url(rust-45.png); width:200px; height:200px; +
+
+ background: url(rust-90.png) yellow; width:200px; height:200px; border: 5px solid #000; +
+ + diff --git a/src/test/ref/rust-0.png b/src/test/ref/rust-0.png new file mode 100644 index 0000000000000000000000000000000000000000..20d93badf5e2290baba400611b888d31dc03b5af GIT binary patch literal 4399 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 BUCRIf literal 0 HcmV?d00001 From a12608d2e4d44da49d8f26fc9d111b7dfd01bfd7 Mon Sep 17 00:00:00 2001 From: Youngmin Yoo Date: Tue, 11 Feb 2014 10:56:05 +0900 Subject: [PATCH 4/5] Add a reftest for background-image --- src/test/ref/background_a.html | 9 +++++++++ src/test/ref/background_b.html | 9 +++++++++ src/test/ref/basic.list | 1 + 3 files changed, 19 insertions(+) create mode 100644 src/test/ref/background_a.html create mode 100644 src/test/ref/background_b.html diff --git a/src/test/ref/background_a.html b/src/test/ref/background_a.html new file mode 100644 index 00000000000..28bc8f6b21d --- /dev/null +++ b/src/test/ref/background_a.html @@ -0,0 +1,9 @@ + + + + + + +
+ + diff --git a/src/test/ref/background_b.html b/src/test/ref/background_b.html new file mode 100644 index 00000000000..11faa177fb7 --- /dev/null +++ b/src/test/ref/background_b.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/test/ref/basic.list b/src/test/ref/basic.list index 290a00741ca..bfd262afecb 100644 --- a/src/test/ref/basic.list +++ b/src/test/ref/basic.list @@ -29,3 +29,4 @@ == position_relative_a.html position_relative_b.html == attr_exists_selector.html attr_exists_selector_ref.html == data_img_a.html data_img_b.html +== background_a.html background_b.html From 7b56e75adb0002a3bd001aa61b55249c938fc60e Mon Sep 17 00:00:00 2001 From: Youngmin Yoo Date: Wed, 19 Feb 2014 15:52:58 +0900 Subject: [PATCH 5/5] Support base_url in stylesheet --- src/components/script/dom/element.rs | 4 +- .../script/html/hubbub_html_parser.rs | 7 +- src/components/style/media_queries.rs | 7 +- src/components/style/properties.rs.mako | 129 ++++++++++++++++-- src/components/style/stylesheets.rs | 12 +- 5 files changed, 133 insertions(+), 26 deletions(-) diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index 9ffb17c3254..2eb0553f2f6 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -221,7 +221,9 @@ impl Element { match local_name.as_slice() { "style" => { - self.style_attribute = Some(style::parse_style_attribute(value)) + let doc = self.node.owner_doc(); + let base_url = doc.document().url.clone(); + self.style_attribute = Some(style::parse_style_attribute(value, &base_url)) } "id" if abstract_self.is_in_doc() => { // XXX: this dual declaration are workaround to avoid the compile error: diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs index 4ba46343817..9b66e4ecb1a 100644 --- a/src/components/script/html/hubbub_html_parser.rs +++ b/src/components/script/html/hubbub_html_parser.rs @@ -26,7 +26,6 @@ use servo_util::url::parse_url; use std::cast; use std::cell::RefCell; use std::comm::{Port, SharedChan}; -use std::from_str::FromStr; use std::str; use style::Stylesheet; @@ -277,7 +276,8 @@ pub fn parse_html(cx: *JSContext, debug!("Fetched page; metadata is {:?}", load_response.metadata); - let url2 = load_response.metadata.final_url.clone(); + let base_url = load_response.metadata.final_url.clone(); + let url2 = base_url.clone(); let url3 = url2.clone(); // Store the final URL before we start parsing, so that DOM routines @@ -485,7 +485,6 @@ pub fn parse_html(cx: *JSContext, // We've reached the end of a