Ita*_*ber 31 cocoa text core-animation objective-c antialiasing
对于使用Core Animation图层支持视图的项目工作的任何人来说,遗憾的是,对于未在预先设置的不透明背景上呈现的文本,禁用了子像素抗锯齿(文本平滑).现在,对于能够为其文本设置不透明背景的人(通过setBackgroundColor:
调用或Interface Builder中的等效设置),此问题不会出现太多问题.但对于其他人来说,绝对没有办法解决它,这不是一个人们无法忽视的事情.
我已经在网上寻找了两天以上的解决方案,并没有任何可用的东西出现.我想要做的就是创建一个在工作表窗口上设置的文本标签(不是用户可编辑的)(工作表窗口背景是透明的,因此将工作表的内容视图声明wantsLayer
为true会禁用窗口上所有标签的文本平滑); 非常简单.我已经看到很多有争议的解决方案(快速谷歌搜索将在许多其他地方提出这个主题),但到目前为止,所有这些解决方案依赖于人们能够并愿意与不透明的背景妥协(你不能在一张纸上使用).
到目前为止,我可以想象的最佳方向是将文本预渲染到文本平滑到图像上,然后像往常一样在图层支持的视图上显示图像.但是,这似乎不可能.我认为可以尝试的"正常"方式是:
NSAttributedString *string = [[self cell] attributedStringValue];
NSImage *textImage = [[NSImage alloc] initWithSize:[string size]];
[textImage lockFocus];
[string drawAtPoint:NSZeroPoint];
[textImage unlockFocus];
Run Code Online (Sandbox Code Playgroud)
但这似乎不起作用(很可能是因为调用时drawRect:
,图形上下文设置已禁用文本平滑 - 关闭子像素抗锯齿,而使用常规抗锯齿),但更多涉及的解决方案也没有找到这个问题(你在哪里创建自己的图形上下文).
那么如何做这样的事情呢?你能以某种方式"伪造"文本平滑的效果吗?是否有甚至黑客攻击的解决方案可以设置一些东西?我真的不想因为这个愚蠢的问题而放弃核心动画; 它有很多好处,可以节省大量的时间和代码.
编辑:经过大量搜索,我找到了一些东西.虽然线程本身只是重申了我的怀疑,但我想我可能已经找到了解决这个问题的方法:自定义CALayer
绘图.Timothy Wood在他的一篇回复中附上了一个示例项目,该项目使用几种技术显示字体平滑,其中一些技术起作用.我会考虑将它集成到我的项目中.
编辑#2:结果,上面的链接也是一个半身像.尽管链接的方法提供了亚像素抗锯齿,但它们在透明背景上也会失败.
如果您使用透明纸张,则事先不知道它下面的像素是什么.他们可能会改变.请记住,对于所有三种颜色,您都有一个Alpha通道:如果您将其设置为透明,则不会看到任何子像素效果,但如果您将其设置为不透明,则所有三个子元素都将与背景合成.如果为白色背景上的合成赋予边缘正确的颜色,如果背景更改为其他颜色,则看起来不正确.
例如,假设您在白色背景上绘制黑色文本,子元素顺序为RGB.右边缘可能是微弱的蓝色:高B值(远离字形的一侧的全亮度),略低但仍然高的R和G值(靠近字形的一侧的亮度较低).如果你现在将该像素合成在深灰色背景上,那么如果你直接在深灰色背景上渲染黑色文本,那么你将使它变得更亮.
基本上,您没有面对CoreAnimation的任意限制:在可能在任意背景上合成的透明层上使用子像素渲染是没有意义的.每个颜色通道需要一个单独的alpha,但由于缓冲区的像素格式是RGBA(或ARGB或其他任何东西),所以你不能拥有它.
但这引出了我们的解决方案.如果您知道背景将保持不变(例如,工作表显示在您控制其内容的窗口上),那么您可以简单地使图层不透明,用背景窗口的覆盖区域的副本填充它,然后渲染子像素抗锯齿的文字就可以了.基本上,您将使用背景预先组合图层.如果背景保持不变,这将看起来与正常的alpha合成相同,除了您现在可以进行亚像素文本渲染; 如果背景发生变化,那么你不得不放弃进行亚像素文本渲染(尽管我猜你可以继续复制背景并重新绘制不透明的叠加层).