Antialiased drawing in a CALayer
Greetings! I'm trying to draw a series of c开发者_Python百科ircles in a CALayer that resides in a zoomable UISCrollView. This is the layer that zooms on pinch. If i draw the circles using CAShapeLayer, then they zoom beautifully:
CAShapeLayer plotLayer = [CAShapeLayer layer];
plotLayer.bounds = self.bounds;
plotLayer.anchorPoint = CGPointZero;
plotLayer.position = CGPointZero;
CGMutablePathRef path = CGPathCreateMutable();
for (id one in many) {
CGRect ellipseRect = [one circleRect];
CGPathAddEllipseInRect(path, NULL, ellipseRect);
}
plotLayer.path = path
CFRelease(path);
[self.layer addSublayer:plotLayer];
[plotLayer setNeedsDisplay];
However, when i try to draw them with vanilla core graphics in my drawLayer:inContext: method, the circles get very jaggy (downright pro-aliased!) No amount of antialias jiggery-pokery seems to help:
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context
{
CGContextSetAllowsAntialiasing(context, true);
CGContextSetShouldAntialias(context, true);
CGContextClip(context);
for (id one in many) {
CGRect ellipseRect = [one circleRect];
CGContextStrokeEllipseInRect(context, ellipseRect);
}
}
I'm trying to figure out what CAShapeLayer is doing to get such nice antialiasing so that (aside from my own edification) i can take full advantage of core graphics in my drawing rather than just the stroke/fill that i can get with CAShapeLayer. Am i just missing a transform somewhere?
Many thanks!
Short answer: contentsScale
Longer answer: (taken almost verbatim from pe8ter at Vector like drawing for zoomable UIScrollView):
You can get a better rendering by setting the contentScale property on the layer in question after zooming:
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView
withView:(UIView *)view
atScale:(float)scale
{
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithBool:YES]
forKey:kCATransactionDisableActions];
uglyBlurryTextLayer.contentsScale = scale;
[CATransaction commit];
}
There's a (typically excellent) description by Brad Larson of when the actual drawing occurs (spoiler, it usually only occurs once despite how many transforms are applied) at So a CALayer does not contain a content bitmap of a view?. Based on this, i can only assume that setting contentsScale causes the layer to render again.
I haven't tried this but if your circles get jaggy when resizing the view, it might be because of the interpolation quality.
Have you tried setting the interpolation quality to high?
CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
精彩评论