Skip to content

Commit

Permalink
ARCify NSImage+iTerm to fix a memory leak in it_imageWithTintColor: w…
Browse files Browse the repository at this point in the history
…here the image is copied but not autoreleased. Issue 8163
  • Loading branch information
gnachman committed Aug 25, 2019
1 parent 0ed945a commit 09a74a2
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 54 deletions.
4 changes: 2 additions & 2 deletions iTerm2.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1959,6 +1959,7 @@
A663013119D0864C004AF81C /* SCEvents.h in Headers */ = {isa = PBXBuildFile; fileRef = A663012619D0864C004AF81C /* SCEvents.h */; };
A663013219D0864C004AF81C /* SCEvents.h in Headers */ = {isa = PBXBuildFile; fileRef = A663012619D0864C004AF81C /* SCEvents.h */; };
A66319872308C60000C502BD /* NSStringITerm.m in Sources */ = {isa = PBXBuildFile; fileRef = E8E901A202743CA303A80106 /* NSStringITerm.m */; };
A66319882312139400C502BD /* NSImage+iTerm.m in Sources */ = {isa = PBXBuildFile; fileRef = A69B45B7197C60FB00F5444D /* NSImage+iTerm.m */; };
A66444BA1DEEA534000AC615 /* iTermDisclosableView.h in Headers */ = {isa = PBXBuildFile; fileRef = A66444B81DEEA534000AC615 /* iTermDisclosableView.h */; };
A666130A225CFF5A00840E89 /* BetterFontPicker.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A6661309225CFF5A00840E89 /* BetterFontPicker.framework */; };
A666130B225CFF5A00840E89 /* BetterFontPicker.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A6661309225CFF5A00840E89 /* BetterFontPicker.framework */; };
Expand Down Expand Up @@ -2893,7 +2894,6 @@
A6C762B41B45C52B00E3C992 /* NSDictionary+Profile.m in Sources */ = {isa = PBXBuildFile; fileRef = A61ABBBA1AE5F38C004656C2 /* NSDictionary+Profile.m */; };
A6C762B51B45C52B00E3C992 /* NSEvent+iTerm.m in Sources */ = {isa = PBXBuildFile; fileRef = A6E77F8E1A2449EF009B1CB6 /* NSEvent+iTerm.m */; };
A6C762B71B45C52B00E3C992 /* NSFont+iTerm.m in Sources */ = {isa = PBXBuildFile; fileRef = A6A2698218FE48B200437DA9 /* NSFont+iTerm.m */; };
A6C762B81B45C52B00E3C992 /* NSImage+iTerm.m in Sources */ = {isa = PBXBuildFile; fileRef = A69B45B7197C60FB00F5444D /* NSImage+iTerm.m */; };
A6C762BA1B45C52B00E3C992 /* NSMutableData+iTerm.m in Sources */ = {isa = PBXBuildFile; fileRef = A680AA1718CEBF5C0034D4F8 /* NSMutableData+iTerm.m */; };
A6C762BB1B45C52B00E3C992 /* NSMutableDictionary+Profile.m in Sources */ = {isa = PBXBuildFile; fileRef = A61ABBC11AE5F54A004656C2 /* NSMutableDictionary+Profile.m */; };
A6C762BD1B45C52B00E3C992 /* NSPasteboard+iTerm.m in Sources */ = {isa = PBXBuildFile; fileRef = A60D85A71A3A8105003AEE22 /* NSPasteboard+iTerm.m */; };
Expand Down Expand Up @@ -12681,6 +12681,7 @@
A63F34D121E1E0F8000C9D52 /* iTermSessionPicker.m in Sources */,
A66DABFF20867749006391A3 /* iTermTextViewAccessibilityHelper.m in Sources */,
53C166AB20C21FBB003B03AF /* iTermMigrationHelper.m in Sources */,
A66319882312139400C502BD /* NSImage+iTerm.m in Sources */,
53D68F812283EE7C0018710D /* iTermTmuxLayoutBuilder.m in Sources */,
A63011A520E7ECC2008114B7 /* iTermStatusBarSetupKnobsViewController.m in Sources */,
A66719611DCE3772000CE608 /* iTermIPV4Address.m in Sources */,
Expand Down Expand Up @@ -12910,7 +12911,6 @@
A6936B521D2F5CA200521B04 /* iTermAdditionalHotKeyObjectValue.m in Sources */,
A6C762FB1B45C52B00E3C992 /* FileTransferManager.m in Sources */,
A658716B1D85E6750061CEEE /* PFMoveApplication.m in Sources */,
A6C762B81B45C52B00E3C992 /* NSImage+iTerm.m in Sources */,
1D300BAB1BD9A8BB002043F7 /* NSDate+iTerm.m in Sources */,
A6C762E61B45C52B00E3C992 /* VT100Grid.m in Sources */,
A6C763981B45C52B00E3C992 /* TmuxControllerRegistry.m in Sources */,
Expand Down
5 changes: 0 additions & 5 deletions sources/NSImage+iTerm.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@
// graphics context in the block. Returns the resulting image.
+ (instancetype)imageOfSize:(NSSize)size drawBlock:(void (^)(void))block;

// Creates a bitmap image context and runs the block. Do drawing into the
// context (or current NSGraphicsContext) in the block. Returns the argb raw
// data.
+ (NSMutableData *)argbDataForImageOfSize:(NSSize)size drawBlock:(void (^)(CGContextRef context))block;

+ (instancetype)imageWithRawData:(NSData *)data
size:(NSSize)size
bitsPerSample:(NSInteger)bitsPerSample // e.g. 8 or 1
Expand Down
82 changes: 35 additions & 47 deletions sources/NSImage+iTerm.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ + (NSImage *)imageOfSize:(NSSize)size color:(NSColor *)color {
}

+ (instancetype)imageOfSize:(NSSize)size drawBlock:(void (^)(void))block {
NSImage *image = [[[NSImage alloc] initWithSize:size] autorelease];
NSImage *image = [[NSImage alloc] initWithSize:size];
[image it_drawWithBlock:block];
return image;
}
Expand All @@ -58,18 +58,6 @@ - (void)it_drawWithBlock:(void (^)(void))block {
[self unlockFocus];
}

+ (NSMutableData *)argbDataForImageOfSize:(NSSize)size drawBlock:(void (^)(CGContextRef context))block {
NSMutableData *data = [NSMutableData data];
CGContextRef context = [NSImage newBitmapContextOfSize:size storage:data];
NSGraphicsContext *graphicsContext = [NSGraphicsContext graphicsContextWithCGContext:context flipped:NO];
NSGraphicsContext *savedContext = [NSGraphicsContext currentContext];
[NSGraphicsContext setCurrentContext:graphicsContext];
block(context);
[NSGraphicsContext setCurrentContext:savedContext];
CGContextRelease(context);
return data;
}

+ (NSData *)dataWithFourBytesPerPixelFromDataWithOneBytePerPixel:(NSData *)input {
NSMutableData *output = [NSMutableData dataWithLength:input.length * 4];
unsigned char *ob = (unsigned char *)output.mutableBytes;
Expand Down Expand Up @@ -101,20 +89,20 @@ + (instancetype)imageWithRawData:(NSData *)data

assert(data.length == size.width * size.height * bitsPerSample * samplesPerPixel / 8);
NSBitmapImageRep *bitmapImageRep =
[[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil // allocate the pixel buffer for us
pixelsWide:size.width
pixelsHigh:size.height
bitsPerSample:bitsPerSample
samplesPerPixel:samplesPerPixel
hasAlpha:hasAlpha
isPlanar:NO
colorSpaceName:colorSpaceName
bytesPerRow:bitsPerSample * samplesPerPixel * size.width / 8
bitsPerPixel:bitsPerSample * samplesPerPixel] autorelease]; // 0 means OS infers it
[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil // allocate the pixel buffer for us
pixelsWide:size.width
pixelsHigh:size.height
bitsPerSample:bitsPerSample
samplesPerPixel:samplesPerPixel
hasAlpha:hasAlpha
isPlanar:NO
colorSpaceName:colorSpaceName
bytesPerRow:bitsPerSample * samplesPerPixel * size.width / 8
bitsPerPixel:bitsPerSample * samplesPerPixel]; // 0 means OS infers it

memmove([bitmapImageRep bitmapData], data.bytes, data.length);

NSImage *theImage = [[[NSImage alloc] initWithSize:size] autorelease];
NSImage *theImage = [[NSImage alloc] initWithSize:size];
[theImage addRepresentation:bitmapImageRep];

return theImage;
Expand Down Expand Up @@ -202,33 +190,33 @@ - (CGContextRef)newBitmapContextWithStorage:(NSMutableData *)data {
}

- (NSImage *)imageWithColor:(NSColor *)color {
NSSize size = self.size;
NSRect rect = NSZeroRect;
rect.size = size;
NSSize size = self.size;
NSRect rect = NSZeroRect;
rect.size = size;

// Create a bitmap context.
NSMutableData *data = [NSMutableData data];
CGContextRef context = [self newBitmapContextWithStorage:data];
// Create a bitmap context.
NSMutableData *data = [NSMutableData data];
CGContextRef context = [self newBitmapContextWithStorage:data];

// Draw myself into that context.
CGContextDrawImage(context, rect, [self CGImageForProposedRect:NULL context:nil hints:nil]);
// Draw myself into that context.
CGContextDrawImage(context, rect, [self CGImageForProposedRect:NULL context:nil hints:nil]);

// Now draw over it with |color|.
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextSetBlendMode(context, kCGBlendModeSourceAtop);
CGContextFillRect(context, rect);
// Now draw over it with |color|.
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextSetBlendMode(context, kCGBlendModeSourceAtop);
CGContextFillRect(context, rect);

// Extract the resulting image into the graphics context.
CGImageRef image = CGBitmapContextCreateImage(context);
// Extract the resulting image into the graphics context.
CGImageRef image = CGBitmapContextCreateImage(context);

// Convert to NSImage
NSImage *coloredImage = [[[NSImage alloc] initWithCGImage:image size:size] autorelease];
// Convert to NSImage
NSImage *coloredImage = [[NSImage alloc] initWithCGImage:image size:size];

// Release memory.
CGContextRelease(context);
CGImageRelease(image);
// Release memory.
CGContextRelease(context);
CGImageRelease(image);

return coloredImage;
return coloredImage;
}

- (void)saveAsPNGTo:(NSString *)filename {
Expand All @@ -240,7 +228,7 @@ - (NSData *)dataForFileOfType:(NSBitmapImageFileType)fileType {
CGImageRef cgImage = [self CGImageForProposedRect:NULL
context:nil
hints:nil];
NSBitmapImageRep *imageRep = [[[NSBitmapImageRep alloc] initWithCGImage:cgImage] autorelease];
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
[imageRep setSize:self.size];
return [imageRep representationUsingType:fileType properties:@{}];
}
Expand Down Expand Up @@ -283,7 +271,7 @@ - (NSBitmapImageRep *)bitmapImageRep {
[ctx flushGraphics];
[NSGraphicsContext restoreGraphicsState];

return [rep autorelease];
return rep;
}

- (NSImageRep *)bestRepresentationForScale:(CGFloat)desiredScale {
Expand Down Expand Up @@ -333,7 +321,7 @@ - (NSImage *)it_flippedImage {
NSPoint corner = NSMakePoint(-size.width / 2., -size.height / 2.);
[self drawAtPoint:corner fromRect:rect operation:NSCompositingOperationCopy fraction:1.0];
[image unlockFocus];
return [image autorelease];
return image;
}

- (NSImage *)it_imageOfSize:(NSSize)newSize {
Expand Down

0 comments on commit 09a74a2

Please sign in to comment.