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

LibGfx: Add AA dotted horizontal/vertical lines

This adds simple dotted lines (horizontal/vertical only for now).

There's a little number fudging added in to make sure the final
dot is always drawn at the endpoint (for lines with at least a
handful of dots).
This commit is contained in:
MacDue 2022-06-18 01:40:24 +01:00 committed by Linus Groh
parent 50c88e5e3a
commit 6139fc5c87
2 changed files with 46 additions and 0 deletions

View file

@ -123,8 +123,52 @@ void Gfx::AntiAliasingPainter::draw_aliased_line(FloatPoint const& actual_from,
draw_anti_aliased_line<AntiAliasPolicy::OnlyEnds>(actual_from, actual_to, color, thickness, style, alternate_color);
}
void Gfx::AntiAliasingPainter::draw_dotted_line(IntPoint point1, IntPoint point2, Gfx::Color color, int thickness)
{
// AA circles don't really work below a radius of 2px.
if (thickness < 4)
return m_underlying_painter.draw_line(point1, point2, color, thickness, Painter::LineStyle::Dotted);
auto draw_spaced_dots = [&](int start, int end, auto to_point) {
int step = thickness * 2;
if (start > end)
swap(start, end);
int delta = end - start;
int dots = delta / step;
if (dots == 0)
return;
int fudge_per_dot = 0;
int extra_fudge = 0;
if (dots > 3) {
// Fudge the numbers so the last dot is drawn at the `end' point (otherwise you can get lines cuts short).
// You need at least a handful of dots to do this.
int fudge = delta % step;
fudge_per_dot = fudge / dots;
extra_fudge = fudge % dots;
}
for (int dot = start; dot <= end; dot += (step + fudge_per_dot + (extra_fudge > 0))) {
fill_circle(to_point(dot), thickness / 2, color);
--extra_fudge;
}
};
if (point1.y() == point2.y()) {
draw_spaced_dots(point1.x(), point2.x(), [&](int dot_x) {
return IntPoint { dot_x, point1.y() };
});
} else if (point1.x() == point2.x()) {
draw_spaced_dots(point1.y(), point2.y(), [&](int dot_y) {
return IntPoint { point1.x(), dot_y };
});
} else {
TODO();
}
}
void Gfx::AntiAliasingPainter::draw_line(FloatPoint const& actual_from, FloatPoint const& actual_to, Color color, float thickness, Gfx::Painter::LineStyle style, Color alternate_color)
{
if (style == Painter::LineStyle::Dotted)
return draw_dotted_line(actual_from.to_rounded<int>(), actual_to.to_rounded<int>(), color, static_cast<int>(round(thickness)));
draw_anti_aliased_line<AntiAliasPolicy::Full>(actual_from, actual_to, color, thickness, style, alternate_color);
}

View file

@ -71,6 +71,8 @@ private:
Range draw_ellipse_part(IntPoint a_rect, int radius_a, int radius_b, Color, bool flip_x_and_y, Optional<Range> x_clip, BlendMode blend_mode);
void draw_dotted_line(IntPoint, IntPoint, Gfx::Color, int thickness);
enum class AntiAliasPolicy {
OnlyEnds,
Full,