Text drawn using Cocoa (OS X) in CALayer
and CATextLayer
comes out all grainy. What method/approach must be used to get the text to come out crisp/clear?
I am happy for the text to be backed by an opaque background - I know that the question would be even more complex if it needed to be transparent.
I can't use an NSView derived instance (like NSTextField) to represent the text in my solution - I am using CALayer because of its more lightweight nature.
EDIT
I am updating with code I have tried based on comments below:
The following is intended to be a custom CATextLayer class where the background color is being pre-set to be opaque prior to the text being composed with it such that sub-pixel anti aliasing can take place:
class TextLayer: CATextLayer {
override func drawInContext(ctx: CGContext!) {
CGContextSaveGState(ctx)
CGContextSetRGBFillColor (ctx, 1, 1, 1, 1)
CGContextFillRect (ctx, self.bounds)
CGContextSetShouldSmoothFonts (ctx, true)
super.drawInContext(ctx)
CGContextSaveGState(ctx)
}
}
This custom derived CATextLayer is then used in a custom view as follows:
override func awakeFromNib() {
self.wantsLayer = true
var backingLayer = self.layer
var textLayer = TextLayer()
textLayer.string = "ABC"
textLayer.fontSize = 16
textLayer.foregroundColor = NSColor.blackColor().CGColor
textLayer.frame = NSMakeRect(0, 0, 80, 40)
backingLayer?.addSublayer(textLayer)
textLayer.setNeedsDisplay()
}
The end result is STILL a grainy picture on my retina macBook Pro.
Playing around with a few properties on CALayer yielded the solution...
For the code above to render the fonts smoothly and in-line with others on a retina mac it appears that you also need to set:
textLayer.contentsScale = 2.0
in the NSView subclass.
My understanding is that this generates a more detailed bitmap from the underlying image that more closely matches the Retina capable hardware.