aboutsummaryrefslogtreecommitdiff
path: root/src/platform
diff options
context:
space:
mode:
authorYuqian Yang <crupest@crupest.life>2025-09-21 23:40:30 +0800
committerYuqian Yang <crupest@crupest.life>2025-09-21 23:43:31 +0800
commit6b78788d049c90dab3aec01d7bb7193f3927dc75 (patch)
tree977cfe754ccafb94e3e6743937d9132d2184df2f /src/platform
parente31b0b8b37ae52e9402dc351e5fb0f361d30d0e0 (diff)
downloadcru-6b78788d049c90dab3aec01d7bb7193f3927dc75.tar.gz
cru-6b78788d049c90dab3aec01d7bb7193f3927dc75.tar.bz2
cru-6b78788d049c90dab3aec01d7bb7193f3927dc75.zip
HALF WORK!geo-arc
Diffstat (limited to 'src/platform')
-rw-r--r--src/platform/graphics/Geometry.cpp37
-rw-r--r--src/platform/graphics/quartz/Geometry.cpp14
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_);
}