diff --git a/Userland/Libraries/LibWeb/Painting/BorderRadiusCornerClipper.cpp b/Userland/Libraries/LibWeb/Painting/BorderRadiusCornerClipper.cpp index 3ac2d0a413c..ce16e730818 100644 --- a/Userland/Libraries/LibWeb/Painting/BorderRadiusCornerClipper.cpp +++ b/Userland/Libraries/LibWeb/Painting/BorderRadiusCornerClipper.cpp @@ -4,116 +4,11 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include -#include #include #include namespace Web::Painting { -BorderRadiusSamplingConfig calculate_border_radius_sampling_config(CornerRadii const& corner_radii, Gfx::IntRect const& border_rect) -{ - auto top_left = corner_radii.top_left; - auto top_right = corner_radii.top_right; - auto bottom_right = corner_radii.bottom_right; - auto bottom_left = corner_radii.bottom_left; - - Gfx::IntSize corners_bitmap_size { - max( - max( - top_left.horizontal_radius + top_right.horizontal_radius, - top_left.horizontal_radius + bottom_right.horizontal_radius), - max( - bottom_left.horizontal_radius + top_right.horizontal_radius, - bottom_left.horizontal_radius + bottom_right.horizontal_radius)), - max( - max( - top_left.vertical_radius + bottom_left.vertical_radius, - top_left.vertical_radius + bottom_right.vertical_radius), - max( - top_right.vertical_radius + bottom_left.vertical_radius, - top_right.vertical_radius + bottom_right.vertical_radius)) - }; - - BorderRadiusSamplingConfig corner_data { - .corner_radii = corner_radii, - .page_locations = { .top_left = border_rect.top_left(), .top_right = border_rect.top_right().translated(-top_right.horizontal_radius, 0), .bottom_right = border_rect.bottom_right().translated(-bottom_right.horizontal_radius, -bottom_right.vertical_radius), .bottom_left = border_rect.bottom_left().translated(0, -bottom_left.vertical_radius) }, - .bitmap_locations = { .top_left = { 0, 0 }, .top_right = { corners_bitmap_size.width() - top_right.horizontal_radius, 0 }, .bottom_right = { corners_bitmap_size.width() - bottom_right.horizontal_radius, corners_bitmap_size.height() - bottom_right.vertical_radius }, .bottom_left = { 0, corners_bitmap_size.height() - bottom_left.vertical_radius } }, - .corners_bitmap_size = corners_bitmap_size, - }; - - return corner_data; -} - -ErrorOr> BorderRadiusCornerClipper::create(CornerRadii const& corner_radii, DevicePixelRect const& border_rect, CornerClip corner_clip) -{ - VERIFY(corner_radii.has_any_radius()); - auto corner_data = calculate_border_radius_sampling_config(corner_radii, border_rect.to_type()); - RefPtr corner_bitmap = TRY(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, corner_data.corners_bitmap_size)); - return try_make_ref_counted(corner_data, corner_bitmap.release_nonnull(), corner_clip, border_rect); -} - -void BorderRadiusCornerClipper::sample_under_corners(Gfx::Painter& page_painter) -{ - // Generate a mask for the corners: - Gfx::Painter corner_painter { *m_corner_bitmap }; - Gfx::AntiAliasingPainter corner_aa_painter { corner_painter }; - corner_aa_painter.fill_rect_with_rounded_corners(m_corner_bitmap->rect(), Color::NamedColor::Black, - m_data.corner_radii.top_left, m_data.corner_radii.top_right, m_data.corner_radii.bottom_right, m_data.corner_radii.bottom_left); - - auto clip_rect = page_painter.clip_rect(); - auto translation = page_painter.translation(); - - auto copy_page_masked = [&](Gfx::IntRect const& mask_src, Gfx::IntPoint const& page_location) { - for (int row = 0; row < mask_src.height(); ++row) { - for (int col = 0; col < mask_src.width(); ++col) { - auto corner_location = mask_src.location().translated(col, row); - auto mask_pixel = m_corner_bitmap->get_pixel(corner_location.x(), corner_location.y()); - u8 mask_alpha = mask_pixel.alpha(); - if (m_corner_clip == CornerClip::Outside) - mask_alpha = ~mask_pixel.alpha(); - auto final_pixel = Color(); - if (mask_alpha > 0) { - auto position = page_location.translated(col, row); - position.translate_by(translation); - if (!clip_rect.contains(position)) - continue; - auto page_pixel = page_painter.target().get_pixel(position.x(), position.y()); - final_pixel = page_pixel.with_alpha(mask_alpha); - } - m_corner_bitmap->set_pixel(corner_location.x(), corner_location.y(), final_pixel); - } - } - }; - - // Copy the pixels under the corner mask (using the alpha of the mask): - if (m_data.corner_radii.top_left) - copy_page_masked(m_data.corner_radii.top_left.as_rect().translated(m_data.bitmap_locations.top_left), m_data.page_locations.top_left); - if (m_data.corner_radii.top_right) - copy_page_masked(m_data.corner_radii.top_right.as_rect().translated(m_data.bitmap_locations.top_right), m_data.page_locations.top_right); - if (m_data.corner_radii.bottom_right) - copy_page_masked(m_data.corner_radii.bottom_right.as_rect().translated(m_data.bitmap_locations.bottom_right), m_data.page_locations.bottom_right); - if (m_data.corner_radii.bottom_left) - copy_page_masked(m_data.corner_radii.bottom_left.as_rect().translated(m_data.bitmap_locations.bottom_left), m_data.page_locations.bottom_left); - - m_has_sampled = true; -} - -void BorderRadiusCornerClipper::blit_corner_clipping(Gfx::Painter& painter) -{ - VERIFY(m_has_sampled); - - // Restore the corners: - if (m_data.corner_radii.top_left) - painter.blit(m_data.page_locations.top_left, *m_corner_bitmap, m_data.corner_radii.top_left.as_rect().translated(m_data.bitmap_locations.top_left)); - if (m_data.corner_radii.top_right) - painter.blit(m_data.page_locations.top_right, *m_corner_bitmap, m_data.corner_radii.top_right.as_rect().translated(m_data.bitmap_locations.top_right)); - if (m_data.corner_radii.bottom_right) - painter.blit(m_data.page_locations.bottom_right, *m_corner_bitmap, m_data.corner_radii.bottom_right.as_rect().translated(m_data.bitmap_locations.bottom_right)); - if (m_data.corner_radii.bottom_left) - painter.blit(m_data.page_locations.bottom_left, *m_corner_bitmap, m_data.corner_radii.bottom_left.as_rect().translated(m_data.bitmap_locations.bottom_left)); -} - ScopedCornerRadiusClip::ScopedCornerRadiusClip(PaintContext& context, DevicePixelRect const& border_rect, BorderRadiiData const& border_radii, CornerClip corner_clip) : m_context(context) , m_id(context.allocate_corner_clipper_id()) diff --git a/Userland/Libraries/LibWeb/Painting/BorderRadiusCornerClipper.h b/Userland/Libraries/LibWeb/Painting/BorderRadiusCornerClipper.h index d959ce52544..8cd5ad876a9 100644 --- a/Userland/Libraries/LibWeb/Painting/BorderRadiusCornerClipper.h +++ b/Userland/Libraries/LibWeb/Painting/BorderRadiusCornerClipper.h @@ -6,7 +6,6 @@ #pragma once -#include #include namespace Web::Painting { @@ -16,47 +15,6 @@ enum class CornerClip { Inside }; -struct BorderRadiusSamplingConfig { - CornerRadii corner_radii; - struct CornerLocations { - Gfx::IntPoint top_left; - Gfx::IntPoint top_right; - Gfx::IntPoint bottom_right; - Gfx::IntPoint bottom_left; - }; - CornerLocations page_locations; - CornerLocations bitmap_locations; - Gfx::IntSize corners_bitmap_size; -}; - -BorderRadiusSamplingConfig calculate_border_radius_sampling_config(CornerRadii const& corner_radii, Gfx::IntRect const& border_rect); - -class BorderRadiusCornerClipper : public RefCounted { -public: - static ErrorOr> create(CornerRadii const&, DevicePixelRect const& border_rect, CornerClip corner_clip = CornerClip::Outside); - - void sample_under_corners(Gfx::Painter& page_painter); - void blit_corner_clipping(Gfx::Painter& page_painter); - - BorderRadiusSamplingConfig m_data; - - DevicePixelRect border_rect() const { return m_border_rect; } - - BorderRadiusCornerClipper(BorderRadiusSamplingConfig corner_data, NonnullRefPtr corner_bitmap, CornerClip corner_clip, DevicePixelRect const& border_rect) - : m_data(corner_data) - , m_corner_bitmap(corner_bitmap) - , m_corner_clip(corner_clip) - , m_border_rect(border_rect) - { - } - -private: - NonnullRefPtr m_corner_bitmap; - bool m_has_sampled { false }; - CornerClip m_corner_clip { false }; - DevicePixelRect m_border_rect; -}; - struct ScopedCornerRadiusClip { ScopedCornerRadiusClip(PaintContext& context, DevicePixelRect const& border_rect, BorderRadiiData const& border_radii, CornerClip corner_clip = CornerClip::Outside); @@ -67,7 +25,6 @@ struct ScopedCornerRadiusClip { private: PaintContext& m_context; - RefPtr m_corner_clipper; u32 m_id; bool m_has_radius { false }; Gfx::IntRect m_border_rect;