From 53c751b5140460b75fc3faa256707f44522ff3b8 Mon Sep 17 00:00:00 2001 From: Honghao Zhang Date: Sun, 15 Sep 2024 12:07:13 -0700 Subject: [PATCH] [graphics] add CGPath transform --- .../Universal/Graphics/CGPath+Transform.swift | 31 +++++++++++++------ .../Graphics/CGPath+TransformTests.swift | 25 +++++++++++++-- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/Sources/ChouTiUI/Universal/Graphics/CGPath+Transform.swift b/Sources/ChouTiUI/Universal/Graphics/CGPath+Transform.swift index f457358..4fe3855 100644 --- a/Sources/ChouTiUI/Universal/Graphics/CGPath+Transform.swift +++ b/Sources/ChouTiUI/Universal/Graphics/CGPath+Transform.swift @@ -156,32 +156,43 @@ public extension CGPath { return resizedPath } + // MARK: - Transform + + /// Creates an new immutable copy of the path transformed by a transformation matrix. + /// + /// - Parameters: + /// - transform: The transform to apply to the path. + /// - Returns: A new, immutable transformed path. + func transform(_ transform: CGAffineTransform) -> CGPath { + var transform = transform + guard let transformedPath = copy(using: &transform) else { + ChouTi.assertFailure("Failed to transform the path", metadata: ["path": "\(self)", "transform": "\(transform)"]) + return self + } + return transformedPath + } + // MARK: - Translate - /// Translate the path. + /// Creates an new immutable copy of the path translated by a certain offset. /// /// - Parameters: /// - point: The point represents the offset to translate the path by. - /// - Returns: A translated path. + /// - Returns: A new, immutable translated path. @inlinable @inline(__always) func translate(_ point: CGPoint) -> CGPath { translate(dx: point.x, dy: point.y) } - /// Translate the path by a certain offset. + /// Creates an new immutable copy of the path translated by a certain offset. /// /// - Parameters: /// - dx: The x-coordinate offset. /// - dy: The y-coordinate offset. - /// - Returns: A translated path. + /// - Returns: A new, immutable translated path. func translate(dx: CGFloat = 0, dy: CGFloat = 0) -> CGPath { - var transform = CGAffineTransform.translation(x: dx, y: dy) - guard let translatedPath = copy(using: &transform) else { - ChouTi.assertFailure("Fail to translate the path", metadata: ["path": "\(self)", "dx": "\(dx)", "dy": "\(dy)"]) - return self - } - return translatedPath + transform(CGAffineTransform.translation(x: dx, y: dy)) } } diff --git a/Tests/ChouTiUITests/Universal/Graphics/CGPath+TransformTests.swift b/Tests/ChouTiUITests/Universal/Graphics/CGPath+TransformTests.swift index ab40694..829c94c 100644 --- a/Tests/ChouTiUITests/Universal/Graphics/CGPath+TransformTests.swift +++ b/Tests/ChouTiUITests/Universal/Graphics/CGPath+TransformTests.swift @@ -268,6 +268,27 @@ class CGPath_TransformTests: XCTestCase { Assert.resetTestAssertionFailureHandler() } + // MARK: - Transform + + func test_transform_identity() { + let rect = CGRect(x: 10, y: 20, width: 100, height: 50) + let path = CGPath(rect: rect, transform: nil) + + let transformedPath = path.transform(CGAffineTransform.identity) + expect(transformedPath) == path + } + + func test_transform_scale() { + let rect = CGRect(x: 10, y: 20, width: 100, height: 50) + let path = CGPath(ellipseIn: rect, transform: nil) + + var scale = CGAffineTransform.scale(2, 2) + let transformedPath = path.transform(scale) + expect(transformedPath) == CGPath(ellipseIn: rect, transform: &scale) + print(transformedPath.boundingBoxOfPath) + expect(transformedPath) == CGPath(ellipseIn: CGRect(x: 20, y: 40, width: 200, height: 100), transform: nil) + } + // MARK: - Translate func test_translate_point() { @@ -318,8 +339,8 @@ class CGPath_TransformTests: XCTestCase { let dy: CGFloat = .nan Assert.setTestAssertionFailureHandler { message, metadata, file, line, column in - expect(message) == "Fail to translate the path" - expect(metadata) == ["path": "\(path)", "dx": "\(dx)", "dy": "\(dy)"] + expect(message) == "Failed to transform the path" + expect(metadata) == ["path": "\(path)", "transform": "\(CGAffineTransform.translation(dx, dy))"] } let translatedPath = path.translate(dx: dx, dy: dy)