J'ai créé une variable CALayer
avec une variable supplémentaire CATextLayer
et le texte est flou. Dans la documentation, ils parlent d '"antialiasing sous-pixel", mais cela ne veut pas dire grand chose pour moi. Quelqu'un at-il un extrait de code qui crée une CATextLayer
avec un peu de texte clair?
Voici le texte de la documentation d'Apple:
Remarque: CATextLayer désactive l'antialiasing des sous-pixels lors du rendu du texte . Le texte ne peut être dessiné avec un antialiasing inférieur au pixel que s'il est composé dans un fond opaque existant en même temps que c'est pixellisé. Il n’existe aucun moyen de dessiner un texte antialiasé de sous-pixels par lui-même, que ce soit dans une image ou un calque, séparément avant avoir les pixels de fond pour tisser les pixels du texte. Réglage la propriété d'opacité du calque sur YES ne modifie pas le rendu mode.
La deuxième phrase implique que l'on peut obtenir un bon texte si l'on composites
dans un existing opaque background at the same time that it's rasterized.
C'est génial, mais comment puis-je le composer, comment lui donner un fond opaque et comment le rasteriser?
Le code qu'ils utilisent dans leur exemple de menu Kiosk est le suivant: (C'est OS X, pas iOS, mais je suppose que cela fonctionne!)
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
Merci!
EDIT: L'ajout du code que j'ai réellement utilisé a entraîné un texte flou. C'est à partir d'une question connexe que j'ai posée sur l'ajout d'une UILabel
plutôt que d'une CATextLayer
mais l'obtention d'une boîte noire à la place. 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: Voir ma réponse ci-dessous pour savoir comment cela a été résolu. sbg.
Réponse courte - Vous devez définir la mise à l'échelle du contenu:
textLayer.contentsScale = [[UIScreen mainScreen] scale];
Il y a quelque temps, j'ai appris que lorsque vous avez un code de dessin personnalisé, vous devez vérifier l'affichage de la rétine et redimensionner vos graphiques en conséquence. UIKit
prend en charge la plupart de ces tâches, y compris la mise à l'échelle des polices.
Pas si avec CATextLayer.
Mon flou vient d’un .zPosition
qui n’est pas nul, c’est-à-dire qu’une transformation a été appliquée à mon calque parent. En réglant ce paramètre à zéro, le flou a disparu et a été remplacé par une pixellisation sérieuse.
Après une recherche en haut et en bas, j'ai trouvé que vous pouvez définir .contentsScale
pour une CATextLayer
et le définir sur [[UIScreen mainScreen] scale]
pour correspondre à la résolution de l'écran. (Je suppose que cela fonctionne pour les rétiniens, mais je n'ai pas vérifié - trop fatigué)
Après avoir inclus cela pour ma CATextLayer
, le texte est devenu net. Remarque - ce n'est pas nécessaire pour le calque parent.
Et le flou? Il revient lorsque vous effectuez une rotation en 3D, mais vous ne le remarquez pas car le texte est clair au début et tant qu'il est en mouvement, vous ne pouvez pas le savoir.
Problème résolu!
Tout d'abord, je tiens à souligner que vous avez associé votre question à iOS, mais que les gestionnaires de contraintes ne sont disponibles que sur OSX. Je ne sais donc pas comment vous allez faire en sorte que cela fonctionne à moins que vous n'ayez pu faire le lien avec cela dans le simulateur en quelque sorte. Sur le périphérique, cette fonctionnalité n'est pas disponible.
Ensuite, je soulignerai simplement que je crée souvent CATextLayers sans jamais avoir le problème de flou dont vous parlez, je sais donc que cela peut être fait. En résumé, ce flou est dû au fait que vous ne positionnez pas votre calque sur le pixel entier. N'oubliez pas que lorsque vous définissez la position d'un calque, vous utilisez une valeur flottante pour x et y. Si ces valeurs ont des nombres après la décimale, le calque ne sera pas positionné sur tout le pixel et donnera donc cet effet de flou dont le degré dépend des valeurs réelles. Pour tester cela, créez simplement un CATextLayer et ajoutez-le explicitement à l'arborescence des calques en vous assurant que votre paramètre de position est sur un pixel entier. Par exemple:
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 votre texte est toujours flou, il y a autre chose qui ne va pas. Le texte flou sur votre calque de texte est un artefact de code mal écrit et non une capacité prévue du calque. Lorsque vous ajoutez vos calques à un calque parent, vous pouvez simplement contraindre les valeurs x et y au pixel entier le plus proche, ce qui devrait résoudre votre problème de flou.
Avant de définir devraitRasterize, vous devez:
Si vous ne le faites pas # 1, la version rétine des sous-couches aura un aspect flou, même pour les CALayers normaux.
- (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];
}
Vous devez faire 2 choses, la première a été mentionnée ci-dessus:
Étendez CATextLayer et définissez les propriétés opaque et contentsScale pour prendre en charge correctement l'affichage de la rétine, puis effectuez le rendu avec l'anticrénelage activé pour le texte.
+ (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];
}
Si vous cherchiez ici un problème similaire pour une couche CATextLayer sous OSX, après avoir beaucoup tapé dans la tête du mur, j'ai obtenu le texte clair et net en faisant:
text_layer.contentsScale = self.window!.backingScaleFactor
(J'ai également défini le contenu de la couche d'arrière-plan de vues comme identique).
C'est plus rapide et plus facile: il vous suffit de définir 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];