From c3412099485e06109f83b3105ce6c083c2b65dd1 Mon Sep 17 00:00:00 2001 From: Yuqian Yang Date: Sun, 21 Sep 2025 23:40:30 +0800 Subject: HALF WORK! --- src/platform/graphics/Geometry.cpp | 52 +++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) (limited to 'src/platform/graphics/Geometry.cpp') diff --git a/src/platform/graphics/Geometry.cpp b/src/platform/graphics/Geometry.cpp index 859a7bd6..e92ea3c9 100644 --- a/src/platform/graphics/Geometry.cpp +++ b/src/platform/graphics/Geometry.cpp @@ -1,10 +1,14 @@ #include "cru/platform/graphics/Geometry.h" - #include "cru/base/StringUtil.h" +#include "cru/base/log/Logger.h" +#include "cru/platform/GraphicsBase.h" +#include "cru/platform/Matrix.h" #include "cru/platform/graphics/Factory.h" #include +#include #include +#include namespace cru::platform::graphics { bool IGeometry::StrokeContains(float width, const Point& point) { @@ -19,6 +23,48 @@ std::unique_ptr IGeometry::CreateStrokeGeometry( "not supported on this platform."); } +IGeometryBuilder::ArcInfo IGeometryBuilder::CalculateArcInfo( + const Point& start_point, const Point& radius, float angle, + bool is_large_arc, bool is_clockwise, const Point& end_point) { + using std::swap; + + auto matrix = + Matrix::Rotation(-angle) * Matrix::Scale(1 / radius.x, 1 / radius.y); + auto s1 = matrix.TransformPoint(start_point), + s2 = matrix.TransformPoint(end_point); + + if (!is_clockwise) { + std::swap(s1, s2); + } + + auto mid = (s1 + s2) / 2; + auto d = s1.Distance(s2) / 2; + if (d > 1) { + CruLogWarn(kLogTag, "Invalid Arc."); + return {}; + } + + auto dc = std::sqrt(1 - d * d); + auto a = std::atan2(s1.x - s2.x, s2.y - s1.y); + Point center(mid.x - dc * std::cos(a), mid.y - dc * std::sin(a)); + + if (std::abs(center.x) < 0.000001) { + center.x = 0.f; + } + if (std::abs(center.y) < 0.000001) { + center.y = 0.f; + } + + auto a1 = std::atan2(s1.y - center.y, s1.x - center.x); + auto a2 = std::atan2(s2.y - center.y, s2.x - center.x); + auto a3 = a2 > a1 ? a2 - a1 : std::numbers::pi_v * 2 - (a1 - a2); + if ((a3 > std::numbers::pi_v) != is_large_arc) { + std::swap(a1, a2); + } + + return {matrix.Inverted()->TransformPoint(center), a1, a2}; +} + void IGeometryBuilder::RelativeMoveTo(const Point& offset) { MoveTo(GetCurrentPosition() + offset); } @@ -233,9 +279,9 @@ void IGeometryBuilder::ParseAndApplySvgPathData(std::string_view path_d) { ++position; } - auto result = cru::string::ParseToNumber( - path_d.substr(position), cru::string::ParseToNumberFlags::AllowTrailingJunk); + path_d.substr(position), + cru::string::ParseToNumberFlags::AllowTrailingJunk); if (!result.valid) throw Exception("Invalid svg path data number."); -- cgit v1.2.3