mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 08:57:34 +00:00
LibAccelGfx+LibWeb: Implement rounded corners rectangle painting
For now corners antialiasing is missing.
This commit is contained in:
parent
0e1bd54896
commit
53c015695e
5 changed files with 106 additions and 2 deletions
|
@ -137,6 +137,12 @@ void delete_texture(Texture const& texture)
|
|||
verify_no_error();
|
||||
}
|
||||
|
||||
void set_uniform(Uniform const& uniform, float value1, float value2)
|
||||
{
|
||||
glUniform2f(uniform.id, value1, value2);
|
||||
verify_no_error();
|
||||
}
|
||||
|
||||
void set_uniform(Uniform const& uniform, float value1, float value2, float value3, float value4)
|
||||
{
|
||||
glUniform4f(uniform.id, value1, value2, value3, value4);
|
||||
|
|
|
@ -73,6 +73,7 @@ void bind_texture(Texture const&);
|
|||
void upload_texture_data(Texture const& texture, Gfx::Bitmap const& bitmap);
|
||||
void delete_texture(Texture const&);
|
||||
|
||||
void set_uniform(Uniform const& uniform, float, float);
|
||||
void set_uniform(Uniform const& uniform, float, float, float, float);
|
||||
void set_vertex_attribute(VertexAttribute const& attribute, u32 offset, int number_of_components);
|
||||
|
||||
|
|
|
@ -49,6 +49,43 @@ void main() {
|
|||
}
|
||||
)";
|
||||
|
||||
char const* rect_with_rounded_corners_fragment_shader_source = R"(
|
||||
#version 330 core
|
||||
uniform vec2 uRectCenter;
|
||||
uniform vec2 uRectCorner;
|
||||
uniform vec2 uTopLeftRadius;
|
||||
uniform vec2 uTopRightRadius;
|
||||
uniform vec2 uBottomLeftRadius;
|
||||
uniform vec2 uBottomRightRadius;
|
||||
uniform vec4 uColor;
|
||||
out vec4 fragColor;
|
||||
|
||||
bool isPointWithinEllipse(vec2 point, vec2 radius) {
|
||||
vec2 normalizedPoint = point / radius;
|
||||
return dot(normalizedPoint, normalizedPoint) <= 1.0;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 p = gl_FragCoord.xy - uRectCenter;
|
||||
vec2 cornerRadius = vec2(0.0, 0.0);
|
||||
if (p.x < 0.0 && p.y < 0.0) {
|
||||
cornerRadius = uTopLeftRadius;
|
||||
} else if (p.x > 0.0 && p.y < 0.0) {
|
||||
cornerRadius = uTopRightRadius;
|
||||
} else if (p.x < 0.0 && p.y > 0.0) {
|
||||
cornerRadius = uBottomLeftRadius;
|
||||
} else if (p.x > 0.0 && p.y > 0.0) {
|
||||
cornerRadius = uBottomRightRadius;
|
||||
}
|
||||
vec2 q = abs(p) - (uRectCorner - cornerRadius);
|
||||
if (q.x < 0 || q.y < 0 || isPointWithinEllipse(q, cornerRadius)) {
|
||||
fragColor = uColor;
|
||||
} else {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
char const* solid_color_fragment_shader_source = R"(
|
||||
#version 330 core
|
||||
uniform vec4 uColor;
|
||||
|
@ -108,6 +145,7 @@ OwnPtr<Painter> Painter::create()
|
|||
Painter::Painter(Context& context)
|
||||
: m_context(context)
|
||||
, m_rectangle_program(Program::create(vertex_shader_source, solid_color_fragment_shader_source))
|
||||
, m_rounded_rectangle_program(Program::create(vertex_shader_source, rect_with_rounded_corners_fragment_shader_source))
|
||||
, m_blit_program(Program::create(blit_vertex_shader_source, blit_fragment_shader_source))
|
||||
, m_linear_gradient_program(Program::create(linear_gradient_vertex_shader_source, linear_gradient_fragment_shader_source))
|
||||
, m_glyphs_texture(GL::create_texture())
|
||||
|
@ -173,6 +211,52 @@ void Painter::fill_rect(Gfx::FloatRect rect, Gfx::Color color)
|
|||
GL::delete_vertex_array(vao);
|
||||
}
|
||||
|
||||
void Painter::fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color const& color, CornerRadius const& top_left_radius, CornerRadius const& top_right_radius, CornerRadius const& bottom_left_radius, CornerRadius const& bottom_right_radius)
|
||||
{
|
||||
fill_rect_with_rounded_corners(rect.to_type<float>(), color, top_left_radius, top_right_radius, bottom_left_radius, bottom_right_radius);
|
||||
}
|
||||
|
||||
void Painter::fill_rect_with_rounded_corners(Gfx::FloatRect const& rect, Color const& color, CornerRadius const& top_left_radius, CornerRadius const& top_right_radius, CornerRadius const& bottom_left_radius, CornerRadius const& bottom_right_radius)
|
||||
{
|
||||
auto vertices = rect_to_vertices(to_clip_space(transform().map(rect)));
|
||||
|
||||
auto vbo = GL::create_buffer();
|
||||
GL::upload_to_buffer(vbo, vertices);
|
||||
|
||||
auto vao = GL::create_vertex_array();
|
||||
GL::bind_vertex_array(vao);
|
||||
GL::bind_buffer(vbo);
|
||||
|
||||
auto [red, green, blue, alpha] = gfx_color_to_opengl_color(color);
|
||||
|
||||
m_rounded_rectangle_program.use();
|
||||
|
||||
auto position_attribute = m_rounded_rectangle_program.get_attribute_location("aVertexPosition");
|
||||
GL::set_vertex_attribute(position_attribute, 0, 2);
|
||||
|
||||
auto color_uniform = m_rounded_rectangle_program.get_uniform_location("uColor");
|
||||
GL::set_uniform(color_uniform, red, green, blue, alpha);
|
||||
|
||||
auto rect_center_uniform = m_rounded_rectangle_program.get_uniform_location("uRectCenter");
|
||||
GL::set_uniform(rect_center_uniform, rect.center().x(), rect.center().y());
|
||||
auto rect_corner_uniform = m_rounded_rectangle_program.get_uniform_location("uRectCorner");
|
||||
GL::set_uniform(rect_corner_uniform, rect.width() / 2, rect.height() / 2);
|
||||
auto top_left_corner_radius_uniform = m_rounded_rectangle_program.get_uniform_location("uTopLeftRadius");
|
||||
GL::set_uniform(top_left_corner_radius_uniform, top_left_radius.horizontal_radius, top_left_radius.vertical_radius);
|
||||
auto top_right_corner_radius_uniform = m_rounded_rectangle_program.get_uniform_location("uTopRightRadius");
|
||||
GL::set_uniform(top_right_corner_radius_uniform, top_right_radius.horizontal_radius, top_right_radius.vertical_radius);
|
||||
auto bottom_left_corner_radius_uniform = m_rounded_rectangle_program.get_uniform_location("uBottomLeftRadius");
|
||||
GL::set_uniform(bottom_left_corner_radius_uniform, bottom_left_radius.horizontal_radius, bottom_left_radius.vertical_radius);
|
||||
auto bottom_right_corner_radius_uniform = m_rounded_rectangle_program.get_uniform_location("uBottomRightRadius");
|
||||
GL::set_uniform(bottom_right_corner_radius_uniform, bottom_right_radius.horizontal_radius, bottom_right_radius.vertical_radius);
|
||||
|
||||
GL::enable_blending();
|
||||
GL::draw_arrays(GL::DrawPrimitive::TriangleFan, 4);
|
||||
|
||||
GL::delete_buffer(vbo);
|
||||
GL::delete_vertex_array(vao);
|
||||
}
|
||||
|
||||
void Painter::draw_line(Gfx::IntPoint a, Gfx::IntPoint b, float thickness, Gfx::Color color)
|
||||
{
|
||||
draw_line(a.to_type<float>(), b.to_type<float>(), thickness, color);
|
||||
|
|
|
@ -77,6 +77,13 @@ public:
|
|||
void fill_rect_with_linear_gradient(Gfx::IntRect const&, ReadonlySpan<Gfx::ColorStop>, float angle, Optional<float> repeat_length = {});
|
||||
void fill_rect_with_linear_gradient(Gfx::FloatRect const&, ReadonlySpan<Gfx::ColorStop>, float angle, Optional<float> repeat_length = {});
|
||||
|
||||
struct CornerRadius {
|
||||
float horizontal_radius;
|
||||
float vertical_radius;
|
||||
};
|
||||
void fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color const& color, CornerRadius const& top_left_radius, CornerRadius const& top_right_radius, CornerRadius const& bottom_left_radius, CornerRadius const& bottom_right_radius);
|
||||
void fill_rect_with_rounded_corners(Gfx::FloatRect const& rect, Color const& color, CornerRadius const& top_left_radius, CornerRadius const& top_right_radius, CornerRadius const& bottom_left_radius, CornerRadius const& bottom_right_radius);
|
||||
|
||||
private:
|
||||
Context& m_context;
|
||||
|
||||
|
@ -92,6 +99,7 @@ private:
|
|||
Vector<State, 1> m_state_stack;
|
||||
|
||||
Program m_rectangle_program;
|
||||
Program m_rounded_rectangle_program;
|
||||
Program m_blit_program;
|
||||
Program m_linear_gradient_program;
|
||||
|
||||
|
|
|
@ -111,9 +111,14 @@ CommandResult PaintingCommandExecutorGPU::paint_text_shadow(int, Gfx::IntRect co
|
|||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
CommandResult PaintingCommandExecutorGPU::fill_rect_with_rounded_corners(Gfx::IntRect const&, Color const&, Gfx::AntiAliasingPainter::CornerRadius const&, Gfx::AntiAliasingPainter::CornerRadius const&, Gfx::AntiAliasingPainter::CornerRadius const&, Gfx::AntiAliasingPainter::CornerRadius const&, Optional<Gfx::FloatPoint> const&)
|
||||
CommandResult PaintingCommandExecutorGPU::fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color const& color, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius, Optional<Gfx::FloatPoint> const&)
|
||||
{
|
||||
// FIXME
|
||||
painter().fill_rect_with_rounded_corners(
|
||||
rect, color,
|
||||
{ static_cast<float>(top_left_radius.horizontal_radius), static_cast<float>(top_left_radius.vertical_radius) },
|
||||
{ static_cast<float>(top_right_radius.horizontal_radius), static_cast<float>(top_right_radius.vertical_radius) },
|
||||
{ static_cast<float>(bottom_left_radius.horizontal_radius), static_cast<float>(bottom_left_radius.vertical_radius) },
|
||||
{ static_cast<float>(bottom_right_radius.horizontal_radius), static_cast<float>(bottom_right_radius.vertical_radius) });
|
||||
return CommandResult::Continue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue