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>
27 CGColorRef kBlackColor, kWhiteColor,
28 kTranslucentGrayColor, kTranslucentLightGrayColor,
29 kAlmostInvisibleWhiteColor,
33 __attribute__((constructor)) // Makes this function run when the app loads
34 static void InitQuartzUtils()
36 kBlackColor = CreateGray(0.0, 1.0);
37 kWhiteColor = CreateGray(1.0, 1.0);
38 kTranslucentGrayColor = CreateGray(0.0, 0.5);
39 kTranslucentLightGrayColor = CreateGray(0.0, 0.25);
40 kAlmostInvisibleWhiteColor = CreateGray(1, 0.05);
41 kHighlightColor = CreateRGB(1, 1, 0, 0.5);
46 CGColorRef CreateGray(CGFloat gray, CGFloat alpha)
48 CGColorSpaceRef graySpace = CGColorSpaceCreateDeviceGray();
49 CGFloat components[2] = {gray,alpha};
50 CGColorRef color = CGColorCreate(graySpace, components);
51 CGColorSpaceRelease(graySpace);
55 CGColorRef CreateRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha)
57 CGColorSpaceRef rgbSpace = CGColorSpaceCreateDeviceRGB();
58 CGFloat components[4] = {red,green,blue,alpha};
59 CGColorRef color = CGColorCreate(rgbSpace, components);
60 CGColorSpaceRelease(rgbSpace);
66 void ChangeSuperlayer( CALayer *layer, CALayer *newSuperlayer, int index )
68 // Disable actions, else the layer will move to the wrong place and then back!
69 [CATransaction flush];
70 [CATransaction begin];
71 [CATransaction setValue:(id)kCFBooleanTrue
72 forKey:kCATransactionDisableActions];
74 CGPoint pos = [newSuperlayer convertPoint: layer.position
75 fromLayer: layer.superlayer];
77 [layer removeFromSuperlayer];
79 [newSuperlayer insertSublayer: layer atIndex: index];
81 [newSuperlayer addSublayer: layer];
85 [CATransaction commit];
89 void RemoveImmediately( CALayer *layer )
91 [CATransaction flush];
92 [CATransaction begin];
93 [CATransaction setValue:(id)kCFBooleanTrue
94 forKey:kCATransactionDisableActions];
95 [layer removeFromSuperlayer];
96 [CATransaction commit];
100 CGImageRef CreateCGImageFromFile( NSString *path )
103 UIImage *uiImage = [UIImage imageWithContentsOfFile: path];
104 if(!uiImage) NSLog(@"Warning: UIImage imageWithContentsOfFile failed on file %@",path);
105 return CGImageRetain(uiImage.CGImage);
107 CGImageRef image = NULL;
108 CFURLRef url = (CFURLRef) [NSURL fileURLWithPath: path];
109 CGImageSourceRef src = CGImageSourceCreateWithURL(url, NULL);
111 image = CGImageSourceCreateImageAtIndex(src, 0, NULL);
113 if(!image) NSLog(@"Warning: CGImageSourceCreateImageAtIndex failed on file %@ (ptr size=%u)",path,sizeof(void*));
120 CGImageRef GetCGImageNamed( NSString *name )
123 name = name.lastPathComponent;
124 UIImage *uiImage = [UIImage imageNamed: name];
125 NSCAssert1(uiImage,@"Couldn't find bundle image resource '%@'",name);
126 return uiImage.CGImage;
128 // For efficiency, loaded images are cached in a dictionary by name.
129 static NSMutableDictionary *sMap;
131 sMap = [[NSMutableDictionary alloc] init];
133 CGImageRef image = (CGImageRef) [sMap objectForKey: name];
135 // Hasn't been cached yet, so load it:
137 if( [name hasPrefix: @"/"] )
140 path = [[NSBundle mainBundle] pathForResource: name ofType: nil];
141 NSCAssert1(path,@"Couldn't find bundle image resource '%@'",name);
143 image = CreateCGImageFromFile(path);
144 NSCAssert1(image,@"Failed to load image from %@",path);
145 [sMap setObject: (id)image forKey: name];
146 CGImageRelease(image);
153 CGColorRef GetCGPatternNamed( NSString *name ) // can be resource name or abs. path
155 // For efficiency, loaded patterns are cached in a dictionary by name.
156 static NSMutableDictionary *sMap;
158 sMap = [[NSMutableDictionary alloc] init];
160 CGColorRef pattern = (CGColorRef) [sMap objectForKey: name];
162 pattern = CreatePatternColor( GetCGImageNamed(name) );
163 [sMap setObject: (id)pattern forKey: name];
164 CGColorRelease(pattern);
170 #if ! TARGET_OS_ASPEN
171 CGImageRef GetCGImageFromPasteboard( NSPasteboard *pb )
173 CGImageSourceRef src = NULL;
174 NSArray *paths = [pb propertyListForType: NSFilenamesPboardType];
175 if( paths.count==1 ) {
176 // If a file is being dragged, read it:
177 CFURLRef url = (CFURLRef) [NSURL fileURLWithPath: [paths objectAtIndex: 0]];
178 src = CGImageSourceCreateWithURL(url, NULL);
180 // Else look for an image type:
181 NSString *type = [pb availableTypeFromArray: [NSImage imageUnfilteredPasteboardTypes]];
183 NSData *data = [pb dataForType: type];
184 src = CGImageSourceCreateWithData((CFDataRef)data, NULL);
188 CGImageRef image = CGImageSourceCreateImageAtIndex(src, 0, NULL);
197 float GetPixelAlpha( CGImageRef image, CGSize imageSize, CGPoint pt )
200 // iPhone uses "flipped" (i.e. normal) coords, so images are wrong-way-up
201 pt.y = imageSize.height - pt.y;
205 if( pt.x<0 || pt.x>=imageSize.width || pt.y<0 || pt.y>=imageSize.height )
208 // sTinyContext is a 1x1 CGBitmapContext whose pixmap stores only alpha.
209 static UInt8 sPixel[1];
210 static CGContextRef sTinyContext;
211 if( ! sTinyContext ) {
212 sTinyContext = CGBitmapContextCreate(sPixel, 1, 1,
213 8, 1, // bpp, rowBytes
216 CGContextSetBlendMode(sTinyContext, kCGBlendModeCopy);
219 // Draw the image into sTinyContext, positioned so the desired point is at
220 // (0,0), then examine the alpha value in the pixmap:
221 CGContextDrawImage(sTinyContext,
222 CGRectMake(-pt.x,-pt.y, imageSize.width,imageSize.height),
224 return sPixel[0] / 255.0;
229 #pragma mark PATTERNS:
232 // callback for CreateImagePattern.
233 static void drawPatternImage (void *info, CGContextRef ctx)
235 CGImageRef image = (CGImageRef) info;
236 CGContextDrawImage(ctx,
237 CGRectMake(0,0, CGImageGetWidth(image),CGImageGetHeight(image)),
241 // callback for CreateImagePattern.
242 static void releasePatternImage( void *info )
244 CGImageRelease( (CGImageRef)info );
248 CGPatternRef CreateImagePattern( CGImageRef image )
250 NSCParameterAssert(image);
251 int width = CGImageGetWidth(image);
252 int height = CGImageGetHeight(image);
253 static const CGPatternCallbacks callbacks = {0, &drawPatternImage, &releasePatternImage};
254 return CGPatternCreate (image,
255 CGRectMake (0, 0, width, height),
256 CGAffineTransformMake (1, 0, 0, 1, 0, 0),
259 kCGPatternTilingConstantSpacing,
265 CGColorRef CreatePatternColor( CGImageRef image )
267 CGPatternRef pattern = CreateImagePattern(image);
268 CGColorSpaceRef space = CGColorSpaceCreatePattern(NULL);
269 CGFloat components[1] = {1.0};
270 CGColorRef color = CGColorCreateWithPattern(space, pattern, components);
271 CGColorSpaceRelease(space);
272 CGPatternRelease(pattern);
281 void AddRoundRect( CGContextRef ctx, CGRect rect, CGFloat radius )
283 radius = MIN(radius, floorf(rect.size.width/2));
284 float x0 = CGRectGetMinX(rect), y0 = CGRectGetMinY(rect),
285 x1 = CGRectGetMaxX(rect), y1 = CGRectGetMaxY(rect);
287 CGContextBeginPath(ctx);
288 CGContextMoveToPoint(ctx,x0+radius,y0);
289 CGContextAddArcToPoint(ctx,x1,y0, x1,y1, radius);
290 CGContextAddArcToPoint(ctx,x1,y1, x0,y1, radius);
291 CGContextAddArcToPoint(ctx,x0,y1, x0,y0, radius);
292 CGContextAddArcToPoint(ctx,x0,y0, x1,y0, radius);
293 CGContextClosePath(ctx);