diff --git a/Tests/LibWeb/Layout/expected/grid/distribute-extra-space-across-spanned-tracks.txt b/Tests/LibWeb/Layout/expected/grid/distribute-extra-space-across-spanned-tracks.txt new file mode 100644 index 0000000000..46d9ea6c2b --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/distribute-extra-space-across-spanned-tracks.txt @@ -0,0 +1,27 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x600 [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 <(anonymous)> (not painted) [BFC] children: inline + TextNode <#text> + BlockContainer at (400,8) content-size 392x17.46875 [BFC] children: inline + line 0 width: 9.34375, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 1, rect: [400,8 9.34375x17.46875] + "a" + TextNode <#text> + BlockContainer <(anonymous)> (not painted) [BFC] children: inline + TextNode <#text> + BlockContainer at (8,8) content-size 392x17.46875 [BFC] children: not-inline + BlockContainer <(anonymous)> at (8,8) content-size 392x0 children: inline + TextNode <#text> + BlockContainer at (8,8) content-size 392x17.46875 children: inline + line 0 width: 9.46875, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 1, rect: [8,8 9.46875x17.46875] + "b" + TextNode <#text> + BlockContainer <(anonymous)> at (8,25.46875) content-size 392x0 children: inline + TextNode <#text> + BlockContainer <(anonymous)> (not painted) [BFC] children: inline + TextNode <#text> + BlockContainer <(anonymous)> at (8,25.46875) content-size 784x0 children: inline + TextNode <#text> diff --git a/Tests/LibWeb/Layout/input/grid/distribute-extra-space-across-spanned-tracks.html b/Tests/LibWeb/Layout/input/grid/distribute-extra-space-across-spanned-tracks.html new file mode 100644 index 0000000000..7e0a038b9f --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/distribute-extra-space-across-spanned-tracks.html @@ -0,0 +1,24 @@ + +
+
a
+
+
b
+
+
diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp index 9892f1d55a..339685cdd9 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp @@ -756,9 +756,16 @@ void GridFormattingContext::resolve_intrinsic_track_sizes(AvailableSpace const& } } -void GridFormattingContext::distribute_extra_space_across_spanned_tracks_base_size(CSSPixels item_size_contribution, Vector& spanned_tracks) +template +void GridFormattingContext::distribute_extra_space_across_spanned_tracks_base_size(CSSPixels item_size_contribution, Vector& spanned_tracks, Match matcher) { - for (auto& track : spanned_tracks) + Vector affected_tracks; + for (auto& track : spanned_tracks) { + if (matcher(track)) + affected_tracks.append(track); + } + + for (auto& track : affected_tracks) track.item_incurred_increase = 0; // 1. Find the space to distribute: @@ -774,15 +781,15 @@ void GridFormattingContext::distribute_extra_space_across_spanned_tracks_base_si // FIXME: If a fixed-point type were used to represent CSS pixels, it would be possible to compare with 0 // instead of epsilon. while (extra_space > NumericLimits().epsilon()) { - auto all_frozen = all_of(spanned_tracks, [](auto const& track) { return track.base_size_frozen; }); + auto all_frozen = all_of(affected_tracks, [](auto const& track) { return track.base_size_frozen; }); if (all_frozen) break; // Find the item-incurred increase for each spanned track with an affected size by: distributing the space // equally among such tracks, freezing a track’s item-incurred increase as its affected size + item-incurred // increase reaches its limit - CSSPixels increase_per_track = extra_space / spanned_tracks.size(); - for (auto& track : spanned_tracks) { + CSSPixels increase_per_track = extra_space / affected_tracks.size(); + for (auto& track : affected_tracks) { if (track.base_size_frozen) continue; @@ -801,15 +808,22 @@ void GridFormattingContext::distribute_extra_space_across_spanned_tracks_base_si // 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. - for (auto& track : spanned_tracks) { + for (auto& track : affected_tracks) { if (track.item_incurred_increase > track.planned_increase) track.planned_increase = track.item_incurred_increase; } } -void GridFormattingContext::distribute_extra_space_across_spanned_tracks_growth_limit(CSSPixels item_size_contribution, Vector& spanned_tracks) +template +void GridFormattingContext::distribute_extra_space_across_spanned_tracks_growth_limit(CSSPixels item_size_contribution, Vector& spanned_tracks, Match matcher) { - for (auto& track : spanned_tracks) + Vector affected_tracks; + for (auto& track : spanned_tracks) { + if (matcher(track)) + affected_tracks.append(track); + } + + for (auto& track : affected_tracks) track.item_incurred_increase = 0; // 1. Find the space to distribute: @@ -830,15 +844,15 @@ void GridFormattingContext::distribute_extra_space_across_spanned_tracks_growth_ // FIXME: If a fixed-point type were used to represent CSS pixels, it would be possible to compare with 0 // instead of epsilon. while (extra_space > NumericLimits().epsilon()) { - auto all_frozen = all_of(spanned_tracks, [](auto const& track) { return track.growth_limit_frozen; }); + auto all_frozen = all_of(affected_tracks, [](auto const& track) { return track.growth_limit_frozen; }); if (all_frozen) break; // Find the item-incurred increase for each spanned track with an affected size by: distributing the space // equally among such tracks, freezing a track’s item-incurred increase as its affected size + item-incurred // increase reaches its limit - CSSPixels increase_per_track = extra_space / spanned_tracks.size(); - for (auto& track : spanned_tracks) { + CSSPixels increase_per_track = extra_space / affected_tracks.size(); + for (auto& track : affected_tracks) { if (track.growth_limit_frozen) continue; @@ -888,11 +902,6 @@ 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. - Vector intrinsic_minimum_spanned_tracks; - for (auto& track : spanned_tracks) { - if (track.min_track_sizing_function.is_intrinsic(available_size)) - intrinsic_minimum_spanned_tracks.append(track); - } auto item_size_contribution = [&] { // If the grid container is being sized under a min- or max-content constraint, use the items’ limited // min-content contributions in place of their minimum contributions here. @@ -900,7 +909,9 @@ 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, intrinsic_minimum_spanned_tracks); + distribute_extra_space_across_spanned_tracks_base_size(item_size_contribution, spanned_tracks, [&](TemporaryTrack const& track) { + return track.min_track_sizing_function.is_intrinsic(available_size); + }); for (auto& track : spanned_tracks) { track.base_size += track.planned_increase; track.planned_increase = 0; @@ -909,14 +920,10 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin // 2. For content-based minimums: Next continue to increase the base size of tracks with a min track // sizing function of min-content or max-content by distributing extra space as needed to account for // these items' min-content contributions. - Vector content_based_minimum_tracks; - for (auto& track : spanned_tracks) { - if (track.min_track_sizing_function.is_min_content() || track.min_track_sizing_function.is_max_content()) { - content_based_minimum_tracks.append(track); - } - } auto item_min_content_contribution = calculate_min_content_contribution(item, dimension); - distribute_extra_space_across_spanned_tracks_base_size(item_min_content_contribution, content_based_minimum_tracks); + distribute_extra_space_across_spanned_tracks_base_size(item_min_content_contribution, spanned_tracks, [&](TemporaryTrack const& track) { + return track.min_track_sizing_function.is_min_content() || track.min_track_sizing_function.is_max_content(); + }); for (auto& track : spanned_tracks) { track.base_size += track.planned_increase; track.planned_increase = 0; @@ -926,14 +933,10 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin // continue to increase the base size of tracks with a min track sizing function of auto or max-content by // distributing extra space as needed to account for these items' limited max-content contributions. if (available_size.is_max_content()) { - Vector max_content_minimum_tracks; - for (auto& track : spanned_tracks) { - if (track.min_track_sizing_function.is_auto(available_size) || track.min_track_sizing_function.is_max_content()) { - max_content_minimum_tracks.append(track); - } - } 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, max_content_minimum_tracks); + distribute_extra_space_across_spanned_tracks_base_size(item_limited_max_content_contribution, spanned_tracks, [&](TemporaryTrack 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) { track.base_size += track.planned_increase; track.planned_increase = 0; @@ -948,13 +951,9 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin } // 5. For intrinsic maximums: Next increase the growth limit of tracks with an intrinsic max track sizing - Vector intrinsic_maximum_tracks; - for (auto& track : spanned_tracks) { - if (track.max_track_sizing_function.is_intrinsic(available_size)) { - intrinsic_maximum_tracks.append(track); - } - } - distribute_extra_space_across_spanned_tracks_growth_limit(item_min_content_contribution, intrinsic_maximum_tracks); + distribute_extra_space_across_spanned_tracks_growth_limit(item_min_content_contribution, spanned_tracks, [&](TemporaryTrack const& track) { + return track.max_track_sizing_function.is_intrinsic(available_size); + }); for (auto& track : spanned_tracks) { if (!isfinite(track.growth_limit.value())) { // If the affected size is an infinite growth limit, set it to the track’s base size plus the planned increase. @@ -971,15 +970,10 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin // 6. For max-content maximums: Lastly continue to increase the growth limit of tracks with a max track // sizing function of max-content by distributing extra space as needed to account for these items' max- // content contributions. - Vector max_content_maximum_tracks; - for (auto& track : spanned_tracks) { - if (track.max_track_sizing_function.is_max_content() || track.max_track_sizing_function.is_auto(available_size)) { - max_content_maximum_tracks.append(track); - } - } - auto item_max_content_contribution = calculate_max_content_contribution(item, dimension); - distribute_extra_space_across_spanned_tracks_growth_limit(item_max_content_contribution, max_content_maximum_tracks); + distribute_extra_space_across_spanned_tracks_growth_limit(item_max_content_contribution, spanned_tracks, [&](TemporaryTrack const& track) { + return track.max_track_sizing_function.is_max_content() || track.max_track_sizing_function.is_auto(available_size); + }); for (auto& track : spanned_tracks) { if (!isfinite(track.growth_limit.value())) { // If the affected size is an infinite growth limit, set it to the track’s base size plus the planned increase. @@ -1009,13 +1003,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. - Vector spanned_flexible_tracks; - for (auto& track : spanned_tracks) { - if (track.min_track_sizing_function.is_flexible_length()) - spanned_flexible_tracks.append(track); - } auto item_minimum_contribution = automatic_minimum_size(item, dimension); - distribute_extra_space_across_spanned_tracks_base_size(item_minimum_contribution, spanned_flexible_tracks); + distribute_extra_space_across_spanned_tracks_base_size(item_minimum_contribution, spanned_tracks, [&](TemporaryTrack const& track) { + return track.min_track_sizing_function.is_flexible_length(); + }); for (auto& track : spanned_tracks) { track.base_size += track.planned_increase; diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h index 8a90600e08..6e316c868e 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h @@ -252,10 +252,14 @@ private: void initialize_grid_tracks_for_columns_and_rows(AvailableSpace const&); void initialize_gap_tracks(AvailableSpace const&); + template + void distribute_extra_space_across_spanned_tracks_base_size(CSSPixels item_size_contribution, Vector& spanned_tracks, Match matcher); + + template + void distribute_extra_space_across_spanned_tracks_growth_limit(CSSPixels item_size_contribution, Vector& spanned_tracks, Match matcher); + void initialize_track_sizes(AvailableSpace const&, GridDimension const); void resolve_intrinsic_track_sizes(AvailableSpace const&, GridDimension const); - void distribute_extra_space_across_spanned_tracks_base_size(CSSPixels item_size_contribution, Vector& spanned_tracks); - void distribute_extra_space_across_spanned_tracks_growth_limit(CSSPixels item_size_contribution, Vector& spanned_tracks); 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);