Fixed some text shrinking issues

Previously I was multiplying the calculated height of the text by the scale factor. This fails in the case where we have a long string that doesn't fit, but it is shrunk so much that it now has more than enough room in the renderer's constrained size. In this case we fail to update the calculated size's width.

Also updated `lineCountForString` in `ASTextKitFontSizeAdjuster` to reuse a sizer layout manager and text container.
This commit is contained in:
rcancro
2016-03-09 15:27:33 -08:00
parent de4e4db671
commit bcb1832fcd
2 changed files with 58 additions and 32 deletions

View File

@@ -22,6 +22,8 @@
std::mutex _textKitMutex;
BOOL _measured;
CGFloat _scaleFactor;
NSLayoutManager *_sizingLayoutManager;
NSTextContainer *_sizingTextContainer;
}
- (instancetype)initWithContext:(ASTextKitContext *)context
@@ -78,30 +80,38 @@
- (NSUInteger)lineCountForString:(NSAttributedString *)attributedString
{
NSUInteger lineCount = 0;
static std::mutex __static_mutex;
std::lock_guard<std::mutex> l(__static_mutex);
NSTextStorage *textStorage = _attributes.textStorageCreationBlock ? _attributes.textStorageCreationBlock(attributedString) : [[NSTextStorage alloc] initWithAttributedString:attributedString];
NSLayoutManager *layoutManager = _attributes.layoutManagerCreationBlock ? _attributes.layoutManagerCreationBlock() : [[ASLayoutManager alloc] init];
layoutManager.usesFontLeading = NO;
[textStorage addLayoutManager:layoutManager];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(_constrainedSize.width, FLT_MAX)];
textContainer.lineFragmentPadding = 0;
textContainer.lineBreakMode = _attributes.lineBreakMode;
// use 0 regardless of what is in the attributes so that we get an accurate line count
textContainer.maximumNumberOfLines = 0;
textContainer.exclusionPaths = _attributes.exclusionPaths;
[layoutManager addTextContainer:textContainer];
for (NSRange lineRange = { 0, 0 }; NSMaxRange(lineRange) < [layoutManager numberOfGlyphs] && lineCount <= _attributes.maximumNumberOfLines; lineCount++) {
[layoutManager lineFragmentRectForGlyphAtIndex:NSMaxRange(lineRange) effectiveRange:&lineRange];
}
return lineCount;
NSUInteger lineCount = 0;
static std::mutex __static_mutex;
std::lock_guard<std::mutex> l(__static_mutex);
NSTextStorage *textStorage = _attributes.textStorageCreationBlock ? _attributes.textStorageCreationBlock(attributedString) : [[NSTextStorage alloc] initWithAttributedString:attributedString];
if (_sizingLayoutManager == nil) {
_sizingLayoutManager = _attributes.layoutManagerCreationBlock ? _attributes.layoutManagerCreationBlock() : [[ASLayoutManager alloc] init];
_sizingLayoutManager.usesFontLeading = NO;
}
[textStorage addLayoutManager:_sizingLayoutManager];
if (_sizingTextContainer == nil) {
// make this text container unbounded in height so that the layout manager will compute the total
// number of lines and not stop counting when height runs out.
_sizingTextContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(_constrainedSize.width, FLT_MAX)];
_sizingTextContainer.lineFragmentPadding = 0;
// use 0 regardless of what is in the attributes so that we get an accurate line count
_sizingTextContainer.maximumNumberOfLines = 0;
[_sizingLayoutManager addTextContainer:_sizingTextContainer];
}
_sizingTextContainer.lineBreakMode = _attributes.lineBreakMode;
_sizingTextContainer.exclusionPaths = _attributes.exclusionPaths;
for (NSRange lineRange = { 0, 0 }; NSMaxRange(lineRange) < [_sizingLayoutManager numberOfGlyphs] && lineCount <= _attributes.maximumNumberOfLines; lineCount++) {
[_sizingLayoutManager lineFragmentRectForGlyphAtIndex:NSMaxRange(lineRange) effectiveRange:&lineRange];
}
[textStorage removeLayoutManager:_sizingLayoutManager];
return lineCount;
}
- (CGFloat)scaleFactor