2010-12-17 16 views
12

Używałem obiektów NSStrokeWidthAttributeName na obiektach , aby umieścić kontur wokół tekstu podczas jego rysowania. Problem polega na tym, że obrys znajduje się w obszarze wypełnienia tekstu. Gdy tekst jest mały (na przykład o grubości 1 piksela), głaskanie sprawia, że ​​tekst jest trudny do odczytania. To, czego naprawdę chcę, to udar na zewnątrz. Czy istnieje jakiś sposób, aby to zrobić?Jak przesuwać _na_ stronę NSAttributedString?

Próbowałem jużbez przesunięcia i rozmycia, ale jest zbyt rozmyte i trudne do zobaczenia. Gdyby istniał sposób na zwiększenie rozmiaru cienia bez rozmycia, to też by działało.

Odpowiedz

31

Chociaż mogą istnieć inne sposoby, jednym ze sposobów osiągnięcia tego jest najpierw narysowanie struny za pomocą tylko obrysu, a następnie narysowanie struny tylko z wypełnieniem, bezpośrednio na wierzchu tego, co zostało wcześniej narysowane. (Adobe InDesign ma to wbudowane, gdzie wydaje się, że pociągnięcie jest stosowane tylko na zewnątrz litery, co pomaga w czytelności).

Jest to tylko przykład pogląd, że pokazuje, jak osiągnąć ten cel (zainspirowany http://developer.apple.com/library/mac/#qa/qa2008/qa1531.html):

najpierw skonfigurować atrybuty:

@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 

To daje następujący wynik:

alt text

alt text

Teraz nie jest idealny, ponieważ glify czasami spadają na ułamkowe granice, ale z pewnością wygląda lepiej niż domyślnie.

Jeśli wydajność jest problemem, możesz zawsze popatrzeć w dół na nieco niższy poziom, na przykład CoreGraphics lub CoreText.

+0

Dzięki. Działa jak smakołyk. –

+0

Świetna, szczegółowa odpowiedź. Dziękuję za poświęcenie czasu! – epologee

+1

Proste. Znakomity. ... i powinno być całkowicie niepotrzebne ... (wsparcie powinno już zaistnieć) – u2Fan

Powiązane problemy