LibWeb/CSS: Store linear-gradient() angle as a StyleValue

This means we now support calc() there too.
This commit is contained in:
Sam Atkins 2025-11-28 17:23:13 +00:00
parent 73fbaaba77
commit d327f677c5
Notes: github-actions[bot] 2025-12-01 11:10:08 +00:00
5 changed files with 24 additions and 22 deletions

View file

@ -300,21 +300,12 @@ RefPtr<LinearGradientStyleValue const> Parser::parse_linear_gradient_function(To
tokens.discard_whitespace();
auto const& first_param = tokens.next_token();
if (first_param.is(Token::Type::Dimension)) {
// <angle>
tokens.discard_a_token(); // <angle>
auto angle_value = first_param.token().dimension_value();
auto unit_string = first_param.token().dimension_unit();
auto angle_type = string_to_angle_unit(unit_string);
if (!angle_type.has_value())
return nullptr;
gradient_direction = Angle { angle_value, angle_type.release_value() };
if (auto maybe_angle = parse_angle_value(tokens)) {
gradient_direction = maybe_angle.release_nonnull();
} else if (first_param.is(Token::Type::Number) && first_param.token().number().value() == 0) {
// <zero>
tokens.discard_a_token(); // <zero>
gradient_direction = Angle::make_degrees(0);
gradient_direction = { AngleStyleValue::create(Angle::make_degrees(0)) };
} else if (is_to_side_or_corner(first_param)) {
// <side-or-corner> = [left | right] || [top | bottom]
@ -379,7 +370,7 @@ RefPtr<LinearGradientStyleValue const> Parser::parse_linear_gradient_function(To
return nullptr;
transaction.commit();
return LinearGradientStyleValue::create(gradient_direction, move(*color_stops), gradient_type, repeating_gradient, maybe_interpolation_method);
return LinearGradientStyleValue::create(move(gradient_direction), move(*color_stops), gradient_type, repeating_gradient, maybe_interpolation_method);
}
RefPtr<ConicGradientStyleValue const> Parser::parse_conic_gradient_function(TokenStream<ComponentValue>& outer_tokens)

View file

@ -8,6 +8,8 @@
*/
#include "LinearGradientStyleValue.h"
#include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
#include <LibWeb/CSS/StyleValues/CalculatedStyleValue.h>
#include <LibWeb/Layout/Node.h>
#include <LibWeb/Painting/DisplayListRecorder.h>
@ -53,8 +55,8 @@ String LinearGradientStyleValue::to_string(SerializationMode mode) const
[&](SideOrCorner side_or_corner) {
builder.appendff("{}{}", m_properties.gradient_type == GradientType::Standard ? "to "sv : ""sv, side_or_corner_to_string(side_or_corner));
},
[&](Angle const& angle) {
builder.append(angle.to_string());
[&](NonnullRefPtr<StyleValue const> const& angle) {
builder.append(angle->to_string(mode));
});
if (has_color_space)
@ -114,8 +116,14 @@ float LinearGradientStyleValue::angle_degrees(CSSPixelSize gradient_size) const
return angle + 180.0;
return angle;
},
[&](Angle const& angle) {
return angle.to_degrees();
[&](NonnullRefPtr<StyleValue const> const& style_value) {
if (style_value->is_angle())
return style_value->as_angle().angle().to_degrees();
if (style_value->is_calculated()) {
if (auto maybe_angle = style_value->as_calculated().resolve_angle({}); maybe_angle.has_value())
return maybe_angle->to_degrees();
}
return 0.0;
});
}

View file

@ -10,8 +10,6 @@
#pragma once
#include <AK/Vector.h>
#include <LibWeb/CSS/Angle.h>
#include <LibWeb/CSS/Percentage.h>
#include <LibWeb/CSS/StyleValues/AbstractImageStyleValue.h>
#include <LibWeb/CSS/StyleValues/ColorStyleValue.h>
#include <LibWeb/Painting/GradientPainting.h>
@ -32,7 +30,7 @@ enum class SideOrCorner {
class LinearGradientStyleValue final : public AbstractImageStyleValue {
public:
using GradientDirection = Variant<Angle, SideOrCorner>;
using GradientDirection = Variant<NonnullRefPtr<StyleValue const>, SideOrCorner>;
enum class GradientType {
Standard,
@ -43,7 +41,7 @@ public:
{
VERIFY(!color_stop_list.is_empty());
bool any_non_legacy = color_stop_list.find_first_index_if([](auto const& stop) { return !stop.color_stop.color->is_keyword() && stop.color_stop.color->as_color().color_syntax() == ColorSyntax::Modern; }).has_value();
return adopt_ref(*new (nothrow) LinearGradientStyleValue(direction, move(color_stop_list), type, repeating, interpolation_method, any_non_legacy ? ColorSyntax::Modern : ColorSyntax::Legacy));
return adopt_ref(*new (nothrow) LinearGradientStyleValue(move(direction), move(color_stop_list), type, repeating, interpolation_method, any_non_legacy ? ColorSyntax::Modern : ColorSyntax::Legacy));
}
virtual String to_string(SerializationMode) const override;
@ -78,7 +76,7 @@ public:
private:
LinearGradientStyleValue(GradientDirection direction, Vector<ColorStopListElement> color_stop_list, GradientType type, GradientRepeating repeating, Optional<InterpolationMethod> interpolation_method, ColorSyntax color_syntax)
: AbstractImageStyleValue(Type::LinearGradient)
, m_properties { .direction = direction, .color_stop_list = move(color_stop_list), .gradient_type = type, .repeating = repeating, .interpolation_method = interpolation_method, .color_syntax = color_syntax }
, m_properties { .direction = move(direction), .color_stop_list = move(color_stop_list), .gradient_type = type, .repeating = repeating, .interpolation_method = interpolation_method, .color_syntax = color_syntax }
{
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 KiB

After

Width:  |  Height:  |  Size: 490 KiB

Before After
Before After

View file

@ -87,6 +87,10 @@
.grad-10 {
background-image: linear-gradient(90deg, red, transparent, blue);
}
.grad-10-calc-angle {
background-image: linear-gradient(calc(30deg * 3), red, transparent, blue);
}
.grad-11 {
background-image: linear-gradient(to top right, indigo, white, deeppink);
@ -251,6 +255,7 @@
<div class="box grad-conic-repeat-1"></div>
<div class="box grad-conic-repeat-2"></div>
<div class="box grad-repeat-4"></div>
<div class="box grad-10-calc-angle"></div>
</section>
<section class="rects">
<div class="rect grad-7"></div>