LibWeb: Apply scroll offset and clip rectangle to table borders

Moves paint_table_borders() call into PaintableBox::paint() to make
scroll offset and clip rectangle of enclosing scrollable be applied
in ::before_paint().
This commit is contained in:
Aliaksandr Kalenik 2024-07-30 13:41:48 +03:00 committed by Alexander Kalenik
parent cf25a06d67
commit 2cc2646f55
Notes: github-actions[bot] 2024-07-31 19:44:04 +00:00
5 changed files with 196 additions and 12 deletions

View File

@ -0,0 +1,82 @@
<!DOCTYPE html>
<head>
<style>
* {
scrollbar-width: none;
}
#scrollable-div {
width: 300px;
height: 300px;
overflow: auto;
border: 1px solid #000;
}
table {
width: 100%;
border-collapse: collapse;
}
th,
td {
padding: 0;
margin: 0;
height: 50px;
box-sizing: content-box;
border: 1px solid #000;
}
</style>
</head>
<body>
<div id="scrollable-div">
<table>
<tbody>
<tr>
<td>Row 2, Cell 1</td>
<td>Row 2, Cell 2</td>
<td>Row 2, Cell 3</td>
<td>Row 2, Cell 4</td>
</tr>
<tr>
<td>Row 3, Cell 1</td>
<td>Row 3, Cell 2</td>
<td>Row 3, Cell 3</td>
<td>Row 3, Cell 4</td>
</tr>
<tr>
<td>Row 4, Cell 1</td>
<td>Row 4, Cell 2</td>
<td>Row 4, Cell 3</td>
<td>Row 4, Cell 4</td>
</tr>
<tr>
<td>Row 5, Cell 1</td>
<td>Row 5, Cell 2</td>
<td>Row 5, Cell 3</td>
<td>Row 5, Cell 4</td>
</tr>
<tr>
<td>Row 6, Cell 1</td>
<td>Row 6, Cell 2</td>
<td>Row 6, Cell 3</td>
<td>Row 6, Cell 4</td>
</tr>
<tr>
<td>Row 7, Cell 1</td>
<td>Row 7, Cell 2</td>
<td>Row 7, Cell 3</td>
<td>Row 7, Cell 4</td>
</tr>
<tr>
<td>Row 8, Cell 1</td>
<td>Row 8, Cell 2</td>
<td>Row 8, Cell 3</td>
<td>Row 8, Cell 4</td>
</tr>
<tr>
<td>Row 9, Cell 1</td>
<td>Row 9, Cell 2</td>
<td>Row 9, Cell 3</td>
<td>Row 9, Cell 4</td>
</tr>
</tbody>
</table>
</div>
</body>

View File

@ -0,0 +1,101 @@
<!DOCTYPE html>
<link rel="match" href="reference/scrollable-contains-table-ref.html" />
<head>
<style>
* {
scrollbar-width: none;
}
#scrollable-div {
width: 300px;
height: 300px;
overflow: auto;
border: 1px solid #000;
}
table {
width: 100%;
border-collapse: collapse;
}
th,
td {
padding: 0;
margin: 0;
height: 50px;
box-sizing: content-box;
border: 1px solid #000;
}
</style>
</head>
<body>
<div id="scrollable-div">
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
<th>Header 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>Row 1, Cell 1</td>
<td>Row 1, Cell 2</td>
<td>Row 1, Cell 3</td>
<td>Row 1, Cell 4</td>
</tr>
<tr>
<td>Row 2, Cell 1</td>
<td>Row 2, Cell 2</td>
<td>Row 2, Cell 3</td>
<td>Row 2, Cell 4</td>
</tr>
<tr>
<td>Row 3, Cell 1</td>
<td>Row 3, Cell 2</td>
<td>Row 3, Cell 3</td>
<td>Row 3, Cell 4</td>
</tr>
<tr>
<td>Row 4, Cell 1</td>
<td>Row 4, Cell 2</td>
<td>Row 4, Cell 3</td>
<td>Row 4, Cell 4</td>
</tr>
<tr>
<td>Row 5, Cell 1</td>
<td>Row 5, Cell 2</td>
<td>Row 5, Cell 3</td>
<td>Row 5, Cell 4</td>
</tr>
<tr>
<td>Row 6, Cell 1</td>
<td>Row 6, Cell 2</td>
<td>Row 6, Cell 3</td>
<td>Row 6, Cell 4</td>
</tr>
<tr>
<td>Row 7, Cell 1</td>
<td>Row 7, Cell 2</td>
<td>Row 7, Cell 3</td>
<td>Row 7, Cell 4</td>
</tr>
<tr>
<td>Row 8, Cell 1</td>
<td>Row 8, Cell 2</td>
<td>Row 8, Cell 3</td>
<td>Row 8, Cell 4</td>
</tr>
<tr>
<td>Row 9, Cell 1</td>
<td>Row 9, Cell 2</td>
<td>Row 9, Cell 3</td>
<td>Row 9, Cell 4</td>
</tr>
</tbody>
</table>
</div>
</body>
<script>
const scrollContainer = document.getElementById("scrollable-div");
scrollContainer.scrollTop = 100;
</script>

View File

@ -16,6 +16,7 @@ namespace Web::Painting {
enum class PaintPhase {
Background,
Border,
TableCollapsedBorder,
Foreground,
Outline,
Overlay,

View File

@ -20,6 +20,7 @@
#include <LibWeb/Painting/SVGPaintable.h>
#include <LibWeb/Painting/SVGSVGPaintable.h>
#include <LibWeb/Painting/StackingContext.h>
#include <LibWeb/Painting/TableBordersPainting.h>
#include <LibWeb/Painting/TextPaintable.h>
#include <LibWeb/Painting/ViewportPaintable.h>
#include <LibWeb/Platform/FontPlugin.h>
@ -309,10 +310,15 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const
paint_box_shadow(context);
}
if (phase == PaintPhase::Border) {
auto const is_table_with_collapsed_borders = display().is_table_inside() && computed_values().border_collapse() == CSS::BorderCollapse::Collapse;
if (!display().is_table_cell() && !is_table_with_collapsed_borders && phase == PaintPhase::Border) {
paint_border(context);
}
if ((display().is_table_inside() || computed_values().border_collapse() == CSS::BorderCollapse::Collapse) && phase == PaintPhase::TableCollapsedBorder) {
paint_table_borders(context, *this);
}
if (phase == PaintPhase::Outline) {
auto const& outline_data = this->outline_data();
if (outline_data.has_value()) {
@ -519,7 +525,7 @@ void PaintableBox::reset_scroll_offset(PaintContext& context, PaintPhase) const
void PaintableBox::apply_clip_overflow_rect(PaintContext& context, PaintPhase phase) const
{
if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::Foreground, PaintPhase::Outline))
if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::TableCollapsedBorder, PaintPhase::Foreground, PaintPhase::Outline))
return;
if (clip_rect().has_value()) {
@ -542,7 +548,7 @@ void PaintableBox::apply_clip_overflow_rect(PaintContext& context, PaintPhase ph
void PaintableBox::clear_clip_overflow_rect(PaintContext& context, PaintPhase phase) const
{
if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::Foreground, PaintPhase::Outline))
if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::TableCollapsedBorder, PaintPhase::Foreground, PaintPhase::Outline))
return;
if (m_clipping_overflow) {

View File

@ -19,7 +19,6 @@
#include <LibWeb/Painting/PaintableBox.h>
#include <LibWeb/Painting/SVGPaintable.h>
#include <LibWeb/Painting/StackingContext.h>
#include <LibWeb/Painting/TableBordersPainting.h>
#include <LibWeb/SVG/SVGMaskElement.h>
namespace Web::Painting {
@ -134,13 +133,9 @@ void StackingContext::paint_descendants(PaintContext& context, Paintable const&
case StackingContextPaintPhase::BackgroundAndBorders:
if (!child_is_inline_or_replaced && !child.is_floating()) {
paint_node(child, context, PaintPhase::Background);
bool is_table_with_collapsed_borders = child.display().is_table_inside() && child.computed_values().border_collapse() == CSS::BorderCollapse::Collapse;
if (!child.display().is_table_cell() && !is_table_with_collapsed_borders)
paint_node(child, context, PaintPhase::Border);
paint_node(child, context, PaintPhase::Border);
paint_descendants(context, child, phase);
if (child.display().is_table_inside() || child.computed_values().border_collapse() == CSS::BorderCollapse::Collapse) {
paint_table_borders(context, verify_cast<PaintableBox>(child));
}
paint_node(child, context, PaintPhase::TableCollapsedBorder);
}
break;
case StackingContextPaintPhase::Floats:
@ -155,8 +150,7 @@ void StackingContext::paint_descendants(PaintContext& context, Paintable const&
if (child_is_inline_or_replaced) {
paint_node(child, context, PaintPhase::Background);
paint_node(child, context, PaintPhase::Border);
if (child.display().is_table_inside() && child.computed_values().border_collapse() == CSS::BorderCollapse::Separate)
paint_table_borders(context, verify_cast<PaintableBox>(child));
paint_node(child, context, PaintPhase::TableCollapsedBorder);
paint_descendants(context, child, StackingContextPaintPhase::BackgroundAndBorders);
}
paint_descendants(context, child, phase);