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).
This commit is contained in:
MacDue 2023-06-03 23:40:03 +01:00 committed by Andreas Kling
parent 910bff9e94
commit 6abc51d9f8
Notes: sideshowbarker 2024-07-17 07:20:49 +09:00
4 changed files with 21 additions and 49 deletions

View file

@ -30,15 +30,13 @@
namespace Gfx {
static Vector<Detail::Edge> prepare_edges(ReadonlySpan<Path::SplitLineSegment> lines, unsigned samples_per_pixel, FloatPoint origin)
static Vector<Detail::Edge> prepare_edges(ReadonlySpan<FloatLine> 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<Detail::Edge> 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);

View file

@ -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<Gfx::Bitmap> PathRasterizer::accumulate()

View file

@ -239,52 +239,38 @@ DeprecatedString Path::to_deprecated_string() const
void Path::segmentize_path()
{
Vector<SplitLineSegment> segments;
Vector<FloatLine> 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 };
}

View file

@ -11,6 +11,7 @@
#include <AK/Optional.h>
#include <AK/Vector.h>
#include <LibGfx/Forward.h>
#include <LibGfx/Line.h>
#include <LibGfx/Point.h>
#include <LibGfx/Rect.h>
@ -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<NonnullRefPtr<Segment const>> const& segments() const { return m_segments; }
auto& split_lines() const
{
if (!m_split_lines.has_value()) {
@ -270,7 +263,7 @@ private:
Vector<NonnullRefPtr<Segment const>> m_segments {};
Optional<Vector<SplitLineSegment>> m_split_lines {};
Optional<Vector<FloatLine>> m_split_lines {};
Optional<Gfx::FloatRect> m_bounding_box;
};