CoreText CTFramesetterSuggestFrameSizeWithConstraints vs UILabel sizeWithFont

I ran in to trouble with UILabel’s sizeWithFont while trying to determine how many CoreText columns will I need for my text. Apparently UILabel and CoreText, while uses same font and font size, has a little bit different line heights and that messes up any calculations. I was quite desperate and too lazy to study various CoreText related references, so I ended up drawing invisible frames filled with text and counting them to get correct number of frames I will actually need.

Today I finally discovered CTFramesetterSuggestFrameSizeWithConstraints which can help with two important things: to get size of the frame you need for your CFAttributedString or to get how many characters of your string would fill frame with particular CGSize.

So, here is some code to illustrate different height results from both functions:

	//	test string
	NSString *text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent pellentesque viverra est, molestie vehicula turpis consectetur sed. In hac habitasse platea dictumst. Maecenas vel dolor dolor, et hendrerit libero. Aliquam malesuada, erat vitae tempus tincidunt, ipsum tortor ultrices nunc, a rhoncus diam ligula nec purus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec nec nisi libero. Phasellus viverra imperdiet urna. Ut mollis vulputate metus sed sollicitudin. Aenean viverra tellus vitae tortor placerat imperdiet. Integer porta magna ut mauris euismod in tincidunt justo ornare. Donec ac leo augue. Quisque luctus vehicula nisi id ornare. Pellentesque quis mi ac arcu semper cursus at eu purus. ";

	CGContextRef context = (CGContextRef)UIGraphicsGetCurrentContext();

	//	creating and formatting CFMutableAttributedString
	CFMutableAttributedStringRef attrStr = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
	CFAttributedStringReplaceString (attrStr, CFRangeMake(0, 0), (CFStringRef) text);
	CTFontRef font = CTFontCreateWithName(CFSTR("Times New Roman"), fontSize, NULL);
	CTTextAlignment alignment = kCTJustifiedTextAlignment;
	CTParagraphStyleSetting _settings[] = {	{kCTParagraphStyleSpecifierAlignment, sizeof(alignment), &alignment} };
	CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(_settings, sizeof(_settings) / sizeof(_settings[0]));
	CFAttributedStringSetAttribute(attrStr, CFRangeMake(0, CFAttributedStringGetLength(attrStr)), kCTParagraphStyleAttributeName, paragraphStyle);
	CFAttributedStringSetAttribute(attrStr, CFRangeMake(0, CFAttributedStringGetLength(attrStr)), kCTFontAttributeName, font);
	CFRelease(paragraphStyle);
	CFRelease(font);	

	CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrStr);
	CFRelease(attrStr);

	int textLength = [text length];
	CFRange range;
	CGFloat maxWidth	= 100.0f;
	CGFloat maxHeight	= 10000.0f;
	CGSize constraint	= CGSizeMake(maxWidth, maxHeight);

	//	checking frame sizes
	CGSize labelSize	= [article.body sizeWithFont:[UIFont fontWithName:@"Times New Roman" size:16] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
	CGSize coreTextSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, textLength), nil, constraint, &range);	

	//	printing results
	NSLog(@"Label.sizeWithFont: %f x %f", labelSize.width, labelSize.height);
	NSLog(@"CoreText.SuggestFrameSize: %f x %f", coreTextSize.width, coreTextSize.height);
	NSLog(@"Character count in constraint frame: %d (total: %d)", range.length, textLength);

Results:

Label.sizeWithFont: 100.000000 x 1160.000000
CoreText.SuggestFrameSize: 100.000008 x 1059.507812
Character count in constraint frame: 718 (total: 718)

100px is significant difference and it increases proportionally with text size. Also to demonstrate CFRange usefulness I’ll use 100×100 constraint:

Label.sizeWithFont: 99.000000 x 100.000000
CoreText.SuggestFrameSize: 100.000000 x 84.390625
Character count in constraint frame: 66 (total: 718)

SuggestFrameSize results are interesting in this one. I guess, we get 84.39 height, because CoreText couldn’t fit another line, so updated constraint frame with REAL height.

Tags: , , , , , ,

4 responses

  1. GianPac
    Posted January 27, 2011 at 20:39 | Permalink

    Did you ever figure out how to fix the problem?

  2. Posted April 10, 2013 at 04:05 | Permalink

    Greetings from Los angeles! I’m bored to death at work so I decided to check out your website on my iphone during lunch break. I love the info you provide here and can’t wait to take a
    look when I get home. I’m shocked at how quick your blog loaded on my cell phone .. I’m not
    even using WIFI, just 3G .. Anyways, superb blog!

  3. Posted April 17, 2013 at 18:19 | Permalink

    I am really loving the theme/design of your website.
    Do you ever run into any browser compatibility problems?
    A number of my blog readers have complained about my site
    not working correctly in Explorer but looks great in
    Opera. Do you have any recommendations to help fix
    this issue?

  4. Posted May 8, 2013 at 08:37 | Permalink

    I know this if off topic but I’m looking into starting my own blog and was wondering what all is needed to get setup? I’m
    assuming having a blog like yours would cost a pretty penny?
    I’m not very internet savvy so I’m not 100% certain. Any suggestions or advice would be greatly appreciated.
    Thanks

Leave a Reply