diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index a1109e741353..9d45a549e317 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -229,7 +229,11 @@ static Maybe GetBackplateColor(nsIFrame* aFrame) { } nscolor backgroundColor = bg->BackgroundColor(frame); if (NS_GET_A(backgroundColor) != 0) { - return Some(backgroundColor); + // NOTE: We intentionally disregard the alpha channel here for the purpose + // of the backplate, in order to guarantee contrast. + return Some(NS_RGB(NS_GET_R(backgroundColor), + NS_GET_G(backgroundColor), + NS_GET_B(backgroundColor))); } break; } diff --git a/layout/reftests/high-contrast/reftest.list b/layout/reftests/high-contrast/reftest.list index 8f9e98af6b87..f3e06fbb6732 100644 --- a/layout/reftests/high-contrast/reftest.list +++ b/layout/reftests/high-contrast/reftest.list @@ -33,6 +33,8 @@ pref(browser.display.document_color_use,0) needs-focus != selection-001.html sel == color-transparent-001.html about:blank != color-transparent-002.html about:blank +!= semi-transparent-overlay.html about:blank +!= semi-transparent-overlay.html semi-transparent-background.html == links.html links-ref.html == links-2.html links-ref.html diff --git a/layout/reftests/high-contrast/semi-transparent-background.html b/layout/reftests/high-contrast/semi-transparent-background.html new file mode 100644 index 000000000000..8902d19fcb0c --- /dev/null +++ b/layout/reftests/high-contrast/semi-transparent-background.html @@ -0,0 +1,11 @@ + + +
+ + Some text that you should be able to read. +
diff --git a/layout/reftests/high-contrast/semi-transparent-overlay.html b/layout/reftests/high-contrast/semi-transparent-overlay.html new file mode 100644 index 000000000000..76f2542ee4a7 --- /dev/null +++ b/layout/reftests/high-contrast/semi-transparent-overlay.html @@ -0,0 +1,15 @@ + + +
+ + Some text that you should be able to read. +
diff --git a/servo/components/style/properties/cascade.rs b/servo/components/style/properties/cascade.rs index 0a84f7e894dd..8fbccd1d97f1 100644 --- a/servo/components/style/properties/cascade.rs +++ b/servo/components/style/properties/cascade.rs @@ -385,6 +385,8 @@ fn tweak_when_ignoring_colors( declaration: &mut Cow, declarations_to_apply_unless_overriden: &mut DeclarationsToApplyUnlessOverriden, ) { + use crate::values::specified::Color; + if !longhand_id.ignored_when_document_colors_disabled() { return; } @@ -401,21 +403,53 @@ fn tweak_when_ignoring_colors( return; } + fn alpha_channel(color: &Color) -> u8 { + match *color { + // Seems safe enough to assume that the default color and system + // colors are opaque in HCM, though maybe we shouldn't asume the + // later? + #[cfg(feature = "gecko")] + Color::InheritFromBodyQuirk | Color::System(..) => 255, + // We don't have the actual color here, but since except for color: + // transparent we force opaque text colors, it seems sane to do + // this. You can technically fool this bit of code with: + // + // color: transparent; background-color: currentcolor; + // + // but this is best-effort, and that seems unlikely to happen in + // practice. + Color::CurrentColor => 255, + // Complex colors are results of interpolation only and probably + // shouldn't show up around here in HCM, but we've always treated + // them as opaque effectively so keep doing it. + Color::Complex { .. } => 255, + Color::Numeric { ref parsed, .. } => parsed.alpha, + } + } + // 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() { - let color = builder.device.default_background_color(); + // For background-color, we revert or initial-with-preserved-alpha + // otherwise, this is needed to preserve semi-transparent + // backgrounds. + // + // FIXME(emilio, bug 1666059): We revert for alpha == 0, but maybe + // should consider not doing that even if it causes some issues like + // bug 1625036, or finding a performant way to preserve the original + // widget background color's rgb channels but not alpha... + let alpha = alpha_channel(color); + if alpha != 0 { + let mut color = builder.device.default_background_color(); + color.alpha = alpha; declarations_to_apply_unless_overriden.push( PropertyDeclaration::BackgroundColor(color.into()) ) } } PropertyDeclaration::Color(ref color) => { - // otherwise. - if color.0.is_transparent() { + // We honor color: transparent, and "revert-or-initial" otherwise. + if alpha_channel(&color.0) == 0 { return; } // If the inherited color would be transparent, but we would diff --git a/servo/components/style/values/specified/color.rs b/servo/components/style/values/specified/color.rs index 59184775c84b..675e1b9a1314 100644 --- a/servo/components/style/values/specified/color.rs +++ b/servo/components/style/values/specified/color.rs @@ -529,15 +529,6 @@ impl Color { parse_hash_color(&serialization) .map_err(|()| location.new_custom_error(StyleParseErrorKind::UnspecifiedError)) } - - /// Returns true if the color is completely transparent, and false - /// otherwise. - pub fn is_transparent(&self) -> bool { - match *self { - Color::Numeric { ref parsed, .. } => parsed.alpha == 0, - _ => false, - } - } } #[cfg(feature = "gecko")]