Как получить текст в CATextLayer, чтобы быть ясным


я CALayer С CATextLayer и текст выходит размытым. В документах они говорят о" субпиксельном сглаживании", но это не имеет большого значения для меня. У кого-нибудь есть фрагмент кода, который делает CATextLayer С небольшим количеством текста, который ясно?

вот текст из документации Apple:

Примечание: CATextLayer отключает субпиксельное сглаживание при рендеринге текста. Текст может быть нарисован только с помощью субпиксельного сглаживания, когда он есть комбинируется в существующий непрозрачный фон, в то же время, что он растеризован. Невозможно нарисовать субпиксельно-сглаженный текст с помощью сам, ли в изображение или слой, отдельно заранее наличие фоновых пикселей для переплетения текстовых пикселей. Установочный свойство непрозрачности слоя YES не изменяет отрисовку режим.

второе предложение подразумевает, что можно получить красивый текст, если один composites на existing opaque background at the same time that it's rasterized. вот отлично, но как мне его скомпоновать и как вы даете ему непрозрачный фон и как вы растеризуете его?

код, который они используют в своем примере меню киоска, таков: (это OS X, а не iOS, но я предполагаю, что это работает!)

NSInteger i;
for (i=0;i<[names count];i++) {
    CATextLayer *menuItemLayer=[CATextLayer layer];
    menuItemLayer.string=[self.names objectAtIndex:i];
    menuItemLayer.font=@"Lucida-Grande";
    menuItemLayer.fontSize=fontSize;
    menuItemLayer.foregroundColor=whiteColor;
    [menuItemLayer addConstraint:[CAConstraint
         constraintWithAttribute:kCAConstraintMaxY
                      relativeTo:@"superlayer"
                       attribute:kCAConstraintMaxY
                          offset:-(i*height+spacing+initialOffset)]];
    [menuItemLayer addConstraint:[CAConstraint
         constraintWithAttribute:kCAConstraintMidX
                      relativeTo:@"superlayer"
                       attribute:kCAConstraintMidX]];
    [self.menuLayer addSublayer:menuItemLayer];
} // end of for loop 

спасибо!


EDIT: добавление кода, который я фактически использовал, что привело к размытому тексту. Это из связанного вопроса, который я опубликовал о добавлении UILabel, а не CATextLayer но вместо этого получаю черный ящик. http://stackoverflow.com/questions/3818676/adding-a-uilabels-layer-to-a-calayer-and-it-just-shows-black-box

CATextLayer* upperOperator = [[CATextLayer alloc] init];
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGFloat components1[4] = {1.0, 1.0, 1.0, 1.0};
CGColorRef almostWhite = CGColorCreate(space,components1);
CGFloat components2[4] = {0.0, 0.0, 0.0, 1.0};
CGColorRef almostBlack = CGColorCreate(space,components2);
CGColorSpaceRelease(space);
upperOperator.string = [NSString stringWithFormat:@"13"];
upperOperator.bounds = CGRectMake(0, 0, 100, 50);
upperOperator.foregroundColor = almostBlack;
upperOperator.backgroundColor = almostWhite;
upperOperator.position = CGPointMake(50.0, 25.0);
upperOperator.font = @"Helvetica-Bold";
upperOperator.fontSize = 48.0f;
upperOperator.borderColor = [UIColor redColor].CGColor;
upperOperator.borderWidth = 1;
upperOperator.alignmentMode = kCAAlignmentCenter;
[card addSublayer:upperOperator];
[upperOperator release];
CGColorRelease(almostWhite);
CGColorRelease(almostBlack);

EDIT 2: Смотрите мой ответ ниже, как это было решено. СБГ.

7 83

7 ответов:

короткий ответ - вам нужно установить масштабирование содержимого:

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

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

не так CATextLayer.

моя размытость произошла от того, что .zPosition это не было нулем, то есть у меня было преобразование, примененное к моему родительскому слою. Установив это значение равным нулю, размытость исчезла, и ее сменила серьезная пикселизация.

после поиска высоко и низко, я обнаружил, что вы можете установить .contentsScale на CATextLayer и вы можете установить его, чтобы [[UIScreen mainScreen] scale] в соответствии с разрешением экрана. (Я предполагаю, что это работает для не-сетчатки, но я не проверял-слишком устал)

после этого для меня CATextLayer текст стал четким. Примечание - это не обязательно для родительского слоя.

и размытость? Он возвращается, когда вы вращаетесь в 3D, но вы не замечаете этого, потому что текст начинается ясно, и пока он находится в движении, вы не можете сказать.

проблема решена!

Swift

установите для текстового слоя тот же масштаб, что и для экрана.

textLayer.contentsScale = UIScreen.main.scale

перед:

enter image description here

после:

enter image description here

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

далее, я просто отмечу, что я часто создаю CATextLayers и никогда не имею проблемы размытия, о которой вы говорите, поэтому я знаю, что это можно сделать. В двух словах это размытие происходит потому что вы не позиционируете свой слой на весь пиксель. Помните, что когда вы устанавливаете положение слоя, вы используете значения с плавающей запятой для x и y. если эти значения имеют числа после десятичного знака, слой не будет расположен на весь пиксель и, следовательно, даст этот эффект размытия-степень которого зависит от фактических значений. Чтобы проверить это, просто создайте CATextLayer и явно добавьте его в дерево слоев, гарантируя, что ваш параметр положения находится на всем пикселе. Для пример:

CATextLayer *textLayer = [CATextLayer layer];
[textLayer setBounds:CGRectMake(0.0f, 0.0f, 200.0f, 30.0f)];
[textLayer setPosition:CGPointMake(200.0f, 100.0f)];
[textLayer setString:@"Hello World!"];

[[self menuLayer] addSublayer:textLayer];

Если вы текст все еще размыто, то есть что-то еще не так. Размытый текст на вашем текстовом слое-это артефакт неверно написанного кода, а не предполагаемая возможность слоя. При добавлении слоев к родительскому слою вы можете просто принудить значения x и y к ближайшему целому пикселю, и это должно решить вашу проблему размытия.

перед установкой shouldRasterize, вы должны:

  1. установите масштаб растеризации базового слоя, который вы собираетесь растеризировать
  2. установите свойство contentsScale любых CATextLayers и, возможно, других типов слоев (это никогда не помешает сделать это)

Если вы не делаете #1,то версия сетчатки подслоев будет выглядеть размытой, даже для нормальных слоев.

- (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];
}

вы должны сделать 2 вещи, первая была описана выше:

расширьте CATextLayer и установите свойства opaque и contentsScale для правильной поддержки дисплея retina, а затем визуализируйте с включенным сглаживанием для текста.

+ (TextActionLayer*) layer
{
  TextActionLayer *layer = [[TextActionLayer alloc] init];
  layer.opaque = TRUE;
  CGFloat scale = [[UIScreen mainScreen] scale];
  layer.contentsScale = scale;
  return [layer autorelease];
}

// Render after enabling with anti aliasing for text

- (void)drawInContext:(CGContextRef)ctx
{
    CGRect bounds = self.bounds;
    CGContextSetFillColorWithColor(ctx, self.backgroundColor);
    CGContextFillRect(ctx, bounds);
    CGContextSetShouldSmoothFonts(ctx, TRUE);
    [super drawInContext:ctx];
}

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

text_layer.contentsScale = self.window!.backingScaleFactor

(Я также установил вид фонового слоя contentsScale, чтобы быть тем же самым).

это быстрее и проще: вам просто нужно установить contentsScale

    CATextLayer *label = [[CATextLayer alloc] init];
    [label setFontSize:15];
    [label setContentsScale:[[UIScreen mainScreen] scale]];
    [label setFrame:CGRectMake(0, 0, 50, 50)];
    [label setString:@"test"];
    [label setAlignmentMode:kCAAlignmentCenter];
    [label setBackgroundColor:[[UIColor clearColor] CGColor]];
    [label setForegroundColor:[[UIColor blackColor] CGColor]];
    [self addSublayer:label];