LCOV - code coverage report
Current view: top level - vcl/generic/print - printerjob.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 464 0.0 %
Date: 2012-08-25 Functions: 0 27 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 788 0.0 %

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

Generated by: LCOV version 1.10