Compact layout / widow reduction.

pull/1/head
Matthew Chen 7 years ago
parent 3bee54dbef
commit f5239a4fbd

@ -855,6 +855,38 @@ NS_ASSUME_NONNULL_BEGIN
OWSMessageTextView *bodyTextView = [self configureBodyTextView];
CGSize textSize = CGSizeCeil([bodyTextView sizeThatFits:CGSizeMake(maxTextWidth, CGFLOAT_MAX)]);
// "Compact" layout to reduce "widows",
// e.g. last lines with only a single word.
//
// After measuring the size of the text, we try to find smaller widths
// in which the text will fit without adding any height, by wrapping
// more text onto the last line. We use a binary search.
if (textSize.width > 0 && textSize.height > 0) {
NSUInteger upperBound = (NSUInteger)textSize.width;
NSUInteger lowerBound = 1;
// The more iterations we perform in our binary search,
// the more accurate the result, but the more expensive
// layout becomes.
const int kMaxIterations = 5;
for (int i = 0; i < kMaxIterations; i++) {
NSUInteger resizeWidth = (upperBound + lowerBound) / 2;
if (resizeWidth >= upperBound || resizeWidth <= lowerBound) {
break;
}
CGSize resizeSize = CGSizeCeil([bodyTextView sizeThatFits:CGSizeMake(resizeWidth, CGFLOAT_MAX)]);
BOOL success
= (resizeSize.width > 0 && resizeSize.width <= resizeWidth && resizeSize.height <= textSize.height);
if (success) {
// Success.
textSize = resizeSize;
upperBound = (NSUInteger)textSize.width;
} else {
// Failure.
lowerBound = resizeWidth;
}
}
}
textSize.width = MIN(textSize.width, maxTextWidth);
CGSize result = textSize;

Loading…
Cancel
Save