Skip to content

Commit

Permalink
Fix bug in sizeWithFont (#1917)
Browse files Browse the repository at this point in the history
NSString+UIKitAdditions sizeWithFont:constrainedToSize: should return the height that the text requires rather than the height of the text that can actually fit in the region that CTFramesetterSuggestFrameSizeWithConstraints returns.
  • Loading branch information
aballway authored Feb 9, 2017
1 parent 4527ce3 commit e6efd44
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
13 changes: 12 additions & 1 deletion Frameworks/UIKit/NSString+UIKitAdditions.mm
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,11 @@ - (CGSize)drawAtPoint:(CGPoint)point
// Returns the bounding box size this string would occupy when drawn as specified
// All sizeWith... functions in this file funnel to this
- (CGSize)_sizeWithAttributes:(NSDictionary<NSString*, id>*)attributes constrainedToSize:(CGSize)size {
UIFont* font = attributes[NSFontAttributeName];
if (font == nil) {
return CGSizeZero;
}

if ([attributes objectForKey:NSParagraphStyleAttributeName]) {
NSMutableDictionary* copied = [NSMutableDictionary dictionaryWithDictionary:attributes];
woc::unique_cf<CTParagraphStyleRef>
Expand All @@ -263,7 +268,13 @@ - (CGSize)_sizeWithAttributes:(NSDictionary<NSString*, id>*)attributes constrain
size.height = std::numeric_limits<CGFloat>::max();
}

return CTFramesetterSuggestFrameSizeWithConstraints(framesetter.get(), CFRangeMake(0, self.length), nullptr, size, nullptr);
CGSize ret = CTFramesetterSuggestFrameSizeWithConstraints(framesetter.get(), CFRangeMake(0, self.length), nullptr, size, nullptr);

// If the constrained height is less than a line height sizeWithFont will increase the returned size to fit at least one line
CGFloat lineHeight = [font ascender] - [font descender];
ret.height = std::max(ret.height, lineHeight);

return ret;
}

// Private helper that converts a UILineBreakMode -> NSParagraphStyle
Expand Down
18 changes: 18 additions & 0 deletions tests/unittests/UIKit/NSString+UIKitAdditionsTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,28 @@

#import <TestFramework.h>
#import <UIKit/UIKit.h>
#import <CppUtils.h>

static constexpr double c_errorDelta = .0001;
TEST(NSString_UIKitAdditions, ShouldNotReturnSizeOfZeroWidth) {
CGSize size =
[@"TEST" sizeWithFont:[UIFont systemFontOfSize:12.0f] constrainedToSize:CGSizeZero lineBreakMode:NSLineBreakByWordWrapping];
EXPECT_LT(0.0, size.width);
EXPECT_LT(0.0, size.height);
}

TEST(NSString_UIKitAdditions, SizeWithFontShouldReturnLineHeightWhenConstrainedHeightIsTooSmall) {
CGSize givenSize = { 0, 15 };
UIFont* font = [UIFont systemFontOfSize:144];
CGFloat lineHeight = [font ascender] - [font descender];
CGSize size = [@"TEST" sizeWithFont:font constrainedToSize:givenSize];
EXPECT_NEAR(lineHeight, size.height, c_errorDelta);

size = [@"TEST\nTEST" sizeWithFont:font constrainedToSize:givenSize];
EXPECT_NEAR(lineHeight, size.height, c_errorDelta);
}

TEST(NSString_UIKitAdditions, SizeWithNoFontShouldReturnCGSizeZero) {
CGSize arbitrarySize = { 100, 150 };
EXPECT_EQ(CGSizeZero, [@"TEST" sizeWithFont:nil constrainedToSize:arbitrarySize]);
}

0 comments on commit e6efd44

Please sign in to comment.