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

This commit is contained in:
Andreas Kling 2022-09-13 20:45:38 +02:00
parent f941b7aefe
commit 63c727a4a3
Notes: sideshowbarker 2024-07-17 07:11:10 +09:00
10 changed files with 37 additions and 25 deletions

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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)