Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Convert NSBezierPath to CGPath (Swift 5.1, Xcode 11.3 (11C29))
extension NSBezierPath {
/// A `CGPath` object representing the current `NSBezierPath`.
var cgPath: CGPath {
let path = CGMutablePath()
let points = UnsafeMutablePointer<NSPoint>.allocate(capacity: 3)
if elementCount > 0 {
var didClosePath = true
for index in 0..<elementCount {
let pathType = element(at: index, associatedPoints: points)
switch pathType {
case .moveTo:
path.move(to: points[0])
case .lineTo:
path.addLine(to: points[0])
didClosePath = false
case .curveTo:
path.addCurve(to: points[2], control1: points[0], control2: points[1])
didClosePath = false
case .closePath:
path.closeSubpath()
didClosePath = true
@unknown default:
break
}
}
if !didClosePath { path.closeSubpath() }
}
points.deallocate()
return path
}
}
@rasronin
Copy link

rasronin commented Mar 11, 2015

Pure awesomeness. Thank you.

@kaishin
Copy link

kaishin commented May 24, 2015

👍

@keefo
Copy link

keefo commented Jan 17, 2021

Alert, This code has a bug at line 24.

path.addCurve(to: CGPoint(x: points[0].x, y: points[0].y), control1: control1, control2: control2)

It should be

path.addCurve(to: points[2], control1: points[0], control2: points[1])

@juliensagot
Copy link
Author

juliensagot commented Jan 18, 2021

@keefo Do you have an example of a non-working path so I can check?

@dceddia
Copy link

dceddia commented Apr 11, 2021

Thanks for this!

@juliensagot I was curious about @keefo's comment and found that Apple's docs say it is indeed (and confusingly) ordered 2, 0, 1 instead of 0, 1, 2. Check this docs page - the relevant part is the last sentence in the Discussion section:

For curve operations, the order of the points is controlPoint1 (points[0]), controlPoint2 (points[1]), endPoint (points[2]).

@keefo
Copy link

keefo commented Apr 11, 2021

Hi @juliensagot

@keefo Do you have an example of a non-working path so I can check?

I use this original code to draw a circle in my project.
it gives me weird results. So, I checked the Apple doc and updated line 24. It works now in my project.

https://github.com/keefo/NeewerLite/blob/main/NeewerLite/NeewerLite/Common/ColorWheel.swift#L112
https://github.com/keefo/NeewerLite/blob/main/NeewerLite/NeewerLite/Common/NSBezierPathExtensions.swift#L28

@juliensagot
Copy link
Author

juliensagot commented Apr 12, 2021

@keefo @dceddia Thank you guys! I've updated the gist 🙏

@pkclsoft
Copy link

pkclsoft commented Aug 15, 2021

Why do you call closeSubPath() at line 31? If you want a path that is not closed, then this causes issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment