Search code examples
iosios7

IoS 7 blurry coretext on CALayer


I have problem with Core Text when it's rendered to CALayer the text is blurry. I did check the position to be integral and frame height and width but still text appears blurry. The layout is simple in the IB i have standard UIView, then in the code i will create CALayer, append this layer to UIView layer and will draw text to this layer with :

drawLayer:(CALayer *)layer inContext:(CGContextRef)context{

Here is the code:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view.layer setPosition:CGPointMake(lroundf(self.view.frame.size.width/2), lroundf(self.view.frame.size.height/2))];
    [self.view setFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];

    CALayer *newLayer = [[CALayer alloc] initWithLayer:self.view.layer];
    newLayer.frame =CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height);
    newLayer.delegate=self;
    [self.view.layer setPosition:CGPointMake(lroundf(self.view.frame.size.width/2), lroundf(self.view.frame.size.height/2))];
    [self.view.layer addSublayer:newLayer];
    [newLayer setNeedsDisplay];

}


-(void) drawLayer:(CALayer *)layer inContext:(CGContextRef)currentContext{
   NSLog(@"drawLayer Layer position x %f pos y %f", layer.position.x,layer.position.y);
   NSLog(@"drawLayer Layer origin x %f y %f", layer.bounds.origin.x,layer.bounds.origin.y);
   NSLog(@"drawLayer Layer bounds width %f height %f", layer.bounds.size.width,layer.bounds.size.height);

    layer.contentsScale=[[UIScreen mainScreen]scale];
    CTFontRef fontRef =
    CTFontCreateWithName((CFStringRef)@"Didot", 36, NULL);
    NSDictionary *attrDictionary = [NSDictionary dictionaryWithObjectsAndKeys: (__bridge id)fontRef, (NSString *)kCTFontAttributeName, (id)[[UIColor blackColor] CGColor], (NSString *)(kCTForegroundColorAttributeName), nil];
    CFRelease(fontRef); 

    // Flip the coordinate system
    CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);
    CGContextTranslateCTM(currentContext, 0, layer.bounds.size.height);
    CGContextScaleCTM(currentContext, 1.0, -1.0);
    CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);
    NSAttributedString *timeMarker = [[NSAttributedString alloc] initWithString:@"Hello blurry text !!!" attributes:attrDictionary] ;
    CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)timeMarker);
    CGContextSetTextPosition(currentContext, 0, 50);
    CTLineDraw(line, currentContext);
    CFRelease(line);
}

Here is the View bounds:

DrawRect[14767:15435976] View bounds <UIView: 0x7fe153d22980; frame = (0 0; 375 667); autoresize = W+H; autoresizesSubviews = NO; layer = <CALayer: 0x7fe153d21c40>>

Below is NSLOG:
2014-11-25 20:18:10.159 DrawRect[15103:15454664] viewDidLoad View Position x 187.500000 pos y 333.500000 
2014-11-25 20:18:10.159 DrawRect[15103:15454664] viewDidLoad View bounds width 375.000000 heights 667.000000
2014-11-25 20:18:10.159 DrawRect[15103:15454664] viewDidLoad View bounds origin x 0.000000 x 0.000000

2014-11-25 20:18:10.159 DrawRect[15103:15454664] viewDidLoad View frame size width 375.000000 height 667.000000
2014-11-25 20:18:10.159 DrawRect[15103:15454664] viewDidLoad View frame origin width 0.000000 height 0.000000

2014-11-25 20:18:10.160 DrawRect[15103:15454664] View Layer frame size width 375.000000 height 667.000000
2014-11-25 20:18:10.160 DrawRect[15103:15454664] View Layer origin width 0.000000 height 0.000000

2014-11-25 20:18:10.165 DrawRect[15103:15454664] drawLayer Layer position x 188.000000 pos y 334.000000
2014-11-25 20:18:10.165 DrawRect[15103:15454664] drawLayer Layer origin x 0.000000 y 0.000000
2014-11-25 20:18:10.165 DrawRect[15103:15454664] drawLayer Layer bounds width 375.000000 height 667.000000

2014-11-25 20:18:10.166 DrawRect[15103:15454664] drawLayer after CTM Layer position x 188.000000 pos y 334.000000
2014-11-25 20:18:10.166 DrawRect[15103:15454664] drawLayer after CTM Layer origin x 0.000000 y 0.000000
2014-11-25 20:18:10.174 DrawRect[15103:15454664] drawLayer after CTM Layer bounds width 375.000000 height 667.000000

Solution

  • The clue was printing CALayer object (po 0x7fec22927c40) in the debugger.

    CABackingStore buffer had same values as layer bounds [375 853], but based on the scale definition CAlayer should draw twice in the buffer.

    Infer was that second draw was skipped. My layer.contentsScale was in the method:

    drawLayer:(CALayer *)layer inContext:(CGContextRef)currentContext
    

    When layer.contentsScale was moved to the viewDidLoad method problem was fixed.

    CALayer *newLayer = [[CALayer alloc] initWithLayer:self.view.layer];
        newLayer.frame =CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height);
        newLayer.delegate=self;
        newLayer.contentsScale=2;
    

    CABackingStore buffer from [375 853] become [750 1706].

    The text was crisp even with non integral super view position.

    viewDidLoad View Position x 187.500000 pos y 333.500000