Lots of reworking. Completed support for game history, including Turn class. Changed Game API around quite a bit.
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>
28 CGColorRef kBlackColor, kWhiteColor,
29 kTranslucentGrayColor, kTranslucentLightGrayColor,
30 kTranslucentWhiteColor, kAlmostInvisibleWhiteColor,
34 __attribute__((constructor)) // Makes this function run when the app loads
35 static void InitQuartzUtils()
37 kBlackColor = CreateGray(0.0, 1.0);
38 kWhiteColor = CreateGray(1.0, 1.0);
39 kTranslucentGrayColor = CreateGray(0.0, 0.5);
40 kTranslucentLightGrayColor = CreateGray(0.0, 0.25);
41 kTranslucentWhiteColor = CreateGray(1, 0.25);
42 kAlmostInvisibleWhiteColor = CreateGray(1, 0.05);
43 kHighlightColor = CreateRGB(1, 1, 0, 0.5);
48 CGColorRef CreateGray(CGFloat gray, CGFloat alpha)
50 CGColorSpaceRef graySpace = CGColorSpaceCreateDeviceGray();
51 CGFloat components[2] = {gray,alpha};
52 CGColorRef color = CGColorCreate(graySpace, components);
53 CGColorSpaceRelease(graySpace);
57 CGColorRef CreateRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha)
59 CGColorSpaceRef rgbSpace = CGColorSpaceCreateDeviceRGB();
60 CGFloat components[4] = {red,green,blue,alpha};
61 CGColorRef color = CGColorCreate(rgbSpace, components);
62 CGColorSpaceRelease(rgbSpace);
68 CGImageRef CreateCGImageFromFile( NSString *path )
71 UIImage *uiImage = [UIImage imageWithContentsOfFile: path];
72 if(!uiImage) NSLog(@"Warning: UIImage imageWithContentsOfFile failed on file %@",path);
73 return CGImageRetain(uiImage.CGImage);
75 CGImageRef image = NULL;
76 CFURLRef url = (CFURLRef) [NSURL fileURLWithPath: path];
77 CGImageSourceRef src = CGImageSourceCreateWithURL(url, NULL);
79 image = CGImageSourceCreateImageAtIndex(src, 0, NULL);
81 if(!image) NSLog(@"Warning: CGImageSourceCreateImageAtIndex failed on file %@ (ptr size=%u)",path,sizeof(void*));
88 CGImageRef GetCGImageNamed( NSString *name )
91 name = name.lastPathComponent;
92 UIImage *uiImage = [UIImage imageNamed: name];
93 NSCAssert1(uiImage,@"Couldn't find bundle image resource '%@'",name);
94 return uiImage.CGImage;
96 // For efficiency, loaded images are cached in a dictionary by name.
97 static NSMutableDictionary *sMap;
99 sMap = [[NSMutableDictionary alloc] init];
101 CGImageRef image = (CGImageRef) [sMap objectForKey: name];
103 // Hasn't been cached yet, so load it:
105 if( [name hasPrefix: @"/"] )
108 path = [[NSBundle mainBundle] pathForResource: name ofType: nil];
109 NSCAssert1(path,@"Couldn't find bundle image resource '%@'",name);
111 image = CreateCGImageFromFile(path);
112 NSCAssert1(image,@"Failed to load image from %@",path);
113 [sMap setObject: (id)image forKey: name];
114 CGImageRelease(image);
121 CGColorRef GetCGPatternNamed( NSString *name ) // can be resource name or abs. path
123 // For efficiency, loaded patterns are cached in a dictionary by name.
124 static NSMutableDictionary *sMap;
126 sMap = [[NSMutableDictionary alloc] init];
128 CGColorRef pattern = (CGColorRef) [sMap objectForKey: name];
130 pattern = CreatePatternColor( GetCGImageNamed(name) );
131 [sMap setObject: (id)pattern forKey: name];
132 CGColorRelease(pattern);
138 #if ! TARGET_OS_IPHONE
139 CGImageRef GetCGImageFromPasteboard( NSPasteboard *pb )
141 CGImageSourceRef src = NULL;
142 NSArray *paths = [pb propertyListForType: NSFilenamesPboardType];
143 if( paths.count==1 ) {
144 // If a file is being dragged, read it:
145 CFURLRef url = (CFURLRef) [NSURL fileURLWithPath: [paths objectAtIndex: 0]];
146 src = CGImageSourceCreateWithURL(url, NULL);
148 // Else look for an image type:
149 NSString *type = [pb availableTypeFromArray: [NSImage imageUnfilteredPasteboardTypes]];
151 NSData *data = [pb dataForType: type];
152 src = CGImageSourceCreateWithData((CFDataRef)data, NULL);
156 CGImageRef image = CGImageSourceCreateImageAtIndex(src, 0, NULL);
165 CGImageRef CreateScaledImage( CGImageRef srcImage, CGFloat scale )
167 int width = CGImageGetWidth(srcImage), height = CGImageGetHeight(srcImage);
170 scale /= MAX(width,height); // interpret scale as target dimensions
171 width = ceil( width * scale);
172 height= ceil( height* scale);
175 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
176 CGContextRef ctx = CGBitmapContextCreate(NULL, width, height, 8, 4*width, space,
177 kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast);
178 CGColorSpaceRelease(space);
179 CGContextSetInterpolationQuality(ctx,kCGInterpolationHigh);
180 CGContextDrawImage(ctx, CGRectMake(0, 0, width, height), srcImage);
181 CGImageRef dstImage = CGBitmapContextCreateImage(ctx);
182 CGContextRelease(ctx);
187 CGImageRef GetScaledImageNamed( NSString *imageName, CGFloat scale )
189 // For efficiency, loaded images are cached in a dictionary by name.
190 static NSMutableDictionary *sMap;
192 sMap = [[NSMutableDictionary alloc] init];
194 NSArray *key = [NSArray arrayWithObjects: imageName, [NSNumber numberWithFloat: scale], nil];
195 CGImageRef image = (CGImageRef) [sMap objectForKey: key];
197 // Hasn't been cached yet, so load it:
198 image = CreateScaledImage(GetCGImageNamed(imageName), scale);
199 [sMap setObject: (id)image forKey: key];
200 CGImageRelease(image);
206 float GetPixelAlpha( CGImageRef image, CGSize imageSize, CGPoint pt )
209 // iPhone uses "flipped" (i.e. normal) coords, so images are wrong-way-up
210 pt.y = imageSize.height - pt.y;
214 if( pt.x<0 || pt.x>=imageSize.width || pt.y<0 || pt.y>=imageSize.height )
217 // sTinyContext is a 1x1 CGBitmapContext whose pixmap stores only alpha.
218 static UInt8 sPixel[1];
219 static CGContextRef sTinyContext;
220 if( ! sTinyContext ) {
221 sTinyContext = CGBitmapContextCreate(sPixel, 1, 1,
222 8, 1, // bpp, rowBytes
225 CGContextSetBlendMode(sTinyContext, kCGBlendModeCopy);
228 // Draw the image into sTinyContext, positioned so the desired point is at
229 // (0,0), then examine the alpha value in the pixmap:
230 CGContextDrawImage(sTinyContext,
231 CGRectMake(-pt.x,-pt.y, imageSize.width,imageSize.height),
233 return sPixel[0] / 255.0;
238 #pragma mark PATTERNS:
241 // callback for CreateImagePattern.
242 static void drawPatternImage (void *info, CGContextRef ctx)
244 CGImageRef image = (CGImageRef) info;
245 CGContextDrawImage(ctx,
246 CGRectMake(0,0, CGImageGetWidth(image),CGImageGetHeight(image)),
250 // callback for CreateImagePattern.
251 static void releasePatternImage( void *info )
253 CGImageRelease( (CGImageRef)info );
257 CGPatternRef CreateImagePattern( CGImageRef image )
259 NSCParameterAssert(image);
260 int width = CGImageGetWidth(image);
261 int height = CGImageGetHeight(image);
262 static const CGPatternCallbacks callbacks = {0, &drawPatternImage, &releasePatternImage};
263 return CGPatternCreate (image,
264 CGRectMake (0, 0, width, height),
265 CGAffineTransformMake (1, 0, 0, 1, 0, 0),
268 kCGPatternTilingConstantSpacing,
274 CGColorRef CreatePatternColor( CGImageRef image )
276 CGPatternRef pattern = CreateImagePattern(image);
277 CGColorSpaceRef space = CGColorSpaceCreatePattern(NULL);
278 CGFloat components[1] = {1.0};
279 CGColorRef color = CGColorCreateWithPattern(space, pattern, components);
280 CGColorSpaceRelease(space);
281 CGPatternRelease(pattern);
290 void AddRoundRect( CGContextRef ctx, CGRect rect, CGFloat radius )
292 radius = MIN(radius, floorf(rect.size.width/2));
293 float x0 = CGRectGetMinX(rect), y0 = CGRectGetMinY(rect),
294 x1 = CGRectGetMaxX(rect), y1 = CGRectGetMaxY(rect);
296 CGContextBeginPath(ctx);
297 CGContextMoveToPoint(ctx,x0+radius,y0);
298 CGContextAddArcToPoint(ctx,x1,y0, x1,y1, radius);
299 CGContextAddArcToPoint(ctx,x1,y1, x0,y1, radius);
300 CGContextAddArcToPoint(ctx,x0,y1, x0,y0, radius);
301 CGContextAddArcToPoint(ctx,x0,y0, x1,y0, radius);
302 CGContextClosePath(ctx);