2011-12-17 12 views
6

chicos, este es mi código:CGContext y Retina Display

- (void) renderPageAtIndex:(NSUInteger)index inContext:(CGContextRef)ctx { 
    //background 
    CGContextSetFillColorWithColor(ctx, [[UIColor colorWithRed:((float)238/255.0f) green:((float)233/255.0f) blue:((float)215/255.0f) alpha:1] CGColor]); 
    CGContextFillRect(ctx, CGRectInset(leavesView.bounds, 0, 0)); 
    //text 
    CGContextSetTextDrawingMode(ctx, kCGTextFill); 
    CGContextSetTextMatrix(ctx, CGAffineTransformMake(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)); 
    CGContextSetFillColorWithColor(ctx, [[UIColor blackColor] CGColor]); 
    UIGraphicsPushContext(ctx); 

    CGContextSaveGState(ctx); 
    CGContextTranslateCTM(ctx, 0.1f, leavesView.bounds.size.height); 
    CGContextScaleCTM(ctx, 1.0f, -1.0f); 

    CGRect textRect = CGRectMake(5, 5, leavesView.bounds.size.width-10, leavesView.bounds.size.height-10); 
    if (pages.count > 0 && pages.count-1 >= index) { 
     [[pages objectAtIndex:index] drawInRect:textRect withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentLeft]; 
    } 

    CGContextRestoreGState(ctx); 

    UIGraphicsPopContext(); 
} 

Funciona perfecto en el iPhone 2G, 3G, 3GS, pero en los nuevos modelos no tengo problemas.

En la retina, el texto no se dibuja al doble de la resolución, como en el estándar.

¿Tiene alguna idea?

Respuesta

16

intente configurar las capas contentScale variable de la siguiente manera:

layer.contentsScale = [UIScreen mainScreen].scale; 

Esto debería hacer que el código adaptarse a la retina/pantallas nonretina.

+0

¡oh hombre! Salvaste mi día. Realmente no tan obvio. – orkenstein

+0

He subclasificado el CALayer y tuve que hacer esto en el método init. En el método drawWithContext arrojaba un error de solo lectura. –

3

Parece que está utilizando el proyecto Leaves en git. Tuve este mismo problema en mi proyecto y lo resolví de la siguiente manera.

En primer lugar, debe dimensionar y escalar el contexto Core Graphics original creado en imageForPageIndex: en LeavesCache.m según la escala de pantalla de los dispositivos. Asegúrese también de escalar CGContextClipToRect también.

- (CGImageRef) imageForPageIndex:(NSUInteger)pageIndex { 
    CGFloat scale = [[UIScreen mainScreen] scale]; // we need to size the graphics context according to the device scale 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(NULL, 
              pageSize.width*scale, 
              pageSize.height*scale, 
              8,      /* bits per component*/ 
              pageSize.width*scale * 4, /* bytes per row */ 
              colorSpace, 
              kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 

    CGColorSpaceRelease(colorSpace); 
    CGContextClipToRect(context, CGRectMake(0, 0, pageSize.width*scale, pageSize.height*scale)); 

    CGContextScaleCTM(context, scale, scale); 

    [dataSource renderPageAtIndex:pageIndex inContext:context]; 

    CGImageRef image = CGBitmapContextCreateImage(context); 
    CGContextRelease(context); 

    [UIImage imageWithCGImage:image]; 
    CGImageRelease(image); 

    return image; 
} 

A continuación, en setUpLayers en LeavesView.m, se tendrá que aplicar la escala de la pantalla del dispositivo a cada CALayer que consigue inicializado. Según lo publicado por Brad Larson en un similar question:

De forma predeterminada, su CALayer no muestra su contenido de Cuarzo con la resolución más alta de la pantalla Retina. Puede activar este código usando como la siguiente:

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

Así que aquí son las primeras líneas de setUpLayers en LeavesView.m donde solicite la escala dispositivo al topPage CALayer. Tendrá que hacer esto para todos los CALayers y CAGradientLayers inicializados en setUpLayers:

- (void) setUpLayers { 
    // Set the backgound image of the leave view to the book page 
    UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:@"open_book_page_turn.png"]]; 

    self.clipsToBounds = YES; 

    topPage = [[CALayer alloc] init]; 
    topPage.contentsScale = [[UIScreen mainScreen] scale]; // We need to apply the device display scale to each layer 
    topPage.masksToBounds = YES; 
    topPage.contentsGravity = kCAGravityLeft; 
    topPage.backgroundColor = [[UIColor whiteColor] CGColor]; 
    topPage.backgroundColor = [background CGColor]; 

    ... 

} 
2

Puede acaba de establecer la escala cuando se inicia el contexto

+ (UIImage *)imageWithView:(UIView *)view { 
    UIGraphicsBeginImageContextWithOptions([view bounds].size, NO, [[UIScreen mainScreen] scale]); 

    [[view layer] renderInContext:UIGraphicsGetCurrentContext()]; 

    UIImage *result = UIGraphicsGetImageFromCurrentImageContext(); 

    UIGraphicsEndImageContext(); 

    return result; 
} 
0

Para Swift 3

func getImageFromContext() -> UIImage{ 

    UIGraphicsBeginImageContextWithOptions(self.frame.size, false, UIScreen.main.scale) 
    self.drawHierarchy(in: self.bounds, afterScreenUpdates: true) 
    self.layer.render(in: UIGraphicsGetCurrentContext()!) 
    let image = UIGraphicsGetImageFromCurrentImageContext() 
    UIGraphicsEndImageContext() 

    return image! 
}