mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:07:47 +00:00
LibGfx: Add ability to get a bounding box from a Path
This commit is contained in:
parent
4155de2572
commit
236eeb6fb1
2 changed files with 43 additions and 4 deletions
|
@ -147,6 +147,19 @@ String Path::to_string() const
|
||||||
void Path::segmentize_path()
|
void Path::segmentize_path()
|
||||||
{
|
{
|
||||||
Vector<SplitLineSegment> segments;
|
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) {
|
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();
|
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,
|
slope == 0 ? 0 : 1 / slope,
|
||||||
x_of_ymin,
|
x_of_ymin,
|
||||||
ymax, ymin, x_of_ymax });
|
ymax, ymin, x_of_ymax });
|
||||||
|
|
||||||
|
add_point_to_bbox(p1);
|
||||||
};
|
};
|
||||||
|
|
||||||
FloatPoint cursor { 0, 0 };
|
FloatPoint cursor { 0, 0 };
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
for (auto& segment : m_segments) {
|
for (auto& segment : m_segments) {
|
||||||
switch (segment.type()) {
|
switch (segment.type()) {
|
||||||
case Segment::Type::MoveTo:
|
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();
|
cursor = segment.point();
|
||||||
break;
|
break;
|
||||||
case Segment::Type::LineTo: {
|
case Segment::Type::LineTo: {
|
||||||
|
@ -193,6 +218,8 @@ void Path::segmentize_path()
|
||||||
case Segment::Type::Invalid:
|
case Segment::Type::Invalid:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort segments by ymax
|
// sort segments by ymax
|
||||||
|
@ -201,6 +228,7 @@ void Path::segmentize_path()
|
||||||
});
|
});
|
||||||
|
|
||||||
m_split_lines = move(segments);
|
m_split_lines = move(segments);
|
||||||
|
m_bounding_box = Gfx::FloatRect { min_x, min_y, max_x - min_x, max_y - min_y };
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <LibGfx/Forward.h>
|
#include <LibGfx/Forward.h>
|
||||||
#include <LibGfx/Point.h>
|
#include <LibGfx/Point.h>
|
||||||
|
#include <LibGfx/Rect.h>
|
||||||
|
|
||||||
namespace Gfx {
|
namespace Gfx {
|
||||||
|
|
||||||
|
@ -174,13 +175,22 @@ public:
|
||||||
const NonnullRefPtrVector<Segment>& segments() const { return m_segments; }
|
const NonnullRefPtrVector<Segment>& segments() const { return m_segments; }
|
||||||
const auto& split_lines()
|
const auto& split_lines()
|
||||||
{
|
{
|
||||||
if (m_split_lines.has_value())
|
if (!m_split_lines.has_value()) {
|
||||||
return m_split_lines.value();
|
segmentize_path();
|
||||||
segmentize_path();
|
ASSERT(m_split_lines.has_value());
|
||||||
ASSERT(m_split_lines.has_value());
|
}
|
||||||
return m_split_lines.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;
|
String to_string() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -199,6 +209,7 @@ private:
|
||||||
NonnullRefPtrVector<Segment> m_segments {};
|
NonnullRefPtrVector<Segment> m_segments {};
|
||||||
|
|
||||||
Optional<Vector<SplitLineSegment>> m_split_lines {};
|
Optional<Vector<SplitLineSegment>> m_split_lines {};
|
||||||
|
Optional<Gfx::FloatRect> m_bounding_box;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const LogStream& operator<<(const LogStream& stream, const Path& path)
|
inline const LogStream& operator<<(const LogStream& stream, const Path& path)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue