Repository: SerenityOS/serenity
File: Userland/Libraries/LibGfx/AntiAliasingPainter.cpp (C++)

Code before:
#    pragma GCC optimize("O3")
#endif

#include <AK/Function.h>
#include <AK/NumericLimits.h>
#include <LibGfx/AntiAliasingPainter.h>
#include <LibGfx/Line.h>
#include <LibGfx/Painter.h>

namespace Gfx {

void AntiAliasingPainter::draw_line(IntPoint actual_from, IntPoint actual_to, Color color, float thickness, LineStyle style, Color alternate_color)
{
    draw_line(actual_from.to_type<float>(), actual_to.to_type<float>(), color, thickness, style, alternate_color);
}

static Path::StrokeStyle line_style_to_stroke_style(LineStyle style, float thickness)
{
    switch (style) {
    case LineStyle::Solid:
        return Path::StrokeStyle { .thickness = thickness, .cap_style = Path::CapStyle::Square, .join_style = Path::JoinStyle::Miter };
    case LineStyle::Dotted:
        // FIXME: 0.2f is arbitrarily chosen as it still looks okay at 1px thickness. Drawing dots is a little awkward as the round caps don't factor into the dash length.
        return Path::StrokeStyle { .thickness = thickness, .cap_style = Path::CapStyle::Round, .join_style = Path::JoinStyle::Round, .dash_pattern = { 0.2f, thickness * 2 } };
    case LineStyle::Dashed:
        return Path::StrokeStyle { .thickness = thickness, .cap_style = Path::CapStyle::Square, .join_style = Path::JoinStyle::Miter, .dash_pattern = { thickness, thickness } };
    }
    VERIFY_NOT_REACHED();
}

void AntiAliasingPainter::draw_line(FloatPoint actual_from, FloatPoint actual_to, Color color, float thickness, LineStyle style, Color)
{
    if (color.alpha() == 0)
        return;

    Path line;
    line.move_to(actual_from);
    line.line_to(actual_to);

    stroke_path(line, color, line_style_to_stroke_style(style, thickness));
}

void AntiAliasingPainter::stroke_path(Path const& path, Color color, Path::StrokeStyle const& stroke_style)
{
    if (stroke_style.thickness <= 0 || color.alpha() == 0)
        return;
    // FIXME: Cache this? Probably at a higher level such as in LibWeb?
    fill_path(path.stroke_to_fill(stroke_style), color);
}

void AntiAliasingPainter::stroke_path(Path const& path, Gfx::PaintStyle const& paint_style, Path::StrokeStyle const& stroke_style, float opacity)

Review comment (suggestion):
Same question here. Square instead of Butt also affects the dashes – with Butt gaps and lines are equal size, but with Square iirc the lines are longer than the gaps in between.

Code after:
#    pragma GCC optimize("O3")
#endif

#include <AK/Function.h>
#include <AK/NumericLimits.h>
#include <LibGfx/AntiAliasingPainter.h>
#include <LibGfx/Line.h>
#include <LibGfx/Painter.h>

namespace Gfx {

void AntiAliasingPainter::draw_line(IntPoint actual_from, IntPoint actual_to, Color color, float thickness, LineStyle style, Color alternate_color)
{
    draw_line(actual_from.to_type<float>(), actual_to.to_type<float>(), color, thickness, style, alternate_color);
}

static Path::StrokeStyle line_style_to_stroke_style(LineStyle style, float thickness)
{
    switch (style) {
    case LineStyle::Solid:
        return Path::StrokeStyle { .thickness = thickness, .cap_style = Path::CapStyle::Butt, .join_style = Path::JoinStyle::Miter };
    case LineStyle::Dotted:
        // FIXME: 0.2f is arbitrarily chosen as it still looks okay at 1px thickness. Drawing dots is a little awkward as the round caps don't factor into the dash length.
        return Path::StrokeStyle { .thickness = thickness, .cap_style = Path::CapStyle::Round, .join_style = Path::JoinStyle::Round, .dash_pattern = { 0.2f, thickness * 2 } };
    case LineStyle::Dashed:
        return Path::StrokeStyle { .thickness = thickness, .cap_style = Path::CapStyle::Butt, .join_style = Path::JoinStyle::Miter, .dash_pattern = { thickness, thickness } };
    }
    VERIFY_NOT_REACHED();
}

void AntiAliasingPainter::draw_line(FloatPoint actual_from, FloatPoint actual_to, Color color, float thickness, LineStyle style, Color)
{
    if (color.alpha() == 0)
        return;

    Path line;
    line.move_to(actual_from);
    line.line_to(actual_to);

    stroke_path(line, color, line_style_to_stroke_style(style, thickness));
}

void AntiAliasingPainter::stroke_path(Path const& path, Color color, Path::StrokeStyle const& stroke_style)
{
    if (stroke_style.thickness <= 0 || color.alpha() == 0)
        return;
    // FIXME: Cache this? Probably at a higher level such as in LibWeb?
    fill_path(path.stroke_to_fill(stroke_style), color);
}

void AntiAliasingPainter::stroke_path(Path const& path, Gfx::PaintStyle const& paint_style, Path::StrokeStyle const& stroke_style, float opacity)