5

I was wondering if someone could please help. Basically I have some Objective C code below, does anyone know how I can attach this to a CAShapeLayer for Mac OS X not iOS?.


****//// Color Declarations
NSColor* fillColor = [NSColor colorWithCalibratedRed: 0 green: 0.886 blue: 0.886 alpha: 1];
NSColor* strokeColor = [NSColor colorWithCalibratedRed: 0 green: 0 blue: 0 alpha: 1];
//// Star Drawing
NSBezierPath* starPath = [NSBezierPath bezierPath];
[starPath moveToPoint: NSMakePoint(106, 91.5)];
[starPath lineToPoint: NSMakePoint(110.21, 82.56)];
[starPath lineToPoint: NSMakePoint(119.18, 86.7)];
[starPath lineToPoint: NSMakePoint(116.65, 77.15)];
[starPath lineToPoint: NSMakePoint(126.19, 74.56)];
[starPath lineToPoint: NSMakePoint(118.11, 68.86)];
[starPath lineToPoint: NSMakePoint(123.75, 60.75)];
[starPath lineToPoint: NSMakePoint(113.91, 61.58)];
[starPath lineToPoint: NSMakePoint(113.01, 51.74)];
[starPath lineToPoint: NSMakePoint(106, 58.7)];
[starPath lineToPoint: NSMakePoint(98.99, 51.74)];
[starPath lineToPoint: NSMakePoint(98.09, 61.58)];
[starPath lineToPoint: NSMakePoint(88.25, 60.75)];
[starPath lineToPoint: NSMakePoint(93.89, 68.86)];
[starPath lineToPoint: NSMakePoint(85.81, 74.56)];
[starPath lineToPoint: NSMakePoint(95.35, 77.15)];
[starPath lineToPoint: NSMakePoint(92.82, 86.7)];
[starPath lineToPoint: NSMakePoint(101.79, 82.56)];
[starPath closePath];
[fillColor setFill];
[starPath fill];
[strokeColor setStroke];
[starPath setLineWidth: 1];
[starPath stroke];****

Basically I use the application Paintcode and would like to create shapes then convert them to a CAShapeLayer that will be used to animate.

Any help would be greatly appreciated.

Regards.

Nightowl
  • 55
  • 1
  • 8
  • I think this post will help http://stackoverflow.com/questions/15318918/how-to-make-my-uibezierpath-animated-with-cashapelayer – BigBadOwl Jul 22 '13 at 13:32
  • I think the link is for iOS only as I have seen this before, I need some code for OS X. Thanks anyway. – Nightowl Jul 22 '13 at 18:26

1 Answers1

10

CAShapeLayer's path property is a CGPathRef, but, unlike with iOS's [UIBezierPath CGPath], there surprisingly isn't any built-in method to convert an OSX NSBezierPath to a CGPathRef. However, in the Apple docs they post a snippet to do the conversion at https://developer.apple.com/library/mac/documentation/cocoa/Conceptual/CocoaDrawingGuide/Paths/Paths.html#//apple_ref/doc/uid/TP40003290-CH206-SW2:

@implementation NSBezierPath (BezierPathQuartzUtilities)
// This method works only in OS X v10.2 and later.
- (CGPathRef)quartzPath
{
    int i, numElements;

    // Need to begin a path here.
    CGPathRef           immutablePath = NULL;

    // Then draw the path elements.
    numElements = [self elementCount];
    if (numElements > 0)
    {
        CGMutablePathRef    path = CGPathCreateMutable();
        NSPoint             points[3];
        BOOL                didClosePath = YES;

        for (i = 0; i < numElements; i++)
        {
            switch ([self elementAtIndex:i associatedPoints:points])
            {
                case NSMoveToBezierPathElement:
                    CGPathMoveToPoint(path, NULL, points[0].x, points[0].y);
                    break;

                case NSLineToBezierPathElement:
                    CGPathAddLineToPoint(path, NULL, points[0].x, points[0].y);
                    didClosePath = NO;
                    break;

                case NSCurveToBezierPathElement:
                    CGPathAddCurveToPoint(path, NULL, points[0].x, points[0].y,
                                        points[1].x, points[1].y,
                                        points[2].x, points[2].y);
                    didClosePath = NO;
                    break;

                case NSClosePathBezierPathElement:
                    CGPathCloseSubpath(path);
                    didClosePath = YES;
                    break;
            }
        }

        // Be sure the path is closed or Quartz may not do valid hit detection.
        if (!didClosePath)
            CGPathCloseSubpath(path);

        immutablePath = CGPathCreateCopy(path);
        CGPathRelease(path);
    }

    return immutablePath;
}
@end

You could paste in this category, and then set the shape on your layer with:

layer.path = [starPath quartzPath];
marcprux
  • 9,845
  • 3
  • 55
  • 72
  • you probably want this to be `CGPathRef quartzPath = [starPath quartzPath]; layer.path = quartzPath; CGPathRelease(quartzPath);` otherwise you'll leak the returned CGPathRef – rudy Mar 22 '16 at 21:21
  • 1
    Its amazing to me that 20 years on nobody at Apple bothered to just add a `cgPath` property. They rather put up a support article. Incredible. –  Mar 05 '21 at 09:45
  • Swift code: https://gist.github.com/juliensagot/9749c3a1df28c38fb9f9 – Rethunk Sep 20 '21 at 19:16