objective framework developer apple text ios core-animation calayer

framework - Cómo hacer que el texto en un CATextLayer sea claro



swift ios documentation (7)

He hecho un CALayer con un CATextLayer agregado y el texto sale borroso. En los documentos, hablan de "antialiasing subpíxel", pero eso no significa mucho para mí. ¿Alguien tiene un fragmento de código que hace un CATextLayer con un poco de texto claro?

Aquí está el texto de la documentación de Apple:

Nota: CATextLayer desactiva el antialiasing subpíxel cuando se renderiza texto. El texto solo se puede dibujar utilizando un antialiasing subpíxel cuando se combina en un fondo opaco existente al mismo tiempo que se rasteriza. No hay forma de dibujar texto antialias subpíxel por sí mismo, ya sea en una imagen o una capa, por separado antes de tener los píxeles de fondo para tejer los píxeles de texto en. Establecer la propiedad de opacidad de la capa en YES no cambia el modo de renderizado.

La segunda oración implica que uno puede obtener un buen texto si se lo composites en un existing opaque background at the same time that it''s rasterized. Eso es genial, pero ¿cómo lo combino y cómo le das un fondo opaco y cómo lo rastrifica?

El código que usan en su ejemplo de un Menú de kiosco es como tal: (Es OS X, no iOS, ¡pero supongo que funciona!)

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

¡Gracias!

EDITAR: Agregar el código que usé realmente que dio como resultado texto borroso. Es de una pregunta relacionada que UILabel sobre cómo agregar un UILabel lugar de un CATextLayer pero obteniendo un recuadro negro en su lugar. 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: Vea mi respuesta a continuación para saber cómo se resolvió esto. sbg.


Rápido

Establezca la capa de texto para usar la misma escala que la pantalla.

textLayer.contentsScale = UIScreen.main.scale

Antes de:

Después:


Antes de configurar shouldRasterize, debe hacer lo siguiente:

  1. establecer la rasterizaciónEscala de la capa base que va a rasterizar
  2. establece la propiedad contentsScale de cualquier CATextLayers y posiblemente otros tipos de capas (nunca está de más hacerlo)

Si no hace # 1, entonces la versión de la retina de las subcapas se verá borrosa, incluso para CALayers normales.

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


Debes hacer 2 cosas, la primera fue mencionada anteriormente:

Extienda CATextLayer y establezca las propiedades opaque y contentsScale para admitir adecuadamente la visualización de retina, luego renderice con anti aliasing habilitado para el texto.

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


En primer lugar, quería señalar que ha etiquetado su pregunta con iOS, pero los administradores de restricciones solo están disponibles en OSX, por lo que no estoy seguro de cómo lograr que esto funcione, a menos que haya podido vincularlo. en el simulador de alguna manera. En el dispositivo, esta funcionalidad no está disponible.

A continuación, señalaré que creo CATextLayers a menudo y nunca tengo el problema de borrosidad al que se refiere, así que sé que se puede hacer. En pocas palabras, este desenfoque se produce porque no está colocando su capa en todo el píxel. Recuerde que cuando establece la posición de una capa, usa un valor flotante para xey. Si esos valores tienen números después del decimal, la capa no se colocará en todo el píxel y, por lo tanto, dará este efecto de desenfoque, cuyo grado depende de los valores reales. Para probar esto, solo crea un CATextLayer y explícitamente agrégalo al árbol de capas asegurando que tu parámetro de posición esté en un píxel entero. Por ejemplo:

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

Si su texto todavía está borroso, entonces hay algo más que está mal. El texto borroso en la capa de texto es un artefacto de código escrito incorrectamente y no una capacidad prevista de la capa. Al agregar las capas a una capa principal, puede forzar los valores de xey en el píxel entero más cercano y resolver su problema de borrosidad.


Esto es más rápido y más fácil: solo necesita configurar 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];


Respuesta corta: debe configurar el escalado del contenido:

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

Hace un tiempo aprendí que cuando tienes un código de dibujo personalizado, debes verificar la retina y escalar tus gráficos en consecuencia. UIKit se encarga de la mayor parte de esto, incluida la escala de fuentes.

No es así con CATextLayer.

Mi borrosidad vino de tener una .zPosition que no era cero, es decir, tuve una transformación aplicada a mi capa padre. Al establecer esto en cero, la borrosidad desapareció y fue reemplazada por una grave pixelación.

Después de buscar alto y bajo, encontré que puede establecer .contentsScale para CATextLayer y puede establecerlo en [[UIScreen mainScreen] scale] para que coincida con la resolución de la pantalla. (Supongo que esto funciona para la no retina, pero no lo he comprobado, demasiado cansado)

Después de incluir esto para mi CATextLayer el texto se volvió CATextLayer . Nota: no es necesario para la capa principal.

Y la borrosidad? Vuelve cuando estás girando en 3D, pero no lo notas porque el texto comienza de forma clara y mientras está en movimiento, no puedes distinguirlo.

¡Problema resuelto!


Si viniste a buscar aquí un problema similar para CATextLayer en OSX, después de muchos golpes en la cabeza de pared, obtuve el texto nítido y claro haciendo:

text_layer.contentsScale = self.window!.backingScaleFactor

(También configuré las vistas de contenido de capa de fondoScale para que sean las mismas).