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
@@ -260,6 +260,11 @@ int decode_utf8_char(const unsigned char * restrict datap,
Loading
@@ -260,6 +260,11 @@ int decode_utf8_char(const unsigned char * restrict datap,
   
- (NSString *)stringByMakingControlCharactersToPrintable; - (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 @end
   
@interface NSMutableString (iTerm) @interface NSMutableString (iTerm)
Loading
Loading
Loading
@@ -1752,6 +1752,72 @@ static TECObjectRef CreateTECConverterForUTF8Variants(TextEncodingVariant varian
Loading
@@ -1752,6 +1752,72 @@ static TECObjectRef CreateTECConverterForUTF8Variants(TextEncodingVariant varian
return temp; 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 @end
   
@implementation NSMutableString (iTerm) @implementation NSMutableString (iTerm)
Loading
Loading
Loading
@@ -9,6 +9,7 @@
Loading
@@ -9,6 +9,7 @@
#import "iTermBadgeLabel.h" #import "iTermBadgeLabel.h"
#import "DebugLogging.h" #import "DebugLogging.h"
#import "iTermAdvancedSettingsModel.h" #import "iTermAdvancedSettingsModel.h"
#import "NSStringITerm.h"
   
@interface iTermBadgeLabel() @interface iTermBadgeLabel()
@property(nonatomic, retain) NSImage *image; @property(nonatomic, retain) NSImage *image;
Loading
@@ -113,16 +114,16 @@
Loading
@@ -113,16 +114,16 @@
NSDictionary *attributes = [self attributesWithPointSize:pointSize]; NSDictionary *attributes = [self attributesWithPointSize:pointSize];
NSMutableDictionary *temp = [[attributes mutableCopy] autorelease]; NSMutableDictionary *temp = [[attributes mutableCopy] autorelease];
temp[NSStrokeColorAttributeName] = [_backgroundColor colorWithAlphaComponent:1]; 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) { if (sizeWithFont.width <= 0 || sizeWithFont.height <= 0) {
return nil; return nil;
} }
   
NSImage *image = [[[NSImage alloc] initWithSize:sizeWithFont] autorelease]; NSImage *image = [[[NSImage alloc] initWithSize:sizeWithFont] autorelease];
[image lockFocus]; [image lockFocus];
[_stringValue drawWithRect:NSMakeRect(0, 0, sizeWithFont.width, sizeWithFont.height) [_stringValue it_drawInRect:NSMakeRect(0, 0, sizeWithFont.width, sizeWithFont.height)
options:NSStringDrawingUsesLineFragmentOrigin attributes:temp];
attributes:temp];
[image unlockFocus]; [image unlockFocus];
   
NSImage *reducedAlphaImage = [[[NSImage alloc] initWithSize:sizeWithFont] autorelease]; NSImage *reducedAlphaImage = [[[NSImage alloc] initWithSize:sizeWithFont] autorelease];
Loading
@@ -159,12 +160,12 @@
Loading
@@ -159,12 +160,12 @@
} }
   
// Size of the image resulting from drawing an attributed string with |attributes|. // 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; NSSize size = self.maxSize;
size.height = CGFLOAT_MAX; size.height = CGFLOAT_MAX;
NSRect bounds = [_stringValue boundingRectWithSize:self.maxSize NSRect bounds = [_stringValue it_boundingRectWithSize:self.maxSize
options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes
attributes:attributes]; truncated:truncated];
return bounds.size; return bounds.size;
} }
   
Loading
@@ -189,9 +190,11 @@
Loading
@@ -189,9 +190,11 @@
int prevPoints = -1; int prevPoints = -1;
NSSize sizeWithFont = NSZeroSize; NSSize sizeWithFont = NSZeroSize;
while (points != prevPoints) { 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)); 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) { sizeWithFont.height > maxSize.height) {
max = points; max = points;
} else if (sizeWithFont.width < maxSize.width && } 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