mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 16:47:41 +00:00
LibWeb: Implement distributing space to tracks beyond limits in GFC
Implements "Distribute space beyond limits" step from: https://www.w3.org/TR/css-grid-2/#distribute-extra-space
This commit is contained in:
parent
e3ade95d24
commit
20edbb70f8
4 changed files with 63 additions and 9 deletions
9
Tests/LibWeb/Layout/expected/grid/grow-beyond-limits.txt
Normal file
9
Tests/LibWeb/Layout/expected/grid/grow-beyond-limits.txt
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||||
|
BlockContainer <html> at (0,0) content-size 800x33.46875 [BFC] children: not-inline
|
||||||
|
BlockContainer <body> at (8,8) content-size 784x17.46875 children: not-inline
|
||||||
|
Box <div.container> at (8,8) content-size 784x17.46875 [GFC] children: not-inline
|
||||||
|
BlockContainer <div.item> at (8,8) content-size 28.6875x17.46875 [BFC] children: inline
|
||||||
|
line 0 width: 28.6875, height: 17.46875, bottom: 17.46875, baseline: 13.53125
|
||||||
|
frag 0 from TextNode start: 0, length: 3, rect: [8,8 28.6875x17.46875]
|
||||||
|
"one"
|
||||||
|
TextNode <#text>
|
10
Tests/LibWeb/Layout/input/grid/grow-beyond-limits.html
Normal file
10
Tests/LibWeb/Layout/input/grid/grow-beyond-limits.html
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html><style>
|
||||||
|
.container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(min-content, 0px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
background-color: aquamarine;
|
||||||
|
}
|
||||||
|
</style><div class="container"><div class="item">one</div></div>
|
|
@ -783,8 +783,10 @@ void GridFormattingContext::resolve_intrinsic_track_sizes(AvailableSpace const&
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Match>
|
template<typename Match>
|
||||||
void GridFormattingContext::distribute_extra_space_across_spanned_tracks_base_size(CSSPixels item_size_contribution, Vector<GridTrack&>& spanned_tracks, Match matcher)
|
void GridFormattingContext::distribute_extra_space_across_spanned_tracks_base_size(GridDimension dimension, CSSPixels item_size_contribution, SpaceDistributionPhase phase, Vector<GridTrack&>& spanned_tracks, Match matcher)
|
||||||
{
|
{
|
||||||
|
auto& available_size = dimension == GridDimension::Column ? m_available_space->width : m_available_space->height;
|
||||||
|
|
||||||
Vector<GridTrack&> affected_tracks;
|
Vector<GridTrack&> affected_tracks;
|
||||||
for (auto& track : spanned_tracks) {
|
for (auto& track : spanned_tracks) {
|
||||||
if (matcher(track))
|
if (matcher(track))
|
||||||
|
@ -830,7 +832,31 @@ void GridFormattingContext::distribute_extra_space_across_spanned_tracks_base_si
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: 3. Distribute space beyond limits
|
// 3. Distribute space beyond limits
|
||||||
|
if (extra_space > 0) {
|
||||||
|
Vector<GridTrack&> tracks_to_grow_beyond_limits;
|
||||||
|
|
||||||
|
// If space remains after all tracks are frozen, unfreeze and continue to
|
||||||
|
// distribute space to the item-incurred increase of...
|
||||||
|
if (phase == SpaceDistributionPhase::AccommodateMinimumContribution || phase == SpaceDistributionPhase::AccommodateMinContentContribution) {
|
||||||
|
// when accommodating minimum contributions or accommodating min-content contributions: any affected track
|
||||||
|
// that happens to also have an intrinsic max track sizing function
|
||||||
|
for (auto& track : affected_tracks) {
|
||||||
|
if (track.max_track_sizing_function.is_intrinsic(available_size))
|
||||||
|
tracks_to_grow_beyond_limits.append(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there are no such tracks, then all affected tracks.
|
||||||
|
if (tracks_to_grow_beyond_limits.size() == 0)
|
||||||
|
tracks_to_grow_beyond_limits = affected_tracks;
|
||||||
|
}
|
||||||
|
// FIXME: when accommodating max-content contributions: any affected track that happens to also have a
|
||||||
|
// max-content max track sizing function; if there are no such tracks, then all affected tracks.
|
||||||
|
|
||||||
|
CSSPixels increase_per_track = extra_space / affected_tracks.size();
|
||||||
|
for (auto& track : affected_tracks)
|
||||||
|
track.item_incurred_increase += increase_per_track;
|
||||||
|
}
|
||||||
|
|
||||||
// 4. For each affected track, if the track’s item-incurred increase is larger than the track’s planned increase
|
// 4. For each affected track, if the track’s item-incurred increase is larger than the track’s planned increase
|
||||||
// set the track’s planned increase to that value.
|
// set the track’s planned increase to that value.
|
||||||
|
@ -935,7 +961,7 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin
|
||||||
return calculate_limited_min_content_contribution(item, dimension);
|
return calculate_limited_min_content_contribution(item, dimension);
|
||||||
return calculate_minimum_contribution(item, dimension);
|
return calculate_minimum_contribution(item, dimension);
|
||||||
}();
|
}();
|
||||||
distribute_extra_space_across_spanned_tracks_base_size(item_size_contribution, spanned_tracks, [&](GridTrack const& track) {
|
distribute_extra_space_across_spanned_tracks_base_size(dimension, item_size_contribution, SpaceDistributionPhase::AccommodateMinimumContribution, spanned_tracks, [&](GridTrack const& track) {
|
||||||
return track.min_track_sizing_function.is_intrinsic(available_size);
|
return track.min_track_sizing_function.is_intrinsic(available_size);
|
||||||
});
|
});
|
||||||
for (auto& track : spanned_tracks) {
|
for (auto& track : spanned_tracks) {
|
||||||
|
@ -947,7 +973,7 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin
|
||||||
// sizing function of min-content or max-content by distributing extra space as needed to account for
|
// sizing function of min-content or max-content by distributing extra space as needed to account for
|
||||||
// these items' min-content contributions.
|
// these items' min-content contributions.
|
||||||
auto item_min_content_contribution = calculate_min_content_contribution(item, dimension);
|
auto item_min_content_contribution = calculate_min_content_contribution(item, dimension);
|
||||||
distribute_extra_space_across_spanned_tracks_base_size(item_min_content_contribution, spanned_tracks, [&](GridTrack const& track) {
|
distribute_extra_space_across_spanned_tracks_base_size(dimension, item_min_content_contribution, SpaceDistributionPhase::AccommodateMinContentContribution, spanned_tracks, [&](GridTrack const& track) {
|
||||||
return track.min_track_sizing_function.is_min_content() || track.min_track_sizing_function.is_max_content();
|
return track.min_track_sizing_function.is_min_content() || track.min_track_sizing_function.is_max_content();
|
||||||
});
|
});
|
||||||
for (auto& track : spanned_tracks) {
|
for (auto& track : spanned_tracks) {
|
||||||
|
@ -960,7 +986,7 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin
|
||||||
// distributing extra space as needed to account for these items' limited max-content contributions.
|
// distributing extra space as needed to account for these items' limited max-content contributions.
|
||||||
if (available_size.is_max_content()) {
|
if (available_size.is_max_content()) {
|
||||||
auto item_limited_max_content_contribution = calculate_limited_max_content_contribution(item, dimension);
|
auto item_limited_max_content_contribution = calculate_limited_max_content_contribution(item, dimension);
|
||||||
distribute_extra_space_across_spanned_tracks_base_size(item_limited_max_content_contribution, spanned_tracks, [&](GridTrack const& track) {
|
distribute_extra_space_across_spanned_tracks_base_size(dimension, item_limited_max_content_contribution, SpaceDistributionPhase::AccommodateMaxContentContribution, spanned_tracks, [&](GridTrack const& track) {
|
||||||
return track.min_track_sizing_function.is_auto(available_size) || track.min_track_sizing_function.is_max_content();
|
return track.min_track_sizing_function.is_auto(available_size) || track.min_track_sizing_function.is_max_content();
|
||||||
});
|
});
|
||||||
for (auto& track : spanned_tracks) {
|
for (auto& track : spanned_tracks) {
|
||||||
|
@ -1030,9 +1056,10 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin
|
||||||
// 1. For intrinsic minimums: First increase the base size of tracks with an intrinsic min track sizing
|
// 1. For intrinsic minimums: First increase the base size of tracks with an intrinsic min track sizing
|
||||||
// function by distributing extra space as needed to accommodate these items’ minimum contributions.
|
// function by distributing extra space as needed to accommodate these items’ minimum contributions.
|
||||||
auto item_minimum_contribution = automatic_minimum_size(item, dimension);
|
auto item_minimum_contribution = automatic_minimum_size(item, dimension);
|
||||||
distribute_extra_space_across_spanned_tracks_base_size(item_minimum_contribution, spanned_tracks, [&](GridTrack const& track) {
|
distribute_extra_space_across_spanned_tracks_base_size(dimension,
|
||||||
return track.min_track_sizing_function.is_flexible_length();
|
item_minimum_contribution, SpaceDistributionPhase::AccommodateMinimumContribution, spanned_tracks, [&](GridTrack const& track) {
|
||||||
});
|
return track.min_track_sizing_function.is_flexible_length();
|
||||||
|
});
|
||||||
|
|
||||||
for (auto& track : spanned_tracks) {
|
for (auto& track : spanned_tracks) {
|
||||||
track.base_size += track.planned_increase;
|
track.base_size += track.planned_increase;
|
||||||
|
@ -1074,6 +1101,8 @@ void GridFormattingContext::maximize_tracks(AvailableSpace const& available_spac
|
||||||
while (free_space_px > 0) {
|
while (free_space_px > 0) {
|
||||||
auto free_space_to_distribute_per_track = free_space_px / tracks.size();
|
auto free_space_to_distribute_per_track = free_space_px / tracks.size();
|
||||||
for (auto& track : tracks) {
|
for (auto& track : tracks) {
|
||||||
|
if (track.base_size_frozen)
|
||||||
|
continue;
|
||||||
VERIFY(isfinite(track.growth_limit.to_double()));
|
VERIFY(isfinite(track.growth_limit.to_double()));
|
||||||
track.base_size = min(track.growth_limit, track.base_size + free_space_to_distribute_per_track);
|
track.base_size = min(track.growth_limit, track.base_size + free_space_to_distribute_per_track);
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,8 +242,14 @@ private:
|
||||||
|
|
||||||
void collapse_auto_fit_tracks_if_needed(GridDimension const);
|
void collapse_auto_fit_tracks_if_needed(GridDimension const);
|
||||||
|
|
||||||
|
enum class SpaceDistributionPhase {
|
||||||
|
AccommodateMinimumContribution,
|
||||||
|
AccommodateMinContentContribution,
|
||||||
|
AccommodateMaxContentContribution
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Match>
|
template<typename Match>
|
||||||
void distribute_extra_space_across_spanned_tracks_base_size(CSSPixels item_size_contribution, Vector<GridTrack&>& spanned_tracks, Match matcher);
|
void distribute_extra_space_across_spanned_tracks_base_size(GridDimension dimension, CSSPixels item_size_contribution, SpaceDistributionPhase phase, Vector<GridTrack&>& spanned_tracks, Match matcher);
|
||||||
|
|
||||||
template<typename Match>
|
template<typename Match>
|
||||||
void distribute_extra_space_across_spanned_tracks_growth_limit(CSSPixels item_size_contribution, Vector<GridTrack&>& spanned_tracks, Match matcher);
|
void distribute_extra_space_across_spanned_tracks_growth_limit(CSSPixels item_size_contribution, Vector<GridTrack&>& spanned_tracks, Match matcher);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue