Bug Summary

File:Source/AIMenuBarIcons.m
Location:line 162, column 2
Description:Memory Leak
Code is compiled without garbage collection.

Annotated Source Code

1/*
2 * Adium is the legal property of its developers, whose names are listed in the copyright file included
3 * with this source distribution.
4 *
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11 * Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 */
16
17#import "AIMenuBarIcons.h"
18#import <AIXtraInfo.h>
19#import <AIUtilities/AIImageAdditions.h>
20#import <QuartzCore/CoreImage.h>
21
22#define KEY_ICONS_DICT @"Icons"
23
24@interface AIMenuBarIcons (PRIVATE)
25- (NSImage *)imageForKey:(NSString *)keyName;
26- (BOOL)keyOfTypeExists:(NSString *)keyName;
27@end
28
29@implementation AIMenuBarIcons
30
31- (id)initWithURL:(NSURL *)url
32{
33 if ((self = [super initWithURL:url])) {
34 imageStates = [[NSMutableDictionary alloc] init];
35 alternateImageStates = [[NSMutableDictionary alloc] init];
36 iconInfo = [xtraBundle objectForInfoDictionaryKey:KEY_ICONS_DICT@ "Icons"];
37 }
38 return self;
39}
40
41- (NSImage *)imageOfType:(NSString *)imageType alternate:(BOOL)alternate
42{
43 NSImage *image;
44
45 // Default to Online if key not found.
46 if (![self keyOfTypeExists:imageType]) {
47 imageType = @"Online";
48 }
49
50 image = [(alternate ? alternateImageStates : imageStates) objectForKey:imageType];
51 if (!image) { // Image not already stored.
52 if (alternate) {
53 NSImage *normalImage = [self imageOfType:imageType alternate:NO( BOOL ) 0];
54 image = [self alternateImageForImage:normalImage];
55 [alternateImageStates setObject:image forKey:imageType];
56 } else {
57 image = [self imageForKey:imageType];
58 if (image) { // Make sure the image exists.
59 [imageStates setObject:image forKey:imageType];
60 }
61 }
62 }
63
64 [image setFlipped:YES( BOOL ) 1];
65
66 return image;
67}
68
69- (NSImage *)imageForKey:(NSString *)keyName
70{
71 NSString *imagePath;
72
73 // This set doesn't contain an Icons dictionary entry. It's invalid.
74 if (!iconInfo) {
75 return nil0;
76 }
77
78 imagePath = [xtraBundle pathForImageResource:[iconInfo objectForKey:keyName]];
79 return [[[NSImage alloc] initWithContentsOfFile:imagePath] autorelease];
80}
81
82- (BOOL)keyOfTypeExists:(NSString *)keyName
83{
84 if (!iconInfo || ![iconInfo objectForKey:keyName]) {
85 return NO( BOOL ) 0;
86 }
87 return YES( BOOL ) 1;
88}
89
90- (void)dealloc
91{
92 [imageStates release];
93 [alternateImageStates release];
94 [super dealloc];
95}
96
97#define PREVIEW_MENU_IMAGE_SIZE 18
98#define PREVIEW_MENU_IMAGE_MARGIN 2
99
100+ (NSImage *)previewMenuImageForIconPackAtPath:(NSString *)inPath
101{
102 NSImage *image;
[1] Method returns an object with a +1 retain count (owning reference).
103 NSBundle *menuIconsBundle = [[NSBundle alloc] initWithPath:inPath];
104 NSDictionary *imageInfo;
105
[2] Taking false branch.
106 if (!menuIconsBundle) {
107 return nil0;
108 }
109
110 imageInfo = [menuIconsBundle objectForInfoDictionaryKey:KEY_ICONS_DICT@ "Icons"];
111
[3] Taking false branch.
112 if (!imageInfo) {
113 [menuIconsBundle release];
114 return nil0;
115 }
116
117 image = [[NSImage alloc] initWithSize:NSMakeSize((PREVIEW_MENU_IMAGE_SIZE18 + PREVIEW_MENU_IMAGE_MARGIN2) * 2,
118 PREVIEW_MENU_IMAGE_SIZE18)];
119
120
[4] Taking false branch.
121 if ([[menuIconsBundle objectForInfoDictionaryKey:@"XtraBundleVersion"] intValue] == 1) {
122 NSEnumerator *enumerator = [[NSArray arrayWithObjects:@"Online",@"Offline",nil0] objectEnumerator];
123 NSString *iconID;
124 int xOrigin = 0;
125
126 [image lockFocus];
127 while ((iconID = [enumerator nextObject])) {
128 NSString *anIconPath = [menuIconsBundle pathForImageResource:[imageInfo objectForKey:iconID]];
129 NSImage *anIcon;
130
131 if ((anIcon = [[[NSImage alloc] initWithContentsOfFile:anIconPath] autorelease])) {
132 NSSize anIconSize = [anIcon size];
133 NSRect targetRect = NSMakeRect(xOrigin, 0, PREVIEW_MENU_IMAGE_SIZE18, PREVIEW_MENU_IMAGE_SIZE18);
134
135 if (anIconSize.width < targetRect.size.width) {
136 float difference = (targetRect.size.width - anIconSize.width)/2;
137
138 targetRect.size.width -= difference;
139 targetRect.origin.x += difference;
140 }
141
142 if (anIconSize.height < targetRect.size.height) {
143 float difference = (targetRect.size.height - anIconSize.height)/2;
144
145 targetRect.size.height -= difference;
146 targetRect.origin.y += difference;
147 }
148
149 [anIcon drawInRect:targetRect
150 fromRect:NSMakeRect(0,0,anIconSize.width,anIconSize.height)
151 operation:NSCompositeCopy
152 fraction:1.0];
153
154 //Shift right in preparation for next image
155 xOrigin += PREVIEW_MENU_IMAGE_SIZE18 + PREVIEW_MENU_IMAGE_MARGIN2;
156 }
157 }
158 [image unlockFocus];
159 [menuIconsBundle release];
160 }
161
[5] Object allocated on line 103 and stored into 'menuIconsBundle' is no longer referenced after this point and has a retain count of +1 (object leaked).
162 return [image autorelease];
163}
164
165// Returns an inverted image.
166- (NSImage *)alternateImageForImage:(NSImage *)inImage
167{
168 NSImage *altImage = [[NSImage alloc] initWithSize:[inImage size]];
169 NSBitmapImageRep *srcImageRep = [inImage largestBitmapImageRep];
170
171 [altImage setFlipped:[inImage isFlipped]];
172
173 id monochromeFilter, invertFilter, alphaFilter;
174
175 monochromeFilter = [CIFilter filterWithName:@"CIColorMonochrome"];
176 [monochromeFilter setValue:[[[CIImage alloc] initWithBitmapImageRep:srcImageRep] autorelease]
177 forKey:@"inputImage"];
178 [monochromeFilter setValue:[NSNumber numberWithFloat:1.0]
179 forKey:@"inputIntensity"];
180 [monochromeFilter setValue:[[[CIColor alloc] initWithColor:[NSColor blackColor]] autorelease]
181 forKey:@"inputColor"];
182
183 //Now invert our greyscale image
184 invertFilter = [CIFilter filterWithName:@"CIColorInvert"];
185 [invertFilter setValue:[monochromeFilter valueForKey:@"outputImage"]
186 forKey:@"inputImage"];
187
188 //And turn the parts that were previously white (are now black) into transparent
189 alphaFilter = [CIFilter filterWithName:@"CIMaskToAlpha"];
190 [alphaFilter setValue:[invertFilter valueForKey:@"outputImage"]
191 forKey:@"inputImage"];
192
193 [altImage addRepresentation:[NSCIImageRep imageRepWithCIImage:[alphaFilter valueForKey:@"outputImage"]]];
194
195 return [altImage autorelease];
196}
197
198@end