From 333c9270b134cde592821fc8b24f49541df8319c Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Mon, 29 Jul 2024 18:13:13 +0300 Subject: [PATCH] LibWeb: Simplify outer box shadow's bounding box calculation There is no need in the overly complicated OuterBoxShadowMetrics after switching to use Skia for painting. --- .../Libraries/LibWeb/Painting/Command.cpp | 8 +- .../LibWeb/Painting/ShadowPainting.cpp | 236 ------------------ .../LibWeb/Painting/ShadowPainting.h | 2 - 3 files changed, 7 insertions(+), 239 deletions(-) diff --git a/Userland/Libraries/LibWeb/Painting/Command.cpp b/Userland/Libraries/LibWeb/Painting/Command.cpp index fd734114d4e..f745bd36860 100644 --- a/Userland/Libraries/LibWeb/Painting/Command.cpp +++ b/Userland/Libraries/LibWeb/Painting/Command.cpp @@ -17,7 +17,13 @@ void DrawGlyphRun::translate_by(Gfx::IntPoint const& offset) Gfx::IntRect PaintOuterBoxShadow::bounding_rect() const { - return get_outer_box_shadow_bounding_rect(box_shadow_params); + auto shadow_rect = box_shadow_params.device_content_rect; + auto spread = box_shadow_params.blur_radius * 2 + box_shadow_params.spread_distance; + shadow_rect.inflate(spread, spread, spread, spread); + auto offset_x = box_shadow_params.offset_x; + auto offset_y = box_shadow_params.offset_y; + shadow_rect.translate_by(offset_x, offset_y); + return shadow_rect; } Gfx::IntRect PaintInnerBoxShadow::bounding_rect() const diff --git a/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp b/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp index d0fb2c0aa7a..fcfc5e7aa2d 100644 --- a/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp @@ -6,12 +6,8 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include #include -#include #include -#include -#include #include #include #include @@ -21,238 +17,6 @@ namespace Web::Painting { -struct OuterBoxShadowMetrics { - Gfx::IntRect shadow_bitmap_rect; - Gfx::IntRect non_blurred_shadow_rect; - Gfx::IntRect inner_bounding_rect; - int blurred_edge_thickness; - int double_radius; - int blur_radius; - - Gfx::IntRect top_left_corner_rect; - Gfx::IntRect top_right_corner_rect; - Gfx::IntRect bottom_right_corner_rect; - Gfx::IntRect bottom_left_corner_rect; - - Gfx::IntPoint top_left_corner_blit_pos; - Gfx::IntPoint top_right_corner_blit_pos; - Gfx::IntPoint bottom_right_corner_blit_pos; - Gfx::IntPoint bottom_left_corner_blit_pos; - - Gfx::IntSize top_left_corner_size; - Gfx::IntSize top_right_corner_size; - Gfx::IntSize bottom_right_corner_size; - Gfx::IntSize bottom_left_corner_size; - - int left_start; - int top_start; - int right_start; - int bottom_start; - - Gfx::IntRect left_edge_rect; - Gfx::IntRect right_edge_rect; - Gfx::IntRect top_edge_rect; - Gfx::IntRect bottom_edge_rect; - - CornerRadius top_left_shadow_corner; - CornerRadius top_right_shadow_corner; - CornerRadius bottom_right_shadow_corner; - CornerRadius bottom_left_shadow_corner; -}; - -static OuterBoxShadowMetrics get_outer_box_shadow_configuration(PaintBoxShadowParams params) -{ - auto device_content_rect = params.device_content_rect; - - auto top_left_corner = params.corner_radii.top_left; - auto top_right_corner = params.corner_radii.top_right; - auto bottom_right_corner = params.corner_radii.bottom_right; - auto bottom_left_corner = params.corner_radii.bottom_left; - - auto offset_x = params.offset_x; - auto offset_y = params.offset_y; - auto blur_radius = params.blur_radius; - auto spread_distance = params.spread_distance; - - // Our blur cannot handle radii over 255 so there's no point trying (255 is silly big anyway) - blur_radius = clamp(blur_radius, 0, 255); - - auto top_left_shadow_corner = top_left_corner; - auto top_right_shadow_corner = top_right_corner; - auto bottom_right_shadow_corner = bottom_right_corner; - auto bottom_left_shadow_corner = bottom_left_corner; - - auto spread_corner = [&](auto& corner) { - if (corner) { - corner.horizontal_radius += spread_distance; - corner.vertical_radius += spread_distance; - } - }; - - spread_corner(top_left_shadow_corner); - spread_corner(top_right_shadow_corner); - spread_corner(bottom_right_shadow_corner); - spread_corner(bottom_left_shadow_corner); - - auto expansion = spread_distance - (blur_radius * 2); - Gfx::IntRect inner_bounding_rect = { - device_content_rect.x() + offset_x - expansion, - device_content_rect.y() + offset_y - expansion, - device_content_rect.width() + 2 * expansion, - device_content_rect.height() + 2 * expansion - }; - - // Calculating and blurring the box-shadow full size is expensive, and wasteful - aside from the corners, - // all vertical strips of the shadow are identical, and the same goes for horizontal ones. - // So instead, we generate a shadow bitmap that is just large enough to include the corners and 1px of - // non-corner, and then we repeatedly blit sections of it. This is similar to a NinePatch on Android. - auto double_radius = blur_radius * 2; - auto blurred_edge_thickness = blur_radius * 4; - - auto default_corner_size = Gfx::IntSize { double_radius, double_radius }; - auto top_left_corner_size = top_left_shadow_corner ? top_left_shadow_corner.as_rect().size() : default_corner_size; - auto top_right_corner_size = top_right_shadow_corner ? top_right_shadow_corner.as_rect().size() : default_corner_size; - auto bottom_left_corner_size = bottom_left_shadow_corner ? bottom_left_shadow_corner.as_rect().size() : default_corner_size; - auto bottom_right_corner_size = bottom_right_shadow_corner ? bottom_right_shadow_corner.as_rect().size() : default_corner_size; - - auto non_blurred_shadow_rect = device_content_rect.inflated(spread_distance, spread_distance, spread_distance, spread_distance); - - auto max_edge_width = non_blurred_shadow_rect.width() / 2; - auto max_edge_height = non_blurred_shadow_rect.height() / 2; - auto extra_edge_width = non_blurred_shadow_rect.width() % 2; - auto extra_edge_height = non_blurred_shadow_rect.height() % 2; - - auto clip_corner_size = [&](auto& size, auto const& corner, int x_bonus = 0, int y_bonus = 0) { - auto max_x = max_edge_width + x_bonus; - auto max_y = max_edge_height + y_bonus; - auto min_x = max(corner.horizontal_radius, min(double_radius, max_x)); - auto min_y = max(corner.vertical_radius, min(double_radius, max_y)); - if (min_x <= max_x) - size.set_width(clamp(size.width(), min_x, max_x)); - if (min_y <= max_y) - size.set_height(clamp(size.height(), min_y, max_y)); - }; - - clip_corner_size(top_left_corner_size, top_left_corner, extra_edge_width, extra_edge_height); - clip_corner_size(top_right_corner_size, top_right_corner, 0, extra_edge_height); - clip_corner_size(bottom_left_corner_size, bottom_left_corner, extra_edge_width); - clip_corner_size(bottom_right_corner_size, bottom_right_corner); - - auto shadow_bitmap_rect = Gfx::IntRect { - 0, 0, - max(max( - top_left_corner_size.width() + top_right_corner_size.width(), - bottom_left_corner_size.width() + bottom_right_corner_size.width()), - max(top_left_corner_size.width() + bottom_right_corner_size.width(), - bottom_left_corner_size.width() + top_right_corner_size.width())) - + 1 + blurred_edge_thickness, - max(max( - top_left_corner_size.height() + bottom_left_corner_size.height(), - top_right_corner_size.height() + bottom_right_corner_size.height()), - max(top_left_corner_size.height() + bottom_right_corner_size.height(), - bottom_left_corner_size.height() + top_right_corner_size.height())) - + 1 + blurred_edge_thickness - }; - - auto top_left_corner_rect = Gfx::IntRect { - 0, 0, - top_left_corner_size.width() + double_radius, - top_left_corner_size.height() + double_radius - }; - auto top_right_corner_rect = Gfx::IntRect { - shadow_bitmap_rect.width() - (top_right_corner_size.width() + double_radius), 0, - top_right_corner_size.width() + double_radius, - top_right_corner_size.height() + double_radius - }; - auto bottom_right_corner_rect = Gfx::IntRect { - shadow_bitmap_rect.width() - (bottom_right_corner_size.width() + double_radius), - shadow_bitmap_rect.height() - (bottom_right_corner_size.height() + double_radius), - bottom_right_corner_size.width() + double_radius, - bottom_right_corner_size.height() + double_radius - }; - auto bottom_left_corner_rect = Gfx::IntRect { - 0, shadow_bitmap_rect.height() - (bottom_left_corner_size.height() + double_radius), - bottom_left_corner_size.width() + double_radius, - bottom_left_corner_size.height() + double_radius - }; - - auto horizontal_edge_width = min(max_edge_height, double_radius) + double_radius; - auto vertical_edge_width = min(max_edge_width, double_radius) + double_radius; - auto horizontal_top_edge_width = min(max_edge_height + extra_edge_height, double_radius) + double_radius; - auto vertical_left_edge_width = min(max_edge_width + extra_edge_width, double_radius) + double_radius; - - Gfx::IntRect left_edge_rect { 0, top_left_corner_rect.height(), vertical_left_edge_width, 1 }; - Gfx::IntRect right_edge_rect { shadow_bitmap_rect.width() - vertical_edge_width, top_right_corner_rect.height(), vertical_edge_width, 1 }; - Gfx::IntRect top_edge_rect { top_left_corner_rect.width(), 0, 1, horizontal_top_edge_width }; - Gfx::IntRect bottom_edge_rect { bottom_left_corner_rect.width(), shadow_bitmap_rect.height() - horizontal_edge_width, 1, horizontal_edge_width }; - - auto left_start = inner_bounding_rect.left() - blurred_edge_thickness; - auto right_start = inner_bounding_rect.left() + inner_bounding_rect.width() + (blurred_edge_thickness - vertical_edge_width); - auto top_start = inner_bounding_rect.top() - blurred_edge_thickness; - auto bottom_start = inner_bounding_rect.top() + inner_bounding_rect.height() + (blurred_edge_thickness - horizontal_edge_width); - - auto top_left_corner_blit_pos = inner_bounding_rect.top_left().translated(-blurred_edge_thickness, -blurred_edge_thickness); - auto top_right_corner_blit_pos = inner_bounding_rect.top_right().translated(-top_right_corner_size.width() + double_radius, -blurred_edge_thickness); - auto bottom_left_corner_blit_pos = inner_bounding_rect.bottom_left().translated(-blurred_edge_thickness, -bottom_left_corner_size.height() + double_radius); - auto bottom_right_corner_blit_pos = inner_bounding_rect.bottom_right().translated(-bottom_right_corner_size.width() + double_radius, -bottom_right_corner_size.height() + double_radius); - - return OuterBoxShadowMetrics { - .shadow_bitmap_rect = shadow_bitmap_rect, - .non_blurred_shadow_rect = non_blurred_shadow_rect, - .inner_bounding_rect = inner_bounding_rect, - .blurred_edge_thickness = blurred_edge_thickness, - .double_radius = double_radius, - .blur_radius = blur_radius, - - .top_left_corner_rect = top_left_corner_rect, - .top_right_corner_rect = top_right_corner_rect, - .bottom_right_corner_rect = bottom_right_corner_rect, - .bottom_left_corner_rect = bottom_left_corner_rect, - - .top_left_corner_blit_pos = top_left_corner_blit_pos, - .top_right_corner_blit_pos = top_right_corner_blit_pos, - .bottom_right_corner_blit_pos = bottom_right_corner_blit_pos, - .bottom_left_corner_blit_pos = bottom_left_corner_blit_pos, - - .top_left_corner_size = top_left_corner_size, - .top_right_corner_size = top_right_corner_size, - .bottom_right_corner_size = bottom_right_corner_size, - .bottom_left_corner_size = bottom_left_corner_size, - - .left_start = left_start, - .top_start = top_start, - .right_start = right_start, - .bottom_start = bottom_start, - - .left_edge_rect = left_edge_rect, - .right_edge_rect = right_edge_rect, - .top_edge_rect = top_edge_rect, - .bottom_edge_rect = bottom_edge_rect, - - .top_left_shadow_corner = top_left_shadow_corner, - .top_right_shadow_corner = top_right_shadow_corner, - .bottom_right_shadow_corner = bottom_right_shadow_corner, - .bottom_left_shadow_corner = bottom_left_shadow_corner, - }; -} - -Gfx::IntRect get_outer_box_shadow_bounding_rect(PaintBoxShadowParams params) -{ - auto shadow_config = get_outer_box_shadow_configuration(params); - - auto const& top_left_corner_blit_pos = shadow_config.top_left_corner_blit_pos; - auto const& top_right_corner_blit_pos = shadow_config.top_right_corner_blit_pos; - auto const& bottom_left_corner_blit_pos = shadow_config.bottom_left_corner_blit_pos; - auto const& top_right_corner_rect = shadow_config.top_right_corner_rect; - auto const& bottom_left_corner_rect = shadow_config.bottom_left_corner_rect; - - return Gfx::IntRect { - top_left_corner_blit_pos, - { top_right_corner_blit_pos.x() - top_left_corner_blit_pos.x() + top_right_corner_rect.width(), - bottom_left_corner_blit_pos.y() - top_left_corner_blit_pos.y() + bottom_left_corner_rect.height() } - }; -} - void paint_box_shadow(PaintContext& context, CSSPixelRect const& bordered_content_rect, CSSPixelRect const& borderless_content_rect, diff --git a/Userland/Libraries/LibWeb/Painting/ShadowPainting.h b/Userland/Libraries/LibWeb/Painting/ShadowPainting.h index a8ba4680cce..b9f8452e71f 100644 --- a/Userland/Libraries/LibWeb/Painting/ShadowPainting.h +++ b/Userland/Libraries/LibWeb/Painting/ShadowPainting.h @@ -15,8 +15,6 @@ namespace Web::Painting { -Gfx::IntRect get_outer_box_shadow_bounding_rect(PaintBoxShadowParams params); - void paint_box_shadow( PaintContext&, CSSPixelRect const& bordered_content_rect,