Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Better string metrics on OS X.
#import <Foundation/Foundation.h>
@interface NSString (IBNMetrics)
- (CGSize)ibn_sizeConstrainedToSize:(CGSize)size font:(NSFont *)font;
- (CGSize)ibn_sizeWithFont:(NSFont *)font;
@end
#import "NSString+IBNMetrics.h"
@implementation NSString (IBNMetrics)
- (CGSize)ibn_sizeWithFont:(NSFont *)font {
return [self ibn_sizeConstrainedToSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) font:font];
}
- (CGSize)ibn_sizeConstrainedToSize:(CGSize)size font:(NSFont *)font {
CTFontRef coreTextFont = CTFontCreateWithName((__bridge CFStringRef)font.fontName, font.pointSize, NULL);
CGFloat leading = font.leading;
CTParagraphStyleSetting paragraphSettings[1] = { kCTParagraphStyleSpecifierLineSpacingAdjustment, sizeof(CGFloat), &leading };
CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(paragraphSettings, 1);
CFRange textRange = CFRangeMake(0, self.length);
CFMutableAttributedStringRef mutableString = CFAttributedStringCreateMutable(kCFAllocatorDefault, self.length);
CFAttributedStringReplaceString(mutableString, CFRangeMake(0, 0), (CFStringRef)self);
CFAttributedStringSetAttribute(mutableString, textRange, kCTFontAttributeName, coreTextFont);
CFAttributedStringSetAttribute(mutableString, textRange, kCTParagraphStyleAttributeName, paragraphStyle);
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(mutableString);
CFRange fitRange;
CGSize frameSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, textRange, NULL, size, &fitRange);
CFRelease(coreTextFont);
CFRelease(paragraphStyle);
CFRelease(framesetter);
CFRelease(mutableString);
return frameSize;
}
@end
@tonyarnold

This comment has been minimized.

Copy link

@tonyarnold tonyarnold commented Jan 3, 2014

This seems to chop off descenders:

Image of chopped off descenders

@jwilling

This comment has been minimized.

Copy link
Owner Author

@jwilling jwilling commented Jan 14, 2014

@tonyarnold Thanks for that, I think I didn't actually try this out with multi-line text. I'll look into this more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.