diff options
author | Philipp Lohmann [pl] <Philipp.Lohmann@Sun.COM> | 2010-08-20 15:12:16 +0200 |
---|---|---|
committer | Philipp Lohmann [pl] <Philipp.Lohmann@Sun.COM> | 2010-08-20 15:12:16 +0200 |
commit | 15b7dd1db09078beda2eed6e532e5930fa4044d1 (patch) | |
tree | 6804e60690ef11adac2a220ac61256d3a52fd0aa | |
parent | 6f59f19bc89387609dfc09b126c46697792f4655 (diff) |
pdfprint: #i94173# handle multiple page formats, collation
-rw-r--r-- | vcl/inc/cupsmgr.hxx | 4 | ||||
-rw-r--r-- | vcl/inc/vcl/jobdata.hxx | 1 | ||||
-rw-r--r-- | vcl/inc/vcl/printerinfomanager.hxx | 4 | ||||
-rw-r--r-- | vcl/unx/source/gdi/salprnpsp.cxx | 186 | ||||
-rw-r--r-- | vcl/unx/source/printer/cupsmgr.cxx | 18 | ||||
-rw-r--r-- | vcl/unx/source/printer/jobdata.cxx | 15 | ||||
-rw-r--r-- | vcl/unx/source/printer/printerinfomanager.cxx | 4 | ||||
-rw-r--r-- | vcl/unx/source/printergfx/printerjob.cxx | 2 |
8 files changed, 170 insertions, 64 deletions
diff --git a/vcl/inc/cupsmgr.hxx b/vcl/inc/cupsmgr.hxx index b413184f477f..0250cece817e 100644 --- a/vcl/inc/cupsmgr.hxx +++ b/vcl/inc/cupsmgr.hxx @@ -70,7 +70,7 @@ class CUPSManager : public PrinterInfoManager virtual void initialize(); - void getOptionsFromDocumentSetup( const JobData& rJob, int& rNumOptions, void** rOptions ) const; + void getOptionsFromDocumentSetup( const JobData& rJob, bool bBanner, int& rNumOptions, void** rOptions ) const; void runDests(); public: // public for stub @@ -84,7 +84,7 @@ public: const char* authenticateUser( const char* ); virtual FILE* startSpool( const rtl::OUString& rPrinterName, bool bQuickCommand ); - virtual int endSpool( const rtl::OUString& rPrinterName, const rtl::OUString& rJobTitle, FILE* pFile, const JobData& rDocumentJobData ); + virtual int endSpool( const rtl::OUString& rPrinterName, const rtl::OUString& rJobTitle, FILE* pFile, const JobData& rDocumentJobData, bool bBanner ); virtual void setupJobContextData( JobData& rData ); // changes the info about a named printer diff --git a/vcl/inc/vcl/jobdata.hxx b/vcl/inc/vcl/jobdata.hxx index 6dc756fe1b5c..793819bdf1ae 100644 --- a/vcl/inc/vcl/jobdata.hxx +++ b/vcl/inc/vcl/jobdata.hxx @@ -74,6 +74,7 @@ struct JobData JobData( const JobData& rData ) { *this = rData; } void setCollate( bool bCollate ); + bool setPaper( int nWidth, int nHeight ); // dimensions in pt // creates a new buffer using new // it is up to the user to delete it again diff --git a/vcl/inc/vcl/printerinfomanager.hxx b/vcl/inc/vcl/printerinfomanager.hxx index f2e0aad538c8..84d8a46965f3 100644 --- a/vcl/inc/vcl/printerinfomanager.hxx +++ b/vcl/inc/vcl/printerinfomanager.hxx @@ -217,8 +217,10 @@ public: // this may either be a regular file or the result of popen() virtual FILE* startSpool( const rtl::OUString& rPrinterName, bool bQuickCommand ); // close the FILE* returned by startSpool and does the actual spooling + // set bBanner to "false" will attempt to suppress banner printing + // set bBanner to "true" will rely on the system default // returns a numerical job id - virtual int endSpool( const rtl::OUString& rPrinterName, const rtl::OUString& rJobTitle, FILE* pFile, const JobData& rDocumentJobData ); + virtual int endSpool( const rtl::OUString& rPrinterName, const rtl::OUString& rJobTitle, FILE* pFile, const JobData& rDocumentJobData, bool bBanner ); // for spadmin: whether adding or removing a printer is possible virtual bool addOrRemovePossible() const; diff --git a/vcl/unx/source/gdi/salprnpsp.cxx b/vcl/unx/source/gdi/salprnpsp.cxx index cf38769b2b99..163877c0208c 100644 --- a/vcl/unx/source/gdi/salprnpsp.cxx +++ b/vcl/unx/source/gdi/salprnpsp.cxx @@ -1118,6 +1118,14 @@ ULONG PspSalPrinter::GetErrorCode() // ----------------------------------------------------------------------- +struct PDFPrintFile +{ + rtl::OUString maTmpURL; + Size maPageSize; + + PDFPrintFile( const rtl::OUString& i_rURL, const Size& i_rSize ) : maTmpURL( i_rURL ), maPageSize( i_rSize ) {} +}; + BOOL PspSalPrinter::StartJob( const String* i_pFileName, const String& i_rJobName, const String& i_rAppName, ImplJobSetup* i_pSetupData, vcl::PrinterController& i_rController ) { @@ -1134,7 +1142,6 @@ BOOL PspSalPrinter::StartJob( const String* i_pFileName, const String& i_rJobNam OSL_ASSERT( m_aJobData.m_nPDFDevice > 0 ); m_aJobData.m_nPDFDevice = 1; - // do we want a progress panel ? // possibly create one job for collated output sal_Bool bSinglePrintJobs = sal_False; beans::PropertyValue* pSingleValue = i_rController.getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintCollateAsSingleJobs" ) ) ); @@ -1143,62 +1150,43 @@ BOOL PspSalPrinter::StartJob( const String* i_pFileName, const String& i_rJobNam pSingleValue->Value >>= bSinglePrintJobs; } - m_aJobData.m_nCopies = i_rController.getPrinter()->GetCopyCount(); - int nJobs = 1; - if( bSinglePrintJobs ) - { - nJobs = m_aJobData.m_nCopies; - m_aJobData.m_nCopies = 1; - } + int nCopies = i_rController.getPrinter()->GetCopyCount(); + bool bCollate = i_rController.getPrinter()->IsCollateCopy(); // notify start of real print job i_rController.jobStarted(); - // produce PDF file - OUString aPDFUrl; - if( i_pFileName ) - aPDFUrl = *i_pFileName; - else - osl_createTempFile( NULL, NULL, &aPDFUrl.pData ); - if( aPDFUrl.compareToAscii( "file:", 5 ) != 0 ) - { - // this is not a file URL, but it should - // form it into a osl friendly file URL - rtl::OUString aTmp; - osl_getFileURLFromSystemPath( aPDFUrl.pData, &aTmp.pData ); - aPDFUrl = aTmp; - } - - // setup PDFWriter - + // setup PDFWriter context vcl::PDFWriter::PDFWriterContext aContext; - aContext.URL = aPDFUrl; aContext.Version = vcl::PDFWriter::PDF_1_4; aContext.Tagged = false; aContext.EmbedStandardFonts = true; aContext.Encrypt = false; aContext.DocumentLocale = Application::GetSettings().GetLocale(); + // prepare doc info vcl::PDFDocInfo aDocInfo; aDocInfo.Title = i_rJobName; aDocInfo.Creator = i_rAppName; aDocInfo.Producer = i_rAppName; - vcl::PDFWriter aPDFWriter( aContext ); - aPDFWriter.SetDocInfo( aDocInfo ); + // define how we handle metafiles in PDFWriter vcl::PDFWriter::PlayMetafileContext aMtfContext; aMtfContext.m_bOnlyLosslessCompression = true; + boost::shared_ptr<vcl::PDFWriter> pWriter; + std::vector< PDFPrintFile > aPDFFiles; boost::shared_ptr<Printer> pPrinter( i_rController.getPrinter() ); int nAllPages = i_rController.getFilteredPageCount(); i_rController.createProgressDialog(); bool bAborted = false; + Size aLastPageSize(0,0); for( int nPage = 0; nPage < nAllPages && ! bAborted; nPage++ ) { if( nPage == nAllPages-1 ) i_rController.setLastPage( sal_True ); - // get the pages metafile + // get the page's metafile GDIMetaFile aPageFile; vcl::PrinterController::PageSize aPageSize = i_rController.getFilteredPageFile( nPage, aPageFile ); if( i_rController.isProgressCanceled() ) @@ -1216,50 +1204,144 @@ BOOL PspSalPrinter::StartJob( const String* i_pFileName, const String& i_rJobNam pPrinter->SetMapMode( MapMode( MAP_100TH_MM ) ); pPrinter->SetPaperSizeUser( aPageSize.aSize, true ); Size aRealSize( pPrinter->GetPaperSize() ); + Size aLSSize( aRealSize.Height(), aRealSize.Width() ); + + // create PDF writer on demand + // either on first page + // or on paper format change - cups does not support multiple paper formats per job (yet?) + // so we need to start a new job to get a new paper format from the printer + // orientation switches (that is switch of height and width) is handled transparently by CUPS + if( ! pWriter || + (aRealSize != aLastPageSize && aLSSize != aLastPageSize && ! i_pFileName ) ) + { + if( pWriter ) + { + pWriter->Emit(); + } + // produce PDF file + OUString aPDFUrl; + if( i_pFileName ) + aPDFUrl = *i_pFileName; + else + osl_createTempFile( NULL, NULL, &aPDFUrl.pData ); + // normalize to file URL + if( aPDFUrl.compareToAscii( "file:", 5 ) != 0 ) + { + // this is not a file URL, but it should + // form it into a osl friendly file URL + rtl::OUString aTmp; + osl_getFileURLFromSystemPath( aPDFUrl.pData, &aTmp.pData ); + aPDFUrl = aTmp; + } + // save current file and paper format + aLastPageSize = aRealSize; + aPDFFiles.push_back( PDFPrintFile( aPDFUrl, aRealSize ) ); + // update context + aContext.URL = aPDFUrl; + + // create and initialize PDFWriter + pWriter.reset( new vcl::PDFWriter( aContext ) ); + pWriter->SetDocInfo( aDocInfo ); + } - aPDFWriter.NewPage( TenMuToPt( aRealSize.Width() ), - TenMuToPt( aRealSize.Height() ), - vcl::PDFWriter::Portrait ); + pWriter->NewPage( TenMuToPt( aRealSize.Width() ), + TenMuToPt( aRealSize.Height() ), + vcl::PDFWriter::Portrait ); - aPDFWriter.PlayMetafile( aPageFile, aMtfContext, NULL ); + pWriter->PlayMetafile( aPageFile, aMtfContext, NULL ); } } - aPDFWriter.Emit(); + // emit the last file + if( pWriter ) + pWriter->Emit(); + // handle collate, copy count and multiple jobs correctly + int nOuterJobs = 1; + if( bSinglePrintJobs ) + { + nOuterJobs = nCopies; + m_aJobData.m_nCopies = 1; + } + else + { + if( bCollate ) + { + if( aPDFFiles.size() == 1 && pPrinter->HasSupport( SUPPORT_COLLATECOPY ) ) + { + m_aJobData.setCollate( true ); + m_aJobData.m_nCopies = nCopies; + } + else + { + nOuterJobs = nCopies; + m_aJobData.m_nCopies = 1; + } + } + else + { + m_aJobData.setCollate( false ); + m_aJobData.m_nCopies = nCopies; + } + } + + // spool files if( ! i_pFileName && ! bAborted ) { - oslFileHandle pFile = NULL; - osl_openFile( aContext.URL.pData, &pFile, osl_File_OpenFlag_Read ); - if( pFile ) + bool bFirstJob = true; + for( int nCurJob = 0; nCurJob < nOuterJobs; nCurJob++ ) { - osl_setFilePos( pFile, osl_Pos_Absolut, 0 ); - std::vector< char > buffer( 0x10000, 0 ); - for( int nCurJob = 0; nCurJob < nJobs; nCurJob++ ) + for( size_t i = 0; i < aPDFFiles.size(); i++ ) { - FILE* fp = PrinterInfoManager::get().startSpool( pPrinter->GetName(), i_rController.isDirectPrint() ); - if( fp ) + oslFileHandle pFile = NULL; + osl_openFile( aPDFFiles[i].maTmpURL.pData, &pFile, osl_File_OpenFlag_Read ); + if( pFile ) { - sal_uInt64 nBytesRead = 0; - do + osl_setFilePos( pFile, osl_Pos_Absolut, 0 ); + std::vector< char > buffer( 0x10000, 0 ); + // update job data with current page size + Size aPageSize( aPDFFiles[i].maPageSize ); + m_aJobData.setPaper( TenMuToPt( aPageSize.Width() ), TenMuToPt( aPageSize.Height() ) ); + + // spool current file + FILE* fp = PrinterInfoManager::get().startSpool( pPrinter->GetName(), i_rController.isDirectPrint() ); + if( fp ) { - osl_readFile( pFile, &buffer[0], buffer.size(), &nBytesRead ); - if( nBytesRead > 0 ) - fwrite( &buffer[0], 1, nBytesRead, fp ); - } while( nBytesRead == buffer.size() ); - PrinterInfoManager::get().endSpool( pPrinter->GetName(), i_rJobName, fp, m_aJobData ); + sal_uInt64 nBytesRead = 0; + do + { + osl_readFile( pFile, &buffer[0], buffer.size(), &nBytesRead ); + if( nBytesRead > 0 ) + fwrite( &buffer[0], 1, nBytesRead, fp ); + } while( nBytesRead == buffer.size() ); + rtl::OUStringBuffer aBuf( i_rJobName.Len() + 8 ); + aBuf.append( i_rJobName ); + if( i > 0 || nCurJob > 0 ) + { + aBuf.append( sal_Unicode(' ') ); + aBuf.append( sal_Int32( i + nCurJob * aPDFFiles.size() ) ); + } + PrinterInfoManager::get().endSpool( pPrinter->GetName(), aBuf.makeStringAndClear(), fp, m_aJobData, bFirstJob ); + bFirstJob = false; + } } + osl_closeFile( pFile ); } - osl_closeFile( pFile ); } } // job has been spooled i_rController.setJobState( bAborted ? view::PrintableState_JOB_ABORTED : view::PrintableState_JOB_SPOOLED ); - // clean up the PDF file + // clean up the temporary PDF files if( ! i_pFileName || bAborted ) - osl_removeFile( aPDFUrl.pData ); + { + for( size_t i = 0; i < aPDFFiles.size(); i++ ) + { + osl_removeFile( aPDFFiles[i].maTmpURL.pData ); + OSL_TRACE( "removed print PDF file %s\n", rtl::OUStringToOString( aPDFFiles[i].maTmpURL, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + } return TRUE; } diff --git a/vcl/unx/source/printer/cupsmgr.cxx b/vcl/unx/source/printer/cupsmgr.cxx index 96f74acf00ba..caf3249b5f46 100644 --- a/vcl/unx/source/printer/cupsmgr.cxx +++ b/vcl/unx/source/printer/cupsmgr.cxx @@ -865,7 +865,7 @@ struct less_ppd_key : public ::std::binary_function<double, double, bool> { return left->getOrderDependency() < right->getOrderDependency(); } }; -void CUPSManager::getOptionsFromDocumentSetup( const JobData& rJob, int& rNumOptions, void** rOptions ) const +void CUPSManager::getOptionsFromDocumentSetup( const JobData& rJob, bool bBanner, int& rNumOptions, void** rOptions ) const { rNumOptions = 0; *rOptions = NULL; @@ -901,13 +901,19 @@ void CUPSManager::getOptionsFromDocumentSetup( const JobData& rJob, int& rNumOpt rtl::OString aVal( rtl::OString::valueOf( sal_Int32( rJob.m_nCopies ) ) ); rNumOptions = m_pCUPSWrapper->cupsAddOption( "copies", aVal.getStr(), rNumOptions, (cups_option_t**)rOptions ); } + if( ! bBanner ) + { + rNumOptions = m_pCUPSWrapper->cupsAddOption( "job-sheets", "none", rNumOptions, (cups_option_t**)rOptions ); + } } -int CUPSManager::endSpool( const OUString& rPrintername, const OUString& rJobTitle, FILE* pFile, const JobData& rDocumentJobData ) +int CUPSManager::endSpool( const OUString& rPrintername, const OUString& rJobTitle, FILE* pFile, const JobData& rDocumentJobData, bool bBanner ) { - OSL_TRACE( "endSpool: %s, %s", + OSL_TRACE( "endSpool: %s, %s, copy count = %d", rtl::OUStringToOString( rPrintername, RTL_TEXTENCODING_UTF8 ).getStr(), - rtl::OUStringToOString( rJobTitle, RTL_TEXTENCODING_UTF8 ).getStr() ); + rtl::OUStringToOString( rJobTitle, RTL_TEXTENCODING_UTF8 ).getStr(), + rDocumentJobData.m_nCopies + ); int nJobID = 0; @@ -918,7 +924,7 @@ int CUPSManager::endSpool( const OUString& rPrintername, const OUString& rJobTit if( dest_it == m_aCUPSDestMap.end() ) { OSL_TRACE( "defer to PrinterInfoManager::endSpool" ); - return PrinterInfoManager::endSpool( rPrintername, rJobTitle, pFile, rDocumentJobData ); + return PrinterInfoManager::endSpool( rPrintername, rJobTitle, pFile, rDocumentJobData, bBanner ); } #ifdef ENABLE_CUPS @@ -931,7 +937,7 @@ int CUPSManager::endSpool( const OUString& rPrintername, const OUString& rJobTit // setup cups options int nNumOptions = 0; cups_option_t* pOptions = NULL; - getOptionsFromDocumentSetup( rDocumentJobData, nNumOptions, (void**)&pOptions ); + getOptionsFromDocumentSetup( rDocumentJobData, bBanner, nNumOptions, (void**)&pOptions ); cups_dest_t* pDest = ((cups_dest_t*)m_pDests) + dest_it->second; nJobID = m_pCUPSWrapper->cupsPrintFile( pDest->name, diff --git a/vcl/unx/source/printer/jobdata.cxx b/vcl/unx/source/printer/jobdata.cxx index 019c1da1fbc9..7839b90ce485 100644 --- a/vcl/unx/source/printer/jobdata.cxx +++ b/vcl/unx/source/printer/jobdata.cxx @@ -84,6 +84,21 @@ void JobData::setCollate( bool bCollate ) } } +bool JobData::setPaper( int i_nWidth, int i_nHeight ) +{ + bool bSuccess = false; + if( m_pParser ) + { + rtl::OUString aPaper( m_pParser->matchPaper( i_nWidth, i_nHeight ) ); + + const PPDKey* pKey = m_pParser->getKey( String( RTL_CONSTASCII_USTRINGPARAM( "PageSize" ) ) ); + const PPDValue* pValue = pKey ? pKey->getValueCaseInsensitive( aPaper ) : NULL; + + bSuccess = pKey && pValue && m_aContext.setValue( pKey, pValue, false ); + } + return bSuccess; +} + bool JobData::getStreamBuffer( void*& pData, int& bytes ) { // consistency checks diff --git a/vcl/unx/source/printer/printerinfomanager.cxx b/vcl/unx/source/printer/printerinfomanager.cxx index 84997d11ac56..1e5ab8fd7007 100644 --- a/vcl/unx/source/printer/printerinfomanager.cxx +++ b/vcl/unx/source/printer/printerinfomanager.cxx @@ -328,7 +328,7 @@ void PrinterInfoManager::initialize() } } #if OSL_DEBUG_LEVEL > 1 - fprintf( stderr, "global settings: fontsubst = %s, %d substitutes\n", m_aGlobalDefaults.m_bPerformFontSubstitution ? "true" : "false", m_aGlobalDefaults.m_aFontSubstitutes.size() ); + fprintf( stderr, "global settings: fontsubst = %s, %d substitutes\n", m_aGlobalDefaults.m_bPerformFontSubstitution ? "true" : "false", (int)m_aGlobalDefaults.m_aFontSubstitutes.size() ); #endif } } @@ -1105,7 +1105,7 @@ FILE* PrinterInfoManager::startSpool( const OUString& rPrintername, bool bQuickC return popen (aShellCommand.getStr(), "w"); } -int PrinterInfoManager::endSpool( const OUString& /*rPrintername*/, const OUString& /*rJobTitle*/, FILE* pFile, const JobData& /*rDocumentJobData*/ ) +int PrinterInfoManager::endSpool( const OUString& /*rPrintername*/, const OUString& /*rJobTitle*/, FILE* pFile, const JobData& /*rDocumentJobData*/, bool /*bBanner*/ ) { return (0 == pclose( pFile )); } diff --git a/vcl/unx/source/printergfx/printerjob.cxx b/vcl/unx/source/printergfx/printerjob.cxx index c69a0771655d..26a1d75f68c2 100644 --- a/vcl/unx/source/printergfx/printerjob.cxx +++ b/vcl/unx/source/printergfx/printerjob.cxx @@ -611,7 +611,7 @@ PrinterJob::EndJob () { PrinterInfoManager& rPrinterInfoManager = PrinterInfoManager::get(); if (0 == rPrinterInfoManager.endSpool( m_aLastJobData.m_aPrinterName, - maJobTitle, pDestFILE, m_aDocumentJobData )) + maJobTitle, pDestFILE, m_aDocumentJobData, true )) { bSuccess = sal_False; } |