From bd85e1b30b57e89ec058ef61833f7562514b3c9c Mon Sep 17 00:00:00 2001 From: Zaggy1024 Date: Mon, 4 Sep 2023 08:21:15 -0500 Subject: [PATCH] LibWeb: Entirely and exactly distribute grids' extra space to tracks Previously, the code assumed that in dividing up the space in the affected tracks there would never be an overshoot. Instead, we can check for each track how much extra space is left and never consume any extra. In the same way, we can ensure that all extra space is consumed by distributing all remaining extra space starting from the first track. Thus, if there is no growth limit, the space distribution should always consume all the extra space. --- .../Layout/expected/grid/grid-span-4.txt | 18 ++++++------- ...nfinite-spinning-in-space-distribution.txt | 18 ++++++------- .../LibWeb/Layout/GridFormattingContext.cpp | 25 ++++++++++--------- Userland/Libraries/LibWeb/PixelUnits.h | 5 ++++ 4 files changed, 36 insertions(+), 30 deletions(-) diff --git a/Tests/LibWeb/Layout/expected/grid/grid-span-4.txt b/Tests/LibWeb/Layout/expected/grid/grid-span-4.txt index a9a0f16a75..303593fa79 100644 --- a/Tests/LibWeb/Layout/expected/grid/grid-span-4.txt +++ b/Tests/LibWeb/Layout/expected/grid/grid-span-4.txt @@ -1,21 +1,21 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline - BlockContainer at (1,1) content-size 798x65.65625 [BFC] children: not-inline - Box at (10,10) content-size 780x47.65625 [GFC] children: not-inline - BlockContainer at (11,11) content-size 778x21.8125 [BFC] children: inline + BlockContainer at (1,1) content-size 798x65.6875 [BFC] children: not-inline + Box at (10,10) content-size 780x47.6875 [GFC] children: not-inline + BlockContainer at (11,11) content-size 778x21.84375 [BFC] children: inline line 0 width: 33.9375, height: 21.84375, bottom: 21.84375, baseline: 16.921875 frag 0 from TextNode start: 0, length: 3, rect: [11,11 33.9375x21.84375] "foo" TextNode <#text> - BlockContainer at (11,34.8125) content-size 778x21.84375 [BFC] children: inline + BlockContainer at (11,34.84375) content-size 778x21.84375 [BFC] children: inline line 0 width: 34.546875, height: 21.84375, bottom: 21.84375, baseline: 16.921875 - frag 0 from TextNode start: 0, length: 3, rect: [11,34.8125 34.546875x21.84375] + frag 0 from TextNode start: 0, length: 3, rect: [11,34.84375 34.546875x21.84375] "bar" TextNode <#text> ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x67.65625] - PaintableBox (Box) [9,9 782x49.65625] - PaintableWithLines (BlockContainer
.foo) [10,10 780x23.8125] overflow: [11,11 778x21.84375] + PaintableWithLines (BlockContainer) [0,0 800x67.6875] + PaintableBox (Box) [9,9 782x49.6875] + PaintableWithLines (BlockContainer
.foo) [10,10 780x23.84375] TextPaintable (TextNode<#text>) - PaintableWithLines (BlockContainer
.bar) [10,33.8125 780x23.84375] + PaintableWithLines (BlockContainer
.bar) [10,33.84375 780x23.84375] TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/expected/grid/should-not-cause-infinite-spinning-in-space-distribution.txt b/Tests/LibWeb/Layout/expected/grid/should-not-cause-infinite-spinning-in-space-distribution.txt index 0896149a1d..22e430a8ce 100644 --- a/Tests/LibWeb/Layout/expected/grid/should-not-cause-infinite-spinning-in-space-distribution.txt +++ b/Tests/LibWeb/Layout/expected/grid/should-not-cause-infinite-spinning-in-space-distribution.txt @@ -1,21 +1,21 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline - BlockContainer at (1,1) content-size 798x56.90625 [BFC] children: not-inline - Box at (10,10) content-size 780x38.90625 [GFC] children: not-inline - BlockContainer at (11,11) content-size 778x17.4375 [BFC] children: inline + BlockContainer at (1,1) content-size 798x56.9375 [BFC] children: not-inline + Box at (10,10) content-size 780x38.9375 [GFC] children: not-inline + BlockContainer at (11,11) content-size 778x17.46875 [BFC] children: inline line 0 width: 27.15625, height: 17.46875, bottom: 17.46875, baseline: 13.53125 frag 0 from TextNode start: 0, length: 3, rect: [11,11 27.15625x17.46875] "foo" TextNode <#text> - BlockContainer at (11,30.4375) content-size 778x17.46875 [BFC] children: inline + BlockContainer at (11,30.46875) content-size 778x17.46875 [BFC] children: inline line 0 width: 27.640625, height: 17.46875, bottom: 17.46875, baseline: 13.53125 - frag 0 from TextNode start: 0, length: 3, rect: [11,30.4375 27.640625x17.46875] + frag 0 from TextNode start: 0, length: 3, rect: [11,30.46875 27.640625x17.46875] "bar" TextNode <#text> ViewportPaintable (Viewport<#document>) [0,0 800x600] - PaintableWithLines (BlockContainer) [0,0 800x58.90625] - PaintableBox (Box) [9,9 782x40.90625] - PaintableWithLines (BlockContainer
.foo) [10,10 780x19.4375] overflow: [11,11 778x17.46875] + PaintableWithLines (BlockContainer) [0,0 800x58.9375] + PaintableBox (Box) [9,9 782x40.9375] + PaintableWithLines (BlockContainer
.foo) [10,10 780x19.46875] TextPaintable (TextNode<#text>) - PaintableWithLines (BlockContainer
.bar) [10,29.4375 780x19.46875] + PaintableWithLines (BlockContainer
.bar) [10,29.46875 780x19.46875] TextPaintable (TextNode<#text>) diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp index 03393058d9..bfb44994ac 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp @@ -841,7 +841,7 @@ void GridFormattingContext::distribute_extra_space_across_spanned_tracks_base_si auto extra_space = max(CSSPixels(0), item_size_contribution - spanned_tracks_sizes_sum); // 2. Distribute space up to limits: - while (true) { + while (extra_space > 0) { auto all_frozen = all_of(affected_tracks, [](auto const& track) { return track.base_size_frozen; }); if (all_frozen) break; @@ -849,24 +849,22 @@ void GridFormattingContext::distribute_extra_space_across_spanned_tracks_base_si // 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 / affected_tracks.size(); - if (increase_per_track == 0) - break; + CSSPixels increase_per_track = max(extra_space / affected_tracks.size(), CSSPixels::smallest_positive_value()); for (auto& track : affected_tracks) { if (track.base_size_frozen) continue; + auto increase = min(increase_per_track, extra_space); + if (track.growth_limit.has_value()) { auto maximum_increase = track.growth_limit.value() - track.base_size; - if (track.item_incurred_increase + increase_per_track >= maximum_increase) { + if (track.item_incurred_increase + increase >= maximum_increase) { track.base_size_frozen = true; - track.item_incurred_increase = maximum_increase; - extra_space -= maximum_increase - track.item_incurred_increase; - continue; + increase = maximum_increase - track.item_incurred_increase; } } - track.item_incurred_increase += increase_per_track; - extra_space -= increase_per_track; + track.item_incurred_increase += increase; + extra_space -= increase; } } @@ -892,8 +890,11 @@ void GridFormattingContext::distribute_extra_space_across_spanned_tracks_base_si // 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; + for (auto& track : affected_tracks) { + auto increase = min(increase_per_track, extra_space); + track.item_incurred_increase += increase; + extra_space -= increase; + } } // 4. For each affected track, if the track’s item-incurred increase is larger than the track’s planned increase diff --git a/Userland/Libraries/LibWeb/PixelUnits.h b/Userland/Libraries/LibWeb/PixelUnits.h index e102531c2c..cace3f9bf3 100644 --- a/Userland/Libraries/LibWeb/PixelUnits.h +++ b/Userland/Libraries/LibWeb/PixelUnits.h @@ -123,6 +123,11 @@ public: return from_raw(NumericLimits::max()); } + static constexpr CSSPixels smallest_positive_value() + { + return from_raw(1); + } + float to_float() const; double to_double() const; int to_int() const;