Fix incorrect ANSI color contrast adjustment on some background colors (#38155)

The `Hsla` -> `Rgba` conversion sometimes results in negative (but very
close to 0) color components due to floating point imprecision, causing
the `.powf(constants.main_trc)` computations in the `srgb_to_y` function
to evaluate to `NaN`. This propagates to `apca_contrast` which then
makes `ensure_minimum_contrast` unconditionally return `black` for
certain background colors. This PR addresses this by clamping the rgba
components in `impl From<Hsla> for Rgba` to 0-1.

Before/after:
<img width="1044" height="48" alt="before"
src="https://github.com/user-attachments/assets/771f809f-3959-43e9-8ed0-152ff284cef8"
/>
<img width="1044" height="49" alt="after"
src="https://github.com/user-attachments/assets/5fd6ae25-1ef0-4334-90d1-7fc5acf48958"
/>

Release Notes:

- Fixed an issue where ANSI colors were incorrectly adjusted to improve
contrast on some background colors
This commit is contained in:
Tim Vermeulen
2025-09-15 07:52:56 +00:00
committed by GitHub
parent 0fef17baa2
commit 5b1c87b6a6
2 changed files with 10 additions and 3 deletions
+3 -3
View File
@@ -151,9 +151,9 @@ impl From<Hsla> for Rgba {
};
Rgba {
r,
g,
b,
r: r.clamp(0., 1.),
g: g.clamp(0., 1.),
b: b.clamp(0., 1.),
a: color.a,
}
}
+7
View File
@@ -393,6 +393,13 @@ mod tests {
);
}
#[test]
fn test_srgb_to_y_nan_issue() {
let dark_red = hsla_from_hex(0x5f0000);
let y_dark_red = srgb_to_y(dark_red, &APCAConstants::default());
assert!(!y_dark_red.is_nan());
}
#[test]
fn test_ensure_minimum_contrast() {
let white_bg = hsla(0.0, 0.0, 1.0, 1.0);