使用Core Animation进行错误的文本渲染

时间:2011-08-13 00:30:47

标签: objective-c cocoa core-animation calayer nsview

首先,我知道这个话题已经提出过几次,但是我发布了这个问题,因为我过去使用过的“解决方案”都没有在这个具体案例中发挥过作用。我正在为我的NSToolbar中的视图托管的CALayer绘制一些文本。这是文本的样子:

Font smoothing on

我尝试使用this StackOverflow帖子中的建议,即在绘制到上下文之前调用CGContextSetShouldSmoothFonts(ctx, false)关闭子像素抗锯齿。这个解决方案在过去给了我可接受的结果,但在这种情况下,它似乎使文本看起来更糟糕:

Font smoothing off

该帖中提到的另一个解决方案是在绘制之前用不透明的背景颜色填充矩形,在这种情况下这是不可能的,因为工具栏背景是渐变。我能做些什么来使这个文本看起来像绘制到普通NSView的文本一样好吗?

3 个答案:

答案 0 :(得分:7)

无法进行子像素抗锯齿的原因是幕后,CALayers基本上只是OpenGL纹理。

这意味着它们是由GPU直接处理和渲染的位图。 GPU对文本一无所知,因此无法应用子像素抗锯齿。

为了处理子像素抗锯齿,每次修改图层时都必须重新计算图层内容的像素值,这将非常昂贵,并且取消了在GPU上托管图层的整个点,是使合成和渲染速度极快。

不透明背景上的文字可以使用SPAA的原因是,在将图层纹理存储在GPU上之前,文本是使用子像素消除锯齿进行预渲染的。如果文本的背景是透明的,则无法进行此操作。

你必须忍受这个限制。值得庆幸的是,当我们最终获得HiDPI显示器时,它将不再是一个问题...看看iPhone,它根本不进行亚像素抗锯齿。在iPhone上,由于屏幕分辨率高,文本看起来很好。

答案 1 :(得分:5)

不幸的是,没有神奇的修复。在一天结束时,文本必须被绘制到不透明背景以获得SPAA。它很糟糕,但考虑到层的工作方式,这很有意义。老实说,我不能看到苹果公司“修复”这个问题。我认为这就是他们长期坚持旧软件合成模型的原因。这是一个难题,他们希望通过高DPI来忽略它。

但无论如何,在您的具体情况下,有几种方法可以获得SPAA。

您可以尝试重新创建渐变并在绘制文本时自己绘制。但是,如果工具栏渐变在操作系统更新中发生变化,那么显然会很脆弱,并且可能很难让渐变完全匹配。

或者您可以尝试在运行时或提前获取工具栏背景的图像,并将其绘制为背景。

答案 2 :(得分:0)

我在OpenGL,动画,实时滚动文本方面有很好的经验,使用多重采样AA在纹理上渲染文本。带有alpha的4字节纹理并不关心背景是透明的还是不透明的。 OpenGL实时渲染透明纹理。并且在字形的任何小变化处重建纹理都是微秒的问题。 Apple可以解决这个问题。