Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSString sizeWithAttributes: content rect

How do I get a NSString's size as if it drew in an NSRect. The problem is when I try -[NSString sizeWithAttributes:], it returns an NSSize as if it had infinite width. I want to give a maximum width to the method. Is there any way of doing so? (BTW: Mac OS, not iPhone OS)

Thanks, Alex

like image 879
Alexandre Cassagne Avatar asked Jan 02 '10 21:01

Alexandre Cassagne


4 Answers

for OSX cocoa/Swift 4: (using a custom NSview, to show also how to draw)

//
//  CustomView.swift
//  DrawMyString
//
//  Created by ing.conti on 19/10/2018.
//  Copyright © 2018 com.ingconti. All rights reserved.
//

import Cocoa

class CustomView: NSView {

    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)

        let s : NSString = "AA BB CC DD EE FF"
        let W = 50
        let size = NSSize(width: W, height: 100)

        let boundingRectWithSize  = s.boundingRect(with: size, options: .usesLineFragmentOrigin, attributes: [:])

        let r = NSRect(origin: CGPoint(x: 20, y: 30), size: boundingRectWithSize.size)

        s.draw(in: r, withAttributes: [:])
        r.frame()
    }
}

(we also draw border, to see it)

like image 66
ingconti Avatar answered Nov 16 '22 03:11

ingconti


float heightForStringDrawing(NSString *myString, NSFont *myFont,
        float myWidth)
{
 NSTextStorage *textStorage = [[[NSTextStorage alloc] initWithString:myString] autorelease];
 NSTextContainer *textContainer = [[[NSTextContainer alloc] initWithContainerSize:NSMakeSize(myWidth, FLT_MAX)] autorelease];
 ;
        NSLayoutManager *layoutManager = [[[NSLayoutManager alloc] init] autorelease];
 [layoutManager addTextContainer:textContainer];
 [textStorage addLayoutManager:layoutManager];
 [textStorage addAttribute:NSFontAttributeName value:myFont
      range:NSMakeRange(0, [textStorage length])];
 [textContainer setLineFragmentPadding:0.0];

 (void) [layoutManager glyphRangeForTextContainer:textContainer];
 return [layoutManager
   usedRectForTextContainer:textContainer].size.height;
}

It was in the docs after all. Thank you Joshua anyway!

like image 34
Alexandre Cassagne Avatar answered Nov 16 '22 03:11

Alexandre Cassagne


I revised Alexandre Cassagne's answer for iOS with ARC enabled.

CGSize ACMStringSize(NSString *string, UIFont *font, CGSize size)
{
    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithString:string];
    [textStorage addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, [textStorage length])];
    NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
    NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:size];
    textContainer.lineFragmentPadding = 0;
    [layoutManager addTextContainer:textContainer];
    [textStorage addLayoutManager:layoutManager];
    return [layoutManager usedRectForTextContainer:textContainer].size;
}
like image 30
ma11hew28 Avatar answered Nov 16 '22 04:11

ma11hew28


I believe your only option here is NSLayoutManager and asking for a union of the used rects for a given glyph range.

like image 40
Joshua Nozzi Avatar answered Nov 16 '22 03:11

Joshua Nozzi