How to get text in a CATextLayer to be clear How to get text in a CATextLayer to be clear ios ios

How to get text in a CATextLayer to be clear


Short answer — You need to set the contents scaling:

textLayer.contentsScale = [[UIScreen mainScreen] scale];

A while ago I learned that when you have custom drawing code, you have to check for the retina display and scale your graphics accordingly. UIKit takes care of most of this, including font scaling.

Not so with CATextLayer.

My blurriness came from having a .zPosition that was not zero, that is, I had a transform applied to my parent layer. By setting this to zero, the blurriness went away, and was replaced by serious pixelation.

After searching high and low, I found that you can set .contentsScale for a CATextLayer and you can set it to [[UIScreen mainScreen] scale] to match the screen resolution. (I assume this works for non-retina, but I haven't checked - too tired)

After including this for my CATextLayer the text became crisp. Note - it's not necessary for the parent layer.

And the blurriness? It comes back when you're rotating in 3D, but you don't notice it because the text starts out clear and while it's in motion, you can't tell.

Problem solved!


Swift

Set the text layer to use the same scale as the screen.

textLayer.contentsScale = UIScreen.main.scale

Before:

enter image description here

After:

enter image description here


Before setting shouldRasterize, you should:

  1. set the rasterizationScale of the base layer you are going to rasterize
  2. set the contentsScale property of any CATextLayers and possibly other types of layers(it never hurts to do it)

If you don't do #1, then the retina version of sub layers will look blurry, even for normal CALayers.

- (void)viewDidLoad {  [super viewDidLoad];  CALayer *mainLayer = [[self view] layer];  [mainLayer setRasterizationScale:[[UIScreen mainScreen] scale]];  CATextLayer *messageLayer = [CATextLayer layer];  [messageLayer setForegroundColor:[[UIColor blackColor] CGColor]];  [messageLayer setContentsScale:[[UIScreen mainScreen] scale]];  [messageLayer setFrame:CGRectMake(50, 170, 250, 50)];  [messageLayer setString:(id)@"asdfasd"];  [mainLayer addSublayer:messageLayer];  [mainLayer setShouldRasterize:YES];}