diff options
author | Matthew Olsson <matthewcolsson@gmail.com> | 2020-10-05 16:22:24 -0700 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-10-10 23:28:41 +0200 |
commit | 236eeb6fb153960a44d9b85a0eca991ba2bd9313 (patch) | |
tree | 05f8df2289bff55006066ab657db6cf8035fb285 | |
parent | 4155de257237bebe96b5d5c976e57fd18ee572eb (diff) | |
download | serenity-236eeb6fb153960a44d9b85a0eca991ba2bd9313.zip |
LibGfx: Add ability to get a bounding box from a Path
-rw-r--r-- | Libraries/LibGfx/Path.cpp | 28 | ||||
-rw-r--r-- | Libraries/LibGfx/Path.h | 19 |
2 files changed, 43 insertions, 4 deletions
diff --git a/Libraries/LibGfx/Path.cpp b/Libraries/LibGfx/Path.cpp index 967dd09c55..5fe2bb2f63 100644 --- a/Libraries/LibGfx/Path.cpp +++ b/Libraries/LibGfx/Path.cpp @@ -147,6 +147,19 @@ String Path::to_string() const void Path::segmentize_path() { Vector<SplitLineSegment> segments; + float min_x = 0; + float min_y = 0; + float max_x = 0; + float max_y = 0; + + auto add_point_to_bbox = [&](const 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); + }; auto add_line = [&](const auto& p0, const auto& p1) { float ymax = p0.y(), ymin = p1.y(), x_of_ymin = p1.x(), x_of_ymax = p0.x(); @@ -161,12 +174,24 @@ void Path::segmentize_path() slope == 0 ? 0 : 1 / slope, x_of_ymin, ymax, ymin, x_of_ymax }); + + 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()); + } cursor = segment.point(); break; case Segment::Type::LineTo: { @@ -193,6 +218,8 @@ void Path::segmentize_path() case Segment::Type::Invalid: ASSERT_NOT_REACHED(); } + + first = false; } // sort segments by ymax @@ -201,6 +228,7 @@ void Path::segmentize_path() }); 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/Libraries/LibGfx/Path.h b/Libraries/LibGfx/Path.h index 9fe7aa3b0e..7a8dfe9567 100644 --- a/Libraries/LibGfx/Path.h +++ b/Libraries/LibGfx/Path.h @@ -33,6 +33,7 @@ #include <AK/Vector.h> #include <LibGfx/Forward.h> #include <LibGfx/Point.h> +#include <LibGfx/Rect.h> namespace Gfx { @@ -174,13 +175,22 @@ public: const NonnullRefPtrVector<Segment>& segments() const { return m_segments; } const auto& split_lines() { - if (m_split_lines.has_value()) - return m_split_lines.value(); - segmentize_path(); - ASSERT(m_split_lines.has_value()); + if (!m_split_lines.has_value()) { + segmentize_path(); + ASSERT(m_split_lines.has_value()); + } return m_split_lines.value(); } + const Gfx::FloatRect& bounding_box() + { + if (!m_bounding_box.has_value()) { + segmentize_path(); + ASSERT(m_bounding_box.has_value()); + } + return m_bounding_box.value(); + } + String to_string() const; private: @@ -199,6 +209,7 @@ private: NonnullRefPtrVector<Segment> m_segments {}; Optional<Vector<SplitLineSegment>> m_split_lines {}; + Optional<Gfx::FloatRect> m_bounding_box; }; inline const LogStream& operator<<(const LogStream& stream, const Path& path) |