mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
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:
parent
910bff9e94
commit
6abc51d9f8
Notes:
sideshowbarker
2024-07-17 07:20:49 +09:00
Author: https://github.com/MacDue Commit: https://github.com/SerenityOS/serenity/commit/6abc51d9f8 Pull-request: https://github.com/SerenityOS/serenity/pull/19250 Reviewed-by: https://github.com/gmta ✅
4 changed files with 21 additions and 49 deletions
|
@ -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);
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 };
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue