merge the formfield patch from ooo-build
[ooovba.git] / vcl / aqua / source / gdi / salprn.cxx
blobd8e09cdbb63149e30695727533e4f4caf9cf1248
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salprn.cxx,v $
10 * $Revision: 1.16 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include "salinst.h"
35 #include "salprn.h"
36 #include "aquaprintview.h"
37 #include "salgdi.h"
38 #include "saldata.hxx"
39 #include "vcl/jobset.h"
40 #include "vcl/salptype.hxx"
41 #include "vcl/impprn.hxx"
42 #include "vcl/print.hxx"
43 #include "vcl/unohelp.hxx"
45 #include <boost/bind.hpp>
47 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
48 #include "com/sun/star/container/XNameAccess.hpp"
49 #include "com/sun/star/beans/PropertyValue.hpp"
51 #include <algorithm>
53 using namespace rtl;
54 using namespace vcl;
55 using namespace com::sun::star::uno;
56 using namespace com::sun::star::lang;
57 using namespace com::sun::star::beans;
58 using namespace com::sun::star::container;
60 // =======================================================================
62 AquaSalInfoPrinter::AquaSalInfoPrinter( const SalPrinterQueueInfo& i_rQueue ) :
63 mpGraphics( 0 ),
64 mbGraphics( false ),
65 mbJob( false ),
66 mpPrinter( nil ),
67 mpPrintInfo( nil ),
68 mePageOrientation( ORIENTATION_PORTRAIT ),
69 mnStartPageOffsetX( 0 ),
70 mnStartPageOffsetY( 0 )
72 NSString* pStr = CreateNSString( i_rQueue.maPrinterName );
73 mpPrinter = [NSPrinter printerWithName: pStr];
74 [pStr release];
76 NSPrintInfo* pShared = [NSPrintInfo sharedPrintInfo];
77 if( pShared )
79 mpPrintInfo = [pShared copy];
80 [mpPrintInfo setPrinter: mpPrinter];
81 mePageOrientation = ([mpPrintInfo orientation] == NSLandscapeOrientation) ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
82 [mpPrintInfo setOrientation: NSPortraitOrientation];
85 mpGraphics = new AquaSalGraphics();
87 const int nWidth = 100, nHeight = 100;
88 maContextMemory.reset( reinterpret_cast<sal_uInt8*>( rtl_allocateMemory( nWidth * 4 * nHeight ) ),
89 boost::bind( rtl_freeMemory, _1 ) );
90 if( maContextMemory )
92 mrContext = CGBitmapContextCreate( maContextMemory.get(), nWidth, nHeight, 8, nWidth * 4, GetSalData()->mxRGBSpace, kCGImageAlphaNoneSkipFirst );
93 if( mrContext )
94 SetupPrinterGraphics( mrContext );
98 // -----------------------------------------------------------------------
100 AquaSalInfoPrinter::~AquaSalInfoPrinter()
102 delete mpGraphics;
103 if( mpPrintInfo )
104 [mpPrintInfo release];
105 #if 0
106 // FIXME: verify that NSPrintInfo releases the printer
107 // else we have a leak here
108 if( mpPrinter )
109 [mpPrinter release];
110 #endif
111 if( mrContext )
112 CFRelease( mrContext );
115 // -----------------------------------------------------------------------
117 void AquaSalInfoPrinter::SetupPrinterGraphics( CGContextRef i_rContext ) const
119 if( mpGraphics )
121 if( mpPrintInfo )
123 // FIXME: get printer resolution
124 long nDPIX = 720, nDPIY = 720;
125 NSSize aPaperSize = [mpPrintInfo paperSize];
127 NSRect aImageRect = [mpPrintInfo imageablePageBounds];
128 if( mePageOrientation == ORIENTATION_PORTRAIT )
130 // move mirrored CTM back into paper
131 double dX = 0, dY = aPaperSize.height;
132 // move CTM to reflect imageable area
133 dX += aImageRect.origin.x;
134 dY -= aPaperSize.height - aImageRect.size.height - aImageRect.origin.y;
135 CGContextTranslateCTM( i_rContext, dX + mnStartPageOffsetX, dY - mnStartPageOffsetY );
136 // scale to be top/down and reflect our "virtual" DPI
137 CGContextScaleCTM( i_rContext, 0.1, -0.1 );
139 else
141 // move CTM to reflect imageable area
142 double dX = aImageRect.origin.x, dY = aPaperSize.height - aImageRect.size.height - aImageRect.origin.y;
143 CGContextTranslateCTM( i_rContext, -dX, -dY );
144 // turn by 90 degree
145 CGContextRotateCTM( i_rContext, M_PI/2 );
146 // move turned CTM back into paper
147 dX = aPaperSize.height;
148 dY = -aPaperSize.width;
149 CGContextTranslateCTM( i_rContext, dX + mnStartPageOffsetY, dY - mnStartPageOffsetX );
150 // scale to be top/down and reflect our "virtual" DPI
151 CGContextScaleCTM( i_rContext, -0.1, 0.1 );
153 mpGraphics->SetPrinterGraphics( i_rContext, nDPIX, nDPIY, 1.0 );
155 else
156 DBG_ERROR( "no print info in SetupPrinterGraphics" );
160 // -----------------------------------------------------------------------
162 SalGraphics* AquaSalInfoPrinter::GetGraphics()
164 SalGraphics* pGraphics = mbGraphics ? NULL : mpGraphics;
165 mbGraphics = true;
166 return pGraphics;
169 // -----------------------------------------------------------------------
171 void AquaSalInfoPrinter::ReleaseGraphics( SalGraphics* )
173 mbGraphics = false;
176 // -----------------------------------------------------------------------
178 BOOL AquaSalInfoPrinter::Setup( SalFrame* i_pFrame, ImplJobSetup* i_pSetupData )
180 return FALSE;
183 // -----------------------------------------------------------------------
185 static struct PaperSizeEntry
187 double fWidth;
188 double fHeight;
189 Paper nPaper;
190 } aPaperSizes[] =
192 { 842, 1191, PAPER_A3 },
193 { 595, 842, PAPER_A4 },
194 { 420, 595, PAPER_A5 },
195 { 612, 792, PAPER_LETTER },
196 { 612, 1008, PAPER_LEGAL },
197 { 728, 1032, PAPER_B4_JIS },
198 { 516, 729, PAPER_B5_JIS },
199 { 792, 1224, PAPER_TABLOID }
202 static bool getPaperSize( double& o_fWidth, double& o_fHeight, const Paper i_ePaper )
204 for(unsigned int i = 0; i < sizeof(aPaperSizes)/sizeof(aPaperSizes[0]); i++ )
206 if( aPaperSizes[i].nPaper == i_ePaper )
208 o_fWidth = aPaperSizes[i].fWidth;
209 o_fHeight = aPaperSizes[i].fHeight;
210 return true;
213 return false;
216 static Paper recognizePaper( double i_fWidth, double i_fHeight )
218 Paper aPaper = PAPER_USER;
219 sal_uInt64 nPaperDesc = 1000000*sal_uInt64(i_fWidth) + sal_uInt64(i_fHeight);
220 switch( nPaperDesc )
222 case 842001191: aPaper = PAPER_A3; break;
223 case 595000842: aPaper = PAPER_A4; break;
224 case 420000595: aPaper = PAPER_A5; break;
225 case 612000792: aPaper = PAPER_LETTER; break;
226 case 728001032: aPaper = PAPER_B4_JIS; break;
227 case 516000729: aPaper = PAPER_B5_JIS; break;
228 case 612001008: aPaper = PAPER_LEGAL; break;
229 case 792001224: aPaper = PAPER_TABLOID; break;
230 default:
231 aPaper = PAPER_USER;
232 break;
235 if( aPaper == PAPER_USER )
237 // search with fuzz factor
238 for( unsigned int i = 0; i < sizeof(aPaperSizes)/sizeof(aPaperSizes[0]); i++ )
240 double w = (i_fWidth > aPaperSizes[i].fWidth) ? i_fWidth - aPaperSizes[i].fWidth : aPaperSizes[i].fWidth - i_fWidth;
241 double h = (i_fHeight > aPaperSizes[i].fHeight) ? i_fHeight - aPaperSizes[i].fHeight : aPaperSizes[i].fHeight - i_fHeight;
242 if( w < 3 && h < 3 )
244 aPaper = aPaperSizes[i].nPaper;
245 break;
250 return aPaper;
253 BOOL AquaSalInfoPrinter::SetPrinterData( ImplJobSetup* io_pSetupData )
255 // FIXME: implement driver data
256 if( io_pSetupData && io_pSetupData->mpDriverData )
257 return SetData( ~0, io_pSetupData );
260 BOOL bSuccess = TRUE;
262 // set system type
263 io_pSetupData->mnSystem = JOBSETUP_SYSTEM_MAC;
265 // get paper format
266 if( mpPrintInfo )
268 NSSize aPaperSize = [mpPrintInfo paperSize];
269 double width = aPaperSize.width, height = aPaperSize.height;
270 // set paper
271 io_pSetupData->mePaperFormat = recognizePaper( width, height );
272 if( io_pSetupData->mePaperFormat == PAPER_USER )
274 io_pSetupData->mnPaperWidth = PtTo10Mu( width );
275 io_pSetupData->mnPaperHeight = PtTo10Mu( height );
277 else
279 io_pSetupData->mnPaperWidth = 0;
280 io_pSetupData->mnPaperHeight = 0;
283 // set orientation
284 io_pSetupData->meOrientation = mePageOrientation;
286 io_pSetupData->mnPaperBin = 0;
287 io_pSetupData->mpDriverData = reinterpret_cast<BYTE*>(rtl_allocateMemory( 4 ));
288 io_pSetupData->mnDriverDataLen = 4;
290 else
291 bSuccess = FALSE;
294 return bSuccess;
297 // -----------------------------------------------------------------------
299 BOOL AquaSalInfoPrinter::SetData( ULONG i_nFlags, ImplJobSetup* io_pSetupData )
301 if( ! io_pSetupData || io_pSetupData->mnSystem != JOBSETUP_SYSTEM_MAC )
302 return FALSE;
305 if( mpPrintInfo )
307 if( (i_nFlags & SAL_JOBSET_PAPERSIZE) != 0)
309 // set paper format
310 double width = 0, height = 0;
311 if( io_pSetupData->mePaperFormat == PAPER_USER )
313 // #i101108# sanity check
314 if( io_pSetupData->mnPaperWidth && io_pSetupData->mnPaperHeight )
316 width = TenMuToPt( io_pSetupData->mnPaperWidth );
317 height = TenMuToPt( io_pSetupData->mnPaperHeight );
320 else
321 getPaperSize( width, height, io_pSetupData->mePaperFormat );
323 if( width > 0 && height > 0 )
325 NSSize aPaperSize = { width, height };
326 [mpPrintInfo setPaperSize: aPaperSize];
330 if( (i_nFlags & SAL_JOBSET_ORIENTATION) != 0 )
331 mePageOrientation = io_pSetupData->meOrientation;
334 return mpPrintInfo != nil;
337 // -----------------------------------------------------------------------
339 ULONG AquaSalInfoPrinter::GetPaperBinCount( const ImplJobSetup* i_pSetupData )
341 return 0;
344 // -----------------------------------------------------------------------
346 XubString AquaSalInfoPrinter::GetPaperBinName( const ImplJobSetup* i_pSetupData, ULONG i_nPaperBin )
348 return XubString();
351 // -----------------------------------------------------------------------
353 static bool getUseNativeDialog()
355 bool bNative = true;
358 // get service provider
359 Reference< XMultiServiceFactory > xSMgr( unohelper::GetMultiServiceFactory() );
360 // create configuration hierachical access name
361 if( xSMgr.is() )
365 Reference< XMultiServiceFactory > xConfigProvider(
366 Reference< XMultiServiceFactory >(
367 xSMgr->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
368 "com.sun.star.configuration.ConfigurationProvider" ))),
369 UNO_QUERY )
371 if( xConfigProvider.is() )
373 Sequence< Any > aArgs(1);
374 PropertyValue aVal;
375 aVal.Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) );
376 aVal.Value <<= OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/Misc" ) );
377 aArgs.getArray()[0] <<= aVal;
378 Reference< XNameAccess > xConfigAccess(
379 Reference< XNameAccess >(
380 xConfigProvider->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
381 "com.sun.star.configuration.ConfigurationAccess" )),
382 aArgs ),
383 UNO_QUERY )
385 if( xConfigAccess.is() )
389 sal_Bool bValue = sal_False;
390 Any aAny = xConfigAccess->getByName( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseSystemPrintDialog" ) ) );
391 if( aAny >>= bValue )
392 bNative = bValue;
394 catch( NoSuchElementException& )
397 catch( WrappedTargetException& )
403 catch( Exception& )
408 catch( WrappedTargetException& )
412 return bNative;
415 ULONG AquaSalInfoPrinter::GetCapabilities( const ImplJobSetup* i_pSetupData, USHORT i_nType )
417 switch( i_nType )
419 case PRINTER_CAPABILITIES_SUPPORTDIALOG:
420 return 0;
421 case PRINTER_CAPABILITIES_COPIES:
422 return 0xffff;
423 case PRINTER_CAPABILITIES_COLLATECOPIES:
424 return 0;
425 case PRINTER_CAPABILITIES_SETORIENTATION:
426 return 1;
427 case PRINTER_CAPABILITIES_SETPAPERBIN:
428 return 0;
429 case PRINTER_CAPABILITIES_SETPAPERSIZE:
430 return 1;
431 case PRINTER_CAPABILITIES_SETPAPER:
432 return 1;
433 case PRINTER_CAPABILITIES_EXTERNALDIALOG:
434 return getUseNativeDialog() ? 1 : 0;
435 default: break;
437 return 0;
440 // -----------------------------------------------------------------------
442 void AquaSalInfoPrinter::GetPageInfo( const ImplJobSetup*,
443 long& o_rOutWidth, long& o_rOutHeight,
444 long& o_rPageOffX, long& o_rPageOffY,
445 long& o_rPageWidth, long& o_rPageHeight )
447 if( mpPrintInfo )
449 long nDPIX = 72, nDPIY = 72;
450 mpGraphics->GetResolution( nDPIX, nDPIY );
451 const double fXScaling = static_cast<double>(nDPIX)/72.0,
452 fYScaling = static_cast<double>(nDPIY)/72.0;
454 NSSize aPaperSize = [mpPrintInfo paperSize];
455 o_rPageWidth = static_cast<long>( double(aPaperSize.width) * fXScaling );
456 o_rPageHeight = static_cast<long>( double(aPaperSize.height) * fYScaling );
458 NSRect aImageRect = [mpPrintInfo imageablePageBounds];
459 o_rPageOffX = static_cast<long>( aImageRect.origin.x * fXScaling );
460 o_rPageOffY = static_cast<long>( (aPaperSize.height - aImageRect.size.height - aImageRect.origin.y) * fYScaling );
461 o_rOutWidth = static_cast<long>( aImageRect.size.width * fXScaling );
462 o_rOutHeight = static_cast<long>( aImageRect.size.height * fYScaling );
464 if( mePageOrientation == ORIENTATION_LANDSCAPE )
466 std::swap( o_rOutWidth, o_rOutHeight );
467 std::swap( o_rPageWidth, o_rPageHeight );
468 std::swap( o_rPageOffX, o_rPageOffY );
473 BOOL AquaSalInfoPrinter::StartJob( const String* pFileName,
474 const String& rAppName,
475 ImplJobSetup* pSetupData,
476 ImplQPrinter* pQPrinter,
477 bool bIsQuickJob )
479 if( mbJob )
480 return FALSE;
482 BOOL bSuccess = FALSE;
483 std::vector<ULONG> aPaperRanges;
484 if( ! pQPrinter->GetPaperRanges( aPaperRanges, true ) )
485 return FALSE;
487 size_t nRanges = aPaperRanges.size();
488 AquaSalInstance* pInst = GetSalData()->mpFirstInstance;
490 for( ULONG nCurRange = 0; nCurRange < nRanges-1; nCurRange++ )
492 mnStartPageOffsetX = mnStartPageOffsetY = 0;
494 // update job data
495 ImplJobSetup* pSetup = pQPrinter->GetPageSetup( aPaperRanges[ nCurRange ] );
496 if( pSetup )
497 SetData( ~0, pSetup );
498 DBG_ASSERT( pSetup, "no job setup for range" );
500 mnCurPageRangeStart = aPaperRanges[nCurRange];
501 mnCurPageRangeCount = aPaperRanges[nCurRange+1] - aPaperRanges[nCurRange];
502 // create view
503 NSView* pPrintView = [[AquaPrintView alloc] initWithQPrinter: pQPrinter withInfoPrinter: this];
505 NSMutableDictionary* pPrintDict = [mpPrintInfo dictionary];
507 // set filename
508 if( pFileName )
510 [mpPrintInfo setJobDisposition: NSPrintSaveJob];
511 NSString* pPath = CreateNSString( *pFileName );
512 [pPrintDict setObject: pPath forKey: NSPrintSavePath];
513 [pPath release];
515 // in this case we can only deliver the print job in one file
516 mnCurPageRangeStart = 0;
517 mnCurPageRangeCount = aPaperRanges.back();
518 nCurRange = nRanges;
521 [pPrintDict setObject: [[NSNumber numberWithInt: (int)pQPrinter->GetCopyCount()] autorelease] forKey: NSPrintCopies];
522 [pPrintDict setObject: [[NSNumber numberWithBool: YES] autorelease] forKey: NSPrintDetailedErrorReporting];
523 [pPrintDict setObject: [[NSNumber numberWithInt: 1] autorelease] forKey: NSPrintFirstPage];
524 [pPrintDict setObject: [[NSNumber numberWithInt: (int)mnCurPageRangeCount] autorelease] forKey: NSPrintLastPage];
527 // create print operation
528 NSPrintOperation* pPrintOperation = [NSPrintOperation printOperationWithView: pPrintView printInfo: mpPrintInfo];
530 if( pPrintOperation )
532 bool bShowPanel = (! bIsQuickJob && getUseNativeDialog() );
533 [pPrintOperation setShowsPrintPanel: bShowPanel ? YES : NO ];
534 // [pPrintOperation setShowsProgressPanel: NO];
535 bSuccess = TRUE;
536 mbJob = true;
537 pInst->startedPrintJob();
538 [pPrintOperation runOperation];
539 pInst->endedPrintJob();
540 mbJob = false;
544 return bSuccess;
547 // -----------------------------------------------------------------------
549 BOOL AquaSalInfoPrinter::EndJob()
551 mnStartPageOffsetX = mnStartPageOffsetY = 0;
552 mbJob = false;
553 return TRUE;
556 // -----------------------------------------------------------------------
558 BOOL AquaSalInfoPrinter::AbortJob()
560 mbJob = false;
562 // FIXME: implementation
563 return FALSE;
566 // -----------------------------------------------------------------------
568 SalGraphics* AquaSalInfoPrinter::StartPage( ImplJobSetup* i_pSetupData, BOOL i_bNewJobData )
570 if( i_bNewJobData && i_pSetupData )
571 SetPrinterData( i_pSetupData );
573 CGContextRef rContext = reinterpret_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]);
575 SetupPrinterGraphics( rContext );
577 return mpGraphics;
580 // -----------------------------------------------------------------------
582 BOOL AquaSalInfoPrinter::EndPage()
584 return TRUE;
587 // -----------------------------------------------------------------------
589 ULONG AquaSalInfoPrinter::GetErrorCode() const
591 return 0;
594 // =======================================================================
596 AquaSalPrinter::AquaSalPrinter( AquaSalInfoPrinter* i_pInfoPrinter ) :
597 mpInfoPrinter( i_pInfoPrinter )
601 // -----------------------------------------------------------------------
603 AquaSalPrinter::~AquaSalPrinter()
607 // -----------------------------------------------------------------------
609 BOOL AquaSalPrinter::StartJob( const String* pFileName,
610 const String& rAppName,
611 ImplJobSetup* pSetupData,
612 ImplQPrinter* pQPrinter )
614 bool bIsQuickJob = false;
615 std::hash_map< rtl::OUString, rtl::OUString, rtl::OUStringHash >::const_iterator quick_it =
616 pSetupData->maValueMap.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsQuickJob" ) ) );
618 if( quick_it != pSetupData->maValueMap.end() )
620 if( quick_it->second.equalsIgnoreAsciiCaseAscii( "true" ) )
621 bIsQuickJob = true;
624 return mpInfoPrinter->StartJob( pFileName, rAppName, pSetupData, pQPrinter, bIsQuickJob );
627 // -----------------------------------------------------------------------
629 BOOL AquaSalPrinter::StartJob( const XubString* i_pFileName,
630 const XubString& i_rJobName,
631 const XubString& i_rAppName,
632 ULONG i_nCopies, BOOL i_bCollate,
633 ImplJobSetup* i_pSetupData )
635 DBG_ERROR( "should never be called" );
636 return FALSE;
639 // -----------------------------------------------------------------------
641 BOOL AquaSalPrinter::EndJob()
643 return mpInfoPrinter->EndJob();
646 // -----------------------------------------------------------------------
648 BOOL AquaSalPrinter::AbortJob()
650 return mpInfoPrinter->AbortJob();
653 // -----------------------------------------------------------------------
655 SalGraphics* AquaSalPrinter::StartPage( ImplJobSetup* i_pSetupData, BOOL i_bNewJobData )
657 return mpInfoPrinter->StartPage( i_pSetupData, i_bNewJobData );
660 // -----------------------------------------------------------------------
662 BOOL AquaSalPrinter::EndPage()
664 return mpInfoPrinter->EndPage();
667 // -----------------------------------------------------------------------
669 ULONG AquaSalPrinter::GetErrorCode()
671 return mpInfoPrinter->GetErrorCode();
674 ////////////////////////////
675 ////// IMPLEMENT US /////
676 ////////////////////////////
678 DuplexMode AquaSalInfoPrinter::GetDuplexMode( const ImplJobSetup* i_pSetupData )
680 return DUPLEX_UNKNOWN;
683 void AquaSalInfoPrinter::InitPaperFormats( const ImplJobSetup* i_pSetupData )
687 int AquaSalInfoPrinter::GetLandscapeAngle( const ImplJobSetup* i_pSetupData )
689 return 0;