2010-12-17 8 views
12

He estado usando NSStrokeWidthAttributeName en NSAttributedString objetos para poner un contorno alrededor del texto tal como se dibuja. El problema es que el trazo está dentro del área de relleno del texto. Cuando el texto es pequeño (por ejemplo, 1 píxel de grosor), la caricia hace que el texto sea difícil de leer. Lo que realmente quiero es un derrame en el exterior. ¿Hay alguna forma de hacer eso?¿Cómo se acaricia el _outside_ de un NSAttributedString?

He intentado un NSShadow sin desplazamiento y un desenfoque, pero es demasiado borroso y difícil de ver. Si hubiera una manera de aumentar el tamaño de la sombra sin ningún efecto borroso, eso también funcionaría.

Respuesta

31

Aunque puede haber otras formas, una forma de lograr esto es dibujar primero la cuerda con solo un trazo, luego dibujar la cuerda con solo un relleno, directamente sobrepasado de lo que se dibujó previamente. (Adobe InDesign tiene esto incorporado, donde parecerá que solo aplicará el trazo al exterior de la letra, lo que ayuda a la legibilidad).

Esto es sólo una vista de ejemplo que muestra cómo lograr esto (inspirado en http://developer.apple.com/library/mac/#qa/qa2008/qa1531.html):

Primero configurar los atributos:

@implementation MDInDesignTextView 

static NSMutableDictionary *regularAttributes = nil; 
static NSMutableDictionary *indesignBackgroundAttributes = nil; 
static NSMutableDictionary *indesignForegroundAttributes = nil; 

- (void)drawRect:(NSRect)frame { 
    NSString *string = @"Got stroke?"; 
    if (regularAttributes == nil) { 
     regularAttributes = [[NSMutableDictionary 
    dictionaryWithObjectsAndKeys: 
     [NSFont systemFontOfSize:64.0],NSFontAttributeName, 
     [NSColor whiteColor],NSForegroundColorAttributeName, 
     [NSNumber numberWithFloat:-5.0],NSStrokeWidthAttributeName, 
     [NSColor blackColor],NSStrokeColorAttributeName, nil] retain]; 
    } 

    if (indesignBackgroundAttributes == nil) { 
     indesignBackgroundAttributes = [[NSMutableDictionary 
     dictionaryWithObjectsAndKeys: 
     [NSFont systemFontOfSize:64.0],NSFontAttributeName, 
     [NSNumber numberWithFloat:-5.0],NSStrokeWidthAttributeName, 
     [NSColor blackColor],NSStrokeColorAttributeName, nil] retain]; 
    } 

    if (indesignForegroundAttributes == nil) { 
     indesignForegroundAttributes = [[NSMutableDictionary 
     dictionaryWithObjectsAndKeys: 
     [NSFont systemFontOfSize:64.0],NSFontAttributeName, 
     [NSColor whiteColor],NSForegroundColorAttributeName, nil] retain]; 
    } 

    [[NSColor grayColor] set]; 
    [NSBezierPath fillRect:frame]; 

    // draw top string 
    [string drawAtPoint: 
     NSMakePoint(frame.origin.x + 200.0, frame.origin.y + 200.0) 
     withAttributes:regularAttributes]; 

    // draw bottom string in two passes 
    [string drawAtPoint: 
     NSMakePoint(frame.origin.x + 200.0, frame.origin.y + 140.0) 
     withAttributes:indesignBackgroundAttributes]; 
    [string drawAtPoint: 
     NSMakePoint(frame.origin.x + 200.0, frame.origin.y + 140.0) 
     withAttributes:indesignForegroundAttributes]; 
} 

@end 

Esto produce el siguiente resultado:

alt text

alt text

Ahora, no es perfecto, ya que los glifos a veces caen en límites fraccionarios, pero, sin duda se ve mejor que el predeterminado.

Si el rendimiento es un problema, siempre se puede considerar bajar a un nivel ligeramente inferior, como CoreGraphics o CoreText.

+0

Gracias. Funciona un placer –

+0

Respuesta excelente y detallada. Gracias por poner el tiempo! – epologee

+1

Simple. Brillante. ... y debería ser completamente innecesario ... (el soporte ya debería existir para esto) – u2Fan

Cuestiones relacionadas