Bug 1341761 - stylo: Add -moz-element support r?xidorn draft
authorNazım Can Altınova <canaltinova@gmail.com>
Thu, 06 Apr 2017 20:25:34 +0300
changeset 559286 f8f82a305be92d8629679f1338991999cfff50b1
parent 559285 94de1ab52757e9ed4c37dda605cf8b57d63ee646
child 559287 1728f86afb57d415c814af930f1d01ae9a8b3204
push id53043
push userbmo:canaltinova@gmail.com
push dateSun, 09 Apr 2017 13:50:52 +0000
reviewersxidorn
bugs1341761
milestone55.0a1
Bug 1341761 - stylo: Add -moz-element support r?xidorn MozReview-Commit-ID: I9gxAoFJH9C
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
servo/components/style/gecko/conversions.rs
servo/components/style/values/computed/image.rs
servo/components/style/values/specified/image.rs
--- 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.