views:

283

answers:

2

I am trying to create a NSImage or NSImageCell with rounded corners inside a NSTableView. I can't get anything to work. Here is the best I have so far inside my custom NSCell:

- (void)drawInteriorWithFrame:(NSRect)frame inView:(NSView *)controlView { 
  if (thumbnailLink) {
 NSURL *url = [NSURL URLWithString:thumbnailLink];
 if (url) {
  NSRect imageFrame = [self _imageFrameForInteriorFrame:frame];
  NSImage *image = [[NSImage alloc] initWithContentsOfURL:url];
  [image setScalesWhenResized:YES];
  [image setSize:NSMakeSize(IMAGE_HEIGHT, IMAGE_WIDTH)];

  [NSGraphicsContext saveGraphicsState];
  imageFrame = NSInsetRect(imageFrame, 1, 1);
  NSBezierPath *clipPath = [NSBezierPath bezierPathWithRoundedRect:imageFrame cornerRadius:5.0];
  [clipPath setWindingRule:NSEvenOddWindingRule];
  [clipPath addClip];
  [NSGraphicsContext restoreGraphicsState]; 
  [image drawInRect:imageFrame fromRect:NSMakeRect(0, 0, 0, 0) operation:NSCompositeSourceIn fraction:1.0];
  [image release];
 }
}
...

Any ideas on how to this?

+4  A: 

You need to keep the clip set when drawing your image, and restore the context after instead. Also I don't think you want to be using "in" compositing but rather "over" if you just want to draw your image normally without taking the destination opacity in consideration. Try something like:

[NSGraphicsContext saveGraphicsState];

NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:imageFrame
                                                     xRadius:5
                                                     yRadius:5];
[path addClip];

[image drawInRect:imageFrame
         fromRect:NSZeroRect
        operation:NSCompositeSourceOver
         fraction:1.0];

[NSGraphicsContext restoreGraphicsState];
Rhult
Thanks so much!
John Wright
+1  A: 

Just to provide a bit more info on what you did wrong:

The purpose of saving and restoring the gstate is to be able to undo your changes to the gstate. In your case, restoring the gsave after clipping undid the clip. That's why the solution (as explained by Rhult) is to draw what you want clipped before you restore the gstate.

Peter Hosey