First of all, I know this topic has been brought up several times before but I'm posting this question because none of the "solutions" I've used in the past have worked in this specific case. I'm drawing some text to a CALayer
that is hosted by a view inside my NSToolbar. Here's开发者_如何学Go what the text look likes:
I tried using a suggestion from this StackOverflow post, which is to call CGContextSetShouldSmoothFonts(ctx, false)
to turn off subpixel antialiasing before drawing into the context. This is a solution that has given me acceptable results in the past, but in this case it seems to have made the text look even worse:
The other solution mentioned in that post is to fill the rect with an opaque background color before drawing, which simply isn't possible in this case because the toolbar background is a gradient. Is there anything I can do to make this text look as nice as text drawn into a plain NSView
?
The reason sub-pixel antialiasing is not possible is that behind the scenes, CALayers
are essentially just OpenGL textures.
This means they are bitmaps handled and rendered directly by the GPU. The GPU knows nothing about text and so can't apply sub-pixel antialiasing.
In order to handle sub-pixel antialiasing, it would have to recalculate the pixel values of the layer content each time the layer was modified, which would be prohibitively expensive and remove the whole point of hosting the layer on the GPU, which is to make compositing and rendering extremely fast.
The reason that text on opaque backgrounds can use SPAA is that the text is pre-rendered with sub-pixel anti-aliasing before the layer texture is stored on the GPU. This is not possible if the background of the text is transparent.
You will have to live with this limitation. Thankfully, it will no longer be an issue when we eventually all get HiDPI displays… have a look at the iPhone, which does not do sub-pixel antialiasing at all. On the iPhone, text looks just fine thanks to the high screen resolution.
Unfortunately there's no magic fix. At the end of the day, the text must be drawn on to an opaque background to get SPAA. It sucks, but it makes a lot of sense given how layers work. And honestly, I can't see Apple ever "fixing" this. I think this is the reason they've stuck with the old software compositing model for so long. It's a hard problem and they're hoping to ignore it by going high-DPI.
But anyways, there are a few ways to get SPAA in your specific case.
You could try to re-create the gradient and draw it yourself when you draw your text. But obviously that's brittle if the toolbar gradient changes in an OS update, and it could be hard to get the gradient to match exactly right.
Or you could actually try to grab an image of the toolbar background, either at runtime or ahead of time, and draw that as your background.
I have a good experience in OpenGL, animation, real-time scrolling text, rendering text on textures using multisample AA. A 4 bytes texture, with alpha, doesn't care about the background is or isn't transparent. OpenGL renders that transparent texture in real time. And remaking a texture at any small change of the glyphs, is a question of microseconds. Apple could fix that.
精彩评论