Initial check-in into Mercurial. Branched from 1.0 release of Apple's sample code. No longer requires garbage collection. Fixed some memory leaks of CG objects. Fixed a bug when advancing to the 8th row in the Checkers game.
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"
26 CGColorRef kBlackColor, kWhiteColor,
27 kTranslucentGrayColor, kTranslucentLightGrayColor,
28 kAlmostInvisibleWhiteColor,
32 __attribute__((constructor)) // Makes this function run when the app loads
33 static void InitQuartzUtils()
35 kBlackColor = CGColorCreateGenericGray(0.0, 1.0);
36 kWhiteColor = CGColorCreateGenericGray(1.0, 1.0);
37 kTranslucentGrayColor = CGColorCreateGenericGray(0.0, 0.5);
38 kTranslucentLightGrayColor = CGColorCreateGenericGray(0.0, 0.25);
39 kAlmostInvisibleWhiteColor = CGColorCreateGenericGray(1, 0.05);
40 kHighlightColor = CGColorCreateGenericRGB(1, 1, 0, 0.5);
44 void ChangeSuperlayer( CALayer *layer, CALayer *newSuperlayer, int index )
46 // Disable actions, else the layer will move to the wrong place and then back!
47 [CATransaction flush];
48 [CATransaction begin];
49 [CATransaction setValue:(id)kCFBooleanTrue
50 forKey:kCATransactionDisableActions];
52 CGPoint pos = [newSuperlayer convertPoint: layer.position
53 fromLayer: layer.superlayer];
55 [layer removeFromSuperlayer];
57 [newSuperlayer insertSublayer: layer atIndex: index];
59 [newSuperlayer addSublayer: layer];
63 [CATransaction commit];
67 void RemoveImmediately( CALayer *layer )
69 [CATransaction flush];
70 [CATransaction begin];
71 [CATransaction setValue:(id)kCFBooleanTrue
72 forKey:kCATransactionDisableActions];
73 [layer removeFromSuperlayer];
74 [CATransaction commit];
78 CATextLayer* AddTextLayer( CALayer *superlayer,
79 NSString *text, NSFont* font,
80 enum CAAutoresizingMask align )
82 CATextLayer *label = [[CATextLayer alloc] init];
85 label.fontSize = font.pointSize;
86 label.foregroundColor = kBlackColor;
89 if( align & kCALayerWidthSizable )
91 else if( align & kCALayerMinXMargin )
95 align |= kCALayerWidthSizable;
96 label.alignmentMode = mode;
98 CGFloat inset = superlayer.borderWidth + 3;
99 CGRect bounds = CGRectInset(superlayer.bounds, inset, inset);
100 CGFloat height = font.ascender;
101 CGFloat y = bounds.origin.y;
102 if( align & kCALayerHeightSizable )
103 y += (bounds.size.height-height)/2.0;
104 else if( align & kCALayerMinYMargin )
105 y += bounds.size.height - height;
106 align &= ~kCALayerHeightSizable;
107 label.bounds = CGRectMake(0, font.descender,
108 bounds.size.width, height - font.descender);
109 label.position = CGPointMake(bounds.origin.x,y+font.descender);
110 label.anchorPoint = CGPointMake(0,0);
112 label.autoresizingMask = align;
113 [superlayer addSublayer: label];
119 CGImageRef CreateCGImageFromFile( NSString *path )
121 CGImageRef image = NULL;
122 CFURLRef url = (CFURLRef) [NSURL fileURLWithPath: path];
123 CGImageSourceRef src = CGImageSourceCreateWithURL(url, NULL);
125 image = CGImageSourceCreateImageAtIndex(src, 0, NULL);
127 if(!image) NSLog(@"Warning: CGImageSourceCreateImageAtIndex failed on file %@ (ptr size=%u)",path,sizeof(void*));
133 CGImageRef GetCGImageNamed( NSString *name )
135 // For efficiency, loaded images are cached in a dictionary by name.
136 static NSMutableDictionary *sMap;
138 sMap = [[NSMutableDictionary alloc] init];
140 CGImageRef image = (CGImageRef) [sMap objectForKey: name];
142 // Hasn't been cached yet, so load it:
144 if( [name hasPrefix: @"/"] )
147 path = [[NSBundle mainBundle] pathForResource: name ofType: nil];
148 NSCAssert1(path,@"Couldn't find bundle image resource '%@'",name);
150 image = CreateCGImageFromFile(path);
151 NSCAssert1(image,@"Failed to load image from %@",path);
152 [sMap setObject: (id)image forKey: name];
153 CGImageRelease(image);
159 CGColorRef GetCGPatternNamed( NSString *name ) // can be resource name or abs. path
161 // For efficiency, loaded patterns are cached in a dictionary by name.
162 static NSMutableDictionary *sMap;
164 sMap = [[NSMutableDictionary alloc] init];
166 CGColorRef pattern = (CGColorRef) [sMap objectForKey: name];
168 pattern = CreatePatternColor( GetCGImageNamed(name) );
169 [sMap setObject: (id)pattern forKey: name];
170 CGColorRelease(pattern);
176 CGImageRef GetCGImageFromPasteboard( NSPasteboard *pb )
178 CGImageSourceRef src = NULL;
179 NSArray *paths = [pb propertyListForType: NSFilenamesPboardType];
180 if( paths.count==1 ) {
181 // If a file is being dragged, read it:
182 CFURLRef url = (CFURLRef) [NSURL fileURLWithPath: [paths objectAtIndex: 0]];
183 src = CGImageSourceCreateWithURL(url, NULL);
185 // Else look for an image type:
186 NSString *type = [pb availableTypeFromArray: [NSImage imageUnfilteredPasteboardTypes]];
188 NSData *data = [pb dataForType: type];
189 src = CGImageSourceCreateWithData((CFDataRef)data, NULL);
193 CGImageRef image = CGImageSourceCreateImageAtIndex(src, 0, NULL);
201 float GetPixelAlpha( CGImageRef image, CGSize imageSize, CGPoint pt )
204 if( pt.x<0 || pt.x>=imageSize.width || pt.y<0 || pt.y>=imageSize.height )
207 // sTinyContext is a 1x1 CGBitmapContext whose pixmap stores only alpha.
208 static UInt8 sPixel[1];
209 static CGContextRef sTinyContext;
210 if( ! sTinyContext ) {
211 sTinyContext = CGBitmapContextCreate(sPixel, 1, 1,
212 8, 1, // bpp, rowBytes
215 CGContextSetBlendMode(sTinyContext, kCGBlendModeCopy);
218 // Draw the image into sTinyContext, positioned so the desired point is at
219 // (0,0), then examine the alpha value in the pixmap:
220 CGContextDrawImage(sTinyContext,
221 CGRectMake(-pt.x,-pt.y, imageSize.width,imageSize.height),
223 return sPixel[0] / 255.0;
228 #pragma mark PATTERNS:
231 // callback for CreateImagePattern.
232 static void drawPatternImage (void *info, CGContextRef ctx)
234 CGImageRef image = (CGImageRef) info;
235 CGContextDrawImage(ctx,
236 CGRectMake(0,0, CGImageGetWidth(image),CGImageGetHeight(image)),
240 // callback for CreateImagePattern.
241 static void releasePatternImage( void *info )
243 CGImageRelease( (CGImageRef)info );
247 CGPatternRef CreateImagePattern( CGImageRef image )
249 NSCParameterAssert(image);
250 int width = CGImageGetWidth(image);
251 int height = CGImageGetHeight(image);
252 static const CGPatternCallbacks callbacks = {0, &drawPatternImage, &releasePatternImage};
253 return CGPatternCreate (image,
254 CGRectMake (0, 0, width, height),
255 CGAffineTransformMake (1, 0, 0, 1, 0, 0),
258 kCGPatternTilingConstantSpacing,
264 CGColorRef CreatePatternColor( CGImageRef image )
266 CGPatternRef pattern = CreateImagePattern(image);
267 CGColorSpaceRef space = CGColorSpaceCreatePattern(NULL);
268 CGFloat components[1] = {1.0};
269 CGColorRef color = CGColorCreateWithPattern(space, pattern, components);
270 CGColorSpaceRelease(space);
271 CGPatternRelease(pattern);