mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
131 lines
5.0 KiB
Swift
131 lines
5.0 KiB
Swift
import Foundation
|
|
import UIKit
|
|
|
|
public func generateRoundedRectWithTailPath(rectSize: CGSize, cornerRadius: CGFloat? = nil, tailSize: CGSize = CGSize(width: 20.0, height: 9.0), tailRadius: CGFloat = 4.0, tailPosition: CGFloat? = 0.5, transformTail: Bool = true) -> UIBezierPath {
|
|
let cornerRadius: CGFloat = cornerRadius ?? rectSize.height / 2.0
|
|
let tailWidth: CGFloat = tailSize.width
|
|
let tailHeight: CGFloat = tailSize.height
|
|
|
|
let rect = CGRect(origin: CGPoint(x: 0.0, y: tailHeight), size: rectSize)
|
|
|
|
guard let tailPosition else {
|
|
return UIBezierPath(cgPath: CGPath(roundedRect: rect, cornerWidth: cornerRadius, cornerHeight: cornerRadius, transform: nil))
|
|
}
|
|
|
|
let cutoff: CGFloat = 0.27
|
|
|
|
let path = UIBezierPath()
|
|
path.move(to: CGPoint(x: rect.minX, y: rect.minY + cornerRadius))
|
|
|
|
var leftArcEndAngle: CGFloat = .pi / 2.0
|
|
var leftConnectionArcRadius = tailRadius
|
|
var tailLeftHalfWidth: CGFloat = tailWidth / 2.0
|
|
var tailLeftArcStartAngle: CGFloat = -.pi / 4.0
|
|
var tailLeftHalfRadius = tailRadius
|
|
|
|
var rightArcStartAngle: CGFloat = -.pi / 2.0
|
|
var rightConnectionArcRadius = tailRadius
|
|
var tailRightHalfWidth: CGFloat = tailWidth / 2.0
|
|
var tailRightArcStartAngle: CGFloat = .pi / 4.0
|
|
var tailRightHalfRadius = tailRadius
|
|
|
|
if transformTail {
|
|
if tailPosition < 0.5 {
|
|
let fraction = max(0.0, tailPosition - 0.15) / 0.35
|
|
leftArcEndAngle *= fraction
|
|
|
|
let connectionFraction = max(0.0, tailPosition - 0.35) / 0.15
|
|
leftConnectionArcRadius *= connectionFraction
|
|
|
|
if tailPosition < cutoff {
|
|
let fraction = tailPosition / cutoff
|
|
tailLeftHalfWidth *= fraction
|
|
tailLeftArcStartAngle *= fraction
|
|
tailLeftHalfRadius *= fraction
|
|
}
|
|
} else if tailPosition > 0.5 {
|
|
let tailPosition = 1.0 - tailPosition
|
|
let fraction = max(0.0, tailPosition - 0.15) / 0.35
|
|
rightArcStartAngle *= fraction
|
|
|
|
let connectionFraction = max(0.0, tailPosition - 0.35) / 0.15
|
|
rightConnectionArcRadius *= connectionFraction
|
|
|
|
if tailPosition < cutoff {
|
|
let fraction = tailPosition / cutoff
|
|
tailRightHalfWidth *= fraction
|
|
tailRightArcStartAngle *= fraction
|
|
tailRightHalfRadius *= fraction
|
|
}
|
|
}
|
|
}
|
|
|
|
path.addArc(
|
|
withCenter: CGPoint(x: rect.minX + cornerRadius, y: rect.minY + cornerRadius),
|
|
radius: cornerRadius,
|
|
startAngle: .pi,
|
|
endAngle: .pi + max(0.0001, leftArcEndAngle),
|
|
clockwise: true
|
|
)
|
|
|
|
let leftArrowStart = max(rect.minX, rect.minX + rectSize.width * tailPosition - tailLeftHalfWidth - leftConnectionArcRadius)
|
|
path.addArc(
|
|
withCenter: CGPoint(x: leftArrowStart, y: rect.minY - leftConnectionArcRadius),
|
|
radius: leftConnectionArcRadius,
|
|
startAngle: .pi / 2.0,
|
|
endAngle: .pi / 4.0,
|
|
clockwise: false
|
|
)
|
|
|
|
path.addLine(to: CGPoint(x: max(rect.minX, rect.minX + rectSize.width * tailPosition - tailLeftHalfRadius), y: rect.minY - tailHeight))
|
|
|
|
path.addArc(
|
|
withCenter: CGPoint(x: rect.minX + rectSize.width * tailPosition, y: rect.minY - tailHeight + tailRadius / 2.0),
|
|
radius: tailRadius,
|
|
startAngle: -.pi / 2.0 + tailLeftArcStartAngle,
|
|
endAngle: -.pi / 2.0 + tailRightArcStartAngle,
|
|
clockwise: true
|
|
)
|
|
|
|
path.addLine(to: CGPoint(x: min(rect.maxX, rect.minX + rectSize.width * tailPosition + tailRightHalfRadius), y: rect.minY - tailHeight))
|
|
|
|
let rightArrowStart = min(rect.maxX, rect.minX + rectSize.width * tailPosition + tailRightHalfWidth + rightConnectionArcRadius)
|
|
path.addArc(
|
|
withCenter: CGPoint(x: rightArrowStart, y: rect.minY - rightConnectionArcRadius),
|
|
radius: rightConnectionArcRadius,
|
|
startAngle: .pi - .pi / 4.0,
|
|
endAngle: .pi / 2.0,
|
|
clockwise: false
|
|
)
|
|
|
|
path.addArc(
|
|
withCenter: CGPoint(x: rect.minX + rectSize.width - cornerRadius, y: rect.minY + cornerRadius),
|
|
radius: cornerRadius,
|
|
startAngle: min(-0.0001, rightArcStartAngle),
|
|
endAngle: 0.0,
|
|
clockwise: true
|
|
)
|
|
|
|
path.addLine(to: CGPoint(x: rect.minX + rectSize.width, y: rect.minY + rectSize.height - cornerRadius))
|
|
|
|
path.addArc(
|
|
withCenter: CGPoint(x: rect.minX + rectSize.width - cornerRadius, y: rect.minY + rectSize.height - cornerRadius),
|
|
radius: cornerRadius,
|
|
startAngle: 0.0,
|
|
endAngle: .pi / 2.0,
|
|
clockwise: true
|
|
)
|
|
|
|
path.addLine(to: CGPoint(x: rect.minX + cornerRadius, y: rect.minY + rectSize.height))
|
|
|
|
path.addArc(
|
|
withCenter: CGPoint(x: rect.minX + cornerRadius, y: rect.minY + rectSize.height - cornerRadius),
|
|
radius: cornerRadius,
|
|
startAngle: .pi / 2.0,
|
|
endAngle: .pi,
|
|
clockwise: true
|
|
)
|
|
|
|
return path
|
|
}
|