commit 557d0a01bb2823242b71b265fbe2ee4f269817f4
parent a370a87a48baa8be994f40b7eb2e6281765e0ef8
Author: Kiril Panayotov <contact@zakrok.dev>
Date: Mon, 8 Dec 2025 12:43:42 +0000
Bug 2001615 - Fix carry forward to not override flags from conversion. r=tlouw,emilio,firefox-style-system-reviewers
The bug occurs because any flags about missing components, generated during conversion of the colour (e.g. HSL->OKLCH it can produce a powerless hue) within are overridden by the source colour's flags.
The change is to make it instead by a disjunction of the source color flag and the flag of the color itself.
Differential Revision: https://phabricator.services.mozilla.com/D275400
Diffstat:
2 files changed, 21 insertions(+), 20 deletions(-)
diff --git a/servo/components/style/color/mix.rs b/servo/components/style/color/mix.rs
@@ -252,43 +252,43 @@ impl AbsoluteColor {
// Lightness L
if matches!(source.color_space, S::Lab | S::Lch | S::Oklab | S::Oklch) {
if matches!(self.color_space, S::Lab | S::Lch | S::Oklab | S::Oklch) {
- self.flags
- .set(F::C0_IS_NONE, source.flags.contains(F::C0_IS_NONE));
+ self.flags |= source.flags & F::C0_IS_NONE;
} else if matches!(self.color_space, S::Hsl) {
- self.flags
- .set(F::C2_IS_NONE, source.flags.contains(F::C0_IS_NONE));
+ if source.flags.contains(F::C0_IS_NONE) {
+ self.flags.insert(F::C2_IS_NONE)
+ }
}
} else if matches!(source.color_space, S::Hsl)
&& matches!(self.color_space, S::Lab | S::Lch | S::Oklab | S::Oklch)
{
- self.flags
- .set(F::C0_IS_NONE, source.flags.contains(F::C2_IS_NONE));
+ if source.flags.contains(F::C2_IS_NONE) {
+ self.flags.insert(F::C0_IS_NONE)
+ }
}
// Colorfulness C, S
if matches!(source.color_space, S::Hsl | S::Lch | S::Oklch)
&& matches!(self.color_space, S::Hsl | S::Lch | S::Oklch)
{
- self.flags
- .set(F::C1_IS_NONE, source.flags.contains(F::C1_IS_NONE));
+ self.flags |= source.flags & F::C1_IS_NONE;
}
// Hue H
if matches!(source.color_space, S::Hsl | S::Hwb) {
if matches!(self.color_space, S::Hsl | S::Hwb) {
- self.flags
- .set(F::C0_IS_NONE, source.flags.contains(F::C0_IS_NONE));
+ self.flags |= source.flags & F::C0_IS_NONE;
} else if matches!(self.color_space, S::Lch | S::Oklch) {
- self.flags
- .set(F::C2_IS_NONE, source.flags.contains(F::C0_IS_NONE));
+ if source.flags.contains(F::C0_IS_NONE) {
+ self.flags.insert(F::C2_IS_NONE)
+ }
}
} else if matches!(source.color_space, S::Lch | S::Oklch) {
if matches!(self.color_space, S::Hsl | S::Hwb) {
- self.flags
- .set(F::C0_IS_NONE, source.flags.contains(F::C2_IS_NONE));
+ if source.flags.contains(F::C2_IS_NONE) {
+ self.flags.insert(F::C0_IS_NONE)
+ }
} else if matches!(self.color_space, S::Lch | S::Oklch) {
- self.flags
- .set(F::C2_IS_NONE, source.flags.contains(F::C2_IS_NONE));
+ self.flags |= source.flags & F::C2_IS_NONE;
}
}
@@ -297,10 +297,8 @@ impl AbsoluteColor {
if matches!(source.color_space, S::Lab | S::Oklab)
&& matches!(self.color_space, S::Lab | S::Oklab)
{
- self.flags
- .set(F::C1_IS_NONE, source.flags.contains(F::C1_IS_NONE));
- self.flags
- .set(F::C2_IS_NONE, source.flags.contains(F::C2_IS_NONE));
+ self.flags |= source.flags & F::C1_IS_NONE;
+ self.flags |= source.flags & F::C2_IS_NONE;
}
}
}
diff --git a/testing/web-platform/tests/css/css-color/parsing/color-computed-color-mix-function.html b/testing/web-platform/tests/css/css-color/parsing/color-computed-color-mix-function.html
@@ -568,6 +568,9 @@
// Percent with calc that uses font-relative length.
fuzzy_test_computed_color(`color-mix(in srgb, red calc(50% + (sign(100em - 1px) * 10%)), blue)`, `color(srgb 0.6 0 0.4)`);
+
+ // Carry forward hue that became powerless due to conversion of colorspace
+ fuzzy_test_computed_color(`color-mix(in oklch, hsl(0 100% 100%), blue)`, `oklch(0.726007 0.156607 264.052)`);
</script>
</body>
</html>