From 09a74a22fc7a906392220e6677f9aa37db681f7e Mon Sep 17 00:00:00 2001 From: George Nachman Date: Sat, 24 Aug 2019 17:59:05 -0700 Subject: [PATCH] ARCify NSImage+iTerm to fix a memory leak in it_imageWithTintColor: where the image is copied but not autoreleased. Issue 8163 --- iTerm2.xcodeproj/project.pbxproj | 4 +- sources/NSImage+iTerm.h | 5 -- sources/NSImage+iTerm.m | 82 ++++++++++++++------------------ 3 files changed, 37 insertions(+), 54 deletions(-) diff --git a/iTerm2.xcodeproj/project.pbxproj b/iTerm2.xcodeproj/project.pbxproj index 4d2aebace7..ddbbc195a3 100644 --- a/iTerm2.xcodeproj/project.pbxproj +++ b/iTerm2.xcodeproj/project.pbxproj @@ -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 */; }; @@ -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 */; }; @@ -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 */, @@ -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 */, diff --git a/sources/NSImage+iTerm.h b/sources/NSImage+iTerm.h index 9396383e6a..369d9f932f 100644 --- a/sources/NSImage+iTerm.h +++ b/sources/NSImage+iTerm.h @@ -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 diff --git a/sources/NSImage+iTerm.m b/sources/NSImage+iTerm.m index 55538e248f..81e9dde30e 100644 --- a/sources/NSImage+iTerm.m +++ b/sources/NSImage+iTerm.m @@ -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; } @@ -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; @@ -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; @@ -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 { @@ -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:@{}]; } @@ -283,7 +271,7 @@ - (NSBitmapImageRep *)bitmapImageRep { [ctx flushGraphics]; [NSGraphicsContext restoreGraphicsState]; - return [rep autorelease]; + return rep; } - (NSImageRep *)bestRepresentationForScale:(CGFloat)desiredScale { @@ -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 {