Fix percentages in the padding of a table-cell (#31430)

This commit is contained in:
Oriol Brufau 2024-02-27 14:28:23 +01:00 committed by GitHub
parent b9e217c480
commit b07505417e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 139 additions and 4 deletions

View file

@ -67,6 +67,7 @@ struct TableLayout<'a> {
row_sizes: Vec<Au>,
row_baselines: Vec<Au>,
cells_laid_out: Vec<Vec<Option<CellLayout>>>,
basis_for_cell_padding_percentage: Au,
}
#[derive(Clone, Debug)]
@ -98,6 +99,7 @@ impl<'a> TableLayout<'a> {
row_sizes: Vec::new(),
row_baselines: Vec::new(),
cells_laid_out: Vec::new(),
basis_for_cell_padding_percentage: Au::zero(),
}
}
@ -167,9 +169,15 @@ impl<'a> TableLayout<'a> {
.max(max_size.inline.min(size.inline))
};
let pbm = cell.style.padding_border_margin(containing_block);
outer_min_content_width += pbm.padding_border_sums.inline;
outer_max_content_width += pbm.padding_border_sums.inline;
let inline_padding_border_sum = Au::from(
cell.style
.padding(writing_mode)
.percentages_relative_to(Length::zero())
.inline_sum() +
cell.style.border_width(writing_mode).inline_sum(),
);
outer_min_content_width += inline_padding_border_sum;
outer_max_content_width += inline_padding_border_sum;
row_measures[column_index] = CellOrColumnMeasure {
content_sizes: ContentSizes {
@ -578,6 +586,10 @@ impl<'a> TableLayout<'a> {
// > border spacing (if any). This is the width that we will be able to allocate to the
// > columns.
self.assignable_width = used_width_of_table - inline_border_spacing;
// This is the amount that we will use to resolve percentages in the padding of cells.
// It matches what Gecko and Blink do, though they disagree when there is a big caption.
self.basis_for_cell_padding_percentage = used_width_of_table - border_spacing.inline * 2;
}
/// Distribute width to columns, performing step 2.4 of table layout from
@ -897,7 +909,7 @@ impl<'a> TableLayout<'a> {
let padding = cell
.style
.padding(containing_block.style.writing_mode)
.percentages_relative_to(Length::zero());
.percentages_relative_to(self.basis_for_cell_padding_percentage.into());
let inline_border_padding_sum = border.inline_sum() + padding.inline_sum();
let mut total_width: CSSPixelLength =
Length::from(total_width) - inline_border_padding_sum;

View file

@ -0,0 +1,2 @@
[padding-percentage.html]
expected: FAIL

View file

@ -243079,6 +243079,19 @@
]
],
"tentative": {
"padding-percentage.html": [
"67f8009de365a32275232b5c5b008072a0c8fc17",
[
null,
[
[
"/css/reference/ref-filled-green-100px-square.xht",
"=="
]
],
{}
]
],
"paint": {
"background-image-column-collapsed.html": [
"6e6ae7a82cfd04c09989dcea682744eb79e982a7",

View file

@ -0,0 +1,108 @@
<!DOCTYPE html>
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
<link rel="match" href="/css/reference/ref-filled-green-100px-square.xht">
<meta name="assert" content="
When a table cell has a percentage in the inline axis of the table,
it should resolve against zero when computing the column sizes,
but once we know the final size of the table, it should re-resolve
against that size minus the leading and trailing border spacing.
This matches what Blink and Gecko do (WebKit is different).
Note that Blink and Gecko disagree in case there is a caption:
Blink still behaves as per above, while Gecko re-resolves against
the sum of column sizes plus the interleaved border spacings.
Due to the lack of interoperability, this test doesn't use captions.
">
<style>
table {
border-spacing: 10px 0;
}
td {
padding: 0;
}
td > div {
width: 100px;
height: 25px;
background: red;
}
td > div.green {
position: relative;
background: green;
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<!--
There is one column, it's 100px wide. The percentage resolves against
that amount, so the padding becomes 100px.
There is an extra spacing of 10px before the 1st column,
that's why the table has a -110px margin.
-->
<table style="margin-left: -110px">
<td style="padding-left: 100%">
<div class="green"></div>
</td>
</table>
<!--
The 1st column is 110px wide, the 2nd column is 100px wide.
And they are separated by 10px, so that's a total of 220px.
The percentage resolves against that amount, so the padding
becomes 0.5 * 220px + 10px = 120px.
There is an extra spacing of 10px before the 1st column,
that's why the table has a -130px margin.
-->
<table style="margin-left: -130px">
<td style="padding-left: calc(50% + 10px)">
<div class="green"></div>
</td>
<td>
<div></div>
</td>
</table>
<!--
There are 3 columns, each one is 100px wide. They are separated by 10px,
so that's a total of 100px * 3 + 10px * 2 = 320px.
The percentage resolves against that amount, so the padding becomes
320px - 100px = 220px.
There is an extra spacing of 10px before the 1st column,
that's why the table has a -230px margin.
-->
<table style="margin-left: -230px">
<td style="padding-left: calc(100% - 100px)">
<div class="green"></div>
</td>
<td>
<div></div>
</td>
<td>
<div></div>
</td>
</table>
<!--
There are 4 columns, the 1st one is 330px wide, each one of the others
is 100px wide. They are separated by 10px, so that's a total of
330px + 100px * 3 + 10px * 3 = 660px.
The percentage resolves against that amount, so the padding becomes
0.5 * 660px + 230px = 560px.
There is an extra spacing of 10px before the 1st column,
that's why the table has a -570px margin.
-->
<table style="margin-left: -570px">
<td style="padding-left: calc(50% + 230px)">
<div class="green"></div>
</td>
<td>
<div></div>
</td>
<td>
<div></div>
</td>
<td>
<div></div>
</td>
</table>