Browse Source

LibWeb: Don't clip to containing block when painting abspos descendants

Andreas Kling 2 years ago
parent
commit
63c727a4a3

+ 7 - 2
Userland/Libraries/LibWeb/Painting/Paintable.h

@@ -83,8 +83,13 @@ public:
     }
 
     virtual void paint(PaintContext&, PaintPhase) const { }
-    virtual void before_children_paint(PaintContext&, PaintPhase) const { }
-    virtual void after_children_paint(PaintContext&, PaintPhase) const { }
+
+    enum class ShouldClipOverflow {
+        No,
+        Yes
+    };
+    virtual void before_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const { }
+    virtual void after_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const { }
 
     virtual Optional<HitTestResult> hit_test(Gfx::FloatPoint const&, HitTestType) const;
 

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

@@ -257,11 +257,14 @@ BorderRadiiData PaintableBox::normalized_border_radii_data(ShrinkRadiiForBorders
     return border_radius_data;
 }
 
-void PaintableBox::before_children_paint(PaintContext& context, PaintPhase phase) const
+void PaintableBox::before_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const
 {
     if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::Foreground))
         return;
 
+    if (should_clip_overflow == ShouldClipOverflow::No)
+        return;
+
     // FIXME: Support more overflow variations.
     auto clip_rect = absolute_padding_box_rect().to_rounded<int>();
     auto overflow_x = computed_values().overflow_x();
@@ -293,11 +296,14 @@ void PaintableBox::before_children_paint(PaintContext& context, PaintPhase phase
     }
 }
 
-void PaintableBox::after_children_paint(PaintContext& context, PaintPhase phase) const
+void PaintableBox::after_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const
 {
     if (!AK::first_is_one_of(phase, PaintPhase::Background, PaintPhase::Border, PaintPhase::Foreground))
         return;
 
+    if (should_clip_overflow == ShouldClipOverflow::No)
+        return;
+
     // FIXME: Support more overflow variations.
     if (m_clipping_overflow) {
         context.painter().restore();

+ 2 - 2
Userland/Libraries/LibWeb/Painting/PaintableBox.h

@@ -107,8 +107,8 @@ public:
     DOM::Document const& document() const { return layout_box().document(); }
     DOM::Document& document() { return layout_box().document(); }
 
-    virtual void before_children_paint(PaintContext&, PaintPhase) const override;
-    virtual void after_children_paint(PaintContext&, PaintPhase) const override;
+    virtual void before_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override;
+    virtual void after_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override;
 
     virtual Optional<HitTestResult> hit_test(Gfx::FloatPoint const&, HitTestType) const override;
 

+ 2 - 2
Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp

@@ -19,9 +19,9 @@ Layout::SVGGraphicsBox const& SVGGraphicsPaintable::layout_box() const
     return static_cast<Layout::SVGGraphicsBox const&>(layout_node());
 }
 
-void SVGGraphicsPaintable::before_children_paint(PaintContext& context, PaintPhase phase) const
+void SVGGraphicsPaintable::before_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const
 {
-    SVGPaintable::before_children_paint(context, phase);
+    SVGPaintable::before_children_paint(context, phase, should_clip_overflow);
     if (phase != PaintPhase::Foreground)
         return;
 

+ 1 - 1
Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.h

@@ -13,7 +13,7 @@ namespace Web::Painting {
 
 class SVGGraphicsPaintable : public SVGPaintable {
 public:
-    virtual void before_children_paint(PaintContext&, PaintPhase) const override;
+    virtual void before_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override;
 
     Layout::SVGGraphicsBox const& layout_box() const;
 

+ 4 - 4
Userland/Libraries/LibWeb/Painting/SVGPaintable.cpp

@@ -20,17 +20,17 @@ Layout::SVGBox const& SVGPaintable::layout_box() const
     return static_cast<Layout::SVGBox const&>(layout_node());
 }
 
-void SVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase) const
+void SVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const
 {
-    PaintableBox::before_children_paint(context, phase);
+    PaintableBox::before_children_paint(context, phase, should_clip_overflow);
     if (phase != PaintPhase::Foreground)
         return;
     context.svg_context().save();
 }
 
-void SVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase) const
+void SVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const
 {
-    PaintableBox::after_children_paint(context, phase);
+    PaintableBox::after_children_paint(context, phase, should_clip_overflow);
     if (phase != PaintPhase::Foreground)
         return;
     context.svg_context().restore();

+ 2 - 2
Userland/Libraries/LibWeb/Painting/SVGPaintable.h

@@ -13,8 +13,8 @@ namespace Web::Painting {
 
 class SVGPaintable : public PaintableBox {
 public:
-    virtual void before_children_paint(PaintContext&, PaintPhase) const override;
-    virtual void after_children_paint(PaintContext&, PaintPhase) const override;
+    virtual void before_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override;
+    virtual void after_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override;
 
     Layout::SVGBox const& layout_box() const;
 

+ 4 - 4
Userland/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp

@@ -24,7 +24,7 @@ Layout::SVGSVGBox const& SVGSVGPaintable::layout_box() const
     return static_cast<Layout::SVGSVGBox const&>(layout_node());
 }
 
-void SVGSVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase) const
+void SVGSVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const
 {
     if (phase != PaintPhase::Foreground)
         return;
@@ -32,12 +32,12 @@ void SVGSVGPaintable::before_children_paint(PaintContext& context, PaintPhase ph
     if (!context.has_svg_context())
         context.set_svg_context(SVGContext(absolute_rect()));
 
-    PaintableBox::before_children_paint(context, phase);
+    PaintableBox::before_children_paint(context, phase, should_clip_overflow);
 }
 
-void SVGSVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase) const
+void SVGSVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const
 {
-    PaintableBox::after_children_paint(context, phase);
+    PaintableBox::after_children_paint(context, phase, should_clip_overflow);
     if (phase != PaintPhase::Foreground)
         return;
     context.clear_svg_context();

+ 2 - 2
Userland/Libraries/LibWeb/Painting/SVGSVGPaintable.h

@@ -15,8 +15,8 @@ class SVGSVGPaintable : public PaintableBox {
 public:
     static NonnullRefPtr<SVGSVGPaintable> create(Layout::SVGSVGBox const&);
 
-    virtual void before_children_paint(PaintContext&, PaintPhase) const override;
-    virtual void after_children_paint(PaintContext&, PaintPhase) const override;
+    virtual void before_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override;
+    virtual void after_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override;
 
     Layout::SVGSVGBox const& layout_box() const;
 

+ 5 - 4
Userland/Libraries/LibWeb/Painting/StackingContext.cpp

@@ -71,7 +71,7 @@ static PaintPhase to_paint_phase(StackingContext::StackingContextPaintPhase phas
 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));
+        paintable->before_children_paint(context, to_paint_phase(phase), Paintable::ShouldClipOverflow::Yes);
 
     box.for_each_child([&](auto& child) {
         // If `child` establishes its own stacking context, skip over it.
@@ -123,7 +123,7 @@ void StackingContext::paint_descendants(PaintContext& context, Layout::Node& box
     });
 
     if (auto* paintable = box.paintable())
-        paintable->after_children_paint(context, to_paint_phase(phase));
+        paintable->after_children_paint(context, to_paint_phase(phase), Paintable::ShouldClipOverflow::Yes);
 }
 
 void StackingContext::paint_internal(PaintContext& context) const
@@ -135,12 +135,13 @@ void StackingContext::paint_internal(PaintContext& context) const
 
     auto paint_child = [&](auto* child) {
         auto parent = child->m_box.parent();
+        auto should_clip_overflow = child->m_box.is_positioned() ? Paintable::ShouldClipOverflow::No : Paintable::ShouldClipOverflow::Yes;
         auto* paintable = parent ? parent->paintable() : nullptr;
         if (paintable)
-            paintable->before_children_paint(context, PaintPhase::Foreground);
+            paintable->before_children_paint(context, PaintPhase::Foreground, should_clip_overflow);
         child->paint(context);
         if (paintable)
-            paintable->after_children_paint(context, PaintPhase::Foreground);
+            paintable->after_children_paint(context, PaintPhase::Foreground, should_clip_overflow);
     };
 
     // Draw positioned descendants with negative z-indices (step 3)