Commit cb5924a5 authored by Aleks Totic's avatar Aleks Totic Committed by Chromium LUCI CQ

[TablesNG] fix block size distribution over empty rows

Did not handle block size distribution over empty rows
correctly.
If there are empty constrained, and unconstrained rows,
distribute only over unconstrained rows.
We used to distribute over all empty rows.

Row height distribution is tricky. There is no agreement
between browsers on what the right thing to do is.
FF never grows empty rows. Chrome does not distribute
heights specified on TBODY.

Bug: 1161157
Change-Id: I7cb2fb76ef4add651c61b10dbf8dd9fa0b58db0b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2632154Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Commit-Queue: Aleks Totic <atotic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#845035}
parent 56d3bc64
...@@ -609,6 +609,10 @@ void DistributeColspanCellToColumnsAuto( ...@@ -609,6 +609,10 @@ void DistributeColspanCellToColumnsAuto(
} }
} }
// Handles distribution of excess block size from: table, sections,
// rows, and rowspanned cells, to rows.
// Rowspanned cells distribute with slight differences from
// general distribution algorithm.
void DistributeExcessBlockSizeToRows( void DistributeExcessBlockSizeToRows(
const wtf_size_t start_row_index, const wtf_size_t start_row_index,
const wtf_size_t row_count, const wtf_size_t row_count,
...@@ -664,6 +668,7 @@ void DistributeExcessBlockSizeToRows( ...@@ -664,6 +668,7 @@ void DistributeExcessBlockSizeToRows(
unsigned unconstrained_non_empty_row_count = 0; unsigned unconstrained_non_empty_row_count = 0;
unsigned constrained_non_empty_row_count = 0; unsigned constrained_non_empty_row_count = 0;
unsigned empty_row_count = 0; unsigned empty_row_count = 0;
unsigned unconstrained_empty_row_count = 0;
LayoutUnit total_block_size; LayoutUnit total_block_size;
LayoutUnit percentage_block_size_deficit; LayoutUnit percentage_block_size_deficit;
...@@ -687,8 +692,11 @@ void DistributeExcessBlockSizeToRows( ...@@ -687,8 +692,11 @@ void DistributeExcessBlockSizeToRows(
} else if (row->is_constrained && !IsEmptyRow(row)) { } else if (row->is_constrained && !IsEmptyRow(row)) {
constrained_non_empty_row_count++; constrained_non_empty_row_count++;
} }
if (IsEmptyRow(row)) if (IsEmptyRow(row)) {
empty_row_count++; empty_row_count++;
if (!row->is_constrained)
unconstrained_empty_row_count++;
}
} }
LayoutUnit distributable_block_size = LayoutUnit distributable_block_size =
...@@ -760,14 +768,14 @@ void DistributeExcessBlockSizeToRows( ...@@ -760,14 +768,14 @@ void DistributeExcessBlockSizeToRows(
} }
// Step 4: Empty row distribution // Step 4: Empty row distribution
// Table distributes evenly between all rows. // At this point all rows are empty and/or constrained.
// If there are any empty rows except start row, last row takes all the
// excess block size.
if (empty_row_count > 0) { if (empty_row_count > 0) {
if (desired_block_size_is_rowspan) { if (desired_block_size_is_rowspan) {
NGTableTypes::Row* last_row = nullptr; NGTableTypes::Row* last_row = nullptr;
NGTableTypes::Row* row = start_row; NGTableTypes::Row* row = start_row;
if (empty_row_count != row_count) // skip initial row. // Rowspan distribution skips initial empty row if possible,
// and distributes everything to the last empty row.
if (empty_row_count != row_count)
++row; ++row;
for (; row != end_row; ++row) { for (; row != end_row; ++row) {
if (row->block_size != LayoutUnit()) if (row->block_size != LayoutUnit())
...@@ -781,20 +789,25 @@ void DistributeExcessBlockSizeToRows( ...@@ -781,20 +789,25 @@ void DistributeExcessBlockSizeToRows(
} else if (empty_row_count == row_count || } else if (empty_row_count == row_count ||
(empty_row_count + constrained_non_empty_row_count == (empty_row_count + constrained_non_empty_row_count ==
row_count)) { row_count)) {
// Grow empty rows if one of these is true: // Grow empty rows if either of these is true:
// - all rows are empty. // - all rows are empty.
// - non-empty rows are all constrained. // - non-empty rows are all constrained.
// Different browsers disagree on when to grow empty rows.
NGTableTypes::Row* last_row = nullptr; NGTableTypes::Row* last_row = nullptr;
LayoutUnit remaining_deficit = distributable_block_size; LayoutUnit remaining_deficit = distributable_block_size;
// If there are constrained and unconstrained empty rows,
// only unconstrained rows grow.
bool grow_only_unconstrained = unconstrained_empty_row_count > 0;
unsigned growing_rows_count = grow_only_unconstrained
? unconstrained_empty_row_count
: empty_row_count;
for (NGTableTypes::Row* row = start_row; row != end_row; ++row) { for (NGTableTypes::Row* row = start_row; row != end_row; ++row) {
if (row->block_size != LayoutUnit()) if (row->block_size != LayoutUnit())
continue; continue;
if (grow_only_unconstrained && row->is_constrained)
continue;
last_row = row; last_row = row;
// Table block size distributes equally, while rowspan distributes to
// last row.
LayoutUnit delta = LayoutUnit delta =
LayoutUnit(distributable_block_size.ToFloat() / empty_row_count); LayoutUnit(distributable_block_size.ToFloat() / growing_rows_count);
row->block_size = delta; row->block_size = delta;
remaining_deficit -= delta; remaining_deficit -= delta;
} }
......
...@@ -674,6 +674,7 @@ crbug.com/613753 external/wpt/css/css-tables/border-spacing-included-in-sizes-00 ...@@ -674,6 +674,7 @@ crbug.com/613753 external/wpt/css/css-tables/border-spacing-included-in-sizes-00
crbug.com/353580 external/wpt/css/css-tables/height-distribution/percentage-sizing-of-table-cell-children-005.html [ Failure ] crbug.com/353580 external/wpt/css/css-tables/height-distribution/percentage-sizing-of-table-cell-children-005.html [ Failure ]
crbug.com/1108224 external/wpt/css/css-tables/min-max-size-table-content-box.html [ Failure ] crbug.com/1108224 external/wpt/css/css-tables/min-max-size-table-content-box.html [ Failure ]
crbug.com/958381 external/wpt/css/css-tables/tentative/position-sticky-container.html [ Failure ] crbug.com/958381 external/wpt/css/css-tables/tentative/position-sticky-container.html [ Failure ]
crbug.com/958381 external/wpt/css/css-tables/tentative/table-height-redistribution.html [ Failure ]
# [css-contain] # [css-contain]
......
<!doctype html>
<title>TABLE height redistribution</title>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src="/resources/check-layout-th.js"></script>
<link rel='stylesheet' href='../support/base.css' />
<link rel="author" title="Aleks Totic" href="atotic@chromium.org" />
<link rel="help" href="https://drafts.csswg.org/css-tables-3/#row-layout" />
<style>
main table {
border-collapse: collapse;
background: #DDD;
height: 100px;
}
main td {
padding: 0;
}
main table tbody:nth-child(1) {
background: #CCC;
}
main table tbody:nth-child(2) {
background: #AAA;
}
main table tbody:nth-child(3) {
background: #999;
}
main table thead {
background: rgba(0,255,0,0.3);
}
main table tfoot {
background: rgba(255,255,0,0.3);
}
main .test {
margin-top:24px;
}
</style>
<main>
<h1>Tests for redistribution of table height to row group height.</h1>
<p>This algorithm has not been standardized. Browsers implementations disagree</p>
<p class="test">Empty sections and rows do grow when table height forces it.</p>
<table>
<tbody data-expected-height="100">
<tr data-expected-height="100">
<td style="width:0;height:0" data-expected-height="100"></td>
</tr>
</tbody>
</table>
<p class="test">Unconstrained sections grow proportionally.</p>
<p>Chrome only grows first TBODY. This test expects only TBODYs to grow.</p>
<table >
<thead data-expected-height="15">
<tr><td><div style="height:15px">0,0</div></td></tr>
</thead>
<tbody data-expected-height="35">
<tr><td>1,0</td></tr>
</tbody>
<tbody data-expected-height="35">
<tr><td>2,0</td></tr>
</tbody>
<tfoot data-expected-height="15">
<tr><td><div style="height:15px">3,0</div></td></tr>
</tfoot>
</table>
<p class="test">Unconstrained sections grow proportionally to their size</p>
<table >
<tbody data-expected-height="75">
<tr><td>0,0</td></tr>
<tr><td>1,0</td></tr>
<tr><td>2,0</td></tr>
</tbody>
<tbody data-expected-height="25">
<tr><td>3,0</td></tr>
</tbody>
</table>
<p class="test">Fixed sections do not grow if there are unconstrained sections.</p>
<p>FF gets the right sizes, but gets locations wrong.</p>
<table>
<tbody style="height:30px" data-expected-height="30" data-offset-y="0">
<tr><td>0,0</td></tr>
</tbody>
<tbody data-expected-height="35" data-offset-y="30">
<tr><td>1,0</td></tr>
</tbody>
<tbody data-expected-height="35" data-offset-y="65">
<tr><td>2,0</td></tr>
</tbody>
</table>
<p class="test">Fixed sections grow proportionally to their height.</p>
<p>FF grows sections equally, not proportionally to height</p>
<table>
<tbody style="height:20px" data-expected-height="25">
<tr><td>0,0</td></tr>
</tbody>
<tbody style="height:60px" data-expected-height="75">
<tr><td>1,0</td></tr>
</tbody>
</table>
<p class="test">Percentage resolution size. Initial percentage resolution size should be undefined.
<table >
<tbody style="height:30%" data-expected-height="20">
<tr><td><div style="height:20px">0,0</div></td></tr>
</tbody>
<tbody style="height:70%" data-expected-height="20">
<tr><td><div style="height:20px">1,0</div></td></tr>
</tbody>
<tbody style="height:200px" data-expected-height="200">
<tr><td>1,0</td></tr>
</tbody>
</table>
<p class="test">Percentage resolution size. During table height redistribution, use table height as
percentage resolution height..
<table>
<tbody style="height:30%" data-expected-height="30">
<tr><td><div style="height:20px">0,0</div></td></tr>
</tbody>
<tbody style="height:70%" data-expected-height="70">
<tr><td><div style="height:20px">1,0</div></td></tr>
</tbody>
</table>
<p class="test">Redistribute percentage bodies proportional to their initial height
<table>
<tbody style="height:20%" data-expected-height="25">
<tr><td><div style="height:20px">0,0</div></td></tr>
</tbody>
<tbody style="height:60%" data-expected-height="75">
<tr><td><div style="height:20px">1,0</div></td></tr>
</tbody>
</table>
<p class="test">Table min-height is not ignored.</p>
<table style="min-height:200px;height:auto" data-expected-height="200">
<tbody>
<tr><td><div style="height:50px">0,0</div></td></tr>
</tbody>
</table>
<p class="test">Table max-height is ignored.</p>
<table style="max-height:90px;height:auto" data-expected-height="100">
<tbody>
<tr><td><div style="height:100px">0,0</div></td></tr>
</tbody>
</table>
<p class="test">Table height does not include caption</p>
<table style="height:100px;" >
<caption>not included</caption>
<tbody>
<tr data-expected-height="100"><td>0,0</td></tr>
</tbody>
</table>
<p class="test">Excess row percentage height is distributed greedily.</p>
<table style="height:160px">
<tbody>
<tr style="height:50%" data-expected-height="80">
<td >
<div style="height:20px">0,0</div>
</td>
</tr>
<tr style="height:30%" data-expected-height="48">
<td >
<div style="height:20px">1,0</div>
</td>
</tr>
<tr style="height:80%" data-expected-height="32">
<td >
<div style="height:20px">2,0</div>
</td>
</tr>
</tbody>
</table>
<p class="test">Row percentage height is influenced by percentage cells.</p>
<table style="height:100px">
<tbody>
<tr style="height:5%" data-expected-height="50">
<td style="height:50%">0,0</td>
</tr>
<tr style="height:5%" data-expected-height="30">
<td style="height:30%">1,0</td>
</tr>
<tr style="height:5%" data-expected-height="20">
<td style="height:20%">2,0</td>
</tr>
</tbody>
</table>
<p class="test">Mixed constrained and unconstrained empty rows: only unconstrained rows grow.</p>
<table style="width:50px;height:50px">
<tbody data-expected-height="50">
<tr style="height:0" data-expected-height="0"><td></td></tr>
<tr data-expected-height="25"><td></td></tr>
<tr data-expected-height="25"><td></td></tr>
</tbody>
</table>
</main>
<script>
checkLayout("table");
</script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment