From 6038e3625063589ab9a4267edc52683262f6b086 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Sun, 30 Jul 2023 16:15:38 +0100 Subject: [PATCH] LibWeb: Add and use the "snap a length as a border width" algorithm Previously, we always rounded border-widths up when converting them to device pixels. However, the spec asks us to follow a specific algorithm to "snap" these values, so that the computed value is snapped. The difference from before, is that widths of between 0 and 1 device pixels are rounded up to 1, and and values larger than 1 are rounded down. --- .../css-snap-a-length-as-a-border-width.txt | 5 ++++ .../css-snap-a-length-as-a-border-width.html | 14 +++++++++++ Userland/Libraries/LibWeb/Layout/Node.cpp | 24 ++++++++++++++++++- 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 Tests/LibWeb/Layout/expected/css-snap-a-length-as-a-border-width.txt create mode 100644 Tests/LibWeb/Layout/input/css-snap-a-length-as-a-border-width.html diff --git a/Tests/LibWeb/Layout/expected/css-snap-a-length-as-a-border-width.txt b/Tests/LibWeb/Layout/expected/css-snap-a-length-as-a-border-width.txt new file mode 100644 index 0000000000..fc12265f91 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/css-snap-a-length-as-a-border-width.txt @@ -0,0 +1,5 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x600 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x204 children: not-inline + BlockContainer at (9,9) content-size 100x100 children: not-inline + BlockContainer at (9,111) content-size 100x100 children: not-inline diff --git a/Tests/LibWeb/Layout/input/css-snap-a-length-as-a-border-width.html b/Tests/LibWeb/Layout/input/css-snap-a-length-as-a-border-width.html new file mode 100644 index 0000000000..95620df759 --- /dev/null +++ b/Tests/LibWeb/Layout/input/css-snap-a-length-as-a-border-width.html @@ -0,0 +1,14 @@ +
\ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index 95d9e1da43..6284f85c50 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -289,6 +289,28 @@ NodeWithStyle::NodeWithStyle(DOM::Document& document, DOM::Node* node, CSS::Comp m_font = Platform::FontPlugin::the().default_font(); } +// https://www.w3.org/TR/css-values-4/#snap-a-length-as-a-border-width +static CSSPixels snap_a_length_as_a_border_width(double device_pixels_per_css_pixel, CSSPixels length) +{ + // 1. Assert: len is non-negative. + VERIFY(length >= 0); + + // 2. If len is an integer number of device pixels, do nothing. + auto device_pixels = length.to_double() * device_pixels_per_css_pixel; + if (device_pixels == trunc(device_pixels)) + return length; + + // 3. If len is greater than zero, but less than 1 device pixel, round len up to 1 device pixel. + if (device_pixels > 0 && device_pixels < 1) + return 1 / device_pixels_per_css_pixel; + + // 4. If len is greater than 1 device pixel, round it down to the nearest integer number of device pixels. + if (device_pixels > 1) + return floor(device_pixels) / device_pixels_per_css_pixel; + + return length; +} + void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style) { auto& computed_values = static_cast(m_computed_values); @@ -676,7 +698,7 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style) VERIFY_NOT_REACHED(); }; - border.width = resolve_border_width(); + border.width = snap_a_length_as_a_border_width(document().page()->client().device_pixels_per_css_pixel(), resolve_border_width()); } };