LibWeb: Maintain rect positioning when rounding to device pixel rects

When rounding a CSSPixelRect to a DevicePixelRect, we simply pulled its
width and height through round() and called it a day. Unfortunately this
could negatively affect the rect's perceived positioning.

A rect at { 0.5, 0.0 } with size { 19.5 x 20.0 } should have its right
edge at position 20, but after rounding it would end up at { 1, 0 } with
size { 20 x 20 }, causing its right edge to be at position 21 instead.

Fix this by first rounding the right and bottom edges of the input rect,
and then determining the dimensions by subtracting its rounded position.

Fixes #245.
This commit is contained in:
Jelle Raaijmakers 2025-08-19 13:34:57 +02:00 committed by Jelle Raaijmakers
commit 0cf6bd0324
Notes: github-actions[bot] 2025-08-19 19:55:08 +00:00
7 changed files with 43 additions and 7 deletions

View file

@ -58,12 +58,10 @@ public:
DevicePixelRect rounded_device_rect(CSSPixelRect rect) const
{
return {
round(rect.x().to_double() * m_device_pixels_per_css_pixel),
round(rect.y().to_double() * m_device_pixels_per_css_pixel),
round(rect.width().to_double() * m_device_pixels_per_css_pixel),
round(rect.height().to_double() * m_device_pixels_per_css_pixel)
};
auto scaled_rect = rect.to_type<double>().scaled(m_device_pixels_per_css_pixel);
auto x = round(scaled_rect.x());
auto y = round(scaled_rect.y());
return { x, y, round(scaled_rect.right()) - x, round(scaled_rect.bottom()) - y };
}
DevicePixelSize enclosing_device_size(CSSPixelSize size) const

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 90 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Before After
Before After

View file

@ -1,6 +1,6 @@
<!doctype html>
<link rel="match" href="../expected/svg-background-no-natural-size-ref.html" />
<meta name="fuzzy" content="maxDifference=0-2;totalPixels=0-455">
<meta name="fuzzy" content="maxDifference=0-3;totalPixels=0-472">
<style>
body {
background-color: white;

View file

@ -0,0 +1,12 @@
SaveLayer
PushStackingContext opacity=1 isolate=false has_clip_path=false transform=[1 0 0 1 0 0]
PushStackingContext opacity=1 isolate=false has_clip_path=false transform=[1 0 0 1 0 0]
FillRect rect=[8,8 29x30] color=rgb(0, 0, 0)
FillRect rect=[38,8 28x30] color=rgb(0, 0, 0)
FillRect rect=[67,8 29x30] color=rgb(0, 0, 0)
FillRect rect=[97,8 28x30] color=rgb(0, 0, 0)
FillRect rect=[126,8 29x30] color=rgb(0, 0, 0)
PopStackingContext
PopStackingContext
Restore

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<style>
.a {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 1px;
width: 147px;
}
.b {
background-color: black;
height: 30px;
}
</style>
<div class="a">
<div class="b"></div>
<div class="b"></div>
<div class="b"></div>
<div class="b"></div>
<div class="b"></div>
</div>
<script src="../include.js"></script>
<script>
test(() => {
println(internals.dumpDisplayList());
});
</script>