ladybird/Libraries/LibGfx/CornerRadii.h
Aliaksandr Kalenik 65962ba03d LibGfx: Add IPC serialization for CornerRadii
The compositor IPC boundary needs to transfer CSS corner radii without
keeping their wire shape in Web-specific glue. Declare the IPC
specializations on the LibGfx types and encode each corner radius pair
next to the CornerRadii implementation.

This is preparatory work required to add IPC between the main and
compositor threads.
2026-05-21 11:45:06 +01:00

109 lines
2.7 KiB
C++

/*
* Copyright (c) 2020, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibGfx/Point.h>
#include <LibGfx/Rect.h>
#include <LibIPC/Forward.h>
namespace Gfx {
enum class CornerClip {
Outside,
Inside
};
struct CornerRadius {
int horizontal_radius { 0 };
int vertical_radius { 0 };
inline operator bool() const
{
return horizontal_radius > 0 && vertical_radius > 0;
}
};
struct CornerRadii {
CornerRadius top_left;
CornerRadius top_right;
CornerRadius bottom_right;
CornerRadius bottom_left;
inline bool has_any_radius() const
{
return top_left || top_right || bottom_right || bottom_left;
}
void adjust_corners_for_spread_distance(int spread_distance);
bool contains(IntPoint point, IntRect const& rect) const
{
if (!rect.contains(point))
return false;
if (!has_any_radius())
return true;
auto const px = point.x();
auto const py = point.y();
auto outside_ellipse = [&](CornerRadius const& r, int cx, int cy) {
auto dx = static_cast<float>(px - cx) / r.horizontal_radius;
auto dy = static_cast<float>(py - cy) / r.vertical_radius;
return dx * dx + dy * dy > 1.f;
};
if (top_left) {
auto cx = rect.left() + top_left.horizontal_radius;
auto cy = rect.top() + top_left.vertical_radius;
if (px < cx && py < cy && outside_ellipse(top_left, cx, cy))
return false;
}
if (top_right) {
auto cx = rect.right() - top_right.horizontal_radius;
auto cy = rect.top() + top_right.vertical_radius;
if (px > cx && py < cy && outside_ellipse(top_right, cx, cy))
return false;
}
if (bottom_right) {
auto cx = rect.right() - bottom_right.horizontal_radius;
auto cy = rect.bottom() - bottom_right.vertical_radius;
if (px > cx && py > cy && outside_ellipse(bottom_right, cx, cy))
return false;
}
if (bottom_left) {
auto cx = rect.left() + bottom_left.horizontal_radius;
auto cy = rect.bottom() - bottom_left.vertical_radius;
if (px < cx && py > cy && outside_ellipse(bottom_left, cx, cy))
return false;
}
return true;
}
};
}
namespace IPC {
template<>
ErrorOr<void> encode(Encoder&, Gfx::CornerRadius const&);
template<>
ErrorOr<Gfx::CornerRadius> decode(Decoder&);
template<>
ErrorOr<void> encode(Encoder&, Gfx::CornerRadii const&);
template<>
ErrorOr<Gfx::CornerRadii> decode(Decoder&);
}