diff options
author | Yuqian Yang <crupest@crupest.life> | 2025-09-21 23:40:30 +0800 |
---|---|---|
committer | Yuqian Yang <crupest@crupest.life> | 2025-09-21 23:43:31 +0800 |
commit | 6b78788d049c90dab3aec01d7bb7193f3927dc75 (patch) | |
tree | 977cfe754ccafb94e3e6743937d9132d2184df2f /src/platform/graphics | |
parent | e31b0b8b37ae52e9402dc351e5fb0f361d30d0e0 (diff) | |
download | cru-6b78788d049c90dab3aec01d7bb7193f3927dc75.tar.gz cru-6b78788d049c90dab3aec01d7bb7193f3927dc75.tar.bz2 cru-6b78788d049c90dab3aec01d7bb7193f3927dc75.zip |
HALF WORK!geo-arc
Diffstat (limited to 'src/platform/graphics')
-rw-r--r-- | src/platform/graphics/Geometry.cpp | 37 | ||||
-rw-r--r-- | src/platform/graphics/quartz/Geometry.cpp | 14 |
2 files changed, 51 insertions, 0 deletions
diff --git a/src/platform/graphics/Geometry.cpp b/src/platform/graphics/Geometry.cpp index b9503c4e..25e6808b 100644 --- a/src/platform/graphics/Geometry.cpp +++ b/src/platform/graphics/Geometry.cpp @@ -2,9 +2,12 @@ #include "cru/base/Exception.h" #include "cru/platform/Exception.h" +#include "cru/platform/GraphicsBase.h" +#include "cru/platform/Matrix.h" #include "cru/platform/graphics/Factory.h" #include <cmath> +#include <numbers> #include <unordered_set> namespace cru::platform::graphics { @@ -20,6 +23,40 @@ std::unique_ptr<IGeometry> IGeometry::CreateStrokeGeometry( u"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) { + 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) { + using std::swap; + swap(s1, s2); + } + + auto mid = (s1 + s2) / 2; + auto d = Point::Distance(s1, s2) / 2; + 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 start_angle = std::atan2(s1.y - center.y, s1.x - center.x); + auto end_angle = std::atan2(s2.y - center.y, s2.x - center.x); + if (end_angle < 0) { + end_angle += std::numbers::pi_v<float> * 2; + } + + return {matrix.Inverted()->TransformPoint(center), start_angle, end_angle}; +} + void IGeometryBuilder::RelativeMoveTo(const Point& offset) { MoveTo(GetCurrentPosition() + offset); } diff --git a/src/platform/graphics/quartz/Geometry.cpp b/src/platform/graphics/quartz/Geometry.cpp index e6558fbb..db0581a7 100644 --- a/src/platform/graphics/quartz/Geometry.cpp +++ b/src/platform/graphics/quartz/Geometry.cpp @@ -68,6 +68,20 @@ void QuartzGeometryBuilder::QuadraticBezierTo(const Point &control_point, control_point.y, end_point.x, end_point.y); } +void QuartzGeometryBuilder::ArcTo(const Point &radius, float angle, + bool is_large_arc, bool is_clockwise, + const Point &end_point) { + auto info = CalculateArcInfo(GetCurrentPosition(), radius, angle, + is_large_arc, is_clockwise, end_point); + + auto matrix = + Matrix::Translation(info.center) * Matrix::Scale(radius.x, radius.y); + CGAffineTransform transform = Convert(matrix); + + CGPathAddArc(cg_mutable_path_, &transform, 0, 0, 1, info.start_angle, + info.end_angle, true); +} + void QuartzGeometryBuilder::CloseFigure(bool close) { if (close) CGPathCloseSubpath(cg_mutable_path_); } |