From 773d19b406acbf87bf0517cf9127a4922009fdae Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 7 Jul 2025 18:27:43 +0200 Subject: [PATCH] LibWeb: Apply either enclosing or own clip rect depending on PaintPhase Previously, we always applied the enclosing clip rectangle for all paint phases except overlays, and the own clip rectangle for the background and foreground phases. The problem is that applying a clip rectangle means emitting an AddClipRect display list item for each clip rectangle in the containing block. With this change, we choose whether to include the own clip based on the paint phase and this way avoid emitting AddClipRect for enclosing clip rectangles twice. --- Libraries/LibWeb/Painting/Paintable.h | 3 -- Libraries/LibWeb/Painting/PaintableBox.cpp | 48 ++++--------------- Libraries/LibWeb/Painting/PaintableBox.h | 3 -- Libraries/LibWeb/Painting/SVGPaintable.cpp | 20 ++++++++ Libraries/LibWeb/Painting/SVGPaintable.h | 3 ++ Libraries/LibWeb/Painting/SVGSVGPaintable.cpp | 20 ++++++++ Libraries/LibWeb/Painting/SVGSVGPaintable.h | 3 ++ 7 files changed, 54 insertions(+), 46 deletions(-) diff --git a/Libraries/LibWeb/Painting/Paintable.h b/Libraries/LibWeb/Painting/Paintable.h index 3fec6eb7bf2..0b01a285b2a 100644 --- a/Libraries/LibWeb/Painting/Paintable.h +++ b/Libraries/LibWeb/Painting/Paintable.h @@ -76,9 +76,6 @@ public: virtual void apply_scroll_offset(PaintContext&, PaintPhase) const { } virtual void reset_scroll_offset(PaintContext&, PaintPhase) const { } - virtual void apply_own_clip_rect(PaintContext&, PaintPhase) const { } - virtual void clear_own_clip_rect(PaintContext&, PaintPhase) const { } - virtual void apply_clip_overflow_rect(PaintContext&, PaintPhase) const { } virtual void clear_clip_overflow_rect(PaintContext&, PaintPhase) const { } diff --git a/Libraries/LibWeb/Painting/PaintableBox.cpp b/Libraries/LibWeb/Painting/PaintableBox.cpp index 81471d6dcd9..58d84ac5387 100644 --- a/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -321,28 +321,28 @@ bool PaintableBox::wants_mouse_events() const return false; } -void PaintableBox::before_paint(PaintContext& context, [[maybe_unused]] PaintPhase phase) const +void PaintableBox::before_paint(PaintContext& context, PaintPhase phase) const { if (!is_visible()) return; - apply_own_clip_rect(context, phase); - - if (!has_css_transform()) { + if (first_is_one_of(phase, PaintPhase::Background, PaintPhase::Foreground) && own_clip_frame()) { + apply_clip(context, own_clip_frame()); + } else if (!has_css_transform()) { apply_clip_overflow_rect(context, phase); } apply_scroll_offset(context, phase); } -void PaintableBox::after_paint(PaintContext& context, [[maybe_unused]] PaintPhase phase) const +void PaintableBox::after_paint(PaintContext& context, PaintPhase phase) const { if (!is_visible()) return; - clear_own_clip_rect(context, phase); - reset_scroll_offset(context, phase); - if (!has_css_transform()) { + if (first_is_one_of(phase, PaintPhase::Background, PaintPhase::Foreground) && own_clip_frame()) { + restore_clip(context, own_clip_frame()); + } else if (!has_css_transform()) { clear_clip_overflow_rect(context, phase); } } @@ -655,38 +655,6 @@ void PaintableBox::clear_clip_overflow_rect(PaintContext& context, PaintPhase ph restore_clip(context, enclosing_clip_frame()); } -void PaintableBox::apply_own_clip_rect(PaintContext& context, PaintPhase phase) const -{ - if (!own_clip_frame()) - return; - - // FIXME: This should apply to SVGs - if (is(*this) || is(*this)) - return; - - // FIXME: This should also apply to borders and outlines. - if (!first_is_one_of(phase, PaintPhase::Background, PaintPhase::Foreground)) - return; - - apply_clip(context, own_clip_frame()); -} - -void PaintableBox::clear_own_clip_rect(PaintContext& context, PaintPhase phase) const -{ - if (!own_clip_frame()) - return; - - // FIXME: This should apply to SVGs - if (is(*this) || is(*this)) - return; - - // FIXME: This should also apply to borders and outlines. - if (!first_is_one_of(phase, PaintPhase::Background, PaintPhase::Foreground)) - return; - - restore_clip(context, own_clip_frame()); -} - void paint_cursor_if_needed(PaintContext& context, TextPaintable const& paintable, PaintableFragment const& fragment) { auto const& navigable = *paintable.navigable(); diff --git a/Libraries/LibWeb/Painting/PaintableBox.h b/Libraries/LibWeb/Painting/PaintableBox.h index 4a0bef6e669..375686b713e 100644 --- a/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Libraries/LibWeb/Painting/PaintableBox.h @@ -142,9 +142,6 @@ public: virtual void apply_clip_overflow_rect(PaintContext&, PaintPhase) const override; virtual void clear_clip_overflow_rect(PaintContext&, PaintPhase) const override; - virtual void apply_own_clip_rect(PaintContext&, PaintPhase) const override; - virtual void clear_own_clip_rect(PaintContext&, PaintPhase) const override; - [[nodiscard]] virtual TraversalDecision hit_test(CSSPixelPoint position, HitTestType type, Function const& callback) const override; Optional hit_test(CSSPixelPoint, HitTestType) const; [[nodiscard]] TraversalDecision hit_test_children(CSSPixelPoint, HitTestType, Function const&) const; diff --git a/Libraries/LibWeb/Painting/SVGPaintable.cpp b/Libraries/LibWeb/Painting/SVGPaintable.cpp index 95352a4dcee..c2973a84fba 100644 --- a/Libraries/LibWeb/Painting/SVGPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGPaintable.cpp @@ -17,6 +17,26 @@ SVGPaintable::SVGPaintable(Layout::SVGBox const& layout_box) { } +void SVGPaintable::before_paint(PaintContext& context, PaintPhase phase) const +{ + if (!is_visible()) + return; + if (!has_css_transform()) { + apply_clip_overflow_rect(context, phase); + } + apply_scroll_offset(context, phase); +} + +void SVGPaintable::after_paint(PaintContext& context, PaintPhase phase) const +{ + if (!is_visible()) + return; + reset_scroll_offset(context, phase); + if (!has_css_transform()) { + clear_clip_overflow_rect(context, phase); + } +} + Layout::SVGBox const& SVGPaintable::layout_box() const { return static_cast(layout_node()); diff --git a/Libraries/LibWeb/Painting/SVGPaintable.h b/Libraries/LibWeb/Painting/SVGPaintable.h index 2d592947755..203d426805e 100644 --- a/Libraries/LibWeb/Painting/SVGPaintable.h +++ b/Libraries/LibWeb/Painting/SVGPaintable.h @@ -22,6 +22,9 @@ protected: SVGPaintable(Layout::SVGBox const&); + virtual void before_paint(PaintContext&, PaintPhase) const override; + virtual void after_paint(PaintContext&, PaintPhase) const override; + virtual CSSPixelRect compute_absolute_rect() const override; }; diff --git a/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp b/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp index c1d42f8a19d..91d5145ca7e 100644 --- a/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp @@ -24,6 +24,26 @@ SVGSVGPaintable::SVGSVGPaintable(Layout::SVGSVGBox const& layout_box) { } +void SVGSVGPaintable::before_paint(PaintContext& context, PaintPhase phase) const +{ + if (!is_visible()) + return; + if (!has_css_transform()) { + apply_clip_overflow_rect(context, phase); + } + apply_scroll_offset(context, phase); +} + +void SVGSVGPaintable::after_paint(PaintContext& context, PaintPhase phase) const +{ + if (!is_visible()) + return; + reset_scroll_offset(context, phase); + if (!has_css_transform()) { + clear_clip_overflow_rect(context, phase); + } +} + Layout::SVGSVGBox const& SVGSVGPaintable::layout_box() const { return static_cast(layout_node()); diff --git a/Libraries/LibWeb/Painting/SVGSVGPaintable.h b/Libraries/LibWeb/Painting/SVGSVGPaintable.h index 7a37c971d86..0fe68f64433 100644 --- a/Libraries/LibWeb/Painting/SVGSVGPaintable.h +++ b/Libraries/LibWeb/Painting/SVGSVGPaintable.h @@ -23,6 +23,9 @@ public: static void paint_svg_box(PaintContext& context, PaintableBox const& svg_box, PaintPhase phase); static void paint_descendants(PaintContext& context, PaintableBox const& paintable, PaintPhase phase); + virtual void before_paint(PaintContext&, PaintPhase) const override; + virtual void after_paint(PaintContext&, PaintPhase) const override; + protected: SVGSVGPaintable(Layout::SVGSVGBox const&);