LibWeb/CSS: Store RadialGradientStyleValue sizes as StyleValues

No significant consequences of this, but it'll make it easier to
absolutize these values.
This commit is contained in:
Sam Atkins 2025-11-24 14:42:09 +00:00
parent d327f677c5
commit fbe0567f90
Notes: github-actions[bot] 2025-12-01 11:09:59 +00:00
3 changed files with 43 additions and 20 deletions

View file

@ -540,10 +540,10 @@ RefPtr<RadialGradientStyleValue const> Parser::parse_radial_gradient_function(To
return {};
};
auto length_percentage_is_non_negative = [](LengthPercentage const& length_percentage) -> bool {
if (length_percentage.is_length() && length_percentage.length().raw_value() < 0)
auto length_percentage_is_non_negative = [](StyleValue const& value) -> bool {
if (value.is_length() && value.as_length().length().raw_value() < 0)
return false;
if (length_percentage.is_percentage() && length_percentage.percentage().value() < 0)
if (value.is_percentage() && value.as_percentage().percentage().value() < 0)
return false;
return true;
};
@ -563,23 +563,22 @@ RefPtr<RadialGradientStyleValue const> Parser::parse_radial_gradient_function(To
return {};
return commit_value(*extent, transaction_size);
}
auto first_radius = parse_length_percentage(tokens);
if (!first_radius.has_value() || !length_percentage_is_non_negative(*first_radius))
auto first_radius = parse_length_percentage_value(tokens);
if (!first_radius || !length_percentage_is_non_negative(*first_radius))
return {};
auto transaction_second_dimension = tokens.begin_transaction();
tokens.discard_whitespace();
if (tokens.has_next_token()) {
auto second_radius = parse_length_percentage(tokens);
if (second_radius.has_value()) {
if (auto second_radius = parse_length_percentage_value(tokens)) {
if (!length_percentage_is_non_negative(*second_radius))
return {};
return commit_value(EllipseSize { first_radius.release_value(), second_radius.release_value() },
return commit_value(EllipseSize { first_radius.release_nonnull(), second_radius.release_nonnull() },
transaction_size, transaction_second_dimension);
}
}
// FIXME: Support calculated lengths
if (first_radius->is_length())
return commit_value(CircleSize { first_radius->length() }, transaction_size);
// We parsed the first value as a <length-percentage>, but here we only want <length>s.
if (first_radius->is_length() || (first_radius->is_calculated() && !first_radius->as_calculated().contains_percentage()))
return commit_value(CircleSize { first_radius.release_nonnull() }, transaction_size);
return {};
};

View file

@ -44,10 +44,10 @@ String RadialGradientStyleValue::to_string(SerializationMode mode) const
}());
},
[&](CircleSize const& circle_size) {
builder.append(circle_size.radius.to_string());
builder.append(circle_size.radius->to_string(mode));
},
[&](EllipseSize const& ellipse_size) {
builder.appendff("{} {}", ellipse_size.radius_a.to_string(mode), ellipse_size.radius_b.to_string(mode));
builder.appendff("{} {}", ellipse_size.radius_a->to_string(mode), ellipse_size.radius_b->to_string(mode));
});
if (has_position) {
@ -179,12 +179,36 @@ CSSPixelSize RadialGradientStyleValue::resolve_size(Layout::Node const& node, CS
}
},
[&](CircleSize const& circle_size) {
auto radius = circle_size.radius.to_px(node);
return CSSPixelSize { radius, radius };
if (circle_size.radius->is_length()) {
auto radius = circle_size.radius->as_length().length().to_px(node);
return CSSPixelSize { radius, radius };
}
if (circle_size.radius->is_calculated()) {
CalculationResolutionContext context {
.length_resolution_context = Length::ResolutionContext::for_layout_node(node),
};
auto radius = circle_size.radius->as_calculated().resolve_length(context)->to_px(node);
return CSSPixelSize { radius, radius };
}
VERIFY_NOT_REACHED();
},
[&](EllipseSize const& ellipse_size) {
auto radius_a = ellipse_size.radius_a.resolved(node, size.width()).to_px(node);
auto radius_b = ellipse_size.radius_b.resolved(node, size.height()).to_px(node);
auto resolve = [&](StyleValue const& radius_value, auto percentage_basis_pixels) {
auto percentage_basis = Length::make_px(percentage_basis_pixels);
CalculationResolutionContext context {
.percentage_basis = percentage_basis,
.length_resolution_context = Length::ResolutionContext::for_layout_node(node),
};
if (radius_value.is_length())
return radius_value.as_length().length().to_px(node);
if (radius_value.is_percentage())
return percentage_basis.percentage_of(radius_value.as_percentage().percentage()).to_px(node);
if (radius_value.is_calculated())
return radius_value.as_calculated().resolve_length(context)->to_px(node);
VERIFY_NOT_REACHED();
};
auto radius_a = resolve(*ellipse_size.radius_a, size.width());
auto radius_b = resolve(*ellipse_size.radius_b, size.height());
return CSSPixelSize { radius_a, radius_b };
});

View file

@ -31,13 +31,13 @@ public:
};
struct CircleSize {
Length radius;
NonnullRefPtr<StyleValue const> radius;
bool operator==(CircleSize const&) const = default;
};
struct EllipseSize {
LengthPercentage radius_a;
LengthPercentage radius_b;
NonnullRefPtr<StyleValue const> radius_a;
NonnullRefPtr<StyleValue const> radius_b;
bool operator==(EllipseSize const&) const = default;
};