@@ -91,6 +91,127 @@ public func generateDisclosureActionBoostLevelBadgeImage(text: String) -> CGImag
9191}
9292#endif
9393
94+
95+ import Cocoa
96+
97+ 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 ) -> NSBezierPath {
98+ let cornerRadius : CGFloat = cornerRadius ?? rectSize. height / 2.0
99+ let tailWidth : CGFloat = tailSize. width
100+ let tailHeight : CGFloat = tailSize. height
101+
102+ let rect = CGRect ( origin: CGPoint ( x: 0.0 , y: tailHeight) , size: rectSize)
103+
104+ guard let tailPosition else {
105+ let path = NSBezierPath ( roundedRect: rect, xRadius: cornerRadius, yRadius: cornerRadius)
106+ return path
107+ }
108+
109+ let cutoff : CGFloat = 0.27
110+
111+ let path = NSBezierPath ( )
112+ path. move ( to: CGPoint ( x: rect. minX, y: rect. minY + cornerRadius) )
113+
114+ var leftArcEndAngle : CGFloat = . pi / 2.0
115+ var leftConnectionArcRadius = tailRadius
116+ var tailLeftHalfWidth : CGFloat = tailWidth / 2.0
117+ var tailLeftArcStartAngle : CGFloat = - . pi / 4.0
118+ var tailLeftHalfRadius = tailRadius
119+
120+ var rightArcStartAngle : CGFloat = - . pi / 2.0
121+ var rightConnectionArcRadius = tailRadius
122+ var tailRightHalfWidth : CGFloat = tailWidth / 2.0
123+ var tailRightArcStartAngle : CGFloat = . pi / 4.0
124+ var tailRightHalfRadius = tailRadius
125+
126+ if transformTail {
127+ if tailPosition < 0.5 {
128+ let fraction = max ( 0.0 , tailPosition - 0.15 ) / 0.35
129+ leftArcEndAngle *= fraction
130+
131+ let connectionFraction = max ( 0.0 , tailPosition - 0.35 ) / 0.15
132+ leftConnectionArcRadius *= connectionFraction
133+
134+ if tailPosition < cutoff {
135+ let fraction = tailPosition / cutoff
136+ tailLeftHalfWidth *= fraction
137+ tailLeftArcStartAngle *= fraction
138+ tailLeftHalfRadius *= fraction
139+ }
140+ } else if tailPosition > 0.5 {
141+ let tailPosition = 1.0 - tailPosition
142+ let fraction = max ( 0.0 , tailPosition - 0.15 ) / 0.35
143+ rightArcStartAngle *= fraction
144+
145+ let connectionFraction = max ( 0.0 , tailPosition - 0.35 ) / 0.15
146+ rightConnectionArcRadius *= connectionFraction
147+
148+ if tailPosition < cutoff {
149+ let fraction = tailPosition / cutoff
150+ tailRightHalfWidth *= fraction
151+ tailRightArcStartAngle *= fraction
152+ tailRightHalfRadius *= fraction
153+ }
154+ }
155+ }
156+
157+ path. appendArc ( withCenter: CGPoint ( x: rect. minX + cornerRadius, y: rect. minY + cornerRadius) ,
158+ radius: cornerRadius,
159+ startAngle: 180 ,
160+ endAngle: 180 + max( 0.0001 , leftArcEndAngle * 180 / . pi) ,
161+ clockwise: false )
162+
163+ let leftArrowStart = max ( rect. minX, rect. minX + rectSize. width * tailPosition - tailLeftHalfWidth - leftConnectionArcRadius)
164+ path. appendArc ( withCenter: CGPoint ( x: leftArrowStart, y: rect. minY - leftConnectionArcRadius) ,
165+ radius: leftConnectionArcRadius,
166+ startAngle: 90 ,
167+ endAngle: 45 ,
168+ clockwise: true )
169+
170+ path. line ( to: CGPoint ( x: max ( rect. minX, rect. minX + rectSize. width * tailPosition - tailLeftHalfRadius) , y: rect. minY - tailHeight) )
171+
172+ path. appendArc ( withCenter: CGPoint ( x: rect. minX + rectSize. width * tailPosition, y: rect. minY - tailHeight + tailRadius / 2.0 ) ,
173+ radius: tailRadius,
174+ startAngle: - 90 + tailLeftArcStartAngle * 180 / . pi,
175+ endAngle: - 90 + tailRightArcStartAngle * 180 / . pi,
176+ clockwise: false )
177+
178+ path. line ( to: CGPoint ( x: min ( rect. maxX, rect. minX + rectSize. width * tailPosition + tailRightHalfRadius) , y: rect. minY - tailHeight) )
179+
180+ let rightArrowStart = min ( rect. maxX, rect. minX + rectSize. width * tailPosition + tailRightHalfWidth + rightConnectionArcRadius)
181+ path. appendArc ( withCenter: CGPoint ( x: rightArrowStart, y: rect. minY - rightConnectionArcRadius) ,
182+ radius: rightConnectionArcRadius,
183+ startAngle: 180 - 45 ,
184+ endAngle: 90 ,
185+ clockwise: true )
186+
187+ path. appendArc ( withCenter: CGPoint ( x: rect. minX + rectSize. width - cornerRadius, y: rect. minY + cornerRadius) ,
188+ radius: cornerRadius,
189+ startAngle: min ( - 0.0001 , rightArcStartAngle * 180 / . pi) ,
190+ endAngle: 0 ,
191+ clockwise: false )
192+
193+ path. line ( to: CGPoint ( x: rect. minX + rectSize. width, y: rect. minY + rectSize. height - cornerRadius) )
194+
195+ path. appendArc ( withCenter: CGPoint ( x: rect. minX + rectSize. width - cornerRadius, y: rect. minY + rectSize. height - cornerRadius) ,
196+ radius: cornerRadius,
197+ startAngle: 0 ,
198+ endAngle: 90 ,
199+ clockwise: false )
200+
201+ path. line ( to: CGPoint ( x: rect. minX + cornerRadius, y: rect. minY + rectSize. height) )
202+
203+ path. appendArc ( withCenter: CGPoint ( x: rect. minX + cornerRadius, y: rect. minY + rectSize. height - cornerRadius) ,
204+ radius: cornerRadius,
205+ startAngle: 90 ,
206+ endAngle: 180 ,
207+ clockwise: false )
208+
209+ return path
210+ }
211+
212+
213+
214+
94215func chatReplyLineDashTemplateImage( _ colors: PeerNameColors . Colors , flipped: Bool ) -> CGImage ? {
95216 let radius : CGFloat = 3.0
96217 var offset : CGFloat = 5.0
0 commit comments