Skip to content
Snippets Groups Projects
Commit 1265313b authored by George Nachman's avatar George Nachman
Browse files

Fix multiline badges. Apple broke measuring text with newlines in 10.13.

parent 4f626513
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -260,6 +260,11 @@ int decode_utf8_char(const unsigned char * restrict datap,
 
- (NSString *)stringByMakingControlCharactersToPrintable;
 
// These methods work on 10.13 with strings that include newlines, and are consistent with each other.
// The built in NSString API ignores everything from the first newline on for computing bounds.
- (NSRect)it_boundingRectWithSize:(NSSize)bounds attributes:(NSDictionary *)attributes truncated:(BOOL *)truncated;
- (void)it_drawInRect:(CGRect)rect attributes:(NSDictionary *)attributes;
@end
 
@interface NSMutableString (iTerm)
Loading
Loading
Loading
Loading
@@ -1752,6 +1752,72 @@ static TECObjectRef CreateTECConverterForUTF8Variants(TextEncodingVariant varian
return temp;
}
 
- (NSRect)it_boundingRectWithSize:(NSSize)bounds attributes:(NSDictionary *)attributes truncated:(BOOL *)truncated {
CGSize size = { 0, 0 };
*truncated = NO;
for (NSString *part in [self componentsSeparatedByString:@"\n"]) {
CFMutableAttributedStringRef string =
(CFMutableAttributedStringRef)[[[NSAttributedString alloc] initWithString:part
attributes:attributes] autorelease];
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(string);
CFRange fitRange;
CFRange textRange = CFRangeMake(0, part.length);
CGSize frameSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter,
textRange,
NULL,
bounds,
&fitRange);
if (fitRange.length != part.length) {
*truncated = YES;
}
CFRelease(framesetter);
size.width = MAX(size.width, frameSize.width);
size.height += frameSize.height;
}
return NSMakeRect(0, 0, size.width, size.height);
}
- (void)it_drawInRect:(CGRect)rect attributes:(NSDictionary *)attributes {
CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort];
CGContextSaveGState(ctx);
for (NSString *part in [self componentsSeparatedByString:@"\n"]) {
CFMutableAttributedStringRef string =
(CFMutableAttributedStringRef)[[[NSAttributedString alloc] initWithString:part
attributes:attributes] autorelease];
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(string);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, rect);
CTFrameRef textFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0,0), path, NULL);
CTFrameDraw(textFrame, ctx);
CFRange fitRange;
// Get the height of the line and translate the context down by it
CFRange textRange = CFRangeMake(0, part.length);
CGSize frameSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter,
textRange,
NULL,
rect.size,
&fitRange);
CGContextTranslateCTM(ctx, 0, -frameSize.height);
CGPathRelease(path);
CFRelease(framesetter);
}
CGContextRestoreGState(ctx);
}
@end
 
@implementation NSMutableString (iTerm)
Loading
Loading
Loading
Loading
@@ -9,6 +9,7 @@
#import "iTermBadgeLabel.h"
#import "DebugLogging.h"
#import "iTermAdvancedSettingsModel.h"
#import "NSStringITerm.h"
 
@interface iTermBadgeLabel()
@property(nonatomic, retain) NSImage *image;
Loading
Loading
@@ -113,16 +114,16 @@
NSDictionary *attributes = [self attributesWithPointSize:pointSize];
NSMutableDictionary *temp = [[attributes mutableCopy] autorelease];
temp[NSStrokeColorAttributeName] = [_backgroundColor colorWithAlphaComponent:1];
NSSize sizeWithFont = [self sizeWithAttributes:temp];
BOOL truncated;
NSSize sizeWithFont = [self sizeWithAttributes:temp truncated:&truncated];
if (sizeWithFont.width <= 0 || sizeWithFont.height <= 0) {
return nil;
}
 
NSImage *image = [[[NSImage alloc] initWithSize:sizeWithFont] autorelease];
[image lockFocus];
[_stringValue drawWithRect:NSMakeRect(0, 0, sizeWithFont.width, sizeWithFont.height)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:temp];
[_stringValue it_drawInRect:NSMakeRect(0, 0, sizeWithFont.width, sizeWithFont.height)
attributes:temp];
[image unlockFocus];
 
NSImage *reducedAlphaImage = [[[NSImage alloc] initWithSize:sizeWithFont] autorelease];
Loading
Loading
@@ -159,12 +160,12 @@
}
 
// Size of the image resulting from drawing an attributed string with |attributes|.
- (NSSize)sizeWithAttributes:(NSDictionary *)attributes {
- (NSSize)sizeWithAttributes:(NSDictionary *)attributes truncated:(BOOL *)truncated {
NSSize size = self.maxSize;
size.height = CGFLOAT_MAX;
NSRect bounds = [_stringValue boundingRectWithSize:self.maxSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes];
NSRect bounds = [_stringValue it_boundingRectWithSize:self.maxSize
attributes:attributes
truncated:truncated];
return bounds.size;
}
 
Loading
Loading
@@ -189,9 +190,11 @@
int prevPoints = -1;
NSSize sizeWithFont = NSZeroSize;
while (points != prevPoints) {
sizeWithFont = [self sizeWithAttributes:[self attributesWithPointSize:points]];
BOOL truncated;
sizeWithFont = [self sizeWithAttributes:[self attributesWithPointSize:points] truncated:&truncated];
DLog(@"Point size of %@ gives label size of %@", @(points), NSStringFromSize(sizeWithFont));
if (sizeWithFont.width > maxSize.width ||
if (truncated ||
sizeWithFont.width > maxSize.width ||
sizeWithFont.height > maxSize.height) {
max = points;
} else if (sizeWithFont.width < maxSize.width &&
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment