Skip to content

Instantly share code, notes, and snippets.

@jorgenisaksson
Created June 10, 2014 18:01
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save jorgenisaksson/76a8dae54fd3dc4e31c2 to your computer and use it in GitHub Desktop.
Save jorgenisaksson/76a8dae54fd3dc4e31c2 to your computer and use it in GitHub Desktop.
Create a CGPath from an NSBezierPath in Swift. Great for CALayers for example.
// Adapted from Cocoa Drawing Guide's "Create a CGPathRef fram an NSBezierPath Object"
func CGPathFromNSBezierPath(nsPath: NSBezierPath) -> CGPath! {
if nsPath.elementCount == 0 {
return nil
}
let path = CGPathCreateMutable()
var didClosePath = false
for i in 0..nsPath.elementCount {
var points = NSPoint[](count: 3, repeatedValue: NSZeroPoint)
switch nsPath.elementAtIndex(i, associatedPoints: &points) {
case .MoveToBezierPathElement:CGPathMoveToPoint(path, nil, points[0].x, points[0].y)
case .LineToBezierPathElement:CGPathAddLineToPoint(path, nil, points[0].x, points[0].y)
case .CurveToBezierPathElement:CGPathAddCurveToPoint(path, nil, points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y)
case .ClosePathBezierPathElement:CGPathCloseSubpath(path)
didClosePath = true
}
}
if !didClosePath {
CGPathCloseSubpath(path)
}
return CGPathCreateCopy(path)
}
@icodeforlove
Copy link

Swift 2.0

extension NSBezierPath {
    func toCGPath () -> CGPath? {
        if self.elementCount == 0 {
            return nil
        }

        let path = CGPathCreateMutable()
        var didClosePath = false

        for i in 0...self.elementCount-1 {
            var points = [NSPoint](count: 3, repeatedValue: NSZeroPoint)

            switch self.elementAtIndex(i, associatedPoints: &points) {
            case .MoveToBezierPathElement:CGPathMoveToPoint(path, nil, points[0].x, points[0].y)
            case .LineToBezierPathElement:CGPathAddLineToPoint(path, nil, points[0].x, points[0].y)
            case .CurveToBezierPathElement:CGPathAddCurveToPoint(path, nil, points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y)
            case .ClosePathBezierPathElement:CGPathCloseSubpath(path)
            didClosePath = true;
            }
        }

        if !didClosePath {
            CGPathCloseSubpath(path)
        }

        return CGPathCreateCopy(path)
    }
}

@jorgenisaksson
Copy link
Author

jorgenisaksson commented Mar 24, 2017

Swift 3.x

import Foundation
import AppKit
import CoreGraphics

public extension NSBezierPath
{
    public var CGPath: CGPath
    {
        let path = CGMutablePath()
        var points = [CGPoint](repeating: .zero, count: 3)
        for i in 0 ..< self.elementCount {
            let type = self.element(at: i, associatedPoints: &points)
            switch type {
            case .moveToBezierPathElement: path.move(to: CGPoint(x: points[0].x, y: points[0].y) )
            case .lineToBezierPathElement: path.addLine(to: CGPoint(x: points[0].x, y: points[0].y) )
            case .curveToBezierPathElement: path.addCurve(      to: CGPoint(x: points[2].x, y: points[2].y),
                                                                control1: CGPoint(x: points[0].x, y: points[0].y),
                                                                control2: CGPoint(x: points[1].x, y: points[1].y) )
            case .closePathBezierPathElement: path.closeSubpath()
            }
        }
        return path
    }
}

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