Переглянути джерело

LibWeb: Honor negative margins on atomic inlines

Sizing already worked correctly, but before this change, we were too
aggressive with inserting line breaks when negative margins would
still an atomic inline to fit on the line.
Andreas Kling 1 рік тому
батько
коміт
7abb182fa3

+ 14 - 0
Tests/LibWeb/Layout/expected/block-and-inline/inline-block-with-negative-margin-left.txt

@@ -0,0 +1,14 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (0,0) content-size 800x60 [BFC] children: not-inline
+    BlockContainer <body> at (5,5) content-size 150x50 children: inline
+      line 0 width: 150, height: 50, bottom: 50, baseline: 50
+        frag 0 from BlockContainer start: 0, length: 0, rect: [5,5 100x50]
+        frag 1 from BlockContainer start: 0, length: 0, rect: [55,5 100x50]
+      BlockContainer <div.foo> at (5,5) content-size 100x50 inline-block [BFC] children: not-inline
+      BlockContainer <div.bar> at (55,5) content-size 100x50 inline-block [BFC] children: not-inline
+
+ViewportPaintable (Viewport<#document>) [0,0 800x600]
+  PaintableWithLines (BlockContainer<HTML>) [0,0 800x60]
+    PaintableWithLines (BlockContainer<BODY>) [0,0 160x60]
+      PaintableWithLines (BlockContainer<DIV>.foo) [5,5 100x50]
+      PaintableWithLines (BlockContainer<DIV>.bar) [55,5 100x50]

+ 14 - 0
Tests/LibWeb/Layout/expected/block-and-inline/inline-block-with-negative-margin-right.txt

@@ -0,0 +1,14 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (0,0) content-size 800x60 [BFC] children: not-inline
+    BlockContainer <body> at (5,5) content-size 150x50 children: inline
+      line 0 width: 150, height: 50, bottom: 50, baseline: 50
+        frag 0 from BlockContainer start: 0, length: 0, rect: [5,5 100x50]
+        frag 1 from BlockContainer start: 0, length: 0, rect: [105,5 100x50]
+      BlockContainer <div.foo> at (5,5) content-size 100x50 inline-block [BFC] children: not-inline
+      BlockContainer <div.bar> at (105,5) content-size 100x50 inline-block [BFC] children: not-inline
+
+ViewportPaintable (Viewport<#document>) [0,0 800x600]
+  PaintableWithLines (BlockContainer<HTML>) [0,0 800x60]
+    PaintableWithLines (BlockContainer<BODY>) [0,0 160x60] overflow: [5,5 200x50]
+      PaintableWithLines (BlockContainer<DIV>.foo) [5,5 100x50]
+      PaintableWithLines (BlockContainer<DIV>.bar) [105,5 100x50]

+ 23 - 0
Tests/LibWeb/Layout/input/block-and-inline/inline-block-with-negative-margin-left.html

@@ -0,0 +1,23 @@
+<!doctype html><style>
+  * {
+    margin: 0;
+    padding: 0;
+  }
+  body {
+    width: max-content;
+    border: 5px solid black;
+  }
+  .foo {
+    display: inline-block;
+    background: orange;
+    width: 100px;
+    height: 50px;
+  }
+  .bar {
+    display: inline-block;
+    background: magenta;
+    margin-left: -50px;
+    width: 100px;
+    height: 50px;
+  }
+</style><body><div class="foo"></div><div class="bar"></div>

+ 23 - 0
Tests/LibWeb/Layout/input/block-and-inline/inline-block-with-negative-margin-right.html

@@ -0,0 +1,23 @@
+<!doctype html><style>
+  * {
+    margin: 0;
+    padding: 0;
+  }
+  body {
+    width: max-content;
+    border: 5px solid black;
+  }
+  .foo {
+    display: inline-block;
+    background: orange;
+    width: 100px;
+    height: 50px;
+  }
+  .bar {
+    display: inline-block;
+    background: magenta;
+    margin-right: -50px;
+    width: 100px;
+    height: 50px;
+  }
+</style><body><div class="foo"></div><div class="bar"></div>

+ 6 - 1
Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp

@@ -275,7 +275,12 @@ void InlineFormattingContext::generate_line_boxes(LayoutMode layout_mode)
             auto& box = verify_cast<Layout::Box>(*item.node);
             compute_inset(box);
             if (containing_block().computed_values().white_space() != CSS::WhiteSpace::Nowrap) {
-                line_builder.break_if_needed(item.border_box_width());
+                auto minimum_space_needed_on_line = item.border_box_width();
+                if (item.margin_start < 0)
+                    minimum_space_needed_on_line += item.margin_start;
+                if (item.margin_end < 0)
+                    minimum_space_needed_on_line += item.margin_end;
+                line_builder.break_if_needed(minimum_space_needed_on_line);
             }
             line_builder.append_box(box, item.border_start + item.padding_start, item.padding_end + item.border_end, item.margin_start, item.margin_end);
             break;