summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorPhilipp Lohmann [pl] <Philipp.Lohmann@Sun.COM>2010-08-20 15:12:16 +0200
committerPhilipp Lohmann [pl] <Philipp.Lohmann@Sun.COM>2010-08-20 15:12:16 +0200
commit15b7dd1db09078beda2eed6e532e5930fa4044d1 (patch)
tree6804e60690ef11adac2a220ac61256d3a52fd0aa /vcl
parent6f59f19bc89387609dfc09b126c46697792f4655 (diff)
pdfprint: #i94173# handle multiple page formats, collation
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/cupsmgr.hxx4
-rw-r--r--vcl/inc/vcl/jobdata.hxx1
-rw-r--r--vcl/inc/vcl/printerinfomanager.hxx4
-rw-r--r--vcl/unx/source/gdi/salprnpsp.cxx186
-rw-r--r--vcl/unx/source/printer/cupsmgr.cxx18
-rw-r--r--vcl/unx/source/printer/jobdata.cxx15
-rw-r--r--vcl/unx/source/printer/printerinfomanager.cxx4
-rw-r--r--vcl/unx/source/printergfx/printerjob.cxx2
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;
}