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