Nic*_*ing 10 core-animation objective-c text-rendering
我NSTextField
在CALayer
背景视图中呈现了一些可变文本.由于CALayer
不支持对其上方任何文本进行文本呈现的子像素别名,因此该文本看起来很垃圾.
一些谷歌搜索揭示了原因,并且必须将文本渲染到不透明的背景上才能启用SPA.在这种情况下,如果可能的话,我想避免渲染到不透明的背景上.有更好的解决方法吗?
我完全可以将自己的文本呈现为NSImage
,如果这会有所帮助,但我找不到任何已确认的报告.
它在Interface Builder中看起来非常好,所以我知道秘密就在这台计算机内的某个地方,只是为了摆脱困境.
找到解决方法。看起来,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];
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4154 次 |
最近记录: |