From 6abc51d9f80892feef201bda6194bf5beaa7092f Mon Sep 17 00:00:00 2001 From: MacDue Date: Sat, 3 Jun 2023 23:40:03 +0100 Subject: [PATCH] LibGfx: Simplify segmentizing paths Remove SplitLineSegment and replace it with a FloatLine, nobody was interested in its extra fields anymore. Also, remove the sorting of the split segments, this really should not have been done here anyway, and is not required by the rasterizer anymore. Keeping the segments in stroke order will also make it possible to generate stroked path geometry (in future). --- .../LibGfx/EdgeFlagPathRasterizer.cpp | 8 ++-- .../Libraries/LibGfx/Font/PathRasterizer.cpp | 2 +- Userland/Libraries/LibGfx/Path.cpp | 47 ++++++------------- Userland/Libraries/LibGfx/Path.h | 13 ++--- 4 files changed, 21 insertions(+), 49 deletions(-) diff --git a/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.cpp b/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.cpp index 488e469f82..cb0fd5f2ce 100644 --- a/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.cpp +++ b/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.cpp @@ -30,15 +30,13 @@ namespace Gfx { -static Vector prepare_edges(ReadonlySpan lines, unsigned samples_per_pixel, FloatPoint origin) +static Vector prepare_edges(ReadonlySpan lines, unsigned samples_per_pixel, FloatPoint origin) { - // FIXME: split_lines() gives similar information, but the form it's in is not that useful (and is const anyway). Vector edges; edges.ensure_capacity(lines.size()); - for (auto& line : lines) { - auto p0 = line.from - origin; - auto p1 = line.to - origin; + auto p0 = line.a() - origin; + auto p1 = line.b() - origin; p0.scale_by(1, samples_per_pixel); p1.scale_by(1, samples_per_pixel); diff --git a/Userland/Libraries/LibGfx/Font/PathRasterizer.cpp b/Userland/Libraries/LibGfx/Font/PathRasterizer.cpp index 51b4c1032f..420e77be0a 100644 --- a/Userland/Libraries/LibGfx/Font/PathRasterizer.cpp +++ b/Userland/Libraries/LibGfx/Font/PathRasterizer.cpp @@ -20,7 +20,7 @@ PathRasterizer::PathRasterizer(Gfx::IntSize size) void PathRasterizer::draw_path(Gfx::Path& path) { for (auto& line : path.split_lines()) - draw_line(line.from, line.to); + draw_line(line.a(), line.b()); } RefPtr PathRasterizer::accumulate() diff --git a/Userland/Libraries/LibGfx/Path.cpp b/Userland/Libraries/LibGfx/Path.cpp index a7e94a6376..ed94af9cb9 100644 --- a/Userland/Libraries/LibGfx/Path.cpp +++ b/Userland/Libraries/LibGfx/Path.cpp @@ -239,52 +239,38 @@ DeprecatedString Path::to_deprecated_string() const void Path::segmentize_path() { - Vector segments; + Vector segments; float min_x = 0; float min_y = 0; float max_x = 0; float max_y = 0; + bool first = true; auto add_point_to_bbox = [&](Gfx::FloatPoint point) { float x = point.x(); float y = point.y(); - min_x = min(min_x, x); - min_y = min(min_y, y); - max_x = max(max_x, x); - max_y = max(max_y, y); + if (first) { + min_x = max_x = x; + min_y = max_y = y; + first = false; + } else { + min_x = min(min_x, x); + min_y = min(min_y, y); + max_x = max(max_x, x); + max_y = max(max_y, y); + } }; auto add_line = [&](auto const& p0, auto const& p1) { - float ymax = p0.y(), ymin = p1.y(), x_of_ymin = p1.x(), x_of_ymax = p0.x(); - auto slope = p0.x() == p1.x() ? 0 : ((float)(p0.y() - p1.y())) / ((float)(p0.x() - p1.x())); - if (p0.y() < p1.y()) { - swap(ymin, ymax); - swap(x_of_ymin, x_of_ymax); - } - - segments.append({ FloatPoint(p0.x(), p0.y()), - FloatPoint(p1.x(), p1.y()), - slope == 0 ? 0 : 1 / slope, - x_of_ymin, - ymax, ymin, x_of_ymax }); - + segments.append({ p0, p1 }); add_point_to_bbox(p1); }; FloatPoint cursor { 0, 0 }; - bool first = true; - for (auto& segment : m_segments) { switch (segment->type()) { case Segment::Type::MoveTo: - if (first) { - min_x = segment->point().x(); - min_y = segment->point().y(); - max_x = segment->point().x(); - max_y = segment->point().y(); - } else { - add_point_to_bbox(segment->point()); - } + add_point_to_bbox(segment->point()); cursor = segment->point(); break; case Segment::Type::LineTo: { @@ -325,11 +311,6 @@ void Path::segmentize_path() first = false; } - // sort segments by ymax - quick_sort(segments, [](auto const& line0, auto const& line1) { - return line1.maximum_y < line0.maximum_y; - }); - m_split_lines = move(segments); m_bounding_box = Gfx::FloatRect { min_x, min_y, max_x - min_x, max_y - min_y }; } diff --git a/Userland/Libraries/LibGfx/Path.h b/Userland/Libraries/LibGfx/Path.h index f2d6c05f38..6c31c02e19 100644 --- a/Userland/Libraries/LibGfx/Path.h +++ b/Userland/Libraries/LibGfx/Path.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -208,16 +209,8 @@ public: void close(); void close_all_subpaths(); - struct SplitLineSegment { - FloatPoint from, to; - float inverse_slope; - float x_of_minimum_y; - float maximum_y; - float minimum_y; - float x; - }; - Vector> const& segments() const { return m_segments; } + auto& split_lines() const { if (!m_split_lines.has_value()) { @@ -270,7 +263,7 @@ private: Vector> m_segments {}; - Optional> m_split_lines {}; + Optional> m_split_lines {}; Optional m_bounding_box; };