Bug 1453258 - Support calc in cursor. r?emilio draft
authorXidorn Quan <me@upsuper.org>
Tue, 17 Apr 2018 21:18:37 +1000
changeset 783569 1232ec45d9b65ef01b9203095c85f5a871a1de51
parent 783326 c64c09c02133019e105d99e1698dd3492f5e0d58
push id106717
push userxquan@mozilla.com
push dateTue, 17 Apr 2018 11:53:19 +0000
reviewersemilio
bugs1453258
milestone61.0a1
Bug 1453258 - Support calc in cursor. r?emilio MozReview-Commit-ID: 1ZzxkYboWZg
layout/style/test/property_database.js
servo/components/style/values/computed/pointing.rs
servo/components/style/values/generics/pointing.rs
servo/components/style/values/specified/pointing.rs
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -3403,17 +3403,30 @@ var gCSSProperties = {
     other_values: [ "foo 1", "bar", "foo 3 bar baz 2", "\\32  1", "-\\32  1", "-c 1", "\\32 1", "-\\32 1", "\\2  1", "-\\2  1", "-c 1", "\\2 1", "-\\2 1", "-\\7f \\9e 1" ],
     invalid_values: [ "none foo", "none foo 3", "foo none", "foo 3 none" ]
   },
   "cursor": {
     domProp: "cursor",
     inherited: true,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "auto" ],
-    other_values: [ "crosshair", "default", "pointer", "move", "e-resize", "ne-resize", "nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize", "w-resize", "text", "wait", "help", "progress", "copy", "alias", "context-menu", "cell", "not-allowed", "col-resize", "row-resize", "no-drop", "vertical-text", "all-scroll", "nesw-resize", "nwse-resize", "ns-resize", "ew-resize", "none", "grab", "grabbing", "zoom-in", "zoom-out", "-moz-grab", "-moz-grabbing", "-moz-zoom-in", "-moz-zoom-out", "url(foo.png), move", "url(foo.png) 5 7, move", "url(foo.png) 12 3, url(bar.png), no-drop", "url(foo.png), url(bar.png) 7 2, wait", "url(foo.png) 3 2, url(bar.png) 7 9, pointer" ],
+    other_values: [
+      "crosshair", "default", "pointer", "move", "e-resize", "ne-resize",
+      "nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize", "w-resize",
+      "text", "wait", "help", "progress", "copy", "alias", "context-menu",
+      "cell", "not-allowed", "col-resize", "row-resize", "no-drop",
+      "vertical-text", "all-scroll", "nesw-resize", "nwse-resize", "ns-resize",
+      "ew-resize", "none", "grab", "grabbing", "zoom-in", "zoom-out",
+      "-moz-grab", "-moz-grabbing", "-moz-zoom-in", "-moz-zoom-out",
+      "url(foo.png), move",
+      "url(foo.png) 5 7, move",
+      "url(foo.png) 12 3, url(bar.png), no-drop",
+      "url(foo.png), url(bar.png) 7 2, wait",
+      "url(foo.png) 3 2, url(bar.png) 7 9, pointer",
+      "url(foo.png) calc(1 + 2) calc(3), pointer" ],
     invalid_values: [ "url(foo.png)", "url(foo.png) 5 5" ]
   },
   "direction": {
     domProp: "direction",
     inherited: true,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "ltr" ],
     other_values: [ "rtl" ],
--- a/servo/components/style/values/computed/pointing.rs
+++ b/servo/components/style/values/computed/pointing.rs
@@ -1,142 +1,21 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 //! Computed values for Pointing properties.
 //!
 //! https://drafts.csswg.org/css-ui/#pointing-keyboard
 
-use cssparser::Parser;
-use parser::{Parse, ParserContext};
-use selectors::parser::SelectorParseErrorKind;
-#[cfg(feature = "gecko")]
-use std::fmt::{self, Write};
-#[cfg(feature = "gecko")]
-use style_traits::{CssWriter, ToCss};
-use style_traits::ParseError;
-use style_traits::cursor::CursorKind;
+use values::computed::Number;
 use values::computed::color::Color;
-use values::generics::pointing::CaretColor as GenericCaretColor;
-#[cfg(feature = "gecko")]
-use values::specified::url::SpecifiedImageUrl;
-
-/// The computed value for the `cursor` property.
-///
-/// https://drafts.csswg.org/css-ui/#cursor
-pub use values::specified::pointing::Cursor;
-#[cfg(feature = "gecko")]
-pub use values::specified::pointing::CursorImage;
-
-impl Cursor {
-    /// Set `cursor` to `auto`
-    #[cfg(feature = "servo")]
-    #[inline]
-    pub fn auto() -> Self {
-        Cursor(CursorKind::Auto)
-    }
-
-    /// Set `cursor` to `auto`
-    #[cfg(feature = "gecko")]
-    #[inline]
-    pub fn auto() -> Self {
-        Self {
-            images: vec![].into_boxed_slice(),
-            keyword: CursorKind::Auto,
-        }
-    }
-}
-
-impl Parse for Cursor {
-    /// cursor: [auto | default | ...]
-    #[cfg(feature = "servo")]
-    fn parse<'i, 't>(
-        context: &ParserContext,
-        input: &mut Parser<'i, 't>,
-    ) -> Result<Self, ParseError<'i>> {
-        Ok(Cursor(CursorKind::parse(context, input)?))
-    }
-
-    /// cursor: [<url> [<number> <number>]?]# [auto | default | ...]
-    #[cfg(feature = "gecko")]
-    fn parse<'i, 't>(
-        context: &ParserContext,
-        input: &mut Parser<'i, 't>,
-    ) -> Result<Self, ParseError<'i>> {
-        let mut images = vec![];
-        loop {
-            match input.try(|input| CursorImage::parse_image(context, input)) {
-                Ok(image) => images.push(image),
-                Err(_) => break,
-            }
-            input.expect_comma()?;
-        }
-        Ok(Self {
-            images: images.into_boxed_slice(),
-            keyword: CursorKind::parse(context, input)?,
-        })
-    }
-}
-
-#[cfg(feature = "gecko")]
-impl ToCss for Cursor {
-    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
-    where
-        W: Write,
-    {
-        for url in &*self.images {
-            url.to_css(dest)?;
-            dest.write_str(", ")?;
-        }
-        self.keyword.to_css(dest)
-    }
-}
-
-impl Parse for CursorKind {
-    fn parse<'i, 't>(
-        _context: &ParserContext,
-        input: &mut Parser<'i, 't>,
-    ) -> Result<Self, ParseError<'i>> {
-        let location = input.current_source_location();
-        let ident = input.expect_ident()?;
-        CursorKind::from_css_keyword(&ident).map_err(|_| {
-            location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone()))
-        })
-    }
-}
-
-#[cfg(feature = "gecko")]
-impl CursorImage {
-    fn parse_image<'i, 't>(
-        context: &ParserContext,
-        input: &mut Parser<'i, 't>,
-    ) -> Result<Self, ParseError<'i>> {
-        Ok(Self {
-            url: SpecifiedImageUrl::parse(context, input)?,
-            // FIXME(emilio): Should use Number::parse to handle calc() correctly.
-            hotspot: match input.try(|input| input.expect_number()) {
-                Ok(number) => Some((number, input.expect_number()?)),
-                Err(_) => None,
-            },
-        })
-    }
-}
-
-#[cfg(feature = "gecko")]
-impl ToCss for CursorImage {
-    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
-    where
-        W: Write,
-    {
-        self.url.to_css(dest)?;
-        if let Some((x, y)) = self.hotspot {
-            dest.write_str(" ")?;
-            x.to_css(dest)?;
-            dest.write_str(" ")?;
-            y.to_css(dest)?;
-        }
-        Ok(())
-    }
-}
+use values::computed::url::ComputedImageUrl;
+use values::generics::pointing as generics;
 
 /// A computed value for the `caret-color` property.
-pub type CaretColor = GenericCaretColor<Color>;
+pub type CaretColor = generics::CaretColor<Color>;
+
+/// A computed value for the `cursor` property.
+pub type Cursor = generics::Cursor<CursorImage>;
+
+/// A computed value for item of `image cursors`.
+pub type CursorImage = generics::CursorImage<ComputedImageUrl, Number>;
--- a/servo/components/style/values/generics/pointing.rs
+++ b/servo/components/style/values/generics/pointing.rs
@@ -1,15 +1,79 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 //! Generic values for pointing properties.
 
+use std::fmt::{self, Write};
+use style_traits::{CssWriter, ToCss};
+use style_traits::cursor::CursorKind;
+
 /// A generic value for the `caret-color` property.
 #[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq,
          ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss)]
 pub enum CaretColor<Color> {
     /// An explicit color.
     Color(Color),
     /// The keyword `auto`.
     Auto,
 }
+
+/// A generic value for the `cursor` property.
+///
+/// https://drafts.csswg.org/css-ui/#cursor
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
+pub struct Cursor<Image> {
+    /// The parsed images for the cursor.
+    pub images: Box<[Image]>,
+    /// The kind of the cursor [default | help | ...].
+    pub keyword: CursorKind,
+}
+
+impl<Image> Cursor<Image> {
+    /// Set `cursor` to `auto`
+    #[inline]
+    pub fn auto() -> Self {
+        Self {
+            images: vec![].into_boxed_slice(),
+            keyword: CursorKind::Auto,
+        }
+    }
+}
+
+impl<Image: ToCss> ToCss for Cursor<Image> {
+    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
+    where
+        W: Write,
+    {
+        for image in &*self.images {
+            image.to_css(dest)?;
+            dest.write_str(", ")?;
+        }
+        self.keyword.to_css(dest)
+    }
+}
+
+/// A generic value for item of `image cursors`.
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
+pub struct CursorImage<ImageUrl, Number> {
+    /// The url to parse images from.
+    pub url: ImageUrl,
+    /// The <x> and <y> coordinates.
+    pub hotspot: Option<(Number, Number)>,
+}
+
+impl<ImageUrl: ToCss, Number: ToCss> ToCss for CursorImage<ImageUrl, Number> {
+    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
+    where
+        W: Write,
+    {
+        self.url.to_css(dest)?;
+        if let Some((ref x, ref y)) = self.hotspot {
+            dest.write_str(" ")?;
+            x.to_css(dest)?;
+            dest.write_str(" ")?;
+            y.to_css(dest)?;
+        }
+        Ok(())
+    }
+}
--- a/servo/components/style/values/specified/pointing.rs
+++ b/servo/components/style/values/specified/pointing.rs
@@ -3,58 +3,84 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Specified values for Pointing properties.
 //!
 //! https://drafts.csswg.org/css-ui/#pointing-keyboard
 
 use cssparser::Parser;
 use parser::{Parse, ParserContext};
-use style_traits::ParseError;
+use style_traits::{ParseError, StyleParseErrorKind};
 use style_traits::cursor::CursorKind;
-use values::generics::pointing::CaretColor as GenericCaretColor;
+use values::generics::pointing as generics;
+use values::specified::Number;
 use values::specified::color::Color;
-#[cfg(feature = "gecko")]
 use values::specified::url::SpecifiedImageUrl;
 
-/// The specified value for the `cursor` property.
-///
-/// https://drafts.csswg.org/css-ui/#cursor
-#[cfg(feature = "servo")]
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
-pub struct Cursor(pub CursorKind);
-
-/// The specified value for the `cursor` property.
-///
-/// https://drafts.csswg.org/css-ui/#cursor
-#[cfg(feature = "gecko")]
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
-pub struct Cursor {
-    /// The parsed images for the cursor.
-    pub images: Box<[CursorImage]>,
-    /// The kind of the cursor [default | help | ...].
-    pub keyword: CursorKind,
-}
-
-/// The specified value for the `image cursors`.
-#[cfg(feature = "gecko")]
-#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
-pub struct CursorImage {
-    /// The url to parse images from.
-    pub url: SpecifiedImageUrl,
-    /// The <x> and <y> coordinates.
-    pub hotspot: Option<(f32, f32)>,
-}
-
 /// A specified value for the `caret-color` property.
-pub type CaretColor = GenericCaretColor<Color>;
+pub type CaretColor = generics::CaretColor<Color>;
 
 impl Parse for CaretColor {
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
         if input.try(|i| i.expect_ident_matching("auto")).is_ok() {
-            return Ok(GenericCaretColor::Auto);
+            return Ok(generics::CaretColor::Auto);
         }
-        Ok(GenericCaretColor::Color(Color::parse(context, input)?))
+        Ok(generics::CaretColor::Color(Color::parse(context, input)?))
     }
 }
+
+/// A specified value for the `cursor` property.
+pub type Cursor = generics::Cursor<CursorImage>;
+
+/// A specified value for item of `image cursors`.
+pub type CursorImage = generics::CursorImage<SpecifiedImageUrl, Number>;
+
+impl Parse for Cursor {
+    /// cursor: [<url> [<number> <number>]?]# [auto | default | ...]
+    fn parse<'i, 't>(
+        context: &ParserContext,
+        input: &mut Parser<'i, 't>,
+    ) -> Result<Self, ParseError<'i>> {
+        let mut images = vec![];
+        loop {
+            match input.try(|input| CursorImage::parse(context, input)) {
+                Ok(image) => images.push(image),
+                Err(_) => break,
+            }
+            input.expect_comma()?;
+        }
+        Ok(Self {
+            images: images.into_boxed_slice(),
+            keyword: CursorKind::parse(context, input)?,
+        })
+    }
+}
+
+impl Parse for CursorKind {
+    fn parse<'i, 't>(
+        _context: &ParserContext,
+        input: &mut Parser<'i, 't>,
+    ) -> Result<Self, ParseError<'i>> {
+        let location = input.current_source_location();
+        let ident = input.expect_ident()?;
+        CursorKind::from_css_keyword(&ident).map_err(|_| {
+            location.new_custom_error(StyleParseErrorKind::UnspecifiedError)
+        })
+    }
+}
+
+impl Parse for CursorImage {
+    fn parse<'i, 't>(
+        context: &ParserContext,
+        input: &mut Parser<'i, 't>,
+    ) -> Result<Self, ParseError<'i>> {
+        Ok(Self {
+            url: SpecifiedImageUrl::parse(context, input)?,
+            hotspot: match input.try(|input| Number::parse(context, input)) {
+                Ok(number) => Some((number, Number::parse(context, input)?)),
+                Err(_) => None,
+            },
+        })
+    }
+}