mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-25 17:25:08 +02:00
LibWeb: Make parsing of border-radius value reusable
This is also useful for `<basic-shape-rect>`
This commit is contained in:
committed by
Jelle Raaijmakers
parent
cb1425877a
commit
84c6fd5730
Notes:
github-actions[bot]
2026-01-06 09:51:34 +00:00
Author: https://github.com/Calme1709 Commit: https://github.com/LadybirdBrowser/ladybird/commit/84c6fd57304 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/7339 Reviewed-by: https://github.com/gmta ✅
@@ -29,6 +29,8 @@
|
||||
#include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/BackgroundSizeStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/BasicShapeStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/BorderRadiusRectStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/BorderRadiusStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/ColorFunctionStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/ColorMixStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/ColorStyleValue.h>
|
||||
@@ -3379,6 +3381,99 @@ RefPtr<URLStyleValue const> Parser::parse_url_value(TokenStream<ComponentValue>&
|
||||
return URLStyleValue::create(url.release_value());
|
||||
}
|
||||
|
||||
RefPtr<BorderRadiusRectStyleValue const> Parser::parse_border_radius_rect_value(TokenStream<ComponentValue>& tokens)
|
||||
{
|
||||
auto top_left = [&](StyleValueVector& radii) { return radii[0]; };
|
||||
auto top_right = [&](StyleValueVector& radii) {
|
||||
switch (radii.size()) {
|
||||
case 4:
|
||||
case 3:
|
||||
case 2:
|
||||
return radii[1];
|
||||
case 1:
|
||||
return radii[0];
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
};
|
||||
auto bottom_right = [&](StyleValueVector& radii) {
|
||||
switch (radii.size()) {
|
||||
case 4:
|
||||
case 3:
|
||||
return radii[2];
|
||||
case 2:
|
||||
case 1:
|
||||
return radii[0];
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
};
|
||||
auto bottom_left = [&](StyleValueVector& radii) {
|
||||
switch (radii.size()) {
|
||||
case 4:
|
||||
return radii[3];
|
||||
case 3:
|
||||
case 2:
|
||||
return radii[1];
|
||||
case 1:
|
||||
return radii[0];
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
};
|
||||
|
||||
StyleValueVector horizontal_radii;
|
||||
StyleValueVector vertical_radii;
|
||||
bool reading_vertical = false;
|
||||
auto transaction = tokens.begin_transaction();
|
||||
tokens.discard_whitespace();
|
||||
|
||||
auto context_guard = push_temporary_value_parsing_context(SpecialContext::BorderRadius);
|
||||
|
||||
while (tokens.has_next_token()) {
|
||||
if (tokens.next_token().is_delim('/')) {
|
||||
if (reading_vertical || horizontal_radii.is_empty())
|
||||
return nullptr;
|
||||
|
||||
reading_vertical = true;
|
||||
tokens.discard_a_token(); // `/`
|
||||
tokens.discard_whitespace();
|
||||
continue;
|
||||
}
|
||||
|
||||
auto maybe_dimension = parse_length_percentage_value(tokens);
|
||||
if (!maybe_dimension)
|
||||
return nullptr;
|
||||
if (maybe_dimension->is_length() && maybe_dimension->as_length().length().raw_value() < 0)
|
||||
return nullptr;
|
||||
if (maybe_dimension->is_percentage() && maybe_dimension->as_percentage().percentage().value() < 0)
|
||||
return nullptr;
|
||||
if (reading_vertical) {
|
||||
vertical_radii.append(maybe_dimension.release_nonnull());
|
||||
} else {
|
||||
horizontal_radii.append(maybe_dimension.release_nonnull());
|
||||
}
|
||||
tokens.discard_whitespace();
|
||||
}
|
||||
|
||||
if (horizontal_radii.size() > 4 || vertical_radii.size() > 4
|
||||
|| horizontal_radii.is_empty()
|
||||
|| (reading_vertical && vertical_radii.is_empty()))
|
||||
return nullptr;
|
||||
|
||||
auto top_left_radius = BorderRadiusStyleValue::create(top_left(horizontal_radii),
|
||||
vertical_radii.is_empty() ? top_left(horizontal_radii) : top_left(vertical_radii));
|
||||
auto top_right_radius = BorderRadiusStyleValue::create(top_right(horizontal_radii),
|
||||
vertical_radii.is_empty() ? top_right(horizontal_radii) : top_right(vertical_radii));
|
||||
auto bottom_right_radius = BorderRadiusStyleValue::create(bottom_right(horizontal_radii),
|
||||
vertical_radii.is_empty() ? bottom_right(horizontal_radii) : bottom_right(vertical_radii));
|
||||
auto bottom_left_radius = BorderRadiusStyleValue::create(bottom_left(horizontal_radii),
|
||||
vertical_radii.is_empty() ? bottom_left(horizontal_radii) : bottom_left(vertical_radii));
|
||||
|
||||
transaction.commit();
|
||||
return BorderRadiusRectStyleValue::create(top_left_radius, top_right_radius, bottom_right_radius, bottom_left_radius);
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-images-4/#radial-size
|
||||
RefPtr<RadialSizeStyleValue const> Parser::parse_radial_size(TokenStream<ComponentValue>& tokens)
|
||||
{
|
||||
@@ -4507,6 +4602,13 @@ RefPtr<CalculatedStyleValue const> Parser::parse_calculated_value(ComponentValue
|
||||
switch (special_context) {
|
||||
case SpecialContext::AngularColorStopList:
|
||||
return CalculationContext { .percentages_resolve_as = ValueType::Angle };
|
||||
case SpecialContext::BorderRadius:
|
||||
return CalculationContext {
|
||||
.percentages_resolve_as = ValueType::Length,
|
||||
.accepted_type_ranges = {
|
||||
{ ValueType::Length, { 0, NumericLimits<float>::max() } },
|
||||
{ ValueType::Percentage, { 0, NumericLimits<float>::max() } } },
|
||||
};
|
||||
case SpecialContext::CubicBezierFunctionXCoordinate:
|
||||
// Coordinates on the X axis must be between 0 and 1
|
||||
return CalculationContext { .accepted_type_ranges = { { ValueType::Number, { 0, 1 } } } };
|
||||
|
||||
Reference in New Issue
Block a user