CAShapeLayer as a mask for CALayer: rounded corners are stretched
CAShapeLayer as a mask for CALayer: rounded corners are stretched
- Subject: CAShapeLayer as a mask for CALayer: rounded corners are stretched
- From: Anton Sotkov <email@hidden>
- Date: Sat, 22 Oct 2011 06:23:21 +0300
Hi!
I want to mask a CALayer with CAShapeLayer, because changes to the shape can be animated.
When I use the CAShapeLayer as a mask, its rounded corners are stretched. However, if I take the same shape, create an image with it, and use the image to mask my CALayer, the rounded corners are perfectly fine.
Here's a screenshot of this behavior: http://pxl.fi/0t3Z0e2R2n1l2N2t2c3J (image-based mask on the left, shape-based on the right).
Here's the code I'm using to mask the layers (and you can download the whole example project at http://pxl.fi/1A2D2z0F1I030e1x1z1c).
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];
And the two methods I'm creating NSImage and CGPathRef with.
- (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;
}
Please note that the actual mask I want to create is more complicated than a rounded rect, otherwise I would've used some of the simpler drawing techniques. I've tried various CGPath drawing functions, but nothing changed. I've tried masking the layer on iOS and observed the same problem. There must be a mistake in my code, I just don't see where it is.
What am I missing here?
Thank you,
Anton._______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden