LibWeb: Improve grid area calculation for abspos items in GFC

- Add support for placement of abspos items into track formed by last
  line and padding edge of grid container
- Correctly handle auto-positioned abspos items by placing them between
  padding edges of grid container

Fixes crashing on https://wpt.live/css/css-grid/abspos/positioned-grid-descendants-001.html
This commit is contained in:
Aliaksandr Kalenik 2024-10-10 23:35:44 +02:00 committed by Andreas Kling
commit 0dec2dc21c
Notes: github-actions[bot] 2024-10-11 07:09:38 +00:00
10 changed files with 473 additions and 85 deletions

View file

@ -0,0 +1,50 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x286 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x270 children: not-inline
Box <div.grid-container> at (58,58) content-size 170x170 positioned [GFC] children: not-inline
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item> at (58,58) content-size 50x50 [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [58,58 6.34375x17] baseline: 13.296875
"1"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item> at (128,58) content-size 100x50 [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [128,58 8.8125x17] baseline: 13.296875
"2"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item> at (58,128) content-size 50x100 [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [58,128 9.09375x17] baseline: 13.296875
"3"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item> at (128,128) content-size 100x100 [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [128,128 7.75x17] baseline: 13.296875
"4"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.abspos-box> at (228,228) content-size 50x50 positioned [BFC] children: not-inline
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <(anonymous)> at (8,278) content-size 784x0 children: inline
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x286]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x270]
PaintableBox (Box<DIV>.grid-container) [8,8 270x270]
PaintableWithLines (BlockContainer<DIV>.grid-item) [58,58 50x50]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.grid-item) [128,58 100x50]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.grid-item) [58,128 50x100]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.grid-item) [128,128 100x100]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.abspos-box) [228,228 50x50]
PaintableWithLines (BlockContainer(anonymous)) [8,278 784x0]

View file

@ -0,0 +1,50 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x286 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x270 children: not-inline
Box <div.grid-container> at (58,58) content-size 170x170 positioned [GFC] children: not-inline
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item> at (58,58) content-size 50x50 [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [58,58 6.34375x17] baseline: 13.296875
"1"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item> at (128,58) content-size 100x50 [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [128,58 8.8125x17] baseline: 13.296875
"2"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item> at (58,128) content-size 50x100 [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [58,128 9.09375x17] baseline: 13.296875
"3"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item> at (128,128) content-size 100x100 [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [128,128 7.75x17] baseline: 13.296875
"4"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.abspos-box> at (8,228) content-size 270x50 positioned [BFC] children: not-inline
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <(anonymous)> at (8,278) content-size 784x0 children: inline
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x286]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x270]
PaintableBox (Box<DIV>.grid-container) [8,8 270x270]
PaintableWithLines (BlockContainer<DIV>.grid-item) [58,58 50x50]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.grid-item) [128,58 100x50]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.grid-item) [58,128 50x100]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.grid-item) [128,128 100x100]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.abspos-box) [8,228 270x50]
PaintableWithLines (BlockContainer(anonymous)) [8,278 784x0]

View file

@ -0,0 +1,50 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x286 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x270 children: not-inline
Box <div.grid-container> at (58,58) content-size 170x170 positioned [GFC] children: not-inline
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item> at (58,58) content-size 50x50 [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [58,58 6.34375x17] baseline: 13.296875
"1"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item> at (128,58) content-size 100x50 [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [128,58 8.8125x17] baseline: 13.296875
"2"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item> at (58,128) content-size 50x100 [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [58,128 9.09375x17] baseline: 13.296875
"3"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item> at (128,128) content-size 100x100 [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [128,128 7.75x17] baseline: 13.296875
"4"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.abspos-box> at (8,8) content-size 270x270 positioned [BFC] children: not-inline
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <(anonymous)> at (8,278) content-size 784x0 children: inline
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x286]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x270]
PaintableBox (Box<DIV>.grid-container) [8,8 270x270]
PaintableWithLines (BlockContainer<DIV>.grid-item) [58,58 50x50]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.grid-item) [128,58 100x50]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.grid-item) [58,128 50x100]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.grid-item) [128,128 100x100]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.abspos-box) [8,8 270x270]
PaintableWithLines (BlockContainer(anonymous)) [8,278 784x0]

View file

@ -0,0 +1,50 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x286 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x270 children: not-inline
Box <div.grid-container> at (58,58) content-size 170x170 positioned [GFC] children: not-inline
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item> at (58,58) content-size 50x50 [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [58,58 6.34375x17] baseline: 13.296875
"1"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item> at (128,58) content-size 100x50 [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [128,58 8.8125x17] baseline: 13.296875
"2"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item> at (58,128) content-size 50x100 [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [58,128 9.09375x17] baseline: 13.296875
"3"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.grid-item> at (128,128) content-size 100x100 [BFC] children: inline
frag 0 from TextNode start: 0, length: 1, rect: [128,128 7.75x17] baseline: 13.296875
"4"
TextNode <#text>
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <div.abspos-box> at (228,8) content-size 50x270 positioned [BFC] children: not-inline
BlockContainer <(anonymous)> (not painted) [BFC] children: inline
TextNode <#text>
BlockContainer <(anonymous)> at (8,278) content-size 784x0 children: inline
TextNode <#text>
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x286]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x270]
PaintableBox (Box<DIV>.grid-container) [8,8 270x270]
PaintableWithLines (BlockContainer<DIV>.grid-item) [58,58 50x50]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.grid-item) [128,58 100x50]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.grid-item) [58,128 50x100]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.grid-item) [128,128 100x100]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>.abspos-box) [228,8 50x270]
PaintableWithLines (BlockContainer(anonymous)) [8,278 784x0]

View file

@ -0,0 +1,35 @@
<!DOCTYPE html>
<style>
.grid-container {
display: grid;
grid-template-columns: 50px 100px;
grid-template-rows: 50px 100px;
position: relative;
background-color: #ccc;
padding: 50px;
gap: 20px;
width: fit-content;
}
.grid-item {
background-color: #4caf50;
}
.abspos-box {
position: absolute;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
width: 100%;
height: 100%;
background-color: red;
grid-row: 3;
grid-column: 3;
}
</style>
<div class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="abspos-box"></div>
</div>

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<style>
.grid-container {
display: grid;
grid-template-columns: 50px 100px;
grid-template-rows: 50px 100px;
position: relative;
background-color: #ccc;
padding: 50px;
gap: 20px;
width: fit-content;
}
.grid-item {
background-color: #4caf50;
}
.abspos-box {
position: absolute;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
width: 100%;
height: 100%;
background-color: red;
grid-row: 3;
}
</style>
<div class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="abspos-box"></div>
</div>

View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<style>
.grid-container {
display: grid;
grid-template-columns: 50px 100px;
grid-template-rows: 50px 100px;
position: relative;
background-color: #ccc;
padding: 50px;
gap: 20px;
width: fit-content;
}
.grid-item {
background-color: #4caf50;
}
.abspos-box {
position: absolute;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
width: 100%;
height: 100%;
background-color: red;
}
</style>
<div class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="abspos-box"></div>
</div>

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<style>
.grid-container {
display: grid;
grid-template-columns: 50px 100px;
grid-template-rows: 50px 100px;
position: relative;
background-color: #ccc;
padding: 50px;
gap: 20px;
width: fit-content;
}
.grid-item {
background-color: #4caf50;
}
.abspos-box {
position: absolute;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
width: 100%;
height: 100%;
background-color: red;
grid-column: 3;
}
</style>
<div class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="abspos-box"></div>
</div>

View file

@ -464,7 +464,7 @@ void GridFormattingContext::place_item_with_no_declared_position(Box const& chil
void GridFormattingContext::record_grid_placement(GridItem grid_item)
{
m_occupation_grid.set_occupied(grid_item.column, grid_item.column + grid_item.column_span, grid_item.row, grid_item.row + grid_item.row_span);
m_occupation_grid.set_occupied(grid_item.column.value(), grid_item.column.value() + grid_item.column_span.value(), grid_item.row.value(), grid_item.row.value() + grid_item.row_span.value());
m_grid_items.append(grid_item);
}
@ -1445,8 +1445,8 @@ void GridFormattingContext::place_grid_items()
// NOTE: When final implicit grid sizes are known, we can offset their positions so leftmost grid track has 0 index.
for (auto& item : m_grid_items) {
item.row = item.row - m_occupation_grid.min_row_index();
item.column = item.column - m_occupation_grid.min_column_index();
item.row = item.row.value() - m_occupation_grid.min_row_index();
item.column = item.column.value() - m_occupation_grid.min_column_index();
}
}
@ -1833,73 +1833,121 @@ void GridFormattingContext::collapse_auto_fit_tracks_if_needed(GridDimension con
CSSPixelRect GridFormattingContext::get_grid_area_rect(GridItem const& grid_item) const
{
auto resolved_row_span = grid_item.row_span * 2;
if (grid_item.gap_adjusted_row() + resolved_row_span > m_grid_rows_and_gaps.size())
resolved_row_span = m_grid_rows_and_gaps.size() - grid_item.gap_adjusted_row();
CSSPixelRect area_rect;
auto resolved_column_span = grid_item.column_span * 2;
if (grid_item.gap_adjusted_column() + resolved_column_span > m_grid_columns_and_gaps.size())
resolved_column_span = m_grid_columns_and_gaps.size() - grid_item.gap_adjusted_column();
auto place_into_track = [&](GridDimension const dimension) {
auto const& tracks_and_gaps = dimension == GridDimension::Column ? m_grid_columns_and_gaps : m_grid_rows_and_gaps;
int row_start = grid_item.gap_adjusted_row();
int row_end = row_start + resolved_row_span;
int column_start = grid_item.gap_adjusted_column();
int column_end = column_start + resolved_column_span;
auto resolved_span = grid_item.span(dimension) * 2;
auto gap_adjusted_position = grid_item.gap_adjusted_position(dimension);
if (gap_adjusted_position + resolved_span > tracks_and_gaps.size()) {
resolved_span = tracks_and_gaps.size() - gap_adjusted_position;
}
auto grid_container_width = m_available_space->width.to_px_or_zero();
CSSPixels sum_base_size_of_columns_and_gaps = 0;
CSSPixels sum_base_size_of_columns = 0;
for (auto const& col_track : m_grid_columns_and_gaps) {
if (!col_track.is_gap)
sum_base_size_of_columns += col_track.base_size;
sum_base_size_of_columns_and_gaps += col_track.base_size;
}
auto const& justify_content = grid_container().computed_values().justify_content();
int start = gap_adjusted_position;
int end = start + resolved_span;
VERIFY(start <= end);
CSSPixels x_start = 0;
CSSPixels x_end = 0;
if (justify_content == CSS::JustifyContent::Center || justify_content == CSS::JustifyContent::SpaceAround || justify_content == CSS::JustifyContent::SpaceEvenly) {
auto free_space = grid_container_width - sum_base_size_of_columns_and_gaps;
free_space = max(free_space, 0);
x_start = free_space / 2;
x_end = free_space / 2;
} else if (justify_content == CSS::JustifyContent::End || justify_content == CSS::JustifyContent::Right) {
auto free_space = grid_container_width - sum_base_size_of_columns_and_gaps;
x_start = free_space;
x_end = free_space;
auto grid_container_size = dimension == GridDimension::Column ? m_available_space->width : m_available_space->height;
CSSPixels sum_of_base_sizes_including_gaps = 0;
for (auto const& track : tracks_and_gaps) {
sum_of_base_sizes_including_gaps += track.base_size;
}
Alignment alignment;
if (dimension == GridDimension::Column) {
alignment = to_alignment(grid_container().computed_values().justify_content());
} else {
alignment = to_alignment(grid_container().computed_values().align_content());
}
CSSPixels start_offset = 0;
CSSPixels end_offset = 0;
if (alignment == Alignment::Center || alignment == Alignment::SpaceAround || alignment == Alignment::SpaceEvenly) {
auto free_space = grid_container_size.to_px_or_zero() - sum_of_base_sizes_including_gaps;
free_space = max(free_space, 0);
start_offset = free_space / 2;
end_offset = free_space / 2;
} else if (alignment == Alignment::End) {
auto free_space = grid_container_size.to_px_or_zero() - sum_of_base_sizes_including_gaps;
start_offset = free_space;
end_offset = free_space;
}
for (int i = 0; i < min(start, tracks_and_gaps.size()); i++)
start_offset += tracks_and_gaps[i].base_size;
for (int i = 0; i < min(end, tracks_and_gaps.size()); i++) {
end_offset += tracks_and_gaps[i].base_size;
}
if (dimension == GridDimension::Column) {
area_rect.set_x(start_offset);
area_rect.set_width(end_offset - start_offset);
} else {
area_rect.set_y(start_offset);
area_rect.set_height(end_offset - start_offset);
}
};
auto place_into_track_formed_by_last_line_and_grid_container_padding_edge = [&](GridDimension const dimension) {
VERIFY(grid_item.box->is_absolutely_positioned());
auto const& tracks_and_gaps = dimension == GridDimension::Column ? m_grid_columns_and_gaps : m_grid_rows_and_gaps;
auto const& grid_container_state = m_state.get(grid_container());
CSSPixels offset = 0;
for (auto const& row_track : tracks_and_gaps) {
offset += row_track.base_size;
}
CSSPixels size = dimension == GridDimension::Column ? grid_container_state.padding_right : grid_container_state.padding_bottom;
if (dimension == GridDimension::Column) {
area_rect.set_x(offset);
area_rect.set_width(size);
} else {
area_rect.set_y(offset);
area_rect.set_height(size);
}
};
if (grid_item.row.has_value()) {
if (grid_item.row == (int)m_grid_rows.size()) {
place_into_track_formed_by_last_line_and_grid_container_padding_edge(GridDimension::Row);
} else {
place_into_track(GridDimension::Row);
}
} else {
// https://www.w3.org/TR/css-grid-2/#abspos-items
// Instead of auto-placement, an auto value for a grid-placement property contributes a special line to the placement whose position
// is that of the corresponding padding edge of the grid container (the padding edge of the scrollable area, if the grid container
// overflows). These lines become the first and last lines (0th and -0th) of the augmented grid used for positioning absolutely-positioned items.
CSSPixels height = 0;
for (auto const& row_track : m_grid_rows_and_gaps) {
height += row_track.base_size;
}
auto const& grid_container_state = m_state.get(grid_container());
height += grid_container_state.padding_top;
height += grid_container_state.padding_bottom;
area_rect.set_height(height);
area_rect.set_y(-grid_container_state.padding_top);
}
auto grid_container_height = m_available_space->height.to_px_or_zero();
CSSPixels sum_base_size_of_rows_and_gaps = 0;
for (auto const& row_track : m_grid_rows_and_gaps) {
sum_base_size_of_rows_and_gaps += row_track.base_size;
}
auto const& align_content = grid_container().computed_values().align_content();
CSSPixels y_start = 0;
CSSPixels y_end = 0;
if (align_content == CSS::AlignContent::Center || align_content == CSS::AlignContent::SpaceAround || align_content == CSS::AlignContent::SpaceEvenly) {
auto free_space = grid_container_height - sum_base_size_of_rows_and_gaps;
free_space = max(free_space, 0);
y_start = free_space / 2;
y_end = free_space / 2;
} else if (align_content == CSS::AlignContent::End || align_content == CSS::AlignContent::FlexEnd) {
auto free_space = grid_container_height - sum_base_size_of_rows_and_gaps;
y_start = free_space;
y_end = free_space;
if (grid_item.column.has_value()) {
if (grid_item.column == (int)m_grid_columns.size()) {
place_into_track_formed_by_last_line_and_grid_container_padding_edge(GridDimension::Column);
} else {
place_into_track(GridDimension::Column);
}
} else {
CSSPixels width = 0;
for (auto const& col_track : m_grid_columns_and_gaps) {
width += col_track.base_size;
}
auto const& grid_container_state = m_state.get(grid_container());
width += grid_container_state.padding_left;
width += grid_container_state.padding_right;
area_rect.set_width(width);
area_rect.set_x(-grid_container_state.padding_left);
}
for (int i = 0; i < column_start; i++)
x_start += m_grid_columns_and_gaps[i].base_size;
for (int i = 0; i < column_end; i++)
x_end += m_grid_columns_and_gaps[i].base_size;
for (int i = 0; i < row_start; i++)
y_start += m_grid_rows_and_gaps[i].base_size;
for (int i = 0; i < row_end; i++) {
y_end += m_grid_rows_and_gaps[i].base_size;
}
return { x_start, y_start, x_end - x_start, y_end - y_start };
return area_rect;
}
void GridFormattingContext::run(AvailableSpace const& available_space)
@ -2037,17 +2085,21 @@ void GridFormattingContext::layout_absolutely_positioned_element(Box const& box)
auto& box_state = m_state.get_mutable(box);
auto const& computed_values = box.computed_values();
auto is_auto_positioned = is_auto_positioned_track(computed_values.grid_row_start(), computed_values.grid_row_end()) || is_auto_positioned_track(computed_values.grid_column_start(), computed_values.grid_column_end());
auto is_auto_row = is_auto_positioned_track(computed_values.grid_row_start(), computed_values.grid_row_end());
auto is_auto_column = is_auto_positioned_track(computed_values.grid_column_start(), computed_values.grid_column_end());
auto row_placement_position = resolve_grid_position(box, GridDimension::Row);
auto column_placement_position = resolve_grid_position(box, GridDimension::Column);
GridItem item { box, {}, {}, {}, {} };
if (!is_auto_row) {
auto row_placement_position = resolve_grid_position(box, GridDimension::Row);
item.row = row_placement_position.start;
item.row_span = row_placement_position.span;
}
if (!is_auto_column) {
auto column_placement_position = resolve_grid_position(box, GridDimension::Column);
item.column = column_placement_position.start;
item.column_span = column_placement_position.span;
}
auto row_start = row_placement_position.start;
auto row_span = row_placement_position.span;
auto column_start = column_placement_position.start;
auto column_span = column_placement_position.span;
GridItem item { box, row_start, row_span, column_start, column_span };
auto grid_area_rect = get_grid_area_rect(item);
auto available_width = AvailableSize::make_definite(grid_area_rect.width());
auto available_height = AvailableSize::make_definite(grid_area_rect.height());
@ -2136,12 +2188,6 @@ void GridFormattingContext::layout_absolutely_positioned_element(Box const& box)
used_offset.set_x(grid_area_rect.x() + box_state.inset_left + box_state.margin_box_left());
used_offset.set_y(grid_area_rect.y() + box_state.inset_top + box_state.margin_box_top());
// NOTE: Absolutely positioned boxes with auto-placement are relative to the *padding edge* of the containing block.
if (is_auto_positioned) {
auto const& containing_block_state = m_state.get_mutable(*box.containing_block());
used_offset.translate_by(-containing_block_state.padding_left, -containing_block_state.padding_top);
}
box_state.set_content_offset(used_offset);
if (independent_formatting_context)
@ -2291,12 +2337,12 @@ bool OccupationGrid::is_occupied(int column_index, int row_index) const
int GridItem::gap_adjusted_row() const
{
return row * 2;
return row.value() * 2;
}
int GridItem::gap_adjusted_column() const
{
return column * 2;
return column.value() * 2;
}
CSSPixels GridFormattingContext::calculate_grid_container_maximum_size(GridDimension const dimension) const

View file

@ -37,19 +37,20 @@ struct GridPosition {
struct GridItem {
JS::NonnullGCPtr<Box const> box;
int row;
size_t row_span;
int column;
size_t column_span;
// Position and span are empty if the item is auto-placed which could only be the case for abspos items
Optional<int> row;
Optional<size_t> row_span;
Optional<int> column;
Optional<size_t> column_span;
[[nodiscard]] size_t span(GridDimension const dimension) const
{
return dimension == GridDimension::Column ? column_span : row_span;
return dimension == GridDimension::Column ? column_span.value() : row_span.value();
}
[[nodiscard]] int raw_position(GridDimension const dimension) const
{
return dimension == GridDimension::Column ? column : row;
return dimension == GridDimension::Column ? column.value() : row.value();
}
[[nodiscard]] CSSPixels add_margin_box_sizes(CSSPixels content_size, GridDimension dimension, LayoutState const& state) const
@ -60,6 +61,11 @@ struct GridItem {
return box_state.margin_box_top() + content_size + box_state.margin_box_bottom();
}
[[nodiscard]] int gap_adjusted_position(GridDimension const dimension) const
{
return dimension == GridDimension::Column ? gap_adjusted_column() : gap_adjusted_row();
}
[[nodiscard]] int gap_adjusted_row() const;
[[nodiscard]] int gap_adjusted_column() const;
};