CALayer和CGGradientRef是否支持反锯齿?

4
我在iPhone上使用CALayer绘制时遇到了奇怪的问题。我有一个根层,它添加了一堆表示“气泡”的子层。最终结果应该看起来像这样:http://www.expensivedna.com/IMG_0018.PNG http://www.expensivedna.com/IMG_0018.PNG。问题是,我似乎无法使图层反锯齿(请注意气泡上的锯齿)。我的代码覆盖了气泡CALayer的drawInContext方法,如下所示:
- (void)drawInContext:(CGContextRef)theContext{
CGContextSetAllowsAntialiasing(theContext, true);
CGContextSetShouldAntialias(theContext, true);

size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 1.0, 1.0, 0.5,  // Start color
                          1.0, 1.0, 1.0, 0.0 }; // End color
CGColorSpaceRef rgbColorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef glossGradient = 
CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);

CGPoint topCenter = CGPointMake(25, 20);
CGPoint midCenter = CGPointMake(25, 25);
CGContextDrawRadialGradient(theContext, glossGradient, midCenter, 20, topCenter, 10, kCGGradientDrawsAfterEndLocation); 

现在真正奇怪的是,如果我稍微修改绘图代码,只绘制普通的红色圆圈,如下所示:

- (void)drawInContext:(CGContextRef)theContext{
CGContextSetAllowsAntialiasing(theContext, true);
CGContextSetShouldAntialias(theContext, true);

CGContextSetFillColorWithColor(theContext, [UIColor redColor].CGColor);
CGContextFillEllipseInRect(theContext, CGRectMake(0, 0, 40,40));
}

一切似乎都进行了抗锯齿处理:

http://www.expensivedna.com/IMG_0017.PNG http://www.expensivedna.com/IMG_0017.PNG

我似乎无法理解这种看似奇怪的行为。我是否错过了渐变和普通圆之间的某些区别?

谢谢大家。

3个回答

4
感谢大家的帮助。事实证明,答案是你们两个的答案(coob和Alex)的组合。基本上看起来CGDrawRadialGradient函数只在起始圆上有锯齿,而不是结束圆。由于我想要两个都有锯齿边缘,所以我首先将函数设置为从内部向外绘制,这样就解决了第一个“边缘”,但产生了以下结果:

步骤1

然后,像coob建议的那样,我对图像进行剪切,这样就可以在气泡的最终边缘周围产生漂亮的锯齿效果:

步骤2

看起来对我来说已经足够好了!
- (void)drawInContext:(CGContextRef)theContext{
CGContextSetAllowsAntialiasing(theContext, true);
CGContextSetShouldAntialias(theContext, true);

size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 1.0, 1.0, 0.0,  // Start color
              1.0, 1.0, 1.0, 0.5 }; // End color
CGColorSpaceRef rgbColorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef glossGradient = 
CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);

CGContextAddEllipseInRect(theContext, CGRectMake(5, 5, 40, 40));
CGContextClip(theContext);

CGPoint topCenter = CGPointMake(25, 20);
CGPoint midCenter = CGPointMake(25, 25);
CGContextDrawRadialGradient(theContext, glossGradient, topCenter, 10, midCenter, 20, kCGGradientDrawsAfterEndLocation);

}


2

Jeff - 将topCenter稍微往外移一点,并使用带有圆形遮罩的CGContextClipToMask。

编辑:实际上更好的方法是使用带有矢量剪切路径的CGContextClip。

编辑2:示例代码:

CGContextAddEllipseInRect(theContext, CGRectMake(20, 20, 10, 10));
CGContextClip(theContext);

在绘制渐变之前,将此添加进去,并向外扩展一点。

提示:我不得不将我的矩形插入一个1点,以完全消除这里的锯齿。 - mattorb

0
也许尝试去掉 kCGGradientDrawsAfterEndLocation?它可能会对 alpha 做出奇怪的影响。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接