diff --git a/Tests/LibWeb/Layout/expected/grid/grow-beyond-limits.txt b/Tests/LibWeb/Layout/expected/grid/grow-beyond-limits.txt new file mode 100644 index 0000000000..ae87836289 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/grow-beyond-limits.txt @@ -0,0 +1,9 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x33.46875 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x17.46875 children: not-inline + Box at (8,8) content-size 784x17.46875 [GFC] children: not-inline + BlockContainer 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> diff --git a/Tests/LibWeb/Layout/input/grid/grow-beyond-limits.html b/Tests/LibWeb/Layout/input/grid/grow-beyond-limits.html new file mode 100644 index 0000000000..2ed83b38cb --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/grow-beyond-limits.html @@ -0,0 +1,10 @@ +
one
\ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp index 7caa945912..c8c2ba7696 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp @@ -783,8 +783,10 @@ void GridFormattingContext::resolve_intrinsic_track_sizes(AvailableSpace const& } template -void GridFormattingContext::distribute_extra_space_across_spanned_tracks_base_size(CSSPixels item_size_contribution, Vector& spanned_tracks, Match matcher) +void GridFormattingContext::distribute_extra_space_across_spanned_tracks_base_size(GridDimension dimension, CSSPixels item_size_contribution, SpaceDistributionPhase phase, Vector& spanned_tracks, Match matcher) { + auto& available_size = dimension == GridDimension::Column ? m_available_space->width : m_available_space->height; + Vector affected_tracks; for (auto& track : spanned_tracks) { 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 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 // 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_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); }); 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 // these items' min-content contributions. 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(); }); 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. if (available_size.is_max_content()) { 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(); }); 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 // function by distributing extra space as needed to accommodate these items’ minimum contributions. 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) { - return track.min_track_sizing_function.is_flexible_length(); - }); + distribute_extra_space_across_spanned_tracks_base_size(dimension, + item_minimum_contribution, SpaceDistributionPhase::AccommodateMinimumContribution, spanned_tracks, [&](GridTrack const& track) { + return track.min_track_sizing_function.is_flexible_length(); + }); for (auto& track : spanned_tracks) { track.base_size += track.planned_increase; @@ -1074,6 +1101,8 @@ void GridFormattingContext::maximize_tracks(AvailableSpace const& available_spac while (free_space_px > 0) { auto free_space_to_distribute_per_track = free_space_px / tracks.size(); for (auto& track : tracks) { + if (track.base_size_frozen) + continue; VERIFY(isfinite(track.growth_limit.to_double())); track.base_size = min(track.growth_limit, track.base_size + free_space_to_distribute_per_track); } diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h index c767a16c40..cd60c5203c 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h @@ -242,8 +242,14 @@ private: void collapse_auto_fit_tracks_if_needed(GridDimension const); + enum class SpaceDistributionPhase { + AccommodateMinimumContribution, + AccommodateMinContentContribution, + AccommodateMaxContentContribution + }; + template - void distribute_extra_space_across_spanned_tracks_base_size(CSSPixels item_size_contribution, Vector& spanned_tracks, Match matcher); + void distribute_extra_space_across_spanned_tracks_base_size(GridDimension dimension, CSSPixels item_size_contribution, SpaceDistributionPhase phase, Vector& spanned_tracks, Match matcher); template void distribute_extra_space_across_spanned_tracks_growth_limit(CSSPixels item_size_contribution, Vector& spanned_tracks, Match matcher);