From 52c0a5e6c95fa88760f23b3ee9b118fb3573c29c Mon Sep 17 00:00:00 2001 From: David Shin <dshin@mozilla.com> Date: Thu, 30 Mar 2023 18:11:40 +0000 Subject: [PATCH] Bug 1819266: Ensure block-direction collapsed border does not extend beyond its row. r=dholbert If `border-collapse` is set and `border` is set for `td` but there's an empty `tr`, the collapsed border was pushed out wrongly by the empty `tr`. Columns borders cannot collapse like row borders as you can't define an empty column without defining a cell. Differential Revision: https://phabricator.services.mozilla.com/D173031 --- layout/tables/nsTableFrame.cpp | 16 ++++ .../tables/border-collapse-empty-row-ref.html | 69 ++++++++++++++ .../tables/border-collapse-empty-row.html | 93 +++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 testing/web-platform/tests/css/CSS2/tables/border-collapse-empty-row-ref.html create mode 100644 testing/web-platform/tests/css/CSS2/tables/border-collapse-empty-row.html diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index 0129c749360a7..e932f2b98c278 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -7285,6 +7285,22 @@ void BCPaintBorderIterator::AccumulateOrDoActionBlockDirSegment( } } blockDirSeg.AdvanceOffsetB(); + // If the row is empty and cell borders are defined, the row will be + // zero-sized (If there existed an empty cell, it'd be sized to contain + // the cell's borders). In this case, we effectively need to "pull up" + // where the segment starts (Unless the empty row has enough block size). + if (mRow->PrincipalChildList().IsEmpty()) { + const auto rowSize = mRow->BSize(mTableWM); + if (blockDirSeg.mBEndOffset > 0 && blockDirSeg.mBEndOffset > rowSize) { + blockDirSeg.mOffsetB -= blockDirSeg.mBEndOffset - rowSize; + } else if (blockDirSeg.mBEndOffset < 0 && + -blockDirSeg.mBEndOffset > rowSize) { + // For cases of segments that don't have bevel (e.g. inner block + // direction borders). Since they "end early," the block end offset is + // negative. + blockDirSeg.mOffsetB += blockDirSeg.mBEndOffset + rowSize; + } + } } blockDirSeg.Start(*this, borderOwner, blockSegISize, inlineSegBSize); } diff --git a/testing/web-platform/tests/css/CSS2/tables/border-collapse-empty-row-ref.html b/testing/web-platform/tests/css/CSS2/tables/border-collapse-empty-row-ref.html new file mode 100644 index 0000000000000..ca1108ccd7bf7 --- /dev/null +++ b/testing/web-platform/tests/css/CSS2/tables/border-collapse-empty-row-ref.html @@ -0,0 +1,69 @@ +<!DOCTYPE html> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="help" href="http://www.w3.org/TR/CSS21/tables.html#collapsing-borders"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1819266"> +<meta name="assert" content="This test checks that collapsed border does not paint outside of its expected area."> +<style> +table { + display: inline-table; + border-collapse: collapse; +} + +td { + border: 10px solid black; + line-height: 0; + padding: 0; +} + +span { + display: inline-block; + width: 10px; + height: 10px; + background: grey; +} + +.spacer-1 tr:not(:last-child) td { + border-bottom: 12px solid black; +} + +.spacer-2 tr:not(:last-child) td { + border-bottom: 15px solid black; +} + +.spacer-3 tr:not(:last-child) td { + border-bottom: 20px solid black; +} + +</style> +<table> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +</table> +<table class="spacer-1"> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +</table> +<table class="spacer-2"> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +</table> +<table class="spacer-3"> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr><td><span></span></td><td><span></span></td></tr> +</table> diff --git a/testing/web-platform/tests/css/CSS2/tables/border-collapse-empty-row.html b/testing/web-platform/tests/css/CSS2/tables/border-collapse-empty-row.html new file mode 100644 index 0000000000000..c4114a145df0c --- /dev/null +++ b/testing/web-platform/tests/css/CSS2/tables/border-collapse-empty-row.html @@ -0,0 +1,93 @@ +<!DOCTYPE html> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="help" href="http://www.w3.org/TR/CSS21/tables.html#collapsing-borders"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1819266"> +<link rel="match" href="border-collapse-empty-row-ref.html"> +<meta name="assert" content="This test checks that collapsed border does not paint outside of its expected area."> +<style> +table { + display: inline-table; + border-collapse: collapse; +} + +td { + border: 10px solid black; + line-height: 0; + padding: 0; +} + +span { + display: inline-block; + width: 10px; + height: 10px; + background: grey; +} + +.spacer-1 { + height: 2px; +} + +.spacer-2 { + height: 5px; +} + +.spacer-3 { + height: 10px; +} +</style> +<!-- Empty rows --> +<table> +<tr><td><span></span></td><td><span></span></td></tr> +<tr></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr></tr> +<tr><td><span></span></td><td><span></span></td></tr> +</table> +<!-- Empty rows, sized less than collapsed border offset (10px / 2 = 5px). --> +<table> +<tr><td><span></span></td><td><span></span></td></tr> +<tr class="spacer-1"></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr class="spacer-1"></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr class="spacer-1"></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr class="spacer-1"></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr class="spacer-1"></tr> +<tr><td><span></span></td><td><span></span></td></tr> +</table> +<!-- Empty rows, sized exactly at collapsed border offset. --> +<table> +<tr><td><span></span></td><td><span></span></td></tr> +<tr class="spacer-2"></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr class="spacer-2"></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr class="spacer-2"></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr class="spacer-2"></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr class="spacer-2"></tr> +<tr><td><span></span></td><td><span></span></td></tr> +</table> +<!-- Empty rows, sized larger than collapsed border offset. --> +<table> +<tr><td><span></span></td><td><span></span></td></tr> +<tr class="spacer-3"></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr class="spacer-3"></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr class="spacer-3"></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr class="spacer-3"></tr> +<tr><td><span></span></td><td><span></span></td></tr> +<tr class="spacer-3"></tr> +<tr><td><span></span></td><td><span></span></td></tr> +</table> -- GitLab