diff options
author | 2008-08-12 17:21:32 +0000 | |
---|---|---|
committer | 2008-08-12 17:21:32 +0000 | |
commit | 7063d76a007fbf636250d7199d6f24ec487163b1 (patch) | |
tree | 5a1f2f0a4b597f62df3e2fe858d76d37b22bbe89 /AppKit | |
parent | 43982f07ba6a0a9839e32e774855c9d2068e9d5e (diff) |
- Added GTMNSMakeUncollectable for forcing objects to survive in a GC world.
- Added GTMCFAutorelease to make the [GTMNSMakeCollectable(cfFoo) autorelease] simpler and clearer, it's now just GTMCFAutorelease(cfFoo), and works in both GC and non-GC world.
- Added GTMIsGarbageCollectionEnabled to GTMGarbageCollection.h. See the note there for it's usage.
- Disabled the unittests for things on top of NSAppleScript in a GC world since Apple has bugs and it can crash. See the unittest for a note about it.
- GTMStackTrace now can figure out ObjC symbols. Downside it is now ObjC only.
- GTMFourCharCode can now be used with NSAppleEventDescriptors easily. typeType, typeKeyword, typeApplSignature, and typeEnumerated all get turned into GTMFourCharCodes.
- Fixed up crash in GTMLoggerRingBufferWriter when used with GC on.
- Significant updates to GTMNSAppleScript+Handler allowing you to list all handlers and properties (including inherited) and cleans up several errors in how scripting was being handled.
Diffstat (limited to 'AppKit')
-rw-r--r-- | AppKit/GTMLargeTypeWindow.h | 9 | ||||
-rw-r--r-- | AppKit/GTMLargeTypeWindow.m | 210 | ||||
-rw-r--r-- | AppKit/GTMLargeTypeWindowTest.m | 100 | ||||
-rw-r--r-- | AppKit/GTMLinearRGBShadingTest.m | 37 | ||||
-rw-r--r-- | AppKit/GTMLoginItems.m | 10 | ||||
-rw-r--r-- | AppKit/GTMLoginItemsTest.m | 46 | ||||
-rw-r--r-- | AppKit/GTMNSBezierPath+CGPath.m | 4 | ||||
-rw-r--r-- | AppKit/GTMNSBezierPath+RoundRectTest.m | 16 | ||||
-rw-r--r-- | AppKit/GTMNSBezierPath+ShadingTest.m | 96 | ||||
-rw-r--r-- | AppKit/TestData/GTMNSBezierPath+RoundRectTest.ppc64.tiff | bin | 8042 -> 10728 bytes | |||
-rw-r--r-- | AppKit/TestData/GTMNSBezierPath+RoundRectTest.tiff | bin | 8036 -> 10724 bytes | |||
-rw-r--r-- | AppKit/TestData/GTMNSBezierPath+RoundRectTest.x86_64.tiff | bin | 8042 -> 10728 bytes | |||
-rw-r--r-- | AppKit/TestData/GTMNSBezierPath+ShadingTest.10.5.tiff | bin | 19450 -> 45080 bytes |
13 files changed, 415 insertions, 113 deletions
diff --git a/AppKit/GTMLargeTypeWindow.h b/AppKit/GTMLargeTypeWindow.h index 9bb6b85..52316fc 100644 --- a/AppKit/GTMLargeTypeWindow.h +++ b/AppKit/GTMLargeTypeWindow.h @@ -28,6 +28,15 @@ // = [[[GTMLargeTypeWindow alloc] initWithString:@"Foo"] autorelease]; // [window makeKeyAndOrderFront:nil]; +// NB This class appears to have a problem with GC on 10.5.4 and below. +// Radar 6137322 CIFilter crashing when run with GC enabled +// This appears to be an Apple bug with GC. +// We do a copy animation that causes things to crash, but only with GC +// on. Currently I have left this enabled in GTMLargeTypeWindow pending +// info from Apple on the bug. It's hard to reproduce, and only appears +// at this time on our test machines. +// Dual-Core Intel Xeon with ATI Radeon X1300 + // Amount of time to fade the window in or out const NSTimeInterval kGTMLargeTypeWindowFadeTime; diff --git a/AppKit/GTMLargeTypeWindow.m b/AppKit/GTMLargeTypeWindow.m index d84ce42..709099d 100644 --- a/AppKit/GTMLargeTypeWindow.m +++ b/AppKit/GTMLargeTypeWindow.m @@ -16,10 +16,12 @@ // the License. // +#import <QuartzCore/QuartzCore.h> + #import "GTMLargeTypeWindow.h" #import "GTMGeometryUtils.h" #import "GTMNSBezierPath+RoundRect.h" - +#import "GTMMethodCheck.h" // Amount of time to fade the window in or out const NSTimeInterval kGTMLargeTypeWindowFadeTime = 0.333; @@ -30,15 +32,23 @@ static const CGFloat kEdgeInset = 16.0; // Give us an alpha value for our backing window static const CGFloat kTwoThirdsAlpha = 0.66; -@interface GTMLargeTypeBackgroundView : NSView +@interface GTMLargeTypeCopyAnimation : NSAnimation +@end + +@interface GTMLargeTypeBackgroundView : NSView { + CIFilter *transition_; + GTMLargeTypeCopyAnimation *animation_; +} +- (void)animateCopy; @end @interface GTMLargeTypeWindow (GTMLargeTypeWindowPrivate) + (CGFloat)displayWidth; -- (void)startFadeInAnimation; +- (void)animateWithEffect:(NSString*)effect; @end @implementation GTMLargeTypeWindow + - (id)initWithString:(NSString *)string { if ([string length] == 0) { _GTMDevLog(@"GTMLargeTypeWindow got an empty string"); @@ -49,18 +59,44 @@ static const CGFloat kTwoThirdsAlpha = 0.66; NSMutableAttributedString *attrString = [[[NSMutableAttributedString alloc] initWithString:string] autorelease]; + NSRange fullRange = NSMakeRange(0, [string length]); + [attrString addAttribute:NSForegroundColorAttributeName + value:[NSColor whiteColor] + range:fullRange]; + + NSMutableParagraphStyle *style + = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease]; + [style setAlignment:NSCenterTextAlignment]; + [attrString addAttribute:NSParagraphStyleAttributeName + value:style + range:fullRange]; + + NSShadow *textShadow = [[[NSShadow alloc] init] autorelease]; + [textShadow setShadowOffset:NSMakeSize( 5, -5 )]; + [textShadow setShadowBlurRadius:10]; + [textShadow setShadowColor:[NSColor colorWithCalibratedWhite:0 + alpha:kTwoThirdsAlpha]]; + [attrString addAttribute:NSShadowAttributeName + value:textShadow + range:fullRange]; + // Try and find a size that fits without iterating too many times. // We start going 50 pixels at a time, then 10, then 1 int size = -26; // start at 24 (-26 + 50) int offsets[] = { 50, 10, 1 }; + NSSize bigSize = NSMakeSize(MAXFLOAT, MAXFLOAT); + NSStringDrawingOptions options = (NSStringDrawingUsesDeviceMetrics | + NSStringDrawingOneShot); for (size_t i = 0; i < sizeof(offsets) / sizeof(int); ++i) { for(size = size + offsets[i]; size >= 24 && size < 300; size += offsets[i]) { - NSFont *textFont = [NSFont boldSystemFontOfSize:size]; - NSDictionary *fontAttr - = [NSDictionary dictionaryWithObject:textFont - forKey:NSFontAttributeName]; - NSSize textSize = [string sizeWithAttributes:fontAttr]; - if (textSize.width > displayWidth) { + NSFont *font = [NSFont boldSystemFontOfSize:size] ; + [attrString addAttribute:NSFontAttributeName + value:font + range:fullRange]; + NSRect textSize = [attrString boundingRectWithSize:bigSize + options:options]; + NSSize maxAdvanceSize = [font maximumAdvancement]; + if (textSize.size.width + maxAdvanceSize.width > displayWidth) { size = size - offsets[i]; break; } @@ -73,30 +109,9 @@ static const CGFloat kTwoThirdsAlpha = 0.66; } else if (size < 24) { size = 24; } - - NSRange fullRange = NSMakeRange(0, [string length]); [attrString addAttribute:NSFontAttributeName value:[NSFont boldSystemFontOfSize:size] range:fullRange]; - [attrString addAttribute:NSForegroundColorAttributeName - value:[NSColor whiteColor] - range:fullRange]; - - NSMutableParagraphStyle *style - = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease]; - [style setAlignment:NSCenterTextAlignment]; - [attrString addAttribute:NSParagraphStyleAttributeName - value:style - range:fullRange]; - - NSShadow *textShadow = [[[NSShadow alloc] init] autorelease]; - [textShadow setShadowOffset:NSMakeSize( 5, -5 )]; - [textShadow setShadowBlurRadius:10]; - [textShadow setShadowColor:[NSColor colorWithCalibratedWhite:0 - alpha:kTwoThirdsAlpha]]; - [attrString addAttribute:NSShadowAttributeName - value:textShadow - range:fullRange]; return [self initWithAttributedString:attrString]; } @@ -186,12 +201,26 @@ static const CGFloat kTwoThirdsAlpha = 0.66; [pb setString:[[firstResponder textStorage] string] forType:NSStringPboardType]; } + + // Give the user some feedback that a copy has occurred + [(GTMLargeTypeBackgroundView*)[self contentView] animateCopy]; } - (BOOL)canBecomeKeyWindow { return YES; } +- (BOOL)performKeyEquivalent:(NSEvent *)theEvent { + NSString *chars = [theEvent charactersIgnoringModifiers]; + NSUInteger flags = ([theEvent modifierFlags] & + NSDeviceIndependentModifierFlagsMask); + BOOL isValid = (flags == NSCommandKeyMask) && [chars isEqualToString:@"c"]; + if (isValid) { + [self copy:self]; + } + return isValid; +} + - (void)keyDown:(NSEvent *)theEvent { [self close]; } @@ -204,30 +233,18 @@ static const CGFloat kTwoThirdsAlpha = 0.66; } - (void)makeKeyAndOrderFront:(id)sender { - [self startFadeInAnimation]; [super makeKeyAndOrderFront:sender]; + [self animateWithEffect:NSViewAnimationFadeInEffect]; } - (void)orderFront:(id)sender { - [self startFadeInAnimation]; [super orderFront:sender]; + [self animateWithEffect:NSViewAnimationFadeInEffect]; } - (void)orderOut:(id)sender { - NSDictionary *fadeOut = [NSDictionary dictionaryWithObjectsAndKeys: - self, NSViewAnimationTargetKey, - NSViewAnimationFadeOutEffect, NSViewAnimationEffectKey, - nil]; - NSArray *animation = [NSArray arrayWithObject:fadeOut]; - NSViewAnimation *viewAnim - = [[[NSViewAnimation alloc] initWithViewAnimations:animation] autorelease]; - [viewAnim setDuration:kGTMLargeTypeWindowFadeTime]; - [viewAnim startAnimation]; - NSDate *fadeOutDate - = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime]; - // We have a local run loop because if this is called as part of a close - // our window will be hidden immediately before it has a chance to fade. - [[NSRunLoop currentRunLoop] runUntilDate:fadeOutDate]; + [self animateWithEffect:NSViewAnimationFadeOutEffect]; + [super orderOut:sender]; } + (CGFloat)displayWidth { @@ -237,40 +254,105 @@ static const CGFloat kTwoThirdsAlpha = 0.66; return NSWidth( screenRect ) * 11.0 / 12.0 - 2.0 * kEdgeInset; } -- (void)startFadeInAnimation { - // If we aren't already fully visible, start fading us in. - if ([self alphaValue] < 1.0) { - NSDictionary *fadeIn = [NSDictionary dictionaryWithObjectsAndKeys: - self, NSViewAnimationTargetKey, - NSViewAnimationFadeInEffect, NSViewAnimationEffectKey, - nil]; - NSArray *animation = [NSArray arrayWithObject:fadeIn]; - NSViewAnimation *viewAnim - = [[[NSViewAnimation alloc] initWithViewAnimations:animation] autorelease]; - [viewAnim setDuration:kGTMLargeTypeWindowFadeTime]; - [viewAnim startAnimation]; - } +- (void)animateWithEffect:(NSString*)effect { + NSDictionary *fadeIn = [NSDictionary dictionaryWithObjectsAndKeys: + self, NSViewAnimationTargetKey, + effect, NSViewAnimationEffectKey, + nil]; + NSArray *animation = [NSArray arrayWithObject:fadeIn]; + NSViewAnimation *viewAnim + = [[[NSViewAnimation alloc] initWithViewAnimations:animation] autorelease]; + [viewAnim setDuration:kGTMLargeTypeWindowFadeTime]; + [viewAnim setAnimationBlockingMode:NSAnimationBlocking]; + [viewAnim startAnimation]; } @end @implementation GTMLargeTypeBackgroundView +GTM_METHOD_CHECK(NSBezierPath, gtm_appendBezierPathWithRoundRect:cornerRadius:); - (BOOL)isOpaque { return NO; } - (void)drawRect:(NSRect)rect { - [[NSColor colorWithDeviceWhite:0 alpha:kTwoThirdsAlpha] set]; rect = [self bounds]; - NSBezierPath *roundRect = [NSBezierPath bezierPath]; CGFloat minRadius = MIN(NSWidth(rect), NSHeight(rect)) * 0.5f; [roundRect gtm_appendBezierPathWithRoundRect:rect cornerRadius:MIN(minRadius, 32)]; - [roundRect addClip]; - NSRectFill(rect); - [super drawRect:rect]; + [roundRect addClip]; + if (transition_) { + NSNumber *val = [NSNumber numberWithFloat:[animation_ currentValue]]; + [transition_ setValue:val forKey:@"inputTime"]; + CIImage *outputCIImage = [transition_ valueForKey:@"outputImage"]; + [outputCIImage drawInRect:rect + fromRect:rect + operation:NSCompositeSourceOver + fraction:1.0]; + } else { + [[NSColor colorWithDeviceWhite:0 alpha:kTwoThirdsAlpha] set]; + + NSRectFill(rect); + } } +- (void)animateCopy { + // This does a photocopy swipe to show folks that their copy has succceeded + // Store off a copy of our background + NSRect bounds = [self bounds]; + NSBitmapImageRep *rep = [self bitmapImageRepForCachingDisplayInRect:bounds]; + NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithBitmapImageRep:rep]; + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:context]; + [self drawRect:bounds]; + [NSGraphicsContext restoreGraphicsState]; + CIVector *extent = [CIVector vectorWithX:bounds.origin.x + Y:bounds.origin.y + Z:bounds.size.width + W:bounds.size.height]; + CIFilter *transition = [CIFilter filterWithName:@"CICopyMachineTransition"]; + [transition setDefaults]; + [transition setValue:extent + forKey:@"inputExtent"]; + CIImage *image = [[CIImage alloc] initWithBitmapImageRep:rep]; + + [transition setValue:image forKey:@"inputImage"]; + [transition setValue:image forKey:@"inputTargetImage"]; + [transition setValue:[NSNumber numberWithInt:0] + forKey:@"inputTime"]; + [transition valueForKey:@"outputImage"]; + [image release]; + transition_ = [transition retain]; + animation_ = [[GTMLargeTypeCopyAnimation alloc] initWithDuration:0.5 + animationCurve:NSAnimationLinear]; + [animation_ setFrameRate:0.0f]; + [animation_ setDelegate:self]; + [animation_ setAnimationBlockingMode:NSAnimationBlocking]; + [animation_ startAnimation]; +} + +- (void)animationDidEnd:(NSAnimation*)animation { + [animation_ release]; + animation_ = nil; + [transition_ release]; + transition_ = nil; + [self display]; +} + +- (float)animation:(NSAnimation*)animation + valueForProgress:(NSAnimationProgress)progress { + // This gives us half the copy animation, so we don't swing back + // Don't want too much gratuitous effect + // 0.6 is required by experimentation. 0.5 doesn't do it + return progress * 0.6f; +} +@end + +@implementation GTMLargeTypeCopyAnimation +- (void)setCurrentProgress:(NSAnimationProgress)progress { + [super setCurrentProgress:progress]; + [[self delegate] display]; +} @end diff --git a/AppKit/GTMLargeTypeWindowTest.m b/AppKit/GTMLargeTypeWindowTest.m index b4a9fe4..d9e56c2 100644 --- a/AppKit/GTMLargeTypeWindowTest.m +++ b/AppKit/GTMLargeTypeWindowTest.m @@ -20,6 +20,8 @@ #import "GTMLargeTypeWindow.h" #import "GTMNSObject+UnitTesting.h" #import "GTMUnitTestDevLog.h" +#import "GTMGarbageCollection.h" +#import "GTMSystemVersion.h" NSString *const kLongTextBlock = @"`Twas brillig, and the slithy toves " @@ -49,11 +51,31 @@ NSString *const kLongTextBlock = NSString *const kMediumTextBlock = @"For the Snark was a Boojum, you see."; +NSString *const kShortTextBlock = @"Short"; + @interface GTMLargeTypeWindowTest : GTMTestCase @end @implementation GTMLargeTypeWindowTest -- (void)testLargeTypeWindow { +- (BOOL)shouldDoAnimateCopy { + // NOTE: Animated copy tests are disabled when GC is on. + // See the comment/warning in the GTMLargeTypeWindow.h for more details, + // but we disable them to avoid the tests failing (crashing) when it's Apple's + // bug. Please bump the system check as appropriate when new systems are + // tested. Currently broken on 10.5.4 and below. + // Radar 6137322 CIFilter crashing when run with GC enabled + long major, minor, bugfix; + [GTMSystemVersion getMajor:&major minor:&minor bugFix:&bugfix]; + if (!(GTMIsGarbageCollectionEnabled() + && major <= 10 && minor <= 5 && bugfix <= 4)) { + return YES; + } else { + NSLog(@"--- animated copy not run because of GC incompatibilites ---"); + return NO; + } +} + +- (void)testLargeTypeWindowIllegalInits { [GTMUnitTestDevLog expectString:@"GTMLargeTypeWindow got an empty string"]; GTMLargeTypeWindow *window = [[[GTMLargeTypeWindow alloc] initWithString:@""] autorelease]; @@ -82,9 +104,11 @@ NSString *const kMediumTextBlock = @"For the Snark was a Boojum, you see."; [GTMUnitTestDevLog expectString:@"GTMLargeTypeWindow got an empty image"]; window = [[[GTMLargeTypeWindow alloc] initWithImage:nil] autorelease]; STAssertNil(window, nil); - - window = [[[GTMLargeTypeWindow alloc] - initWithString:kMediumTextBlock] autorelease]; +} + +- (void)testLargeTypeWindowMediumText { + GTMLargeTypeWindow *window = [[[GTMLargeTypeWindow alloc] + initWithString:kMediumTextBlock] autorelease]; STAssertNotNil(window, nil); STAssertTrue([window canBecomeKeyWindow], nil); [window makeKeyAndOrderFront:nil]; @@ -94,52 +118,80 @@ NSString *const kMediumTextBlock = @"For the Snark was a Boojum, you see."; GTMAssertObjectStateEqualToStateNamed(window, @"GTMLargeTypeWindowMediumTextTest", nil); - [window copy:nil]; - NSPasteboard *pb = [NSPasteboard generalPasteboard]; - NSString *pbString = [pb stringForType:NSStringPboardType]; - STAssertEqualObjects(pbString, kMediumTextBlock, nil); + if ([self shouldDoAnimateCopy]) { + [window copy:nil]; + NSPasteboard *pb = [NSPasteboard generalPasteboard]; + NSString *pbString = [pb stringForType:NSStringPboardType]; + STAssertEqualObjects(pbString, kMediumTextBlock, nil); + } [window keyDown:nil]; - - window = [[[GTMLargeTypeWindow alloc] initWithString:@"Short"] autorelease]; +} + +- (void)testLargeTypeWindowShortText { + GTMLargeTypeWindow *window = [[[GTMLargeTypeWindow alloc] + initWithString:kShortTextBlock] autorelease]; STAssertNotNil(window, nil); STAssertTrue([window canBecomeKeyWindow], nil); [window makeKeyAndOrderFront:nil]; - endDate = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime]; + NSDate *endDate + = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime]; [[NSRunLoop currentRunLoop] runUntilDate:endDate]; GTMAssertObjectStateEqualToStateNamed(window, @"GTMLargeTypeWindowShortTextTest", nil); - [window copy:nil]; - pbString = [pb stringForType:NSStringPboardType]; - STAssertEqualObjects(pbString, @"Short", nil); + if ([self shouldDoAnimateCopy]) { + [window copy:nil]; + NSPasteboard *pb = [NSPasteboard generalPasteboard]; + NSString *pbString = [pb stringForType:NSStringPboardType]; + STAssertEqualObjects(pbString, kShortTextBlock, nil); + } [window resignKeyWindow]; +} - window = [[[GTMLargeTypeWindow alloc] - initWithString:kLongTextBlock] autorelease]; +- (void)testLargeTypeWindowLongText { + GTMLargeTypeWindow *window = [[[GTMLargeTypeWindow alloc] + initWithString:kLongTextBlock] autorelease]; STAssertNotNil(window, nil); [window orderFront:nil]; - endDate = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime]; + NSDate *endDate + = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime]; [[NSRunLoop currentRunLoop] runUntilDate:endDate]; // Can't do state for long text as it will wrap differently on different // sized screens. GTMAssertObjectStateEqualToStateNamed(window, @"GTMLargeTypeWindowLongTextTest", nil); + if ([self shouldDoAnimateCopy]) { + [window copy:nil]; + NSPasteboard *pb = [NSPasteboard generalPasteboard]; + NSString *pbString = [pb stringForType:NSStringPboardType]; + STAssertEqualObjects(pbString, kLongTextBlock, nil); + } [window keyDown:nil]; - +} + +- (void)testLargeTypeWindowImageText { NSImage *image = [NSApp applicationIconImage]; - window = [[[GTMLargeTypeWindow alloc] initWithImage:image] autorelease]; + GTMLargeTypeWindow *window = [[[GTMLargeTypeWindow alloc] + initWithImage:image] autorelease]; STAssertNotNil(window, nil); [window makeKeyAndOrderFront:nil]; - endDate = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime]; + NSDate *endDate + = [NSDate dateWithTimeIntervalSinceNow:kGTMLargeTypeWindowFadeTime]; [[NSRunLoop currentRunLoop] runUntilDate:endDate]; GTMAssertObjectStateEqualToStateNamed(window, @"GTMLargeTypeWindowImageTest", nil); - [window copy:nil]; - // Pasteboard should not change for an image - pbString = [pb stringForType:NSStringPboardType]; - STAssertEqualObjects(pbString, @"Short", nil); + NSString *testString = @"TestString"; + NSPasteboard *pb = [NSPasteboard generalPasteboard]; + [pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:self]; + [pb setString:testString forType:NSStringPboardType]; + if ([self shouldDoAnimateCopy]) { + [window copy:nil]; + // Pasteboard should not change for an image + NSString *pbString = [pb stringForType:NSStringPboardType]; + STAssertEqualObjects(pbString, testString, nil); + } [window resignKeyWindow]; } diff --git a/AppKit/GTMLinearRGBShadingTest.m b/AppKit/GTMLinearRGBShadingTest.m index cb65572..d70b878 100644 --- a/AppKit/GTMLinearRGBShadingTest.m +++ b/AppKit/GTMLinearRGBShadingTest.m @@ -69,6 +69,24 @@ STAssertEqualsWithAccuracy(theColor[2], newValue, 0.001, nil); STAssertEqualsWithAccuracy(theColor[3], newValue, 0.001, nil); } + // Create a shading with 1 color to test that special handling + NSColor *purple = [NSColor purpleColor]; + NSColor *singleColor[1] = { purple }; + CGFloat singlePosition[1] = { 0.5 }; + theShading = + [GTMLinearRGBShading shadingWithColors:singleColor + fromSpaceNamed:NSCalibratedRGBColorSpace + atPositions:singlePosition + count:1]; + // test over a range to make sure we always get the same color + for (NSUInteger i = 0; i < kColorCount; i++) { + CGFloat newValue = kColorIncrement * i; + CGFloat *theColor = (CGFloat*)[theShading valueAtPosition:newValue]; + STAssertEqualsWithAccuracy(theColor[0], [purple redComponent], 0.001, nil); + STAssertEqualsWithAccuracy(theColor[1], [purple greenComponent], 0.001, nil); + STAssertEqualsWithAccuracy(theColor[2], [purple blueComponent], 0.001, nil); + STAssertEqualsWithAccuracy(theColor[3], [purple alphaComponent], 0.001, nil); + } } - (void)testShadeFunction { @@ -83,6 +101,7 @@ } - (void)testColorSpace { + // Calibrated RGB GTMLinearRGBShading *theShading = [GTMLinearRGBShading shadingWithColors:nil fromSpaceNamed:NSCalibratedRGBColorSpace @@ -91,5 +110,23 @@ CGColorSpaceRef theColorSpace = [theShading colorSpace]; STAssertNotNULL(theColorSpace, nil); STAssertEquals(CFGetTypeID(theColorSpace), CGColorSpaceGetTypeID(), nil); + + // Device RGB + theShading = + [GTMLinearRGBShading shadingWithColors:nil + fromSpaceNamed:NSDeviceRGBColorSpace + atPositions:nil + count:0]; + theColorSpace = [theShading colorSpace]; + STAssertNotNULL(theColorSpace, nil); + STAssertEquals(CFGetTypeID(theColorSpace), CGColorSpaceGetTypeID(), nil); + + // Device CMYK (not supported) + theShading = + [GTMLinearRGBShading shadingWithColors:nil + fromSpaceNamed:NSDeviceCMYKColorSpace + atPositions:nil + count:0]; + STAssertNULL(theShading, nil); } @end diff --git a/AppKit/GTMLoginItems.m b/AppKit/GTMLoginItems.m index 61a2120..1e59e70 100644 --- a/AppKit/GTMLoginItems.m +++ b/AppKit/GTMLoginItems.m @@ -57,22 +57,28 @@ NSString * const kGTMLoginItemsHiddenKey = @"Hide"; + (BOOL)compileAndRunScript:(NSString *)script withError:(NSError **)errorInfo { if ([script length] == 0) { + // COV_NF_START - no real way to test this if (errorInfo) *errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-90 userInfo:nil]; return NO; + // COV_NF_END } NSAppleScript *query = [[[NSAppleScript alloc] initWithSource:script] autorelease]; NSDictionary *errDict = nil; if ( ![query compileAndReturnError:&errDict]) { + // COV_NF_START - no real way to test this if (errorInfo) *errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-91 userInfo:errDict]; return NO; + // COV_NF_END } NSAppleEventDescriptor *scriptResult = [query executeAndReturnError:&errDict]; if (!scriptResult) { + // COV_NF_START - no real way to test this if (*errorInfo) *errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-92 userInfo:errDict]; return NO; + // COV_NF_END } // we don't process the result return YES; @@ -90,19 +96,23 @@ NSString * const kGTMLoginItemsHiddenKey = @"Hide"; NSString *querySource = @"tell application \"System Events\" to get properties of login items"; query = [[NSAppleScript alloc] initWithSource:querySource]; if ( ![query compileAndReturnError:&errDict]) { + // COV_NF_START - no real way to test this if (errorInfo) *errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-1 userInfo:errDict]; [query release]; query = nil; return nil; + // COV_NF_END } } // run the script NSAppleEventDescriptor *scriptResult = [query executeAndReturnError:&errDict]; if (!scriptResult) { + // COV_NF_START - no real way to test this if (*errorInfo) *errorInfo = [NSError errorWithDomain:@"GTMLoginItems" code:-2 userInfo:errDict]; return nil; + // COV_NF_END } // build our results NSMutableArray *result = [NSMutableArray array]; diff --git a/AppKit/GTMLoginItemsTest.m b/AppKit/GTMLoginItemsTest.m index ec08a85..980f772 100644 --- a/AppKit/GTMLoginItemsTest.m +++ b/AppKit/GTMLoginItemsTest.m @@ -23,14 +23,12 @@ // we don't really run this test because if someone had it in some automated // tests, then if something did fail, it could leave things in the login items // on the computer which could be a nasty surprise. -#define TESTS_ENABLED 0 +#define MODIFICATION_TESTS_ENABLED 0 @interface GTMLoginItemsTest : GTMTestCase @end -#if TESTS_ENABLED - static BOOL ItemsListHasPath(NSArray *items, NSString *path) { NSDictionary *item = nil; NSEnumerator *itemsEnum = [items objectEnumerator]; @@ -43,14 +41,42 @@ static BOOL ItemsListHasPath(NSArray *items, NSString *path) { return NO; } -#endif // TESTS_ENABLED - @implementation GTMLoginItemsTest -- (void)testGTMLoginItems { +- (void)testNoModification { -#if TESTS_ENABLED + NSError *error = nil; + NSString *bogusAppPath = @"/Applications/AppThatDoesNotExist.app"; + NSString *bogusAppName = @"AppThatDoesNotExist"; + + // fetch the starting values + NSArray *initialItems = [GTMLoginItems loginItems:&error]; + STAssertNotNil(initialItems, @"shouldn't be nil (%@)", error); + STAssertFalse(ItemsListHasPath(initialItems, bogusAppPath), + @"bogusApp shouldn't be in list to start for test (%@)", initialItems); + + // check by path + STAssertFalse([GTMLoginItems pathInLoginItems:bogusAppPath], nil); + + // check by name + STAssertFalse([GTMLoginItems itemWithNameInLoginItems:bogusAppName], nil); + + // remove it by path + [GTMLoginItems removePathFromLoginItems:bogusAppPath]; + NSArray *curItems = [GTMLoginItems loginItems:nil]; + STAssertEqualObjects(initialItems, curItems, nil); + + // remove it by name + [GTMLoginItems removeItemWithNameFromLoginItems:bogusAppName]; + curItems = [GTMLoginItems loginItems:nil]; + STAssertEqualObjects(initialItems, curItems, nil); + +} +- (void)testModification { + +#if MODIFICATION_TESTS_ENABLED + NSError *error = nil; NSString *textEditPath = @"/Applications/TextEdit.app"; NSString *textEditName = @"TextEdit"; @@ -79,7 +105,7 @@ static BOOL ItemsListHasPath(NSArray *items, NSString *path) { // check by path STAssertFalse([GTMLoginItems pathInLoginItems:textEditPath], nil); - + // check by name STAssertFalse([GTMLoginItems itemWithNameInLoginItems:textEditName], nil); @@ -105,8 +131,8 @@ static BOOL ItemsListHasPath(NSArray *items, NSString *path) { // check by name STAssertFalse([GTMLoginItems itemWithNameInLoginItems:textEditName], nil); -#endif // TESTS_ENABLED - +#endif // MODIFICATION_TESTS_ENABLED + } @end diff --git a/AppKit/GTMNSBezierPath+CGPath.m b/AppKit/GTMNSBezierPath+CGPath.m index 3bc6de9..656a139 100644 --- a/AppKit/GTMNSBezierPath+CGPath.m +++ b/AppKit/GTMNSBezierPath+CGPath.m @@ -58,9 +58,9 @@ case NSClosePathBezierPathElement: CGPathCloseSubpath(thePath); break; - default: + default: // COV_NF_START _GTMDevLog(@"Unknown element at [NSBezierPath (GTMBezierPathCGPathAdditions) cgPath]"); - break; + break; // COV_NF_END }; } return thePath; diff --git a/AppKit/GTMNSBezierPath+RoundRectTest.m b/AppKit/GTMNSBezierPath+RoundRectTest.m index ad64fd4..5bdf3a3 100644 --- a/AppKit/GTMNSBezierPath+RoundRectTest.m +++ b/AppKit/GTMNSBezierPath+RoundRectTest.m @@ -1,5 +1,5 @@ // -// NSBezierPath+RoundRectTest.m +// GTMNSBezierPath+RoundRectTest.m // // Copyright 2006-2008 Google Inc. // @@ -28,7 +28,7 @@ @implementation GTMNSBezierPath_RoundRectTest - (void)testRoundRects { - GTMAssertDrawingEqualToImageNamed(self, NSMakeSize(330, 430), + GTMAssertDrawingEqualToImageNamed(self, NSMakeSize(490, 430), @"GTMNSBezierPath+RoundRectTest", nil, nil); } @@ -39,7 +39,8 @@ NSMakeRect(50.0, 10.0, 30.0, 30.0), //Square Test NSMakeRect(100.0, 10.0, 1.0, 2.0), //Small Test NSMakeRect(120.0, 10.0, 15.0, 20.0), //Medium Test - NSMakeRect(140.0, 10.0, 150.0, 30.0) //Large Test + NSMakeRect(140.0, 10.0, 150.0, 30.0), //Large Test + NSMakeRect(300.0, 10.0, 150.0, 30.0) //Large Test 2 (for different radius) }; const NSUInteger theRectCount = sizeof(theRects) / sizeof(NSRect); @@ -50,8 +51,9 @@ for (i = 0; i < theLineWidthCount; ++i) { for (j = 0; j < theRectCount; ++j) { + CGFloat cornerRadius = ( (j < (theRectCount - 1)) ? 20.0 : 0.0 ); NSBezierPath *roundRect = [NSBezierPath gtm_bezierPathWithRoundRect:theRects[j] - cornerRadius:20.0]; + cornerRadius:cornerRadius]; [roundRect setLineWidth: theLineWidths[i]]; [roundRect stroke]; CGFloat newWidth = 35.0; @@ -71,8 +73,9 @@ for (i = 0; i < theColorCount; ++i) { for (j = 0; j < theRectCount; ++j) { + CGFloat cornerRadius = ( (j < (theRectCount - 1)) ? 10.0 : 0.0 ); NSBezierPath *roundRect = [NSBezierPath gtm_bezierPathWithRoundRect:theRects[j] - cornerRadius:10.0]; + cornerRadius:cornerRadius]; [theColors[i] setFill]; [roundRect fill]; theRects[j].origin.y += 35.0; @@ -85,8 +88,9 @@ for (i = 0; i < theFlatnessCount; i++) { for (j = 0; j < theRectCount; ++j) { + CGFloat cornerRadius = ( (j < (theRectCount - 1)) ? 6.0 : 0.0 ); NSBezierPath *roundRect = [NSBezierPath gtm_bezierPathWithRoundRect:theRects[j] - cornerRadius:6.0]; + cornerRadius:cornerRadius]; [roundRect setFlatness:theFlatness[i]]; [roundRect stroke]; theRects[j].origin.y += 35.0; diff --git a/AppKit/GTMNSBezierPath+ShadingTest.m b/AppKit/GTMNSBezierPath+ShadingTest.m index 5634cf3..a9dfbef 100644 --- a/AppKit/GTMNSBezierPath+ShadingTest.m +++ b/AppKit/GTMNSBezierPath+ShadingTest.m @@ -31,7 +31,7 @@ - (void)testShadings { GTMAssertDrawingEqualToImageNamed(self, - NSMakeSize(200, 200), + NSMakeSize(310, 410), @"GTMNSBezierPath+ShadingTest", nil, nil); } @@ -50,7 +50,7 @@ count:sizeof(theFloatArray)/sizeof(CGFloat)]; NSBezierPath *shadedPath; - // axialStrokeRect test + // axial stroke rect - diagonal fill NSRect axialStrokeRect = NSMakeRect(10.0f, 10.0f, 90.0f, 90.0f); shadedPath = [NSBezierPath bezierPathWithRect:axialStrokeRect]; [shadedPath setLineWidth: 10.0f]; @@ -59,8 +59,28 @@ NSPoint endPoint = NSMakePoint(axialStrokeRect.origin.x + axialStrokeRect.size.width - 20.0f, axialStrokeRect.origin.y + axialStrokeRect.size.height - 20.0f); [shadedPath gtm_strokeAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading]; + + // axial stroke rect - v line fill + axialStrokeRect = NSMakeRect(110.0f, 10.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:axialStrokeRect]; + [shadedPath setLineWidth: 10.0f]; + startPoint = NSMakePoint(axialStrokeRect.origin.x + axialStrokeRect.size.width / 2.0f, + axialStrokeRect.origin.y + 20.0f); + endPoint = NSMakePoint(axialStrokeRect.origin.x + axialStrokeRect.size.width / 2.0f, + axialStrokeRect.origin.y + axialStrokeRect.size.height - 20.0f); + [shadedPath gtm_strokeAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading]; + + // axial stroke rect - h line fill + axialStrokeRect = NSMakeRect(210.0f, 10.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:axialStrokeRect]; + [shadedPath setLineWidth: 10.0f]; + startPoint = NSMakePoint(axialStrokeRect.origin.x + 20.0f, + axialStrokeRect.origin.y + axialStrokeRect.size.height / 2.0f); + endPoint = NSMakePoint(axialStrokeRect.origin.x + axialStrokeRect.size.width - 20.0f, + axialStrokeRect.origin.y + axialStrokeRect.size.height / 2.0f); + [shadedPath gtm_strokeAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading]; - // axial fill + // axial fill rect - diagonal fill NSRect axialFillRect = NSMakeRect(10.0f, 110.0f, 90.0f, 90.0f); shadedPath = [NSBezierPath bezierPathWithRect:axialFillRect]; startPoint = NSMakePoint(axialFillRect.origin.x + 20.0f, @@ -69,8 +89,26 @@ axialFillRect.origin.y + axialFillRect.size.height - 20.0f); [shadedPath gtm_fillAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading]; - // radial stroke - NSRect radialStrokeRect = NSMakeRect(110.0f, 110.0f, 90.0f, 90.0f); + // axial fill rect - v line fill + axialFillRect = NSMakeRect(110.0f, 110.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:axialFillRect]; + startPoint = NSMakePoint(axialFillRect.origin.x + axialFillRect.size.width / 2.0f, + axialFillRect.origin.y + 20.0f); + endPoint = NSMakePoint(axialFillRect.origin.x + axialFillRect.size.width / 2.0f, + axialFillRect.origin.y + axialFillRect.size.height - 20.0f); + [shadedPath gtm_fillAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading]; + + // axial fill rect - h line fill + axialFillRect = NSMakeRect(210.0f, 110.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:axialFillRect]; + startPoint = NSMakePoint(axialFillRect.origin.x + 20.0f, + axialFillRect.origin.y + axialFillRect.size.height / 2.0f); + endPoint = NSMakePoint(axialFillRect.origin.x + axialFillRect.size.width - 20.0f, + axialFillRect.origin.y + axialFillRect.size.height / 2.0f); + [shadedPath gtm_fillAxiallyFrom:startPoint to:endPoint extendingStart:YES extendingEnd:YES shading:shading]; + + // radial stroke rect - diagonal fill + NSRect radialStrokeRect = NSMakeRect(10.0f, 210.0f, 90.0f, 90.0f); shadedPath = [NSBezierPath bezierPathWithRect:radialStrokeRect]; startPoint = NSMakePoint(radialStrokeRect.origin.x + 20.0f, radialStrokeRect.origin.y + 20.0f); @@ -80,8 +118,30 @@ to:endPoint toRadius:20.0f extendingStart:YES extendingEnd:YES shading:shading]; - // radial fill - NSRect radialFillRect = NSMakeRect(110.0f, 10.0f, 90.0f, 90.0f); + // radial stroke rect - v line fill + radialStrokeRect = NSMakeRect(110.0f, 210.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:radialStrokeRect]; + startPoint = NSMakePoint(radialStrokeRect.origin.x + radialStrokeRect.size.width / 2.0f, + radialStrokeRect.origin.y + 20.0f); + endPoint = NSMakePoint(radialStrokeRect.origin.x + radialStrokeRect.size.width / 2.0f, + radialStrokeRect.origin.y + radialStrokeRect.size.height - 20.0f); + [shadedPath gtm_strokeRadiallyFrom:startPoint fromRadius:60.0f + to:endPoint toRadius:20.0f + extendingStart:YES extendingEnd:YES shading:shading]; + + // radial stroke rect - h line fill + radialStrokeRect = NSMakeRect(210.0f, 210.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:radialStrokeRect]; + startPoint = NSMakePoint(radialStrokeRect.origin.x + 20.0f, + radialStrokeRect.origin.y + radialStrokeRect.size.height / 2.0f); + endPoint = NSMakePoint(radialStrokeRect.origin.x + radialStrokeRect.size.width - 20.0f, + radialStrokeRect.origin.y + radialStrokeRect.size.height / 2.0f); + [shadedPath gtm_strokeRadiallyFrom:startPoint fromRadius:60.0f + to:endPoint toRadius:20.0f + extendingStart:YES extendingEnd:YES shading:shading]; + + // radial fill rect - diagonal fill + NSRect radialFillRect = NSMakeRect(10.0f, 310.0f, 90.0f, 90.0f); shadedPath = [NSBezierPath bezierPathWithRect:radialFillRect]; startPoint = NSMakePoint(radialFillRect.origin.x + 20.0f, radialFillRect.origin.y + 20.0f); @@ -90,6 +150,28 @@ [shadedPath gtm_fillRadiallyFrom:startPoint fromRadius:10.0f to:endPoint toRadius:20.0f extendingStart:YES extendingEnd:YES shading:shading]; + + // radial fill rect - v line fill + radialFillRect = NSMakeRect(110.0f, 310.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:radialFillRect]; + startPoint = NSMakePoint(radialFillRect.origin.x + radialFillRect.size.width / 2.0f, + radialFillRect.origin.y + 20.0f); + endPoint = NSMakePoint(radialFillRect.origin.x + radialFillRect.size.width / 2.0f, + radialFillRect.origin.y + radialFillRect.size.height - 20.0f); + [shadedPath gtm_fillRadiallyFrom:startPoint fromRadius:10.0f + to:endPoint toRadius:20.0f + extendingStart:YES extendingEnd:YES shading:shading]; + + // radial fill rect - h line fill + radialFillRect = NSMakeRect(210.0f, 310.0f, 90.0f, 90.0f); + shadedPath = [NSBezierPath bezierPathWithRect:radialFillRect]; + startPoint = NSMakePoint(radialFillRect.origin.x + 20.0f, + radialFillRect.origin.y + radialFillRect.size.height / 2.0f); + endPoint = NSMakePoint(radialFillRect.origin.x + radialFillRect.size.width - 20.0f, + radialFillRect.origin.y + radialFillRect.size.height / 2.0f); + [shadedPath gtm_fillRadiallyFrom:startPoint fromRadius:10.0f + to:endPoint toRadius:20.0f + extendingStart:YES extendingEnd:YES shading:shading]; } @end diff --git a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.ppc64.tiff b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.ppc64.tiff Binary files differindex a4df8f8..ef22b6b 100644 --- a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.ppc64.tiff +++ b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.ppc64.tiff diff --git a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.tiff b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.tiff Binary files differindex c41ab04..b165acf 100644 --- a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.tiff +++ b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.tiff diff --git a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.x86_64.tiff b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.x86_64.tiff Binary files differindex a4df8f8..ef22b6b 100644 --- a/AppKit/TestData/GTMNSBezierPath+RoundRectTest.x86_64.tiff +++ b/AppKit/TestData/GTMNSBezierPath+RoundRectTest.x86_64.tiff diff --git a/AppKit/TestData/GTMNSBezierPath+ShadingTest.10.5.tiff b/AppKit/TestData/GTMNSBezierPath+ShadingTest.10.5.tiff Binary files differindex 040cb0d..b44b5bf 100644 --- a/AppKit/TestData/GTMNSBezierPath+ShadingTest.10.5.tiff +++ b/AppKit/TestData/GTMNSBezierPath+ShadingTest.10.5.tiff |