LibWeb: Support relative lengths in calc color values

Gains us ~40 WPT tests.
This commit is contained in:
Callum Law 2025-06-29 17:18:05 +12:00 committed by Sam Atkins
commit 9ab7c5d08d
Notes: github-actions[bot] 2025-07-04 12:20:09 +00:00
17 changed files with 169 additions and 74 deletions

View file

@ -226,7 +226,7 @@ Color ComputedProperties::color_or_fallback(PropertyID id, Layout::NodeWithStyle
auto const& value = property(id);
if (!value.has_color())
return fallback;
return value.to_color(node, {});
return value.to_color(node, { .length_resolution_context = Length::ResolutionContext::for_layout_node(node) });
}
// https://drafts.csswg.org/css-color-adjust-1/#determine-the-used-color-scheme
@ -670,7 +670,7 @@ Optional<Color> ComputedProperties::accent_color(Layout::NodeWithStyle const& no
{
auto const& value = property(PropertyID::AccentColor);
if (value.has_color())
return value.to_color(node, {});
return value.to_color(node, { .length_resolution_context = Length::ResolutionContext::for_layout_node(node) });
return {};
}
@ -924,7 +924,7 @@ Color ComputedProperties::caret_color(Layout::NodeWithStyle const& node) const
return node.computed_values().color();
if (value.has_color())
return value.to_color(node, {});
return value.to_color(node, { .length_resolution_context = Length::ResolutionContext::for_layout_node(node) });
return InitialValues::caret_color();
}
@ -1187,7 +1187,7 @@ Vector<ShadowData> ComputedProperties::shadow(PropertyID property_id, Layout::No
maybe_offset_y.release_value(),
maybe_blur_radius.release_value(),
maybe_spread_distance.release_value(),
value.color()->to_color(as<Layout::NodeWithStyle>(layout_node), {}),
value.color()->to_color(as<Layout::NodeWithStyle>(layout_node), { .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }),
value.placement()
};
};
@ -1807,8 +1807,9 @@ Color ComputedProperties::stop_color() const
value = property(PropertyID::Color);
}
if (value->has_color()) {
// FIXME: This is used by the SVGStopElement, which does not participate in layout,
// so can't pass a layout node (so can't resolve some colors, e.g. palette ones)
// FIXME: This is used by the SVGStopElement, which does not participate in layout, so we can't pass a layout
// node or CalculationResolutionContext. This means we don't support all valid colors (e.g. palette
// colors, calculated values which depend on length resolution, etc)
return value->to_color({}, {});
}
return Color::Black;
@ -1893,8 +1894,8 @@ ScrollbarColorData ComputedProperties::scrollbar_color(Layout::NodeWithStyle con
if (value.is_scrollbar_color()) {
auto& scrollbar_color_value = value.as_scrollbar_color();
auto thumb_color = scrollbar_color_value.thumb_color()->to_color(layout_node, {});
auto track_color = scrollbar_color_value.track_color()->to_color(layout_node, {});
auto thumb_color = scrollbar_color_value.thumb_color()->to_color(layout_node, { .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) });
auto track_color = scrollbar_color_value.track_color()->to_color(layout_node, { .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) });
return { thumb_color, track_color };
}

View file

@ -659,6 +659,13 @@ RefPtr<CSSStyleValue const> interpolate_box_shadow(DOM::Element& element, Calcul
StyleValueVector result_shadows;
result_shadows.ensure_capacity(from_shadows.size());
Optional<Layout::NodeWithStyle const&> layout_node;
CalculationResolutionContext resolution_context;
if (auto node = element.layout_node()) {
layout_node = *node;
resolution_context.length_resolution_context = Length::ResolutionContext::for_layout_node(*node);
}
for (size_t i = 0; i < from_shadows.size(); i++) {
auto const& from_shadow = from_shadows[i]->as_shadow();
auto const& to_shadow = to_shadows[i]->as_shadow();
@ -669,7 +676,7 @@ RefPtr<CSSStyleValue const> interpolate_box_shadow(DOM::Element& element, Calcul
if (!interpolated_offset_x || !interpolated_offset_y || !interpolated_blur_radius || !interpolated_spread_distance)
return {};
auto result_shadow = ShadowStyleValue::create(
CSSColorValue::create_from_color(interpolate_color(from_shadow.color()->to_color({}, {}), to_shadow.color()->to_color({}, {}), 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), ColorSyntax::Modern),
*interpolated_offset_x,
*interpolated_offset_y,
*interpolated_blur_radius,
@ -781,9 +788,13 @@ static RefPtr<CSSStyleValue const> interpolate_value_impl(DOM::Element& element,
}
case CSSStyleValue::Type::Color: {
Optional<Layout::NodeWithStyle const&> layout_node;
if (auto node = element.layout_node())
CalculationResolutionContext resolution_context {};
if (auto node = element.layout_node()) {
layout_node = *node;
return CSSColorValue::create_from_color(interpolate_color(from.to_color(layout_node, {}), to.to_color(layout_node, {}), delta), ColorSyntax::Modern);
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);
}
case CSSStyleValue::Type::Edge: {
auto resolved_from = from.as_edge().resolved_value(calculation_context);

View file

@ -5113,6 +5113,7 @@ RefPtr<CSSStyleValue const> Parser::parse_filter_value_list_value(TokenStream<Co
}
Optional<Color> color = {};
if (maybe_color)
// FIXME: We should support colors which require compute-time information (i.e. `em` and `vw` to `px` ratios).
color = maybe_color->to_color({}, {});
return if_no_more_tokens_return(FilterOperation::DropShadow { x_offset.value(), y_offset.value(), maybe_radius, color });