Added support for clicking the board to place new pieces. Go and Tic-Tac-Toe now use this.
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 = layer.position;
75 if( layer.superlayer )
76 pos = [newSuperlayer convertPoint: pos fromLayer: layer.superlayer];
78 [layer removeFromSuperlayer];
80 [newSuperlayer insertSublayer: layer atIndex: index];
82 [newSuperlayer addSublayer: layer];
86 [CATransaction commit];
90 void RemoveImmediately( CALayer *layer )
92 [CATransaction flush];
93 [CATransaction begin];
94 [CATransaction setValue:(id)kCFBooleanTrue
95 forKey:kCATransactionDisableActions];
96 [layer removeFromSuperlayer];
97 [CATransaction commit];
101 CGImageRef CreateCGImageFromFile( NSString *path )
104 UIImage *uiImage = [UIImage imageWithContentsOfFile: path];
105 if(!uiImage) NSLog(@"Warning: UIImage imageWithContentsOfFile failed on file %@",path);
106 return CGImageRetain(uiImage.CGImage);
108 CGImageRef image = NULL;
109 CFURLRef url = (CFURLRef) [NSURL fileURLWithPath: path];
110 CGImageSourceRef src = CGImageSourceCreateWithURL(url, NULL);
112 image = CGImageSourceCreateImageAtIndex(src, 0, NULL);
114 if(!image) NSLog(@"Warning: CGImageSourceCreateImageAtIndex failed on file %@ (ptr size=%u)",path,sizeof(void*));
121 CGImageRef GetCGImageNamed( NSString *name )
124 name = name.lastPathComponent;
125 UIImage *uiImage = [UIImage imageNamed: name];
126 NSCAssert1(uiImage,@"Couldn't find bundle image resource '%@'",name);
127 return uiImage.CGImage;
129 // For efficiency, loaded images are cached in a dictionary by name.
130 static NSMutableDictionary *sMap;
132 sMap = [[NSMutableDictionary alloc] init];
134 CGImageRef image = (CGImageRef) [sMap objectForKey: name];
136 // Hasn't been cached yet, so load it:
138 if( [name hasPrefix: @"/"] )
141 path = [[NSBundle mainBundle] pathForResource: name ofType: nil];
142 NSCAssert1(path,@"Couldn't find bundle image resource '%@'",name);
144 image = CreateCGImageFromFile(path);
145 NSCAssert1(image,@"Failed to load image from %@",path);
146 [sMap setObject: (id)image forKey: name];
147 CGImageRelease(image);
154 CGColorRef GetCGPatternNamed( NSString *name ) // can be resource name or abs. path
156 // For efficiency, loaded patterns are cached in a dictionary by name.
157 static NSMutableDictionary *sMap;
159 sMap = [[NSMutableDictionary alloc] init];
161 CGColorRef pattern = (CGColorRef) [sMap objectForKey: name];
163 pattern = CreatePatternColor( GetCGImageNamed(name) );
164 [sMap setObject: (id)pattern forKey: name];
165 CGColorRelease(pattern);
171 #if ! TARGET_OS_ASPEN
172 CGImageRef GetCGImageFromPasteboard( NSPasteboard *pb )
174 CGImageSourceRef src = NULL;
175 NSArray *paths = [pb propertyListForType: NSFilenamesPboardType];
176 if( paths.count==1 ) {
177 // If a file is being dragged, read it:
178 CFURLRef url = (CFURLRef) [NSURL fileURLWithPath: [paths objectAtIndex: 0]];
179 src = CGImageSourceCreateWithURL(url, NULL);
181 // Else look for an image type:
182 NSString *type = [pb availableTypeFromArray: [NSImage imageUnfilteredPasteboardTypes]];
184 NSData *data = [pb dataForType: type];
185 src = CGImageSourceCreateWithData((CFDataRef)data, NULL);
189 CGImageRef image = CGImageSourceCreateImageAtIndex(src, 0, NULL);
198 float GetPixelAlpha( CGImageRef image, CGSize imageSize, CGPoint pt )
201 // iPhone uses "flipped" (i.e. normal) coords, so images are wrong-way-up
202 pt.y = imageSize.height - pt.y;
206 if( pt.x<0 || pt.x>=imageSize.width || pt.y<0 || pt.y>=imageSize.height )
209 // sTinyContext is a 1x1 CGBitmapContext whose pixmap stores only alpha.
210 static UInt8 sPixel[1];
211 static CGContextRef sTinyContext;
212 if( ! sTinyContext ) {
213 sTinyContext = CGBitmapContextCreate(sPixel, 1, 1,
214 8, 1, // bpp, rowBytes
217 CGContextSetBlendMode(sTinyContext, kCGBlendModeCopy);
220 // Draw the image into sTinyContext, positioned so the desired point is at
221 // (0,0), then examine the alpha value in the pixmap:
222 CGContextDrawImage(sTinyContext,
223 CGRectMake(-pt.x,-pt.y, imageSize.width,imageSize.height),
225 return sPixel[0] / 255.0;
230 #pragma mark PATTERNS:
233 // callback for CreateImagePattern.
234 static void drawPatternImage (void *info, CGContextRef ctx)
236 CGImageRef image = (CGImageRef) info;
237 CGContextDrawImage(ctx,
238 CGRectMake(0,0, CGImageGetWidth(image),CGImageGetHeight(image)),
242 // callback for CreateImagePattern.
243 static void releasePatternImage( void *info )
245 CGImageRelease( (CGImageRef)info );
249 CGPatternRef CreateImagePattern( CGImageRef image )
251 NSCParameterAssert(image);
252 int width = CGImageGetWidth(image);
253 int height = CGImageGetHeight(image);
254 static const CGPatternCallbacks callbacks = {0, &drawPatternImage, &releasePatternImage};
255 return CGPatternCreate (image,
256 CGRectMake (0, 0, width, height),
257 CGAffineTransformMake (1, 0, 0, 1, 0, 0),
260 kCGPatternTilingConstantSpacing,
266 CGColorRef CreatePatternColor( CGImageRef image )
268 CGPatternRef pattern = CreateImagePattern(image);
269 CGColorSpaceRef space = CGColorSpaceCreatePattern(NULL);
270 CGFloat components[1] = {1.0};
271 CGColorRef color = CGColorCreateWithPattern(space, pattern, components);
272 CGColorSpaceRelease(space);
273 CGPatternRelease(pattern);
282 void AddRoundRect( CGContextRef ctx, CGRect rect, CGFloat radius )
284 radius = MIN(radius, floorf(rect.size.width/2));
285 float x0 = CGRectGetMinX(rect), y0 = CGRectGetMinY(rect),
286 x1 = CGRectGetMaxX(rect), y1 = CGRectGetMaxY(rect);
288 CGContextBeginPath(ctx);
289 CGContextMoveToPoint(ctx,x0+radius,y0);
290 CGContextAddArcToPoint(ctx,x1,y0, x1,y1, radius);
291 CGContextAddArcToPoint(ctx,x1,y1, x0,y1, radius);
292 CGContextAddArcToPoint(ctx,x0,y1, x0,y0, radius);
293 CGContextAddArcToPoint(ctx,x0,y0, x1,y0, radius);
294 CGContextClosePath(ctx);