【问题标题】:Bad text rendering with Core Animation使用 Core Animation 渲染错误的文本
【发布时间】:2011-10-26 05:42:09
【问题描述】:

首先,我知道这个话题之前已经多次提出,但我发布这个问题是因为我过去使用的任何“解决方案”都没有在这个特定案例中起作用。我正在向由我的 NSToolbar 中的视图托管的 CALayer 绘制一些文本。文本如下所示:

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

那篇文章中提到的另一个解决方案是在绘制之前用不透明的背景颜色填充矩形,在这种情况下这是不可能的,因为工具栏背景是渐变的。有什么办法可以让这个文本看起来和绘制成普通 NSView 的文本一样漂亮吗?

【问题讨论】:

  • 我相信 CA 渲染没有子像素抗锯齿,因为它不知道图层与屏幕像素的对齐方式。但在许多情况下,图层完全对齐,因此子像素抗锯齿是合适的。我还没有找到具体的解决方案——+1,希望我们能得到一个很好的答案:)
  • 另外:您发布的第一个屏幕截图有什么问题?你想要的结果是什么?
  • 很难用语言来解释,但文字看起来有点过于尖锐/清晰。它看起来几乎是锯齿状的。从那张小屏幕截图中很难看出,但是一旦您看到与应用程序的其余部分相比的整体情况,就会非常明显
  • 我最近问了同样的问题。看看它;也许会有所帮助:stackoverflow.com/questions/6858205/…。不幸的是,你将不得不忍受它。这根本不可能……

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


【解决方案1】:

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

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

为了处理亚像素抗锯齿,每次修改图层时都必须重新计算图层内容的像素值,这将非常昂贵并且消除了在 GPU 上托管图层的全部意义,这就是让合成和渲染速度极快。

不透明背景上的文本可以使用SPAA的原因是文本在图层纹理存储到GPU之前进行了亚像素抗锯齿预渲染。如果文本的背景是透明的,这是不可能的。

您将不得不忍受这个限制。值得庆幸的是,当我们最终都获得 HiDPI 显示器时,这将不再是一个问题……看看 iPhone,它根本不做亚像素抗锯齿。在 iPhone 上,由于屏幕分辨率高,文字看起来还不错。

【讨论】:

  • 但是文本(例如,来自CATextLayer)在什么时候呈现?有没有简单的方法可以用亚像素抗锯齿来渲染它,只要你知道它总是与屏幕像素对齐?
  • 文本在发生变化时被渲染,本质上是作为位图写入支持 OpenGL 纹理的。我同意,如果可以在可以计算 SPAA 的情况下以某种方式解决此问题,那就太好了,但不幸的是,事实并非如此。如果您想更改它,请提交错误报告......
  • 但这有点可能。如果你有一个纯色背景的文本字段(标签),即使它的父视图是图层支持的,它似乎也使用了SPAA。是什么导致了这种情况发生?
  • 我实际上用这个信息更新了答案。基本上,文本可以在位图发送到 GPU 之前预渲染到不透明背景上。对于透明背景,这是不可能的。
  • 我相信它在图层上使用了opaque 标志,但这没关系。如果你欺骗它错误地执行SPAA,它看起来会更糟。如果你知道背景,你总是可以自己把整个东西(文本和背景)渲染成一个不透明的层。如果您不知道背景,那么您想要消除锯齿时 CA 也不知道。
【解决方案2】:

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

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

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

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

【讨论】:

  • 最后一个建议似乎是一个不错的建议。我会试一试,然后告诉你结果如何。
  • 我最终只是重新创建了渐变然后绘制它,它完美地工作。正如你所说,它可能会在未来的操作系统版本中发生变化,但我想我会有时间为那个事件做准备;-)。我将这个答案标记为正确,因为我实际上设法让它使用这种方法,但是 Rob 的答案也提供了一个很棒的技术解释。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-17
    • 2011-02-28
    • 1970-01-01
    • 1970-01-01
    • 2016-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多