Returned path is refcounted, so you'll need toCFRelease
when done.- (CGPathRef) newPathForRoundRect: (CGRect) rect radius: (CGFloat) radius strokeWidth: (CGFloat) strokeWidth { // Fit the stroked path inside the rectangle. rect.size.height -= strokeWidth; rect.size.width -= strokeWidth; rect.origin.x += strokeWidth / 2.0; rect.origin.y += strokeWidth / 2.0; CGMutablePathRef path = CGPathCreateMutable(); // The inner rect size gives us X/Y/W/H values for the parts of the rect // that aren't on the curve. CGRect innerRect = CGRectInset(rect, radius, radius); CGFloat insideRight = innerRect.origin.x + innerRect.size.width; CGFloat outsideRight = rect.origin.x + rect.size.width; CGFloat insideBottom = innerRect.origin.y + innerRect.size.height; CGFloat outsideBottom = rect.origin.y + rect.size.height; CGFloat insideTop = innerRect.origin.y; CGFloat outsideTop = rect.origin.y; CGFloat outsideLeft = rect.origin.x; CGPathMoveToPoint (path, NULL, innerRect.origin.x, outsideTop); CGPathAddLineToPoint (path, NULL, insideRight, outsideTop); CGPathAddArcToPoint (path, NULL, outsideRight, outsideTop, outsideRight, insideTop, radius); CGPathAddLineToPoint (path, NULL, outsideRight, insideBottom); CGPathAddArcToPoint (path, NULL, outsideRight, outsideBottom, insideRight, outsideBottom, radius); CGPathAddLineToPoint (path, NULL, innerRect.origin.x, outsideBottom); CGPathAddArcToPoint (path, NULL, outsideLeft, outsideBottom, outsideLeft, insideBottom, radius); CGPathAddLineToPoint (path, NULL, outsideLeft, insideTop); CGPathAddArcToPoint (path, NULL, outsideLeft, outsideTop, innerRect.origin.x, outsideTop, radius); CGPathCloseSubpath (path); return path; } // newPathForRoundRectIf you're not in CGLand (or not needing the same code to work on the desktop and device), there's also UIBezierPath's-bezierPathWithRoundedRect:cornerRadius:
(for all corners), and-bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:
(for some arbitrary subset of corners), and NSBezierPath's-bezierPathWithRoundedRect:xRadius:yRadius:
. Muchos Thankos to Paul Collins for the reminder.