Michel
Michel

Reputation: 11749

CGContextShowGlyphsAtPoint DEPRECATED

After spending quite a bit of time to display "Thai Phonetic YK" fonts in an iPhone app. I finally got things sorted out and working.

Though it is functionning there is still a complaint (warning) from the compiler about one line of code in the (void)drawRect: method of my class performing the display.

CGContextShowGlyphsAtPoint(context, 20, 50, textToPrint, textLength);

The compiler tells me that this code is DEPRECATED. My question is “How am I supposed to change it?”. Even though I searched the net for an answer, I didn’t find any thing clear. The documentation says something like “Use Core Text instead” which is far too vague to be considered as an answer.

Upvotes: 3

Views: 952

Answers (1)

foundry
foundry

Reputation: 31745

Core Graphics:

void CGContextShowGlyphsAtPoint (
   CGContextRef context,
   CGFloat x,
   CGFloat y,
   const CGGlyph glyphs[],
   size_t count
);

Core Text:

void CTFontDrawGlyphs (
   CTFontRef font,
   const CGGlyph glyphs[],
   const CGPoint positions[],
   size_t count,
   CGContextRef context
);

The Core Text version requires a CTFontRef (in the Core Graphics version, the font is expected to be set in the context).

You can obtain a CTFontRef from a UIFont:

    CTFontRef ctFont = CTFontCreateWithName( (__bridge CFStringRef)uiFont.fontName, uiFont.pointSize, NULL);

The CT version also requires an array of points, one for each glyph. Assuming you were drawing a single glyph with the CG code, you could create the array like this:

        CGPoint point = CGPointMake(x, y);
        const CGPoint* positions = &point;

This change does mean you will need a point position for each glyph. In my case the extra work was minimal: I was advancing the typesetter one character at a time (for curved text) so I had to do this calculation anyway.

You may be able to typeset one text run at a time with CTRun:

  void CTRunDraw ( 
      CTRunRef run, 
      CGContextRef context, 
      CFRange range );    

That could save you the trouble of iterating over each glyph. You could use it something like this...

CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CTLineRef line = CTLineCreateWithAttributedString(
      (__bridge CFTypeRef)self.attributedString);

  CFArrayRef runs = CTLineGetGlyphRuns(line);
  CFIndex runCount = CFArrayGetCount(runs);
  for (CFIndex runIndex = 0; runIndex < runCount; ++runIndex) {
      CTRunRef run = CFArrayGetValueAtIndex(runs, runIndex);
      [self adjustContextForRun:run];
       CTRunDraw (run, context, 0)
 }

(thats just a sketch, implementation will depend on your needs, and i haven't tested the code)

adjustContextForRun would be responsible for setting things like font and initial draw position for the run.

Each CTRun represents a subrange of an attributed string where all of the attributes are the same. IF you don't vary attributes over a line, you can abstract this further:

  CTLineDraw(line, context);

I don't know if that level of abstraction would work in your case (i am only used to working with Latin fonts), but its worth knowing it's there, saves a lot of lower-level trouble.

You can set the initial drawing position for the text with this:

 void CGContextSetTextPosition ( 
    CGContextRef c, 
    CGFloat x, 
    CGFloat y );

Upvotes: 3

Related Questions