Как вы поглаживаете _outside_ из NSAttributedString?

Я использовал объекты NSStrokeWidthAttributeName on NSAttributedString, чтобы нарисовать контур вокруг текста. Проблема в том, что штрих находится внутри области заполнения текста. Когда текст мал (например, толщиной в 1 пиксель), поглаживание делает текст трудным для чтения. То, что я действительно хочу, - это удар снаружи. Есть ли способ сделать это?

Я пробовал NSShadow без смещения и размытия, но он слишком размытый и трудно различимый. Если бы был способ увеличить размер тени без размытия, это тоже сработало бы.

1 ответ

Хотя могут быть и другие способы, один из способов добиться этого - сначала нарисовать строку только одним штрихом, а затем нарисовать строку только с заполнением, непосредственно перевернув то, что было ранее нарисовано. (Adobe InDesign на самом деле имеет этот встроенный модуль, где он, кажется, применит только штрих к внешней стороне письма, что помогает с читабельностью).

Это просто пример, который показывает, как это сделать (вдохновленный http://developer.apple.com/library/mac/#qa/qa2008/qa1531.html):

Сначала настройте атрибуты:

@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

Это приводит к следующему выводу:

Теперь это не идеально, поскольку глифы будут иногда падать на дробные границы, но, конечно, выглядит лучше, чем по умолчанию.

Если производительность является проблемой, вы всегда можете перейти на несколько более низкий уровень, например CoreGraphics или CoreText.

licensed under cc by-sa 3.0 with attribution.