diff --git a/Userland/Libraries/LibWeb/Painting/Paintable.h b/Userland/Libraries/LibWeb/Painting/Paintable.h index bbef8388b0..49e97f5316 100644 --- a/Userland/Libraries/LibWeb/Painting/Paintable.h +++ b/Userland/Libraries/LibWeb/Painting/Paintable.h @@ -109,6 +109,9 @@ public: return TraversalDecision::Continue; } + virtual void before_paint(PaintContext&, PaintPhase) const { } + virtual void after_paint(PaintContext&, PaintPhase) const { } + virtual void paint(PaintContext&, PaintPhase) const { } virtual void before_children_paint(PaintContext&, PaintPhase) const { } diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index 790a5a0216..e0b24e9737 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -176,6 +176,37 @@ StackingContext* PaintableBox::enclosing_stacking_context() VERIFY_NOT_REACHED(); } +Optional PaintableBox::get_clip_rect() const +{ + auto clip = computed_values().clip(); + if (clip.is_rect() && layout_box().is_absolutely_positioned()) { + auto border_box = absolute_border_box_rect(); + return clip.to_rect().resolved(layout_node(), border_box.to_type()).to_type(); + } + return {}; +} + +void PaintableBox::before_paint(PaintContext& context, [[maybe_unused]] PaintPhase phase) const +{ + if (!is_visible()) + return; + + auto clip_rect = get_clip_rect(); + if (clip_rect.has_value()) { + context.painter().save(); + context.painter().add_clip_rect(clip_rect->to_type()); + } +} + +void PaintableBox::after_paint(PaintContext& context, [[maybe_unused]] PaintPhase phase) const +{ + if (!is_visible()) + return; + + if (get_clip_rect().has_value()) + context.painter().restore(); +} + void PaintableBox::paint(PaintContext& context, PaintPhase phase) const { if (!is_visible()) @@ -424,15 +455,12 @@ void PaintableBox::apply_clip_overflow_rect(PaintContext& context, PaintPhase ph auto overflow_x = computed_values().overflow_x(); auto overflow_y = computed_values().overflow_y(); - auto clip = computed_values().clip(); - if (clip.is_rect() && layout_box().is_absolutely_positioned()) { - auto border_box = absolute_border_box_rect(); - auto resolved_clip_rect = clip.to_rect().resolved(layout_node(), border_box.to_type()).to_type(); - if (clip_rect.has_value()) { - clip_rect->intersect(resolved_clip_rect); - } else { - clip_rect = resolved_clip_rect; - } + auto css_clip_property = get_clip_rect(); + if (css_clip_property.has_value()) { + if (clip_rect.has_value()) + clip_rect->intersect(css_clip_property.value()); + else + clip_rect = css_clip_property.value(); } if (!clip_rect.has_value()) diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.h b/Userland/Libraries/LibWeb/Painting/PaintableBox.h index 93dadf055c..b20d38d7c7 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.h @@ -20,6 +20,9 @@ public: static JS::NonnullGCPtr create(Layout::Box const&); virtual ~PaintableBox(); + virtual void before_paint(PaintContext&, PaintPhase) const override; + virtual void after_paint(PaintContext&, PaintPhase) const override; + virtual void paint(PaintContext&, PaintPhase) const override; bool is_visible() const { return layout_box().is_visible(); } @@ -186,6 +189,8 @@ public: protected: explicit PaintableBox(Layout::Box const&); + Optional get_clip_rect() const; + virtual void paint_border(PaintContext&) const; virtual void paint_backdrop_filter(PaintContext&) const; virtual void paint_background(PaintContext&) const; diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp index ec41ec7dfd..5772adf34a 100644 --- a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp +++ b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp @@ -26,7 +26,9 @@ namespace Web::Painting { static void paint_node(Paintable const& paintable, PaintContext& context, PaintPhase phase) { + paintable.before_paint(context, phase); paintable.paint(context, phase); + paintable.after_paint(context, phase); } StackingContext::StackingContext(PaintableBox& paintable_box, StackingContext* parent, size_t index_in_tree_order)