Adding a reflection to an NSImage

To add an reflection in Cocoa to a NSImage object you can use the following NSImage category:

@interface NSImage(MKAddReflection)
- (NSImage*) addReflection:(CGFloat)percentage;
@end

@implementation NSImage(MKAddReflection)

- (NSImage*) addReflection:(CGFloat)percentage
{
	NSAssert(percentage > 0 && percentage <= 1.0, @"Please use percentage between 0 and 1");
	CGRect offscreenFrame = CGRectMake(0, 0, self.size.width, self.size.height*(1.0+percentage));
	NSBitmapImageRep * offscreen = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
														pixelsWide:offscreenFrame.size.width
														pixelsHigh:offscreenFrame.size.height
													 bitsPerSample:8
												   samplesPerPixel:4 
														  hasAlpha:YES
														  isPlanar:NO 
													colorSpaceName:NSDeviceRGBColorSpace
													  bitmapFormat:0
													   bytesPerRow:offscreenFrame.size.width * 4
													  bitsPerPixel:32];
	
	[NSGraphicsContext saveGraphicsState];
	[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreen]];
	
	[[NSColor clearColor] set];
	NSRectFill(offscreenFrame);
	
	NSGradient * fade = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithCalibratedWhite:1.0 alpha:0.2] endingColor:[NSColor clearColor]];
	CGRect fadeFrame = CGRectMake(0, 0, self.size.width, offscreen.size.height - self.size.height);
	[fade drawInRect:fadeFrame angle:270.0];	
	
    NSAffineTransform* transform = [NSAffineTransform transform];
    [transform translateXBy:0.0 yBy:fadeFrame.size.height];
    [transform scaleXBy:1.0 yBy:-1.0];
    [transform concat];
	
	// Draw the image over the gradient -> becomes reflection
	[self drawAtPoint:NSMakePoint(0, 0) fromRect:CGRectMake(0, 0, self.size.width, self.size.height) operation:NSCompositeSourceIn fraction:1.0];
	
	[transform invert];
	[transform concat];

	// Draw the original image
	[self drawAtPoint:CGPointMake(0, offscreenFrame.size.height - self.size.height) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
	
	[NSGraphicsContext restoreGraphicsState];
	
	NSImage * imageWithReflection = [[NSImage alloc] initWithSize:offscreenFrame.size];
	[imageWithReflection addRepresentation:offscreen];
	
	return imageWithReflection;
}

To get a copy of a NSImage with a reflection applied you call [image addReflection:0.3], where the float value defines the percentage of the reflection regarding the height of the input image, e.g.

NSImage * input = [[NSImage alloc] initWithContentsOfFile:@"/Users/mk/Desktop/input.jpg"];
NSImage * output = [input addReflection:0.4];

Advertisements

Kerning comparison OSX – Windows – TLF

I did some tests comparing the same text on OS X with the TextEdit, on Windows XP with WordPad and on OS X in Safari on the Adobe Text Layout Framework demo site. I used everywhere Times New Roman as the font and a font size of 28.
Although Windows does not use kerning the text looks almost the same with some pixel difference. Have a look for yourself:
Comparing a text on OSX, Windows XP and TLF

Howto retrieve the current language for Mac OS X

I have a client who needs localizations for several languages. To retrieve the current language I used

NSString * localeString = [[NSLocale currentLocale] localeIdentifier];
NSString * language = [[[localeString componentsSeparatedByString:@"_"] objectAtIndex:0] uppercaseString];

Most of the time the content of localeString represented the settings in the system preference pane. But if I set English as the first language and Finland as the region in Formats it returns “fi_FI” as the localeString, but uses the Finnish nib files.

Preference pane Language

Preference pange Formats

To get the languages in the order from the preference pane “Language” one has to use the following code:

NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
NSArray* languages = [defs objectForKey:@"AppleLanguages"];
NSString* language = [[languages objectAtIndex:0] uppercaseString];

The variable language contains now “EN” as expected.