Skip to content

Instantly share code, notes, and snippets.

@jordanekay
Last active October 7, 2015 17:01
Show Gist options
  • Save jordanekay/3556830428f56e4850ea to your computer and use it in GitHub Desktop.
Save jordanekay/3556830428f56e4850ea to your computer and use it in GitHub Desktop.
Replacement implementation of round-rect UIBezierPaths
import Darwin
private typealias Point = (x: CGFloat, y: CGFloat)
private typealias Points = (Point, Point?)
extension UIBezierPath {
public convenience init(rect: CGRect, cornerRadius radius: CGFloat, roundedCorners: UIRectCorner = .AllCorners) {
self.init()
let path = Path(rect: rect, radius: radius, roundedCorners: roundedCorners)
drawPath(path)
}
}
private enum Corner: Int {
case BottomRight
case BottomLeft
case TopLeft
case TopRight
var startAngle: CGFloat {
return CGFloat(Double(rawValue) * M_PI_2)
}
var endAngle: CGFloat {
return startAngle + CGFloat(M_PI_2)
}
var rectCorner: UIRectCorner {
switch self {
case .TopLeft: return .TopLeft
case .TopRight: return .TopRight
case .BottomRight: return .BottomRight
case .BottomLeft: return .BottomLeft
}
}
}
private struct Path {
let rect: CGRect
let radius: CGFloat
let roundedCorners: UIRectCorner
func pointsForCorner(corner: Corner) -> (CGPoint, CGPoint?) {
let points: Points
let minX = CGRectGetMinX(rect)
let minY = CGRectGetMinY(rect)
let maxX = CGRectGetMaxX(rect)
let maxY = CGRectGetMaxY(rect)
let rounded = roundedCorners.contains(corner.rectCorner)
switch corner {
case .TopLeft:
points = rounded ? ((minX, minY + radius), (minX + radius, minY + radius)) : ((minX, minY), nil) as Points
case .TopRight:
points = rounded ? ((maxX - radius, minY), (maxX - radius, minY + radius)) : ((maxX, minY), nil) as Points
case .BottomRight:
points = rounded ? ((maxX, maxY - radius), (maxX - radius, maxY - radius)) : ((maxX, maxY), nil) as Points
case .BottomLeft:
points = rounded ? ((minX + radius, maxY), (minX + radius, maxY - radius)) : ((minX, maxY), nil) as Points
}
let mapping = { CGPoint(x: ($0 as Point).x, y: $0.y) }
return (mapping(points.0), points.1.map(mapping))
}
}
private extension UIBezierPath {
func drawPath(path: Path) {
let (start, _) = path.pointsForCorner(.TopLeft)
moveToPoint(start)
for corner: Corner in [.TopLeft, .TopRight, .BottomRight, .BottomLeft] {
let points = path.pointsForCorner(corner)
addLineToPoint(points.0)
if let center = points.1 {
addArcWithCenter(center, radius: path.radius, startAngle: corner.startAngle, endAngle: corner.endAngle, clockwise: true)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment