diff --git a/layout/reftests/high-contrast/bg-image-div-001.html b/layout/reftests/high-contrast/bg-image-div-001.html index 7be803381977..8764901fb553 100644 --- a/layout/reftests/high-contrast/bg-image-div-001.html +++ b/layout/reftests/high-contrast/bg-image-div-001.html @@ -10,12 +10,12 @@ height: 100px; width: 100px; } - .url { - background-image: url("green.png"); - } .gradient { background-image: linear-gradient(red, red); } + .url { + background-image: url("green.png"); + } .urlGradient { background-image: url("red.png"), linear-gradient(red, red); } diff --git a/layout/reftests/high-contrast/cascade-001.html b/layout/reftests/high-contrast/cascade-001.html new file mode 100644 index 000000000000..9fdf1ae1ae9f --- /dev/null +++ b/layout/reftests/high-contrast/cascade-001.html @@ -0,0 +1,15 @@ + + +
You should see me
diff --git a/layout/reftests/high-contrast/reftest.list b/layout/reftests/high-contrast/reftest.list index fc10ce7d13dc..78d3e3017268 100644 --- a/layout/reftests/high-contrast/reftest.list +++ b/layout/reftests/high-contrast/reftest.list @@ -35,3 +35,5 @@ pref(browser.display.document_color_use,0) needs-focus != selection-001.html sel pref(browser.display.document_color_use,2) == non-themed-button-001.html non-themed-button-001-ref.html pref(browser.display.document_color_use,2) == non-themed-button-002.html non-themed-button-002-ref.html + +!= cascade-001.html about:blank diff --git a/servo/components/style/properties/cascade.rs b/servo/components/style/properties/cascade.rs index da069b28fc6c..9d3660730451 100644 --- a/servo/components/style/properties/cascade.rs +++ b/servo/components/style/properties/cascade.rs @@ -337,94 +337,74 @@ where context.builder.build() } -/// How should a declaration behave when ignoring document colors? -enum DeclarationApplication { - /// We should apply the declaration. - Apply, - /// We should ignore the declaration. - Ignore, - /// We should apply the following declaration, only if any other declaration - /// hasn't set it before. - ApplyUnlessOverriden(PropertyDeclaration), -} +/// For ignored colors mode, we sometimes want to do something equivalent to +/// "revert-or-initial", where we `revert` for a given origin, but then apply a +/// given initial value if nothing in other origins did override it. +/// +/// This is a bit of a clunky way of achieving this. +type DeclarationsToApplyUnlessOverriden = SmallVec::<[PropertyDeclaration; 2]>; -fn application_when_ignoring_colors( +fn tweak_when_ignoring_colors( builder: &StyleBuilder, longhand_id: LonghandId, origin: Origin, - declaration: &PropertyDeclaration, -) -> DeclarationApplication { + declaration: &mut Cow, + declarations_to_apply_unless_overriden: &mut DeclarationsToApplyUnlessOverriden, +) { if !longhand_id.ignored_when_document_colors_disabled() { - return DeclarationApplication::Apply; + return; } let is_ua_or_user_rule = matches!(origin, Origin::User | Origin::UserAgent); if is_ua_or_user_rule { - return DeclarationApplication::Apply; + return; } // Don't override background-color on ::-moz-color-swatch. It is set as an // author style (via the style attribute), but it's pretty important for it // to show up for obvious reasons :) if builder.pseudo.map_or(false, |p| p.is_color_swatch()) && longhand_id == LonghandId::BackgroundColor { - return DeclarationApplication::Apply; + return; } - // Treat background-color a bit differently. If the specified color is - // anything other than a fully transparent color, convert it into the - // Device's default background color. - // Also: for now, we treat background-image a bit differently, too. - // background-image is marked as ignored, but really, we only ignore - // it when backplates are disabled (since then text may be unreadable over - // a background image, if we're ignoring document colors). - // Here we check backplate status to decide if ignoring background-image - // is the right decision. - match *declaration { - // If we've got multiple declarations in the same block, they'll - // get overridden at parse time. We should probably adjust this - // to turn Ignored decls into `none`. See 1619701 + // A few special-cases ahead. + match **declaration { + // We honor color and background-color: transparent, and + // "revert-or-initial" otherwise. PropertyDeclaration::BackgroundColor(ref color) => { if color.is_transparent() { - return DeclarationApplication::Apply; + return; } let color = builder.device.default_background_color(); - DeclarationApplication::ApplyUnlessOverriden( + declarations_to_apply_unless_overriden.push( PropertyDeclaration::BackgroundColor(color.into()) ) } PropertyDeclaration::Color(ref color) => { + // otherwise. if color.0.is_transparent() { - return DeclarationApplication::Apply; - } - if builder.get_parent_inherited_text().clone_color().alpha != 0 { - return DeclarationApplication::Ignore; + return; } let color = builder.device.default_color(); - DeclarationApplication::ApplyUnlessOverriden( + declarations_to_apply_unless_overriden.push( PropertyDeclaration::Color(specified::ColorPropertyValue(color.into())) ) }, - // In the future, if/when we remove the backplate pref, we can remove this - // special case along with the 'ignored_when_colors_disabled=True' mako line - // for the "background-image" property. + // We honor url background-images if backplating. #[cfg(feature = "gecko")] PropertyDeclaration::BackgroundImage(ref bkg) => { use crate::values::generics::image::Image; - // We should only allow images to be rendered in HCM if the backplate pref - // is enabled, and if all the images applied to the background are from URLs. - // If one or more background images aren't from URL's (ie. gradients) - // we should ignore all background-image styling. if static_prefs::pref!("browser.display.permit_backplate") { if bkg.0.iter().all(|image| matches!(*image, Image::Url(..))) { - return DeclarationApplication::Apply; + return; } - return DeclarationApplication::Ignore; - } else { - return DeclarationApplication::Ignore; } }, - _ => DeclarationApplication::Ignore, + _ => {}, } + + *declaration.to_mut() = PropertyDeclaration::css_wide_keyword(longhand_id, CSSWideKeyword::Revert); + } struct Cascade<'a, 'b: 'a> { @@ -502,7 +482,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { let ignore_colors = !self.context.builder.device.use_document_colors(); let mut declarations_to_apply_unless_overriden = - SmallVec::<[PropertyDeclaration; 2]>::new(); + DeclarationsToApplyUnlessOverriden::new(); for (declaration, origin) in declarations { let declaration_id = declaration.id(); @@ -544,26 +524,23 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { continue; } - let declaration = self.substitute_variables_if_needed(declaration); + let mut declaration = self.substitute_variables_if_needed(declaration); // When document colors are disabled, do special handling of // properties that are marked as ignored in that mode. if ignore_colors { - let application = application_when_ignoring_colors( + tweak_when_ignoring_colors( &self.context.builder, longhand_id, origin, - &declaration, + &mut declaration, + &mut declarations_to_apply_unless_overriden, + ); + debug_assert_eq!( + declaration.id(), + PropertyDeclarationId::Longhand(longhand_id), + "Shouldn't change the declaration id!", ); - - match application { - DeclarationApplication::Ignore => continue, - DeclarationApplication::Apply => {}, - DeclarationApplication::ApplyUnlessOverriden(decl) => { - declarations_to_apply_unless_overriden.push(decl); - continue; - } - } } let css_wide_keyword = declaration.get_css_wide_keyword(); diff --git a/servo/components/style/properties/properties.mako.rs b/servo/components/style/properties/properties.mako.rs index d3e618675181..a232b275c88a 100644 --- a/servo/components/style/properties/properties.mako.rs +++ b/servo/components/style/properties/properties.mako.rs @@ -1590,10 +1590,7 @@ impl UnparsedValue { } else { CSSWideKeyword::Initial }; - PropertyDeclaration::CSSWideKeyword(WideKeywordDeclaration { - id: longhand_id, - keyword, - }) + PropertyDeclaration::css_wide_keyword(longhand_id, keyword) }; let css = match crate::custom_properties::substitute( @@ -1630,10 +1627,7 @@ impl UnparsedValue { let mut input = Parser::new(&mut input); input.skip_whitespace(); // Unnecessary for correctness, but may help try() rewind less. if let Ok(keyword) = input.try(CSSWideKeyword::parse) { - return PropertyDeclaration::CSSWideKeyword(WideKeywordDeclaration { - id: longhand_id, - keyword, - }); + return PropertyDeclaration::css_wide_keyword(longhand_id, keyword); } let declaration = input.parse_entirely(|input| { @@ -2239,6 +2233,12 @@ impl PropertyDeclaration { } } + /// Returns a CSS-wide keyword declaration for a given property. + #[inline] + pub fn css_wide_keyword(id: LonghandId, keyword: CSSWideKeyword) -> Self { + Self::CSSWideKeyword(WideKeywordDeclaration { id, keyword }) + } + /// Returns a CSS-wide keyword if the declaration's value is one. #[inline] pub fn get_css_wide_keyword(&self) -> Option { @@ -2367,9 +2367,7 @@ impl PropertyDeclaration { PropertyId::Longhand(id) => { input.skip_whitespace(); // Unnecessary for correctness, but may help try() rewind less. input.try(CSSWideKeyword::parse).map(|keyword| { - PropertyDeclaration::CSSWideKeyword( - WideKeywordDeclaration { id, keyword }, - ) + PropertyDeclaration::css_wide_keyword(id, keyword) }).or_else(|()| { input.look_for_var_or_env_functions(); input.parse_entirely(|input| id.parse_value(context, input)) @@ -2403,12 +2401,7 @@ impl PropertyDeclaration { declarations.all_shorthand = AllShorthand::CSSWideKeyword(keyword) } else { for longhand in id.longhands() { - declarations.push(PropertyDeclaration::CSSWideKeyword( - WideKeywordDeclaration { - id: longhand, - keyword, - }, - )) + declarations.push(PropertyDeclaration::css_wide_keyword(longhand, keyword)); } } } else { @@ -2550,12 +2543,7 @@ impl<'a> Iterator for AllShorthandDeclarationIterator<'a> { match *self.all_shorthand { AllShorthand::NotSet => None, AllShorthand::CSSWideKeyword(ref keyword) => { - Some(PropertyDeclaration::CSSWideKeyword( - WideKeywordDeclaration { - id: self.longhands.next()?, - keyword: *keyword - } - )) + Some(PropertyDeclaration::css_wide_keyword(self.longhands.next()?, *keyword)) } AllShorthand::WithVariables(ref unparsed) => { Some(PropertyDeclaration::WithVariables(