1
1
mirror of https://github.com/exyte/Macaw.git synced 2024-08-15 16:10:39 +03:00

Merge pull request #689 from f3dm76/task/path-from-cgpath

Add toMacaw for CGPath
This commit is contained in:
Yuri Strot 2020-06-02 15:42:41 +07:00 committed by GitHub
commit b13d043073
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 70 additions and 0 deletions

View File

@ -99,4 +99,10 @@ extension UIScreen {
}
}
extension UIBezierPath {
var usesEvenOddFillRule: Bool {
return self.usesEvenOddFillRule
}
}
#endif

View File

@ -184,4 +184,10 @@ extension NSWindow {
}
}
extension NSBezierPath {
var usesEvenOddFillRule: Bool {
return self.windingRule == .evenOdd
}
}
#endif

View File

@ -153,3 +153,61 @@ public extension Node {
}
}
extension MBezierPath {
public func toMacaw() -> Path {
let fillRule: FillRule = self.usesEvenOddFillRule ? .evenodd : .nonzero
return self.cgPath.toMacaw(fillRule: fillRule)
}
}
extension CGPath {
public func toMacaw(fillRule: FillRule = .nonzero) -> Path {
func createPathSegment(type: PathSegmentType, points: UnsafeMutablePointer<CGPoint>, count: Int) -> PathSegment {
var data = [Double]()
for index in 0..<count {
let point = points[index]
data.append(contentsOf: [Double(point.x), Double(point.y)])
}
return PathSegment(type: type, data: data)
}
var segments = [PathSegment]()
self.forEach(body: { (element: CGPathElement) in
let segment: PathSegment
switch element.type {
case .moveToPoint:
segment = createPathSegment(type: .M, points: element.points, count: 1)
case .addLineToPoint:
segment = createPathSegment(type: .L, points: element.points, count: 1)
case .addQuadCurveToPoint:
segment = createPathSegment(type: .Q, points: element.points, count: 2)
case .addCurveToPoint:
segment = createPathSegment(type: .C, points: element.points, count: 3)
case .closeSubpath:
segment = PathSegment(type: .z)
@unknown default:
fatalError("Unknown element type: \(element.type)")
}
segments.append(segment)
})
return Path(segments: segments, fillRule: .nonzero)
}
private func forEach( body: @escaping @convention(block) (CGPathElement) -> Void) {
typealias Body = @convention(block) (CGPathElement) -> Void
func callback(info: UnsafeMutableRawPointer?, element: UnsafePointer<CGPathElement>) {
let body = unsafeBitCast(info, to: Body.self)
body(element.pointee)
}
let unsafeBody = unsafeBitCast(body, to: UnsafeMutableRawPointer.self)
self.apply(info: unsafeBody, function: callback)
}
}