mirror of
https://github.com/RGBCube/serenity
synced 2025-05-29 16:25:07 +00:00
LibWeb: Complete table border conflict resolution
Add the element type and grid position to the algorithm and change the table borders painting to apply the new criteria to corners as well.
This commit is contained in:
parent
849cf894d8
commit
a7166eb103
6 changed files with 317 additions and 127 deletions
|
@ -119,7 +119,7 @@ struct LayoutState {
|
|||
void add_floating_descendant(Box const& box) { m_floating_descendants.set(&box); }
|
||||
auto const& floating_descendants() const { return m_floating_descendants; }
|
||||
|
||||
void set_override_borders_data(Painting::BordersData const& override_borders_data) { m_override_borders_data = override_borders_data; }
|
||||
void set_override_borders_data(Painting::PaintableBox::BordersDataWithElementKind const& override_borders_data) { m_override_borders_data = override_borders_data; }
|
||||
auto const& override_borders_data() const { return m_override_borders_data; }
|
||||
|
||||
void set_table_cell_coordinates(Painting::PaintableBox::TableCellCoordinates const& table_cell_coordinates) { m_table_cell_coordinates = table_cell_coordinates; }
|
||||
|
@ -146,7 +146,7 @@ struct LayoutState {
|
|||
|
||||
HashTable<JS::GCPtr<Box const>> m_floating_descendants;
|
||||
|
||||
Optional<Painting::BordersData> m_override_borders_data;
|
||||
Optional<Painting::PaintableBox::BordersDataWithElementKind> m_override_borders_data;
|
||||
Optional<Painting::PaintableBox::TableCellCoordinates> m_table_cell_coordinates;
|
||||
};
|
||||
|
||||
|
|
|
@ -1182,7 +1182,8 @@ void TableFormattingContext::position_cell_boxes()
|
|||
|
||||
bool TableFormattingContext::border_is_less_specific(const CSS::BorderData& a, const CSS::BorderData& b)
|
||||
{
|
||||
// Implements criteria for steps 1, 2 and 3 of border conflict resolution algorithm.
|
||||
// Implements criteria for steps 1, 2 and 3 of border conflict resolution algorithm, as described in
|
||||
// https://www.w3.org/TR/CSS22/tables.html#border-conflict-resolution.
|
||||
static HashMap<CSS::LineStyle, unsigned> const line_style_score = {
|
||||
{ CSS::LineStyle::Inset, 0 },
|
||||
{ CSS::LineStyle::Groove, 1 },
|
||||
|
@ -1194,6 +1195,8 @@ bool TableFormattingContext::border_is_less_specific(const CSS::BorderData& a, c
|
|||
{ CSS::LineStyle::Double, 7 },
|
||||
};
|
||||
|
||||
// 1. Borders with the 'border-style' of 'hidden' take precedence over all other conflicting borders. Any border with this
|
||||
// value suppresses all borders at this location.
|
||||
if (a.line_style == CSS::LineStyle::Hidden) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1202,12 +1205,17 @@ bool TableFormattingContext::border_is_less_specific(const CSS::BorderData& a, c
|
|||
return true;
|
||||
}
|
||||
|
||||
// 2. Borders with a style of 'none' have the lowest priority. Only if the border properties of all the elements meeting
|
||||
// at this edge are 'none' will the border be omitted (but note that 'none' is the default value for the border style.)
|
||||
if (a.line_style == CSS::LineStyle::None) {
|
||||
return true;
|
||||
}
|
||||
if (b.line_style == CSS::LineStyle::None) {
|
||||
return false;
|
||||
}
|
||||
// 3. If none of the styles are 'hidden' and at least one of them is not 'none', then narrow borders are discarded in favor
|
||||
// of wider ones. If several have the same 'border-width' then styles are preferred in this order: 'double', 'solid',
|
||||
// 'dashed', 'dotted', 'ridge', 'outset', 'groove', and the lowest: 'inset'.
|
||||
if (a.width > b.width) {
|
||||
return false;
|
||||
} else if (a.width < b.width) {
|
||||
|
@ -1221,11 +1229,6 @@ bool TableFormattingContext::border_is_less_specific(const CSS::BorderData& a, c
|
|||
return false;
|
||||
}
|
||||
|
||||
static const CSS::BorderData& winning_border_style(const CSS::BorderData& a, const CSS::BorderData& b)
|
||||
{
|
||||
return TableFormattingContext::border_is_less_specific(a, b) ? b : a;
|
||||
}
|
||||
|
||||
const CSS::BorderData& TableFormattingContext::border_data_conflicting_edge(TableFormattingContext::ConflictingEdge const& conflicting_edge)
|
||||
{
|
||||
auto const& style = conflicting_edge.element->computed_values();
|
||||
|
@ -1248,10 +1251,52 @@ const CSS::BorderData& TableFormattingContext::border_data_conflicting_edge(Tabl
|
|||
}
|
||||
}
|
||||
|
||||
const Painting::PaintableBox::BorderDataWithElementKind TableFormattingContext::border_data_with_element_kind_from_conflicting_edge(ConflictingEdge const& conflicting_edge)
|
||||
{
|
||||
auto const& border_data = border_data_conflicting_edge(conflicting_edge);
|
||||
return { .border_data = border_data, .element_kind = conflicting_edge.element_kind };
|
||||
}
|
||||
|
||||
TableFormattingContext::ConflictingEdge const& TableFormattingContext::winning_conflicting_edge(TableFormattingContext::ConflictingEdge const& a, TableFormattingContext::ConflictingEdge const& b)
|
||||
{
|
||||
auto a_border_data = border_data_conflicting_edge(a);
|
||||
auto b_border_data = border_data_conflicting_edge(b);
|
||||
// First check if step 4 of border conflict resolution applies, as described in https://www.w3.org/TR/CSS22/tables.html#border-conflict-resolution.
|
||||
if (a_border_data.line_style == b_border_data.line_style && a_border_data.width == b_border_data.width) {
|
||||
// 4. If border styles differ only in color, then a style set on a cell wins over one on a row, which wins over a
|
||||
// row group, column, column group and, lastly, table. When two elements of the same type conflict, then the one
|
||||
// further to the left (if the table's 'direction' is 'ltr'; right, if it is 'rtl') and further to the top wins.
|
||||
if (static_cast<unsigned>(a.element_kind) < static_cast<unsigned>(b.element_kind)) {
|
||||
return a;
|
||||
} else if (static_cast<unsigned>(a.element_kind) > static_cast<unsigned>(b.element_kind)) {
|
||||
return b;
|
||||
}
|
||||
// Here the element kind is the same, thus the coordinates are either both set or not set.
|
||||
VERIFY(a.column.has_value() == b.column.has_value());
|
||||
VERIFY(a.row.has_value() == b.row.has_value());
|
||||
if (a.column.has_value()) {
|
||||
if (a.column.value() < b.column.value()) {
|
||||
return a;
|
||||
} else if (a.column.value() > b.column.value()) {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
if (a.row.has_value()) {
|
||||
if (a.row.value() < b.row.value()) {
|
||||
return a;
|
||||
} else if (a.row.value() > b.row.value()) {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
// Apply steps 1, 2 and 3 of the border conflict resolution algorithm.
|
||||
return border_is_less_specific(a_border_data, b_border_data) ? b : a;
|
||||
}
|
||||
|
||||
void TableFormattingContext::border_conflict_resolution()
|
||||
{
|
||||
// Partially implements border conflict resolution, as described in
|
||||
// https://www.w3.org/TR/CSS22/tables.html#border-conflict-resolution
|
||||
// Implements border conflict resolution, as described in https://www.w3.org/TR/CSS22/tables.html#border-conflict-resolution.
|
||||
BorderConflictFinder finder(this);
|
||||
for (auto& cell : m_cells) {
|
||||
auto& cell_state = m_state.get_mutable(cell.box);
|
||||
|
@ -1264,36 +1309,55 @@ void TableFormattingContext::border_conflict_resolution()
|
|||
if (cell.box->computed_values().border_collapse() == CSS::BorderCollapse::Separate) {
|
||||
continue;
|
||||
}
|
||||
// Execute steps 1, 2 and 3 of the algorithm for each edge.
|
||||
Painting::BordersData override_borders_data;
|
||||
auto const& cell_style = cell.box->computed_values();
|
||||
auto winning_border_left = cell_style.border_left();
|
||||
for (auto const conflicting_edge : finder.conflicting_edges(cell, ConflictingSide::Left)) {
|
||||
winning_border_left = winning_border_style(winning_border_left, border_data_conflicting_edge(conflicting_edge));
|
||||
Painting::PaintableBox::BordersDataWithElementKind override_borders_data;
|
||||
ConflictingEdge winning_edge_left {
|
||||
.element = cell.box,
|
||||
.element_kind = Painting::PaintableBox::ConflictingElementKind::Cell,
|
||||
.side = ConflictingSide::Left,
|
||||
.row = cell.row_index,
|
||||
.column = cell.column_index,
|
||||
};
|
||||
for (auto const& conflicting_edge : finder.conflicting_edges(cell, ConflictingSide::Left)) {
|
||||
winning_edge_left = winning_conflicting_edge(winning_edge_left, conflicting_edge);
|
||||
}
|
||||
override_borders_data.left = winning_border_left;
|
||||
cell_state.border_left = winning_border_left.width;
|
||||
auto winning_border_right = cell_style.border_right();
|
||||
for (auto const conflicting_edge : finder.conflicting_edges(cell, ConflictingSide::Right)) {
|
||||
winning_border_right = winning_border_style(winning_border_right, border_data_conflicting_edge(conflicting_edge));
|
||||
override_borders_data.left = border_data_with_element_kind_from_conflicting_edge(winning_edge_left);
|
||||
cell_state.border_left = override_borders_data.left.border_data.width;
|
||||
ConflictingEdge winning_edge_right {
|
||||
.element = cell.box,
|
||||
.element_kind = Painting::PaintableBox::ConflictingElementKind::Cell,
|
||||
.side = ConflictingSide::Right,
|
||||
.row = cell.row_index,
|
||||
.column = cell.column_index,
|
||||
};
|
||||
for (auto const& conflicting_edge : finder.conflicting_edges(cell, ConflictingSide::Right)) {
|
||||
winning_edge_right = winning_conflicting_edge(winning_edge_right, conflicting_edge);
|
||||
}
|
||||
override_borders_data.right = winning_border_right;
|
||||
cell_state.border_right = winning_border_right.width;
|
||||
auto winning_border_top = cell_style.border_top();
|
||||
for (auto const conflicting_edge : finder.conflicting_edges(cell, ConflictingSide::Top)) {
|
||||
winning_border_top = winning_border_style(winning_border_top, border_data_conflicting_edge(conflicting_edge));
|
||||
override_borders_data.right = border_data_with_element_kind_from_conflicting_edge(winning_edge_right);
|
||||
cell_state.border_right = override_borders_data.right.border_data.width;
|
||||
ConflictingEdge winning_edge_top {
|
||||
.element = cell.box,
|
||||
.element_kind = Painting::PaintableBox::ConflictingElementKind::Cell,
|
||||
.side = ConflictingSide::Top,
|
||||
.row = cell.row_index,
|
||||
.column = cell.column_index,
|
||||
};
|
||||
for (auto const& conflicting_edge : finder.conflicting_edges(cell, ConflictingSide::Top)) {
|
||||
winning_edge_top = winning_conflicting_edge(winning_edge_top, conflicting_edge);
|
||||
}
|
||||
override_borders_data.top = winning_border_top;
|
||||
cell_state.border_top = winning_border_top.width;
|
||||
auto winning_border_bottom = cell_style.border_bottom();
|
||||
for (auto const conflicting_edge : finder.conflicting_edges(cell, ConflictingSide::Bottom)) {
|
||||
winning_border_bottom = winning_border_style(winning_border_bottom, border_data_conflicting_edge(conflicting_edge));
|
||||
override_borders_data.top = border_data_with_element_kind_from_conflicting_edge(winning_edge_top);
|
||||
cell_state.border_top = override_borders_data.top.border_data.width;
|
||||
ConflictingEdge winning_edge_bottom {
|
||||
.element = cell.box,
|
||||
.element_kind = Painting::PaintableBox::ConflictingElementKind::Cell,
|
||||
.side = ConflictingSide::Bottom,
|
||||
.row = cell.row_index,
|
||||
.column = cell.column_index,
|
||||
};
|
||||
for (auto const& conflicting_edge : finder.conflicting_edges(cell, ConflictingSide::Bottom)) {
|
||||
winning_edge_bottom = winning_conflicting_edge(winning_edge_bottom, conflicting_edge);
|
||||
}
|
||||
override_borders_data.bottom = winning_border_bottom;
|
||||
cell_state.border_bottom = override_borders_data.bottom.width;
|
||||
// FIXME: 4. If border styles differ only in color, then a style set on a cell wins over one on a row, which wins over a
|
||||
// row group, column, column group and, lastly, table. When two elements of the same type conflict, then the one
|
||||
// further to the left (if the table's 'direction' is 'ltr'; right, if it is 'rtl') and further to the top wins.
|
||||
override_borders_data.bottom = border_data_with_element_kind_from_conflicting_edge(winning_edge_bottom);
|
||||
cell_state.border_bottom = override_borders_data.bottom.border_data.width;
|
||||
cell_state.set_override_borders_data(override_borders_data);
|
||||
}
|
||||
}
|
||||
|
@ -1384,97 +1448,105 @@ Vector<TableFormattingContext::ConflictingEdge> TableFormattingContext::BorderCo
|
|||
{
|
||||
Vector<ConflictingEdge> result = {};
|
||||
if (cell.column_index >= cell.column_span && edge == ConflictingSide::Left) {
|
||||
auto maybe_cell_to_left = m_context->m_cells_by_coordinate[cell.row_index][cell.column_index - cell.column_span];
|
||||
auto left_cell_column_index = cell.column_index - cell.column_span;
|
||||
auto maybe_cell_to_left = m_context->m_cells_by_coordinate[cell.row_index][left_cell_column_index];
|
||||
if (maybe_cell_to_left.has_value()) {
|
||||
result.append({ maybe_cell_to_left->box, ConflictingSide::Right });
|
||||
result.append({ maybe_cell_to_left->box, Painting::PaintableBox::ConflictingElementKind::Cell, ConflictingSide::Right, cell.row_index, left_cell_column_index });
|
||||
}
|
||||
}
|
||||
if (cell.column_index + cell.column_span < m_context->m_cells_by_coordinate[cell.row_index].size() && edge == ConflictingSide::Right) {
|
||||
auto maybe_cell_to_right = m_context->m_cells_by_coordinate[cell.row_index][cell.column_index + cell.column_span];
|
||||
auto right_cell_column_index = cell.column_index + cell.column_span;
|
||||
auto maybe_cell_to_right = m_context->m_cells_by_coordinate[cell.row_index][right_cell_column_index];
|
||||
if (maybe_cell_to_right.has_value()) {
|
||||
result.append({ maybe_cell_to_right->box, ConflictingSide::Left });
|
||||
result.append({ maybe_cell_to_right->box, Painting::PaintableBox::ConflictingElementKind::Cell, ConflictingSide::Left, cell.row_index, right_cell_column_index });
|
||||
}
|
||||
}
|
||||
if (cell.row_index >= cell.row_span && edge == ConflictingSide::Top) {
|
||||
auto maybe_cell_above = m_context->m_cells_by_coordinate[cell.row_index - cell.row_span][cell.column_index];
|
||||
auto above_cell_row_index = cell.row_index - cell.row_span;
|
||||
auto maybe_cell_above = m_context->m_cells_by_coordinate[above_cell_row_index][cell.column_index];
|
||||
if (maybe_cell_above.has_value()) {
|
||||
result.append({ maybe_cell_above->box, ConflictingSide::Bottom });
|
||||
result.append({ maybe_cell_above->box, Painting::PaintableBox::ConflictingElementKind::Cell, ConflictingSide::Bottom, above_cell_row_index, cell.column_index });
|
||||
}
|
||||
}
|
||||
if (cell.row_index + cell.row_span < m_context->m_cells_by_coordinate.size() && edge == ConflictingSide::Bottom) {
|
||||
auto maybe_cell_below = m_context->m_cells_by_coordinate[cell.row_index + cell.row_span][cell.column_index];
|
||||
auto below_cell_row_index = cell.row_index + cell.row_span;
|
||||
auto maybe_cell_below = m_context->m_cells_by_coordinate[below_cell_row_index][cell.column_index];
|
||||
if (maybe_cell_below.has_value()) {
|
||||
result.append({ maybe_cell_below->box, ConflictingSide::Top });
|
||||
result.append({ maybe_cell_below->box, Painting::PaintableBox::ConflictingElementKind::Cell, ConflictingSide::Top, below_cell_row_index, cell.column_index });
|
||||
}
|
||||
}
|
||||
if (edge == ConflictingSide::Top) {
|
||||
result.append({ m_context->m_rows[cell.row_index].box, ConflictingSide::Top });
|
||||
result.append({ m_context->m_rows[cell.row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Top, cell.row_index, {} });
|
||||
}
|
||||
if (edge == ConflictingSide::Bottom) {
|
||||
result.append({ m_context->m_rows[cell.row_index].box, ConflictingSide::Bottom });
|
||||
result.append({ m_context->m_rows[cell.row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Bottom, cell.row_index, {} });
|
||||
}
|
||||
if (cell.row_index >= cell.row_span && edge == ConflictingSide::Top) {
|
||||
result.append({ m_context->m_rows[cell.row_index - cell.row_span].box, ConflictingSide::Bottom });
|
||||
auto above_row_index = cell.row_index - cell.row_span;
|
||||
result.append({ m_context->m_rows[above_row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Bottom, above_row_index, {} });
|
||||
}
|
||||
if (cell.row_index + cell.row_span < m_context->m_rows.size() && edge == ConflictingSide::Bottom) {
|
||||
result.append({ m_context->m_rows[cell.row_index + cell.row_span].box, ConflictingSide::Top });
|
||||
auto below_row_index = cell.row_index + cell.row_span;
|
||||
result.append({ m_context->m_rows[below_row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Top, below_row_index, {} });
|
||||
}
|
||||
auto const& maybe_row_group = m_row_group_elements_by_index[cell.row_index];
|
||||
if (maybe_row_group.has_value() && cell.row_index == maybe_row_group->start_index && edge == ConflictingSide::Top) {
|
||||
result.append({ maybe_row_group->row_group, ConflictingSide::Top });
|
||||
result.append({ maybe_row_group->row_group, Painting::PaintableBox::ConflictingElementKind::RowGroup, ConflictingSide::Top, maybe_row_group->start_index, {} });
|
||||
}
|
||||
if (cell.row_index >= cell.row_span) {
|
||||
auto const& maybe_row_group_above = m_row_group_elements_by_index[cell.row_index - cell.row_span];
|
||||
if (maybe_row_group_above.has_value() && cell.row_index == maybe_row_group_above->start_index + maybe_row_group_above->row_count && edge == ConflictingSide::Top) {
|
||||
result.append({ maybe_row_group_above->row_group, ConflictingSide::Bottom });
|
||||
result.append({ maybe_row_group_above->row_group, Painting::PaintableBox::ConflictingElementKind::RowGroup, ConflictingSide::Bottom, maybe_row_group_above->start_index, {} });
|
||||
}
|
||||
}
|
||||
if (maybe_row_group.has_value() && cell.row_index == maybe_row_group->start_index + maybe_row_group->row_count - 1 && edge == ConflictingSide::Bottom) {
|
||||
result.append({ maybe_row_group->row_group, ConflictingSide::Bottom });
|
||||
result.append({ maybe_row_group->row_group, Painting::PaintableBox::ConflictingElementKind::RowGroup, ConflictingSide::Bottom, maybe_row_group->start_index, {} });
|
||||
}
|
||||
if (cell.row_index + cell.row_span < m_row_group_elements_by_index.size()) {
|
||||
auto const& maybe_row_group_below = m_row_group_elements_by_index[cell.row_index + cell.row_span];
|
||||
if (maybe_row_group_below.has_value() && cell.row_index + cell.row_span == maybe_row_group_below->start_index && edge == ConflictingSide::Bottom) {
|
||||
result.append({ maybe_row_group_below->row_group, ConflictingSide::Top });
|
||||
result.append({ maybe_row_group_below->row_group, Painting::PaintableBox::ConflictingElementKind::RowGroup, ConflictingSide::Top, maybe_row_group_below->start_index, {} });
|
||||
}
|
||||
}
|
||||
if (m_col_elements_by_index[cell.column_index] && edge == ConflictingSide::Left) {
|
||||
result.append({ m_col_elements_by_index[cell.column_index], ConflictingSide::Left });
|
||||
result.append({ m_col_elements_by_index[cell.column_index], Painting::PaintableBox::ConflictingElementKind::ColumnGroup, ConflictingSide::Left, {}, cell.column_index });
|
||||
}
|
||||
if (cell.column_index >= cell.column_span && m_col_elements_by_index[cell.column_index - cell.column_span] && edge == ConflictingSide::Left) {
|
||||
result.append({ m_col_elements_by_index[cell.column_index - cell.column_span], ConflictingSide::Right });
|
||||
auto left_column_index = cell.column_index - cell.column_span;
|
||||
result.append({ m_col_elements_by_index[left_column_index], Painting::PaintableBox::ConflictingElementKind::ColumnGroup, ConflictingSide::Right, {}, left_column_index });
|
||||
}
|
||||
if (m_col_elements_by_index[cell.column_index] && edge == ConflictingSide::Right) {
|
||||
result.append({ m_col_elements_by_index[cell.column_index], ConflictingSide::Right });
|
||||
result.append({ m_col_elements_by_index[cell.column_index], Painting::PaintableBox::ConflictingElementKind::ColumnGroup, ConflictingSide::Right, {}, cell.column_index });
|
||||
}
|
||||
if (cell.column_index + cell.column_span < m_col_elements_by_index.size() && m_col_elements_by_index[cell.column_index + cell.column_span] && edge == ConflictingSide::Right) {
|
||||
result.append({ m_col_elements_by_index[cell.column_index + cell.column_span], ConflictingSide::Left });
|
||||
auto right_column_index = cell.column_index + cell.column_span;
|
||||
result.append({ m_col_elements_by_index[right_column_index], Painting::PaintableBox::ConflictingElementKind::ColumnGroup, ConflictingSide::Left, {}, right_column_index });
|
||||
}
|
||||
if (cell.row_index == 0 && edge == ConflictingSide::Top) {
|
||||
if (m_col_elements_by_index[cell.column_index]) {
|
||||
result.append({ m_col_elements_by_index[cell.column_index], ConflictingSide::Top });
|
||||
result.append({ m_col_elements_by_index[cell.column_index], Painting::PaintableBox::ConflictingElementKind::ColumnGroup, ConflictingSide::Top, {}, cell.column_index });
|
||||
}
|
||||
result.append({ &m_context->table_box(), ConflictingSide::Top });
|
||||
result.append({ &m_context->table_box(), Painting::PaintableBox::ConflictingElementKind::Table, ConflictingSide::Top, {}, {} });
|
||||
}
|
||||
if (cell.row_index == m_context->m_rows.size() - 1 && edge == ConflictingSide::Bottom) {
|
||||
if (m_col_elements_by_index[cell.column_index]) {
|
||||
result.append({ m_col_elements_by_index[cell.column_index], ConflictingSide::Bottom });
|
||||
result.append({ m_col_elements_by_index[cell.column_index], Painting::PaintableBox::ConflictingElementKind::ColumnGroup, ConflictingSide::Bottom, {}, cell.column_index });
|
||||
}
|
||||
result.append({ &m_context->table_box(), ConflictingSide::Bottom });
|
||||
result.append({ &m_context->table_box(), Painting::PaintableBox::ConflictingElementKind::Table, ConflictingSide::Bottom, {}, {} });
|
||||
}
|
||||
if (cell.column_index == 0 && edge == ConflictingSide::Left) {
|
||||
result.append({ m_context->m_rows[cell.row_index].box, ConflictingSide::Left });
|
||||
result.append({ m_context->m_rows[cell.row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Left, cell.row_index, {} });
|
||||
if (m_row_group_elements_by_index[cell.row_index].has_value()) {
|
||||
result.append({ m_row_group_elements_by_index[cell.row_index]->row_group, ConflictingSide::Left });
|
||||
result.append({ m_row_group_elements_by_index[cell.row_index]->row_group, Painting::PaintableBox::ConflictingElementKind::RowGroup, ConflictingSide::Left, cell.row_index, {} });
|
||||
}
|
||||
result.append({ &m_context->table_box(), ConflictingSide::Left });
|
||||
result.append({ &m_context->table_box(), Painting::PaintableBox::ConflictingElementKind::Table, ConflictingSide::Left, {}, {} });
|
||||
}
|
||||
if (cell.column_index == m_context->m_columns.size() - 1 && edge == ConflictingSide::Right) {
|
||||
result.append({ m_context->m_rows[cell.row_index].box, ConflictingSide::Right });
|
||||
result.append({ m_context->m_rows[cell.row_index].box, Painting::PaintableBox::ConflictingElementKind::Row, ConflictingSide::Right, cell.row_index, {} });
|
||||
if (m_row_group_elements_by_index[cell.row_index].has_value()) {
|
||||
result.append({ m_row_group_elements_by_index[cell.row_index]->row_group, ConflictingSide::Right });
|
||||
result.append({ m_row_group_elements_by_index[cell.row_index]->row_group, Painting::PaintableBox::ConflictingElementKind::RowGroup, ConflictingSide::Right, cell.row_index, {} });
|
||||
}
|
||||
result.append({ &m_context->table_box(), ConflictingSide::Right });
|
||||
result.append({ &m_context->table_box(), Painting::PaintableBox::ConflictingElementKind::Table, ConflictingSide::Right, {}, {} });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -157,10 +157,16 @@ private:
|
|||
|
||||
struct ConflictingEdge {
|
||||
Node const* element;
|
||||
Painting::PaintableBox::ConflictingElementKind element_kind;
|
||||
ConflictingSide side;
|
||||
Optional<size_t> row;
|
||||
Optional<size_t> column;
|
||||
};
|
||||
|
||||
static TableFormattingContext::ConflictingEdge const& winning_conflicting_edge(TableFormattingContext::ConflictingEdge const& a, TableFormattingContext::ConflictingEdge const& b);
|
||||
|
||||
static const CSS::BorderData& border_data_conflicting_edge(ConflictingEdge const& conflicting_edge);
|
||||
static const Painting::PaintableBox::BorderDataWithElementKind border_data_with_element_kind_from_conflicting_edge(ConflictingEdge const& conflicting_edge);
|
||||
|
||||
class BorderConflictFinder {
|
||||
public:
|
||||
|
|
|
@ -224,9 +224,19 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const
|
|||
}
|
||||
}
|
||||
|
||||
BordersData PaintableBox::remove_element_kind_from_borders_data(PaintableBox::BordersDataWithElementKind borders_data)
|
||||
{
|
||||
return {
|
||||
.top = borders_data.top.border_data,
|
||||
.right = borders_data.right.border_data,
|
||||
.bottom = borders_data.bottom.border_data,
|
||||
.left = borders_data.left.border_data,
|
||||
};
|
||||
}
|
||||
|
||||
void PaintableBox::paint_border(PaintContext& context) const
|
||||
{
|
||||
auto borders_data = m_override_borders_data.has_value() ? m_override_borders_data.value() : BordersData {
|
||||
auto borders_data = m_override_borders_data.has_value() ? remove_element_kind_from_borders_data(m_override_borders_data.value()) : BordersData {
|
||||
.top = box_model().border.top == 0 ? CSS::BorderData() : computed_values().border_top(),
|
||||
.right = box_model().border.right == 0 ? CSS::BorderData() : computed_values().border_right(),
|
||||
.bottom = box_model().border.bottom == 0 ? CSS::BorderData() : computed_values().border_bottom(),
|
||||
|
|
|
@ -130,8 +130,31 @@ public:
|
|||
|
||||
bool is_out_of_view(PaintContext&) const;
|
||||
|
||||
void set_override_borders_data(BordersData const& override_borders_data) { m_override_borders_data = override_borders_data; }
|
||||
Optional<BordersData> const& override_borders_data() const { return m_override_borders_data; }
|
||||
enum class ConflictingElementKind {
|
||||
Cell,
|
||||
Row,
|
||||
RowGroup,
|
||||
Column,
|
||||
ColumnGroup,
|
||||
Table,
|
||||
};
|
||||
|
||||
struct BorderDataWithElementKind {
|
||||
CSS::BorderData border_data;
|
||||
ConflictingElementKind element_kind;
|
||||
};
|
||||
|
||||
struct BordersDataWithElementKind {
|
||||
BorderDataWithElementKind top;
|
||||
BorderDataWithElementKind right;
|
||||
BorderDataWithElementKind bottom;
|
||||
BorderDataWithElementKind left;
|
||||
};
|
||||
|
||||
void set_override_borders_data(BordersDataWithElementKind const& override_borders_data) { m_override_borders_data = override_borders_data; }
|
||||
Optional<BordersDataWithElementKind> const& override_borders_data() const { return m_override_borders_data; }
|
||||
|
||||
static BordersData remove_element_kind_from_borders_data(PaintableBox::BordersDataWithElementKind borders_data);
|
||||
|
||||
struct TableCellCoordinates {
|
||||
size_t row_index;
|
||||
|
@ -182,7 +205,7 @@ private:
|
|||
mutable bool m_clipping_overflow { false };
|
||||
Optional<BorderRadiusCornerClipper> mutable m_overflow_corner_radius_clipper;
|
||||
|
||||
Optional<BordersData> m_override_borders_data;
|
||||
Optional<BordersDataWithElementKind> m_override_borders_data;
|
||||
Optional<TableCellCoordinates> m_table_cell_coordinates;
|
||||
};
|
||||
|
||||
|
|
|
@ -49,97 +49,147 @@ enum class EdgeDirection {
|
|||
|
||||
struct BorderEdgePaintingInfo {
|
||||
DevicePixelRect rect;
|
||||
CSS::BorderData border_data;
|
||||
PaintableBox::BorderDataWithElementKind border_data_with_element_kind;
|
||||
EdgeDirection direction;
|
||||
Optional<size_t> row;
|
||||
Optional<size_t> column;
|
||||
};
|
||||
|
||||
static BorderEdgePaintingInfo make_right_cell_edge(PaintContext& context, CSSPixelRect const& right_cell_rect, CSSPixelRect const& cell_rect, BordersData const& borders_data)
|
||||
static Optional<size_t> row_index_for_element_kind(size_t index, Painting::PaintableBox::ConflictingElementKind element_kind)
|
||||
{
|
||||
switch (element_kind) {
|
||||
case Painting::PaintableBox::ConflictingElementKind::Cell:
|
||||
case Painting::PaintableBox::ConflictingElementKind::Row:
|
||||
case Painting::PaintableBox::ConflictingElementKind::RowGroup: {
|
||||
return index;
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
static Optional<size_t> column_index_for_element_kind(size_t index, Painting::PaintableBox::ConflictingElementKind element_kind)
|
||||
{
|
||||
switch (element_kind) {
|
||||
case Painting::PaintableBox::ConflictingElementKind::Cell:
|
||||
case Painting::PaintableBox::ConflictingElementKind::Column:
|
||||
case Painting::PaintableBox::ConflictingElementKind::ColumnGroup: {
|
||||
return index;
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
static BorderEdgePaintingInfo make_right_cell_edge(
|
||||
PaintContext& context,
|
||||
CSSPixelRect const& right_cell_rect,
|
||||
CSSPixelRect const& cell_rect,
|
||||
PaintableBox::BordersDataWithElementKind const& borders_data,
|
||||
CellCoordinates const& coordinates)
|
||||
{
|
||||
DevicePixelRect right_border_rect = {
|
||||
context.rounded_device_pixels(right_cell_rect.x() - round(borders_data.right.width / 2)),
|
||||
context.rounded_device_pixels(cell_rect.y() - round(borders_data.top.width / 2)),
|
||||
context.rounded_device_pixels(borders_data.right.width),
|
||||
context.rounded_device_pixels(max(cell_rect.height(), right_cell_rect.height()) + round(borders_data.top.width / 2) + round(borders_data.bottom.width / 2)),
|
||||
context.rounded_device_pixels(right_cell_rect.x() - round(borders_data.right.border_data.width / 2)),
|
||||
context.rounded_device_pixels(cell_rect.y() - round(borders_data.top.border_data.width / 2)),
|
||||
context.rounded_device_pixels(borders_data.right.border_data.width),
|
||||
context.rounded_device_pixels(max(cell_rect.height(), right_cell_rect.height()) + round(borders_data.top.border_data.width / 2) + round(borders_data.bottom.border_data.width / 2)),
|
||||
};
|
||||
return BorderEdgePaintingInfo {
|
||||
.rect = right_border_rect,
|
||||
.border_data = borders_data.right,
|
||||
.border_data_with_element_kind = borders_data.right,
|
||||
.direction = EdgeDirection::Vertical,
|
||||
.row = row_index_for_element_kind(coordinates.row_index, borders_data.right.element_kind),
|
||||
.column = column_index_for_element_kind(coordinates.column_index, borders_data.right.element_kind),
|
||||
};
|
||||
}
|
||||
|
||||
static BorderEdgePaintingInfo make_down_cell_edge(PaintContext& context, CSSPixelRect const& down_cell_rect, CSSPixelRect const& cell_rect, BordersData const& borders_data)
|
||||
static BorderEdgePaintingInfo make_down_cell_edge(
|
||||
PaintContext& context,
|
||||
CSSPixelRect const& down_cell_rect,
|
||||
CSSPixelRect const& cell_rect,
|
||||
PaintableBox::BordersDataWithElementKind const& borders_data,
|
||||
CellCoordinates const& coordinates)
|
||||
{
|
||||
DevicePixelRect down_border_rect = {
|
||||
context.rounded_device_pixels(cell_rect.x() - round(borders_data.left.width / 2)),
|
||||
context.rounded_device_pixels(down_cell_rect.y() - round(borders_data.bottom.width / 2)),
|
||||
context.rounded_device_pixels(max(cell_rect.width(), down_cell_rect.width()) + round(borders_data.left.width / 2) + round(borders_data.right.width / 2)),
|
||||
context.rounded_device_pixels(borders_data.bottom.width),
|
||||
context.rounded_device_pixels(cell_rect.x() - round(borders_data.left.border_data.width / 2)),
|
||||
context.rounded_device_pixels(down_cell_rect.y() - round(borders_data.bottom.border_data.width / 2)),
|
||||
context.rounded_device_pixels(max(cell_rect.width(), down_cell_rect.width()) + round(borders_data.left.border_data.width / 2) + round(borders_data.right.border_data.width / 2)),
|
||||
context.rounded_device_pixels(borders_data.bottom.border_data.width),
|
||||
};
|
||||
return BorderEdgePaintingInfo {
|
||||
.rect = down_border_rect,
|
||||
.border_data = borders_data.bottom,
|
||||
.border_data_with_element_kind = borders_data.bottom,
|
||||
.direction = EdgeDirection::Horizontal,
|
||||
.row = row_index_for_element_kind(coordinates.row_index, borders_data.bottom.element_kind),
|
||||
.column = column_index_for_element_kind(coordinates.column_index, borders_data.bottom.element_kind),
|
||||
};
|
||||
}
|
||||
|
||||
static BorderEdgePaintingInfo make_first_row_top_cell_edge(PaintContext& context, CSSPixelRect const& cell_rect, BordersData const& borders_data)
|
||||
static BorderEdgePaintingInfo make_first_row_top_cell_edge(PaintContext& context, CSSPixelRect const& cell_rect, PaintableBox::BordersDataWithElementKind const& borders_data, CellCoordinates const& coordinates)
|
||||
{
|
||||
DevicePixelRect top_border_rect = {
|
||||
context.rounded_device_pixels(cell_rect.x() - round(borders_data.left.width / 2)),
|
||||
context.rounded_device_pixels(cell_rect.y() - round(borders_data.top.width / 2)),
|
||||
context.rounded_device_pixels(cell_rect.x() - round(borders_data.left.border_data.width / 2)),
|
||||
context.rounded_device_pixels(cell_rect.y() - round(borders_data.top.border_data.width / 2)),
|
||||
context.rounded_device_pixels(cell_rect.width()),
|
||||
context.rounded_device_pixels(borders_data.top.width),
|
||||
context.rounded_device_pixels(borders_data.top.border_data.width),
|
||||
};
|
||||
return BorderEdgePaintingInfo {
|
||||
.rect = top_border_rect,
|
||||
.border_data = borders_data.top,
|
||||
.border_data_with_element_kind = borders_data.top,
|
||||
.direction = EdgeDirection::Horizontal,
|
||||
.row = row_index_for_element_kind(coordinates.row_index, borders_data.top.element_kind),
|
||||
.column = column_index_for_element_kind(coordinates.column_index, borders_data.top.element_kind),
|
||||
};
|
||||
}
|
||||
|
||||
static BorderEdgePaintingInfo make_last_row_bottom_cell_edge(PaintContext& context, CSSPixelRect const& cell_rect, BordersData const& borders_data)
|
||||
static BorderEdgePaintingInfo make_last_row_bottom_cell_edge(PaintContext& context, CSSPixelRect const& cell_rect, PaintableBox::BordersDataWithElementKind const& borders_data, CellCoordinates const& coordinates)
|
||||
{
|
||||
DevicePixelRect bottom_border_rect = {
|
||||
context.rounded_device_pixels(cell_rect.x() - round(borders_data.left.width / 2)),
|
||||
context.rounded_device_pixels(cell_rect.y() + cell_rect.height() - round(borders_data.bottom.width / 2)),
|
||||
context.rounded_device_pixels(cell_rect.width() + round(borders_data.left.width / 2) + round(borders_data.right.width / 2)),
|
||||
context.rounded_device_pixels(borders_data.bottom.width),
|
||||
context.rounded_device_pixels(cell_rect.x() - round(borders_data.left.border_data.width / 2)),
|
||||
context.rounded_device_pixels(cell_rect.y() + cell_rect.height() - round(borders_data.bottom.border_data.width / 2)),
|
||||
context.rounded_device_pixels(cell_rect.width() + round(borders_data.left.border_data.width / 2) + round(borders_data.right.border_data.width / 2)),
|
||||
context.rounded_device_pixels(borders_data.bottom.border_data.width),
|
||||
};
|
||||
return BorderEdgePaintingInfo {
|
||||
.rect = bottom_border_rect,
|
||||
.border_data = borders_data.bottom,
|
||||
.border_data_with_element_kind = borders_data.bottom,
|
||||
.direction = EdgeDirection::Horizontal,
|
||||
.row = row_index_for_element_kind(coordinates.row_index, borders_data.bottom.element_kind),
|
||||
.column = column_index_for_element_kind(coordinates.column_index, borders_data.bottom.element_kind),
|
||||
};
|
||||
}
|
||||
|
||||
static BorderEdgePaintingInfo make_first_column_left_cell_edge(PaintContext& context, CSSPixelRect const& cell_rect, BordersData const& borders_data)
|
||||
static BorderEdgePaintingInfo make_first_column_left_cell_edge(PaintContext& context, CSSPixelRect const& cell_rect, PaintableBox::BordersDataWithElementKind const& borders_data, CellCoordinates const& coordinates)
|
||||
{
|
||||
DevicePixelRect left_border_rect = {
|
||||
context.rounded_device_pixels(cell_rect.x() - round(borders_data.left.width / 2)),
|
||||
context.rounded_device_pixels(cell_rect.y() - round(borders_data.top.width / 2)),
|
||||
context.rounded_device_pixels(borders_data.left.width),
|
||||
context.rounded_device_pixels(cell_rect.height() + round(borders_data.top.width / 2)),
|
||||
context.rounded_device_pixels(cell_rect.x() - round(borders_data.left.border_data.width / 2)),
|
||||
context.rounded_device_pixels(cell_rect.y() - round(borders_data.top.border_data.width / 2)),
|
||||
context.rounded_device_pixels(borders_data.left.border_data.width),
|
||||
context.rounded_device_pixels(cell_rect.height() + round(borders_data.top.border_data.width / 2)),
|
||||
};
|
||||
return BorderEdgePaintingInfo {
|
||||
.rect = left_border_rect,
|
||||
.border_data = borders_data.left,
|
||||
.border_data_with_element_kind = borders_data.left,
|
||||
.direction = EdgeDirection::Vertical,
|
||||
.row = row_index_for_element_kind(coordinates.row_index, borders_data.left.element_kind),
|
||||
.column = column_index_for_element_kind(coordinates.column_index, borders_data.left.element_kind),
|
||||
};
|
||||
}
|
||||
|
||||
static BorderEdgePaintingInfo make_last_column_right_cell_edge(PaintContext& context, CSSPixelRect const& cell_rect, BordersData const& borders_data)
|
||||
static BorderEdgePaintingInfo make_last_column_right_cell_edge(PaintContext& context, CSSPixelRect const& cell_rect, PaintableBox::BordersDataWithElementKind const& borders_data, CellCoordinates const& coordinates)
|
||||
{
|
||||
DevicePixelRect right_border_rect = {
|
||||
context.rounded_device_pixels(cell_rect.x() + cell_rect.width() - round(borders_data.right.width / 2)),
|
||||
context.rounded_device_pixels(cell_rect.y() - round(borders_data.top.width / 2)),
|
||||
context.rounded_device_pixels(borders_data.right.width),
|
||||
context.rounded_device_pixels(cell_rect.height() + round(borders_data.top.width / 2) + round(borders_data.bottom.width / 2)),
|
||||
context.rounded_device_pixels(cell_rect.x() + cell_rect.width() - round(borders_data.right.border_data.width / 2)),
|
||||
context.rounded_device_pixels(cell_rect.y() - round(borders_data.top.border_data.width / 2)),
|
||||
context.rounded_device_pixels(borders_data.right.border_data.width),
|
||||
context.rounded_device_pixels(cell_rect.height() + round(borders_data.top.border_data.width / 2) + round(borders_data.bottom.border_data.width / 2)),
|
||||
};
|
||||
return BorderEdgePaintingInfo {
|
||||
.rect = right_border_rect,
|
||||
.border_data = borders_data.right,
|
||||
.border_data_with_element_kind = borders_data.right,
|
||||
.direction = EdgeDirection::Vertical,
|
||||
.row = row_index_for_element_kind(coordinates.row_index, borders_data.right.element_kind),
|
||||
.column = column_index_for_element_kind(coordinates.column_index, borders_data.right.element_kind),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -147,17 +197,38 @@ static void paint_collected_edges(PaintContext& context, Vector<BorderEdgePainti
|
|||
{
|
||||
// This sorting step isn't part of the specification, but it matches the behavior of other browsers at border intersections, which aren't
|
||||
// part of border conflict resolution in the specification but it's still desirable to handle them in a way which is consistent with it.
|
||||
// See https://www.w3.org/TR/CSS22/tables.html#border-conflict-resolution for reference.
|
||||
quick_sort(border_edge_painting_info_list, [](auto const& a, auto const& b) {
|
||||
return Layout::TableFormattingContext::border_is_less_specific(a.border_data, b.border_data);
|
||||
auto const& a_border_data = a.border_data_with_element_kind.border_data;
|
||||
auto const& b_border_data = b.border_data_with_element_kind.border_data;
|
||||
if (a_border_data.line_style == b_border_data.line_style && a_border_data.width == b_border_data.width) {
|
||||
if (b.border_data_with_element_kind.element_kind < a.border_data_with_element_kind.element_kind) {
|
||||
return true;
|
||||
} else if (b.border_data_with_element_kind.element_kind > a.border_data_with_element_kind.element_kind) {
|
||||
return false;
|
||||
}
|
||||
// Here the element kind is the same, thus the coordinates are either both set or not set.
|
||||
VERIFY(a.column.has_value() == b.column.has_value());
|
||||
VERIFY(a.row.has_value() == b.row.has_value());
|
||||
if (a.column.has_value()) {
|
||||
if (b.column.value() < a.column.value()) {
|
||||
return true;
|
||||
} else if (b.column.value() > a.column.value()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return a.row.has_value() ? b.row.value() < a.row.value() : false;
|
||||
}
|
||||
return Layout::TableFormattingContext::border_is_less_specific(a_border_data, b_border_data);
|
||||
});
|
||||
|
||||
for (auto const& border_edge_painting_info : border_edge_painting_info_list) {
|
||||
auto const& border_data = border_edge_painting_info.border_data;
|
||||
CSSPixels width = border_data.width;
|
||||
auto const& border_data_with_element_kind = border_edge_painting_info.border_data_with_element_kind;
|
||||
CSSPixels width = border_data_with_element_kind.border_data.width;
|
||||
if (width <= 0)
|
||||
continue;
|
||||
auto color = border_data.color;
|
||||
auto border_style = border_data.line_style;
|
||||
auto color = border_data_with_element_kind.border_data.color;
|
||||
auto border_style = border_data_with_element_kind.border_data.line_style;
|
||||
auto p1 = border_edge_painting_info.rect.top_left();
|
||||
auto p2 = border_edge_painting_info.direction == EdgeDirection::Horizontal
|
||||
? border_edge_painting_info.rect.top_right()
|
||||
|
@ -194,31 +265,39 @@ void paint_table_collapsed_borders(PaintContext& context, Layout::Node const& bo
|
|||
column_count = max(column_count, cell_box->table_cell_coordinates()->column_index + cell_box->table_cell_coordinates()->column_span);
|
||||
}
|
||||
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(),
|
||||
auto borders_data = cell_box->override_borders_data().has_value() ? cell_box->override_borders_data().value() : PaintableBox::BordersDataWithElementKind {
|
||||
.top = { .border_data = cell_box->box_model().border.top == 0 ? CSS::BorderData() : cell_box->computed_values().border_top(), .element_kind = PaintableBox::ConflictingElementKind::Cell },
|
||||
.right = { .border_data = cell_box->box_model().border.right == 0 ? CSS::BorderData() : cell_box->computed_values().border_right(), .element_kind = PaintableBox::ConflictingElementKind::Cell },
|
||||
.bottom = { .border_data = cell_box->box_model().border.bottom == 0 ? CSS::BorderData() : cell_box->computed_values().border_bottom(), .element_kind = PaintableBox::ConflictingElementKind::Cell },
|
||||
.left = { .border_data = cell_box->box_model().border.left == 0 ? CSS::BorderData() : cell_box->computed_values().border_left(), .element_kind = PaintableBox::ConflictingElementKind::Cell },
|
||||
};
|
||||
auto cell_rect = cell_box->absolute_border_box_rect();
|
||||
auto maybe_right_cell = cell_coordinates_to_box.get(CellCoordinates {
|
||||
CellCoordinates right_cell_coordinates {
|
||||
.row_index = cell_box->table_cell_coordinates()->row_index,
|
||||
.column_index = cell_box->table_cell_coordinates()->column_index + cell_box->table_cell_coordinates()->column_span });
|
||||
auto maybe_down_cell = cell_coordinates_to_box.get(CellCoordinates {
|
||||
.column_index = cell_box->table_cell_coordinates()->column_index + cell_box->table_cell_coordinates()->column_span
|
||||
};
|
||||
auto maybe_right_cell = cell_coordinates_to_box.get(right_cell_coordinates);
|
||||
CellCoordinates down_cell_coordinates {
|
||||
.row_index = cell_box->table_cell_coordinates()->row_index + cell_box->table_cell_coordinates()->row_span,
|
||||
.column_index = cell_box->table_cell_coordinates()->column_index });
|
||||
.column_index = cell_box->table_cell_coordinates()->column_index
|
||||
};
|
||||
auto maybe_down_cell = cell_coordinates_to_box.get(down_cell_coordinates);
|
||||
if (maybe_right_cell.has_value())
|
||||
border_edge_painting_info_list.append(make_right_cell_edge(context, maybe_right_cell.value()->absolute_border_box_rect(), cell_rect, borders_data));
|
||||
border_edge_painting_info_list.append(make_right_cell_edge(context, maybe_right_cell.value()->absolute_border_box_rect(), cell_rect, borders_data, right_cell_coordinates));
|
||||
if (maybe_down_cell.has_value())
|
||||
border_edge_painting_info_list.append(make_down_cell_edge(context, maybe_down_cell.value()->absolute_border_box_rect(), cell_rect, borders_data));
|
||||
border_edge_painting_info_list.append(make_down_cell_edge(context, maybe_down_cell.value()->absolute_border_box_rect(), cell_rect, borders_data, down_cell_coordinates));
|
||||
if (cell_box->table_cell_coordinates()->row_index == 0)
|
||||
border_edge_painting_info_list.append(make_first_row_top_cell_edge(context, cell_rect, borders_data));
|
||||
border_edge_painting_info_list.append(make_first_row_top_cell_edge(context, cell_rect, borders_data,
|
||||
{ .row_index = 0, .column_index = cell_box->table_cell_coordinates()->column_index }));
|
||||
if (cell_box->table_cell_coordinates()->row_index + cell_box->table_cell_coordinates()->row_span == row_count)
|
||||
border_edge_painting_info_list.append(make_last_row_bottom_cell_edge(context, cell_rect, borders_data));
|
||||
border_edge_painting_info_list.append(make_last_row_bottom_cell_edge(context, cell_rect, borders_data,
|
||||
{ .row_index = row_count - 1, .column_index = cell_box->table_cell_coordinates()->column_index }));
|
||||
if (cell_box->table_cell_coordinates()->column_index == 0)
|
||||
border_edge_painting_info_list.append(make_first_column_left_cell_edge(context, cell_rect, borders_data));
|
||||
border_edge_painting_info_list.append(make_first_column_left_cell_edge(context, cell_rect, borders_data,
|
||||
{ .row_index = cell_box->table_cell_coordinates()->row_index, .column_index = 0 }));
|
||||
if (cell_box->table_cell_coordinates()->column_index + cell_box->table_cell_coordinates()->column_span == column_count)
|
||||
border_edge_painting_info_list.append(make_last_column_right_cell_edge(context, cell_rect, borders_data));
|
||||
border_edge_painting_info_list.append(make_last_column_right_cell_edge(context, cell_rect, borders_data,
|
||||
{ .row_index = cell_box->table_cell_coordinates()->row_index, .column_index = column_count - 1 }));
|
||||
}
|
||||
|
||||
paint_collected_edges(context, border_edge_painting_info_list);
|
||||
|
@ -232,7 +311,7 @@ void paint_table_collapsed_borders(PaintContext& context, Layout::Node const& bo
|
|||
if (!top_left && !top_right && !bottom_left && !bottom_right) {
|
||||
continue;
|
||||
} else {
|
||||
auto borders_data = cell_box->override_borders_data().has_value() ? cell_box->override_borders_data().value() : BordersData {
|
||||
auto borders_data = cell_box->override_borders_data().has_value() ? PaintableBox::remove_element_kind_from_borders_data(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(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue