使用NSString的drawAtPoint方法替代CGContextShowGlyphsAtPoint方法存在问题

10
在我的应用程序中,我正在尝试沿路径渲染文本;这对于大多数字符来说都很好,但是对于日语(或任何非 mac-Roman 字符集)则不行。我已经被建议使用 [NSString drawAtPoint] 在我的 CATiledLayer 中显示正确的字符;然而,它们在大约 5 秒后就消失了。在这段时间内,我可以缩放图层并且它们可以正确地缩放,但它们似乎没有像通常渲染的其余文本一样被提交到 CATiledLayer 中。
在渲染之前,我检查字符串并决定是否有任何无法渲染的内容。如果我会遇到问题,我会使用 drawAtpoint。
if (!isFullyDisplayable)
 {
  CGContextShowGlyphsAtPoint(context, pt.x, pt.y, realGlyph, 1);
 }
 else {
  // fall back on less flexible font rendering for difficult characters

  NSString *b = [gv text];
  NSString *c = [b substringWithRange:NSMakeRange(j,1)];

  [c drawAtPoint:pt withFont:[UIFont fontWithName:@"Helvetica-Bold" size:16.0]];


 }

有人能提供一些关于为什么文本会消失的指向吗?

只要使用drawAtPoint,我的调试输出就会被淹没:

<Error>: CGContextGetShouldSmoothFonts: invalid context
<Error>: CGContextSetFont: invalid context
<Error>: CGContextSetTextMatrix: invalid context
<Error>: CGContextSetFontSize: invalid context
<Error>: CGContextSetTextPosition: invalid context
<Error>: CGContextShowGlyphsWithAdvances: invalid context

所以我猜测这与我的上下文管理有关,但我认为如果这个代码段在我使用CGContextShowGlyphsAtPoint的同一位置,它应该已经具有正确的上下文了?

2个回答

17
回答我的问题:
NSString drawAtPoint:withFont: 使用了上下文堆栈,并且在我调用此方法的位置上堆栈为空。用以下代码将其包装起来:
UIGraphicsPushContext(context); and UIGraphicsPopContext();

起了作用。


1
你应该提到这仅适用于iOS 4.0及更高版本。在旧的固件中,UIKit图形扩展不是线程安全的。 - Split

1

为了完整起见,这里是Cocoa所需的代码。同样适用于.drawInRect...

CGContextSaveGState(context)
let old_nsctx = NSGraphicsContext.currentContext() // in case there was one
// force "my" context...
NSGraphicsContext.setCurrentContext(NSGraphicsContext(CGContext: context, flipped: true)) 

// Do any rotations, translations, etc. here
str.drawAtPoint(cgPt, withAttributes: attributes)

NSGraphicsContext.setCurrentContext(old_nsctx)// clean up for others
CGContextRestoreGState(context)

这通常是不必要的,正如@davbryn所说,因为通常已经有一个在堆栈中的“工作”上下文与您的上下文相同(您希望如此!),但是,正如他指出的那样,有时并不是这样。我特别在MapKit的MKOverlayRenderer的drawMapRect:中发现了这个问题,如果不明确设置上下文,它将无法显示文本。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接