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: */
|