Bug 1341761 - stylo: Add -moz-element support r?xidorn
MozReview-Commit-ID: I9gxAoFJH9C
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -980,16 +980,22 @@ void
Gecko_SetUrlImageValue(nsStyleImage* aImage, ServoBundledURI aURI)
{
RefPtr<nsStyleImageRequest> req =
CreateStyleImageRequest(nsStyleImageRequest::Mode::Track, aURI);
aImage->SetImageRequest(req.forget());
}
void
+Gecko_SetImageElement(nsStyleImage* aImage, nsIAtom* aAtom) {
+ MOZ_ASSERT(aImage);
+ aImage->SetElementId(do_AddRef(aAtom));
+}
+
+void
Gecko_CopyImageValueFrom(nsStyleImage* aImage, const nsStyleImage* aOther)
{
MOZ_ASSERT(aImage);
MOZ_ASSERT(aOther);
*aImage = *aOther;
}
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -221,21 +221,21 @@ void Gecko_FontFamilyList_AppendNamed(Fo
void Gecko_FontFamilyList_AppendGeneric(FontFamilyList* list, FontFamilyType familyType);
void Gecko_CopyFontFamilyFrom(nsFont* dst, const nsFont* src);
// Counter style.
void Gecko_SetListStyleType(nsStyleList* style_struct, uint32_t type);
void Gecko_CopyListStyleTypeFrom(nsStyleList* dst, const nsStyleList* src);
// background-image style.
-// TODO: support element() and -moz-image()
void Gecko_SetNullImageValue(nsStyleImage* image);
void Gecko_SetGradientImageValue(nsStyleImage* image, nsStyleGradient* gradient);
void Gecko_SetUrlImageValue(nsStyleImage* image,
ServoBundledURI uri);
+void Gecko_SetImageElement(nsStyleImage* image, nsIAtom* atom);
void Gecko_CopyImageValueFrom(nsStyleImage* image, const nsStyleImage* other);
void Gecko_InitializeImageCropRect(nsStyleImage* image);
nsStyleGradient* Gecko_CreateGradient(uint8_t shape,
uint8_t size,
bool repeating,
bool legacy_syntax,
uint32_t stops);
--- a/servo/components/style/gecko/conversions.rs
+++ b/servo/components/style/gecko/conversions.rs
@@ -6,17 +6,17 @@
//! Ideally, it would be in geckolib itself, but coherence
//! forces us to keep the traits and implementations here
#![allow(unsafe_code)]
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};
use stylesheets::{Origin, RulesMutateError};
use values::computed::{CalcLengthOrPercentage, Gradient, Image, LengthOrPercentage, LengthOrPercentageOrAuto};
impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
@@ -136,16 +136,21 @@ impl nsStyleImage {
// Set CropRect
let ref mut rect = *self.mCropRect.mPtr;
image_rect.top.to_gecko_style_coord(&mut rect.data_at_mut(0));
image_rect.right.to_gecko_style_coord(&mut rect.data_at_mut(1));
image_rect.bottom.to_gecko_style_coord(&mut rect.data_at_mut(2));
image_rect.left.to_gecko_style_coord(&mut rect.data_at_mut(3));
}
}
+ Image::Element(ref element) => {
+ unsafe {
+ Gecko_SetImageElement(self, element.as_ptr());
+ }
+ },
_ => (),
}
}
fn set_gradient(&mut self, gradient: Gradient) {
use cssparser::Color as CSSColor;
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_CIRCULAR, NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL};
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_LINEAR, NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER};
--- a/servo/components/style/values/computed/image.rs
+++ b/servo/components/style/values/computed/image.rs
@@ -2,17 +2,18 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! CSS handling for the computed value of
//! [`image`][image]s
//!
//! [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;
use values::computed::{Angle, Context, Length, LengthOrPercentage, NumberOrPercentage, ToComputedValue};
use values::computed::position::Position;
use values::specified::{self, HorizontalDirection, SizeKeyword, VerticalDirection};
use values::specified::url::SpecifiedUrl;
@@ -26,16 +27,19 @@ impl ToComputedValue for specified::Imag
specified::Image::Url(ref url_value) => {
Image::Url(url_value.clone())
},
specified::Image::Gradient(ref gradient) => {
Image::Gradient(gradient.to_computed_value(context))
},
specified::Image::ImageRect(ref image_rect) => {
Image::ImageRect(image_rect.to_computed_value(context))
+ },
+ specified::Image::Element(ref selector) => {
+ Image::Element(selector.clone())
}
}
}
#[inline]
fn from_computed_value(computed: &Image) -> Self {
match *computed {
Image::Url(ref url_value) => {
@@ -46,55 +50,70 @@ impl ToComputedValue for specified::Imag
ToComputedValue::from_computed_value(linear_gradient)
)
},
Image::ImageRect(ref image_rect) => {
specified::Image::ImageRect(
ToComputedValue::from_computed_value(image_rect)
)
},
+ Image::Element(ref selector) => {
+ specified::Image::Element(selector.clone())
+ },
}
}
}
/// Computed values for an image according to CSS-IMAGES.
/// https://drafts.csswg.org/css-images/#image-values
#[derive(Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
pub enum Image {
Url(SpecifiedUrl),
Gradient(Gradient),
ImageRect(ImageRect),
+ Element(Atom),
}
impl fmt::Debug for Image {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Image::Url(ref url) => url.to_css(f),
Image::Gradient(ref grad) => {
if grad.repeating {
let _ = write!(f, "repeating-");
}
match grad.gradient_kind {
GradientKind::Linear(_) => write!(f, "linear-gradient({:?})", grad),
GradientKind::Radial(_, _) => write!(f, "radial-gradient({:?})", grad),
}
},
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(")")
+ },
}
}
}
impl ToCss for Image {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
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(")")
+ },
}
}
}
/// Computed values for a CSS gradient.
/// https://drafts.csswg.org/css-images/#gradients
#[derive(Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
--- a/servo/components/style/values/specified/image.rs
+++ b/servo/components/style/values/specified/image.rs
@@ -2,17 +2,18 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! CSS handling for the specified value of
//! [`image`][image]s
//!
//! [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;
use std::fmt;
use style_traits::ToCss;
use values::specified::{Angle, CSSColor, Length, LengthOrPercentage, NumberOrPercentage};
use values::specified::position::Position;
use values::specified::url::SpecifiedUrl;
@@ -23,47 +24,72 @@ use values::specified::url::SpecifiedUrl
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Image {
/// A `<url()>` image.
Url(SpecifiedUrl),
/// A `<gradient>` image.
Gradient(Gradient),
/// A `-moz-image-rect` image
ImageRect(ImageRect),
+ /// A `-moz-element(# <element-id>)`
+ Element(Atom),
}
impl ToCss for Image {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
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(")")
+ },
}
}
}
impl Image {
#[allow(missing_docs)]
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Image, ()> {
if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
return Ok(Image::Url(url));
}
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
/// for insertion in the cascade.
#[cfg(feature = "servo")]
pub fn for_cascade(url: ServoUrl) -> Self {
Image::Url(SpecifiedUrl::for_cascade(url))
}
+
+ /// Parses a `-moz-element(# <element-id>)`.
+ fn parse_element(input: &mut Parser) -> Result<Atom, ()> {
+ 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.
/// https://drafts.csswg.org/css-images/#gradients
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Gradient {
/// The color stops.