LibWeb: Support relative lengths in stop-color calcs

This commit is contained in:
Callum Law 2025-07-19 16:00:37 +12:00 committed by Sam Atkins
commit 3b52b1139a
Notes: github-actions[bot] 2025-08-04 10:30:24 +00:00
7 changed files with 32 additions and 25 deletions

View file

@ -1813,24 +1813,6 @@ MaskType ComputedProperties::mask_type() const
return keyword_to_mask_type(value.to_keyword()).release_value(); return keyword_to_mask_type(value.to_keyword()).release_value();
} }
Color ComputedProperties::stop_color() const
{
NonnullRawPtr<CSSStyleValue const> value = property(PropertyID::StopColor);
if (value->is_keyword()) {
// Workaround lack of layout node to resolve current color.
auto const& keyword = value->as_keyword();
if (keyword.keyword() == Keyword::Currentcolor)
value = property(PropertyID::Color);
}
if (value->has_color()) {
// 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({}).value_or(Color::Black);
}
return Color::Black;
}
void ComputedProperties::set_math_depth(int math_depth) void ComputedProperties::set_math_depth(int math_depth)
{ {
m_math_depth = math_depth; m_math_depth = math_depth;

View file

@ -185,7 +185,6 @@ public:
Optional<Transformation> scale() const; Optional<Transformation> scale() const;
MaskType mask_type() const; MaskType mask_type() const;
Color stop_color() const;
float stop_opacity() const; float stop_opacity() const;
float fill_opacity() const; float fill_opacity() const;
StrokeLinecap stroke_linecap() const; StrokeLinecap stroke_linecap() const;

View file

@ -881,8 +881,9 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style)
computed_values.set_stroke(stroke.to_color(CSS::ColorResolutionContext::for_layout_node_with_style(*this)).value()); computed_values.set_stroke(stroke.to_color(CSS::ColorResolutionContext::for_layout_node_with_style(*this)).value());
else if (stroke.is_url()) else if (stroke.is_url())
computed_values.set_stroke(stroke.as_url().url()); computed_values.set_stroke(stroke.as_url().url());
if (auto const& stop_color = computed_style.property(CSS::PropertyID::StopColor); stop_color.has_color())
computed_values.set_stop_color(stop_color.to_color(CSS::ColorResolutionContext::for_layout_node_with_style(*this)).value()); computed_values.set_stop_color(computed_style.color_or_fallback(CSS::PropertyID::StopColor, CSS::ColorResolutionContext::for_layout_node_with_style(*this), CSS::InitialValues::stop_color()));
auto const& stroke_width = computed_style.property(CSS::PropertyID::StrokeWidth); auto const& stroke_width = computed_style.property(CSS::PropertyID::StrokeWidth);
// FIXME: Converting to pixels isn't really correct - values should be in "user units" // FIXME: Converting to pixels isn't really correct - values should be in "user units"
// https://svgwg.org/svg2-draft/coords.html#TermUserUnits // https://svgwg.org/svg2-draft/coords.html#TermUserUnits

View file

@ -46,11 +46,11 @@ void SVGStopElement::apply_presentational_hints(GC::Ref<CSS::CascadedProperties>
}); });
} }
Gfx::Color SVGStopElement::stop_color() const Gfx::Color SVGStopElement::stop_color()
{ {
if (auto computed_properties = this->computed_properties()) if (auto computed_properties = this->computed_properties())
return computed_properties->stop_color(); return computed_properties->color_or_fallback(CSS::PropertyID::StopColor, CSS::ColorResolutionContext::for_element({ *this }), CSS::InitialValues::stop_color());
return Color::Black; return CSS::InitialValues::stop_color();
} }
float SVGStopElement::stop_opacity() const float SVGStopElement::stop_opacity() const

View file

@ -27,7 +27,7 @@ public:
virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override; virtual void apply_presentational_hints(GC::Ref<CSS::CascadedProperties>) const override;
float stop_offset() { return offset()->base_val(); } float stop_offset() { return offset()->base_val(); }
Gfx::Color stop_color() const; Gfx::Color stop_color();
float stop_opacity() const; float stop_opacity() const;
private: private:

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<svg viewBox="0 0 10 10">
<defs>
<linearGradient id="myGradient">
<stop offset="0" stop-color="#FF0000" />
<stop offset="100%" stop-color="#00FF00" />
</linearGradient>
</defs>
<circle cx="5" cy="5" r="4" fill="url('#myGradient')" />
</svg>
</html>

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html style="color: rgb(calc(255 * sign(1em - 1px)) 0 0)">
<link rel="match" href="../expected/stop-color-non-trival-ref.html" />
<svg viewBox="0 0 10 10">
<defs>
<linearGradient id="myGradient">
<stop offset="0" stop-color="currentcolor" />
<stop offset="100%" stop-color="rgb(0 calc(255 * sign(1em - 1px)) 0)" />
</linearGradient>
</defs>
<circle cx="5" cy="5" r="4" fill="url('#myGradient')" />
</svg>
</html>