Как заставить CATextLayer сгладить текст?

Согласно документации, можно включить шрифт сглаживание внутри 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.

Вот как я понимаю эту фразу:

@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;

что не работает. Текст не рисуется с использованием субпиксельного сглаживания.


person alecail    schedule 10.02.2013    source источник
comment
Вы пытались установить цвет фона текстового слоя? [blackText setBackgroundColor:[NSColor whiteColor].CGColor]   -  person rob mayoff    schedule 10.02.2013
comment
@robmayoff Признаюсь, я забыл попробовать установить цвет фона на whiteColor, но это не работает, т. е. не субпиксельное aa.   -  person alecail    schedule 11.02.2013
comment
Я сама работаю над этим в данный момент. По крайней мере, одна проблема с приведенным выше кодом заключается в том, что вы говорите слою blackText растеризовать сам себя, что не поможет. Вам нужно сообщить суперслою, чтобы он растеризовал свои подслои при рендеринге (установив для него «setShouldRasterize:». Мое чтение этого фрагмента документации предполагает, что если вы сделаете это (на суперслое) -CATextLayer будет растрирован в суперслой со сглаживанием.Я буду тестировать позже, если не найду другой подход.   -  person Benjohn    schedule 17.12.2013


Ответы (6)


Метод, описанный здесь, работает:

Случай 2: Если вы используете CATextLayer напрямую, вам нужно создать подкласс CATextLayer и сделать что-то вроде следующего в коде рисования:

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

Вот сравнение сглаженного и несглаженного:

текст на обычном CATextLayer

текст с субпикселем-aa

800% масштаб обоих слоев

PS: не смотрите на этот ответ на ЭЛТ.

person alecail    schedule 10.02.2013

Может быть поздно. Но я вижу, что этот вопрос имеет идеальное решение, как ответ Стива и комментарий nacho4d:

Как сделать текст в CATextLayer четким

person vietstone    schedule 10.09.2013

Насколько я понимаю в этой документации, там сказано, что CATextLayer всегда отключает субпиксельное сглаживание. Процитированное вами предложение дано просто как объяснение этого, а не как инструкция о том, как его включить — за ним следует:

Установка для свойства непрозрачности слоя значения YES не меняет режим рендеринга.

... что означает, что даже если вы используете непрозрачный фон для слоя, это не изменит того факта, что CATextLayer не использует субпиксель-аа.

person omz    schedule 10.02.2013

Если вы искали проблему, из-за которой CATextLayer отображает слегка размытый текст в OSX, после большого удара головой о стену я получил четкий четкий текст, выполнив:

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

(Я также устанавливаю содержимоеScale фонового слоя представлений таким же).

person James Alvarez    schedule 04.02.2015
comment
какой из вариантов лучше window.backingScaleFactor или UIScreen.mainScreens backingScaleFactor - person Sangram Shivankar; 14.08.2018

Принятый ответ не работает для моего.

Я нашел рабочее решение в блоге Игнасио Ньето

textLayer.contentsScale = UIScreen.mainScreen().scale
person George    schedule 21.06.2016

наиболее распространенным случаем является наличие четких видимых шрифтов, поэтому в Objective-C это будет выглядеть так...

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 игнорируется при установке свойства .font, но перед установкой шрифта с мостом его можно использовать для сохранения размера шрифта при создании шрифта

person Ol Sen    schedule 04.10.2018