How to get text in a CATextLayer to be clear

前端 未结 7 1819
不思量自难忘°
不思量自难忘° 2021-01-29 18:19

I\'ve made a CALayer with an added CATextLayer and the text comes out blurry. In the docs, they talk about \"sub-pixel antialiasing\", but that doesn\

相关标签:
7条回答
  • 2021-01-29 18:56

    Swift

    Set the text layer to use the same scale as the screen.

    textLayer.contentsScale = UIScreen.main.scale
    

    Before:

    After:

    0 讨论(0)
  • 2021-01-29 19:01

    You should do 2 things, the first was mentioned above:

    Extend CATextLayer and set the opaque and contentsScale properties to properly support retina display, then render with anti aliasing enabled for text.

    + (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 讨论(0)
  • 2021-01-29 19:03

    Before setting shouldRasterize, you should:

    1. set the rasterizationScale of the base layer you are going to rasterize
    2. set the contentsScale property of any CATextLayers and possibly other types of layers(it never hurts to do it)

    If you don't do #1, then the retina version of sub layers will look blurry, even for normal 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];
    }
    
    0 讨论(0)
  • 2021-01-29 19:04

    First off I wanted to point out that you've tagged your question with iOS, but constraint managers are only available on OSX, so I'm not sure how you're getting this to work unless you've been able to link against it in the simulator somehow. On the device, this functionality is not available.

    Next, I'll just point out that I create CATextLayers often and never have the blurring problem you're referring to so I know it can be done. In a nutshell this blurring occurs because you are not positioning your layer on the whole pixel. Remember that when you set the position of a layer, you use a float values for the x and y. If those values have numbers after the decimal, the layer will not be positioned on the whole pixel and will therefore give this blurring effect--the degree of which depending upon the actual values. To test this, just create a CATextLayer and explicitly add it to the layer tree ensuring that your position parameter is on a whole pixel. For example:

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

    If your text is still blurry, then there is something else wrong. Blurred text on your text layer is an artifact of incorrectly written code and not an intended capability of the layer. When adding your layers to a parent layer, you can just coerce the x and y values to the nearest whole pixel and it should solve your blurring problem.

    0 讨论(0)
  • 2021-01-29 19:13

    If you came searching here for a similar issue for a CATextLayer in OSX, after much wall head banging, I got the sharp clear text by doing:

    text_layer.contentsScale = self.window!.backingScaleFactor
    

    (I also set the views background layer contentsScale to be the same).

    0 讨论(0)
  • 2021-01-29 19:13

    This is faster and easier: you just need to set 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];
    
    0 讨论(0)
提交回复
热议问题