mirror of
https://github.com/zebrajr/ladybird.git
synced 2025-12-06 00:19:53 +01:00
LibWeb: Fix color interpolation by premultiplying alpha
The current Color::interpolate_color method does not follow the specs properly. Started improving it by handling premultiplied alpha in color interpolation. Only one WPT test covers this (color-transition-premultiplied), which we currently pass due to a different approach in Color.mixed_with.
This commit is contained in:
parent
d91d28dc2a
commit
783ae44462
|
|
@ -236,6 +236,16 @@ public:
|
|||
return from_linear_srgb(red, green, blue, alpha);
|
||||
}
|
||||
|
||||
constexpr Oklab to_premultiplied_oklab()
|
||||
{
|
||||
auto oklab = to_oklab();
|
||||
return {
|
||||
oklab.L * alpha() / 255,
|
||||
oklab.a * alpha() / 255,
|
||||
oklab.b * alpha() / 255,
|
||||
};
|
||||
}
|
||||
|
||||
// https://bottosson.github.io/posts/oklab/
|
||||
constexpr Oklab to_oklab()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -890,6 +890,7 @@ Color interpolate_color(Color from, Color to, float delta, ColorSyntax syntax)
|
|||
// https://drafts.csswg.org/css-color/#interpolation
|
||||
// FIXME: Handle all interpolation methods.
|
||||
// FIXME: Handle "analogous", "missing", and "powerless" components, somehow.
|
||||
// FIXME: Remove duplicated code with Color::mixed_with(Color other, float weight)
|
||||
|
||||
// https://drafts.csswg.org/css-color/#interpolation-space
|
||||
// If the host syntax does not define what color space interpolation should take place in, it defaults to Oklab.
|
||||
|
|
@ -899,21 +900,30 @@ Color interpolate_color(Color from, Color to, float delta, ColorSyntax syntax)
|
|||
|
||||
Color result;
|
||||
if (syntax == ColorSyntax::Modern) {
|
||||
auto from_oklab = from.to_oklab();
|
||||
auto to_oklab = to.to_oklab();
|
||||
// 5. changing the color components to premultiplied form
|
||||
auto from_oklab = from.to_premultiplied_oklab();
|
||||
auto to_oklab = to.to_premultiplied_oklab();
|
||||
|
||||
// 6. linearly interpolating each component of the computed value of the color separately
|
||||
// 7. undoing premultiplication
|
||||
auto from_alpha = from.alpha() / 255.0f;
|
||||
auto to_alpha = to.alpha() / 255.0f;
|
||||
auto interpolated_alpha = interpolate_raw(from_alpha, to_alpha, delta);
|
||||
|
||||
result = Color::from_oklab(
|
||||
interpolate_raw(from_oklab.L, to_oklab.L, delta),
|
||||
interpolate_raw(from_oklab.a, to_oklab.a, delta),
|
||||
interpolate_raw(from_oklab.b, to_oklab.b, delta));
|
||||
interpolate_raw(from_oklab.L, to_oklab.L, delta) / interpolated_alpha,
|
||||
interpolate_raw(from_oklab.a, to_oklab.a, delta) / interpolated_alpha,
|
||||
interpolate_raw(from_oklab.b, to_oklab.b, delta) / interpolated_alpha,
|
||||
interpolated_alpha);
|
||||
} else {
|
||||
result = Color {
|
||||
interpolate_raw(from.red(), to.red(), delta),
|
||||
interpolate_raw(from.green(), to.green(), delta),
|
||||
interpolate_raw(from.blue(), to.blue(), delta),
|
||||
interpolate_raw(from.alpha(), to.alpha(), delta)
|
||||
};
|
||||
}
|
||||
result.set_alpha(interpolate_raw(from.alpha(), to.alpha(), delta));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
rgba(255, 0, 0, 0.1)
|
||||
11
Tests/LibWeb/Text/input/interpolate-alpha-premultiplied.html
Normal file
11
Tests/LibWeb/Text/input/interpolate-alpha-premultiplied.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="include.js"></script>
|
||||
<script>
|
||||
test(() => {
|
||||
const div = document.createElement('div');
|
||||
div.style.backgroundColor = 'color-mix(in oklab, red 10%, transparent)';
|
||||
document.body.appendChild(div);
|
||||
|
||||
println(getComputedStyle(div).backgroundColor);
|
||||
});
|
||||
</script>
|
||||
Loading…
Reference in New Issue
Block a user