From 685d269e31b8a7835cb1ce4dc25142f1df9f2b65 Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Tue, 16 May 2023 07:28:58 +0200 Subject: [PATCH] style: Support image-set() on the cursor property Differential Revision: https://phabricator.services.mozilla.com/D106745 --- components/style/values/computed/ui.rs | 4 +-- components/style/values/generics/ui.rs | 9 +++-- components/style/values/specified/image.rs | 42 +++++++++++++++++----- components/style/values/specified/ui.rs | 14 +++++--- 4 files changed, 49 insertions(+), 20 deletions(-) diff --git a/components/style/values/computed/ui.rs b/components/style/values/computed/ui.rs index ae12dfcdae0..562b7d15897 100644 --- a/components/style/values/computed/ui.rs +++ b/components/style/values/computed/ui.rs @@ -5,7 +5,7 @@ //! Computed values for UI properties use crate::values::computed::color::Color; -use crate::values::computed::url::ComputedImageUrl; +use crate::values::computed::image::Image; use crate::values::computed::Number; use crate::values::generics::ui as generics; @@ -16,7 +16,7 @@ pub use crate::values::specified::ui::{MozForceBrokenImageIcon, UserSelect}; pub type Cursor = generics::GenericCursor; /// A computed value for item of `image cursors`. -pub type CursorImage = generics::GenericCursorImage; +pub type CursorImage = generics::GenericCursorImage; /// A computed value for `scrollbar-color` property. pub type ScrollbarColor = generics::GenericScrollbarColor; diff --git a/components/style/values/generics/ui.rs b/components/style/values/generics/ui.rs index 04c2951c70b..ff6aefdc63e 100644 --- a/components/style/values/generics/ui.rs +++ b/components/style/values/generics/ui.rs @@ -61,15 +61,14 @@ impl ToCss for Cursor { Debug, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem, )] #[repr(C)] -pub struct GenericCursorImage { +pub struct GenericCursorImage { /// The url to parse images from. - pub url: ImageUrl, + pub image: Image, /// Whether the image has a hotspot or not. pub has_hotspot: bool, /// The x coordinate. @@ -80,12 +79,12 @@ pub struct GenericCursorImage { pub use self::GenericCursorImage as CursorImage; -impl ToCss for CursorImage { +impl ToCss for CursorImage { fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where W: Write, { - self.url.to_css(dest)?; + self.image.to_css(dest)?; if self.has_hotspot { dest.write_str(" ")?; self.hotspot_x.to_css(dest)?; diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index 3ec678cd237..0be0fcd2a0c 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -181,7 +181,7 @@ impl Parse for Image { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { - Image::parse_with_cors_mode(context, input, CorsMode::None, /* allow_none = */ true) + Image::parse_with_cors_mode(context, input, CorsMode::None, /* allow_none = */ true, /* only_url = */ false) } } @@ -191,23 +191,32 @@ impl Image { input: &mut Parser<'i, 't>, cors_mode: CorsMode, allow_none: bool, + only_url: bool, ) -> Result> { if allow_none && input.try_parse(|i| i.expect_ident_matching("none")).is_ok() { return Ok(generic::Image::None); } + if let Ok(url) = input .try_parse(|input| SpecifiedImageUrl::parse_with_cors_mode(context, input, cors_mode)) { return Ok(generic::Image::Url(url)); } - if let Ok(gradient) = input.try_parse(|i| Gradient::parse(context, i)) { - return Ok(generic::Image::Gradient(Box::new(gradient))); - } + if image_set_enabled() { - if let Ok(is) = input.try_parse(|input| ImageSet::parse(context, input, cors_mode)) { + if let Ok(is) = input.try_parse(|input| ImageSet::parse(context, input, cors_mode, only_url)) { return Ok(generic::Image::ImageSet(Box::new(is))); } } + + if only_url { + return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + } + + if let Ok(gradient) = input.try_parse(|i| Gradient::parse(context, i)) { + return Ok(generic::Image::Gradient(Box::new(gradient))); + } + if cross_fade_enabled() { if let Ok(cf) = input.try_parse(|input| CrossFade::parse(context, input, cors_mode)) { return Ok(generic::Image::CrossFade(Box::new(cf))); @@ -264,6 +273,21 @@ impl Image { input, CorsMode::Anonymous, /* allow_none = */ true, + /* only_url = */ false, + ) + } + + /// Provides an alternate method for parsing, but only for urls. + pub fn parse_only_url<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + Self::parse_with_cors_mode( + context, + input, + CorsMode::None, + /* allow_none = */ false, + /* only_url = */ true, ) } } @@ -310,7 +334,7 @@ impl CrossFadeImage { cors_mode: CorsMode, ) -> Result> { if let Ok(image) = input.try_parse(|input| { - Image::parse_with_cors_mode(context, input, cors_mode, /* allow_none = */ false) + Image::parse_with_cors_mode(context, input, cors_mode, /* allow_none = */ false, /* only_url = */ false) }) { return Ok(Self::Image(image)); } @@ -339,10 +363,11 @@ impl ImageSet { context: &ParserContext, input: &mut Parser<'i, 't>, cors_mode: CorsMode, + only_url: bool, ) -> Result> { input.expect_function_matching("image-set")?; let items = input.parse_nested_block(|input| { - input.parse_comma_separated(|input| ImageSetItem::parse(context, input, cors_mode)) + input.parse_comma_separated(|input| ImageSetItem::parse(context, input, cors_mode, only_url)) })?; Ok(Self { selected_index: 0, @@ -356,6 +381,7 @@ impl ImageSetItem { context: &ParserContext, input: &mut Parser<'i, 't>, cors_mode: CorsMode, + only_url: bool, ) -> Result> { let image = match input.try_parse(|i| i.expect_url_or_string()) { Ok(url) => Image::Url(SpecifiedImageUrl::parse_from_string( @@ -364,7 +390,7 @@ impl ImageSetItem { cors_mode, )), Err(..) => Image::parse_with_cors_mode( - context, input, cors_mode, /* allow_none = */ false, + context, input, cors_mode, /* allow_none = */ false, /* only_url = */ only_url )?, }; let resolution = input diff --git a/components/style/values/specified/ui.rs b/components/style/values/specified/ui.rs index 74440a67205..d37fe647976 100644 --- a/components/style/values/specified/ui.rs +++ b/components/style/values/specified/ui.rs @@ -7,17 +7,17 @@ use crate::parser::{Parse, ParserContext}; use crate::values::generics::ui as generics; use crate::values::specified::color::Color; -use crate::values::specified::url::SpecifiedImageUrl; +use crate::values::specified::image::Image; use crate::values::specified::Number; use cssparser::Parser; use std::fmt::{self, Write}; -use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; +use style_traits::{CssWriter, ParseError, SpecifiedValueInfo, StyleParseErrorKind, ToCss}; /// A specified value for the `cursor` property. pub type Cursor = generics::GenericCursor; /// A specified value for item of `image cursors`. -pub type CursorImage = generics::GenericCursorImage; +pub type CursorImage = generics::GenericCursorImage; impl Parse for Cursor { /// cursor: [ [ ]?]# [auto | default | ...] @@ -47,7 +47,7 @@ impl Parse for CursorImage { ) -> Result> { use crate::Zero; - let url = SpecifiedImageUrl::parse(context, input)?; + let image = Image::parse_only_url(context, input)?; let mut has_hotspot = false; let mut hotspot_x = Number::zero(); let mut hotspot_y = Number::zero(); @@ -59,7 +59,7 @@ impl Parse for CursorImage { } Ok(Self { - url, + image, has_hotspot, hotspot_x, hotspot_y, @@ -67,6 +67,10 @@ impl Parse for CursorImage { } } +// This trait is manually implemented because we don't support the whole +// syntax for cursors +impl SpecifiedValueInfo for CursorImage {} + /// Specified value of `-moz-force-broken-image-icon` #[derive( Clone,