1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-06-01 12:08:14 +00:00

LibWeb: Some improvements for painting of collapsed table borders

Follow the specification in making the borders centered on the grid
lines. This avoids visual bugs due to double-rendering of borders on
either side of an edge and paves the way for a full implementation of
the harmonization algorithm for collapsed borders.

Currently, this still lacks complete handling of row and column spans.
Also, the box model for cells still considers the full width of the
internal borders instead of just half, as the specification requires.
Some additional handling of rounding issues will be needed to avoid very
subtle visual bugs.

Despite these limitations, this improves the appearance of all the
tables with collapsed borders I've tried while limiting the amount of
change to something reasonable.
This commit is contained in:
Andi Gallo 2023-07-01 03:06:21 +00:00 committed by Andreas Kling
parent f6d2a21d27
commit f544132fe8
6 changed files with 269 additions and 29 deletions

View file

@ -20,6 +20,7 @@
#include <LibWeb/Layout/Viewport.h>
#include <LibWeb/Painting/PaintableBox.h>
#include <LibWeb/Painting/StackingContext.h>
#include <LibWeb/Painting/TableBordersPainting.h>
namespace Web::Painting {
@ -72,33 +73,6 @@ static PaintPhase to_paint_phase(StackingContext::StackingContextPaintPhase phas
}
}
static void collect_cell_boxes_with_collapsed_borders(Vector<PaintableBox const*>& cell_boxes, Layout::Node const& box)
{
box.for_each_child([&](auto& child) {
if (child.display().is_table_cell() && child.computed_values().border_collapse() == CSS::BorderCollapse::Collapse) {
VERIFY(is<Layout::Box>(child) && child.paintable());
cell_boxes.append(static_cast<Layout::Box const&>(child).paintable_box());
} else {
collect_cell_boxes_with_collapsed_borders(cell_boxes, child);
}
});
}
static void paint_table_collapsed_borders(PaintContext& context, Layout::Node const& box)
{
Vector<PaintableBox const*> cell_boxes;
collect_cell_boxes_with_collapsed_borders(cell_boxes, box);
for (auto const cell_box : cell_boxes) {
auto borders_data = cell_box->override_borders_data().has_value() ? cell_box->override_borders_data().value() : BordersData {
.top = cell_box->box_model().border.top == 0 ? CSS::BorderData() : cell_box->computed_values().border_top(),
.right = cell_box->box_model().border.right == 0 ? CSS::BorderData() : cell_box->computed_values().border_right(),
.bottom = cell_box->box_model().border.bottom == 0 ? CSS::BorderData() : cell_box->computed_values().border_bottom(),
.left = cell_box->box_model().border.left == 0 ? CSS::BorderData() : cell_box->computed_values().border_left(),
};
paint_all_borders(context, cell_box->absolute_border_box_rect(), cell_box->normalized_border_radii_data(), borders_data);
}
}
void StackingContext::paint_descendants(PaintContext& context, Layout::Node const& box, StackingContextPaintPhase phase) const
{
if (auto* paintable = box.paintable()) {