LCOV - code coverage report
Current view: top level - libreoffice/vcl/generic/print - printerjob.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 464 0.0 %
Date: 2012-12-17 Functions: 0 27 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <stdio.h>
      22             : #include <sys/types.h>
      23             : #include <sys/stat.h>
      24             : #include <fcntl.h>
      25             : #include <unistd.h>
      26             : 
      27             : #include "psputil.hxx"
      28             : #include "glyphset.hxx"
      29             : 
      30             : #include "generic/printerjob.hxx"
      31             : #include "generic/printergfx.hxx"
      32             : #include "vcl/ppdparser.hxx"
      33             : #include "vcl/strhelper.hxx"
      34             : #include "vcl/printerinfomanager.hxx"
      35             : 
      36             : #include "rtl/ustring.hxx"
      37             : #include "rtl/strbuf.hxx"
      38             : #include "rtl/ustrbuf.hxx"
      39             : 
      40             : #include <osl/thread.h>
      41             : #include <osl/security.hxx>
      42             : #include <sal/alloca.h>
      43             : #include <sal/macros.h>
      44             : 
      45             : #include <algorithm>
      46             : #include <vector>
      47             : 
      48             : using namespace psp;
      49             : 
      50             : using ::rtl::OUString;
      51             : using ::rtl::OUStringToOString;
      52             : using ::rtl::OString;
      53             : using ::rtl::OStringBuffer;
      54             : 
      55             : // forward declaration
      56             : 
      57             : #define nBLOCKSIZE 0x2000
      58             : 
      59             : namespace psp
      60             : {
      61             : 
      62             : sal_Bool
      63           0 : AppendPS (FILE* pDst, osl::File* pSrc, sal_uChar* pBuffer,
      64             :           sal_uInt32 nBlockSize = nBLOCKSIZE)
      65             : {
      66           0 :     if ((pDst == NULL) || (pSrc == NULL))
      67           0 :         return sal_False;
      68             : 
      69           0 :     if (pSrc->setPos(osl_Pos_Absolut, 0) != osl::FileBase::E_None)
      70           0 :         return sal_False;
      71             : 
      72           0 :     if (nBlockSize == 0)
      73           0 :         nBlockSize = nBLOCKSIZE;
      74           0 :     if (pBuffer == NULL)
      75           0 :         pBuffer = (sal_uChar*)alloca (nBlockSize);
      76             : 
      77           0 :     sal_uInt64 nIn = 0;
      78           0 :     sal_uInt64 nOut = 0;
      79           0 :     do
      80             :     {
      81           0 :         pSrc->read  (pBuffer, nBlockSize, nIn);
      82           0 :         if (nIn > 0)
      83           0 :             nOut = fwrite (pBuffer, 1, sal::static_int_cast<sal_uInt32>(nIn), pDst);
      84             :     }
      85             :     while ((nIn > 0) && (nIn == nOut));
      86             : 
      87           0 :     return sal_True;
      88             : }
      89             : 
      90             : } // namespace psp
      91             : 
      92             : /*
      93             :  * private convenience routines for file handling
      94             :  */
      95             : 
      96             : osl::File*
      97           0 : PrinterJob::CreateSpoolFile (const rtl::OUString& rName, const rtl::OUString& rExtension)
      98             : {
      99           0 :     osl::File::RC nError = osl::File::E_None;
     100           0 :     osl::File*    pFile  = NULL;
     101             : 
     102           0 :     rtl::OUString aFile = rName + rExtension;
     103           0 :     rtl::OUString aFileURL;
     104           0 :     nError = osl::File::getFileURLFromSystemPath( aFile, aFileURL );
     105           0 :     if (nError != osl::File::E_None)
     106           0 :         return NULL;
     107           0 :     aFileURL = maSpoolDirName + rtl::OUString("/") + aFileURL;
     108             : 
     109           0 :     pFile = new osl::File (aFileURL);
     110           0 :     nError = pFile->open (osl_File_OpenFlag_Read | osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
     111           0 :     if (nError != osl::File::E_None)
     112             :     {
     113           0 :         delete pFile;
     114           0 :         return NULL;
     115             :     }
     116             : 
     117             :     pFile->setAttributes (aFileURL,
     118           0 :                           osl_File_Attribute_OwnWrite | osl_File_Attribute_OwnRead);
     119           0 :     return pFile;
     120             : }
     121             : 
     122             : /*
     123             :  * public methods of PrinterJob: for use in PrinterGfx
     124             :  */
     125             : 
     126             : void
     127           0 : PrinterJob::GetScale (double &rXScale, double &rYScale) const
     128             : {
     129           0 :     rXScale = mfXScale;
     130           0 :     rYScale = mfYScale;
     131           0 : }
     132             : 
     133             : sal_uInt16
     134           0 : PrinterJob::GetDepth () const
     135             : {
     136           0 :     sal_Int32 nLevel = GetPostscriptLevel();
     137           0 :     sal_Bool  bColor = IsColorPrinter ();
     138             : 
     139           0 :     return nLevel > 1 && bColor ? 24 : 8;
     140             : }
     141             : 
     142             : sal_uInt16
     143           0 : PrinterJob::GetPostscriptLevel (const JobData *pJobData) const
     144             : {
     145           0 :     sal_uInt16 nPSLevel = 2;
     146             : 
     147           0 :     if( pJobData == NULL )
     148           0 :         pJobData = &m_aLastJobData;
     149             : 
     150           0 :     if( pJobData->m_nPSLevel )
     151           0 :         nPSLevel = pJobData->m_nPSLevel;
     152             :     else
     153           0 :         if( pJobData->m_pParser )
     154           0 :             nPSLevel = pJobData->m_pParser->getLanguageLevel();
     155             : 
     156           0 :     return nPSLevel;
     157             : }
     158             : 
     159             : sal_Bool
     160           0 : PrinterJob::IsColorPrinter () const
     161             : {
     162           0 :     sal_Bool bColor = sal_False;
     163             : 
     164           0 :     if( m_aLastJobData.m_nColorDevice )
     165           0 :         bColor = m_aLastJobData.m_nColorDevice == -1 ? sal_False : sal_True;
     166           0 :     else if( m_aLastJobData.m_pParser )
     167           0 :         bColor = m_aLastJobData.m_pParser->isColorDevice() ? sal_True : sal_False;
     168             : 
     169           0 :     return bColor;
     170             : }
     171             : 
     172             : osl::File*
     173           0 : PrinterJob::GetCurrentPageHeader ()
     174             : {
     175           0 :     return maHeaderList.back();
     176             : }
     177             : 
     178             : osl::File*
     179           0 : PrinterJob::GetCurrentPageBody ()
     180             : {
     181           0 :     return maPageList.back();
     182             : }
     183             : 
     184             : /*
     185             :  * public methods of PrinterJob: the actual job / spool handling
     186             :  */
     187             : 
     188           0 : PrinterJob::PrinterJob () :
     189             :         mpJobHeader( NULL ),
     190             :         mpJobTrailer( NULL ),
     191           0 :         m_bQuickJob( false )
     192             : {
     193           0 : }
     194             : 
     195             : /* remove all our temporary files, uses external program "rm", since
     196             :    osl functionality is inadequate */
     197             : void
     198           0 : removeSpoolDir (const rtl::OUString& rSpoolDir)
     199             : {
     200           0 :     rtl::OUString aSysPath;
     201           0 :     if( osl::File::E_None != osl::File::getSystemPathFromFileURL( rSpoolDir, aSysPath ) )
     202             :     {
     203             :         // Conversion did not work, as this is quite a dangerous action,
     204             :         // we should abort here ....
     205             :         OSL_FAIL( "psprint: couldn't remove spool directory" );
     206           0 :         return;
     207             :     }
     208             :     rtl::OString aSysPathByte =
     209           0 :         rtl::OUStringToOString (aSysPath, osl_getThreadTextEncoding());
     210             :     sal_Char  pSystem [128];
     211           0 :     sal_Int32 nChar = 0;
     212             : 
     213           0 :     nChar  = psp::appendStr ("rm -rf ",     pSystem);
     214           0 :     nChar += psp::appendStr (aSysPathByte.getStr(), pSystem + nChar);
     215             : 
     216           0 :     if (system (pSystem) == -1)
     217           0 :         OSL_FAIL( "psprint: couldn't remove spool directory" );
     218             : }
     219             : 
     220             : /* creates a spool directory with a "pidgin random" value based on
     221             :    current system time */
     222             : rtl::OUString
     223           0 : createSpoolDir ()
     224             : {
     225             :     TimeValue aCur;
     226           0 :     osl_getSystemTime( &aCur );
     227           0 :     sal_Int32 nRand = aCur.Seconds ^ (aCur.Nanosec/1000);
     228             : 
     229           0 :     rtl::OUString aTmpDir;
     230           0 :     osl_getTempDirURL( &aTmpDir.pData );
     231             : 
     232           0 :     do
     233             :     {
     234           0 :         rtl::OUStringBuffer aDir( aTmpDir.getLength() + 16 );
     235           0 :         aDir.append( aTmpDir );
     236           0 :         aDir.appendAscii( "/psp" );
     237           0 :         aDir.append(nRand);
     238           0 :         rtl::OUString aResult = aDir.makeStringAndClear();
     239           0 :         if( osl::Directory::create( aResult ) == osl::FileBase::E_None )
     240             :         {
     241             :             osl::File::setAttributes( aResult,
     242             :                                         osl_File_Attribute_OwnWrite
     243             :                                       | osl_File_Attribute_OwnRead
     244           0 :                                       | osl_File_Attribute_OwnExe );
     245           0 :             return aResult;
     246             :         }
     247           0 :         nRand++;
     248             :     } while( nRand );
     249           0 :     return rtl::OUString();
     250             : }
     251             : 
     252           0 : PrinterJob::~PrinterJob ()
     253             : {
     254           0 :     std::list< osl::File* >::iterator pPage;
     255           0 :     for (pPage = maPageList.begin(); pPage != maPageList.end(); ++pPage)
     256             :     {
     257             :         //(*pPage)->remove();
     258           0 :         delete *pPage;
     259             :     }
     260           0 :     for (pPage = maHeaderList.begin(); pPage != maHeaderList.end(); ++pPage)
     261             :     {
     262             :         //(*pPage)->remove();
     263           0 :         delete *pPage;
     264             :     }
     265             :     // mpJobHeader->remove();
     266           0 :     delete mpJobHeader;
     267             :     // mpJobTrailer->remove();
     268           0 :     delete mpJobTrailer;
     269             : 
     270             :     // XXX should really call osl::remove routines
     271           0 :     if( !maSpoolDirName.isEmpty() )
     272           0 :         removeSpoolDir (maSpoolDirName);
     273             : 
     274             :     // osl::Directory::remove (maSpoolDirName);
     275           0 : }
     276             : 
     277           0 : static void WriteLocalTimePS( osl::File *rFile )
     278             : {
     279             :     TimeValue m_start_time, tLocal;
     280             :     oslDateTime date_time;
     281           0 :     if (osl_getSystemTime( &m_start_time ) &&
     282           0 :         osl_getLocalTimeFromSystemTime( &m_start_time, &tLocal ) &&
     283           0 :         osl_getDateTimeFromTimeValue( &tLocal, &date_time ))
     284             :     {
     285             :         char ar[ 256 ];
     286             :         snprintf(
     287             :             ar, sizeof (ar),
     288             :             "%04d-%02d-%02d %02d:%02d:%02d ",
     289             :             date_time.Year, date_time.Month, date_time.Day,
     290           0 :             date_time.Hours, date_time.Minutes, date_time.Seconds );
     291           0 :         WritePS( rFile, ar );
     292             :     }
     293             :     else
     294           0 :         WritePS( rFile, "Unknown-Time" );
     295           0 : }
     296             : 
     297           0 : static bool isAscii( const rtl::OUString& rStr )
     298             : {
     299           0 :     sal_Int32 nLen = rStr.getLength();
     300           0 :     for( sal_Int32 i = 0; i < nLen; i++ )
     301           0 :         if( rStr[i] > 127 )
     302           0 :             return false;
     303           0 :     return true;
     304             : }
     305             : 
     306             : sal_Bool
     307           0 : PrinterJob::StartJob (
     308             :                       const rtl::OUString& rFileName,
     309             :                       int nMode,
     310             :                       const rtl::OUString& rJobName,
     311             :                       const rtl::OUString& rAppName,
     312             :                       const JobData& rSetupData,
     313             :                       PrinterGfx* pGraphics,
     314             :                       bool bIsQuickJob
     315             :                       )
     316             : {
     317           0 :     m_bQuickJob = bIsQuickJob;
     318           0 :     mnMaxWidthPt = mnMaxHeightPt = 0;
     319           0 :     mnLandscapes = mnPortraits = 0;
     320           0 :     m_pGraphics = pGraphics;
     321           0 :     InitPaperSize (rSetupData);
     322             : 
     323             :     // create file container for document header and trailer
     324           0 :     maFileName = rFileName;
     325           0 :     mnFileMode = nMode;
     326           0 :     maSpoolDirName = createSpoolDir ();
     327           0 :     maJobTitle = rJobName;
     328             : 
     329           0 :     rtl::OUString aExt(".ps");
     330           0 :     mpJobHeader  = CreateSpoolFile (rtl::OUString("psp_head"), aExt);
     331           0 :     mpJobTrailer = CreateSpoolFile (rtl::OUString("psp_tail"), aExt);
     332           0 :     if( ! (mpJobHeader && mpJobTrailer) ) // existing files are removed in destructor
     333           0 :         return sal_False;
     334             : 
     335             :     // write document header according to Document Structuring Conventions (DSC)
     336             :     WritePS (mpJobHeader,
     337             :              "%!PS-Adobe-3.0\n"
     338           0 :              "%%BoundingBox: (atend)\n" );
     339             : 
     340           0 :     rtl::OUString aFilterWS;
     341             : 
     342             :     // Creator (this application)
     343           0 :     aFilterWS = WhitespaceToSpace( rAppName, sal_False );
     344           0 :     WritePS (mpJobHeader, "%%Creator: (");
     345           0 :     WritePS (mpJobHeader, aFilterWS);
     346           0 :     WritePS (mpJobHeader, ")\n");
     347             : 
     348             :     // For (user name)
     349           0 :     osl::Security aSecurity;
     350           0 :     rtl::OUString aUserName;
     351           0 :     if( aSecurity.getUserName( aUserName ) )
     352             :     {
     353           0 :         WritePS (mpJobHeader, "%%For: (");
     354           0 :         WritePS (mpJobHeader, aUserName);
     355           0 :         WritePS (mpJobHeader, ")\n");
     356             :     }
     357             : 
     358             :     // Creation Date (locale independent local time)
     359           0 :     WritePS (mpJobHeader, "%%CreationDate: (");
     360           0 :     WriteLocalTimePS (mpJobHeader);
     361           0 :     WritePS (mpJobHeader, ")\n");
     362             : 
     363             :     // Document Title
     364             :     /* #i74335#
     365             :     * The title should be clean ascii; rJobName however may
     366             :     * contain any Unicode character. So implement the following
     367             :     * algorithm:
     368             :     * use rJobName, if it contains only ascii
     369             :     * use the filename, if it contains only ascii
     370             :     * else omit %%Title
     371             :     */
     372           0 :     aFilterWS = WhitespaceToSpace( rJobName, sal_False );
     373           0 :     rtl::OUString aTitle( aFilterWS );
     374           0 :     if( ! isAscii( aTitle ) )
     375             :     {
     376           0 :         sal_Int32 nIndex = 0;
     377           0 :         while( nIndex != -1 )
     378           0 :             aTitle = rFileName.getToken( 0, '/', nIndex );
     379           0 :         aTitle = WhitespaceToSpace( aTitle, sal_False );
     380           0 :         if( ! isAscii( aTitle ) )
     381           0 :             aTitle = rtl::OUString();
     382             :     }
     383             : 
     384           0 :     maJobTitle = aFilterWS;
     385           0 :     if( !aTitle.isEmpty() )
     386             :     {
     387           0 :         WritePS (mpJobHeader, "%%Title: (");
     388           0 :         WritePS (mpJobHeader, aTitle);
     389           0 :         WritePS (mpJobHeader, ")\n");
     390             :     }
     391             : 
     392             :     // Language Level
     393             :     sal_Char pLevel[16];
     394           0 :     sal_Int32 nSz = getValueOf(GetPostscriptLevel(&rSetupData), pLevel);
     395           0 :     pLevel[nSz++] = '\n';
     396           0 :     pLevel[nSz  ] = '\0';
     397           0 :     WritePS (mpJobHeader, "%%LanguageLevel: ");
     398           0 :     WritePS (mpJobHeader, pLevel);
     399             : 
     400             :     // Other
     401           0 :     WritePS (mpJobHeader, "%%DocumentData: Clean7Bit\n");
     402           0 :     WritePS (mpJobHeader, "%%Pages: (atend)\n");
     403           0 :     WritePS (mpJobHeader, "%%Orientation: (atend)\n");
     404           0 :     WritePS (mpJobHeader, "%%PageOrder: Ascend\n");
     405           0 :     WritePS (mpJobHeader, "%%EndComments\n");
     406             : 
     407             :     // write Prolog
     408           0 :     writeProlog (mpJobHeader, rSetupData);
     409             : 
     410             :     // mark last job setup as not set
     411           0 :     m_aLastJobData.m_pParser = NULL;
     412           0 :     m_aLastJobData.m_aContext.setParser( NULL );
     413             : 
     414           0 :     return sal_True;
     415             : }
     416             : 
     417             : sal_Bool
     418           0 : PrinterJob::EndJob ()
     419             : {
     420             :     // no pages ? that really means no print job
     421           0 :     if( maPageList.empty() )
     422           0 :         return sal_False;
     423             : 
     424             :     // write document setup (done here because it
     425             :     // includes the accumulated fonts
     426           0 :     if( mpJobHeader )
     427           0 :         writeSetup( mpJobHeader, m_aDocumentJobData );
     428           0 :     m_pGraphics->OnEndJob();
     429           0 :     if( ! (mpJobHeader && mpJobTrailer) )
     430           0 :         return sal_False;
     431             : 
     432             :     // write document trailer according to Document Structuring Conventions (DSC)
     433           0 :     rtl::OStringBuffer aTrailer(512);
     434           0 :     aTrailer.append( "%%Trailer\n" );
     435           0 :     aTrailer.append( "%%BoundingBox: 0 0 " );
     436           0 :     aTrailer.append( (sal_Int32)mnMaxWidthPt );
     437           0 :     aTrailer.append( " " );
     438           0 :     aTrailer.append( (sal_Int32)mnMaxHeightPt );
     439           0 :     if( mnLandscapes > mnPortraits )
     440           0 :         aTrailer.append("\n%%Orientation: Landscape");
     441             :     else
     442           0 :         aTrailer.append("\n%%Orientation: Portrait");
     443           0 :     aTrailer.append( "\n%%Pages: " );
     444           0 :     aTrailer.append( (sal_Int32)maPageList.size() );
     445           0 :     aTrailer.append( "\n%%EOF\n" );
     446           0 :     WritePS (mpJobTrailer, aTrailer.getStr());
     447             : 
     448             :     /*
     449             :      * spool the set of files to their final destination, this is U**X dependent
     450             :      */
     451             : 
     452           0 :     FILE* pDestFILE = NULL;
     453             : 
     454             :     /* create a destination either as file or as a pipe */
     455           0 :     sal_Bool bSpoolToFile = !maFileName.isEmpty();
     456           0 :     if (bSpoolToFile)
     457             :     {
     458             :         const rtl::OString aFileName = rtl::OUStringToOString (maFileName,
     459           0 :                                                                osl_getThreadTextEncoding());
     460           0 :         if( mnFileMode )
     461             :         {
     462           0 :             int nFile = open( aFileName.getStr(), O_CREAT | O_EXCL | O_RDWR, mnFileMode );
     463           0 :             if( nFile != -1 )
     464             :             {
     465           0 :                 pDestFILE = fdopen( nFile, "w" );
     466           0 :                 if( pDestFILE == NULL )
     467             :                 {
     468           0 :                     close( nFile );
     469           0 :                     unlink( aFileName.getStr() );
     470           0 :                     return sal_False;
     471             :                 }
     472             :             }
     473             :             else
     474           0 :                 chmod( aFileName.getStr(), mnFileMode );
     475             :         }
     476           0 :         if (pDestFILE == NULL)
     477           0 :             pDestFILE = fopen (aFileName.getStr(), "w");
     478             : 
     479           0 :         if (pDestFILE == NULL)
     480           0 :             return sal_False;
     481             :     }
     482             :     else
     483             :     {
     484           0 :         PrinterInfoManager& rPrinterInfoManager = PrinterInfoManager::get ();
     485           0 :         pDestFILE = rPrinterInfoManager.startSpool( m_aLastJobData.m_aPrinterName, m_bQuickJob );
     486           0 :         if (pDestFILE == NULL)
     487           0 :             return sal_False;
     488             :     }
     489             : 
     490             :     /* spool the document parts to the destination */
     491             : 
     492             :     sal_uChar pBuffer[ nBLOCKSIZE ];
     493             : 
     494           0 :     AppendPS (pDestFILE, mpJobHeader, pBuffer);
     495           0 :     mpJobHeader->close();
     496             : 
     497           0 :     sal_Bool bSuccess = sal_True;
     498           0 :     std::list< osl::File* >::iterator pPageBody;
     499           0 :     std::list< osl::File* >::iterator pPageHead;
     500           0 :     for (pPageBody  = maPageList.begin(), pPageHead  = maHeaderList.begin();
     501           0 :          pPageBody != maPageList.end() && pPageHead != maHeaderList.end();
     502             :          ++pPageBody, ++pPageHead)
     503             :     {
     504           0 :         if( *pPageHead )
     505             :         {
     506           0 :             osl::File::RC nError = (*pPageHead)->open(osl_File_OpenFlag_Read);
     507           0 :             if (nError == osl::File::E_None)
     508             :             {
     509           0 :                 AppendPS (pDestFILE, *pPageHead, pBuffer);
     510           0 :                 (*pPageHead)->close();
     511             :             }
     512             :         }
     513             :         else
     514           0 :             bSuccess = sal_False;
     515           0 :         if( *pPageBody )
     516             :         {
     517           0 :             osl::File::RC nError = (*pPageBody)->open(osl_File_OpenFlag_Read);
     518           0 :             if (nError == osl::File::E_None)
     519             :             {
     520           0 :                 AppendPS (pDestFILE, *pPageBody, pBuffer);
     521           0 :                 (*pPageBody)->close();
     522             :             }
     523             :         }
     524             :         else
     525           0 :             bSuccess = sal_False;
     526             :     }
     527             : 
     528           0 :     AppendPS (pDestFILE, mpJobTrailer, pBuffer);
     529           0 :     mpJobTrailer->close();
     530             : 
     531             :     /* well done */
     532             : 
     533           0 :     if (bSpoolToFile)
     534           0 :         fclose (pDestFILE);
     535             :     else
     536             :     {
     537           0 :         PrinterInfoManager& rPrinterInfoManager = PrinterInfoManager::get();
     538           0 :         if (0 == rPrinterInfoManager.endSpool( m_aLastJobData.m_aPrinterName,
     539           0 :             maJobTitle, pDestFILE, m_aDocumentJobData, true ))
     540             :         {
     541           0 :             bSuccess = sal_False;
     542             :         }
     543             :     }
     544             : 
     545           0 :     return bSuccess;
     546             : }
     547             : 
     548             : sal_Bool
     549           0 : PrinterJob::AbortJob ()
     550             : {
     551           0 :     m_pGraphics->OnEndJob();
     552           0 :     return sal_False;
     553             : }
     554             : 
     555             : void
     556           0 : PrinterJob::InitPaperSize (const JobData& rJobSetup)
     557             : {
     558           0 :     int nRes = rJobSetup.m_aContext.getRenderResolution ();
     559             : 
     560           0 :     rtl::OUString aPaper;
     561             :     int nWidth, nHeight;
     562           0 :     rJobSetup.m_aContext.getPageSize (aPaper, nWidth, nHeight);
     563             : 
     564           0 :     int nLeft = 0, nRight = 0, nUpper = 0, nLower = 0;
     565           0 :     const PPDParser* pParser = rJobSetup.m_aContext.getParser();
     566           0 :     if (pParser != NULL)
     567           0 :         pParser->getMargins (aPaper, nLeft, nRight, nUpper, nLower);
     568             : 
     569           0 :     mnResolution    = nRes;
     570             : 
     571           0 :     mnWidthPt       = nWidth;
     572           0 :     mnHeightPt      = nHeight;
     573             : 
     574           0 :     if( mnWidthPt > mnMaxWidthPt )
     575           0 :         mnMaxWidthPt = mnWidthPt;
     576           0 :     if( mnHeightPt > mnMaxHeightPt )
     577           0 :         mnMaxHeightPt = mnHeightPt;
     578             : 
     579           0 :     mnLMarginPt     = nLeft;
     580           0 :     mnRMarginPt     = nRight;
     581           0 :     mnTMarginPt     = nUpper;
     582           0 :     mnBMarginPt     = nLower;
     583             : 
     584           0 :     mfXScale        = (double)72.0 / (double)mnResolution;
     585           0 :     mfYScale        = -1.0 * (double)72.0 / (double)mnResolution;
     586           0 : }
     587             : 
     588             : 
     589             : sal_Bool
     590           0 : PrinterJob::StartPage (const JobData& rJobSetup)
     591             : {
     592           0 :     InitPaperSize (rJobSetup);
     593             : 
     594           0 :     rtl::OUString aPageNo = rtl::OUString::valueOf ((sal_Int32)maPageList.size()+1); // sequential page number must start with 1
     595           0 :     rtl::OUString aExt    = aPageNo + rtl::OUString(".ps");
     596             : 
     597           0 :     osl::File* pPageHeader = CreateSpoolFile ( rtl::OUString("psp_pghead"), aExt);
     598           0 :     osl::File* pPageBody   = CreateSpoolFile ( rtl::OUString("psp_pgbody"), aExt);
     599             : 
     600           0 :     maHeaderList.push_back (pPageHeader);
     601           0 :     maPageList.push_back (pPageBody);
     602             : 
     603           0 :     if( ! (pPageHeader && pPageBody) )
     604           0 :         return sal_False;
     605             : 
     606             :     // write page header according to Document Structuring Conventions (DSC)
     607           0 :     WritePS (pPageHeader, "%%Page: ");
     608           0 :     WritePS (pPageHeader, aPageNo);
     609           0 :     WritePS (pPageHeader, " ");
     610           0 :     WritePS (pPageHeader, aPageNo);
     611           0 :     WritePS (pPageHeader, "\n");
     612             : 
     613           0 :     if( rJobSetup.m_eOrientation == orientation::Landscape )
     614             :     {
     615           0 :         WritePS (pPageHeader, "%%PageOrientation: Landscape\n");
     616           0 :         mnLandscapes++;
     617             :     }
     618             :     else
     619             :     {
     620           0 :         WritePS (pPageHeader, "%%PageOrientation: Portrait\n");
     621           0 :         mnPortraits++;
     622             :     }
     623             : 
     624             :     sal_Char  pBBox [256];
     625           0 :     sal_Int32 nChar = 0;
     626             : 
     627           0 :     nChar  = psp::appendStr  ("%%PageBoundingBox: ",    pBBox);
     628           0 :     nChar += psp::getValueOf (mnLMarginPt,              pBBox + nChar);
     629           0 :     nChar += psp::appendStr  (" ",                      pBBox + nChar);
     630           0 :     nChar += psp::getValueOf (mnBMarginPt,              pBBox + nChar);
     631           0 :     nChar += psp::appendStr  (" ",                      pBBox + nChar);
     632           0 :     nChar += psp::getValueOf (mnWidthPt  - mnRMarginPt, pBBox + nChar);
     633           0 :     nChar += psp::appendStr  (" ",                      pBBox + nChar);
     634           0 :     nChar += psp::getValueOf (mnHeightPt - mnTMarginPt, pBBox + nChar);
     635           0 :     nChar += psp::appendStr  ("\n",                     pBBox + nChar);
     636             : 
     637           0 :     WritePS (pPageHeader, pBBox);
     638             : 
     639             :     /* #i7262# #i65491# write setup only before first page
     640             :      *  (to %%Begin(End)Setup, instead of %%Begin(End)PageSetup)
     641             :      *  don't do this in StartJob since the jobsetup there may be
     642             :      *  different.
     643             :      */
     644           0 :     bool bWriteFeatures = true;
     645           0 :     if( 1 == maPageList.size() )
     646             :     {
     647           0 :         m_aDocumentJobData = rJobSetup;
     648           0 :         bWriteFeatures = false;
     649             :     }
     650             : 
     651           0 :     if ( writePageSetup( pPageHeader, rJobSetup, bWriteFeatures ) )
     652             :     {
     653           0 :         m_aLastJobData = rJobSetup;
     654           0 :         return true;
     655             :     }
     656             : 
     657           0 :     return false;
     658             : }
     659             : 
     660             : sal_Bool
     661           0 : PrinterJob::EndPage ()
     662             : {
     663           0 :     m_pGraphics->OnEndPage();
     664             : 
     665           0 :     osl::File* pPageHeader = maHeaderList.back();
     666           0 :     osl::File* pPageBody   = maPageList.back();
     667             : 
     668           0 :     if( ! (pPageBody && pPageHeader) )
     669           0 :         return sal_False;
     670             : 
     671             :     // copy page to paper and write page trailer according to DSC
     672             : 
     673             :     sal_Char pTrailer[256];
     674           0 :     sal_Int32 nChar = 0;
     675           0 :     nChar  = psp::appendStr ("grestore grestore\n", pTrailer);
     676           0 :     nChar += psp::appendStr ("showpage\n",          pTrailer + nChar);
     677           0 :     nChar += psp::appendStr ("%%PageTrailer\n\n",   pTrailer + nChar);
     678           0 :     WritePS (pPageBody, pTrailer);
     679             : 
     680             :     // this page is done for now, close it to avoid having too many open fd's
     681             : 
     682           0 :     pPageHeader->close();
     683           0 :     pPageBody->close();
     684             : 
     685           0 :     return sal_True;
     686             : }
     687             : 
     688             : struct less_ppd_key : public ::std::binary_function<double, double, bool>
     689             : {
     690           0 :     bool operator()(const PPDKey* left, const PPDKey* right)
     691           0 :     { return left->getOrderDependency() < right->getOrderDependency(); }
     692             : };
     693             : 
     694           0 : static bool writeFeature( osl::File* pFile, const PPDKey* pKey, const PPDValue* pValue, bool bUseIncluseFeature )
     695             : {
     696           0 :     if( ! pKey || ! pValue )
     697           0 :         return true;
     698             : 
     699           0 :     OStringBuffer aFeature(256);
     700           0 :     aFeature.append( "[{\n" );
     701           0 :     if( bUseIncluseFeature )
     702           0 :         aFeature.append( "%%IncludeFeature:" );
     703             :     else
     704           0 :         aFeature.append( "%%BeginFeature:" );
     705           0 :     aFeature.append( " *" );
     706           0 :     aFeature.append( OUStringToOString( pKey->getKey(), RTL_TEXTENCODING_ASCII_US ) );
     707           0 :     aFeature.append( ' ' );
     708           0 :     aFeature.append( OUStringToOString( pValue->m_aOption, RTL_TEXTENCODING_ASCII_US ) );
     709           0 :     if( !bUseIncluseFeature )
     710             :     {
     711           0 :         aFeature.append( '\n' );
     712           0 :         aFeature.append( OUStringToOString( pValue->m_aValue, RTL_TEXTENCODING_ASCII_US ) );
     713           0 :         aFeature.append( "\n%%EndFeature" );
     714             :     }
     715           0 :     aFeature.append( "\n} stopped cleartomark\n" );
     716           0 :     sal_uInt64 nWritten = 0;
     717           0 :     return pFile->write( aFeature.getStr(), aFeature.getLength(), nWritten )
     718           0 :         || nWritten != (sal_uInt64)aFeature.getLength() ? false : true;
     719             : }
     720             : 
     721           0 : bool PrinterJob::writeFeatureList( osl::File* pFile, const JobData& rJob, bool bDocumentSetup )
     722             : {
     723           0 :     bool bSuccess = true;
     724             : 
     725             :     // emit features ordered to OrderDependency
     726             :     // ignore features that are set to default
     727             : 
     728             :     // sanity check
     729           0 :     if( rJob.m_pParser == rJob.m_aContext.getParser() &&
     730             :         rJob.m_pParser &&
     731             :         ( m_aLastJobData.m_pParser == rJob.m_pParser || m_aLastJobData.m_pParser == NULL )
     732             :         )
     733             :     {
     734             :         int i;
     735           0 :         int nKeys = rJob.m_aContext.countValuesModified();
     736           0 :         ::std::vector< const PPDKey* > aKeys( nKeys );
     737           0 :         for(  i = 0; i < nKeys; i++ )
     738           0 :             aKeys[i] = rJob.m_aContext.getModifiedKey( i );
     739           0 :         ::std::sort( aKeys.begin(), aKeys.end(), less_ppd_key() );
     740             : 
     741           0 :         for( i = 0; i < nKeys && bSuccess; i++ )
     742             :         {
     743           0 :             const PPDKey* pKey = aKeys[i];
     744           0 :             bool bEmit = false;
     745           0 :             if( bDocumentSetup )
     746             :             {
     747           0 :                 if( pKey->getSetupType()    == PPDKey::DocumentSetup )
     748           0 :                     bEmit = true;
     749             :             }
     750           0 :             if( pKey->getSetupType()    == PPDKey::PageSetup        ||
     751           0 :                 pKey->getSetupType()    == PPDKey::AnySetup )
     752           0 :                 bEmit = true;
     753           0 :             if( bEmit )
     754             :             {
     755           0 :                 const PPDValue* pValue = rJob.m_aContext.getValue( pKey );
     756           0 :                 if( pValue
     757             :                     && pValue->m_eType == eInvocation
     758             :                     && ( m_aLastJobData.m_pParser == NULL
     759           0 :                          || m_aLastJobData.m_aContext.getValue( pKey ) != pValue
     760             :                          || bDocumentSetup
     761             :                          )
     762             :                    )
     763             :                 {
     764             :                     // try to avoid PS level 2 feature commands if level is set to 1
     765           0 :                     if( GetPostscriptLevel( &rJob ) == 1 )
     766             :                     {
     767             :                         bool bHavePS2 =
     768           0 :                             ( pValue->m_aValue.SearchAscii( "<<" ) != STRING_NOTFOUND )
     769             :                             ||
     770           0 :                             ( pValue->m_aValue.SearchAscii( ">>" ) != STRING_NOTFOUND );
     771           0 :                         if( bHavePS2 )
     772           0 :                             continue;
     773             :                     }
     774           0 :                     bSuccess = writeFeature( pFile, pKey, pValue, PrinterInfoManager::get().getUseIncludeFeature() );
     775             :                 }
     776             :             }
     777           0 :         }
     778             :     }
     779             :     else
     780           0 :         bSuccess = false;
     781             : 
     782           0 :     return bSuccess;
     783             : }
     784             : 
     785           0 : bool PrinterJob::writePageSetup( osl::File* pFile, const JobData& rJob, bool bWriteFeatures )
     786             : {
     787           0 :     bool bSuccess = true;
     788             : 
     789           0 :     WritePS (pFile, "%%BeginPageSetup\n%\n");
     790           0 :     if ( bWriteFeatures )
     791           0 :         bSuccess = writeFeatureList( pFile, rJob, false );
     792           0 :     WritePS (pFile, "%%EndPageSetup\n");
     793             : 
     794             :     sal_Char  pTranslate [128];
     795           0 :     sal_Int32 nChar = 0;
     796             : 
     797           0 :     if( rJob.m_eOrientation == orientation::Portrait )
     798             :     {
     799           0 :         nChar  = psp::appendStr  ("gsave\n[",   pTranslate);
     800           0 :         nChar += psp::getValueOfDouble (        pTranslate + nChar, mfXScale, 5);
     801           0 :         nChar += psp::appendStr  (" 0 0 ",      pTranslate + nChar);
     802           0 :         nChar += psp::getValueOfDouble (        pTranslate + nChar, mfYScale, 5);
     803           0 :         nChar += psp::appendStr  (" ",          pTranslate + nChar);
     804           0 :         nChar += psp::getValueOf (mnRMarginPt,  pTranslate + nChar);
     805           0 :         nChar += psp::appendStr  (" ",          pTranslate + nChar);
     806             :         nChar += psp::getValueOf (mnHeightPt-mnTMarginPt,
     807           0 :                                   pTranslate + nChar);
     808             :         nChar += psp::appendStr  ("] concat\ngsave\n",
     809           0 :                                   pTranslate + nChar);
     810             :     }
     811             :     else
     812             :     {
     813           0 :         nChar  = psp::appendStr  ("gsave\n",    pTranslate);
     814           0 :         nChar += psp::appendStr  ("[ 0 ",       pTranslate + nChar);
     815           0 :         nChar += psp::getValueOfDouble (        pTranslate + nChar, -mfYScale, 5);
     816           0 :         nChar += psp::appendStr  (" ",          pTranslate + nChar);
     817           0 :         nChar += psp::getValueOfDouble (        pTranslate + nChar, mfXScale, 5);
     818           0 :         nChar += psp::appendStr  (" 0 ",        pTranslate + nChar );
     819           0 :         nChar += psp::getValueOfDouble (        pTranslate + nChar, mnLMarginPt, 5 );
     820           0 :         nChar += psp::appendStr  (" ",          pTranslate + nChar);
     821           0 :         nChar += psp::getValueOf (mnBMarginPt,  pTranslate + nChar );
     822             :         nChar += psp::appendStr ("] concat\ngsave\n",
     823           0 :                                  pTranslate + nChar);
     824             :     }
     825             : 
     826           0 :     WritePS (pFile, pTranslate);
     827             : 
     828           0 :     return bSuccess;
     829             : }
     830             : 
     831           0 : void PrinterJob::writeJobPatch( osl::File* pFile, const JobData& rJobData )
     832             : {
     833           0 :     if( ! PrinterInfoManager::get().getUseJobPatch() )
     834             :         return;
     835             : 
     836           0 :     const PPDKey* pKey = NULL;
     837             : 
     838           0 :     if( rJobData.m_pParser )
     839           0 :         pKey = rJobData.m_pParser->getKey( OUString( "JobPatchFile"  ) );
     840           0 :     if( ! pKey )
     841             :         return;
     842             : 
     843             :     // order the patch files
     844             :     // according to PPD spec the JobPatchFile options must be int
     845             :     // and should be emitted in order
     846           0 :     std::list< sal_Int32 > patch_order;
     847           0 :     int nValueCount = pKey->countValues();
     848           0 :     for( int i = 0; i < nValueCount; i++ )
     849             :     {
     850           0 :         const PPDValue* pVal = pKey->getValue( i );
     851           0 :         patch_order.push_back( pVal->m_aOption.ToInt32() );
     852           0 :         if( patch_order.back() == 0 && ! pVal->m_aOption.EqualsAscii( "0" ) )
     853             :         {
     854           0 :             WritePS( pFile, "% Warning: left out JobPatchFile option \"" );
     855           0 :             OString aOption = OUStringToOString( pVal->m_aOption, RTL_TEXTENCODING_ASCII_US );
     856           0 :             WritePS( pFile, aOption.getStr() );
     857             :             WritePS( pFile,
     858             :                      "\"\n% as it violates the PPD spec;\n"
     859           0 :                      "% JobPatchFile options need to be numbered for ordering.\n" );
     860             :         }
     861             :     }
     862             : 
     863           0 :     patch_order.sort();
     864           0 :     patch_order.unique();
     865             : 
     866           0 :     while( patch_order.begin() != patch_order.end() )
     867             :     {
     868             :         // note: this discards patch files not adhering to the "int" scheme
     869             :         // as there won't be a value for them
     870           0 :         writeFeature( pFile, pKey, pKey->getValue( OUString::valueOf( patch_order.front() ) ), false );
     871           0 :         patch_order.pop_front();
     872           0 :     }
     873             : }
     874             : 
     875           0 : bool PrinterJob::writeProlog (osl::File* pFile, const JobData& rJobData )
     876             : {
     877           0 :     WritePS( pFile, "%%BeginProlog\n" );
     878             : 
     879             :     // JobPatchFile feature needs to be emitted at begin of prolog
     880           0 :     writeJobPatch( pFile, rJobData );
     881             : 
     882             :     static const sal_Char pProlog[] = {
     883             :         "%%BeginResource: procset PSPrint-Prolog 1.0 0\n"
     884             :         "/ISO1252Encoding [\n"
     885             :         "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
     886             :         "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
     887             :         "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
     888             :         "/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef\n"
     889             :         "/space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quotesingle\n"
     890             :         "/parenleft /parenright /asterisk /plus /comma /hyphen /period /slash\n"
     891             :         "/zero /one /two /three /four /five /six /seven\n"
     892             :         "/eight /nine /colon /semicolon /less /equal /greater /question\n"
     893             :         "/at /A /B /C /D /E /F /G\n"
     894             :         "/H /I /J /K /L /M /N /O\n"
     895             :         "/P /Q /R /S /T /U /V /W\n"
     896             :         "/X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore\n"
     897             :         "/grave /a /b /c /d /e /f /g\n"
     898             :         "/h /i /j /k /l /m /n /o\n"
     899             :         "/p /q /r /s /t /u /v /w\n"
     900             :         "/x /y /z /braceleft /bar /braceright /asciitilde /unused\n"
     901             :         "/Euro /unused /quotesinglbase /florin /quotedblbase /ellipsis /dagger /daggerdbl\n"
     902             :         "/circumflex /perthousand /Scaron /guilsinglleft /OE /unused /Zcaron /unused\n"
     903             :         "/unused /quoteleft /quoteright /quotedblleft /quotedblright /bullet /endash /emdash\n"
     904             :         "/tilde /trademark /scaron /guilsinglright /oe /unused /zcaron /Ydieresis\n"
     905             :         "/space /exclamdown /cent /sterling /currency /yen /brokenbar /section\n"
     906             :         "/dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron\n"
     907             :         "/degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph /periodcentered\n"
     908             :         "/cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf /threequarters /questiondown\n"
     909             :         "/Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla\n"
     910             :         "/Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis\n"
     911             :         "/Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply\n"
     912             :         "/Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls\n"
     913             :         "/agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla\n"
     914             :         "/egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis\n"
     915             :         "/eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide\n"
     916             :         "/oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis] def\n"
     917             :         "\n"
     918             :         "/psp_definefont { exch dup findfont dup length dict begin { 1 index /FID ne\n"
     919             :         "{ def } { pop pop } ifelse } forall /Encoding 3 -1 roll def\n"
     920             :         "currentdict end exch pop definefont pop } def\n"
     921             :         "\n"
     922             :         "/pathdict dup 8 dict def load begin\n"
     923             :         "/rcmd { { currentfile 1 string readstring pop 0 get dup 32 gt { exit }\n"
     924             :         "{ pop } ifelse } loop dup 126 eq { pop exit } if 65 sub dup 16#3 and 1\n"
     925             :         "add exch dup 16#C and -2 bitshift 16#3 and 1 add exch 16#10 and 16#10\n"
     926             :         "eq 3 1 roll exch } def\n"
     927             :         "/rhex { dup 1 sub exch currentfile exch string readhexstring pop dup 0\n"
     928             :         "get dup 16#80 and 16#80 eq dup 3 1 roll { 16#7f and } if 2 index 0 3\n"
     929             :         "-1 roll put 3 1 roll 0 0 1 5 -1 roll { 2 index exch get add 256 mul }\n"
     930             :         "for 256 div exch pop exch { neg } if } def\n"
     931             :         "/xcmd { rcmd exch rhex exch rhex exch 5 -1 roll add exch 4 -1 roll add\n"
     932             :         "1 index 1 index 5 -1 roll { moveto } { lineto } ifelse } def end\n"
     933             :         "/readpath { 0 0 pathdict begin { xcmd } loop end pop pop } def\n"
     934             :         "\n"
     935             :         "systemdict /languagelevel known not {\n"
     936             :         "/xshow { exch dup length 0 1 3 -1 roll 1 sub { dup 3 index exch get\n"
     937             :         "exch 2 index exch get 1 string dup 0 4 -1 roll put currentpoint 3 -1\n"
     938             :         "roll show moveto 0 rmoveto } for pop pop } def\n"
     939             :         "/rectangle { 4 -2 roll moveto 1 index 0 rlineto 0 exch rlineto neg 0\n"
     940             :         "rlineto closepath } def\n"
     941             :         "/rectfill { rectangle fill } def\n"
     942             :         "/rectstroke { rectangle stroke } def } if\n"
     943             :         "/bshow { currentlinewidth 3 1 roll currentpoint 3 index show moveto\n"
     944             :         "setlinewidth false charpath stroke setlinewidth } def\n"
     945             :         "/bxshow { currentlinewidth 4 1 roll setlinewidth exch dup length 1 sub\n"
     946             :         "0 1 3 -1 roll { 1 string 2 index 2 index get 1 index exch 0 exch put dup\n"
     947             :         "currentpoint 3 -1 roll show moveto currentpoint 3 -1 roll false charpath\n"
     948             :         "stroke moveto 2 index exch get 0 rmoveto } for pop pop setlinewidth } def\n"
     949             :         "\n"
     950             :         "/psp_lzwfilter { currentfile /ASCII85Decode filter /LZWDecode filter } def\n"
     951             :         "/psp_ascii85filter { currentfile /ASCII85Decode filter } def\n"
     952             :         "/psp_lzwstring { psp_lzwfilter 1024 string readstring } def\n"
     953             :         "/psp_ascii85string { psp_ascii85filter 1024 string readstring } def\n"
     954             :         "/psp_imagedict {\n"
     955             :         "/psp_bitspercomponent { 3 eq { 1 }{ 8 } ifelse } def\n"
     956             :         "/psp_decodearray { [ [0 1 0 1 0 1] [0 255] [0 1] [0 255] ] exch get }\n"
     957             :         "def 7 dict dup\n"
     958             :         "/ImageType 1 put dup\n"
     959             :         "/Width 7 -1 roll put dup\n"
     960             :         "/Height 5 index put dup\n"
     961             :         "/BitsPerComponent 4 index psp_bitspercomponent put dup\n"
     962             :         "/Decode 5 -1 roll psp_decodearray put dup\n"
     963             :         "/ImageMatrix [1 0 0 1 0 0] dup 5 8 -1 roll put put dup\n"
     964             :         "/DataSource 4 -1 roll 1 eq { psp_lzwfilter } { psp_ascii85filter } ifelse put\n"
     965             :         "} def\n"
     966             :         "%%EndResource\n"
     967             :         "%%EndProlog\n"
     968             :     };
     969           0 :     WritePS (pFile, pProlog);
     970             : 
     971           0 :     return true;
     972             : }
     973             : 
     974           0 : bool PrinterJob::writeSetup( osl::File* pFile, const JobData& rJob )
     975             : {
     976           0 :     WritePS (pFile, "%%BeginSetup\n%\n");
     977             : 
     978             :     // download fonts
     979           0 :     std::list< rtl::OString > aFonts[2];
     980           0 :     m_pGraphics->writeResources( pFile, aFonts[0], aFonts[1] );
     981             : 
     982           0 :     for( int i = 0; i < 2; i++ )
     983             :     {
     984           0 :         if( !aFonts[i].empty() )
     985             :         {
     986           0 :             std::list< rtl::OString >::const_iterator it = aFonts[i].begin();
     987           0 :             rtl::OStringBuffer aLine( 256 );
     988           0 :             if( i == 0 )
     989           0 :                 aLine.append( "%%DocumentSuppliedResources: font " );
     990             :             else
     991           0 :                 aLine.append( "%%DocumentNeededResources: font " );
     992           0 :             aLine.append( *it );
     993           0 :             aLine.append( "\n" );
     994           0 :             WritePS ( pFile, aLine.getStr() );
     995           0 :             while( (++it) != aFonts[i].end() )
     996             :             {
     997           0 :                 aLine.setLength(0);
     998           0 :                 aLine.append( "%%+ font " );
     999           0 :                 aLine.append( *it );
    1000           0 :                 aLine.append( "\n" );
    1001           0 :                 WritePS ( pFile, aLine.getStr() );
    1002           0 :             }
    1003             :         }
    1004             :     }
    1005             : 
    1006           0 :     bool bSuccess = true;
    1007             :     // in case of external print dialog the number of copies is prepended
    1008             :     // to the job, let us not complicate things by emitting our own copy count
    1009           0 :     bool bExternalDialog = PrinterInfoManager::get().checkFeatureToken( GetPrinterName(), "external_dialog" );
    1010           0 :     if( ! bExternalDialog && rJob.m_nCopies > 1 )
    1011             :     {
    1012             :         // setup code
    1013           0 :         rtl::OStringBuffer aLine(RTL_CONSTASCII_STRINGPARAM("/#copies "));
    1014           0 :         aLine.append(static_cast<sal_Int32>(rJob.m_nCopies));
    1015           0 :         aLine.append(RTL_CONSTASCII_STRINGPARAM(" def\n"));
    1016           0 :         sal_uInt64 nWritten = 0;
    1017           0 :         bSuccess = pFile->write(aLine.getStr(), aLine.getLength(), nWritten)
    1018           0 :             || nWritten != static_cast<sal_uInt64>(aLine.getLength()) ?
    1019           0 :              false : true;
    1020             : 
    1021           0 :         if( bSuccess && GetPostscriptLevel( &rJob ) >= 2 )
    1022           0 :             WritePS (pFile, "<< /NumCopies null /Policies << /NumCopies 1 >> >> setpagedevice\n" );
    1023             :     }
    1024             : 
    1025           0 :     bool bFeatureSuccess = writeFeatureList( pFile, rJob, true );
    1026             : 
    1027           0 :     WritePS (pFile, "%%EndSetup\n");
    1028             : 
    1029           0 :     return bSuccess && bFeatureSuccess;
    1030             : }
    1031             : 
    1032             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10