Forráskód Böngészése

LibWeb: Apply overflow: hidden to all (relevant) child paint phases

Previously, before/after_children_paint() was only called for the
"Foreground" paint phase, this meant the backgrounds and other
features of child nodes of a element with overflow: hidden were
not clipped.
MacDue 3 éve
szülő
commit
f079214b18

+ 9 - 2
Userland/Libraries/LibWeb/Painting/PaintableBox.cpp

@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-2-Clause
  */
 
+#include <AK/GenericShorthands.h>
 #include <LibUnicode/CharacterTypes.h>
 #include <LibWeb/DOM/Document.h>
 #include <LibWeb/HTML/HTMLHtmlElement.h>
@@ -242,8 +243,11 @@ BorderRadiiData PaintableBox::normalized_border_radii_data() const
         computed_values().border_bottom_left_radius());
 }
 
-void PaintableBox::before_children_paint(PaintContext& context, PaintPhase) const
+void PaintableBox::before_children_paint(PaintContext& context, PaintPhase phase) const
 {
+    if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::Foreground))
+        return;
+
     // FIXME: Support more overflow variations.
     auto clip_rect = absolute_padding_box_rect().to_rounded<int>();
     auto overflow_x = computed_values().overflow_x();
@@ -277,8 +281,11 @@ void PaintableBox::before_children_paint(PaintContext& context, PaintPhase) cons
     }
 }
 
-void PaintableBox::after_children_paint(PaintContext& context, PaintPhase) const
+void PaintableBox::after_children_paint(PaintContext& context, PaintPhase phase) const
 {
+    if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::Foreground))
+        return;
+
     // FIXME: Support more overflow variations.
     if (m_clipping_overflow) {
         context.painter().restore();

+ 21 - 8
Userland/Libraries/LibWeb/Painting/StackingContext.cpp

@@ -48,12 +48,27 @@ void StackingContext::sort()
         child->sort();
 }
 
-void StackingContext::paint_descendants(PaintContext& context, Layout::Node& box, StackingContextPaintPhase phase) const
+static PaintPhase to_paint_phase(StackingContext::StackingContextPaintPhase phase)
 {
-    if (phase == StackingContextPaintPhase::Foreground) {
-        if (auto* paintable = box.paintable())
-            paintable->before_children_paint(context, PaintPhase::Foreground);
+    // There are not a fully correct mapping since some stacking context phases are combind.
+    switch (phase) {
+    case StackingContext::StackingContextPaintPhase::Floats:
+    case StackingContext::StackingContextPaintPhase::BackgroundAndBordersForInlineLevelAndReplaced:
+    case StackingContext::StackingContextPaintPhase::BackgroundAndBorders:
+        return PaintPhase::Background;
+    case StackingContext::StackingContextPaintPhase::Foreground:
+        return PaintPhase::Foreground;
+    case StackingContext::StackingContextPaintPhase::FocusAndOverlay:
+        return PaintPhase::Overlay;
+    default:
+        VERIFY_NOT_REACHED();
     }
+}
+
+void StackingContext::paint_descendants(PaintContext& context, Layout::Node& box, StackingContextPaintPhase phase) const
+{
+    if (auto* paintable = box.paintable())
+        paintable->before_children_paint(context, to_paint_phase(phase));
 
     box.for_each_child([&](auto& child) {
         // If `child` establishes its own stacking context, skip over it.
@@ -104,10 +119,8 @@ void StackingContext::paint_descendants(PaintContext& context, Layout::Node& box
         }
     });
 
-    if (phase == StackingContextPaintPhase::Foreground) {
-        if (auto* paintable = box.paintable())
-            paintable->after_children_paint(context, PaintPhase::Foreground);
-    }
+    if (auto* paintable = box.paintable())
+        paintable->after_children_paint(context, to_paint_phase(phase));
 }
 
 void StackingContext::paint_internal(PaintContext& context) const