mirror of
https://github.com/RGBCube/serenity
synced 2025-05-22 16:35:08 +00:00

The refactor of the border painting mainly to handle: 1. Single border with minor border radius. 2. Different border widths and border colors joined situations. This refactor only apply to solid border. The main differece is to use Path.fill to paint each border, not fill_rect anymore. There's a special case need to consider. The Path.fill will leave shared edge blank between two borders. To handle this, we decide to combine the borders with same color to paint together.
82 lines
2.5 KiB
C++
82 lines
2.5 KiB
C++
/*
|
|
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <LibGfx/AntiAliasingPainter.h>
|
|
#include <LibGfx/Forward.h>
|
|
#include <LibWeb/CSS/ComputedValues.h>
|
|
#include <LibWeb/Painting/PaintContext.h>
|
|
|
|
namespace Web::Painting {
|
|
|
|
struct BorderRadiusData {
|
|
CSSPixels horizontal_radius { 0 };
|
|
CSSPixels vertical_radius { 0 };
|
|
|
|
Gfx::AntiAliasingPainter::CornerRadius as_corner(PaintContext& context) const
|
|
{
|
|
return Gfx::AntiAliasingPainter::CornerRadius {
|
|
context.floored_device_pixels(horizontal_radius).value(),
|
|
context.floored_device_pixels(vertical_radius).value()
|
|
};
|
|
}
|
|
|
|
inline operator bool() const
|
|
{
|
|
return horizontal_radius > 0 && vertical_radius > 0;
|
|
}
|
|
|
|
inline void shrink(CSSPixels horizontal, CSSPixels vertical)
|
|
{
|
|
horizontal_radius = max(CSSPixels(0), horizontal_radius - horizontal);
|
|
vertical_radius = max(CSSPixels(0), vertical_radius - vertical);
|
|
}
|
|
};
|
|
|
|
struct BorderRadiiData {
|
|
BorderRadiusData top_left;
|
|
BorderRadiusData top_right;
|
|
BorderRadiusData bottom_right;
|
|
BorderRadiusData bottom_left;
|
|
|
|
inline bool has_any_radius() const
|
|
{
|
|
return top_left || top_right || bottom_right || bottom_left;
|
|
}
|
|
|
|
inline void shrink(CSSPixels top, CSSPixels right, CSSPixels bottom, CSSPixels left)
|
|
{
|
|
top_left.shrink(left, top);
|
|
top_right.shrink(right, top);
|
|
bottom_right.shrink(right, bottom);
|
|
bottom_left.shrink(left, bottom);
|
|
}
|
|
};
|
|
|
|
BorderRadiiData normalized_border_radii_data(Layout::Node const&, CSSPixelRect 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,
|
|
Right,
|
|
Bottom,
|
|
Left,
|
|
};
|
|
struct BordersData {
|
|
CSS::BorderData top;
|
|
CSS::BorderData right;
|
|
CSS::BorderData bottom;
|
|
CSS::BorderData left;
|
|
};
|
|
|
|
RefPtr<Gfx::Bitmap> get_cached_corner_bitmap(DevicePixelSize corners_size);
|
|
|
|
void paint_border(PaintContext& context, BorderEdge edge, DevicePixelRect const& rect, Gfx::AntiAliasingPainter::CornerRadius const& radius, Gfx::AntiAliasingPainter::CornerRadius const& opposite_radius, BordersData const& borders_data, Gfx::Path& path, bool last);
|
|
void paint_all_borders(PaintContext& context, CSSPixelRect const& bordered_rect, BorderRadiiData const& border_radii_data, BordersData const&);
|
|
|
|
Gfx::Color border_color(BorderEdge edge, BordersData const& borders_data);
|
|
|
|
}
|