2010-09-28 3 views
78

Я сделал CALayer с добавленным CATextLayer и текст получился размытым. В документах они говорят о «подпиксельном сглаживании», но это не значит для меня. У кого-нибудь есть фрагмент кода, который делает 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]; 
    [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/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: Смотрите мой ответ ниже, как это удалось решить. SBG.

+0

Это не ответ на ваш вопрос, но может быть для кого-то вроде меня, кто только ищет, чтобы рисовать приписаны текст, наиболее похожий на использование UILabel: http://stackoverflow.com/questions/3786528/iphone-ipad-how-exactly-use-nsattributedstrin g – DenNukem

ответ

190

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

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

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

Не так с CATextLayer.

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

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

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

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

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

+37

Это короткий ответ: 'textLayer.contentScale = [[UIScreen mainScreen] scale];' BTW, мне тоже нужны длинные ответы :) – nacho4d

+0

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

+17

Коррекция '_textLayer.contentsScale = [[UIScreen mainScreen]]:' Вам не хватает «s»;) – Ralphleon

17

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

12

Перед установкой shouldRasterize, вам необходимо:

  1. установить rasterizationScale базового слоя вы собираетесь растеризации
  2. установить свойство 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]; 
} 
4

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

Продлить CATextLayer и установить непрозрачные и 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]; 
} 
0

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

text_layer.contentsScale = self.window!.backingScaleFactor 

(Я также установить точку background layer contentsScale будет одинаковым).

0

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

Swift

Установите текстовый слой, чтобы использовать один и тот же масштаб, что и экран.

textLayer.contentsScale = UIScreen.main.scale 

До:

enter image description here

После:

enter image description here