From 7591a420f61cc738b374b34dba738fc30994346b Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Sat, 20 May 2023 17:46:21 +0300 Subject: [PATCH 1/2] LibWeb: Implement more of spanning tracks sizing in GFC Implements more parts of sizing algorithm for tracks with spanning items to archive parity with implementation for sizing of tracks with non-spanning items. --- .../expected/grid/row-span-2-maxcontent.txt | 105 ++++++++++ .../expected/grid/row-span-2-mincontent.txt | 186 ++++++++++++++++++ .../input/grid/row-span-2-maxcontent.html | 53 +++++ .../input/grid/row-span-2-mincontent.html | 43 ++++ .../LibWeb/Layout/GridFormattingContext.cpp | 172 ++++++++++++++-- .../LibWeb/Layout/GridFormattingContext.h | 14 +- 6 files changed, 553 insertions(+), 20 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/grid/row-span-2-maxcontent.txt create mode 100644 Tests/LibWeb/Layout/expected/grid/row-span-2-mincontent.txt create mode 100644 Tests/LibWeb/Layout/input/grid/row-span-2-maxcontent.html create mode 100644 Tests/LibWeb/Layout/input/grid/row-span-2-mincontent.html diff --git a/Tests/LibWeb/Layout/expected/grid/row-span-2-maxcontent.txt b/Tests/LibWeb/Layout/expected/grid/row-span-2-maxcontent.txt new file mode 100644 index 00000000000000..c8fcf92aee1277 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/row-span-2-maxcontent.txt @@ -0,0 +1,105 @@ +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 784x315.40625 children: not-inline + Box at (8,8) content-size 784x315.40625 [GFC] children: not-inline + BlockContainer <(anonymous)> at (8,8) content-size 0x0 [BFC] children: inline + TextNode <#text> + BlockContainer at (401.46875,8) content-size 392x131.296875 [BFC] children: inline + line 0 width: 319.171875, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 1, length: 40, rect: [401.46875,8 319.171875x17.46875] + "In a sollicitudin augue. Sed ante augue," + line 1 width: 335.125, height: 17.9375, bottom: 35.40625, baseline: 13.53125 + frag 0 from TextNode start: 42, length: 42, rect: [401.46875,25 335.125x17.46875] + "rhoncus nec porttitor id, lacinia et nibh." + line 2 width: 378.625, height: 18.40625, bottom: 53.34375, baseline: 13.53125 + frag 0 from TextNode start: 85, length: 48, rect: [401.46875,42 378.625x17.46875] + "Pellentesque diam libero, ultrices eget eleifend" + line 3 width: 182.8125, height: 17.875, bottom: 70.28125, baseline: 13.53125 + frag 0 from TextNode start: 134, length: 22, rect: [401.46875,60 182.8125x17.46875] + "at, consequat ut orci." + TextNode <#text> + BlockContainer <(anonymous)> at (8,8) content-size 0x0 [BFC] children: inline + TextNode <#text> + BlockContainer at (401.46875,139.296875) content-size 392x184.109375 [BFC] children: inline + line 0 width: 359.15625, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 1, length: 43, rect: [401.46875,139.296875 359.15625x17.46875] + "Suspendisse potenti. Pellentesque at varius" + line 1 width: 318.5625, height: 17.9375, bottom: 35.40625, baseline: 13.53125 + frag 0 from TextNode start: 45, length: 41, rect: [401.46875,156.296875 318.5625x17.46875] + "lacus, sed sollicitudin leo. Pellentesque" + line 2 width: 377.640625, height: 18.40625, bottom: 53.34375, baseline: 13.53125 + frag 0 from TextNode start: 87, length: 44, rect: [401.46875,173.296875 377.640625x17.46875] + "malesuada mi eget pellentesque tempor. Donec" + line 3 width: 378.03125, height: 17.875, bottom: 70.28125, baseline: 13.53125 + frag 0 from TextNode start: 132, length: 47, rect: [401.46875,191.296875 378.03125x17.46875] + "egestas mauris est, ut lobortis nisi luctus at." + line 4 width: 345.953125, height: 18.34375, bottom: 88.21875, baseline: 13.53125 + frag 0 from TextNode start: 180, length: 41, rect: [401.46875,208.296875 345.953125x17.46875] + "Vivamus eleifend, lorem vulputate maximus" + line 5 width: 312.765625, height: 17.8125, bottom: 105.15625, baseline: 13.53125 + frag 0 from TextNode start: 222, length: 37, rect: [401.46875,226.296875 312.765625x17.46875] + "porta, nunc metus porttitor nibh, nec" + line 6 width: 242.921875, height: 18.28125, bottom: 123.09375, baseline: 13.53125 + frag 0 from TextNode start: 260, length: 31, rect: [401.46875,243.296875 242.921875x17.46875] + "bibendum nulla lectus ut felis." + TextNode <#text> + BlockContainer <(anonymous)> at (8,8) content-size 0x0 [BFC] children: inline + TextNode <#text> + BlockContainer at (8,8) content-size 393.46875x315.40625 [BFC] children: inline + line 0 width: 337.6875, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 1, length: 39, rect: [8,8 337.6875x17.46875] + "Lorem ipsum dolor sit amet, consectetur" + line 1 width: 376.34375, height: 17.9375, bottom: 35.40625, baseline: 13.53125 + frag 0 from TextNode start: 41, length: 47, rect: [8,25 376.34375x17.46875] + "adipiscing elit. Sed vitae condimentum erat, ac" + line 2 width: 365.84375, height: 18.40625, bottom: 53.34375, baseline: 13.53125 + frag 0 from TextNode start: 89, length: 45, rect: [8,42 365.84375x17.46875] + "posuere arcu. Aenean tincidunt mi ligula, vel" + line 3 width: 381.96875, height: 17.875, bottom: 70.28125, baseline: 13.53125 + frag 0 from TextNode start: 135, length: 46, rect: [8,60 381.96875x17.46875] + "semper dolor aliquet at. Phasellus scelerisque" + line 4 width: 377.203125, height: 18.34375, bottom: 88.21875, baseline: 13.53125 + frag 0 from TextNode start: 182, length: 45, rect: [8,77 377.203125x17.46875] + "dapibus diam sed rhoncus. Proin sed orci leo." + line 5 width: 375.390625, height: 17.8125, bottom: 105.15625, baseline: 13.53125 + frag 0 from TextNode start: 228, length: 45, rect: [8,95 375.390625x17.46875] + "Praesent pellentesque mi eu nunc gravida, vel" + line 6 width: 383.53125, height: 18.28125, bottom: 123.09375, baseline: 13.53125 + frag 0 from TextNode start: 274, length: 46, rect: [8,112 383.53125x17.46875] + "consectetur nulla malesuada. Sed pellentesque," + line 7 width: 344.8125, height: 17.75, bottom: 140.03125, baseline: 13.53125 + frag 0 from TextNode start: 321, length: 47, rect: [8,130 344.8125x17.46875] + "elit sit amet sollicitudin sollicitudin, lectus" + line 8 width: 374.703125, height: 18.21875, bottom: 157.96875, baseline: 13.53125 + frag 0 from TextNode start: 369, length: 46, rect: [8,147 374.703125x17.46875] + "justo facilisis lacus, ac vehicula metus neque" + line 9 width: 384.125, height: 17.6875, bottom: 174.90625, baseline: 13.53125 + frag 0 from TextNode start: 416, length: 45, rect: [8,165 384.125x17.46875] + "ac mi. In in augue et massa maximus venenatis" + line 10 width: 373.25, height: 18.15625, bottom: 192.84375, baseline: 13.53125 + frag 0 from TextNode start: 462, length: 44, rect: [8,182 373.25x17.46875] + "auctor fermentum dui. Aliquam dictum finibus" + line 11 width: 288.203125, height: 17.625, bottom: 209.78125, baseline: 13.53125 + frag 0 from TextNode start: 507, length: 35, rect: [8,200 288.203125x17.46875] + "urna, quis lacinia massa laoreet a." + line 12 width: 316.296875, height: 18.09375, bottom: 227.71875, baseline: 13.53125 + frag 0 from TextNode start: 543, length: 36, rect: [8,217 316.296875x17.46875] + "Suspendisse elementum non lectus nec" + line 13 width: 388.78125, height: 17.5625, bottom: 244.65625, baseline: 13.53125 + frag 0 from TextNode start: 580, length: 48, rect: [8,235 388.78125x17.46875] + "elementum. Quisque ultricies suscipit porttitor." + line 14 width: 373.828125, height: 18.03125, bottom: 262.59375, baseline: 13.53125 + frag 0 from TextNode start: 629, length: 45, rect: [8,252 373.828125x17.46875] + "Sed non urna rutrum, mattis nulla at, feugiat" + line 15 width: 368.75, height: 17.5, bottom: 279.53125, baseline: 13.53125 + frag 0 from TextNode start: 675, length: 48, rect: [8,270 368.75x17.46875] + "erat. Duis orci elit, vehicula sed blandit eget," + line 16 width: 390.625, height: 17.96875, bottom: 297.46875, baseline: 13.53125 + frag 0 from TextNode start: 724, length: 46, rect: [8,287 390.625x17.46875] + "auctor in arcu. Ut cursus magna sit amet nulla" + line 17 width: 294.90625, height: 18.4375, bottom: 315.40625, baseline: 13.53125 + frag 0 from TextNode start: 771, length: 36, rect: [8,304 294.90625x17.46875] + "cursus, vitae gravida mauris dictum." + TextNode <#text> + BlockContainer <(anonymous)> at (8,8) content-size 0x0 [BFC] children: inline + TextNode <#text> diff --git a/Tests/LibWeb/Layout/expected/grid/row-span-2-mincontent.txt b/Tests/LibWeb/Layout/expected/grid/row-span-2-mincontent.txt new file mode 100644 index 00000000000000..40e0c2cac953ba --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/row-span-2-mincontent.txt @@ -0,0 +1,186 @@ +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 784x560.0625 children: not-inline + Box at (8,8) content-size 784x560.0625 [GFC] children: not-inline + BlockContainer <(anonymous)> at (8,8) content-size 0x0 [BFC] children: inline + TextNode <#text> + BlockContainer at (108.640625,8) content-size 101.515625x244.65625 [BFC] children: inline + line 0 width: 31.546875, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 1, length: 4, rect: [108.640625,8 31.546875x17.46875] + "In a" + line 1 width: 84.84375, height: 17.9375, bottom: 35.40625, baseline: 13.53125 + frag 0 from TextNode start: 6, length: 12, rect: [108.640625,25 84.84375x17.46875] + "sollicitudin" + line 2 width: 86.046875, height: 18.40625, bottom: 53.34375, baseline: 13.53125 + frag 0 from TextNode start: 19, length: 10, rect: [108.640625,42 86.046875x17.46875] + "augue. Sed" + line 3 width: 92.734375, height: 17.875, bottom: 70.28125, baseline: 13.53125 + frag 0 from TextNode start: 30, length: 11, rect: [108.640625,60 92.734375x17.46875] + "ante augue," + line 4 width: 101.3125, height: 18.34375, bottom: 88.21875, baseline: 13.53125 + frag 0 from TextNode start: 42, length: 11, rect: [108.640625,77 101.3125x17.46875] + "rhoncus nec" + line 5 width: 98.40625, height: 17.8125, bottom: 105.15625, baseline: 13.53125 + frag 0 from TextNode start: 54, length: 13, rect: [108.640625,95 98.40625x17.46875] + "porttitor id," + line 6 width: 74.125, height: 18.28125, bottom: 123.09375, baseline: 13.53125 + frag 0 from TextNode start: 68, length: 10, rect: [108.640625,112 74.125x17.46875] + "lacinia et" + line 7 width: 37.28125, height: 17.75, bottom: 140.03125, baseline: 13.53125 + frag 0 from TextNode start: 79, length: 5, rect: [108.640625,130 37.28125x17.46875] + "nibh." + line 8 width: 101.515625, height: 18.21875, bottom: 157.96875, baseline: 13.53125 + frag 0 from TextNode start: 85, length: 12, rect: [108.640625,147 101.515625x17.46875] + "Pellentesque" + line 9 width: 93.1875, height: 17.6875, bottom: 174.90625, baseline: 13.53125 + frag 0 from TextNode start: 98, length: 12, rect: [108.640625,165 93.1875x17.46875] + "diam libero," + line 10 width: 101.0625, height: 18.15625, bottom: 192.84375, baseline: 13.53125 + frag 0 from TextNode start: 111, length: 13, rect: [108.640625,182 101.0625x17.46875] + "ultrices eget" + line 11 width: 88.109375, height: 17.625, bottom: 209.78125, baseline: 13.53125 + frag 0 from TextNode start: 125, length: 12, rect: [108.640625,200 88.109375x17.46875] + "eleifend at," + line 12 width: 83.953125, height: 18.09375, bottom: 227.71875, baseline: 13.53125 + frag 0 from TextNode start: 138, length: 9, rect: [108.640625,217 83.953125x17.46875] + "consequat" + line 13 width: 61.609375, height: 17.5625, bottom: 244.65625, baseline: 13.53125 + frag 0 from TextNode start: 148, length: 8, rect: [108.640625,235 61.609375x17.46875] + "ut orci." + TextNode <#text> + BlockContainer <(anonymous)> at (8,8) content-size 0x0 [BFC] children: inline + TextNode <#text> + BlockContainer at (108.640625,252.65625) content-size 101.515625x315.40625 [BFC] children: inline + line 0 width: 98.65625, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 1, length: 11, rect: [108.640625,252.65625 98.65625x17.46875] + "Suspendisse" + line 1 width: 60.734375, height: 17.9375, bottom: 35.40625, baseline: 13.53125 + frag 0 from TextNode start: 13, length: 8, rect: [108.640625,269.65625 60.734375x17.46875] + "potenti." + line 2 width: 101.515625, height: 18.40625, bottom: 53.34375, baseline: 13.53125 + frag 0 from TextNode start: 22, length: 12, rect: [108.640625,286.65625 101.515625x17.46875] + "Pellentesque" + line 3 width: 74.25, height: 17.875, bottom: 70.28125, baseline: 13.53125 + frag 0 from TextNode start: 35, length: 9, rect: [108.640625,304.65625 74.25x17.46875] + "at varius" + line 4 width: 80.546875, height: 18.34375, bottom: 88.21875, baseline: 13.53125 + frag 0 from TextNode start: 45, length: 10, rect: [108.640625,321.65625 80.546875x17.46875] + "lacus, sed" + line 5 width: 84.84375, height: 17.8125, bottom: 105.15625, baseline: 13.53125 + frag 0 from TextNode start: 56, length: 12, rect: [108.640625,339.65625 84.84375x17.46875] + "sollicitudin" + line 6 width: 27.65625, height: 18.28125, bottom: 123.09375, baseline: 13.53125 + frag 0 from TextNode start: 69, length: 4, rect: [108.640625,356.65625 27.65625x17.46875] + "leo." + line 7 width: 101.515625, height: 17.75, bottom: 140.03125, baseline: 13.53125 + frag 0 from TextNode start: 74, length: 12, rect: [108.640625,374.65625 101.515625x17.46875] + "Pellentesque" + line 8 width: 80.15625, height: 18.21875, bottom: 157.96875, baseline: 13.53125 + frag 0 from TextNode start: 87, length: 9, rect: [108.640625,391.65625 80.15625x17.46875] + "malesuada" + line 9 width: 56.625, height: 17.6875, bottom: 174.90625, baseline: 13.53125 + frag 0 from TextNode start: 97, length: 7, rect: [108.640625,409.65625 56.625x17.46875] + "mi eget" + line 10 width: 99.40625, height: 18.15625, bottom: 192.84375, baseline: 13.53125 + frag 0 from TextNode start: 105, length: 12, rect: [108.640625,426.65625 99.40625x17.46875] + "pellentesque" + line 11 width: 60.734375, height: 17.625, bottom: 209.78125, baseline: 13.53125 + frag 0 from TextNode start: 118, length: 7, rect: [108.640625,444.65625 60.734375x17.46875] + "tempor." + line 12 width: 48.71875, height: 18.09375, bottom: 227.71875, baseline: 13.53125 + frag 0 from TextNode start: 126, length: 5, rect: [108.640625,461.65625 48.71875x17.46875] + "Donec" + line 13 width: 59.890625, height: 17.5625, bottom: 244.65625, baseline: 13.53125 + frag 0 from TextNode start: 132, length: 7, rect: [108.640625,479.65625 59.890625x17.46875] + "egestas" + line 14 width: 92.015625, height: 18.03125, bottom: 262.59375, baseline: 13.53125 + frag 0 from TextNode start: 140, length: 11, rect: [108.640625,496.65625 92.015625x17.46875] + "mauris est," + line 15 width: 88.640625, height: 17.5, bottom: 279.53125, baseline: 13.53125 + frag 0 from TextNode start: 152, length: 11, rect: [108.640625,514.65625 88.640625x17.46875] + "ut lobortis" + line 16 width: 84.9375, height: 17.96875, bottom: 297.46875, baseline: 13.53125 + frag 0 from TextNode start: 164, length: 11, rect: [108.640625,531.65625 84.9375x17.46875] + "nisi luctus" + line 17 width: 20.546875, height: 18.4375, bottom: 315.40625, baseline: 13.53125 + frag 0 from TextNode start: 176, length: 3, rect: [108.640625,548.65625 20.546875x17.46875] + "at." + TextNode <#text> + BlockContainer <(anonymous)> at (8,8) content-size 0x0 [BFC] children: inline + TextNode <#text> + BlockContainer at (8,8) content-size 100.640625x560.0625 [BFC] children: inline + line 0 width: 50.96875, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 1, length: 5, rect: [8,8 50.96875x17.46875] + "Lorem" + line 1 width: 94.9375, height: 17.9375, bottom: 35.40625, baseline: 13.53125 + frag 0 from TextNode start: 7, length: 11, rect: [8,25 94.9375x17.46875] + "ipsum dolor" + line 2 width: 70.9375, height: 18.40625, bottom: 53.34375, baseline: 13.53125 + frag 0 from TextNode start: 19, length: 9, rect: [8,42 70.9375x17.46875] + "sit amet," + line 3 width: 96.84375, height: 17.875, bottom: 70.28125, baseline: 13.53125 + frag 0 from TextNode start: 29, length: 11, rect: [8,60 96.84375x17.46875] + "consectetur" + line 4 width: 75.71875, height: 18.34375, bottom: 88.21875, baseline: 13.53125 + frag 0 from TextNode start: 41, length: 10, rect: [8,77 75.71875x17.46875] + "adipiscing" + line 5 width: 65.265625, height: 17.8125, bottom: 105.15625, baseline: 13.53125 + frag 0 from TextNode start: 52, length: 9, rect: [8,95 65.265625x17.46875] + "elit. Sed" + line 6 width: 37.6875, height: 18.28125, bottom: 123.09375, baseline: 13.53125 + frag 0 from TextNode start: 62, length: 5, rect: [8,112 37.6875x17.46875] + "vitae" + line 7 width: 100.640625, height: 17.75, bottom: 140.03125, baseline: 13.53125 + frag 0 from TextNode start: 68, length: 11, rect: [8,130 100.640625x17.46875] + "condimentum" + line 8 width: 65.03125, height: 18.21875, bottom: 157.96875, baseline: 13.53125 + frag 0 from TextNode start: 80, length: 8, rect: [8,147 65.03125x17.46875] + "erat, ac" + line 9 width: 65.15625, height: 17.6875, bottom: 174.90625, baseline: 13.53125 + frag 0 from TextNode start: 89, length: 7, rect: [8,165 65.15625x17.46875] + "posuere" + line 10 width: 41.171875, height: 18.15625, bottom: 192.84375, baseline: 13.53125 + frag 0 from TextNode start: 97, length: 5, rect: [8,182 41.171875x17.46875] + "arcu." + line 11 width: 60.265625, height: 17.625, bottom: 209.78125, baseline: 13.53125 + frag 0 from TextNode start: 103, length: 6, rect: [8,200 60.265625x17.46875] + "Aenean" + line 12 width: 93.34375, height: 18.09375, bottom: 227.71875, baseline: 13.53125 + frag 0 from TextNode start: 110, length: 12, rect: [8,217 93.34375x17.46875] + "tincidunt mi" + line 13 width: 73.90625, height: 17.5625, bottom: 244.65625, baseline: 13.53125 + frag 0 from TextNode start: 123, length: 11, rect: [8,235 73.90625x17.46875] + "ligula, vel" + line 14 width: 57.234375, height: 18.03125, bottom: 262.59375, baseline: 13.53125 + frag 0 from TextNode start: 135, length: 6, rect: [8,252 57.234375x17.46875] + "semper" + line 15 width: 41.640625, height: 17.5, bottom: 279.53125, baseline: 13.53125 + frag 0 from TextNode start: 142, length: 5, rect: [8,270 41.640625x17.46875] + "dolor" + line 16 width: 83.09375, height: 17.96875, bottom: 297.46875, baseline: 13.53125 + frag 0 from TextNode start: 148, length: 11, rect: [8,287 83.09375x17.46875] + "aliquet at." + line 17 width: 75.8125, height: 18.4375, bottom: 315.40625, baseline: 13.53125 + frag 0 from TextNode start: 160, length: 9, rect: [8,304 75.8125x17.46875] + "Phasellus" + line 18 width: 92.1875, height: 17.90625, bottom: 332.34375, baseline: 13.53125 + frag 0 from TextNode start: 170, length: 11, rect: [8,322 92.1875x17.46875] + "scelerisque" + line 19 width: 59.765625, height: 18.375, bottom: 350.28125, baseline: 13.53125 + frag 0 from TextNode start: 182, length: 7, rect: [8,339 59.765625x17.46875] + "dapibus" + line 20 width: 67.890625, height: 17.84375, bottom: 367.21875, baseline: 13.53125 + frag 0 from TextNode start: 190, length: 8, rect: [8,357 67.890625x17.46875] + "diam sed" + line 21 width: 70.4375, height: 18.3125, bottom: 385.15625, baseline: 13.53125 + frag 0 from TextNode start: 199, length: 8, rect: [8,374 70.4375x17.46875] + "rhoncus." + line 22 width: 78.8125, height: 17.78125, bottom: 402.09375, baseline: 13.53125 + frag 0 from TextNode start: 208, length: 9, rect: [8,392 78.8125x17.46875] + "Proin sed" + line 23 width: 68.296875, height: 18.25, bottom: 420.03125, baseline: 13.53125 + frag 0 from TextNode start: 218, length: 9, rect: [8,409 68.296875x17.46875] + "orci leo." + TextNode <#text> + BlockContainer <(anonymous)> at (8,8) content-size 0x0 [BFC] children: inline + TextNode <#text> diff --git a/Tests/LibWeb/Layout/input/grid/row-span-2-maxcontent.html b/Tests/LibWeb/Layout/input/grid/row-span-2-maxcontent.html new file mode 100644 index 00000000000000..b564ca8e42905e --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/row-span-2-maxcontent.html @@ -0,0 +1,53 @@ + +
+
+In a sollicitudin augue. Sed ante augue, rhoncus nec porttitor id, +lacinia et nibh. Pellentesque diam libero, ultrices eget eleifend at, +consequat ut orci. +
+
+Suspendisse potenti. Pellentesque at varius lacus, sed sollicitudin leo. +Pellentesque malesuada mi eget pellentesque tempor. Donec egestas mauris +est, ut lobortis nisi luctus at. Vivamus eleifend, lorem vulputate +maximus porta, nunc metus porttitor nibh, nec bibendum nulla lectus ut +felis. +
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae +condimentum erat, ac posuere arcu. Aenean tincidunt mi ligula, vel +semper dolor aliquet at. Phasellus scelerisque dapibus diam sed rhoncus. +Proin sed orci leo. Praesent pellentesque mi eu nunc gravida, vel +consectetur nulla malesuada. Sed pellentesque, elit sit amet +sollicitudin sollicitudin, lectus justo facilisis lacus, ac vehicula +metus neque ac mi. In in augue et massa maximus venenatis auctor +fermentum dui. Aliquam dictum finibus urna, quis lacinia massa laoreet +a. Suspendisse elementum non lectus nec elementum. Quisque ultricies +suscipit porttitor. Sed non urna rutrum, mattis nulla at, feugiat erat. +Duis orci elit, vehicula sed blandit eget, auctor in arcu. Ut cursus +magna sit amet nulla cursus, vitae gravida mauris dictum. +
+
\ No newline at end of file diff --git a/Tests/LibWeb/Layout/input/grid/row-span-2-mincontent.html b/Tests/LibWeb/Layout/input/grid/row-span-2-mincontent.html new file mode 100644 index 00000000000000..c4e9d67f0d8296 --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/row-span-2-mincontent.html @@ -0,0 +1,43 @@ + +
+
+In a sollicitudin augue. Sed ante augue, rhoncus nec porttitor id, +lacinia et nibh. Pellentesque diam libero, ultrices eget eleifend at, +consequat ut orci. +
+
+Suspendisse potenti. Pellentesque at varius lacus, sed sollicitudin leo. +Pellentesque malesuada mi eget pellentesque tempor. Donec egestas mauris +est, ut lobortis nisi luctus at. +
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae +condimentum erat, ac posuere arcu. Aenean tincidunt mi ligula, vel +semper dolor aliquet at. Phasellus scelerisque dapibus diam sed rhoncus. +Proin sed orci leo. +
+
\ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp index 3845f93c4922cc..97f13e788ec8cb 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp @@ -847,7 +847,7 @@ void GridFormattingContext::resolve_intrinsic_track_sizes(AvailableSpace const& for (auto& item : m_grid_items) max_item_span = max(item.span(dimension), max_item_span); for (size_t span = 2; span <= max_item_span; span++) { - increase_sizes_to_accommodate_spanning_items_crossing_content_sized_tracks(dimension, 2); + increase_sizes_to_accommodate_spanning_items_crossing_content_sized_tracks(available_space, dimension, 2); } // 4. Increase sizes to accommodate spanning items crossing flexible tracks: Next, repeat the previous @@ -862,17 +862,12 @@ void GridFormattingContext::resolve_intrinsic_track_sizes(AvailableSpace const& track.growth_limit = track.base_size; } } - - for (auto& track : tracks_and_gaps) - track.has_definite_base_size = true; } -void GridFormattingContext::distribute_extra_space_across_spanned_tracks(CSSPixels item_size_contribution, Vector& spanned_tracks) +void GridFormattingContext::distribute_extra_space_across_spanned_tracks_base_size(CSSPixels item_size_contribution, Vector& spanned_tracks) { - for (auto& track : spanned_tracks) { - track.planned_increase = 0; + for (auto& track : spanned_tracks) track.item_incurred_increase = 0; - } // 1. Find the space to distribute: CSSPixels spanned_tracks_sizes_sum = 0; @@ -884,8 +879,10 @@ void GridFormattingContext::distribute_extra_space_across_spanned_tracks(CSSPixe auto extra_space = max(CSSPixels(0), item_size_contribution - spanned_tracks_sizes_sum); // 2. Distribute space up to limits: - while (extra_space > 0) { - auto all_frozen = all_of(spanned_tracks, [](auto const& track) { return track.frozen; }); + // 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; }); if (all_frozen) break; @@ -894,11 +891,11 @@ void GridFormattingContext::distribute_extra_space_across_spanned_tracks(CSSPixe // increase reaches its limit CSSPixels increase_per_track = extra_space / spanned_tracks.size(); for (auto& track : spanned_tracks) { - if (track.frozen) + if (track.base_size_frozen) continue; if (increase_per_track >= track.growth_limit) { - track.frozen = true; + track.base_size_frozen = true; track.item_incurred_increase = track.growth_limit; extra_space -= track.growth_limit; } else { @@ -918,8 +915,68 @@ void GridFormattingContext::distribute_extra_space_across_spanned_tracks(CSSPixe } } -void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossing_content_sized_tracks(GridDimension const dimension, size_t span) +void GridFormattingContext::distribute_extra_space_across_spanned_tracks_growth_limit(CSSPixels item_size_contribution, Vector& spanned_tracks) +{ + for (auto& track : spanned_tracks) + track.item_incurred_increase = 0; + + // 1. Find the space to distribute: + CSSPixels spanned_tracks_sizes_sum = 0; + for (auto& track : spanned_tracks) { + if (track.growth_limit != INFINITY) { + spanned_tracks_sizes_sum += track.growth_limit; + } else { + spanned_tracks_sizes_sum += track.base_size; + } + } + + // Subtract the corresponding size of every spanned track from the item’s size contribution to find the item’s + // remaining size contribution. + auto extra_space = max(CSSPixels(0), item_size_contribution - spanned_tracks_sizes_sum); + + // 2. Distribute space up to limits: + // 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; }); + 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) { + if (track.growth_limit_frozen) + continue; + + // For growth limits, the limit is infinity if it is marked as infinitely growable, and equal to the + // growth limit otherwise. + auto limit = track.infinitely_growable ? INFINITY : track.growth_limit; + if (increase_per_track >= limit) { + track.growth_limit_frozen = true; + track.item_incurred_increase = limit; + extra_space -= limit; + } else { + track.item_incurred_increase += increase_per_track; + extra_space -= increase_per_track; + } + } + } + + // FIXME: 3. Distribute space beyond limits + + // 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) { + if (track.item_incurred_increase > track.planned_increase) + track.planned_increase = track.item_incurred_increase; + } +} + +void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossing_content_sized_tracks(AvailableSpace const& available_space, GridDimension const dimension, size_t span) { + auto& available_size = dimension == GridDimension::Column ? available_space.width : available_space.height; auto& tracks = dimension == GridDimension::Column ? m_grid_columns : m_grid_rows; for (auto& item : m_grid_items) { auto const item_span = item.span(dimension); @@ -944,11 +1001,51 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin if (track.min_track_sizing_function.is_intrinsic_track_sizing()) intrinsic_minimum_spanned_tracks.append(track); } - auto item_minimum_contribution = calculate_minimum_contribution(item, dimension); - distribute_extra_space_across_spanned_tracks(item_minimum_contribution, intrinsic_minimum_spanned_tracks); + 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. + if (available_size.is_intrinsic_sizing_constraint()) + 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); + for (auto& track : spanned_tracks) { + track.base_size += track.planned_increase; + track.planned_increase = 0; + } + // 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); for (auto& track : spanned_tracks) { track.base_size += track.planned_increase; + track.planned_increase = 0; + } + + // 3. For max-content minimums: Next, if the grid container is being sized under a max-content constraint, + // 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() || 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); + for (auto& track : spanned_tracks) { + track.base_size += track.planned_increase; + track.planned_increase = 0; + } } // 4. If at this point any track’s growth limit is now less than its base size, increase its growth limit to @@ -957,6 +1054,49 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin if (track.growth_limit < track.base_size) track.growth_limit = track.base_size; } + + // 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_track_sizing()) { + intrinsic_maximum_tracks.append(track); + } + } + distribute_extra_space_across_spanned_tracks_growth_limit(item_min_content_contribution, intrinsic_maximum_tracks); + for (auto& track : spanned_tracks) { + if (track.growth_limit == INFINITY) { + // If the affected size is an infinite growth limit, set it to the track’s base size plus the planned increase. + track.growth_limit = track.base_size + track.planned_increase; + // Mark any tracks whose growth limit changed from infinite to finite in this step as infinitely growable + // for the next step. + track.infinitely_growable = true; + } else { + track.growth_limit += track.planned_increase; + } + track.planned_increase = 0; + } + + // 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()) { + 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); + for (auto& track : spanned_tracks) { + if (track.growth_limit == INFINITY) { + // If the affected size is an infinite growth limit, set it to the track’s base size plus the planned increase. + track.growth_limit = track.base_size + track.planned_increase; + } else { + track.growth_limit += track.planned_increase; + } + track.planned_increase = 0; + } } } @@ -983,7 +1123,7 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin spanned_flexible_tracks.append(track); } auto item_minimum_contribution = automatic_minimum_size(item, dimension); - distribute_extra_space_across_spanned_tracks(item_minimum_contribution, spanned_flexible_tracks); + distribute_extra_space_across_spanned_tracks_base_size(item_minimum_contribution, spanned_flexible_tracks); 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 9e83854c8910e5..6d95022590885b 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h @@ -104,13 +104,18 @@ class GridFormattingContext final : public FormattingContext { struct TemporaryTrack { CSS::GridSize min_track_sizing_function; CSS::GridSize max_track_sizing_function; + CSSPixels base_size { 0 }; - bool has_definite_base_size { false }; + bool base_size_frozen { false }; + CSSPixels growth_limit { 0 }; + bool growth_limit_frozen { false }; + bool infinitely_growable { false }; + CSSPixels space_to_distribute { 0 }; CSSPixels planned_increase { 0 }; CSSPixels item_incurred_increase { 0 }; - bool frozen { false }; + bool is_gap { false }; TemporaryTrack(CSS::GridSize min_track_sizing_function, CSS::GridSize max_track_sizing_function) @@ -216,8 +221,9 @@ class GridFormattingContext final : public FormattingContext { void initialize_track_sizes(AvailableSpace const&, GridDimension const); void resolve_intrinsic_track_sizes(AvailableSpace const&, GridDimension const); - void distribute_extra_space_across_spanned_tracks(CSSPixels item_size_contribution, Vector& spanned_tracks); - void increase_sizes_to_accommodate_spanning_items_crossing_content_sized_tracks(GridDimension const, size_t span); + 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); void expand_flexible_tracks(AvailableSpace const&, GridDimension const); From aea4408daee38aa0c6591c68939f22a241d006b2 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Sat, 20 May 2023 17:55:44 +0300 Subject: [PATCH 2/2] LibWeb: Use code to size spanning tracks for non-spanning tracks in GFC Since the specifications indicate that the algorithm for sizing tracks without any spanning items is a simplified version of the more general algorithm used for sizing tracks with spanning items, we can reuse the code to size both cases. --- .../LibWeb/Layout/GridFormattingContext.cpp | 119 +----------------- 1 file changed, 2 insertions(+), 117 deletions(-) diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp index 97f13e788ec8cb..0624a414e17bbe 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp @@ -695,126 +695,11 @@ void GridFormattingContext::resolve_intrinsic_track_sizes(AvailableSpace const& // across those tracks insofar as possible. auto& tracks_and_gaps = dimension == GridDimension::Column ? m_grid_columns_and_gaps : m_grid_rows_and_gaps; - auto& available_size = dimension == GridDimension::Column ? available_space.width : available_space.height; // FIXME: 1. Shim baseline-aligned items so their intrinsic size contributions reflect their baseline alignment. - // 2. Size tracks to fit non-spanning items: For each track with an intrinsic track sizing function and - // not a flexible sizing function, consider the items in it with a span of 1: - - size_t index = 0; - for (auto& track : tracks_and_gaps) { - if (track.is_gap) { - ++index; - continue; - } - - Vector grid_items_of_track; - for (auto& grid_item : m_grid_items) { - if (dimension == GridDimension::Column) { - if (grid_item.gap_adjusted_column(grid_container()) == index && grid_item.raw_column_span() == 1) { - grid_items_of_track.append(grid_item); - } - } else { - if (grid_item.gap_adjusted_row(grid_container()) == index && grid_item.raw_row_span() == 1) { - grid_items_of_track.append(grid_item); - } - } - } - - if (grid_items_of_track.size() == 0) { - ++index; - continue; - } - - if (!track.min_track_sizing_function.is_intrinsic_track_sizing() && !track.max_track_sizing_function.is_intrinsic_track_sizing()) { - ++index; - continue; - } - - switch (track.min_track_sizing_function.type()) { - case CSS::GridSize::Type::MinContent: { - // If the track has a min-content min track sizing function, set its base size to the maximum of the - // items’ min-content contributions, floored at zero. - CSSPixels base_size = 0; - for (auto& item : grid_items_of_track) { - base_size = max(base_size, calculate_min_content_contribution(item, dimension)); - } - track.base_size = base_size; - } break; - case CSS::GridSize::Type::MaxContent: { - // If the track has a max-content min track sizing function, set its base size to the maximum of the - // items’ max-content contributions, floored at zero. - CSSPixels base_size = 0; - for (auto& item : grid_items_of_track) { - base_size = max(base_size, calculate_max_content_contribution(item, dimension)); - } - track.base_size = base_size; - } break; - case CSS::GridSize::Type::LengthPercentage: { - if (track.min_track_sizing_function.is_auto() && available_size.is_intrinsic_sizing_constraint()) { - // If the track has an auto min track sizing function and the grid container is being sized under a - // min-/max-content constraint, set the track’s base size to the maximum of its items’ limited - // min-/max-content contributions (respectively), floored at zero. - if (available_size.is_min_content()) { - CSSPixels base_size = 0; - for (auto& item : grid_items_of_track) { - base_size = max(base_size, calculate_limited_min_content_contribution(item, dimension)); - } - track.base_size = base_size; - } else if (available_size.is_max_content()) { - CSSPixels base_size = 0; - for (auto& item : grid_items_of_track) { - base_size = max(base_size, calculate_limited_max_content_contribution(item, dimension)); - } - track.base_size = base_size; - } - } else if (track.min_track_sizing_function.is_auto()) { - // Otherwise, set the track’s base size to the maximum of its items’ minimum contributions, floored at zero. - CSSPixels base_size = 0; - for (auto& item : grid_items_of_track) { - base_size = max(base_size, calculate_minimum_contribution(item, dimension)); - } - track.base_size = base_size; - } - - break; - } - case CSS::GridSize::Type::FlexibleLength: { - // do nothing - break; - } - default: - VERIFY_NOT_REACHED(); - } - - auto const& max_track_sizing_function = track.max_track_sizing_function; - if (max_track_sizing_function.is_min_content()) { - // If the track has a min-content max track sizing function, set its growth limit to the maximum of - // the items’ min-content contributions. - CSSPixels growth_limit = 0; - for (auto& item : grid_items_of_track) { - growth_limit = max(growth_limit, calculate_min_content_contribution(item, dimension)); - } - track.growth_limit = growth_limit; - } else if (max_track_sizing_function.is_max_content() || max_track_sizing_function.is_auto()) { - // If the track has a max-content max track sizing function, set its growth limit to the maximum of - // the items’ max-content contributions. For fit-content() maximums, furthermore clamp this growth - // limit by the fit-content() argument. - CSSPixels growth_limit = 0; - for (auto& item : grid_items_of_track) { - growth_limit = max(growth_limit, calculate_max_content_contribution(item, dimension)); - } - track.growth_limit = growth_limit; - } - - // In all cases, if a track’s growth limit is now less than its base size, increase the growth limit - // to match the base size. - if (track.growth_limit < track.base_size) - track.growth_limit = track.base_size; - - ++index; - } + // 2. Size tracks to fit non-spanning items: + increase_sizes_to_accommodate_spanning_items_crossing_content_sized_tracks(available_space, dimension, 1); // https://www.w3.org/TR/css-grid-2/#auto-repeat // The auto-fit keyword behaves the same as auto-fill, except that after grid item placement any