public static Shape createRoundRectanglePath( float x, float y, float width, float height,
		float arcTopLeft, float arcTopRight, float arcBottomLeft, float arcBottomRight )
	{
		if( arcTopLeft <= 0 && arcTopRight <= 0 && arcBottomLeft <= 0 && arcBottomRight <= 0 )
			return new Rectangle2D.Float( x, y, width, height );

		// limit arcs to min(width,height)
		float maxArc = Math.min( width, height ) / 2;
		arcTopLeft = (arcTopLeft > 0) ? Math.min( arcTopLeft, maxArc ) : 0;
		arcTopRight = (arcTopRight > 0) ? Math.min( arcTopRight, maxArc ) : 0;
		arcBottomLeft = (arcBottomLeft > 0) ? Math.min( arcBottomLeft, maxArc ) : 0;
		arcBottomRight = (arcBottomRight > 0) ? Math.min( arcBottomRight, maxArc ) : 0;

		float x2 = x + width;
		float y2 = y + height;

		// same constant as in java.awt.geom.EllipseIterator.CtrlVal used to paint circles
		double c = 0.5522847498307933;
		double ci = 1. - c;
		double ciTopLeft = arcTopLeft * ci;
		double ciTopRight = arcTopRight * ci;
		double ciBottomLeft = arcBottomLeft * ci;
		double ciBottomRight = arcBottomRight * ci;

		Path2D rect = new Path2D.Float( Path2D.WIND_NON_ZERO, 16 );
		rect.moveTo(  x2 - arcTopRight, y );
		rect.curveTo( x2 - ciTopRight, y,
					  x2, y + ciTopRight,
					  x2, y + arcTopRight );
		rect.lineTo(  x2, y2 - arcBottomRight );
		rect.curveTo( x2, y2 - ciBottomRight,
					  x2 - ciBottomRight, y2,
					  x2 - arcBottomRight, y2 );
		rect.lineTo(  x + arcBottomLeft, y2 );
		rect.curveTo( x + ciBottomLeft, y2,
					  x, y2 - ciBottomLeft,
					  x, y2 - arcBottomLeft );
		rect.lineTo(  x, y + arcTopLeft );
		rect.curveTo( x, y + ciTopLeft,
					  x + ciTopLeft, y,
					  x + arcTopLeft, y );
		rect.closePath();

		return rect;
	}
Creates a filled rounded rectangle shape and allows specifying the radius of each corner.
flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java