Why are my quartz arcs thicker than straight lines?

I am trying to create a custom UIButton that should look like UIButtonTypeRoundedRect. In my drawRect :, I create a path with the first call to CGContextMoveToPoint (), and then four calls to CGContextAddArc (). Then I will stroke the path. However, in the resulting image, the four rounded corners are obviously thicker than the rest of the path.

I suspected that this had something to do with anti-aliasing, so I tried to disable it using CGContextSetShouldAntiAlias ​​(), but then it looked even worse. I also tried to experiment with line widths, but arcs are always thicker than straight lines. Apple's UIButtonTypeRoundedRect looks great, so it can be solved somehow. Somebody knows?

Edit: corresponding code:

CGContextRef context = UIGraphicsGetCurrentContext(); CGContextBeginPath(context); CGContextMoveToPoint(context, rect.origin.x + kRoundedRectButtonRadius, rect.origin.y); CGContextAddArc(context, rect.origin.x + rect.size.width - kRoundedRectButtonRadius, rect.origin.y + kRoundedRectButtonRadius, kRoundedRectButtonRadius, 3 * M_PI_2, 0, NO); CGContextAddArc(context, rect.origin.x + rect.size.width - kRoundedRectButtonRadius, rect.origin.y + rect.size.height - kRoundedRectButtonRadius, kRoundedRectButtonRadius, 0, M_PI_2, NO); CGContextAddArc(context, rect.origin.x + kRoundedRectButtonRadius, rect.origin.y + rect.size.height - kRoundedRectButtonRadius, kRoundedRectButtonRadius, M_PI_2, M_PI, NO); CGContextAddArc(context, rect.origin.x + kRoundedRectButtonRadius, rect.origin.y + kRoundedRectButtonRadius, kRoundedRectButtonRadius, M_PI, 3 * M_PI_2, NO); CGContextClosePath(context); CGContextSetLineWidth(context, 1.7); CGContextStrokePath(context); 
+4
source share
1 answer

I already came across this when creating custom buttons. The behavior you see is related to the fact that cocoa drawing procedures draw lines centered around the pixel positions that you ask for them. Let me explain.

The straight lines you draw fall to the very edge of the button's rectangle. When the drawing procedure is called, cocoa is convenient to set the clipping area to the exact border of the button's rectangle, but when you ask cocoa to draw a line along the edge, exactly half of the line is drawn outside the clipping rectangle.

You noticed a difference in the rounded corners, because the curved part completely fell into the cut-off rectangle, so none of them are cut off.

Now for the solution:

Suppose the lines you draw are exactly two pixels. This would mean that one pixel is drawn inside the clipping rectangle, and one is drawn out (and therefore ignored). All you have to do is draw lines one pixel closer to the center of the rectangle. In the case of a custom drawing procedure, you probably use:

 NSRect myBounds = [self bounds]; 

And then calculate your corner points from there. Insead, use:

 NSRect myProperBounds = NSInsetRect([self bounds], 1.0, 1.0); 

And you should be good to go.

+11
source

All Articles