From 94491ead67fe496358bade432a679a4f24b983a0 Mon Sep 17 00:00:00 2001 From: zhiyuang Date: Mon, 24 Jul 2023 19:09:34 +0800 Subject: [PATCH] LibWeb: Fix border painting with border-radius and zero-width sides When joined border width is zero width, then the midpoint of the joined corner is no longer need to be computed anymore. Just set the mid point to be the endpoint of the corner. --- Base/res/html/misc/border-radius.html | 22 +++++ .../LibWeb/Painting/BorderPainting.cpp | 90 ++++++++++--------- 2 files changed, 71 insertions(+), 41 deletions(-) diff --git a/Base/res/html/misc/border-radius.html b/Base/res/html/misc/border-radius.html index bae2b9334d..5502d26089 100644 --- a/Base/res/html/misc/border-radius.html +++ b/Base/res/html/misc/border-radius.html @@ -70,6 +70,22 @@ border-left: 20px solid blue; } + .box-1-13 { + border-radius: 15px; + border-color: black; + border: 3px solid black; + border-top-width: 0; + border-bottom-width: 0; + } + + .box-1-14 { + border-radius: 15px; + border-color: black; + border: 3px solid black; + border-left-width: 0; + border-right-width: 0; + } + .box-3 { border: 1px solid black; border-top-right-radius: 10px; @@ -418,6 +434,12 @@ Four border with different colors

+ Border radius with top and bottom zero width +
+
+ Border radius with left and right zero width +
+
top-left 10px

diff --git a/Userland/Libraries/LibWeb/Painting/BorderPainting.cpp b/Userland/Libraries/LibWeb/Painting/BorderPainting.cpp index 303712664d..e9d204d5df 100644 --- a/Userland/Libraries/LibWeb/Painting/BorderPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/BorderPainting.cpp @@ -205,10 +205,22 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& } }; - auto compute_midpoint = [](int horizontal_radius, int vertical_radius) { + auto compute_midpoint = [&](int horizontal_radius, int vertical_radius, int joined_border_width) { if (horizontal_radius == 0 && vertical_radius == 0) { return Gfx::FloatPoint(0, 0); } + if (joined_border_width == 0) { + switch (edge) { + case BorderEdge::Top: + case BorderEdge::Bottom: + return Gfx::FloatPoint(horizontal_radius, 0); + case BorderEdge::Right: + case BorderEdge::Left: + return Gfx::FloatPoint(0, vertical_radius); + default: + VERIFY_NOT_REACHED(); + } + } // FIXME: this middle point rule seems not exacly the same as main browsers // compute the midpoint based on point whose tangent slope of 1 // https://math.stackexchange.com/questions/3325134/find-the-points-on-the-ellipse-where-the-slope-of-the-tangent-line-is-1 @@ -235,17 +247,14 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& Gfx::FloatPoint joined_corner_endpoint_offset; Gfx::FloatPoint opposite_joined_border_corner_offset; - if (borders_data.left.width == 0) { - joined_corner_endpoint_offset = Gfx::FloatPoint(-radius.horizontal_radius, radius.vertical_radius); - } else { - auto midpoint = compute_midpoint(radius.horizontal_radius, radius.vertical_radius); + + { + auto midpoint = compute_midpoint(radius.horizontal_radius, radius.vertical_radius, joined_border_width.value()); joined_corner_endpoint_offset = Gfx::FloatPoint(-midpoint.x(), radius.vertical_radius - midpoint.y()); } - if (borders_data.right.width == 0) { - opposite_joined_border_corner_offset = Gfx::FloatPoint(opposite_radius.horizontal_radius, opposite_radius.vertical_radius); - } else { - auto midpoint = compute_midpoint(opposite_radius.horizontal_radius, opposite_radius.vertical_radius); + { + auto midpoint = compute_midpoint(opposite_radius.horizontal_radius, opposite_radius.vertical_radius, opposite_joined_border_width.value()); opposite_joined_border_corner_offset = Gfx::FloatPoint(midpoint.x(), opposite_radius.vertical_radius - midpoint.y()); } @@ -256,7 +265,8 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& if (joined_corner_has_inner_corner) { Gfx::FloatPoint midpoint = compute_midpoint( radius.horizontal_radius - joined_border_width.value(), - radius.vertical_radius - device_pixel_width.value()); + radius.vertical_radius - device_pixel_width.value(), + joined_border_width.value()); Gfx::FloatPoint inner_corner_endpoint_offset = Gfx::FloatPoint( -midpoint.x(), radius.vertical_radius - device_pixel_width.value() - midpoint.y()); @@ -272,7 +282,8 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& if (opposite_joined_corner_has_inner_corner) { Gfx::FloatPoint midpoint = compute_midpoint( opposite_radius.horizontal_radius - opposite_joined_border_width.value(), - opposite_radius.vertical_radius - device_pixel_width.value()); + opposite_radius.vertical_radius - device_pixel_width.value(), + opposite_joined_border_width.value()); Gfx::FloatPoint inner_corner_endpoint_offset = Gfx::FloatPoint( midpoint.x(), opposite_radius.vertical_radius - device_pixel_width.value() - midpoint.y()); @@ -305,17 +316,14 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& Gfx::FloatPoint joined_corner_endpoint_offset; Gfx::FloatPoint opposite_joined_border_corner_offset; - if (borders_data.top.width == 0) { - joined_corner_endpoint_offset = Gfx::FloatPoint(-radius.horizontal_radius, -radius.vertical_radius); - } else { - auto midpoint = compute_midpoint(radius.horizontal_radius, radius.vertical_radius); + + { + auto midpoint = compute_midpoint(radius.horizontal_radius, radius.vertical_radius, joined_border_width.value()); joined_corner_endpoint_offset = Gfx::FloatPoint(midpoint.x() - radius.horizontal_radius, -midpoint.y()); } - if (borders_data.bottom.width == 0) { - opposite_joined_border_corner_offset = Gfx::FloatPoint(-opposite_radius.horizontal_radius, opposite_radius.vertical_radius); - } else { - auto midpoint = compute_midpoint(opposite_radius.horizontal_radius, opposite_radius.vertical_radius); + { + auto midpoint = compute_midpoint(opposite_radius.horizontal_radius, opposite_radius.vertical_radius, opposite_joined_border_width.value()); opposite_joined_border_corner_offset = Gfx::FloatPoint(midpoint.x() - opposite_radius.horizontal_radius, midpoint.y()); } @@ -326,7 +334,8 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& if (joined_corner_has_inner_corner) { auto midpoint = compute_midpoint( radius.horizontal_radius - device_pixel_width.value(), - radius.vertical_radius - joined_border_width.value()); + radius.vertical_radius - joined_border_width.value(), + joined_border_width.value()); Gfx::FloatPoint inner_corner = Gfx::FloatPoint( -(radius.horizontal_radius - midpoint.x() - device_pixel_width.value()), -midpoint.y()); @@ -340,7 +349,8 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& if (opposite_joined_corner_has_inner_corner) { auto midpoint = compute_midpoint( opposite_radius.horizontal_radius - device_pixel_width.value(), - opposite_radius.vertical_radius - opposite_joined_border_width.value()); + opposite_radius.vertical_radius - opposite_joined_border_width.value(), + opposite_joined_border_width.value()); Gfx::FloatPoint inner_corner = Gfx::FloatPoint( -(opposite_radius.horizontal_radius - midpoint.x() - device_pixel_width.value()), midpoint.y()); @@ -371,17 +381,14 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& Gfx::FloatPoint joined_corner_endpoint_offset; Gfx::FloatPoint opposite_joined_border_corner_offset; - if (borders_data.right.width == 0) { - joined_corner_endpoint_offset = Gfx::FloatPoint(radius.horizontal_radius, -radius.vertical_radius); - } else { - auto midpoint = compute_midpoint(radius.horizontal_radius, radius.vertical_radius); + + { + auto midpoint = compute_midpoint(radius.horizontal_radius, radius.vertical_radius, joined_border_width.value()); joined_corner_endpoint_offset = Gfx::FloatPoint(midpoint.x(), midpoint.y() - radius.vertical_radius); } - if (borders_data.left.width == 0) { - opposite_joined_border_corner_offset = Gfx::FloatPoint(-opposite_radius.horizontal_radius, -opposite_radius.vertical_radius); - } else { - auto midpoint = compute_midpoint(opposite_radius.horizontal_radius, opposite_radius.vertical_radius); + { + auto midpoint = compute_midpoint(opposite_radius.horizontal_radius, opposite_radius.vertical_radius, opposite_joined_border_width.value()); opposite_joined_border_corner_offset = Gfx::FloatPoint(-midpoint.x(), midpoint.y() - opposite_radius.vertical_radius); } @@ -392,7 +399,8 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& if (joined_corner_has_inner_corner) { auto midpoint = compute_midpoint( radius.horizontal_radius - joined_border_width.value(), - radius.vertical_radius - device_pixel_width.value()); + radius.vertical_radius - device_pixel_width.value(), + joined_border_width.value()); Gfx::FloatPoint inner_corner = Gfx::FloatPoint(midpoint.x(), -(radius.vertical_radius - midpoint.y() - device_pixel_width.value())); points.append(Gfx::FloatPoint(rect.top_right().to_type()) + inner_corner); points.append(Gfx::FloatPoint(rect.top_right().to_type())); @@ -404,7 +412,8 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& if (opposite_joined_corner_has_inner_corner) { auto midpoint = compute_midpoint( opposite_radius.horizontal_radius - opposite_joined_border_width.value(), - opposite_radius.vertical_radius - device_pixel_width.value()); + opposite_radius.vertical_radius - device_pixel_width.value(), + opposite_joined_border_width.value()); Gfx::FloatPoint inner_corner = Gfx::FloatPoint( -midpoint.x(), -(opposite_radius.vertical_radius - midpoint.y() - device_pixel_width.value())); @@ -434,17 +443,14 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& Gfx::FloatPoint joined_corner_endpoint_offset; Gfx::FloatPoint opposite_joined_border_corner_offset; - if (borders_data.bottom.width == 0) { - joined_corner_endpoint_offset = Gfx::FloatPoint(radius.horizontal_radius, radius.vertical_radius); - } else { - auto midpoint = compute_midpoint(radius.horizontal_radius, radius.vertical_radius); + + { + auto midpoint = compute_midpoint(radius.horizontal_radius, radius.vertical_radius, joined_border_width.value()); joined_corner_endpoint_offset = Gfx::FloatPoint(radius.horizontal_radius - midpoint.x(), midpoint.y()); } - if (borders_data.top.width == 0) { - opposite_joined_border_corner_offset = Gfx::FloatPoint(opposite_radius.horizontal_radius, opposite_radius.vertical_radius); - } else { - auto midpoint = compute_midpoint(opposite_radius.horizontal_radius, opposite_radius.vertical_radius); + { + auto midpoint = compute_midpoint(opposite_radius.horizontal_radius, opposite_radius.vertical_radius, opposite_joined_border_width.value()); opposite_joined_border_corner_offset = Gfx::FloatPoint(opposite_radius.horizontal_radius - midpoint.x(), -midpoint.y()); } @@ -455,7 +461,8 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& if (joined_corner_has_inner_corner) { auto midpoint = compute_midpoint( radius.horizontal_radius - device_pixel_width.value(), - radius.vertical_radius - joined_border_width.value()); + radius.vertical_radius - joined_border_width.value(), + joined_border_width.value()); Gfx::FloatPoint inner_corner = Gfx::FloatPoint(radius.horizontal_radius - device_pixel_width.value() - midpoint.x(), midpoint.y()); points.append(Gfx::FloatPoint(rect.bottom_right().to_type()) + inner_corner); points.append(Gfx::FloatPoint(rect.bottom_right().to_type())); @@ -467,7 +474,8 @@ void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& if (opposite_joined_corner_has_inner_corner) { auto midpoint = compute_midpoint( opposite_radius.horizontal_radius - device_pixel_width.value(), - opposite_radius.vertical_radius - opposite_joined_border_width.value()); + opposite_radius.vertical_radius - opposite_joined_border_width.value(), + opposite_joined_border_width.value()); Gfx::FloatPoint inner_corner = Gfx::FloatPoint( opposite_radius.horizontal_radius - device_pixel_width.value() - midpoint.x(), -midpoint.y());