@@ -208,6 +208,11 @@ interface CornerPathParams {
208208 height : number
209209}
210210
211+ // The article from figma's blog
212+ // https://www.figma.com/blog/desperately-seeking-squircles/
213+ //
214+ // The original code by MartinRGB
215+ // https://github.com/MartinRGB/Figma_Squircles_Approximation/blob/bf29714aab58c54329f3ca130ffa16d39a2ff08c/js/rounded-corners.js#L64
211216function getPathParamsForCorner ( {
212217 cornerRadius,
213218 cornerSmoothing,
@@ -217,32 +222,20 @@ function getPathParamsForCorner({
217222 const maxRadius = Math . min ( width , height ) / 2
218223 cornerRadius = Math . min ( cornerRadius , maxRadius )
219224
220- // The article from figma's blog
221- // https://www.figma.com/blog/desperately-seeking-squircles/
225+ // From figure 12.2 in the article
226+ // p = (1 + cornerSmoothing) * q
227+ // in this case q = R because theta = 90deg
222228 //
223- // The original code
224- // https://github.com/MartinRGB/Figma_Squircles_Approximation/blob/bf29714aab58c54329f3ca130ffa16d39a2ff08c/js/rounded-corners.js#L64
229+ // Also, when there's not enough space left, we need to back off the smoothing
230+ const maxCornerSmoothing = maxRadius / cornerRadius - 1
231+ cornerSmoothing = Math . min ( cornerSmoothing , maxCornerSmoothing )
225232
226- // 12.2 from the article
227- const p = Math . min ( ( 1 + cornerSmoothing ) * cornerRadius , maxRadius )
228-
229- let angleAlpha : number , angleBeta : number
230-
231- if ( cornerRadius <= maxRadius / 2 ) {
232- angleBeta = 90 * ( 1 - cornerSmoothing )
233- angleAlpha = 45 * cornerSmoothing
234- } else {
235- // When `cornerRadius` is larger and `maxRadius / 2`,
236- // these angles also depend on `cornerRadius` and `maxRadius / 2`
237- //
238- // I did a few tests in Figma and this code generated similar but not identical results
239- // `diffRatio` was called `change_percentage` in the orignal code
240- const diffRatio = ( cornerRadius - maxRadius / 2 ) / ( maxRadius / 2 )
241-
242- angleBeta = 90 * ( 1 - cornerSmoothing * ( 1 - diffRatio ) )
243- angleAlpha = 45 * cornerSmoothing * ( 1 - diffRatio )
244- }
233+ const p = ( 1 + cornerSmoothing ) * cornerRadius
245234
235+ // These are the angles used in the original code
236+ // angleTheta is not the same as theta in the article
237+ const angleBeta = 90 * ( 1 - cornerSmoothing )
238+ const angleAlpha = 45 * cornerSmoothing
246239 const angleTheta = ( 90 - angleBeta ) / 2
247240
248241 // This was called `h_longest` in the original code
@@ -253,7 +246,7 @@ function getPathParamsForCorner({
253246 const circularSectionLength =
254247 Math . sin ( toRadians ( angleBeta / 2 ) ) * cornerRadius * Math . sqrt ( 2 )
255248
256- // a, b, c and d are from 11.1 in the article
249+ // a, b, c and d are from figure 11.1 in the article
257250 const c = p3ToP4Distance * Math . cos ( toRadians ( angleAlpha ) )
258251 const d = c * Math . tan ( toRadians ( angleAlpha ) )
259252 const b = ( p - circularSectionLength - c - d ) / 3
0 commit comments