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
This commit is contained in:
Oriol Brufau 2023-04-29 13:31:10 +02:00
parent 4339b3bab4
commit 678b590f80
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

@ -131138,7 +131138,7 @@
}
]
],
"background-rounded-image-clip.html": [
"background-rounded-image-clip-001.html": [
"e6222190c192c0fa3db307e2c0cecf6d9a99a13c",
[
null,
@ -131167,6 +131167,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>