LibWeb: Redo "tracks maximize" if initial run is over max-size in GFC

Implements missing "redo" step defined in the spec.
This commit is contained in:
Aliaksandr Kalenik 2023-12-26 18:13:17 +01:00 committed by Andreas Kling
parent 467faee1b8
commit cd56ec6e5c
4 changed files with 117 additions and 6 deletions

View file

@ -0,0 +1,35 @@
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
BlockContainer <html> at (0,0) content-size 800x121.15625 [BFC] children: not-inline
BlockContainer <body> at (8,8) content-size 784x105.15625 children: not-inline
BlockContainer <div.wrapper> at (8,8) content-size 270x105.15625 children: not-inline
Box <div.constrained> at (8,8) content-size 270x105.15625 [GFC] children: not-inline
BlockContainer <(anonymous)> at (8,8) content-size 270x105.15625 [BFC] children: inline
line 0 width: 261.0625, height: 17.46875, bottom: 17.46875, baseline: 13.53125
frag 0 from TextNode start: 1, length: 35, rect: [8,8 261.0625x17.46875]
"hello hello hello hello hello hello"
line 1 width: 261.0625, height: 17.9375, bottom: 35.40625, baseline: 13.53125
frag 0 from TextNode start: 37, length: 35, rect: [8,25 261.0625x17.46875]
"hello hello hello hello hello hello"
line 2 width: 261.0625, height: 18.40625, bottom: 53.34375, baseline: 13.53125
frag 0 from TextNode start: 73, length: 35, rect: [8,42 261.0625x17.46875]
"hello hello hello hello hello hello"
line 3 width: 261.0625, height: 17.875, bottom: 70.28125, baseline: 13.53125
frag 0 from TextNode start: 109, length: 35, rect: [8,60 261.0625x17.46875]
"hello hello hello hello hello hello"
line 4 width: 261.0625, height: 18.34375, bottom: 88.21875, baseline: 13.53125
frag 0 from TextNode start: 145, length: 35, rect: [8,77 261.0625x17.46875]
"hello hello hello hello hello hello"
line 5 width: 81.6875, height: 17.8125, bottom: 105.15625, baseline: 13.53125
frag 0 from TextNode start: 181, length: 11, rect: [8,95 81.6875x17.46875]
"hello hello"
TextNode <#text>
BlockContainer <div> at (8,113.15625) content-size 270x0 [BFC] children: not-inline
ViewportPaintable (Viewport<#document>) [0,0 800x600]
PaintableWithLines (BlockContainer<HTML>) [0,0 800x121.15625]
PaintableWithLines (BlockContainer<BODY>) [8,8 784x105.15625]
PaintableWithLines (BlockContainer<DIV>.wrapper) [8,8 270x105.15625]
PaintableBox (Box<DIV>.constrained) [8,8 270x105.15625]
PaintableWithLines (BlockContainer(anonymous)) [8,8 270x105.15625]
TextPaintable (TextNode<#text>)
PaintableWithLines (BlockContainer<DIV>) [8,113.15625 270x0]

View file

@ -0,0 +1,14 @@
<!doctype html><style>
* { outline: 1px solid black; }
.constrained {
max-width: 270px;
display: grid;
}
.wrapper {
background: yellow;
width: max-content;
}
</style><body><div class="wrapper"><div class="constrained">
hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello
hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello
<div></div></div></div>

View file

@ -1121,7 +1121,7 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin
}
}
void GridFormattingContext::maximize_tracks(AvailableSpace const& available_space, GridDimension const dimension)
void GridFormattingContext::maximize_tracks_using_available_size(AvailableSpace const& available_space, GridDimension const dimension)
{
// https://www.w3.org/TR/css-grid-2/#algo-grow-tracks
// 12.6. Maximize Tracks
@ -1157,10 +1157,45 @@ void GridFormattingContext::maximize_tracks(AvailableSpace const& available_spac
break;
free_space_px = get_free_space_px();
}
}
// FIXME: If this would cause the grid to be larger than the grid containers inner size as limited by its
void GridFormattingContext::maximize_tracks(GridDimension const dimension)
{
// https://www.w3.org/TR/css-grid-2/#algo-grow-tracks
// 12.6. Maximize Tracks
auto& tracks = dimension == GridDimension::Column ? m_grid_columns : m_grid_rows;
Vector<CSSPixels> saved_base_sizes;
for (auto& track : tracks)
saved_base_sizes.append(track.base_size);
maximize_tracks_using_available_size(*m_available_space, dimension);
// If this would cause the grid to be larger than the grid containers inner size as limited by its
// max-width/height, then redo this step, treating the available grid space as equal to the grid
// containers inner size when its sized to its max-width/height.
CSSPixels grid_container_inner_size = 0;
for (auto& track : tracks)
grid_container_inner_size += track.base_size;
auto const& available_size = dimension == GridDimension::Column ? m_available_space->width : m_available_space->height;
auto const& computed_values = grid_container().computed_values();
auto should_treat_grid_container_maximum_size_as_none = [&] {
if (dimension == GridDimension::Column)
return should_treat_max_width_as_none(grid_container(), available_size);
return !computed_values.max_height().is_auto();
}();
auto maximum_size = calculate_grid_container_maximum_size(dimension);
if (!should_treat_grid_container_maximum_size_as_none && grid_container_inner_size > maximum_size) {
for (size_t i = 0; i < tracks.size(); i++)
tracks[i].base_size = saved_base_sizes[i];
auto available_space_with_max_width = *m_available_space;
if (dimension == GridDimension::Column)
available_space_with_max_width.width = AvailableSize::make_definite(maximum_size);
else
available_space_with_max_width.height = AvailableSize::make_definite(maximum_size);
maximize_tracks_using_available_size(available_space_with_max_width, dimension);
}
}
void GridFormattingContext::expand_flexible_tracks(AvailableSpace const& available_space, GridDimension const dimension)
@ -1307,7 +1342,7 @@ void GridFormattingContext::run_track_sizing(AvailableSpace const& available_spa
resolve_intrinsic_track_sizes(available_space, dimension);
// 3. Maximize Tracks
maximize_tracks(available_space, dimension);
maximize_tracks(dimension);
// 4. Expand Flexible Tracks
expand_flexible_tracks(available_space, dimension);
@ -2243,6 +2278,14 @@ int GridItem::gap_adjusted_column(Box const& grid_box) const
return grid_box.computed_values().column_gap().is_auto() ? column : column * 2;
}
CSSPixels GridFormattingContext::calculate_grid_container_maximum_size(GridDimension const dimension) const
{
auto const& computed_values = grid_container().computed_values();
if (dimension == GridDimension::Column)
return calculate_inner_width(grid_container(), m_available_space->width, computed_values.max_width()).to_px(grid_container());
return calculate_inner_height(grid_container(), m_available_space->height, computed_values.max_height()).to_px(grid_container());
}
CSS::Size const& GridFormattingContext::get_item_preferred_size(GridItem const& item, GridDimension const dimension) const
{
if (dimension == GridDimension::Column)
@ -2357,11 +2400,19 @@ CSSPixels GridFormattingContext::calculate_limited_min_content_contribution(Grid
// The limited min-content contribution of an item is its min-content contribution,
// limited by the max track sizing function (which could be the argument to a fit-content() track
// sizing function) if that is fixed and ultimately floored by its minimum contribution.
// FIXME: limit by max track sizing function
auto min_content_contribution = calculate_min_content_contribution(item, dimension);
auto minimum_contribution = calculate_minimum_contribution(item, dimension);
if (min_content_contribution < minimum_contribution)
return minimum_contribution;
// FIXME: limit by max track sizing function instead of grid container maximum size
auto const& available_size = dimension == GridDimension::Column ? m_available_space->width : m_available_space->height;
if (!should_treat_max_width_as_none(grid_container(), available_size)) {
auto max_width = calculate_grid_container_maximum_size(dimension);
if (min_content_contribution > max_width)
return max_width;
}
return min_content_contribution;
}
@ -2370,11 +2421,19 @@ CSSPixels GridFormattingContext::calculate_limited_max_content_contribution(Grid
// The limited max-content contribution of an item is its max-content contribution,
// limited by the max track sizing function (which could be the argument to a fit-content() track
// sizing function) if that is fixed and ultimately floored by its minimum contribution.
// FIXME: limit by max track sizing function
auto max_content_contribution = calculate_max_content_contribution(item, dimension);
auto minimum_contribution = calculate_minimum_contribution(item, dimension);
if (max_content_contribution < minimum_contribution)
return minimum_contribution;
// FIXME: limit by max track sizing function instead of grid container maximum size
auto const& available_size = dimension == GridDimension::Column ? m_available_space->width : m_available_space->height;
if (!should_treat_max_width_as_none(grid_container(), available_size)) {
auto max_width = calculate_grid_container_maximum_size(dimension);
if (max_content_contribution > max_width)
return max_width;
}
return max_content_contribution;
}

View file

@ -269,11 +269,14 @@ private:
void resolve_intrinsic_track_sizes(AvailableSpace const&, GridDimension const);
void increase_sizes_to_accommodate_spanning_items_crossing_content_sized_tracks(AvailableSpace const&, GridDimension const, size_t span);
void increase_sizes_to_accommodate_spanning_items_crossing_flexible_tracks(GridDimension const);
void maximize_tracks(AvailableSpace const&, GridDimension const);
void maximize_tracks_using_available_size(AvailableSpace const& available_space, GridDimension const dimension);
void maximize_tracks(GridDimension const);
void expand_flexible_tracks(AvailableSpace const&, GridDimension const);
void stretch_auto_tracks(AvailableSpace const&, GridDimension const);
void run_track_sizing(AvailableSpace const&, GridDimension const);
CSSPixels calculate_grid_container_maximum_size(GridDimension const) const;
CSS::Size const& get_item_preferred_size(GridItem const&, GridDimension const) const;
CSSPixels calculate_min_content_size(GridItem const&, GridDimension const) const;