Fixed some problems reported by the CLANG static analyzer.
1 /* This code is based on Apple's "GeekGameBoard" sample code, version 1.0.
2 http://developer.apple.com/samplecode/GeekGameBoard/
3 Copyright © 2007 Apple Inc. Copyright © 2008 Jens Alfke. All Rights Reserved.
5 Redistribution and use in source and binary forms, with or without modification, are permitted
6 provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright notice, this list of conditions
9 and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice, this list of
11 conditions and the following disclaimer in the documentation and/or other materials provided
12 with the distribution.
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
15 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRI-
17 BUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
19 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
21 THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 #import "QuartzUtils.h"
24 #import <QuartzCore/QuartzCore.h>
29 CGColorRef kBlackColor, kWhiteColor,
30 kTranslucentGrayColor, kTranslucentLightGrayColor,
31 kTranslucentWhiteColor, kAlmostInvisibleWhiteColor,
35 __attribute__((constructor)) // Makes this function run when the app loads
36 static void InitQuartzUtils()
38 kBlackColor = CreateGray(0.0, 1.0);
39 kWhiteColor = CreateGray(1.0, 1.0);
40 kTranslucentGrayColor = CreateGray(0.0, 0.5);
41 kTranslucentLightGrayColor = CreateGray(0.0, 0.25);
42 kTranslucentWhiteColor = CreateGray(1, 0.25);
43 kAlmostInvisibleWhiteColor = CreateGray(1, 0.05);
44 kHighlightColor = CreateRGB(1, 1, 0, 0.5);
49 CGColorRef CreateGray(CGFloat gray, CGFloat alpha)
51 CGColorSpaceRef graySpace = CGColorSpaceCreateDeviceGray();
52 CGFloat components[2] = {gray,alpha};
53 CGColorRef color = CGColorCreate(graySpace, components);
54 CGColorSpaceRelease(graySpace);
58 CGColorRef CreateRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha)
60 CGColorSpaceRef rgbSpace = CGColorSpaceCreateDeviceRGB();
61 CGFloat components[4] = {red,green,blue,alpha};
62 CGColorRef color = CGColorCreate(rgbSpace, components);
63 CGColorSpaceRelease(rgbSpace);
69 CGImageRef CreateCGImageFromFile( NSString *path )
72 UIImage *uiImage = [UIImage imageWithContentsOfFile: path];
73 if(!uiImage) Warn(@"UIImage imageWithContentsOfFile failed on file %@",path);
74 return CGImageRetain(uiImage.CGImage);
76 CGImageRef image = NULL;
77 CFURLRef url = (CFURLRef) [NSURL fileURLWithPath: path];
78 CGImageSourceRef src = CGImageSourceCreateWithURL(url, NULL);
80 image = CGImageSourceCreateImageAtIndex(src, 0, NULL);
82 if(!image) Warn(@"CGImageSourceCreateImageAtIndex failed on file %@ (ptr size=%u)",path,sizeof(void*));
89 CGImageRef GetCGImageNamed( NSString *name )
92 name = name.lastPathComponent;
93 UIImage *uiImage = [UIImage imageNamed: name];
94 NSCAssert1(uiImage,@"Couldn't find bundle image resource '%@'",name);
95 return uiImage.CGImage;
97 // For efficiency, loaded images are cached in a dictionary by name.
98 static NSMutableDictionary *sMap;
100 sMap = [[NSMutableDictionary alloc] init];
102 CGImageRef image = (CGImageRef) [sMap objectForKey: name];
104 // Hasn't been cached yet, so load it:
106 if( [name hasPrefix: @"/"] )
109 NSString *dir = [name stringByDeletingLastPathComponent];
110 name = [name lastPathComponent];
111 NSString *ext = name.pathExtension;
112 name = [name stringByDeletingPathExtension];
113 path = [[NSBundle mainBundle] pathForResource: name ofType: ext inDirectory: dir];
114 NSCAssert3(path,@"Couldn't find bundle image resource '%@' type '%@' in '%@'",name,ext,dir);
116 image = CreateCGImageFromFile(path);
117 NSCAssert1(image,@"Failed to load image from %@",path);
118 [sMap setObject: (id)image forKey: name];
119 CGImageRelease(image);
126 CGColorRef GetCGPatternNamed( NSString *name ) // can be resource name or abs. path
128 // For efficiency, loaded patterns are cached in a dictionary by name.
129 static NSMutableDictionary *sMap;
131 sMap = [[NSMutableDictionary alloc] init];
133 CGColorRef pattern = (CGColorRef) [sMap objectForKey: name];
135 pattern = CreatePatternColor( GetCGImageNamed(name) );
136 [sMap setObject: (id)pattern forKey: name];
137 CGColorRelease(pattern);
143 #if ! TARGET_OS_IPHONE
145 BOOL CanGetCGImageFromPasteboard( NSPasteboard *pb )
147 return [NSImage canInitWithPasteboard: pb]
148 || [[pb types] containsObject: @"PixadexIconPathPboardType"];
150 /*if( [[pb types] containsObject: NSFilesPromisePboardType] ) {
151 NSArray *fileTypes = [pb propertyListForType: NSFilesPromisePboardType];
152 NSLog(@"Got file promise! Types = %@",fileTypes);
153 //FIX: Check file types
154 return NSDragOperationCopy;
158 CGImageRef GetCGImageFromPasteboard( NSPasteboard *pb, id<NSDraggingInfo>dragInfo )
160 CGImageSourceRef src = NULL;
161 NSArray *paths = [pb propertyListForType: NSFilenamesPboardType];
162 if( paths.count==1 ) {
163 // If a file is being dragged, read it:
164 CFURLRef url = (CFURLRef) [NSURL fileURLWithPath: [paths objectAtIndex: 0]];
165 src = CGImageSourceCreateWithURL(url, NULL);
167 } else if( dragInfo && [[pb types] containsObject:NSFilesPromisePboardType] ) {
168 NSString *dropDir = NSTemporaryDirectory();
169 NSArray *filenames = [dragInfo namesOfPromisedFilesDroppedAtDestination: [NSURL fileURLWithPath: dropDir]];
170 NSLog(@"promised files are %@ / %@", dropDir,filenames);
172 } else if( [[pb types] containsObject: @"PixadexIconPathPboardType"] ) {
173 // Candybar 3 (nee Pixadex) doesn't drag out icons in any normal image type.
174 // It does support file-promises, but I couldn't get those to work using the Cocoa APIs.
175 // So instead I'm using its custom type that provides the path(s) to its internal ".pxicon" files.
176 // The icon is really easy to get from one of these: it's just file's custom icon.
177 NSArray *files = [pb propertyListForType: @"PixadexIconPathPboardType"];
178 if( files.count == 1 ) {
179 NSString *path = [files objectAtIndex: 0];
180 NSImage *icon = [[NSWorkspace sharedWorkspace] iconForFile: path];
181 for( NSImageRep *rep in icon.representations ) {
182 if( [rep isKindOfClass: [NSBitmapImageRep class]] ) {
183 [rep retain]; //FIX: This leaks; but if the rep goes away, the CGImage breaks...
184 return [(NSBitmapImageRep*)rep CGImage];
189 // Else look for an image type:
190 NSString *type = [pb availableTypeFromArray: [NSImage imageUnfilteredPasteboardTypes]];
192 NSData *data = [pb dataForType: type];
193 src = CGImageSourceCreateWithData((CFDataRef)data, NULL);
197 CGImageRef image = CGImageSourceCreateImageAtIndex(src, 0, NULL);
206 CGImageRef CreateScaledImage( CGImageRef srcImage, CGFloat scale )
208 int width = CGImageGetWidth(srcImage), height = CGImageGetHeight(srcImage);
211 scale /= MAX(width,height); // interpret scale as target dimensions
212 width = ceil( width * scale);
213 height= ceil( height* scale);
216 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
217 CGContextRef ctx = CGBitmapContextCreate(NULL, width, height, 8, 4*width, space,
218 kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast);
219 CGColorSpaceRelease(space);
220 CGContextSetInterpolationQuality(ctx,kCGInterpolationHigh);
221 CGContextDrawImage(ctx, CGRectMake(0, 0, width, height), srcImage);
222 CGImageRef dstImage = CGBitmapContextCreateImage(ctx);
223 CGContextRelease(ctx);
228 CGImageRef GetScaledImageNamed( NSString *imageName, CGFloat scale )
230 // For efficiency, loaded images are cached in a dictionary by name.
231 static NSMutableDictionary *sMap;
233 sMap = [[NSMutableDictionary alloc] init];
235 NSArray *key = [NSArray arrayWithObjects: imageName, [NSNumber numberWithFloat: scale], nil];
236 CGImageRef image = (CGImageRef) [sMap objectForKey: key];
238 // Hasn't been cached yet, so load it:
239 image = CreateScaledImage(GetCGImageNamed(imageName), scale);
240 [sMap setObject: (id)image forKey: key];
241 CGImageRelease(image);
247 float GetPixelAlpha( CGImageRef image, CGSize imageSize, CGPoint pt )
249 NSCParameterAssert(image);
251 // iPhone uses "flipped" (i.e. normal) coords, so images are wrong-way-up
252 pt.y = imageSize.height - pt.y;
256 if( pt.x<0 || pt.x>=imageSize.width || pt.y<0 || pt.y>=imageSize.height )
259 // sTinyContext is a 1x1 CGBitmapContext whose pixmap stores only alpha.
260 static UInt8 sPixel[1];
261 static CGContextRef sTinyContext;
262 if( ! sTinyContext ) {
263 sTinyContext = CGBitmapContextCreate(sPixel, 1, 1,
264 8, 1, // bpp, rowBytes
267 CGContextSetBlendMode(sTinyContext, kCGBlendModeCopy);
270 // Draw the image into sTinyContext, positioned so the desired point is at
271 // (0,0), then examine the alpha value in the pixmap:
272 CGContextDrawImage(sTinyContext,
273 CGRectMake(-pt.x,-pt.y, imageSize.width,imageSize.height),
275 return sPixel[0] / 255.0;
280 #pragma mark PATTERNS:
283 // callback for CreateImagePattern.
284 static void drawPatternImage (void *info, CGContextRef ctx)
286 CGImageRef image = (CGImageRef) info;
287 CGContextDrawImage(ctx,
288 CGRectMake(0,0, CGImageGetWidth(image),CGImageGetHeight(image)),
292 // callback for CreateImagePattern.
293 static void releasePatternImage( void *info )
295 CGImageRelease( (CGImageRef)info );
299 CGPatternRef CreateImagePattern( CGImageRef image )
301 NSCParameterAssert(image);
302 int width = CGImageGetWidth(image);
303 int height = CGImageGetHeight(image);
304 static const CGPatternCallbacks callbacks = {0, &drawPatternImage, &releasePatternImage};
305 return CGPatternCreate (image,
306 CGRectMake (0, 0, width, height),
307 CGAffineTransformMake (1, 0, 0, 1, 0, 0),
310 kCGPatternTilingConstantSpacing,
316 CGColorRef CreatePatternColor( CGImageRef image )
318 CGPatternRef pattern = CreateImagePattern(image);
319 CGColorSpaceRef space = CGColorSpaceCreatePattern(NULL);
320 CGFloat components[1] = {1.0};
321 CGColorRef color = CGColorCreateWithPattern(space, pattern, components);
322 CGColorSpaceRelease(space);
323 CGPatternRelease(pattern);
332 void AddRoundRect( CGContextRef ctx, CGRect rect, CGFloat radius )
334 radius = MIN(radius, floorf(rect.size.width/2));
335 float x0 = CGRectGetMinX(rect), y0 = CGRectGetMinY(rect),
336 x1 = CGRectGetMaxX(rect), y1 = CGRectGetMaxY(rect);
338 CGContextBeginPath(ctx);
339 CGContextMoveToPoint(ctx,x0+radius,y0);
340 CGContextAddArcToPoint(ctx,x1,y0, x1,y1, radius);
341 CGContextAddArcToPoint(ctx,x1,y1, x0,y1, radius);
342 CGContextAddArcToPoint(ctx,x0,y1, x0,y0, radius);
343 CGContextAddArcToPoint(ctx,x0,y0, x1,y0, radius);
344 CGContextClosePath(ctx);