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