diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 380517d9924..89e1fa65961 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -657,6 +657,9 @@ impl FragmentDisplayListBuilding for Fragment { Some(computed::Image::ImageRect(_)) => { // TODO: Implement `-moz-image-rect` } + Some(computed::Image::Element(_)) => { + // TODO: Implement `-moz-element` + } } } } @@ -1154,6 +1157,9 @@ impl FragmentDisplayListBuilding for Fragment { Some(computed::Image::ImageRect(..)) => { // TODO: Handle border-image with `-moz-image-rect`. } + Some(computed::Image::Element(..)) => { + // TODO: Handle border-image with `-moz-element`. + } Some(computed::Image::Url(ref image_url)) => { if let Some(url) = image_url.url() { let webrender_image = state.layout_context diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index 87052c942d0..573bb5e0070 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -11,7 +11,7 @@ use app_units::Au; use gecko::values::{convert_rgba_to_nscolor, GeckoStyleCoordConvertible}; use gecko_bindings::bindings::{Gecko_CreateGradient, Gecko_SetGradientImageValue, Gecko_SetUrlImageValue}; -use gecko_bindings::bindings::Gecko_InitializeImageCropRect; +use gecko_bindings::bindings::{Gecko_InitializeImageCropRect, Gecko_SetImageElement}; use gecko_bindings::structs::{nsStyleCoord_CalcValue, nsStyleImage}; use gecko_bindings::structs::{nsresult, SheetType}; use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordDataMut}; @@ -141,6 +141,11 @@ impl nsStyleImage { image_rect.left.to_gecko_style_coord(&mut rect.data_at_mut(3)); } } + Image::Element(ref element) => { + unsafe { + Gecko_SetImageElement(self, element.as_ptr()); + } + }, _ => (), } } diff --git a/components/style/gecko_bindings/bindings.rs b/components/style/gecko_bindings/bindings.rs index 90f5c7c38b9..78ee8fe3472 100644 --- a/components/style/gecko_bindings/bindings.rs +++ b/components/style/gecko_bindings/bindings.rs @@ -701,6 +701,10 @@ extern "C" { pub fn Gecko_SetUrlImageValue(image: *mut nsStyleImage, uri: ServoBundledURI); } +extern "C" { + pub fn Gecko_SetImageElement(image: *mut nsStyleImage, + atom: *mut nsIAtom); +} extern "C" { pub fn Gecko_CopyImageValueFrom(image: *mut nsStyleImage, other: *const nsStyleImage); diff --git a/components/style/values/computed/image.rs b/components/style/values/computed/image.rs index cf41462d655..da424959e74 100644 --- a/components/style/values/computed/image.rs +++ b/components/style/values/computed/image.rs @@ -7,7 +7,8 @@ //! //! [image]: https://drafts.csswg.org/css-images/#image-values -use cssparser::Color as CSSColor; +use Atom; +use cssparser::{Color as CSSColor, serialize_identifier}; use std::f32::consts::PI; use std::fmt; use style_traits::ToCss; @@ -31,6 +32,9 @@ impl ToComputedValue for specified::Image { }, specified::Image::ImageRect(ref image_rect) => { Image::ImageRect(image_rect.to_computed_value(context)) + }, + specified::Image::Element(ref selector) => { + Image::Element(selector.clone()) } } } @@ -51,6 +55,9 @@ impl ToComputedValue for specified::Image { ToComputedValue::from_computed_value(image_rect) ) }, + Image::Element(ref selector) => { + specified::Image::Element(selector.clone()) + }, } } } @@ -64,6 +71,7 @@ pub enum Image { Url(SpecifiedUrl), Gradient(Gradient), ImageRect(ImageRect), + Element(Atom), } impl fmt::Debug for Image { @@ -80,6 +88,11 @@ impl fmt::Debug for Image { } }, Image::ImageRect(ref image_rect) => write!(f, "{:?}", image_rect), + Image::Element(ref selector) => { + f.write_str("-moz-element(#")?; + serialize_identifier(&*selector.to_string(), f)?; + f.write_str(")") + }, } } } @@ -90,6 +103,12 @@ impl ToCss for Image { Image::Url(ref url) => url.to_css(dest), Image::Gradient(ref gradient) => gradient.to_css(dest), Image::ImageRect(ref image_rect) => image_rect.to_css(dest), + Image::Element(ref selector) => { + dest.write_str("-moz-element(#")?; + // FIXME: We should get rid of these intermediate strings. + serialize_identifier(&*selector.to_string(), dest)?; + dest.write_str(")") + }, } } } diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index affe73d542b..bfe31313ea7 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -7,7 +7,8 @@ //! //! [image]: https://drafts.csswg.org/css-images/#image-values -use cssparser::Parser; +use Atom; +use cssparser::{Parser, Token, serialize_identifier}; use parser::{Parse, ParserContext}; #[cfg(feature = "servo")] use servo_url::ServoUrl; @@ -28,6 +29,8 @@ pub enum Image { Gradient(Gradient), /// A `-moz-image-rect` image ImageRect(ImageRect), + /// A `-moz-element(# )` + Element(Atom), } impl ToCss for Image { @@ -36,6 +39,12 @@ impl ToCss for Image { Image::Url(ref url_value) => url_value.to_css(dest), Image::Gradient(ref gradient) => gradient.to_css(dest), Image::ImageRect(ref image_rect) => image_rect.to_css(dest), + Image::Element(ref selector) => { + dest.write_str("-moz-element(#")?; + // FIXME: We should get rid of these intermediate strings. + serialize_identifier(&*selector.to_string(), dest)?; + dest.write_str(")") + }, } } } @@ -49,8 +58,11 @@ impl Image { if let Ok(gradient) = input.try(|input| Gradient::parse_function(context, input)) { return Ok(Image::Gradient(gradient)); } + if let Ok(image_rect) = input.try(|input| ImageRect::parse(context, input)) { + return Ok(Image::ImageRect(image_rect)); + } - Ok(Image::ImageRect(ImageRect::parse(context, input)?)) + Ok(Image::Element(Image::parse_element(input)?)) } /// Creates an already specified image value from an already resolved URL @@ -59,6 +71,20 @@ impl Image { pub fn for_cascade(url: ServoUrl) -> Self { Image::Url(SpecifiedUrl::for_cascade(url)) } + + /// Parses a `-moz-element(# )`. + fn parse_element(input: &mut Parser) -> Result { + if input.try(|i| i.expect_function_matching("-moz-element")).is_ok() { + input.parse_nested_block(|i| { + match i.next()? { + Token::IDHash(id) => Ok(Atom::from(id)), + _ => Err(()), + } + }) + } else { + Err(()) + } + } } /// Specified values for a CSS gradient.