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

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

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

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

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

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

NSInteger i;
for (i=0;i<[names count];i++) {
    CATextLayer *menuItemLayer=[CATextLayer layer];
    menuItemLayer.string=[self.names objectAtIndex:i];
    [email protected]"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/info/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);

ИЗМЕНИТЬ 2: см. мой ответ ниже, как это было решено. SBG.

Ответ 1

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

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

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

Не так с CATextLayer.

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

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

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

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

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

Ответ 2

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

Затем я просто укажу, что я часто создаю CATextLayers и никогда не сталкиваюсь с проблемой размытия, о которой вы говорите, поэтому я знаю, что это можно сделать. В двух словах это размывание происходит потому, что вы не позиционируете свой слой на весь пиксель. Помните, что когда вы устанавливаете положение слоя, вы используете значения float для 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 к ближайшему целому пикселю, и это должно решить вашу проблему размытия.

Ответ 3

Swift

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

textLayer.contentsScale = UIScreen.main.scale

Перед

введите описание изображения здесь

После того, как:

введите описание изображения здесь

Ответ 4

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

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

Если вы не делаете # 1, то версия подтипов сетчатки будет выглядеть размытой, даже для обычных 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];
}

Ответ 5

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

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

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

Ответ 6

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

text_layer.contentsScale = self.window!.backingScaleFactor

(Я также устанавливаю, что содержание фонового слоя ViewsScale одинаковое).

Ответ 7

Это быстрее и проще: вам просто нужно установить 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];