I need to draw centered text to a CGContext.
I started with a Cocoa approach. I created a NSCell with the text and tried to draw it thus:
NSGraphicsConte
I finally managed to find answers after 4 days of searching. I really wish Apple makes better documentation. So here we go
I assume you already have CGFontRef with you. If not let me know I will tell you how to load a ttf from resource bundle into CgFontRef.
Below is the code snippet to compute the bounds of any string with any CGFontref
int charCount = [string length];
CGGlyph glyphs[charCount];
CGRect rects[charCount];
CTFontGetGlyphsForCharacters(theCTFont, (const unichar*)[string cStringUsingEncoding:NSUnicodeStringEncoding], glyphs, charCount);
CTFontGetBoundingRectsForGlyphs(theCTFont, kCTFontDefaultOrientation, glyphs, rects, charCount);
int totalwidth = 0, maxheight = 0;
for (int i=0; i < charCount; i++)
{
totalwidth += rects[i].size.width;
maxheight = maxheight < rects[i].size.height ? rects[i].size.height : maxheight;
}
dim = CGSizeMake(totalwidth, maxheight);
Reuse the same function CTFontGetGlyphsForCharacters to get the glyphs. To get a CTFontRef from a CGFontRef use CTFontCreateWithGraphicsFont() function
Also remember NSFont and CGFontRef are toll-free bridged, meaning they can casted into each other and they will work seamlessly without any extra work.
Swift 5 version!
let targetSize: CGSize = // the space you have available for drawing the text
let origin: CGPoint = // where you want to position the top-left corner
let string: String = // your string
let font: UIFont = // your font
let attrs: [NSAttributedString.Key:Any] = [.font: font]
let boundingRect = string.boundingRect(with: targetSize, options: [.usesLineFragmentOrigin], attributes: attrs, context: nil)
let textRect = CGRect(origin: origin, size: boundingRect.size)
text.draw(with: textRect, options: [.usesLineFragmentOrigin], attributes: attrs, context: nil)
I would continue with your above approach but use NSAttributedString instead.
NSGraphicsContext* newCtx = [NSGraphicsContext graphicsContextWithGraphicsPort:bitmapContext flipped:true];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:newCtx];
NSAttributedString *string = /* make a string with all of the desired attributes */;
[string drawInRect:locationToDraw];
[NSGraphicsContext restoreGraphicsState];