diff --git a/Userland/Libraries/LibWeb/Painting/Paintable.h b/Userland/Libraries/LibWeb/Painting/Paintable.h index c9e2b964aa..5bdb06e0dd 100644 --- a/Userland/Libraries/LibWeb/Painting/Paintable.h +++ b/Userland/Libraries/LibWeb/Painting/Paintable.h @@ -86,12 +86,8 @@ public: virtual void 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 void before_children_paint(PaintContext&, PaintPhase) const { } + virtual void after_children_paint(PaintContext&, PaintPhase) const { } virtual Optional hit_test(Gfx::FloatPoint const&, HitTestType) const; diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index 3107927bb6..b6f0804f78 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -310,34 +310,53 @@ BorderRadiiData PaintableBox::normalized_border_radii_data(ShrinkRadiiForBorders return border_radius_data; } -void PaintableBox::before_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const +Optional PaintableBox::clip_rect() const +{ + if (!m_clip_rect.has_value()) { + if (containing_block() && containing_block()->paint_box()) + m_clip_rect = containing_block()->paint_box()->clip_rect(); + + auto overflow_x = computed_values().overflow_x(); + auto overflow_y = computed_values().overflow_y(); + + if (overflow_x == CSS::Overflow::Hidden && overflow_y == CSS::Overflow::Hidden) { + if (m_clip_rect.has_value()) { + m_clip_rect->intersect(absolute_padding_box_rect().to_rounded()); + } else { + m_clip_rect = absolute_padding_box_rect().to_rounded(); + } + } + } + + return m_clip_rect; +} + +void PaintableBox::before_children_paint(PaintContext& context, PaintPhase phase) 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(); + auto clip_rect = this->clip_rect(); auto overflow_x = computed_values().overflow_x(); auto overflow_y = computed_values().overflow_y(); auto clip_overflow = [&] { if (!m_clipping_overflow) { context.painter().save(); - context.painter().add_clip_rect(clip_rect); + context.painter().add_clip_rect(*clip_rect); m_clipping_overflow = true; } }; - if (overflow_x == CSS::Overflow::Hidden && overflow_y == CSS::Overflow::Hidden) { + if (clip_rect.has_value()) { clip_overflow(); } + if (overflow_y == CSS::Overflow::Hidden || overflow_x == CSS::Overflow::Hidden) { auto border_radii_data = normalized_border_radii_data(ShrinkRadiiForBorders::Yes); if (border_radii_data.has_any_radius()) { - auto corner_clipper = BorderRadiusCornerClipper::create(clip_rect, border_radii_data, CornerClip::Outside, BorderRadiusCornerClipper::UseCachedBitmap::No); + auto corner_clipper = BorderRadiusCornerClipper::create(absolute_padding_box_rect().to_rounded(), border_radii_data, CornerClip::Outside, BorderRadiusCornerClipper::UseCachedBitmap::No); if (corner_clipper.is_error()) { dbgln("Failed to create overflow border-radius corner clipper: {}", corner_clipper.error()); return; @@ -349,14 +368,11 @@ void PaintableBox::before_children_paint(PaintContext& context, PaintPhase phase } } -void PaintableBox::after_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) 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; - if (should_clip_overflow == ShouldClipOverflow::No) - return; - // FIXME: Support more overflow variations. if (m_clipping_overflow) { context.painter().restore(); diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.h b/Userland/Libraries/LibWeb/Painting/PaintableBox.h index 603f9ff7b3..345c0d6c9d 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.h @@ -96,6 +96,8 @@ public: return m_overflow_data->scrollable_overflow_rect; } + Optional clip_rect() const; + void set_overflow_data(Optional data) { m_overflow_data = move(data); } void set_containing_line_box_fragment(Optional); @@ -110,8 +112,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, ShouldClipOverflow) const override; - virtual void after_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override; + virtual void before_children_paint(PaintContext&, PaintPhase) const override; + virtual void after_children_paint(PaintContext&, PaintPhase) const override; virtual Optional hit_test(Gfx::FloatPoint const&, HitTestType) const override; @@ -153,6 +155,8 @@ private: Optional mutable m_absolute_rect; Optional mutable m_absolute_paint_rect; + Optional mutable m_clip_rect; + mutable bool m_clipping_overflow { false }; Optional mutable m_overflow_corner_radius_clipper; }; diff --git a/Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp b/Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp index 8f3990bd14..52e5e06c79 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp @@ -19,9 +19,9 @@ Layout::SVGGraphicsBox const& SVGGraphicsPaintable::layout_box() const return static_cast(layout_node()); } -void SVGGraphicsPaintable::before_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const +void SVGGraphicsPaintable::before_children_paint(PaintContext& context, PaintPhase phase) const { - SVGPaintable::before_children_paint(context, phase, should_clip_overflow); + SVGPaintable::before_children_paint(context, phase); if (phase != PaintPhase::Foreground) return; diff --git a/Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.h b/Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.h index 39877db81b..56b1a2e488 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.h +++ b/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, ShouldClipOverflow) const override; + virtual void before_children_paint(PaintContext&, PaintPhase) const override; Layout::SVGGraphicsBox const& layout_box() const; diff --git a/Userland/Libraries/LibWeb/Painting/SVGPaintable.cpp b/Userland/Libraries/LibWeb/Painting/SVGPaintable.cpp index 84910de306..e1dae92297 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/SVGPaintable.cpp @@ -20,17 +20,17 @@ Layout::SVGBox const& SVGPaintable::layout_box() const return static_cast(layout_node()); } -void SVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const +void SVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase) const { - PaintableBox::before_children_paint(context, phase, should_clip_overflow); + PaintableBox::before_children_paint(context, phase); if (phase != PaintPhase::Foreground) return; context.svg_context().save(); } -void SVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const +void SVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase) const { - PaintableBox::after_children_paint(context, phase, should_clip_overflow); + PaintableBox::after_children_paint(context, phase); if (phase != PaintPhase::Foreground) return; context.svg_context().restore(); diff --git a/Userland/Libraries/LibWeb/Painting/SVGPaintable.h b/Userland/Libraries/LibWeb/Painting/SVGPaintable.h index a4c3b90573..b1783e16eb 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGPaintable.h +++ b/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, ShouldClipOverflow) const override; - virtual void after_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override; + virtual void before_children_paint(PaintContext&, PaintPhase) const override; + virtual void after_children_paint(PaintContext&, PaintPhase) const override; Layout::SVGBox const& layout_box() const; diff --git a/Userland/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp b/Userland/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp index 3ca3f69167..b5216b1418 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp @@ -24,7 +24,7 @@ Layout::SVGSVGBox const& SVGSVGPaintable::layout_box() const return static_cast(layout_node()); } -void SVGSVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const +void SVGSVGPaintable::before_children_paint(PaintContext& context, PaintPhase phase) 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, should_clip_overflow); + PaintableBox::before_children_paint(context, phase); } -void SVGSVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase, ShouldClipOverflow should_clip_overflow) const +void SVGSVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase) const { - PaintableBox::after_children_paint(context, phase, should_clip_overflow); + PaintableBox::after_children_paint(context, phase); if (phase != PaintPhase::Foreground) return; context.clear_svg_context(); diff --git a/Userland/Libraries/LibWeb/Painting/SVGSVGPaintable.h b/Userland/Libraries/LibWeb/Painting/SVGSVGPaintable.h index 9c207c3e18..443747abaa 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGSVGPaintable.h +++ b/Userland/Libraries/LibWeb/Painting/SVGSVGPaintable.h @@ -15,8 +15,8 @@ class SVGSVGPaintable : public PaintableBox { public: static NonnullRefPtr create(Layout::SVGSVGBox const&); - virtual void before_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override; - virtual void after_children_paint(PaintContext&, PaintPhase, ShouldClipOverflow) const override; + virtual void before_children_paint(PaintContext&, PaintPhase) const override; + virtual void after_children_paint(PaintContext&, PaintPhase) const override; Layout::SVGSVGBox const& layout_box() const; diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp index 2e994815ad..77ab796bfe 100644 --- a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp +++ b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp @@ -72,7 +72,7 @@ static PaintPhase to_paint_phase(StackingContext::StackingContextPaintPhase phas void StackingContext::paint_descendants(PaintContext& context, Layout::Node const& box, StackingContextPaintPhase phase) const { if (auto* paintable = box.paintable()) - paintable->before_children_paint(context, to_paint_phase(phase), Paintable::ShouldClipOverflow::Yes); + 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. @@ -125,7 +125,7 @@ void StackingContext::paint_descendants(PaintContext& context, Layout::Node cons }); if (auto* paintable = box.paintable()) - paintable->after_children_paint(context, to_paint_phase(phase), Paintable::ShouldClipOverflow::Yes); + paintable->after_children_paint(context, to_paint_phase(phase)); } void StackingContext::paint_internal(PaintContext& context) const @@ -137,13 +137,12 @@ 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_absolutely_positioned() ? Paintable::ShouldClipOverflow::No : Paintable::ShouldClipOverflow::Yes; auto* paintable = parent ? parent->paintable() : nullptr; if (paintable) - paintable->before_children_paint(context, PaintPhase::Foreground, should_clip_overflow); + paintable->before_children_paint(context, PaintPhase::Foreground); child->paint(context); if (paintable) - paintable->after_children_paint(context, PaintPhase::Foreground, should_clip_overflow); + paintable->after_children_paint(context, PaintPhase::Foreground); }; // Draw positioned descendants with negative z-indices (step 3)