Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSBezierPath drawing

I want to do a rounded rectangle outline on an NSImage and I figured that using NSBezierPath would be the best way. However, I ran into a problem: instead of drawing a nice curve, I get this:

enter image description here

For reasons I can't understand, NSBezierPath is drawing the rounded part with a darker color than the rest.

Here's the code I'm using (inside a drawRect: call on a custom view):

NSBezierPath* bp = [NSBezierPath bezierPathWithRoundedRect: self.bounds xRadius: 5 yRadius: 5];
[[[NSColor blackColor] colorWithAlphaComponent: 0.5] setStroke];
[bp stroke];

Any ideas?

Edit:

If I inset the path by 0.5 everything draws just fine. But why is it that I get this when I offset the path by 10 pixels (for example)?

enter image description here

If I understand correctly, it should draw a thin line as well...

like image 542
Alex Avatar asked Dec 02 '12 21:12

Alex


1 Answers

Many rendering systems are derived from the PostScript drawing model. Core Graphics is one of these derivative systems. (Here are some others: PDF, SVG, the HTML Canvas 2D Context, Cairo.)

All of these systems have the idea of stroking a path with a line of some fixed width. When you stroke the path, the line straddles the path: half of the line's width is on one side of the path, and half of the line's width is on the other side. Here's a diagram that may make this clearer:

path stroke

Now, what happens when you stroke a path that lies along the boundary of your view? Half of the stroke will fall outside of your view's bounds and be clipped away - not drawn. You will only see the half of the stroke that falls inside the view's bounds.

When you use a rounded corner, that corner pulls away from the view's boundary, toward its center, so more of the stroke around the corner falls inside the view's boundary. So the stroke appears to get thicker around the rounded corner, like this:

path stroke clipped

To fix this, you need to inset your path by half the line width, so that the entire stroke falls inside your view's bounds along the entire path. The default line width is 1.0, so:

NSBezierPath* bp = [NSBezierPath bezierPathWithRoundedRect:
    NSRectInset(self.bounds, 0.5, 0.5) xRadius:5 yRadius:5];
like image 90
rob mayoff Avatar answered Oct 27 '22 22:10

rob mayoff