1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-29 07:37:46 +00:00

LibWeb: Bring border painting much closer to the spec/other browsers

This commit adds some much nicer border painting, which now supports:

 - Elliptical corners
 - Blending between different border thicknesses, with rounded corners
 - Anti-aliasing

There are some little TODOs left to tackle:

 - Painting the corners with line styles other than solid
 - Blending between colors on the corners (see comments)

The painting requires allocating a small bitmap, that only fits the
corners (so in most cases this is very small).

This bitmap is then cached so for all paints but the first there will
be no further allocations.
This commit is contained in:
MacDue 2022-06-13 23:33:54 +01:00 committed by Linus Groh
parent 411a815c3b
commit 9e71fa9aa7
6 changed files with 175 additions and 193 deletions

View file

@ -6,6 +6,7 @@
#pragma once
#include <LibGfx/AntiAliasingPainter.h>
#include <LibGfx/Forward.h>
#include <LibWeb/CSS/ComputedValues.h>
@ -14,6 +15,19 @@ namespace Web::Painting {
struct BorderRadiusData {
float horizontal_radius { 0 };
float vertical_radius { 0 };
Gfx::AntiAliasingPainter::CornerRadius as_corner() const
{
return Gfx::AntiAliasingPainter::CornerRadius {
static_cast<int>(horizontal_radius),
static_cast<int>(vertical_radius)
};
};
inline operator bool() const
{
return static_cast<int>(horizontal_radius) > 0 && static_cast<int>(vertical_radius) > 0;
}
};
struct BorderRadiiData {
@ -21,14 +35,14 @@ struct BorderRadiiData {
BorderRadiusData top_right;
BorderRadiusData bottom_right;
BorderRadiusData bottom_left;
inline bool has_any_radius() const
{
return top_left || top_right || bottom_right || bottom_left;
}
};
enum class RelativeToWidthOnly {
Yes,
No
};
BorderRadiiData normalized_border_radii_data(Layout::Node const&, Gfx::FloatRect const&, CSS::BorderRadiusData top_left_radius, CSS::BorderRadiusData top_right_radius, CSS::BorderRadiusData bottom_right_radius, CSS::BorderRadiusData bottom_left_radius, RelativeToWidthOnly relative_to_width_only = RelativeToWidthOnly::No);
BorderRadiiData normalized_border_radii_data(Layout::Node const&, Gfx::FloatRect const&, CSS::BorderRadiusData top_left_radius, CSS::BorderRadiusData top_right_radius, CSS::BorderRadiusData bottom_right_radius, CSS::BorderRadiusData bottom_left_radius);
enum class BorderEdge {
Top,
@ -42,7 +56,7 @@ struct BordersData {
CSS::BorderData bottom;
CSS::BorderData left;
};
void paint_border(PaintContext& context, BorderEdge edge, Gfx::FloatRect const& rect, BorderRadiiData const& border_radii_data, BordersData const& borders_data);
void paint_border(PaintContext& context, BorderEdge edge, Gfx::IntRect const& rect, BordersData const& borders_data);
void paint_all_borders(PaintContext& context, Gfx::FloatRect const& bordered_rect, BorderRadiiData const& border_radii_data, BordersData const&);
}