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(