I want to hide CALayer with CAShapeLayer , because changes to the form can be animated.
When I use CAShapeLayer as a mask, the rounded corners are stretched. However, if I take the same shape, create an NSImage with it and use the image to mask my CALayer , the rounded corners are fine.

Here is the code I use to mask the layers (you can also download the entire sample project ):
CGColorRef backgroundColor = CGColorCreateGenericRGB(0.0, 0.0, 0.0, 1.0f); [self.window.contentView setLayer:[CALayer layer]]; [self.window.contentView setWantsLayer:YES]; [[self.window.contentView layer] setFrame:[self.window.contentView frame]]; CALayer *imageBasedMaskLayer = [CALayer layer]; [imageBasedMaskLayer setContents:(id)[[self maskWithSize:NSMakeSize(50, 50)] CGImageForProposedRect:NULL context:nil hints:nil]]; [imageBasedMaskLayer setFrame:CGRectMake(0, 0, 50, 50)]; CALayer *layerWithImageBasedMaskLayer = [CALayer layer]; [layerWithImageBasedMaskLayer setBackgroundColor:backgroundColor]; [layerWithImageBasedMaskLayer setMask:imageBasedMaskLayer]; CAShapeLayer *shapeBasedMaskLayer = [CAShapeLayer layer]; CGPathRef maskShape = [self newMaskPathWithFrame:NSMakeRect(0, 0, 50, 50)]; [shapeBasedMaskLayer setPath:maskShape]; [shapeBasedMaskLayer setFillRule:kCAFillRuleEvenOdd]; CGPathRelease(maskShape); [shapeBasedMaskLayer setFrame:CGRectMake(0, 0, 50, 50)]; CALayer *layerWithShapeBasedMaskLayer = [CALayer layer]; [layerWithShapeBasedMaskLayer setBackgroundColor:backgroundColor]; [layerWithShapeBasedMaskLayer setMask:nil]; [layerWithShapeBasedMaskLayer setMask:shapeBasedMaskLayer]; [layerWithImageBasedMaskLayer setFrame:CGRectMake(50, 50, 50, 50)]; [layerWithShapeBasedMaskLayer setFrame:CGRectMake(120, 50, 50, 50)]; [[self.window.contentView layer] addSublayer:layerWithImageBasedMaskLayer]; [[self.window.contentView layer] addSublayer:layerWithShapeBasedMaskLayer]; CGColorRelease(backgroundColor);
And the two methods that I use to create NSImage and CGPathRef .
- (NSImage *)maskWithSize:(CGSize)size; { NSImage *maskImage = [[NSImage alloc] initWithSize:size]; [maskImage lockFocus]; [[NSColor blackColor] setFill]; CGPathRef mask = [self newMaskPathWithFrame:CGRectMake(0, 0, size.width, size.height)]; CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; CGContextAddPath(context, mask); CGContextFillPath(context); CGPathRelease(mask); [maskImage unlockFocus]; return [maskImage autorelease]; } - (CGPathRef)newMaskPathWithFrame:(CGRect)frame; { CGFloat cornerRadius = 3; CGFloat height = CGRectGetMaxY(frame); CGFloat width = CGRectGetMaxX(frame); CGMutablePathRef maskPath = CGPathCreateMutable(); CGPathMoveToPoint(maskPath, NULL, 0, height-cornerRadius); CGPathAddArcToPoint(maskPath, NULL, 0, height, cornerRadius, height, cornerRadius); CGPathAddLineToPoint(maskPath, NULL, width-cornerRadius, height); CGPathAddArcToPoint(maskPath, NULL, width, height, width, height-cornerRadius, cornerRadius); CGPathAddLineToPoint(maskPath, NULL, width, cornerRadius); CGPathAddArcToPoint(maskPath, NULL, width, 0, width-cornerRadius, 0, cornerRadius); CGPathAddLineToPoint(maskPath, NULL, cornerRadius, 0); CGPathAddArcToPoint(maskPath, NULL, 0, 0, 0, cornerRadius, cornerRadius); CGPathCloseSubpath(maskPath); return maskPath; }
Note that the actual mask I want to create is harder than a rounded rectangle, otherwise I would use some of the simple drawing methods. I tried various CGPath drawing CGPath , the problem did not disappear.
What am I missing here?