mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-23 13:05:12 +00:00
LibWeb: Ensure the shortest serialization is used for border-radius
This implementation also fixes an issue where the individual components of the `border-radius` shorthand were always assumed to be of type `BorderRadiusStyleValue`, which could lead to a crash when CSS-wide keywords were used.
This commit is contained in:
parent
040dca0223
commit
85728b297f
Notes:
github-actions[bot]
2025-03-18 20:56:13 +00:00
Author: https://github.com/tcl3 Commit: https://github.com/LadybirdBrowser/ladybird/commit/85728b297f5 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3982 Reviewed-by: https://github.com/AtkinsSJ Reviewed-by: https://github.com/gmta ✅
4 changed files with 119 additions and 18 deletions
|
@ -134,20 +134,50 @@ String ShorthandStyleValue::to_string(SerializationMode mode) const
|
|||
return MUST(builder.to_string());
|
||||
}
|
||||
case PropertyID::BorderRadius: {
|
||||
auto& top_left = longhand(PropertyID::BorderTopLeftRadius)->as_border_radius();
|
||||
auto& top_right = longhand(PropertyID::BorderTopRightRadius)->as_border_radius();
|
||||
auto& bottom_right = longhand(PropertyID::BorderBottomRightRadius)->as_border_radius();
|
||||
auto& bottom_left = longhand(PropertyID::BorderBottomLeftRadius)->as_border_radius();
|
||||
auto top_left = longhand(PropertyID::BorderTopLeftRadius);
|
||||
auto top_right = longhand(PropertyID::BorderTopRightRadius);
|
||||
auto bottom_right = longhand(PropertyID::BorderBottomRightRadius);
|
||||
auto bottom_left = longhand(PropertyID::BorderBottomLeftRadius);
|
||||
|
||||
return MUST(String::formatted("{} {} {} {} / {} {} {} {}",
|
||||
top_left.horizontal_radius().to_string(),
|
||||
top_right.horizontal_radius().to_string(),
|
||||
bottom_right.horizontal_radius().to_string(),
|
||||
bottom_left.horizontal_radius().to_string(),
|
||||
top_left.vertical_radius().to_string(),
|
||||
top_right.vertical_radius().to_string(),
|
||||
bottom_right.vertical_radius().to_string(),
|
||||
bottom_left.vertical_radius().to_string()));
|
||||
auto horizontal_radius = [&](auto& style_value) -> String {
|
||||
if (style_value->is_border_radius())
|
||||
return style_value->as_border_radius().horizontal_radius().to_string();
|
||||
return style_value->to_string(mode);
|
||||
};
|
||||
|
||||
auto top_left_horizontal_string = horizontal_radius(top_left);
|
||||
auto top_right_horizontal_string = horizontal_radius(top_right);
|
||||
auto bottom_right_horizontal_string = horizontal_radius(bottom_right);
|
||||
auto bottom_left_horizontal_string = horizontal_radius(bottom_left);
|
||||
|
||||
auto vertical_radius = [&](auto& style_value) -> String {
|
||||
if (style_value->is_border_radius())
|
||||
return style_value->as_border_radius().vertical_radius().to_string();
|
||||
return style_value->to_string(mode);
|
||||
};
|
||||
|
||||
auto top_left_vertical_string = vertical_radius(top_left);
|
||||
auto top_right_vertical_string = vertical_radius(top_right);
|
||||
auto bottom_right_vertical_string = vertical_radius(bottom_right);
|
||||
auto bottom_left_vertical_string = vertical_radius(bottom_left);
|
||||
|
||||
auto serialize_radius = [](auto top_left, auto const& top_right, auto const& bottom_right, auto const& bottom_left) -> String {
|
||||
if (first_is_equal_to_all_of(top_left, top_right, bottom_right, bottom_left))
|
||||
return top_left;
|
||||
if (top_left == bottom_right && top_right == bottom_left)
|
||||
return MUST(String::formatted("{} {}", top_left, top_right));
|
||||
if (top_right == bottom_left)
|
||||
return MUST(String::formatted("{} {} {}", top_left, top_right, bottom_right));
|
||||
|
||||
return MUST(String::formatted("{} {} {} {}", top_left, top_right, bottom_right, bottom_left));
|
||||
};
|
||||
|
||||
auto first_radius_serialization = serialize_radius(move(top_left_horizontal_string), top_right_horizontal_string, bottom_right_horizontal_string, bottom_left_horizontal_string);
|
||||
auto second_radius_serialization = serialize_radius(move(top_left_vertical_string), top_right_vertical_string, bottom_right_vertical_string, bottom_left_vertical_string);
|
||||
if (first_radius_serialization == second_radius_serialization)
|
||||
return first_radius_serialization;
|
||||
|
||||
return MUST(String::formatted("{} / {}", first_radius_serialization, second_radius_serialization));
|
||||
}
|
||||
case PropertyID::Columns: {
|
||||
auto column_width = longhand(PropertyID::ColumnWidth)->to_string(mode);
|
||||
|
|
|
@ -57,9 +57,9 @@ All supported properties and their default values exposed from CSSStyleDeclarati
|
|||
'WebkitBorderBottomRightRadius': '0px'
|
||||
'webkitBorderBottomRightRadius': '0px'
|
||||
'-webkit-border-bottom-right-radius': '0px'
|
||||
'WebkitBorderRadius': '0px 0px 0px 0px / 0px 0px 0px 0px'
|
||||
'webkitBorderRadius': '0px 0px 0px 0px / 0px 0px 0px 0px'
|
||||
'-webkit-border-radius': '0px 0px 0px 0px / 0px 0px 0px 0px'
|
||||
'WebkitBorderRadius': '0px'
|
||||
'webkitBorderRadius': '0px'
|
||||
'-webkit-border-radius': '0px'
|
||||
'WebkitBorderTopLeftRadius': '0px'
|
||||
'webkitBorderTopLeftRadius': '0px'
|
||||
'-webkit-border-top-left-radius': '0px'
|
||||
|
@ -242,8 +242,8 @@ All supported properties and their default values exposed from CSSStyleDeclarati
|
|||
'border-left-style': 'none'
|
||||
'borderLeftWidth': 'medium'
|
||||
'border-left-width': 'medium'
|
||||
'borderRadius': '0px 0px 0px 0px / 0px 0px 0px 0px'
|
||||
'border-radius': '0px 0px 0px 0px / 0px 0px 0px 0px'
|
||||
'borderRadius': '0px'
|
||||
'border-radius': '0px'
|
||||
'borderRight': 'medium none rgb(0, 0, 0)'
|
||||
'border-right': 'medium none rgb(0, 0, 0)'
|
||||
'borderRightColor': 'rgb(0, 0, 0)'
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 23 tests
|
||||
|
||||
21 Pass
|
||||
2 Fail
|
||||
Pass e.style['border-radius'] = "initial" should set the property value
|
||||
Pass e.style['border-radius'] = "inherit" should set the property value
|
||||
Pass e.style['border-radius'] = "unset" should set the property value
|
||||
Pass e.style['border-radius'] = "revert" should set the property value
|
||||
Pass e.style['border-radius'] = "1px" should set the property value
|
||||
Pass e.style['border-radius'] = "1px 5%" should set the property value
|
||||
Pass e.style['border-radius'] = "1px 2% 3px" should set the property value
|
||||
Pass e.style['border-radius'] = "1px 2% 3px 4%" should set the property value
|
||||
Pass e.style['border-radius'] = "1px / 2px" should set the property value
|
||||
Pass e.style['border-radius'] = "5em / 1px 2% 3px 4%" should set the property value
|
||||
Pass e.style['border-radius'] = "1px 2% / 3px 4px" should set the property value
|
||||
Pass e.style['border-radius'] = "1px 2px 3em / 1px 2px 3%" should set the property value
|
||||
Pass e.style['border-radius'] = "1px 2% / 2px 3em 4px 5em" should set the property value
|
||||
Pass e.style['border-radius'] = "1px 2% 3px 4% / 5em" should set the property value
|
||||
Pass e.style['border-radius'] = "1px 1px 1px 2% / 1px 2% 1px 2%" should set the property value
|
||||
Pass e.style['border-radius'] = "1px 1px 1px 1px / 1px 1px 2% 1px" should set the property value
|
||||
Pass e.style['border-radius'] = "1px 1px 2% 2%" should set the property value
|
||||
Pass e.style['border-radius'] = "1px 2% 1px 1px" should set the property value
|
||||
Pass e.style['border-radius'] = "1px 2% 2% 2% / 1px 2% 3px 2%" should set the property value
|
||||
Pass e.style['border-top-left-radius'] = "10px" should set the property value
|
||||
Pass e.style['border-top-right-radius'] = "20%" should set the property value
|
||||
Fail e.style['border-bottom-right-radius'] = "30px 40%" should set the property value
|
||||
Fail e.style['border-bottom-left-radius'] = "50% 60px" should set the property value
|
|
@ -0,0 +1,42 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Backgrounds and Borders Module Level 3: parsing border-radius with valid values</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-radius">
|
||||
<meta name="assert" content="border-radius supports CSS Wide keywords and the full grammar '<length-percentage>{1,4} [ / <length-percentage>{1,4} ]?'.">
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
<script src="../../../css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
test_valid_value("border-radius", "initial");
|
||||
test_valid_value("border-radius", "inherit");
|
||||
test_valid_value("border-radius", "unset");
|
||||
test_valid_value("border-radius", "revert");
|
||||
|
||||
test_valid_value("border-radius", "1px");
|
||||
test_valid_value("border-radius", "1px 5%");
|
||||
test_valid_value("border-radius", "1px 2% 3px");
|
||||
test_valid_value("border-radius", "1px 2% 3px 4%");
|
||||
test_valid_value("border-radius", "1px / 2px");
|
||||
test_valid_value("border-radius", "5em / 1px 2% 3px 4%");
|
||||
test_valid_value("border-radius", "1px 2% / 3px 4px");
|
||||
test_valid_value("border-radius", "1px 2px 3em / 1px 2px 3%");
|
||||
test_valid_value("border-radius", "1px 2% / 2px 3em 4px 5em");
|
||||
test_valid_value("border-radius", "1px 2% 3px 4% / 5em");
|
||||
|
||||
test_valid_value("border-radius", "1px 1px 1px 2% / 1px 2% 1px 2%", "1px 1px 1px 2% / 1px 2%");
|
||||
test_valid_value("border-radius", "1px 1px 1px 1px / 1px 1px 2% 1px", "1px / 1px 1px 2%");
|
||||
test_valid_value("border-radius", "1px 1px 2% 2%");
|
||||
test_valid_value("border-radius", "1px 2% 1px 1px");
|
||||
test_valid_value("border-radius", "1px 2% 2% 2% / 1px 2% 3px 2%", "1px 2% 2% / 1px 2% 3px");
|
||||
|
||||
test_valid_value("border-top-left-radius", "10px");
|
||||
test_valid_value("border-top-right-radius", "20%");
|
||||
test_valid_value("border-bottom-right-radius", "30px 40%");
|
||||
test_valid_value("border-bottom-left-radius", "50% 60px");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Reference in a new issue