1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-19 00:05:06 +00:00
serenity/Userland/Libraries/LibWeb/Painting/BorderRadiusCornerClipper.h
MacDue b7fd844c9d LibWeb: Add ScopedCornerRadiusClip
This a simple RAII helper for the BorderRadiusCornerClipper it
samples under the corners on construction, then blits them back
on exiting the scope. This encapsulates a fairly common pattern.
2022-07-04 23:09:06 +02:00

91 lines
2.7 KiB
C++

/*
* Copyright (c) 2022, MacDue <macdue@dueutil.tech>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibGfx/AntiAliasingPainter.h>
#include <LibWeb/Painting/BorderPainting.h>
namespace Web::Painting {
enum class CornerClip {
Outside,
Inside
};
class BorderRadiusCornerClipper {
public:
enum class UseCachedBitmap {
Yes,
No
};
static ErrorOr<BorderRadiusCornerClipper> create(Gfx::IntRect const& border_rect, BorderRadiiData const& border_radii, CornerClip corner_clip = CornerClip::Outside, UseCachedBitmap use_cached_bitmap = UseCachedBitmap::Yes);
void sample_under_corners(Gfx::Painter& page_painter);
void blit_corner_clipping(Gfx::Painter& page_painter);
private:
using CornerRadius = Gfx::AntiAliasingPainter::CornerRadius;
struct CornerData {
struct CornerRadii {
CornerRadius top_left;
CornerRadius top_right;
CornerRadius bottom_right;
CornerRadius bottom_left;
} 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 corner_bitmap_size;
} m_data;
NonnullRefPtr<Gfx::Bitmap> m_corner_bitmap;
bool m_has_sampled { false };
CornerClip m_corner_clip { false };
BorderRadiusCornerClipper(CornerData corner_data, NonnullRefPtr<Gfx::Bitmap> corner_bitmap, CornerClip corner_clip)
: m_data(move(corner_data))
, m_corner_bitmap(corner_bitmap)
, m_corner_clip(corner_clip)
{
}
};
struct ScopedCornerRadiusClip {
ScopedCornerRadiusClip(Gfx::Painter& painter, Gfx::IntRect const& border_rect, BorderRadiiData const& border_radii, CornerClip corner_clip = CornerClip::Outside, BorderRadiusCornerClipper::UseCachedBitmap use_cached_bitmap = BorderRadiusCornerClipper::UseCachedBitmap::Yes)
: m_painter(painter)
{
if (border_radii.has_any_radius()) {
auto clipper = BorderRadiusCornerClipper::create(border_rect, border_radii, corner_clip, use_cached_bitmap);
if (!clipper.is_error()) {
m_corner_clipper = clipper.release_value();
m_corner_clipper->sample_under_corners(m_painter);
}
}
}
~ScopedCornerRadiusClip()
{
if (m_corner_clipper.has_value()) {
m_corner_clipper->blit_corner_clipping(m_painter);
}
}
AK_MAKE_NONMOVABLE(ScopedCornerRadiusClip);
AK_MAKE_NONCOPYABLE(ScopedCornerRadiusClip);
private:
Gfx::Painter& m_painter;
Optional<BorderRadiusCornerClipper> m_corner_clipper;
};
}