/* * Copyright (c) 2018-2020, Andreas Kling * Copyright (c) 2021, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include namespace Web::Painting { void paint_box_shadow(PaintContext& context, Gfx::IntRect const& content_rect, BoxShadowData const& box_shadow_data) { 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()) return; auto new_bitmap = Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, bitmap_rect.size()); if (!new_bitmap) { dbgln("Unable to allocate temporary bitmap for box-shadow rendering"); return; } 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); 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); } }