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