Auto merge of #29686 - Loirooriol:normalize-border-radius, r=mrobinson

Normalize corner radii that add up to > 100%

WebRender already seems to be doing this normalization, but this is needed by inner_radii in order to properly compute the reduced radii when background-clip is content-box or padding-box.

This will also be needed for expanding the radii for box-shadow or outline.

Test: css/css-backgrounds/background-rounded-image-clip-002.html

<!-- Please describe your changes on the following line: -->

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix #29685 (GitHub issue number if applicable)

<!-- Either: -->
- [X] There are tests for these changes OR
- [ ] These changes do not require tests because ___

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
This commit is contained in:
bors-servo 2023-05-01 18:48:49 +02:00 committed by GitHub
commit c92ea9774f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 84 additions and 2 deletions

View file

@ -322,12 +322,30 @@ impl<'a> BuilderForBoxFragment<'a> {
)
};
let b = fragment.style.get_border();
wr::BorderRadius {
let mut radius = wr::BorderRadius {
top_left: corner(&b.border_top_left_radius),
top_right: corner(&b.border_top_right_radius),
bottom_right: corner(&b.border_bottom_right_radius),
bottom_left: corner(&b.border_bottom_left_radius),
};
// Normalize radii that add up to > 100%.
// https://www.w3.org/TR/css-backgrounds-3/#corner-overlap
// > Let f = min(L_i/S_i), where i ∈ {top, right, bottom, left},
// > S_i is the sum of the two corresponding radii of the corners on side i,
// > and L_top = L_bottom = the width of the box,
// > and L_left = L_right = the height of the box.
// > If f < 1, then all corner radii are reduced by multiplying them by f.
let f = (border_rect.width() / (radius.top_left.width + radius.top_right.width))
.min(border_rect.width() / (radius.bottom_left.width + radius.bottom_right.width))
.min(border_rect.height() / (radius.top_left.height + radius.bottom_left.height))
.min(border_rect.height() / (radius.top_right.height + radius.bottom_right.height));
if f < 1.0 {
radius.top_left *= f;
radius.top_right *= f;
radius.bottom_right *= f;
radius.bottom_left *= f;
}
radius
};
Self {

View file

@ -131218,7 +131218,7 @@
}
]
],
"background-rounded-image-clip.html": [
"background-rounded-image-clip-001.html": [
"e6222190c192c0fa3db307e2c0cecf6d9a99a13c",
[
null,
@ -131247,6 +131247,35 @@
}
]
],
"background-rounded-image-clip-002.html": [
"4af7702602027ae39c26befcd1f04d2e323e4642",
[
null,
[
[
"/css/reference/ref-filled-green-200px-square.html",
"=="
]
],
{
"fuzzy": [
[
null,
[
[
0,
5
],
[
0,
100
]
]
]
]
}
]
],
"background-size": {
"background-size-contain.xht": [
"7309905bbac46d67f16907d799fb3ba7716bb31a",

View file

@ -0,0 +1,35 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Background Clip Follows Rounded Corner</title>
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com">
<meta name="fuzzy" content="maxDifference=0-5; totalPixels=0-100">
<link rel="match" href="../reference/ref-filled-green-200px-square.html">
<link rel="help" href="https://drafts.csswg.org/css-backgrounds-3/#corner-clipping">
<link rel="help" href="https://github.com/servo/servo/issues/29685">
<style>
.wrapper {
width: 200px;
height: 200px;
background: red;
}
.wrapper > * {
position: absolute;
width: 100px;
height: 100px;
border: 50px solid green;
}
.round-border {
border-radius: 100px 150px 200px 250px / 350px;
}
.background {
border-color: transparent;
background: linear-gradient(green, green) padding-box;
transform: scale(1.05);
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div class="wrapper">
<div class="round-border background"></div>
<div class="round-border"></div>
<div></div>
</div>