1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <officecfg/Office/Common.hxx>
21 
22 #include <vcl/gdimtf.hxx>
23 #include <vcl/print.hxx>
24 #include <sal/macros.h>
25 #include <osl/diagnose.h>
26 #include <tools/long.hxx>
27 
28 #include <osx/salinst.h>
29 #include <osx/salprn.h>
30 #include <osx/printview.h>
31 #include <quartz/salgdi.h>
32 #include <osx/saldata.hxx>
33 #include <quartz/utils.h>
34 
35 #include <jobset.h>
36 #include <salptype.hxx>
37 
38 #include <com/sun/star/beans/PropertyValue.hpp>
39 #include <com/sun/star/awt/Size.hpp>
40 #include <com/sun/star/uno/Sequence.hxx>
41 
42 #include <algorithm>
43 #include <cstdlib>
44 
45 using namespace vcl;
46 using namespace com::sun::star;
47 using namespace com::sun::star::beans;
48 
AquaSalInfoPrinter(const SalPrinterQueueInfo & i_rQueue)49 AquaSalInfoPrinter::AquaSalInfoPrinter( const SalPrinterQueueInfo& i_rQueue ) :
50     mpGraphics( nullptr ),
51     mbGraphics( false ),
52     mbJob( false ),
53     mpPrinter( nil ),
54     mpPrintInfo( nil ),
55     mePageOrientation( Orientation::Portrait ),
56     mnStartPageOffsetX( 0 ),
57     mnStartPageOffsetY( 0 ),
58     mnCurPageRangeStart( 0 ),
59     mnCurPageRangeCount( 0 )
60 {
61     NSString* pStr = CreateNSString( i_rQueue.maPrinterName );
62     mpPrinter = [NSPrinter printerWithName: pStr];
63     [pStr release];
64 
65     NSPrintInfo* pShared = [NSPrintInfo sharedPrintInfo];
66     if( pShared )
67     {
68         mpPrintInfo = [pShared copy];
69         [mpPrintInfo setPrinter: mpPrinter];
70         mePageOrientation = ([mpPrintInfo orientation] == NSPaperOrientationLandscape) ? Orientation::Landscape : Orientation::Portrait;
71         [mpPrintInfo setOrientation: NSPaperOrientationPortrait];
72     }
73 
74     mpGraphics = new AquaSalGraphics();
75 
76     const int nWidth = 100, nHeight = 100;
77     mpContextMemory.reset(new (std::nothrow) sal_uInt8[nWidth * 4 * nHeight]);
78 
79     if (mpContextMemory)
80     {
81         mrContext = CGBitmapContextCreate(mpContextMemory.get(),
82                 nWidth, nHeight, 8, nWidth * 4,
83                 GetSalData()->mxRGBSpace, kCGImageAlphaNoneSkipFirst);
84         if( mrContext )
85             SetupPrinterGraphics( mrContext );
86     }
87 }
88 
~AquaSalInfoPrinter()89 AquaSalInfoPrinter::~AquaSalInfoPrinter()
90 {
91     delete mpGraphics;
92     if( mpPrintInfo )
93         [mpPrintInfo release];
94     if( mrContext )
95         CFRelease( mrContext );
96 }
97 
SetupPrinterGraphics(CGContextRef i_rContext) const98 void AquaSalInfoPrinter::SetupPrinterGraphics( CGContextRef i_rContext ) const
99 {
100     if( mpGraphics )
101     {
102         if( mpPrintInfo )
103         {
104             // FIXME: get printer resolution
105             sal_Int32 nDPIX = 720, nDPIY = 720;
106             NSSize aPaperSize = [mpPrintInfo paperSize];
107 
108             NSRect aImageRect = [mpPrintInfo imageablePageBounds];
109             if( mePageOrientation == Orientation::Portrait )
110             {
111                 // move mirrored CTM back into paper
112                 double dX = 0, dY = aPaperSize.height;
113                 // move CTM to reflect imageable area
114                 dX += aImageRect.origin.x;
115                 dY -= aPaperSize.height - aImageRect.size.height - aImageRect.origin.y;
116                 CGContextTranslateCTM( i_rContext, dX + mnStartPageOffsetX, dY - mnStartPageOffsetY );
117                 // scale to be top/down and reflect our "virtual" DPI
118                 CGContextScaleCTM( i_rContext, 72.0/double(nDPIX), -(72.0/double(nDPIY)) );
119             }
120             else
121             {
122                 // move CTM to reflect imageable area
123                 double dX = aImageRect.origin.x, dY = aPaperSize.height - aImageRect.size.height - aImageRect.origin.y;
124                 CGContextTranslateCTM( i_rContext, -dX, -dY );
125                 // turn by 90 degree
126                 CGContextRotateCTM( i_rContext, M_PI/2 );
127                 // move turned CTM back into paper
128                 dX = aPaperSize.height;
129                 dY = -aPaperSize.width;
130                 CGContextTranslateCTM( i_rContext, dX + mnStartPageOffsetY, dY - mnStartPageOffsetX );
131                 // scale to be top/down and reflect our "virtual" DPI
132                 CGContextScaleCTM( i_rContext, -(72.0/double(nDPIY)), (72.0/double(nDPIX)) );
133             }
134             mpGraphics->SetPrinterGraphics( i_rContext, nDPIX, nDPIY );
135         }
136         else
137             OSL_FAIL( "no print info in SetupPrinterGraphics" );
138     }
139 }
140 
AcquireGraphics()141 SalGraphics* AquaSalInfoPrinter::AcquireGraphics()
142 {
143     SalGraphics* pGraphics = mbGraphics ? nullptr : mpGraphics;
144     mbGraphics = true;
145     return pGraphics;
146 }
147 
ReleaseGraphics(SalGraphics *)148 void AquaSalInfoPrinter::ReleaseGraphics( SalGraphics* )
149 {
150     mbGraphics = false;
151 }
152 
Setup(weld::Window *,ImplJobSetup *)153 bool AquaSalInfoPrinter::Setup( weld::Window*, ImplJobSetup* )
154 {
155     return false;
156 }
157 
SetPrinterData(ImplJobSetup * io_pSetupData)158 bool AquaSalInfoPrinter::SetPrinterData( ImplJobSetup* io_pSetupData )
159 {
160     // FIXME: implement driver data
161     if( io_pSetupData && io_pSetupData->GetDriverData() )
162         return SetData( JobSetFlags::ALL, io_pSetupData );
163 
164     bool bSuccess = true;
165 
166     // set system type
167     io_pSetupData->SetSystem( JOBSETUP_SYSTEM_MAC );
168 
169     // get paper format
170     if( mpPrintInfo )
171     {
172         NSSize aPaperSize = [mpPrintInfo paperSize];
173         double width = aPaperSize.width, height = aPaperSize.height;
174         // set paper
175         PaperInfo aInfo( PtTo10Mu( width ), PtTo10Mu( height ) );
176         aInfo.doSloppyFit();
177         io_pSetupData->SetPaperFormat( aInfo.getPaper() );
178         if( io_pSetupData->GetPaperFormat() == PAPER_USER )
179         {
180             io_pSetupData->SetPaperWidth( PtTo10Mu( width ) );
181             io_pSetupData->SetPaperHeight( PtTo10Mu( height ) );
182         }
183         else
184         {
185             io_pSetupData->SetPaperWidth( 0 );
186             io_pSetupData->SetPaperHeight( 0 );
187         }
188 
189         // set orientation
190         io_pSetupData->SetOrientation( mePageOrientation );
191 
192         io_pSetupData->SetPaperBin( 0 );
193         io_pSetupData->SetDriverData( static_cast<sal_uInt8*>(std::malloc( 4 )) );
194         io_pSetupData->SetDriverDataLen( 4 );
195     }
196     else
197         bSuccess = false;
198 
199     return bSuccess;
200 }
201 
setPaperSize(tools::Long i_nWidth,tools::Long i_nHeight,Orientation i_eSetOrientation)202 void AquaSalInfoPrinter::setPaperSize( tools::Long i_nWidth, tools::Long i_nHeight, Orientation i_eSetOrientation )
203 {
204 
205     Orientation ePaperOrientation = Orientation::Portrait;
206     const PaperInfo* pPaper = matchPaper( i_nWidth, i_nHeight, ePaperOrientation );
207 
208     if( pPaper )
209     {
210         NSString* pPaperName = [CreateNSString( OStringToOUString(PaperInfo::toPSName(pPaper->getPaper()), RTL_TEXTENCODING_ASCII_US) ) autorelease];
211         [mpPrintInfo setPaperName: pPaperName];
212     }
213     else if( i_nWidth > 0 && i_nHeight > 0 )
214     {
215         NSSize aPaperSize = { static_cast<CGFloat>(TenMuToPt(i_nWidth)), static_cast<CGFloat>(TenMuToPt(i_nHeight)) };
216         [mpPrintInfo setPaperSize: aPaperSize];
217     }
218     // this seems counterintuitive
219     mePageOrientation = i_eSetOrientation;
220 }
221 
SetData(JobSetFlags i_nFlags,ImplJobSetup * io_pSetupData)222 bool AquaSalInfoPrinter::SetData( JobSetFlags i_nFlags, ImplJobSetup* io_pSetupData )
223 {
224     if( ! io_pSetupData || io_pSetupData->GetSystem() != JOBSETUP_SYSTEM_MAC )
225         return false;
226 
227     if( mpPrintInfo )
228     {
229         if( i_nFlags & JobSetFlags::ORIENTATION )
230             mePageOrientation = io_pSetupData->GetOrientation();
231 
232         if( i_nFlags & JobSetFlags::PAPERSIZE )
233         {
234             // set paper format
235             tools::Long width = 21000, height = 29700;
236             if( io_pSetupData->GetPaperFormat() == PAPER_USER )
237             {
238                 // #i101108# sanity check
239                 if( io_pSetupData->GetPaperWidth() && io_pSetupData->GetPaperHeight() )
240                 {
241                     width = io_pSetupData->GetPaperWidth();
242                     height = io_pSetupData->GetPaperHeight();
243                 }
244             }
245             else
246             {
247                 PaperInfo aInfo( io_pSetupData->GetPaperFormat() );
248                 width = aInfo.getWidth();
249                 height = aInfo.getHeight();
250             }
251 
252             setPaperSize( width, height, mePageOrientation );
253         }
254     }
255 
256     return mpPrintInfo != nil;
257 }
258 
GetPaperBinCount(const ImplJobSetup *)259 sal_uInt16 AquaSalInfoPrinter::GetPaperBinCount( const ImplJobSetup* )
260 {
261     return 0;
262 }
263 
GetPaperBinName(const ImplJobSetup *,sal_uInt16)264 OUString AquaSalInfoPrinter::GetPaperBinName( const ImplJobSetup*, sal_uInt16 )
265 {
266     return OUString();
267 }
268 
GetCapabilities(const ImplJobSetup *,PrinterCapType i_nType)269 sal_uInt32 AquaSalInfoPrinter::GetCapabilities( const ImplJobSetup*, PrinterCapType i_nType )
270 {
271     switch( i_nType )
272     {
273         case PrinterCapType::SupportDialog:
274             return 0;
275         case PrinterCapType::Copies:
276             return 0xffff;
277         case PrinterCapType::CollateCopies:
278             return 0xffff;
279         case PrinterCapType::SetOrientation:
280             return 1;
281         case PrinterCapType::SetPaperSize:
282             return 1;
283         case PrinterCapType::SetPaper:
284             return 1;
285         case PrinterCapType::ExternalDialog:
286             return officecfg::Office::Common::Misc::UseSystemPrintDialog::get()
287                 ? 1 : 0;
288         case PrinterCapType::PDF:
289             return 1;
290         case PrinterCapType::UsePullModel:
291             return 1;
292         default: break;
293     }
294     return 0;
295 }
296 
GetPageInfo(const ImplJobSetup *,tools::Long & o_rOutWidth,tools::Long & o_rOutHeight,Point & rPageOffset,Size & rPaperSize)297 void AquaSalInfoPrinter::GetPageInfo( const ImplJobSetup*,
298                                   tools::Long& o_rOutWidth, tools::Long& o_rOutHeight,
299                                   Point& rPageOffset,
300                                   Size& rPaperSize )
301 {
302     if( mpPrintInfo )
303     {
304         sal_Int32 nDPIX = 72, nDPIY = 72;
305         mpGraphics->GetResolution( nDPIX, nDPIY );
306         const double fXScaling = static_cast<double>(nDPIX)/72.0,
307                      fYScaling = static_cast<double>(nDPIY)/72.0;
308 
309         NSSize aPaperSize = [mpPrintInfo paperSize];
310         rPaperSize.setWidth( static_cast<tools::Long>( double(aPaperSize.width) * fXScaling ) );
311         rPaperSize.setHeight( static_cast<tools::Long>( double(aPaperSize.height) * fYScaling ) );
312 
313         NSRect aImageRect = [mpPrintInfo imageablePageBounds];
314         rPageOffset.setX( static_cast<tools::Long>( aImageRect.origin.x * fXScaling ) );
315         rPageOffset.setY( static_cast<tools::Long>( (aPaperSize.height - aImageRect.size.height - aImageRect.origin.y) * fYScaling ) );
316         o_rOutWidth   = static_cast<tools::Long>( aImageRect.size.width * fXScaling );
317         o_rOutHeight  = static_cast<tools::Long>( aImageRect.size.height * fYScaling );
318 
319         if( mePageOrientation == Orientation::Landscape )
320         {
321             std::swap( o_rOutWidth, o_rOutHeight );
322             // swap width and height
323             tools::Long n = rPaperSize.Width();
324             rPaperSize.setWidth(rPaperSize.Height());
325             rPaperSize.setHeight(n);
326             // swap offset x and y
327             n = rPageOffset.X();
328             rPageOffset.setX(rPageOffset.Y());
329             rPageOffset.setY(n);
330         }
331     }
332 }
333 
getPageSize(vcl::PrinterController const & i_rController,sal_Int32 i_nPage)334 static Size getPageSize( vcl::PrinterController const & i_rController, sal_Int32 i_nPage )
335 {
336     Size aPageSize;
337     uno::Sequence< PropertyValue > const aPageParms( i_rController.getPageParameters( i_nPage ) );
338     for( const PropertyValue & pv : aPageParms )
339     {
340         if ( pv.Name == "PageSize" )
341         {
342             awt::Size aSize;
343             pv.Value >>= aSize;
344             aPageSize.setWidth( aSize.Width );
345             aPageSize.setHeight( aSize.Height );
346             break;
347         }
348     }
349     return aPageSize;
350 }
351 
StartJob(const OUString * i_pFileName,const OUString & i_rJobName,ImplJobSetup * i_pSetupData,vcl::PrinterController & i_rController)352 bool AquaSalInfoPrinter::StartJob( const OUString* i_pFileName,
353                                    const OUString& i_rJobName,
354                                    ImplJobSetup* i_pSetupData,
355                                    vcl::PrinterController& i_rController
356                                    )
357 {
358     if( mbJob )
359         return false;
360 
361     bool bSuccess = false;
362     bool bWasAborted = false;
363     AquaSalInstance* pInst = GetSalData()->mpInstance;
364     PrintAccessoryViewState aAccViewState;
365     sal_Int32 nAllPages = 0;
366 
367     // reset IsLastPage
368     i_rController.setLastPage( false );
369 
370     // update job data
371     if( i_pSetupData )
372         SetData( JobSetFlags::ALL, i_pSetupData );
373 
374     // do we want a progress panel ?
375     bool bShowProgressPanel = true;
376     beans::PropertyValue* pMonitor = i_rController.getValue( OUString( "MonitorVisible" ) );
377     if( pMonitor )
378         pMonitor->Value >>= bShowProgressPanel;
379     if( ! i_rController.isShowDialogs() )
380         bShowProgressPanel = false;
381 
382     // possibly create one job for collated output
383     bool bSinglePrintJobs = i_rController.getPrinter()->IsSinglePrintJobs();
384 
385     // FIXME: jobStarted() should be done after the print dialog has ended (if there is one)
386     // how do I know when that might be ?
387     i_rController.jobStarted();
388 
389     int nCopies = i_rController.getPrinter()->GetCopyCount();
390     int nJobs = 1;
391     if( bSinglePrintJobs )
392     {
393         nJobs = nCopies;
394         nCopies = 1;
395     }
396 
397     for( int nCurJob = 0; nCurJob < nJobs; nCurJob++ )
398     {
399         aAccViewState.bNeedRestart = true;
400         do
401         {
402             if( aAccViewState.bNeedRestart )
403             {
404                 mnCurPageRangeStart = 0;
405                 mnCurPageRangeCount = 0;
406                 nAllPages = i_rController.getFilteredPageCount();
407             }
408 
409             aAccViewState.bNeedRestart = false;
410 
411             Size aCurSize( 21000, 29700 );
412             if( nAllPages > 0 )
413             {
414                 mnCurPageRangeCount = 1;
415                 aCurSize = getPageSize( i_rController, mnCurPageRangeStart );
416                 Size aNextSize( aCurSize );
417 
418                 // print pages up to a different size
419                 while( mnCurPageRangeCount + mnCurPageRangeStart < nAllPages )
420                 {
421                     aNextSize = getPageSize( i_rController, mnCurPageRangeStart + mnCurPageRangeCount );
422                     if( aCurSize == aNextSize // same page size
423                         ||
424                         (aCurSize.Width() == aNextSize.Height() && aCurSize.Height() == aNextSize.Width()) // same size, but different orientation
425                         )
426                     {
427                         mnCurPageRangeCount++;
428                     }
429                     else
430                         break;
431                 }
432             }
433             else
434                 mnCurPageRangeCount = 0;
435 
436             // now for the current run
437             mnStartPageOffsetX = mnStartPageOffsetY = 0;
438             // setup the paper size and orientation
439             // do this on our associated Printer object, since that is
440             // out interface to the applications which occasionally rely on the paper
441             // information (e.g. brochure printing scales to the found paper size)
442             // also SetPaperSizeUser has the advantage that we can share a
443             // platform independent paper matching algorithm
444             VclPtr<Printer> pPrinter( i_rController.getPrinter() );
445             pPrinter->SetMapMode( MapMode( MapUnit::Map100thMM ) );
446             pPrinter->SetPaperSizeUser( aCurSize );
447 
448             // create view
449             NSView* pPrintView = [[AquaPrintView alloc] initWithController: &i_rController withInfoPrinter: this];
450 
451             NSMutableDictionary* pPrintDict = [mpPrintInfo dictionary];
452 
453             // set filename
454             if( i_pFileName )
455             {
456                 [mpPrintInfo setJobDisposition: NSPrintSaveJob];
457                 NSString* pPath = CreateNSString( *i_pFileName );
458                 [pPrintDict setObject:[NSURL fileURLWithPath:pPath] forKey:NSPrintJobSavingURL];
459                 [pPath release];
460             }
461 
462             [pPrintDict setObject: [[NSNumber numberWithInt: nCopies] autorelease] forKey: NSPrintCopies];
463             if( nCopies > 1 )
464                 [pPrintDict setObject: [[NSNumber numberWithBool: pPrinter->IsCollateCopy()] autorelease] forKey: NSPrintMustCollate];
465             [pPrintDict setObject: [[NSNumber numberWithBool: YES] autorelease] forKey: NSPrintDetailedErrorReporting];
466             [pPrintDict setObject: [[NSNumber numberWithInt: 1] autorelease] forKey: NSPrintFirstPage];
467             // #i103253# weird: for some reason, autoreleasing the value below like the others above
468             // leads do a double free malloc error. Why this value should behave differently from all the others
469             // is a mystery.
470             [pPrintDict setObject: [NSNumber numberWithInt: mnCurPageRangeCount] forKey: NSPrintLastPage];
471 
472             // create print operation
473             NSPrintOperation* pPrintOperation = [NSPrintOperation printOperationWithView: pPrintView printInfo: mpPrintInfo];
474 
475             if( pPrintOperation )
476             {
477                 NSObject* pReleaseAfterUse = nil;
478                 bool bShowPanel = !i_rController.isDirectPrint()
479                     && (officecfg::Office::Common::Misc::UseSystemPrintDialog::
480                         get())
481                     && i_rController.isShowDialogs();
482                 [pPrintOperation setShowsPrintPanel: bShowPanel ? YES : NO ];
483                 [pPrintOperation setShowsProgressPanel: bShowProgressPanel ? YES : NO];
484 
485                 // set job title (since MacOSX 10.5)
486                 if( [pPrintOperation respondsToSelector: @selector(setJobTitle:)] )
487                     [pPrintOperation performSelector: @selector(setJobTitle:) withObject: [CreateNSString( i_rJobName ) autorelease]];
488 
489                 if( bShowPanel && mnCurPageRangeStart == 0 && nCurJob == 0) // only the first range of pages (in the first job) gets the accessory view
490                     pReleaseAfterUse = [AquaPrintAccessoryView setupPrinterPanel: pPrintOperation withController: &i_rController withState: &aAccViewState];
491 
492                 bSuccess = true;
493                 mbJob = true;
494                 pInst->startedPrintJob();
495                 bool wasSuccessful = [pPrintOperation runOperation];
496                 pInst->endedPrintJob();
497                 bSuccess = wasSuccessful;
498                 bWasAborted = [[[pPrintOperation printInfo] jobDisposition] compare: NSPrintCancelJob] == NSOrderedSame;
499                 mbJob = false;
500                 if( pReleaseAfterUse )
501                     [pReleaseAfterUse release];
502             }
503 
504             mnCurPageRangeStart += mnCurPageRangeCount;
505             mnCurPageRangeCount = 1;
506         } while( aAccViewState.bNeedRestart || mnCurPageRangeStart + mnCurPageRangeCount < nAllPages );
507     }
508 
509     // inform application that it can release its data
510     // this is awkward, but the XRenderable interface has no method for this,
511     // so we need to call XRenderable::render one last time with IsLastPage = true
512     i_rController.setLastPage( true );
513     GDIMetaFile aPageFile;
514     if( mrContext )
515         SetupPrinterGraphics( mrContext );
516     i_rController.getFilteredPageFile( 0, aPageFile );
517 
518     i_rController.setJobState( bWasAborted
519                              ? view::PrintableState_JOB_ABORTED
520                              : view::PrintableState_JOB_SPOOLED );
521 
522     mnCurPageRangeStart = mnCurPageRangeCount = 0;
523 
524     return bSuccess;
525 }
526 
EndJob()527 bool AquaSalInfoPrinter::EndJob()
528 {
529     mnStartPageOffsetX = mnStartPageOffsetY = 0;
530     mbJob = false;
531     return true;
532 }
533 
AbortJob()534 bool AquaSalInfoPrinter::AbortJob()
535 {
536     mbJob = false;
537 
538     // FIXME: implementation
539     return false;
540 }
541 
StartPage(ImplJobSetup * i_pSetupData,bool i_bNewJobData)542 SalGraphics* AquaSalInfoPrinter::StartPage( ImplJobSetup* i_pSetupData, bool i_bNewJobData )
543 {
544     if( i_bNewJobData && i_pSetupData )
545         SetPrinterData( i_pSetupData );
546 
547     CGContextRef rContext = [[NSGraphicsContext currentContext] CGContext];
548 
549     SetupPrinterGraphics( rContext );
550 
551     return mpGraphics;
552 }
553 
EndPage()554 bool AquaSalInfoPrinter::EndPage()
555 {
556     mpGraphics->InvalidateContext();
557     return true;
558 }
559 
AquaSalPrinter(AquaSalInfoPrinter * i_pInfoPrinter)560 AquaSalPrinter::AquaSalPrinter( AquaSalInfoPrinter* i_pInfoPrinter ) :
561     mpInfoPrinter( i_pInfoPrinter )
562 {
563 }
564 
~AquaSalPrinter()565 AquaSalPrinter::~AquaSalPrinter()
566 {
567 }
568 
StartJob(const OUString * i_pFileName,const OUString & i_rJobName,const OUString &,ImplJobSetup * i_pSetupData,vcl::PrinterController & i_rController)569 bool AquaSalPrinter::StartJob( const OUString* i_pFileName,
570                                const OUString& i_rJobName,
571                                const OUString&,
572                                ImplJobSetup* i_pSetupData,
573                                vcl::PrinterController& i_rController )
574 {
575     return mpInfoPrinter->StartJob( i_pFileName, i_rJobName, i_pSetupData, i_rController );
576 }
577 
StartJob(const OUString *,const OUString &,const OUString &,sal_uInt32,bool,bool,ImplJobSetup *)578 bool AquaSalPrinter::StartJob( const OUString* /*i_pFileName*/,
579                                const OUString& /*i_rJobName*/,
580                                const OUString& /*i_rAppName*/,
581                                sal_uInt32 /*i_nCopies*/,
582                                bool /*i_bCollate*/,
583                                bool /*i_bDirect*/,
584                                ImplJobSetup* )
585 {
586     OSL_FAIL( "should never be called" );
587     return false;
588 }
589 
EndJob()590 bool AquaSalPrinter::EndJob()
591 {
592     return mpInfoPrinter->EndJob();
593 }
594 
StartPage(ImplJobSetup * i_pSetupData,bool i_bNewJobData)595 SalGraphics* AquaSalPrinter::StartPage( ImplJobSetup* i_pSetupData, bool i_bNewJobData )
596 {
597     return mpInfoPrinter->StartPage( i_pSetupData, i_bNewJobData );
598 }
599 
EndPage()600 void AquaSalPrinter::EndPage()
601 {
602     mpInfoPrinter->EndPage();
603 }
604 
InitPaperFormats(const ImplJobSetup *)605 void AquaSalInfoPrinter::InitPaperFormats( const ImplJobSetup* )
606 {
607     m_aPaperFormats.clear();
608     m_bPapersInit = true;
609 
610     if( mpPrinter )
611     {
612         SAL_WNODEPRECATED_DECLARATIONS_PUSH
613             //TODO: 10.9 statusForTable:, stringListForKey:inTable:
614         if( [mpPrinter statusForTable: @"PPD"] == NSPrinterTableOK )
615         {
616             NSArray* pPaperNames = [mpPrinter stringListForKey: @"PageSize" inTable: @"PPD"];
617             if( pPaperNames )
618             {
619                 unsigned int nPapers = [pPaperNames count];
620                 for( unsigned int i = 0; i < nPapers; i++ )
621                 {
622                     NSString* pPaper = [pPaperNames objectAtIndex: i];
623                     // first try to match the name
624                     OString aPaperName( [pPaper UTF8String] );
625                     Paper ePaper = PaperInfo::fromPSName( aPaperName );
626                     if( ePaper != PAPER_USER )
627                     {
628                         m_aPaperFormats.push_back( PaperInfo( ePaper ) );
629                     }
630                     else
631                     {
632                         NSSize aPaperSize = [mpPrinter pageSizeForPaper: pPaper];
633                         if( aPaperSize.width > 0 && aPaperSize.height > 0 )
634                         {
635                             PaperInfo aInfo( PtTo10Mu( aPaperSize.width ),
636                                              PtTo10Mu( aPaperSize.height ) );
637                             if( aInfo.getPaper() == PAPER_USER )
638                                 aInfo.doSloppyFit();
639                             m_aPaperFormats.push_back( aInfo );
640                         }
641                     }
642                 }
643             }
644         }
645         SAL_WNODEPRECATED_DECLARATIONS_POP
646     }
647 }
648 
matchPaper(tools::Long i_nWidth,tools::Long i_nHeight,Orientation & o_rOrientation) const649 const PaperInfo* AquaSalInfoPrinter::matchPaper( tools::Long i_nWidth, tools::Long i_nHeight, Orientation& o_rOrientation ) const
650 {
651     if( ! m_bPapersInit )
652         const_cast<AquaSalInfoPrinter*>(this)->InitPaperFormats( nullptr );
653 
654     const PaperInfo* pMatch = nullptr;
655     o_rOrientation = Orientation::Portrait;
656     for( int n = 0; n < 2 ; n++ )
657     {
658         for( size_t i = 0; i < m_aPaperFormats.size(); i++ )
659         {
660             if( std::abs( m_aPaperFormats[i].getWidth() - i_nWidth ) < 50 &&
661                 std::abs( m_aPaperFormats[i].getHeight() - i_nHeight ) < 50 )
662             {
663                 pMatch = &m_aPaperFormats[i];
664                 return pMatch;
665             }
666         }
667         o_rOrientation = Orientation::Landscape;
668         std::swap( i_nWidth, i_nHeight );
669     }
670     return pMatch;
671 }
672 
GetLandscapeAngle(const ImplJobSetup *)673 int AquaSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* )
674 {
675     return 900;
676 }
677 
678 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
679