mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 15:57:35 +00:00
LibWeb: Render multiple box-shadows
Because why not? :^)
This commit is contained in:
parent
b51f428165
commit
10c6c77b5c
8 changed files with 107 additions and 65 deletions
|
@ -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;
|
||||
// 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
|
||||
};
|
||||
|
||||
if (bitmap_rect.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();
|
||||
|
||||
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);
|
||||
}
|
||||
auto new_bitmap = bitmap_or_error.release_value_but_fixme_should_propagate_errors();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue