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