xref: /trunk/main/vcl/aqua/source/gdi/salprn.cxx (revision 4696c98e)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 #include <boost/bind.hpp>
28 
29 #include "vcl/print.hxx"
30 #include "vcl/unohelp.hxx"
31 
32 #include "aqua/salinst.h"
33 #include "aqua/salprn.h"
34 #include "aqua/aquaprintview.h"
35 #include "aqua/salgdi.h"
36 #include "aqua/saldata.hxx"
37 
38 #include "jobset.h"
39 #include "salptype.hxx"
40 
41 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
42 #include "com/sun/star/container/XNameAccess.hpp"
43 #include "com/sun/star/beans/PropertyValue.hpp"
44 #include "com/sun/star/awt/Size.hpp"
45 
46 #include <algorithm>
47 
48 using namespace rtl;
49 using namespace vcl;
50 using namespace com::sun::star;
51 using namespace com::sun::star::uno;
52 using namespace com::sun::star::lang;
53 using namespace com::sun::star::beans;
54 using namespace com::sun::star::container;
55 
56 // =======================================================================
57 
AquaSalInfoPrinter(const SalPrinterQueueInfo & i_rQueue)58 AquaSalInfoPrinter::AquaSalInfoPrinter( const SalPrinterQueueInfo& i_rQueue ) :
59     mpGraphics( 0 ),
60     mbGraphics( false ),
61     mbJob( false ),
62     mpPrinter( nil ),
63     mpPrintInfo( nil ),
64     mePageOrientation( ORIENTATION_PORTRAIT ),
65     mnStartPageOffsetX( 0 ),
66     mnStartPageOffsetY( 0 ),
67     mnCurPageRangeStart( 0 ),
68     mnCurPageRangeCount( 0 )
69 {
70     NSString* pStr = CreateNSString( i_rQueue.maPrinterName );
71     mpPrinter = [NSPrinter printerWithName: pStr];
72     [pStr release];
73 
74     NSPrintInfo* pShared = [NSPrintInfo sharedPrintInfo];
75     if( pShared )
76     {
77         mpPrintInfo = [pShared copy];
78         [mpPrintInfo setPrinter: mpPrinter];
79 #if 1 // code for SDK 10.9 or newer
80         mePageOrientation = ([mpPrintInfo orientation] == NSPaperOrientationLandscape) ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
81         [mpPrintInfo setOrientation: NSPaperOrientationPortrait];
82 #else // code for SDK 10.8 or older
83         mePageOrientation = ([mpPrintInfo orientation] == NSLandscapeOrientation) ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
84         [mpPrintInfo setOrientation: NSPortraitOrientation];
85 #endif
86     }
87 
88     mpGraphics = new AquaSalGraphics();
89 
90     const int nWidth = 100, nHeight = 100;
91     maContextMemory.reset( reinterpret_cast<sal_uInt8*>( rtl_allocateMemory( nWidth * 4 * nHeight ) ),
92                            boost::bind( rtl_freeMemory, _1 ) );
93 
94     if( maContextMemory )
95     {
96         mrContext = CGBitmapContextCreate( maContextMemory.get(), nWidth, nHeight, 8, nWidth * 4, GetSalData()->mxRGBSpace, kCGImageAlphaNoneSkipFirst );
97         if( mrContext )
98             SetupPrinterGraphics( mrContext );
99     }
100 }
101 
102 // -----------------------------------------------------------------------
103 
~AquaSalInfoPrinter()104 AquaSalInfoPrinter::~AquaSalInfoPrinter()
105 {
106     delete mpGraphics;
107     if( mpPrintInfo )
108         [mpPrintInfo release];
109     #if 0
110     // FIXME: verify that NSPrintInfo releases the printer
111     // else we have a leak here
112     if( mpPrinter )
113         [mpPrinter release];
114     #endif
115     if( mrContext )
116         CFRelease( mrContext );
117 }
118 
119 // -----------------------------------------------------------------------
120 
SetupPrinterGraphics(CGContextRef i_rContext) const121 void AquaSalInfoPrinter::SetupPrinterGraphics( CGContextRef i_rContext ) const
122 {
123     if( mpGraphics )
124     {
125         if( mpPrintInfo )
126         {
127             // FIXME: get printer resolution
128             long nDPIX = 720, nDPIY = 720;
129             NSSize aPaperSize = [mpPrintInfo paperSize];
130 
131             NSRect aImageRect = [mpPrintInfo imageablePageBounds];
132             if( mePageOrientation == ORIENTATION_PORTRAIT )
133             {
134                 // move mirrored CTM back into paper
135                 double dX = 0, dY = aPaperSize.height;
136                 // move CTM to reflect imageable area
137                 dX += aImageRect.origin.x;
138                 dY -= aPaperSize.height - aImageRect.size.height - aImageRect.origin.y;
139                 CGContextTranslateCTM( i_rContext, dX + mnStartPageOffsetX, dY - mnStartPageOffsetY );
140                 // scale to be top/down and reflect our "virtual" DPI
141                 CGContextScaleCTM( i_rContext, 72.0/double(nDPIX), -(72.0/double(nDPIY)) );
142             }
143             else
144             {
145                 // move CTM to reflect imageable area
146                 double dX = aImageRect.origin.x, dY = aPaperSize.height - aImageRect.size.height - aImageRect.origin.y;
147                 CGContextTranslateCTM( i_rContext, -dX, -dY );
148                 // turn by 90 degree
149                 CGContextRotateCTM( i_rContext, M_PI/2 );
150                 // move turned CTM back into paper
151                 dX = aPaperSize.height;
152                 dY = -aPaperSize.width;
153                 CGContextTranslateCTM( i_rContext, dX + mnStartPageOffsetY, dY - mnStartPageOffsetX );
154                 // scale to be top/down and reflect our "virtual" DPI
155                 CGContextScaleCTM( i_rContext, -(72.0/double(nDPIY)), (72.0/double(nDPIX)) );
156             }
157             mpGraphics->SetPrinterGraphics( i_rContext, nDPIX, nDPIY, 1.0 );
158         }
159         else
160             DBG_ERROR( "no print info in SetupPrinterGraphics" );
161     }
162 }
163 
164 // -----------------------------------------------------------------------
165 
GetGraphics()166 SalGraphics* AquaSalInfoPrinter::GetGraphics()
167 {
168     SalGraphics* pGraphics = mbGraphics ? NULL : mpGraphics;
169     mbGraphics = true;
170 	return pGraphics;
171 }
172 
173 // -----------------------------------------------------------------------
174 
ReleaseGraphics(SalGraphics *)175 void AquaSalInfoPrinter::ReleaseGraphics( SalGraphics* )
176 {
177     mbGraphics = false;
178 }
179 
180 // -----------------------------------------------------------------------
181 
Setup(SalFrame *,ImplJobSetup *)182 sal_Bool AquaSalInfoPrinter::Setup( SalFrame*, ImplJobSetup* )
183 {
184 	return sal_False;
185 }
186 
187 // -----------------------------------------------------------------------
188 
SetPrinterData(ImplJobSetup * io_pSetupData)189 sal_Bool AquaSalInfoPrinter::SetPrinterData( ImplJobSetup* io_pSetupData )
190 {
191     // FIXME: implement driver data
192     if( io_pSetupData && io_pSetupData->mpDriverData )
193         return SetData( ~0, io_pSetupData );
194 
195 
196     sal_Bool bSuccess = sal_True;
197 
198     // set system type
199     io_pSetupData->mnSystem = JOBSETUP_SYSTEM_MAC;
200 
201     // get paper format
202     if( mpPrintInfo )
203     {
204         NSSize aPaperSize = [mpPrintInfo paperSize];
205         double width = aPaperSize.width, height = aPaperSize.height;
206         // set paper
207         PaperInfo aInfo( PtTo10Mu( width ), PtTo10Mu( height ) );
208         aInfo.doSloppyFit();
209         io_pSetupData->mePaperFormat = aInfo.getPaper();
210         if( io_pSetupData->mePaperFormat == PAPER_USER )
211         {
212             io_pSetupData->mnPaperWidth = PtTo10Mu( width );
213             io_pSetupData->mnPaperHeight = PtTo10Mu( height );
214         }
215         else
216         {
217             io_pSetupData->mnPaperWidth = 0;
218             io_pSetupData->mnPaperHeight = 0;
219         }
220 
221         // set orientation
222         io_pSetupData->meOrientation = mePageOrientation;
223 
224         io_pSetupData->mnPaperBin = 0;
225         io_pSetupData->mpDriverData = reinterpret_cast<sal_uInt8*>(rtl_allocateMemory( 4 ));
226         io_pSetupData->mnDriverDataLen = 4;
227     }
228     else
229         bSuccess = sal_False;
230 
231 
232 	return bSuccess;
233 }
234 
235 // -----------------------------------------------------------------------
236 
setPaperSize(long i_nWidth,long i_nHeight,Orientation i_eSetOrientation)237 void AquaSalInfoPrinter::setPaperSize( long i_nWidth, long i_nHeight, Orientation i_eSetOrientation )
238 {
239 
240     Orientation ePaperOrientation = ORIENTATION_PORTRAIT;
241     const PaperInfo* pPaper = matchPaper( i_nWidth, i_nHeight, ePaperOrientation );
242 
243     if( pPaper )
244     {
245         NSString* pPaperName = [CreateNSString( rtl::OStringToOUString(PaperInfo::toPSName(pPaper->getPaper()), RTL_TEXTENCODING_ASCII_US) ) autorelease];
246         [mpPrintInfo setPaperName: pPaperName];
247     }
248     else if( i_nWidth > 0 && i_nHeight > 0 )
249     {
250         NSSize aPaperSize = NSMakeSize( TenMuToPt(i_nWidth), TenMuToPt(i_nHeight));
251         [mpPrintInfo setPaperSize: aPaperSize];
252     }
253     // this seems counterintuitive
254     mePageOrientation = i_eSetOrientation;
255 }
256 
257 // -----------------------------------------------------------------------
258 
SetData(sal_uLong i_nFlags,ImplJobSetup * io_pSetupData)259 sal_Bool AquaSalInfoPrinter::SetData( sal_uLong i_nFlags, ImplJobSetup* io_pSetupData )
260 {
261     if( ! io_pSetupData || io_pSetupData->mnSystem != JOBSETUP_SYSTEM_MAC )
262         return sal_False;
263 
264 
265     if( mpPrintInfo )
266     {
267         if( (i_nFlags & SAL_JOBSET_ORIENTATION) != 0 )
268             mePageOrientation = io_pSetupData->meOrientation;
269 
270         if( (i_nFlags & SAL_JOBSET_PAPERSIZE) !=  0)
271         {
272             // set paper format
273             long width = 21000, height = 29700;
274             if( io_pSetupData->mePaperFormat == PAPER_USER )
275             {
276                 // #i101108# sanity check
277                 if( io_pSetupData->mnPaperWidth && io_pSetupData->mnPaperHeight )
278                 {
279                     width = io_pSetupData->mnPaperWidth;
280                     height = io_pSetupData->mnPaperHeight;
281                 }
282             }
283             else
284             {
285                 PaperInfo aInfo( io_pSetupData->mePaperFormat );
286                 width = aInfo.getWidth();
287                 height = aInfo.getHeight();
288             }
289 
290             setPaperSize( width, height, mePageOrientation );
291         }
292     }
293 
294 	return mpPrintInfo != nil;
295 }
296 
297 // -----------------------------------------------------------------------
298 
GetPaperBinCount(const ImplJobSetup *)299 sal_uLong AquaSalInfoPrinter::GetPaperBinCount( const ImplJobSetup* )
300 {
301 	return 0;
302 }
303 
304 // -----------------------------------------------------------------------
305 
GetPaperBinName(const ImplJobSetup *,sal_uLong)306 XubString AquaSalInfoPrinter::GetPaperBinName( const ImplJobSetup*, sal_uLong )
307 {
308 	return XubString();
309 }
310 
311 // -----------------------------------------------------------------------
312 
getUseNativeDialog()313 static bool getUseNativeDialog()
314 {
315     bool bNative = true;
316     try
317     {
318         // get service provider
319         uno::Reference< XMultiServiceFactory > xSMgr( unohelper::GetMultiServiceFactory() );
320         // create configuration hierarchical access name
321         if( xSMgr.is() )
322         {
323             try
324             {
325                 uno::Reference< XMultiServiceFactory > xConfigProvider(
326                    uno::Reference< XMultiServiceFactory >(
327                         xSMgr->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
328                                         "com.sun.star.configuration.ConfigurationProvider" ))),
329                         UNO_QUERY )
330                     );
331                 if( xConfigProvider.is() )
332                 {
333                     Sequence< Any > aArgs(1);
334                     PropertyValue aVal;
335                     aVal.Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) );
336                     aVal.Value <<= OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/Misc" ) );
337                     aArgs.getArray()[0] <<= aVal;
338                     uno::Reference< XNameAccess > xConfigAccess(
339                         uno::Reference< XNameAccess >(
340                             xConfigProvider->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
341                                                 "com.sun.star.configuration.ConfigurationAccess" )),
342                                                                             aArgs ),
343                             UNO_QUERY )
344                         );
345                     if( xConfigAccess.is() )
346                     {
347                         try
348                         {
349                             sal_Bool bValue = sal_False;
350                             Any aAny = xConfigAccess->getByName( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseSystemPrintDialog" ) ) );
351                             if( aAny >>= bValue )
352                                 bNative = bValue;
353                         }
354                         catch( NoSuchElementException& )
355                         {
356                         }
357                         catch( WrappedTargetException& )
358                         {
359                         }
360                     }
361                 }
362             }
363             catch( Exception& )
364             {
365             }
366         }
367     }
368     catch( WrappedTargetException& )
369     {
370     }
371 
372     return bNative;
373 }
374 
GetCapabilities(const ImplJobSetup *,sal_uInt16 i_nType)375 sal_uLong AquaSalInfoPrinter::GetCapabilities( const ImplJobSetup*, sal_uInt16 i_nType )
376 {
377 	switch( i_nType )
378 	{
379 		case PRINTER_CAPABILITIES_SUPPORTDIALOG:
380 			return 0;
381 		case PRINTER_CAPABILITIES_COPIES:
382 			return 0xffff;
383 		case PRINTER_CAPABILITIES_COLLATECOPIES:
384 			return 0xffff;
385 		case PRINTER_CAPABILITIES_SETORIENTATION:
386 			return 1;
387 		case PRINTER_CAPABILITIES_SETDUPLEX:
388 			return 0;
389 		case PRINTER_CAPABILITIES_SETPAPERBIN:
390 			return 0;
391 		case PRINTER_CAPABILITIES_SETPAPERSIZE:
392 			return 1;
393 		case PRINTER_CAPABILITIES_SETPAPER:
394 			return 1;
395         case PRINTER_CAPABILITIES_EXTERNALDIALOG:
396             return getUseNativeDialog() ? 1 : 0;
397         case PRINTER_CAPABILITIES_PDF:
398             return 1;
399         case PRINTER_CAPABILITIES_USEPULLMODEL:
400             return 1;
401 		default: break;
402 	};
403 	return 0;
404 }
405 
406 // -----------------------------------------------------------------------
407 
GetPageInfo(const ImplJobSetup *,long & o_rOutWidth,long & o_rOutHeight,long & o_rPageOffX,long & o_rPageOffY,long & o_rPageWidth,long & o_rPageHeight)408 void AquaSalInfoPrinter::GetPageInfo( const ImplJobSetup*,
409 								  long& o_rOutWidth, long& o_rOutHeight,
410 								  long& o_rPageOffX, long& o_rPageOffY,
411 								  long& o_rPageWidth, long& o_rPageHeight )
412 {
413     if( mpPrintInfo )
414     {
415         sal_Int32 nDPIX = 72, nDPIY = 72;
416         mpGraphics->GetResolution( nDPIX, nDPIY );
417         const double fXScaling = static_cast<double>(nDPIX)/72.0,
418                      fYScaling = static_cast<double>(nDPIY)/72.0;
419 
420         NSSize aPaperSize = [mpPrintInfo paperSize];
421         o_rPageWidth  = static_cast<long>( double(aPaperSize.width) * fXScaling );
422         o_rPageHeight = static_cast<long>( double(aPaperSize.height) * fYScaling );
423 
424         NSRect aImageRect = [mpPrintInfo imageablePageBounds];
425         o_rPageOffX   = static_cast<long>( aImageRect.origin.x * fXScaling );
426         o_rPageOffY   = static_cast<long>( (aPaperSize.height - aImageRect.size.height - aImageRect.origin.y) * fYScaling );
427         o_rOutWidth   = static_cast<long>( aImageRect.size.width * fXScaling );
428         o_rOutHeight  = static_cast<long>( aImageRect.size.height * fYScaling );
429 
430         if( mePageOrientation == ORIENTATION_LANDSCAPE )
431         {
432             std::swap( o_rOutWidth, o_rOutHeight );
433             std::swap( o_rPageWidth, o_rPageHeight );
434             std::swap( o_rPageOffX, o_rPageOffY );
435         }
436     }
437 }
438 
getPageSize(vcl::PrinterController & i_rController,sal_Int32 i_nPage)439 static Size getPageSize( vcl::PrinterController& i_rController, sal_Int32 i_nPage )
440 {
441     Size aPageSize;
442     Sequence< PropertyValue > aPageParms( i_rController.getPageParameters( i_nPage ) );
443     for( sal_Int32 nProperty = 0, nPropertyCount = aPageParms.getLength(); nProperty < nPropertyCount; ++nProperty )
444     {
445         if( aPageParms[ nProperty ].Name.equalsAscii( "PageSize" ) )
446         {
447             awt::Size aSize;
448             aPageParms[ nProperty].Value >>= aSize;
449             aPageSize.Width() = aSize.Width;
450             aPageSize.Height() = aSize.Height;
451             break;
452         }
453     }
454     return aPageSize;
455 }
456 
StartJob(const String * i_pFileName,const String & i_rJobName,const String &,ImplJobSetup * i_pSetupData,vcl::PrinterController & i_rController)457 sal_Bool AquaSalInfoPrinter::StartJob( const String* i_pFileName,
458                                    const String& i_rJobName,
459                                    const String& /*i_rAppName*/,
460                                    ImplJobSetup* i_pSetupData,
461                                    vcl::PrinterController& i_rController
462                                    )
463 {
464     if( mbJob )
465         return sal_False;
466 
467     sal_Bool bSuccess = sal_False;
468     bool bWasAborted = false;
469     AquaSalInstance* pInst = GetSalData()->mpFirstInstance;
470     PrintAccessoryViewState aAccViewState;
471     sal_Int32 nAllPages = 0;
472 
473     // reset IsLastPage
474     i_rController.setLastPage( sal_False );
475 
476     // update job data
477     if( i_pSetupData )
478         SetData( ~0, i_pSetupData );
479 
480     // do we want a progress panel ?
481     sal_Bool bShowProgressPanel = sal_True;
482     beans::PropertyValue* pMonitor = i_rController.getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MonitorVisible" ) ) );
483     if( pMonitor )
484         pMonitor->Value >>= bShowProgressPanel;
485     if( ! i_rController.isShowDialogs() )
486         bShowProgressPanel = sal_False;
487 
488     // possibly create one job for collated output
489     sal_Bool bSinglePrintJobs = sal_False;
490     beans::PropertyValue* pSingleValue = i_rController.getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintCollateAsSingleJobs" ) ) );
491     if( pSingleValue )
492     {
493         pSingleValue->Value >>= bSinglePrintJobs;
494     }
495 
496     // FIXME: jobStarted() should be done after the print dialog has ended (if there is one)
497     // how do I know when that might be ?
498     i_rController.jobStarted();
499 
500 
501     int nCopies = i_rController.getPrinter()->GetCopyCount();
502     int nJobs = 1;
503     if( bSinglePrintJobs )
504     {
505         nJobs = nCopies;
506         nCopies = 1;
507     }
508 
509     for( int nCurJob = 0; nCurJob < nJobs; nCurJob++ )
510     {
511         aAccViewState.bNeedRestart = true;
512         do
513         {
514             if( aAccViewState.bNeedRestart )
515             {
516                 mnCurPageRangeStart = 0;
517                 mnCurPageRangeCount = 0;
518                 nAllPages = i_rController.getFilteredPageCount();
519             }
520 
521             aAccViewState.bNeedRestart = false;
522 
523             Size aCurSize( 21000, 29700 );
524             if( nAllPages > 0 )
525             {
526                 mnCurPageRangeCount = 1;
527                 aCurSize = getPageSize( i_rController, mnCurPageRangeStart );
528                 Size aNextSize( aCurSize );
529 
530                 // print pages up to a different size
531                 while( mnCurPageRangeCount + mnCurPageRangeStart < nAllPages )
532                 {
533                     aNextSize = getPageSize( i_rController, mnCurPageRangeStart + mnCurPageRangeCount );
534                     if( aCurSize == aNextSize // same page size
535                         ||
536                         (aCurSize.Width() == aNextSize.Height() && aCurSize.Height() == aNextSize.Width()) // same size, but different orientation
537                         )
538                     {
539                         mnCurPageRangeCount++;
540                     }
541                     else
542                         break;
543                 }
544             }
545             else
546                 mnCurPageRangeCount = 0;
547 
548             // now for the current run
549             mnStartPageOffsetX = mnStartPageOffsetY = 0;
550             // setup the paper size and orientation
551             // do this on our associated Printer object, since that is
552             // out interface to the applications which occasionally rely on the paper
553             // information (e.g. brochure printing scales to the found paper size)
554             // also SetPaperSizeUser has the advantage that we can share a
555             // platform independent paper matching algorithm
556             boost::shared_ptr<Printer> pPrinter( i_rController.getPrinter() );
557             pPrinter->SetMapMode( MapMode( MAP_100TH_MM ) );
558             pPrinter->SetPaperSizeUser( aCurSize, true );
559 
560             // create view
561             NSView* pPrintView = [[AquaPrintView alloc] initWithController: &i_rController withInfoPrinter: this];
562 
563             NSMutableDictionary* pPrintDict = [mpPrintInfo dictionary];
564 
565             // set filename
566             if( i_pFileName )
567             {
568                 [mpPrintInfo setJobDisposition: NSPrintSaveJob];
569                 NSString* pPath = CreateNSString( *i_pFileName );
570                 [pPrintDict setObject: pPath forKey: NSPrintSavePath];
571                 [pPath release];
572             }
573 
574             [pPrintDict setObject: [[NSNumber numberWithInt: nCopies] autorelease] forKey: NSPrintCopies];
575             if( nCopies > 1 )
576                 [pPrintDict setObject: [[NSNumber numberWithBool: pPrinter->IsCollateCopy()] autorelease] forKey: NSPrintMustCollate];
577             [pPrintDict setObject: [[NSNumber numberWithBool: YES] autorelease] forKey: NSPrintDetailedErrorReporting];
578             [pPrintDict setObject: [[NSNumber numberWithInt: 1] autorelease] forKey: NSPrintFirstPage];
579             // #i103253# weird: for some reason, autoreleasing the value below like the others above
580             // leads do a double free malloc error. Why this value should behave differently from all the others
581             // is a mystery.
582             [pPrintDict setObject: [NSNumber numberWithInt: mnCurPageRangeCount] forKey: NSPrintLastPage];
583 
584 
585             // create print operation
586             NSPrintOperation* pPrintOperation = [NSPrintOperation printOperationWithView: pPrintView printInfo: mpPrintInfo];
587 
588             if( pPrintOperation )
589             {
590                 NSObject* pReleaseAfterUse = nil;
591                 bool bShowPanel = (! i_rController.isDirectPrint() && getUseNativeDialog() && i_rController.isShowDialogs() );
592                 [pPrintOperation setShowsPrintPanel: bShowPanel ? YES : NO ];
593                 [pPrintOperation setShowsProgressPanel: bShowProgressPanel ? YES : NO];
594 
595                 // set job title (since MacOSX 10.5)
596                 if( [pPrintOperation respondsToSelector: @selector(setJobTitle:)] )
597                     [pPrintOperation performSelector: @selector(setJobTitle:) withObject: [CreateNSString( i_rJobName ) autorelease]];
598 
599                 if( bShowPanel && mnCurPageRangeStart == 0 && nCurJob == 0) // only the first range of pages (in the first job) gets the accesory view
600                     pReleaseAfterUse = [AquaPrintAccessoryView setupPrinterPanel: pPrintOperation withController: &i_rController withState: &aAccViewState];
601 
602                 bSuccess = sal_True;
603                 mbJob = true;
604                 pInst->startedPrintJob();
605                 [pPrintOperation runOperation];
606                 pInst->endedPrintJob();
607                 bWasAborted = [[[pPrintOperation printInfo] jobDisposition] compare: NSPrintCancelJob] == NSOrderedSame;
608                 mbJob = false;
609                 if( pReleaseAfterUse )
610                     [pReleaseAfterUse release];
611             }
612 
613             mnCurPageRangeStart += mnCurPageRangeCount;
614             mnCurPageRangeCount = 1;
615         } while( aAccViewState.bNeedRestart || mnCurPageRangeStart + mnCurPageRangeCount < nAllPages );
616     }
617 
618     // inform application that it can release its data
619     // this is awkward, but the XRenderable interface has no method for this,
620     // so we need to call XRenderadble::render one last time with IsLastPage = sal_True
621     i_rController.setLastPage( sal_True );
622     GDIMetaFile aPageFile;
623     if( mrContext )
624         SetupPrinterGraphics( mrContext );
625     i_rController.getFilteredPageFile( 0, aPageFile );
626 
627     i_rController.setJobState( bWasAborted
628                              ? view::PrintableState_JOB_ABORTED
629                              : view::PrintableState_JOB_SPOOLED );
630 
631     mnCurPageRangeStart = mnCurPageRangeCount = 0;
632 
633     return bSuccess;
634 }
635 
636 // -----------------------------------------------------------------------
637 
EndJob()638 sal_Bool AquaSalInfoPrinter::EndJob()
639 {
640     mnStartPageOffsetX = mnStartPageOffsetY = 0;
641     mbJob = false;
642     return sal_True;
643 }
644 
645 // -----------------------------------------------------------------------
646 
AbortJob()647 sal_Bool AquaSalInfoPrinter::AbortJob()
648 {
649     mbJob = false;
650 
651     // FIXME: implementation
652 	return sal_False;
653 }
654 
655 // -----------------------------------------------------------------------
656 
StartPage(ImplJobSetup * i_pSetupData,sal_Bool i_bNewJobData)657 SalGraphics* AquaSalInfoPrinter::StartPage( ImplJobSetup* i_pSetupData, sal_Bool i_bNewJobData )
658 {
659     if( i_bNewJobData && i_pSetupData )
660         SetPrinterData( i_pSetupData );
661 
662     CGContextRef rContext = reinterpret_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]);
663 
664     SetupPrinterGraphics( rContext );
665 
666 	return mpGraphics;
667 }
668 
669 // -----------------------------------------------------------------------
670 
EndPage()671 sal_Bool AquaSalInfoPrinter::EndPage()
672 {
673     mpGraphics->InvalidateContext();
674 	return sal_True;
675 }
676 
677 // -----------------------------------------------------------------------
678 
GetErrorCode() const679 sal_uLong AquaSalInfoPrinter::GetErrorCode() const
680 {
681 	return 0;
682 }
683 
684 // =======================================================================
685 
AquaSalPrinter(AquaSalInfoPrinter * i_pInfoPrinter)686 AquaSalPrinter::AquaSalPrinter( AquaSalInfoPrinter* i_pInfoPrinter ) :
687     mpInfoPrinter( i_pInfoPrinter )
688 {
689 }
690 
691 // -----------------------------------------------------------------------
692 
~AquaSalPrinter()693 AquaSalPrinter::~AquaSalPrinter()
694 {
695 }
696 
697 // -----------------------------------------------------------------------
698 
StartJob(const String * i_pFileName,const String & i_rJobName,const String & i_rAppName,ImplJobSetup * i_pSetupData,vcl::PrinterController & i_rController)699 sal_Bool AquaSalPrinter::StartJob( const String* i_pFileName,
700                                const String& i_rJobName,
701                                const String& i_rAppName,
702                                ImplJobSetup* i_pSetupData,
703                                vcl::PrinterController& i_rController )
704 {
705     return mpInfoPrinter->StartJob( i_pFileName, i_rJobName, i_rAppName, i_pSetupData, i_rController );
706 }
707 
708 // -----------------------------------------------------------------------
709 
StartJob(const XubString *,const XubString &,const XubString &,sal_uLong,bool,bool,ImplJobSetup *)710 sal_Bool AquaSalPrinter::StartJob( const XubString* /*i_pFileName*/,
711                                const XubString& /*i_rJobName*/,
712                                const XubString& /*i_rAppName*/,
713                                sal_uLong /*i_nCopies*/,
714                                bool /*i_bCollate*/,
715                                bool /*i_bDirect*/,
716                                ImplJobSetup* )
717 {
718     DBG_ERROR( "should never be called" );
719     return sal_False;
720 }
721 
722 // -----------------------------------------------------------------------
723 
EndJob()724 sal_Bool AquaSalPrinter::EndJob()
725 {
726 	return mpInfoPrinter->EndJob();
727 }
728 
729 // -----------------------------------------------------------------------
730 
AbortJob()731 sal_Bool AquaSalPrinter::AbortJob()
732 {
733 	return mpInfoPrinter->AbortJob();
734 }
735 
736 // -----------------------------------------------------------------------
737 
StartPage(ImplJobSetup * i_pSetupData,sal_Bool i_bNewJobData)738 SalGraphics* AquaSalPrinter::StartPage( ImplJobSetup* i_pSetupData, sal_Bool i_bNewJobData )
739 {
740 	return mpInfoPrinter->StartPage( i_pSetupData, i_bNewJobData );
741 }
742 
743 // -----------------------------------------------------------------------
744 
EndPage()745 sal_Bool AquaSalPrinter::EndPage()
746 {
747 	return mpInfoPrinter->EndPage();
748 }
749 
750 // -----------------------------------------------------------------------
751 
GetErrorCode()752 sal_uLong AquaSalPrinter::GetErrorCode()
753 {
754 	return mpInfoPrinter->GetErrorCode();
755 }
756 
InitPaperFormats(const ImplJobSetup *)757 void AquaSalInfoPrinter::InitPaperFormats( const ImplJobSetup* )
758 {
759     m_aPaperFormats.clear();
760     m_bPapersInit = true;
761 
762     if( mpPrinter )
763     {
764         if( [mpPrinter statusForTable: @"PPD"] == NSPrinterTableOK )
765         {
766             NSArray* pPaperNames = [mpPrinter stringListForKey: @"PageSize" inTable: @"PPD"];
767             if( pPaperNames )
768             {
769                 unsigned int nPapers = [pPaperNames count];
770                 for( unsigned int i = 0; i < nPapers; i++ )
771                 {
772                     NSString* pPaper = [pPaperNames objectAtIndex: i];
773                     // first try to match the name
774                     rtl::OString aPaperName( [pPaper UTF8String] );
775                     Paper ePaper = PaperInfo::fromPSName( aPaperName );
776                     if( ePaper != PAPER_USER )
777                     {
778                         m_aPaperFormats.push_back( PaperInfo( ePaper ) );
779                     }
780                     else
781                     {
782                         NSSize aPaperSize = [mpPrinter pageSizeForPaper: pPaper];
783                         if( aPaperSize.width > 0 && aPaperSize.height > 0 )
784                         {
785                             PaperInfo aInfo( PtTo10Mu( aPaperSize.width ),
786                                              PtTo10Mu( aPaperSize.height ) );
787                             if( aInfo.getPaper() == PAPER_USER )
788                                 aInfo.doSloppyFit();
789                             m_aPaperFormats.push_back( aInfo );
790                         }
791                     }
792                 }
793             }
794         }
795     }
796 }
797 
matchPaper(long i_nWidth,long i_nHeight,Orientation & o_rOrientation) const798 const PaperInfo* AquaSalInfoPrinter::matchPaper( long i_nWidth, long i_nHeight, Orientation& o_rOrientation ) const
799 {
800     if( ! m_bPapersInit )
801         const_cast<AquaSalInfoPrinter*>(this)->InitPaperFormats( NULL );
802 
803     const PaperInfo* pMatch = NULL;
804     o_rOrientation = ORIENTATION_PORTRAIT;
805     for( int n = 0; n < 2 ; n++ )
806     {
807         for( size_t i = 0; i < m_aPaperFormats.size(); i++ )
808         {
809             if( abs( m_aPaperFormats[i].getWidth() - i_nWidth ) < 50 &&
810                 abs( m_aPaperFormats[i].getHeight() - i_nHeight ) < 50 )
811             {
812                 pMatch = &m_aPaperFormats[i];
813                 return pMatch;
814             }
815         }
816         o_rOrientation = ORIENTATION_LANDSCAPE;
817         std::swap( i_nWidth, i_nHeight );
818     }
819     return pMatch;
820 }
821 
GetLandscapeAngle(const ImplJobSetup *)822 int AquaSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* )
823 {
824     return 900;
825 }
826 
827 
828