diff options
Diffstat (limited to 'Userland/Libraries/LibWeb')
-rw-r--r-- | Userland/Libraries/LibWeb/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Layout/Box.cpp | 44 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp | 53 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Painting/ShadowPainting.h | 22 |
4 files changed, 83 insertions, 37 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 57b67867f5..f92e187999 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -222,6 +222,7 @@ set(SOURCES Page/EventHandler.cpp Page/Page.cpp Painting/BorderPainting.cpp + Painting/ShadowPainting.cpp Painting/StackingContext.cpp RequestIdleCallback/IdleDeadline.cpp SVG/AttributeNames.cpp diff --git a/Userland/Libraries/LibWeb/Layout/Box.cpp b/Userland/Libraries/LibWeb/Layout/Box.cpp index 73e135c572..3938bcf195 100644 --- a/Userland/Libraries/LibWeb/Layout/Box.cpp +++ b/Userland/Libraries/LibWeb/Layout/Box.cpp @@ -5,8 +5,6 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include <LibGfx/DisjointRectSet.h> -#include <LibGfx/Filters/FastBoxBlurFilter.h> #include <LibGfx/Painter.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/HTMLBodyElement.h> @@ -16,6 +14,7 @@ #include <LibWeb/Layout/FormattingContext.h> #include <LibWeb/Page/BrowsingContext.h> #include <LibWeb/Painting/BorderPainting.h> +#include <LibWeb/Painting/ShadowPainting.h> namespace Web::Layout { @@ -261,42 +260,13 @@ void Box::paint_box_shadow(PaintContext& context) if (!box_shadow_data.has_value()) return; - auto enclosed_int_rect = enclosing_int_rect(bordered_rect()); - - auto offset_x_px = (int)box_shadow_data->offset_x.resolved_or_zero(*this, width()).to_px(*this); - auto offset_y_px = (int)box_shadow_data->offset_y.resolved_or_zero(*this, width()).to_px(*this); - auto blur_radius = (int)box_shadow_data->blur_radius.resolved_or_zero(*this, width()).to_px(*this); - - Gfx::IntRect bitmap_rect = { - 0, - 0, - enclosed_int_rect.width() + 4 * blur_radius, - enclosed_int_rect.height() + 4 * blur_radius - }; - - Gfx::IntPoint blur_rect_position = { - enclosed_int_rect.x() - 2 * blur_radius + offset_x_px, - enclosed_int_rect.y() - 2 * blur_radius + offset_y_px + auto resolved_box_shadow_data = Painting::BoxShadowData { + .offset_x = (int)box_shadow_data->offset_x.resolved_or_zero(*this, width()).to_px(*this), + .offset_y = (int)box_shadow_data->offset_y.resolved_or_zero(*this, width()).to_px(*this), + .blur_radius = (int)box_shadow_data->blur_radius.resolved_or_zero(*this, width()).to_px(*this), + .color = box_shadow_data->color }; - - 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 * blur_radius, 2 * blur_radius }, enclosed_int_rect.size() }, box_shadow_data->color); - - Gfx::FastBoxBlurFilter filter(*new_bitmap); - filter.apply_three_passes(blur_radius); - - Gfx::DisjointRectSet rect_set; - rect_set.add(bitmap_rect); - auto shattered = rect_set.shatter({ enclosed_int_rect.location() - blur_rect_position, enclosed_int_rect.size() }); - - for (auto& rect : shattered.rects()) - context.painter().blit(rect.location() + blur_rect_position, *new_bitmap, rect); + Painting::paint_box_shadow(context, enclosing_int_rect(bordered_rect()), resolved_box_shadow_data); } Painting::BorderRadiusData Box::normalized_border_radius_data() diff --git a/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp b/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp new file mode 100644 index 0000000000..8b5c93ed7e --- /dev/null +++ b/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibGfx/DisjointRectSet.h> +#include <LibGfx/Filters/FastBoxBlurFilter.h> +#include <LibGfx/Painter.h> +#include <LibWeb/Painting/PaintContext.h> +#include <LibWeb/Painting/ShadowPainting.h> + +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); +} + +} diff --git a/Userland/Libraries/LibWeb/Painting/ShadowPainting.h b/Userland/Libraries/LibWeb/Painting/ShadowPainting.h new file mode 100644 index 0000000000..fd330aad92 --- /dev/null +++ b/Userland/Libraries/LibWeb/Painting/ShadowPainting.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibGfx/Forward.h> + +namespace Web::Painting { + +struct BoxShadowData { + int offset_x; + int offset_y; + int blur_radius; + Gfx::Color color; +}; + +void paint_box_shadow(PaintContext&, Gfx::IntRect const&, BoxShadowData const&); + +} |