Drawing Text with Core Graphics

后端 未结 3 1228
庸人自扰
庸人自扰 2021-02-02 02:15

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         


        
相关标签:
3条回答
  • 2021-02-02 02:58

    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.

    0 讨论(0)
  • 2021-02-02 03:03

    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)
    
    0 讨论(0)
  • 2021-02-02 03:07

    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];
    
    0 讨论(0)
提交回复
热议问题