Найден обходной путь. Казалось бы, ничто в Quartz не может отображать текст с субпиксельным псевдонимом поверх прозрачного фона. Однако вы МОЖЕТЕ визуализировать текст в закадровый буфер растрового изображения, при условии, что внеэкранный буфер растрового изображения был создан правильным образом. Фон этого буфера должен быть непрозрачным.
У моего представления ранее был фон PNG, который был слегка прозрачным. Я мог бы просто сделать этот фон непрозрачным и отобразить его без проблем, но поскольку этот вид должен постепенно появляться и исчезать, он должен был поддерживаться CALayer, чтобы текст отображался правильно один раз, а затем впоследствии отображался без субпиксельного псевдонима. .
Вот мой код. Это кажется невероятно многословным, я был бы рад, если бы кто-нибудь помог мне сократить его. Предполагается, что у вас есть NSImageView с именем _title
и NSString с именем title
.
// Create the attributed string
NSMutableAttributedString *attStr = [[[NSMutableAttributedString alloc] initWithString: title] autorelease];
NSRange strRange = NSMakeRange(0, [attStr length]);
NSFont *font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize: NSSmallControlSize]];
[attStr addAttribute: NSForegroundColorAttributeName value: [NSColor whiteColor] range: strRange];
[attStr addAttribute: NSFontAttributeName value: font range: strRange];
NSMutableParagraphStyle *paraStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
[paraStyle setAlignment: NSCenterTextAlignment];
[paraStyle setLineBreakMode: NSLineBreakByTruncatingMiddle];
[attStr addAttribute: NSParagraphStyleAttributeName value: paraStyle range: strRange];
// Set up the image context
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * [_title frame].size.width;
NSUInteger bitsPerComponent = 8;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// These constants are necessary to enable sub-pixel aliasing.
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
// Create the memory buffer to be used as the context's workspace
unsigned char *contextBuffer = malloc([_title frame].size.height * [_title frame].size.width * 4);
CGContextRef context = CGBitmapContextCreate(contextBuffer,
[_title frame].size.width,
[_title frame].size.height,
bitsPerComponent,
bytesPerRow,
colorSpace,
bitmapInfo);
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO]];
CGContextSetFillColorWithColor(context, CGColorGetConstantColor(kCGColorBlack));
CGRect rectangle = CGRectMake(0, 0, [_title frame].size.width,[_title frame].size.height);
CGContextAddRect(context, rectangle);
CGContextFillPath(context);
CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)attStr);
CGContextSetTextPosition(context, 10.0, 10.0);
CTLineDraw(line, context);
CFRelease(line);
// Create a data provider from the context buffer in memory
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, contextBuffer, bytesPerRow * [_title frame].size.height, NULL);
// Create an image from the data provider
CGImageRef imageRef = CGImageCreate ([_title frame].size.width,
[_title frame].size.height,
bitsPerComponent,
bytesPerPixel * 8,
bytesPerRow,
colorSpace,
bitmapInfo,
dataProvider,
NULL,
false,
kCGRenderingIntentDefault
);
// Turn it into an NSImage
NSImage *newImage = [[[NSImage alloc] initWithCGImage:imageRef size: NSZeroSize] autorelease];
CGDataProviderRelease(dataProvider);
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
CGImageRelease(imageRef);
free(contextBuffer);
[NSGraphicsContext restoreGraphicsState];
[_title setImage: newImage];
person
Nick Locking
schedule
20.12.2010