mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-31 21:29:06 +00:00
LibWeb: Apply clip rect before painting background and foreground items
This commit is contained in:
parent
6584ae0080
commit
212d748ded
Notes:
github-actions[bot]
2025-06-24 11:58:05 +00:00
Author: https://github.com/tcl3
Commit: 212d748ded
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5185
Reviewed-by: https://github.com/AtkinsSJ ✅
13 changed files with 217 additions and 12 deletions
|
@ -79,6 +79,9 @@ public:
|
||||||
virtual void apply_scroll_offset(PaintContext&, PaintPhase) const { }
|
virtual void apply_scroll_offset(PaintContext&, PaintPhase) const { }
|
||||||
virtual void reset_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 apply_clip_overflow_rect(PaintContext&, PaintPhase) const { }
|
||||||
virtual void clear_clip_overflow_rect(PaintContext&, PaintPhase) const { }
|
virtual void clear_clip_overflow_rect(PaintContext&, PaintPhase) const { }
|
||||||
|
|
||||||
|
|
|
@ -326,6 +326,8 @@ void PaintableBox::before_paint(PaintContext& context, [[maybe_unused]] PaintPha
|
||||||
if (!is_visible())
|
if (!is_visible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
apply_own_clip_rect(context, phase);
|
||||||
|
|
||||||
if (!has_css_transform()) {
|
if (!has_css_transform()) {
|
||||||
apply_clip_overflow_rect(context, phase);
|
apply_clip_overflow_rect(context, phase);
|
||||||
}
|
}
|
||||||
|
@ -337,6 +339,8 @@ void PaintableBox::after_paint(PaintContext& context, [[maybe_unused]] PaintPhas
|
||||||
if (!is_visible())
|
if (!is_visible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
clear_own_clip_rect(context, phase);
|
||||||
|
|
||||||
reset_scroll_offset(context, phase);
|
reset_scroll_offset(context, phase);
|
||||||
if (!has_css_transform()) {
|
if (!has_css_transform()) {
|
||||||
clear_clip_overflow_rect(context, phase);
|
clear_clip_overflow_rect(context, phase);
|
||||||
|
@ -651,6 +655,38 @@ void PaintableBox::clear_clip_overflow_rect(PaintContext& context, PaintPhase ph
|
||||||
restore_clip(context, enclosing_clip_frame());
|
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<SVGPaintable>(*this) || is<SVGSVGPaintable>(*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<SVGPaintable>(*this) || is<SVGSVGPaintable>(*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)
|
void paint_cursor_if_needed(PaintContext& context, TextPaintable const& paintable, PaintableFragment const& fragment)
|
||||||
{
|
{
|
||||||
auto const& navigable = *paintable.navigable();
|
auto const& navigable = *paintable.navigable();
|
||||||
|
@ -870,12 +906,7 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const
|
||||||
|
|
||||||
PaintableBox::paint(context, phase);
|
PaintableBox::paint(context, phase);
|
||||||
|
|
||||||
if (own_clip_frame()) {
|
apply_own_clip_rect(context, phase);
|
||||||
apply_clip(context, own_clip_frame());
|
|
||||||
if (own_scroll_frame_id().has_value()) {
|
|
||||||
context.display_list_recorder().push_scroll_frame_id(own_scroll_frame_id().value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Text shadows
|
// Text shadows
|
||||||
// This is yet another loop, but done here because all shadows should appear under all text.
|
// This is yet another loop, but done here because all shadows should appear under all text.
|
||||||
|
@ -899,12 +930,7 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const
|
||||||
paint_text_fragment(context, static_cast<TextPaintable const&>(fragment.paintable()), fragment, phase);
|
paint_text_fragment(context, static_cast<TextPaintable const&>(fragment.paintable()), fragment, phase);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (own_clip_frame()) {
|
clear_own_clip_rect(context, phase);
|
||||||
if (own_scroll_frame_id().has_value()) {
|
|
||||||
context.display_list_recorder().pop_scroll_frame_id();
|
|
||||||
}
|
|
||||||
restore_clip(context, own_clip_frame());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Paintable::DispatchEventOfSameName PaintableBox::handle_mousedown(Badge<EventHandler>, CSSPixelPoint position, unsigned, unsigned)
|
Paintable::DispatchEventOfSameName PaintableBox::handle_mousedown(Badge<EventHandler>, CSSPixelPoint position, unsigned, unsigned)
|
||||||
|
|
|
@ -142,6 +142,9 @@ public:
|
||||||
virtual void apply_clip_overflow_rect(PaintContext&, PaintPhase) const override;
|
virtual void apply_clip_overflow_rect(PaintContext&, PaintPhase) const override;
|
||||||
virtual void clear_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<TraversalDecision(HitTestResult)> const& callback) const override;
|
[[nodiscard]] virtual TraversalDecision hit_test(CSSPixelPoint position, HitTestType type, Function<TraversalDecision(HitTestResult)> const& callback) const override;
|
||||||
Optional<HitTestResult> hit_test(CSSPixelPoint, HitTestType) const;
|
Optional<HitTestResult> hit_test(CSSPixelPoint, HitTestType) const;
|
||||||
[[nodiscard]] TraversalDecision hit_test_continuation(Function<TraversalDecision(HitTestResult)> const& callback) const;
|
[[nodiscard]] TraversalDecision hit_test_continuation(Function<TraversalDecision(HitTestResult)> const& callback) const;
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CSS Reftest Reference</title>
|
||||||
|
<link rel="author" title="Dirk Schulze" href="mailto:dschulze@adobe.com">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>The test passes if there is a green square and no red.</p>
|
||||||
|
<div style="width: 200px; height: 200px; background-color: green;"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CSS Reftest Reference</title>
|
||||||
|
<link rel="author" title="Dirk Schulze" href="mailto:dschulze@adobe.com">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>The test passes if there is a green square with a blue border.</p>
|
||||||
|
<div style="width: 100px; height: 100px; border: solid blue 50px; background-color: green;"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,64 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
|
||||||
|
<title>CSS Test: clip - auto value</title>
|
||||||
|
|
||||||
|
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
|
||||||
|
<link rel="author" title="Vasil Dinkov" href="http://www.vadikom.com/" />
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/CSS21/visufx.html#clipping" />
|
||||||
|
<link rel="match" href="../../../../../expected/wpt-import/css/CSS2/visufx/../reference/ref-filled-green-100px-square.xht" />
|
||||||
|
|
||||||
|
<meta content="dom" name="flags" />
|
||||||
|
<meta content="An element must not clip when clip is set to auto." name="assert" />
|
||||||
|
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
||||||
|
|
||||||
|
<style type="text/css"><![CDATA[
|
||||||
|
#red-overlapped-layer
|
||||||
|
{
|
||||||
|
background-color: red;
|
||||||
|
height: 100px;
|
||||||
|
position: absolute;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#red-parent
|
||||||
|
{
|
||||||
|
background-color: red;
|
||||||
|
clip: rect(0, 1px, 1px, 0);
|
||||||
|
height: 2px;
|
||||||
|
position: absolute;
|
||||||
|
width: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#green-child
|
||||||
|
{
|
||||||
|
background-color: green;
|
||||||
|
height: 100px;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
]]></style>
|
||||||
|
|
||||||
|
<script type="text/javascript"><![CDATA[
|
||||||
|
function startTest()
|
||||||
|
{
|
||||||
|
document.getElementById("red-parent").style.clip = "auto";
|
||||||
|
}
|
||||||
|
]]></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body onload="startTest();">
|
||||||
|
|
||||||
|
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||||
|
|
||||||
|
<div id="red-overlapped-layer"></div>
|
||||||
|
|
||||||
|
<div id="red-parent">
|
||||||
|
<div id="green-child"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title>CSS Test: Clip using pixels with a zero value, 0px</title>
|
||||||
|
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/CSS21/visufx.html#propdef-clip" />
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/CSS21/visufx.html#clipping" />
|
||||||
|
<link rel="match" href="../../../../../expected/wpt-import/css/CSS2/visufx/../reference/no-red-on-blank-page-ref.xht"/>
|
||||||
|
<meta name="assert" content="The 'clip' property sets a zero value, in pixels, for all sides of the clipping rectangle." />
|
||||||
|
<style type="text/css">
|
||||||
|
div
|
||||||
|
{
|
||||||
|
background: red;
|
||||||
|
clip: rect(0px, 0px, 0px, 0px);
|
||||||
|
height: 1in;
|
||||||
|
position: absolute;
|
||||||
|
width: 1in;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Test passes if there is no red visible on the page.</p>
|
||||||
|
<div></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title>CSS Test: Clip using pixels with a nominal value, 96px</title>
|
||||||
|
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/CSS21/visufx.html#propdef-clip" />
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/CSS21/visufx.html#clipping" />
|
||||||
|
<link rel="match" href="../../../../../expected/wpt-import/css/CSS2/visufx/../reference/no-red-on-blank-page-ref.xht"/>
|
||||||
|
<meta name="assert" content="The 'clip' property sets a value of ninety-six pixels, for all sides of the clipping rectangle." />
|
||||||
|
<style type="text/css">
|
||||||
|
div
|
||||||
|
{
|
||||||
|
background: red;
|
||||||
|
clip: rect(96px, 96px, 96px, 96px);
|
||||||
|
height: 3in;
|
||||||
|
position: absolute;
|
||||||
|
width: 3in;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Test passes if there is no red visible on the page.</p>
|
||||||
|
<div></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,19 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CSS Masking: Test clip property does not clip on with negative values - 1</title>
|
||||||
|
<link rel="author" title="Dirk Schulze" href="mailto:dschulze@adobe.com">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css-masking-1/#clipping-paths">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css-masking-1/#clip-property">
|
||||||
|
<link rel="match" href="../../../../../expected/wpt-import/css/css-masking/clip/reference/clip-full-ref.html">
|
||||||
|
<meta name="assert" content="Negative values are permitted on rect function
|
||||||
|
for clip. Test that whole element is clipped if bottom edge is before top
|
||||||
|
edge. On pass you should see a green square and no red.">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>The test passes if there is a green square and no red.</p>
|
||||||
|
<div style="background-color: green; width: 200px; height: 200px;">
|
||||||
|
<div style="width: 200px; height: 200px; background-color: red; position: absolute; clip: rect(0, -50px, 200px, 50px);"></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CSS Masking: Test clip property with rect function and auto values clip to border box - 2</title>
|
||||||
|
<link rel="author" title="Dirk Schulze" href="mailto:dschulze@adobe.com">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css-masking-1/#clipping-paths">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css-masking-1/#clip-property">
|
||||||
|
<link rel="match" href="../../../../../expected/wpt-import/css/css-masking/clip/reference/clip-no-clipping-ref.html">
|
||||||
|
<meta name="assert" content="A value of 'auto' in the rect function is
|
||||||
|
equal to the certain edge of the border box. The box shadow should be
|
||||||
|
clipped, since it is painted outside the border box. On pass you should see
|
||||||
|
a green square with a blue border.">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>The test passes if there is a green square with a blue border.</p>
|
||||||
|
<div style="width: 100px; height: 100px; border: solid blue 50px; background-color: green; position: absolute; clip: rect(auto, auto, auto, auto); box-shadow: 0 0 10px red;"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Binary file not shown.
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Binary file not shown.
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 91 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 6.3 KiB |
Loading…
Add table
Add a link
Reference in a new issue