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