mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-11 03:56:16 +00:00
LibWeb: Interpolate legacy colors in sRGB
This commit is contained in:
parent
c18314b942
commit
1b7323fc2d
Notes:
github-actions[bot]
2025-07-04 14:29:15 +00:00
Author: https://github.com/Gingeh
Commit: 1b7323fc2d
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5285
Reviewed-by: https://github.com/AtkinsSJ ✅
Reviewed-by: https://github.com/tcl3 ✅
8 changed files with 137 additions and 113 deletions
|
@ -595,23 +595,36 @@ RefPtr<CSSStyleValue const> interpolate_transform(DOM::Element& element, CSSStyl
|
|||
return StyleValueList::create({ TransformationStyleValue::create(PropertyID::Transform, TransformFunction::Matrix3d, move(values)) }, StyleValueList::Separator::Comma);
|
||||
}
|
||||
|
||||
Color interpolate_color(Color from, Color to, float delta)
|
||||
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.
|
||||
|
||||
// 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.
|
||||
// However, user agents must handle interpolation between legacy sRGB color formats (hex colors, named colors,
|
||||
// rgb(), hsl() or hwb() and the equivalent alpha-including forms) in gamma-encoded sRGB space. This provides
|
||||
// Web compatibility; legacy sRGB content interpolates in the sRGB space by default.
|
||||
// FIXME: Use srgb by default for these, once we can distinguish what form a color was specified in.
|
||||
auto from_oklab = from.to_oklab();
|
||||
auto to_oklab = to.to_oklab();
|
||||
|
||||
auto color = 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));
|
||||
color.set_alpha(interpolate_raw(from.alpha(), to.alpha(), delta));
|
||||
return color;
|
||||
Color result;
|
||||
if (syntax == ColorSyntax::Modern) {
|
||||
auto from_oklab = from.to_oklab();
|
||||
auto to_oklab = to.to_oklab();
|
||||
|
||||
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));
|
||||
} else {
|
||||
result = Color {
|
||||
interpolate_raw(from.red(), to.red(), delta),
|
||||
interpolate_raw(from.green(), to.green(), delta),
|
||||
interpolate_raw(from.blue(), to.blue(), delta),
|
||||
};
|
||||
}
|
||||
result.set_alpha(interpolate_raw(from.alpha(), to.alpha(), delta));
|
||||
return result;
|
||||
}
|
||||
|
||||
RefPtr<CSSStyleValue const> interpolate_box_shadow(DOM::Element& element, CalculationContext const& calculation_context, CSSStyleValue const& from, CSSStyleValue const& to, float delta, AllowDiscrete allow_discrete)
|
||||
|
@ -675,8 +688,13 @@ RefPtr<CSSStyleValue const> interpolate_box_shadow(DOM::Element& element, Calcul
|
|||
auto interpolated_spread_distance = interpolate_value(element, calculation_context, from_shadow.spread_distance(), to_shadow.spread_distance(), delta, allow_discrete);
|
||||
if (!interpolated_offset_x || !interpolated_offset_y || !interpolated_blur_radius || !interpolated_spread_distance)
|
||||
return {};
|
||||
auto color_syntax = ColorSyntax::Legacy;
|
||||
if ((!from_shadow.color()->is_keyword() && from_shadow.color()->as_color().color_syntax() == ColorSyntax::Modern)
|
||||
|| (!to_shadow.color()->is_keyword() && to_shadow.color()->as_color().color_syntax() == ColorSyntax::Modern)) {
|
||||
color_syntax = ColorSyntax::Modern;
|
||||
}
|
||||
auto result_shadow = ShadowStyleValue::create(
|
||||
CSSColorValue::create_from_color(interpolate_color(from_shadow.color()->to_color(layout_node, resolution_context), to_shadow.color()->to_color(layout_node, resolution_context), delta), ColorSyntax::Modern),
|
||||
CSSColorValue::create_from_color(interpolate_color(from_shadow.color()->to_color(layout_node, resolution_context), to_shadow.color()->to_color(layout_node, resolution_context), delta, color_syntax), ColorSyntax::Modern),
|
||||
*interpolated_offset_x,
|
||||
*interpolated_offset_y,
|
||||
*interpolated_blur_radius,
|
||||
|
@ -794,7 +812,12 @@ static RefPtr<CSSStyleValue const> interpolate_value_impl(DOM::Element& element,
|
|||
resolution_context.length_resolution_context = Length::ResolutionContext::for_layout_node(*node);
|
||||
}
|
||||
|
||||
return CSSColorValue::create_from_color(interpolate_color(from.to_color(layout_node, resolution_context), to.to_color(layout_node, resolution_context), delta), ColorSyntax::Modern);
|
||||
auto color_syntax = ColorSyntax::Legacy;
|
||||
if ((!from.is_keyword() && from.as_color().color_syntax() == ColorSyntax::Modern)
|
||||
|| (!to.is_keyword() && to.as_color().color_syntax() == ColorSyntax::Modern)) {
|
||||
color_syntax = ColorSyntax::Modern;
|
||||
}
|
||||
return CSSColorValue::create_from_color(interpolate_color(from.to_color(layout_node, resolution_context), to.to_color(layout_node, resolution_context), delta, color_syntax), ColorSyntax::Modern);
|
||||
}
|
||||
case CSSStyleValue::Type::Edge: {
|
||||
auto resolved_from = from.as_edge().resolved_value(calculation_context);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <LibWeb/CSS/CSSStyleValue.h>
|
||||
#include <LibWeb/CSS/Enums.h>
|
||||
#include <LibWeb/CSS/StyleValues/CSSColorValue.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
@ -28,6 +29,6 @@ RefPtr<CSSStyleValue const> interpolate_repeatable_list(DOM::Element&, Calculati
|
|||
RefPtr<CSSStyleValue const> interpolate_box_shadow(DOM::Element&, CalculationContext const&, CSSStyleValue const& from, CSSStyleValue const& to, float delta, AllowDiscrete);
|
||||
RefPtr<CSSStyleValue const> interpolate_transform(DOM::Element&, CSSStyleValue const& from, CSSStyleValue const& to, float delta, AllowDiscrete);
|
||||
|
||||
Color interpolate_color(Color from, Color to, float delta);
|
||||
Color interpolate_color(Color from, Color to, float delta, ColorSyntax syntax);
|
||||
|
||||
}
|
||||
|
|
|
@ -177,13 +177,13 @@ ColorMixStyleValue::PercentageNormalizationResult ColorMixStyleValue::normalize_
|
|||
// https://drafts.csswg.org/css-color-5/#color-mix-result
|
||||
Color ColorMixStyleValue::to_color(Optional<Layout::NodeWithStyle const&> node, CalculationResolutionContext const& resolution_context) const
|
||||
{
|
||||
// FIXME: Do this in a spec-compliant way.
|
||||
// Our color interpolation doesn't currently take the color space or hue interpolation method into account.
|
||||
// FIXME: Take the color space and hue interpolation method into account.
|
||||
// The current implementation only uses oklab interpolation.
|
||||
auto normalized_percentages = normalize_percentages();
|
||||
auto from_color = m_properties.first_component.color->to_color(node, resolution_context);
|
||||
auto to_color = m_properties.second_component.color->to_color(node, resolution_context);
|
||||
auto from_color = m_properties.first_component.color;
|
||||
auto to_color = m_properties.second_component.color;
|
||||
auto delta = normalized_percentages.p2.value() / 100;
|
||||
return interpolate_color(from_color, to_color, delta);
|
||||
return interpolate_color(from_color->to_color(node, resolution_context), to_color->to_color(node, resolution_context), delta, ColorSyntax::Modern);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue