From a8c1bb04618e5becd1f8bacd2560325631bd869c Mon Sep 17 00:00:00 2001 From: BenJilks Date: Fri, 12 Jul 2024 13:52:21 +0100 Subject: [PATCH] LibWeb: Draw dashed and dotted lines in Skia painter Use the `SkDashPathEffect` path effect, to implement dashed and dotted line styles. --- .../LibWeb/Painting/DisplayListPlayerSkia.cpp | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp b/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp index 011cb624e42..ffa2033c33e 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp +++ b/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp @@ -13,8 +13,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -923,9 +925,44 @@ CommandResult DisplayListPlayerSkia::draw_line(DrawLine const& command) auto from = to_skia_point(command.from); auto to = to_skia_point(command.to); auto& canvas = surface().canvas(); + SkPaint paint; paint.setStrokeWidth(command.thickness); paint.setColor(to_skia_color(command.color)); + + switch (command.style) { + case Gfx::LineStyle::Solid: + break; + case Gfx::LineStyle::Dotted: { + auto length = command.to.distance_from(command.from); + auto dot_count = floor(length / (static_cast(command.thickness) * 2)); + auto interval = length / dot_count; + SkScalar intervals[] = { 0, interval }; + paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); + paint.setStrokeCap(SkPaint::Cap::kRound_Cap); + + // NOTE: As Skia doesn't render a dot exactly at the end of a line, we need + // to extend it by less then an interval. + auto direction = to - from; + direction.normalize(); + to += direction * (interval / 2.0f); + break; + } + case Gfx::LineStyle::Dashed: { + auto length = command.to.distance_from(command.from) + command.thickness; + auto dash_count = floor(length / static_cast(command.thickness) / 4) * 2 + 1; + auto interval = length / dash_count; + SkScalar intervals[] = { interval, interval }; + paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); + + auto direction = to - from; + direction.normalize(); + from -= direction * (command.thickness / 2.0f); + to += direction * (command.thickness / 2.0f); + break; + } + } + canvas.drawLine(from, to, paint); return CommandResult::Continue; }