mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
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:
@@ -22,6 +22,8 @@
|
|||||||
std::mutex _textKitMutex;
|
std::mutex _textKitMutex;
|
||||||
BOOL _measured;
|
BOOL _measured;
|
||||||
CGFloat _scaleFactor;
|
CGFloat _scaleFactor;
|
||||||
|
NSLayoutManager *_sizingLayoutManager;
|
||||||
|
NSTextContainer *_sizingTextContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithContext:(ASTextKitContext *)context
|
- (instancetype)initWithContext:(ASTextKitContext *)context
|
||||||
@@ -84,23 +86,31 @@
|
|||||||
std::lock_guard<std::mutex> l(__static_mutex);
|
std::lock_guard<std::mutex> l(__static_mutex);
|
||||||
|
|
||||||
NSTextStorage *textStorage = _attributes.textStorageCreationBlock ? _attributes.textStorageCreationBlock(attributedString) : [[NSTextStorage alloc] initWithAttributedString:attributedString];
|
NSTextStorage *textStorage = _attributes.textStorageCreationBlock ? _attributes.textStorageCreationBlock(attributedString) : [[NSTextStorage alloc] initWithAttributedString:attributedString];
|
||||||
NSLayoutManager *layoutManager = _attributes.layoutManagerCreationBlock ? _attributes.layoutManagerCreationBlock() : [[ASLayoutManager alloc] init];
|
if (_sizingLayoutManager == nil) {
|
||||||
layoutManager.usesFontLeading = NO;
|
_sizingLayoutManager = _attributes.layoutManagerCreationBlock ? _attributes.layoutManagerCreationBlock() : [[ASLayoutManager alloc] init];
|
||||||
[textStorage addLayoutManager:layoutManager];
|
_sizingLayoutManager.usesFontLeading = NO;
|
||||||
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(_constrainedSize.width, FLT_MAX)];
|
}
|
||||||
|
[textStorage addLayoutManager:_sizingLayoutManager];
|
||||||
textContainer.lineFragmentPadding = 0;
|
if (_sizingTextContainer == nil) {
|
||||||
textContainer.lineBreakMode = _attributes.lineBreakMode;
|
// 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
|
// use 0 regardless of what is in the attributes so that we get an accurate line count
|
||||||
textContainer.maximumNumberOfLines = 0;
|
_sizingTextContainer.maximumNumberOfLines = 0;
|
||||||
textContainer.exclusionPaths = _attributes.exclusionPaths;
|
[_sizingLayoutManager addTextContainer:_sizingTextContainer];
|
||||||
[layoutManager addTextContainer:textContainer];
|
|
||||||
|
|
||||||
for (NSRange lineRange = { 0, 0 }; NSMaxRange(lineRange) < [layoutManager numberOfGlyphs] && lineCount <= _attributes.maximumNumberOfLines; lineCount++) {
|
|
||||||
[layoutManager lineFragmentRectForGlyphAtIndex:NSMaxRange(lineRange) effectiveRange:&lineRange];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_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;
|
return lineCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -145,7 +145,17 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet()
|
|||||||
|
|
||||||
// Force glyph generation and layout, which may not have happened yet (and isn't triggered by
|
// Force glyph generation and layout, which may not have happened yet (and isn't triggered by
|
||||||
// -usedRectForTextContainer:).
|
// -usedRectForTextContainer:).
|
||||||
|
__block NSTextStorage *scaledTextStorage = nil;
|
||||||
|
BOOL isScaled = [self isScaled];
|
||||||
[[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
|
[[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
|
||||||
|
if (isScaled) {
|
||||||
|
NSMutableAttributedString *scaledString = [[NSMutableAttributedString alloc] initWithAttributedString:textStorage];
|
||||||
|
[ASTextKitFontSizeAdjuster adjustFontSizeForAttributeString:scaledString withScaleFactor:_currentScaleFactor];
|
||||||
|
scaledTextStorage = [[NSTextStorage alloc] initWithAttributedString:scaledString];
|
||||||
|
|
||||||
|
[textStorage removeLayoutManager:layoutManager];
|
||||||
|
[scaledTextStorage addLayoutManager:layoutManager];
|
||||||
|
}
|
||||||
[layoutManager ensureLayoutForTextContainer:textContainer];
|
[layoutManager ensureLayoutForTextContainer:textContainer];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@@ -153,6 +163,11 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet()
|
|||||||
__block CGRect boundingRect;
|
__block CGRect boundingRect;
|
||||||
[[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
|
[[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
|
||||||
boundingRect = [layoutManager usedRectForTextContainer:textContainer];
|
boundingRect = [layoutManager usedRectForTextContainer:textContainer];
|
||||||
|
if (isScaled) {
|
||||||
|
// put the non-scaled version back
|
||||||
|
[scaledTextStorage removeLayoutManager:layoutManager];
|
||||||
|
[textStorage addLayoutManager:layoutManager];
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
// TextKit often returns incorrect glyph bounding rects in the horizontal direction, so we clip to our bounding rect
|
// TextKit often returns incorrect glyph bounding rects in the horizontal direction, so we clip to our bounding rect
|
||||||
@@ -160,10 +175,11 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet()
|
|||||||
boundingRect = CGRectIntersection(boundingRect, {.size = constrainedRect.size});
|
boundingRect = CGRectIntersection(boundingRect, {.size = constrainedRect.size});
|
||||||
CGSize boundingSize = [_shadower outsetSizeWithInsetSize:boundingRect.size];
|
CGSize boundingSize = [_shadower outsetSizeWithInsetSize:boundingRect.size];
|
||||||
_calculatedSize = CGSizeMake(boundingSize.width, boundingSize.height);
|
_calculatedSize = CGSizeMake(boundingSize.width, boundingSize.height);
|
||||||
|
}
|
||||||
|
|
||||||
if (_currentScaleFactor > 0.0 && _currentScaleFactor < 1.0) {
|
- (BOOL)isScaled
|
||||||
_calculatedSize.height = ceilf(_calculatedSize.height * _currentScaleFactor);
|
{
|
||||||
}
|
return (self.currentScaleFactor > 0 && self.currentScaleFactor < 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Drawing
|
#pragma mark - Drawing
|
||||||
@@ -189,7 +205,7 @@ static NSCharacterSet *_defaultAvoidTruncationCharacterSet()
|
|||||||
[[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
|
[[self context] performBlockWithLockedTextKitComponents:^(NSLayoutManager *layoutManager, NSTextStorage *textStorage, NSTextContainer *textContainer) {
|
||||||
|
|
||||||
NSTextStorage *scaledTextStorage = nil;
|
NSTextStorage *scaledTextStorage = nil;
|
||||||
BOOL isScaled = (self.currentScaleFactor > 0 && self.currentScaleFactor < 1.0);
|
BOOL isScaled = [self isScaled];
|
||||||
|
|
||||||
if (isScaled) {
|
if (isScaled) {
|
||||||
// if we are going to scale the text, swap out the non-scaled text for the scaled version.
|
// if we are going to scale the text, swap out the non-scaled text for the scaled version.
|
||||||
|
|||||||
Reference in New Issue
Block a user