Bug 1668029 - When resetting background color for high contrast, preserve alpha channel appropriately. r=morgan

But discard it when backplating behind text, so that text is readable.

This should be uncontroversial... Dealing with widgets is a bit harder
so TBD.

Differential Revision: https://phabricator.services.mozilla.com/D91779
This commit is contained in:
Emilio Cobos Álvarez 2020-09-29 22:04:56 +00:00
Родитель 47694b3690
Коммит 0967845f95
6 изменённых файлов: 73 добавлений и 16 удалений

Просмотреть файл

@ -229,7 +229,11 @@ static Maybe<nscolor> 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;
}

Просмотреть файл

@ -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

Просмотреть файл

@ -0,0 +1,11 @@
<!doctype html>
<style>
.container {
position: relative;
background-color: rgba(0, 0, 0, .2);
}
</style>
<div class="container">
<a href="#"></a>
Some text that you should be able to read.
</div>

Просмотреть файл

@ -0,0 +1,15 @@
<!doctype html>
<style>
.container {
position: relative;
}
a {
position: absolute;
inset: 0;
background-color: rgba(0, 0, 0, .2);
}
</style>
<div class="container">
<a href="#"></a>
Some text that you should be able to read.
</div>

Просмотреть файл

@ -385,6 +385,8 @@ fn tweak_when_ignoring_colors(
declaration: &mut Cow<PropertyDeclaration>,
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

Просмотреть файл

@ -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")]