8

According to the documentation, it is possible to enable font smoothing inside CATextLayer:

Text can only be drawn using sub-pixel antialiasing when it is composited into an existing opaque background at the same time that it's rasterized.

Here is how I understand this sentence:

@implementation CATextLayerWithFontSmoothing
-(id)init {
    self=[super init];
    if (self) {
    CALayer * whiteBackground = [CALayer layer];
    CATextLayer * blackText = [CATextLayer layer];

    [whiteBackground setBounds:NSMakeRect(0, 0, 300, 300)];
    [blackText setBounds:NSMakeRect(0, 0, 300, 300)];

    [whiteBackground setBackgroundColor:[NSColor whiteColor].CGColor];
    [blackText setForegroundColor:[NSColor blackColor].CGColor];
    [blackText setString:@"CATextLayer"];

    [blackText setShouldRasterize:YES];

    [self addSublayer:whiteBackground];
    [self addSublayer: blackText];

    }
    return self;

which doesn't work. Text is not drawn using subpixel anti-aliasing.

alecail
  • 3,993
  • 4
  • 33
  • 52
  • Have you tried setting the text layer's background color? `[blackText setBackgroundColor:[NSColor whiteColor].CGColor]` – rob mayoff Feb 10 '13 at 19:41
  • @robmayoff I admit I have forgotten to try setting the background color to whiteColor, but it doesn't work, ie it does non subpixel aa. – alecail Feb 10 '13 at 20:09
  • I'm working through this myself at the moment. At least one problem with the code above is that you're telling the blackText layer to rasterise in to itself, which won't help. You need to tell a super layer to rasterise its sub layers in to it when it renders (by setting 'setShouldRasterize:' on it. My reading of that bit of the documentations suggests that if you do this (on the super layer) the sub-CATextLayer will be rasterised in to the super layer with anti-alising. I'll be testing later, unless I find another approach. – Benjohn Dec 17 '13 at 14:13

6 Answers6

9

The method described here works:

Case 2: If you're using a CATextLayer directly, you'll need to subclass CATextLayer and do something like the following in your drawing code:

- (void)drawInContext:(CGContextRef)ctx
{
CGContextSetRGBFillColor (ctx, r, g, b, a);
CGContextFillRect (ctx, [self bounds]);
CGContextSetShouldSmoothFonts (ctx, true);
[super drawInContext:ctx];
}

Here is a comparison of smoothed vs non-smoothed:

text on a regular CATextLayer

text with sub-pixel-aa

800% zoom of both layers

PS: Don't look at this answer on a CRT.

alecail
  • 3,993
  • 4
  • 33
  • 52
3

May be late. But I see that this question has a perfect solution, as Steve's answer, and nacho4d's comment:

How to get text in a CATextLayer to be clear

Community
  • 1
  • 1
vietstone
  • 8,784
  • 16
  • 52
  • 79
2

The way I understand this documentation, it says that CATextLayer always disables sub-pixel antialiasing. The sentence you quoted is just given as an explanation for this, not as instructions on how to enable it – it's followed by:

Setting the opacity property of the layer to YES does not change the rendering mode.

...which implies that even if you use an opaque background for the layer, this won't change the fact that CATextLayer doesn't use sub-pixel-aa.

omz
  • 53,243
  • 5
  • 129
  • 141
1

If you came searching for an issue where CATextLayer is rendering slightly blurry text in OSX, after much wall head banging, I got the sharp clear text by doing:

text_layer.contentsScale = self.window!.backingScaleFactor
text_layer.zPosition = 0

(I also set the views background layer contentsScale to be the same).

James Alvarez
  • 7,159
  • 6
  • 31
  • 46
1

Accepted answer do not work for my.

I found working solution on Ignacio Nieto blog

textLayer.contentsScale = UIScreen.mainScreen().scale
George
  • 643
  • 9
  • 23
0

the most common case is to have clear sharp visible fonts, so in Objective-C it would look like...

CATextLayer *text = [CATextLayer layer];
text.allowsEdgeAntialiasing = NO;
text.allowsFontSubpixelQuantization = YES;
// the following is a CGFloat, so can even be scaled down, to make it pixelish
text.contentsScale = [UIScreen mainScreen].scale;
text.frame = CGRectInset(self.frame, 0, 5);
text.foregroundColor = UIColor.orangeColor.CGColor;
text.fontSize = 36.0;
text.font = (__bridge CFTypeRef _Nullable)([UIFont fontWithName:@"HelveticaNeue-UltraLight" size:text.fontSize]);
[self.layer addSublayer:text];

text.fontSize is ignored when setting .font property but before setting the font with bridging it can be used to store the fonts size when creating the font

Ol Sen
  • 3,163
  • 2
  • 21
  • 30