LibWeb: Apply own clip rect for background phase only when clip used

Fixes a bug where we would clip `box-shadow` when `overflow: hidden`
was set, which is not supposed to happen since `overflow` only affects
clipping of an element's content.
This commit is contained in:
Aliaksandr Kalenik 2025-11-19 04:21:10 +01:00 committed by Jelle Raaijmakers
parent e816a92dfe
commit 597fe8288c
Notes: github-actions[bot] 2025-11-19 17:19:01 +00:00
10 changed files with 48 additions and 6 deletions

View file

@ -26,6 +26,8 @@ struct WEB_API ClipFrame : public AtomicRefCounted<ClipFrame> {
CSSPixelRect clip_rect_for_hit_testing() const;
bool includes_rect_from_clip_property { false };
private:
Vector<ClipRectWithScrollFrame> m_clip_rects;
};

View file

@ -332,11 +332,20 @@ void PaintableBox::before_paint(DisplayListRecordingContext& context, PaintPhase
if (!is_visible())
return;
if (first_is_one_of(phase, PaintPhase::Background, PaintPhase::Foreground) && own_clip_frame()) {
context.display_list_recorder().push_clip_frame(own_clip_frame());
auto const& own_clip_frame = this->own_clip_frame();
bool apply_own_clip_frame = [&] {
if (phase == PaintPhase::Background)
return own_clip_frame && own_clip_frame->includes_rect_from_clip_property;
if (phase == PaintPhase::Foreground)
return !own_clip_frame.is_null();
return false;
}();
if (apply_own_clip_frame) {
context.display_list_recorder().push_clip_frame(own_clip_frame);
} else if (!has_css_transform()) {
apply_clip_overflow_rect(context, phase);
}
apply_scroll_offset(context);
}
@ -346,7 +355,16 @@ void PaintableBox::after_paint(DisplayListRecordingContext& context, PaintPhase
return;
reset_scroll_offset(context);
if (first_is_one_of(phase, PaintPhase::Background, PaintPhase::Foreground) && own_clip_frame()) {
auto const& own_clip_frame = this->own_clip_frame();
bool reset_own_clip_frame = [&] {
if (phase == PaintPhase::Background)
return own_clip_frame && own_clip_frame->includes_rect_from_clip_property;
if (phase == PaintPhase::Foreground)
return !own_clip_frame.is_null();
return false;
}();
if (reset_own_clip_frame) {
context.display_list_recorder().pop_clip_frame();
} else if (!has_css_transform()) {
clear_clip_overflow_rect(context, phase);

View file

@ -167,6 +167,7 @@ void ViewportPaintable::assign_clip_frames()
auto clip_rect = block_paintable_box.overflow_clip_edge_rect();
if (block_paintable_box.get_clip_rect().has_value()) {
clip_frame.includes_rect_from_clip_property = true;
clip_rect.intersect(block_paintable_box.get_clip_rect().value());
clip_x = true;
clip_y = true;

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<link rel="match" href="../expected/box-shadow-with-overflow-hidden-ref.html" />
<!DOCTYPE html><style>
.box {
background-color: black;
width: 100px;
height: 100px;
box-shadow: 12px 12px 2px 1px red;
}
</style><div class="box"></div>

View file

@ -0,0 +1,11 @@
<!DOCTYPE html>
<link rel="match" href="../expected/box-shadow-with-overflow-hidden-ref.html" />
<!DOCTYPE html><style>
.box {
overflow: clip;
background-color: black;
width: 100px;
height: 100px;
box-shadow: 12px 12px 2px 1px red;
}
</style><div class="box"></div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Before After
Before After

View file

@ -1,6 +1,6 @@
<!DOCTYPE html>
<link rel="match" href="../expected/color-scheme-ref.html" />
<meta name="fuzzy" content="maxDifference=0-3;totalPixels=0-4638">
<meta name="fuzzy" content="maxDifference=0-3;totalPixels=0-4660">
<style>
body>div>div {
padding: 1em;

View file

@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<title>CSS Background Tests</title>
<link rel="match" href="../expected/css-backgrounds-ref.html" />
<meta name="fuzzy" content="maxDifference=0-21;totalPixels=0-72032">
<meta name="fuzzy" content="maxDifference=0-21;totalPixels=0-72122">
<style>
.box {
width: 180px;

View file

@ -1,6 +1,6 @@
<!DOCTYPE html>
<link rel="match" href="../expected/nested-boxes-with-hidden-overflow-and-border-radius-ref.html" />
<meta name="fuzzy" content="maxDifference=0-1;totalPixels=0-153">
<meta name="fuzzy" content="maxDifference=0-2;totalPixels=0-301">
<style>
.outer {
overflow: hidden;