开发者

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);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜