diff options
Diffstat (limited to 'Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp')
-rw-r--r-- | Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp | 68 |
1 files changed, 38 insertions, 30 deletions
diff --git a/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp b/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp index 91c09737d5..5fa8eafdf5 100644 --- a/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org> + * Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ @@ -13,42 +13,50 @@ namespace Web::Painting { -void paint_box_shadow(PaintContext& context, Gfx::IntRect const& content_rect, BoxShadowData const& box_shadow_data) +void paint_box_shadow(PaintContext& context, Gfx::IntRect const& content_rect, Vector<BoxShadowData> const& box_shadow_layers) { - Gfx::IntRect bitmap_rect = { - 0, - 0, - content_rect.width() + 4 * box_shadow_data.blur_radius, - content_rect.height() + 4 * box_shadow_data.blur_radius - }; - - Gfx::IntPoint blur_rect_position = { - content_rect.x() - 2 * box_shadow_data.blur_radius + box_shadow_data.offset_x, - content_rect.y() - 2 * box_shadow_data.blur_radius + box_shadow_data.offset_y - }; - - if (bitmap_rect.is_empty()) + if (box_shadow_layers.is_empty()) return; - auto bitmap_or_error = Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, bitmap_rect.size()); - if (bitmap_or_error.is_error()) { - dbgln("Unable to allocate temporary bitmap for box-shadow rendering: {}", bitmap_or_error.error()); - return; - } - auto new_bitmap = bitmap_or_error.release_value_but_fixme_should_propagate_errors(); + // Note: Box-shadow layers are ordered front-to-back, so we paint them in reverse + for (int layer_index = box_shadow_layers.size() - 1; layer_index >= 0; layer_index--) { + auto& box_shadow_data = box_shadow_layers[layer_index]; + + Gfx::IntRect bitmap_rect = { + 0, + 0, + content_rect.width() + 4 * box_shadow_data.blur_radius, + content_rect.height() + 4 * box_shadow_data.blur_radius + }; + + Gfx::IntPoint blur_rect_position = { + content_rect.x() - 2 * box_shadow_data.blur_radius + box_shadow_data.offset_x, + content_rect.y() - 2 * box_shadow_data.blur_radius + box_shadow_data.offset_y + }; - Gfx::Painter painter(*new_bitmap); - painter.fill_rect({ { 2 * box_shadow_data.blur_radius, 2 * box_shadow_data.blur_radius }, content_rect.size() }, box_shadow_data.color); + if (bitmap_rect.is_empty()) + return; - Gfx::FastBoxBlurFilter filter(*new_bitmap); - filter.apply_three_passes(box_shadow_data.blur_radius); + auto bitmap_or_error = Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, bitmap_rect.size()); + if (bitmap_or_error.is_error()) { + dbgln("Unable to allocate temporary bitmap for box-shadow rendering: {}", bitmap_or_error.error()); + return; + } + auto new_bitmap = bitmap_or_error.release_value_but_fixme_should_propagate_errors(); - Gfx::DisjointRectSet rect_set; - rect_set.add(bitmap_rect); - auto shattered = rect_set.shatter({ content_rect.location() - blur_rect_position, content_rect.size() }); + Gfx::Painter painter(*new_bitmap); + painter.fill_rect({ { 2 * box_shadow_data.blur_radius, 2 * box_shadow_data.blur_radius }, content_rect.size() }, box_shadow_data.color); - for (auto& rect : shattered.rects()) - context.painter().blit(rect.location() + blur_rect_position, *new_bitmap, rect); + Gfx::FastBoxBlurFilter filter(*new_bitmap); + filter.apply_three_passes(box_shadow_data.blur_radius); + + Gfx::DisjointRectSet rect_set; + rect_set.add(bitmap_rect); + auto shattered = rect_set.shatter({ content_rect.location() - blur_rect_position, content_rect.size() }); + + for (auto& rect : shattered.rects()) + context.painter().blit(rect.location() + blur_rect_position, *new_bitmap, rect); + } } } |