From 7012d882fe7b8a4ea2104cbcf81cb019bd54efe9 Mon Sep 17 00:00:00 2001 From: Luboš Luňák Date: Thu, 26 Feb 2015 15:56:24 +0100 Subject: support fast MM printing in non-single-file mode only for CUPS As said in the comment, the non-single-file mode could create way too many print jobs, so enable this only for the CUPS backend, which has been modified to send them as a single batch. Change-Id: I4c02ca0e8b91323b1d02f004c7b4813433064a11 --- vcl/unx/generic/printer/cupsmgr.cxx | 113 ++++++++++++++++++++----- vcl/unx/generic/printer/jobdata.cxx | 18 ++++ vcl/unx/generic/printer/printerinfomanager.cxx | 15 ++++ 3 files changed, 126 insertions(+), 20 deletions(-) (limited to 'vcl/unx') diff --git a/vcl/unx/generic/printer/cupsmgr.cxx b/vcl/unx/generic/printer/cupsmgr.cxx index 6b06596df614..5169d29199a4 100644 --- a/vcl/unx/generic/printer/cupsmgr.cxx +++ b/vcl/unx/generic/printer/cupsmgr.cxx @@ -646,8 +646,6 @@ int CUPSManager::endSpool( const OUString& rPrintername, const OUString& rJobTit rDocumentJobData.m_nCopies ); - int nJobID = 0; - osl::MutexGuard aGuard( m_aCUPSMutex ); boost::unordered_map< OUString, int, OUStringHash >::iterator dest_it = @@ -659,25 +657,98 @@ int CUPSManager::endSpool( const OUString& rPrintername, const OUString& rJobTit } boost::unordered_map< FILE*, OString, FPtrHash >::const_iterator it = m_aSpoolFiles.find( pFile ); - if( it != m_aSpoolFiles.end() ) + if( it == m_aSpoolFiles.end() ) + return false; + fclose( pFile ); + PendingJob job( rPrintername, rJobTitle, rDocumentJobData, bBanner, it->second ); + m_aSpoolFiles.erase( pFile ); + pendingJobs.push_back( job ); + if( !batchMode ) // process immediately, otherwise will be handled by flushBatchPrint() + return processPendingJobs(); + return true; +} + +bool CUPSManager::startBatchPrint() +{ + batchMode = true; + return true; +} + +bool CUPSManager::supportsBatchPrint() const +{ + return true; +} + +bool CUPSManager::flushBatchPrint() +{ + osl::MutexGuard aGuard( m_aCUPSMutex ); + return processPendingJobs(); +} + +bool CUPSManager::processPendingJobs() +{ + // Print all jobs that have the same data using one CUPS call (i.e. merge all jobs that differ only in files to print). + PendingJob currentJobData; + bool first = true; + std::vector< OString > files; + bool ok = true; + while( !pendingJobs.empty()) + { + if( first ) + { + currentJobData = pendingJobs.front(); + first = false; + } + else if( currentJobData.printerName != pendingJobs.front().printerName + || currentJobData.jobTitle != pendingJobs.front().jobTitle + || currentJobData.jobData != pendingJobs.front().jobData + || currentJobData.banner != pendingJobs.front().banner ) + { + if( !printJobs( currentJobData, files )) + ok = false; + files.clear(); + currentJobData = pendingJobs.front(); + } + files.push_back( pendingJobs.front().file ); + pendingJobs.pop_front(); + } + if( !first ) { - fclose( pFile ); - rtl_TextEncoding aEnc = osl_getThreadTextEncoding(); + if( !printJobs( currentJobData, files )) // print the last batch + ok = false; + } + return ok; +} - // setup cups options - int nNumOptions = 0; - cups_option_t* pOptions = NULL; - getOptionsFromDocumentSetup( rDocumentJobData, bBanner, nNumOptions, (void**)&pOptions ); +bool CUPSManager::printJobs( const PendingJob& job, const std::vector< OString >& files ) +{ + boost::unordered_map< OUString, int, OUStringHash >::iterator dest_it = + m_aCUPSDestMap.find( job.printerName ); + + rtl_TextEncoding aEnc = osl_getThreadTextEncoding(); + + // setup cups options + int nNumOptions = 0; + cups_option_t* pOptions = NULL; + getOptionsFromDocumentSetup( job.jobData, job.banner, nNumOptions, reinterpret_cast(&pOptions) ); + + cups_dest_t* pDest = ((cups_dest_t*)m_pDests) + dest_it->second; - cups_dest_t* pDest = ((cups_dest_t*)m_pDests) + dest_it->second; - nJobID = cupsPrintFile( pDest->name, - it->second.getStr(), - OUStringToOString( rJobTitle, aEnc ).getStr(), - nNumOptions, pOptions ); + std::vector< const char* > fnames; + for( std::vector< OString >::const_iterator it = files.begin(); + it != files.end(); + ++it ) + fnames.push_back( it->getStr()); + + int nJobID = cupsPrintFiles(pDest->name, + fnames.size(), + fnames.data(), + OUStringToOString( job.jobTitle, aEnc ).getStr(), + nNumOptions, pOptions); #if OSL_DEBUG_LEVEL > 1 fprintf( stderr, "cupsPrintFile( %s, %s, %s, %d, %p ) returns %d\n", pDest->name, - it->second.getStr(), + ( fnames.size() == 1 ? files.front() : OString::number( fnames.size()) ).getStr(), OUStringToOString( rJobTitle, aEnc ).getStr(), nNumOptions, pOptions, @@ -691,11 +762,13 @@ int CUPSManager::endSpool( const OUString& rPrintername, const OUString& rJobTit system( aCmd.getStr() ); #endif - unlink( it->second.getStr() ); - m_aSpoolFiles.erase( pFile ); - if( pOptions ) - cupsFreeOptions( nNumOptions, pOptions ); - } + for( std::vector< OString >::const_iterator it = files.begin(); + it != files.end(); + ++it ) + unlink( it->getStr()); + + if( pOptions ) + cupsFreeOptions( nNumOptions, pOptions ); return nJobID; } diff --git a/vcl/unx/generic/printer/jobdata.cxx b/vcl/unx/generic/printer/jobdata.cxx index d40fffd913a7..16adb96b4b90 100644 --- a/vcl/unx/generic/printer/jobdata.cxx +++ b/vcl/unx/generic/printer/jobdata.cxx @@ -52,6 +52,24 @@ JobData& JobData::operator=(const JobData& rRight) return *this; } +bool psp::operator==(const psp::JobData& rLeft, const psp::JobData& rRight) +{ + return rLeft.m_nCopies == rRight.m_nCopies +// && rLeft.m_bCollate == rRight.m_bCollate + && rLeft.m_nLeftMarginAdjust == rRight.m_nLeftMarginAdjust + && rLeft.m_nRightMarginAdjust == rRight.m_nRightMarginAdjust + && rLeft.m_nTopMarginAdjust == rRight.m_nTopMarginAdjust + && rLeft.m_nBottomMarginAdjust == rRight.m_nBottomMarginAdjust + && rLeft.m_nColorDepth == rRight.m_nColorDepth + && rLeft.m_eOrientation == rRight.m_eOrientation + && rLeft.m_aPrinterName == rRight.m_aPrinterName + && rLeft.m_pParser == rRight.m_pParser +// && rLeft.m_aContext == rRight.m_aContext + && rLeft.m_nPSLevel == rRight.m_nPSLevel + && rLeft.m_nPDFDevice == rRight.m_nPDFDevice + && rLeft.m_nColorDevice == rRight.m_nColorDevice; +} + void JobData::setCollate( bool bCollate ) { const PPDParser* pParser = m_aContext.getParser(); diff --git a/vcl/unx/generic/printer/printerinfomanager.cxx b/vcl/unx/generic/printer/printerinfomanager.cxx index 7def80fd5564..b895f8208f98 100644 --- a/vcl/unx/generic/printer/printerinfomanager.cxx +++ b/vcl/unx/generic/printer/printerinfomanager.cxx @@ -1180,6 +1180,21 @@ void PrinterInfoManager::setDefaultPaper( PPDContext& rContext ) const // ----------------------------------------------------------------- +bool PrinterInfoManager::startBatchPrint() +{ + return false; // not implemented +} + +bool PrinterInfoManager::supportsBatchPrint() const +{ + return false; +} + +bool PrinterInfoManager::flushBatchPrint() +{ + return false; +} + SystemQueueInfo::SystemQueueInfo() : m_bChanged( false ) { -- cgit