aboutsummaryrefslogtreecommitdiff
path: root/AppKit
diff options
context:
space:
mode:
authorGravatar thomasvl@gmail.com <thomasvl@gmail.com@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-09-10 21:04:47 +0000
committerGravatar thomasvl@gmail.com <thomasvl@gmail.com@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2008-09-10 21:04:47 +0000
commitbfaf8705cccb15c0c2a7704b17ba011ddba8242f (patch)
treeb48e104487ee5e29522da1bce6accafa007e29cf /AppKit
parent0f0f40db85a2c295a9b6dc1623cd76106a4448a5 (diff)
- Added GTMExceptionalInlines for dealing with cases where you get
warning: variable 'r' might be clobbered by 'longjmp' or 'vfork' when using certain Apple inlined functions in @synchronized/@try blocks. - Updated to Xcode 3.1 so the GTM and iPhone project have the same baseline. The code should work in other version of xcode, but the projects and xcconfig files now use 3.1 features. - Added GTMABAddressBook which is a cocoa wrapper for the 'C' AddressBook APIs on the iPhone. - Added several set environment variable statements to RunIPhoneUnitTest.sh to encourage bugs to come out of the woodwork.
Diffstat (limited to 'AppKit')
-rw-r--r--AppKit/GTMNSImage+Scaling.h46
-rw-r--r--AppKit/GTMNSImage+Scaling.m168
-rw-r--r--AppKit/GTMNSImage+ScalingTest.m47
3 files changed, 261 insertions, 0 deletions
diff --git a/AppKit/GTMNSImage+Scaling.h b/AppKit/GTMNSImage+Scaling.h
new file mode 100644
index 0000000..297d18c
--- /dev/null
+++ b/AppKit/GTMNSImage+Scaling.h
@@ -0,0 +1,46 @@
+//
+// GTMNSImage+Scaling.h
+//
+// Scales NSImages to a variety of sizes for drawing
+//
+// Copyright 2006-2008 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+
+#import <Foundation/Foundation.h>
+
+@interface NSImage (GTMNSImageScaling)
+
+// Return an existing representation of a size
+- (NSImageRep *)gtm_representationOfSize:(NSSize)size;
+
+// Return the exact or next largest representation for a size
+- (NSImageRep *)gtm_bestRepresentationForSize:(NSSize)size;
+
+// Create a new represetation for a given size
+- (BOOL)gtm_createRepresentationOfSize:(NSSize)size;
+
+// Create 32 and 16px reps
+- (BOOL)gtm_createIconRepresentations;
+
+// Remove reps larger than a given size and create a new rep if needed
+- (void)gtm_shrinkToSize:(NSSize)size;
+
+// Remove reps larger than a given size
+- (void)gtm_removeRepresentationsLargerThanSize:(NSSize)size;
+
+// Return a dup shrunk to a given size
+- (NSImage *)gtm_duplicateOfSize:(NSSize)size;
+@end
diff --git a/AppKit/GTMNSImage+Scaling.m b/AppKit/GTMNSImage+Scaling.m
new file mode 100644
index 0000000..57687fd
--- /dev/null
+++ b/AppKit/GTMNSImage+Scaling.m
@@ -0,0 +1,168 @@
+//
+// GTMNSImage+Scaling.m
+//
+// Scales NSImages to a variety of sizes for drawing
+//
+// Copyright 2006-2008 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+#import "GTMNSImage+Scaling.h"
+#import "GTMGeometryUtils.h"
+
+@implementation NSImage (GTMNSImageScaling)
+
+- (NSImageRep *)gtm_bestRepresentationForSize:(NSSize)size {
+ NSImageRep *bestRep = [self gtm_representationOfSize:size];
+ if (bestRep) {
+ return bestRep;
+ }
+ NSArray *reps = [self representations];
+
+ CGFloat repDistance = CGFLOAT_MAX;
+
+ NSImageRep *thisRep;
+ NSEnumerator *repEnum = [reps objectEnumerator];
+ while ((thisRep = [repEnum nextObject])) {
+ CGFloat thisDistance;
+ thisDistance = MIN(size.width - [thisRep size].width,
+ size.height-[thisRep size].height);
+
+ if (repDistance < 0 && thisDistance > 0) continue;
+ if (ABS(thisDistance) < ABS(repDistance)
+ || (thisDistance < 0 && repDistance > 0)) {
+ repDistance = thisDistance;
+ bestRep = thisRep;
+ }
+ }
+
+ if (!bestRep) {
+ bestRep = [self bestRepresentationForDevice:nil];
+ }
+
+ return bestRep;
+}
+
+- (NSImageRep *)gtm_representationOfSize:(NSSize)size {
+ NSArray *reps = [self representations];
+
+ NSImageRep *thisRep;
+ NSEnumerator *repEnum = [reps objectEnumerator];
+ while ((thisRep = [repEnum nextObject])) {
+ if (NSEqualSizes([thisRep size], size)) {
+ return thisRep;
+ }
+ }
+ return nil;
+}
+
+- (BOOL)gtm_createIconRepresentations {
+ [self setFlipped:NO];
+ [self gtm_createRepresentationOfSize:NSMakeSize(16, 16)];
+ [self gtm_createRepresentationOfSize:NSMakeSize(32, 32)];
+ [self setScalesWhenResized:NO];
+ return YES;
+}
+
+- (BOOL)gtm_createRepresentationOfSize:(NSSize)size {
+ if ([self gtm_representationOfSize:size]) {
+ return NO;
+ }
+
+ NSBitmapImageRep *bestRep =
+ (NSBitmapImageRep *)[self gtm_bestRepresentationForSize:size];
+
+ NSRect drawRect = GTMNSScaleRectToRect(GTMNSRectOfSize([bestRep size]),
+ GTMNSRectOfSize(size),
+ GTMScaleProportionally,
+ GTMRectAlignCenter);
+
+ if ([bestRep respondsToSelector:@selector(CGImage)]) {
+ CGImageRef imageRef = (CGImageRef)[bestRep performSelector:@selector(CGImage)];
+
+ CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB();
+ if (!cspace) return NO;
+
+ CGContextRef smallContext =
+ CGBitmapContextCreate(NULL,
+ size.width,
+ size.height,
+ 8, // bits per component
+ size.width * 4, // bytes per pixel
+ cspace,
+ kCGBitmapByteOrder32Host
+ | kCGImageAlphaPremultipliedLast);
+ CFRelease(cspace);
+
+ if (!smallContext) return NO;
+
+
+ CGContextDrawImage(smallContext, GTMNSRectToCGRect(drawRect), imageRef);
+
+ CGImageRef smallImage = CGBitmapContextCreateImage(smallContext);
+
+ if (smallImage) {
+ NSBitmapImageRep *cgRep =
+ [[[NSBitmapImageRep alloc] initWithCGImage:smallImage] autorelease];
+ [self addRepresentation:cgRep];
+ CGImageRelease(smallImage);
+ } else {
+ CGContextRelease(smallContext);
+ return NO;
+ }
+ CGContextRelease(smallContext);
+ return YES;
+ } else {
+ // This functionality is here to allow it to work under Tiger
+ // It can probably only be called safely from the main thread
+ NSImage* scaledImage = [[NSImage alloc] initWithSize:size];
+ [scaledImage lockFocus];
+ NSGraphicsContext *graphicsContext = [NSGraphicsContext currentContext];
+ [graphicsContext setImageInterpolation:NSImageInterpolationHigh];
+ [graphicsContext setShouldAntialias:YES];
+ [bestRep drawInRect:drawRect];
+ NSBitmapImageRep* iconRep =
+ [[[NSBitmapImageRep alloc] initWithFocusedViewRect:
+ NSMakeRect(0, 0, size.width, size.height)] autorelease];
+ [scaledImage unlockFocus];
+ [scaledImage release];
+ [self addRepresentation:iconRep];
+ return YES;
+ }
+ return NO;
+}
+
+- (void)gtm_removeRepresentationsLargerThanSize:(NSSize)size {
+ NSEnumerator *e = [[self representations] reverseObjectEnumerator];
+ NSImageRep *thisRep;
+ while((thisRep = [e nextObject]) ) {
+ if ([thisRep size].width > size.width
+ && [thisRep size].height > size.height)
+ [self removeRepresentation:thisRep];
+ }
+}
+
+- (NSImage *)gtm_duplicateOfSize:(NSSize)size {
+ NSImage *duplicate = [[self copy] autorelease];
+ [duplicate gtm_shrinkToSize:size];
+ [duplicate setFlipped:NO];
+ return duplicate;
+}
+
+- (void)gtm_shrinkToSize:(NSSize)size {
+ [self gtm_createRepresentationOfSize:size];
+ [self setSize:size];
+ [self gtm_removeRepresentationsLargerThanSize:size];
+}
+@end
diff --git a/AppKit/GTMNSImage+ScalingTest.m b/AppKit/GTMNSImage+ScalingTest.m
new file mode 100644
index 0000000..ec17cc5
--- /dev/null
+++ b/AppKit/GTMNSImage+ScalingTest.m
@@ -0,0 +1,47 @@
+//
+// GTMNSImage+ScalingTest.m
+//
+// Copyright 2006-2008 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+
+#import <Cocoa/Cocoa.h>
+
+#import "GTMSenTestCase.h"
+
+#import "GTMNSImage+Scaling.h"
+
+@interface GTMNSImage_ScalingTest : GTMTestCase
+@end
+
+@implementation GTMNSImage_ScalingTest
+
+- (void)testScaling {
+ NSImage *testImage = [NSImage imageNamed:@"NSApplicationIcon"];
+
+ NSImageRep *rep = nil;
+ rep = [testImage gtm_bestRepresentationForSize:NSMakeSize(99, 99)];
+ STAssertTrue(NSEqualSizes([rep size], NSMakeSize(128, 128)), nil);
+
+ [testImage gtm_createIconRepresentations];
+ STAssertNotNil([testImage gtm_representationOfSize:NSMakeSize(16, 16)], nil);
+ STAssertNotNil([testImage gtm_representationOfSize:NSMakeSize(32, 32)], nil);
+
+ NSImage *duplicate = [testImage gtm_duplicateOfSize: NSMakeSize(48, 48)];
+ rep = [duplicate gtm_bestRepresentationForSize:NSMakeSize(50, 50)];
+ STAssertTrue(NSEqualSizes([rep size], NSMakeSize(48, 48)), nil);
+
+}
+
+@end