Using NSString's drawAtPoint method in place of CGContextShowGlyphsAtPoint problems

倾然丶 夕夏残阳落幕 提交于 2019-12-21 08:01:27

问题


In my app I'm trying to render text along a path; this is fine for most characters but not for Japanese (or anything non mac-Roman). I've been advised to use [NSString drawAtPoint] which displays the correct characters in my CATiledLayer; however, they dissapear after approximately 5 seconds. In this time I can zoom the layer and they scale properly, but they don't seem to get committed to the CATiledLayer like the rest of the text usually is.

Before I render, I check the string and decide whether any of them will not be renderable. If I'm going to have issues, I use drawAtpoint instead:

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]];


 }

Does anyone have any pointers as to why the text disappears?

As soon as the drawAtPoint is used my debug output gets flooded with:

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

So I'm guessing it is something to do with my context management, but I assumed that if this is in the same place as I use CGContextShowGlyphsAtPoint it should have the correct context already?


回答1:


Answering my own question:

NSString drawAtPoint:withFont: makes use of the context stack, and from where I was calling this method the stack was empty. Wrapping the call with

UIGraphicsPushContext(context); and UIGraphicsPopContext();

did the trick.




回答2:


For completeness, here is the code needed for Cocoa. Also works with .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)

This is mostly not needed, as @davbryn says, as normally there is already a "working" context on the stack that is the same (you hope!) as your context, however, as he points out, sometimes there isn't. I discovered this problem particularly with MapKit MKOverlayRenderer's drawMapRect:, which simply wouldn't show text without setting the context explicitly.



来源:https://stackoverflow.com/questions/2319873/using-nsstrings-drawatpoint-method-in-place-of-cgcontextshowglyphsatpoint-probl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!