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 #include "precompiled_sd.hxx" 25 26 #include <com/sun/star/beans/XPropertySet.hpp> 27 28 #include "DocumentRenderer.hxx" 29 #include "DocumentRenderer.hrc" 30 31 #include "drawdoc.hxx" 32 #include "optsitem.hxx" 33 #include "sdresid.hxx" 34 #include "strings.hrc" 35 #include "sdattr.hxx" 36 #include "Window.hxx" 37 #include "drawview.hxx" 38 #include "DrawViewShell.hxx" 39 #include "FrameView.hxx" 40 #include "Outliner.hxx" 41 #include "OutlineViewShell.hxx" 42 43 #include <basegfx/polygon/b2dpolygon.hxx> 44 #include <basegfx/polygon/b2dpolypolygon.hxx> 45 #include <basegfx/matrix/b2dhommatrix.hxx> 46 #include <sfx2/printer.hxx> 47 #include <editeng/editstat.hxx> 48 #include <editeng/outlobj.hxx> 49 #include <svx/svdetc.hxx> 50 #include <svx/svditer.hxx> 51 #include <svx/svdopage.hxx> 52 #include <svx/svdopath.hxx> 53 #include <svx/xlnclit.hxx> 54 #include <toolkit/awt/vclxdevice.hxx> 55 #include <tools/resary.hxx> 56 #include <unotools/localedatawrapper.hxx> 57 #include <vcl/msgbox.hxx> 58 #include <unotools/moduleoptions.hxx> 59 60 #include <vector> 61 62 using namespace ::com::sun::star; 63 using namespace ::com::sun::star::uno; 64 using ::rtl::OUString; 65 66 67 namespace sd { 68 69 namespace { 70 OUString A2S (const char* pString) 71 { 72 return OUString::createFromAscii(pString); 73 } 74 75 76 77 /** Convenience class to extract values from the sequence of properties 78 given to one of the XRenderable methods. 79 */ 80 class PrintOptions 81 { 82 public: 83 PrintOptions ( 84 const vcl::PrinterOptionsHelper& rHelper, 85 const ::std::vector<sal_Int32>& rSlidesPerPage) 86 : mrProperties(rHelper), 87 maSlidesPerPage(rSlidesPerPage) 88 { 89 } 90 91 bool IsWarningOrientation (void) const 92 { 93 return GetBoolValue(NULL, true); 94 } 95 96 bool IsPrintPageName (void) const 97 { 98 return GetBoolValue("IsPrintName"); 99 } 100 101 bool IsDate (void) const 102 { 103 return GetBoolValue("IsPrintDateTime"); 104 } 105 106 bool IsTime (void) const 107 { 108 return GetBoolValue("IsPrintDateTime"); 109 } 110 111 bool IsHiddenPages (void) const 112 { 113 return GetBoolValue("IsPrintHidden"); 114 } 115 116 bool IsHandoutHorizontal (void) const 117 { 118 return GetBoolValue("SlidesPerPageOrder", sal_Int32(0), true); 119 } 120 121 sal_Int32 GetHandoutPageCount (void) const 122 { 123 sal_uInt32 nIndex = static_cast<sal_Int32>(mrProperties.getIntValue("SlidesPerPage", sal_Int32(0))); 124 if (nIndex<maSlidesPerPage.size()) 125 return maSlidesPerPage[nIndex]; 126 else if ( ! maSlidesPerPage.empty()) 127 return maSlidesPerPage[0]; 128 else 129 return 0; 130 } 131 132 bool IsDraw (void) const 133 { 134 return GetBoolValue("PageContentType", sal_Int32(0)); 135 } 136 137 bool IsHandout (void) const 138 { 139 return GetBoolValue("PageContentType", sal_Int32(1)); 140 } 141 142 bool IsNotes (void) const 143 { 144 return GetBoolValue("PageContentType", sal_Int32(2)); 145 } 146 147 bool IsOutline (void) const 148 { 149 return GetBoolValue("PageContentType", sal_Int32(3)); 150 } 151 152 sal_uLong GetOutputQuality (void) const 153 { 154 sal_Int32 nQuality = static_cast<sal_Int32>(mrProperties.getIntValue( "Quality", sal_Int32(0) )); 155 return nQuality; 156 } 157 158 bool IsPageSize (void) const 159 { 160 return GetBoolValue("PageOptions", sal_Int32(1)); 161 } 162 163 bool IsTilePage (void) const 164 { 165 return GetBoolValue("PageOptions", sal_Int32(2)) || GetBoolValue("PageOptions", sal_Int32(3)); 166 } 167 168 bool IsCutPage (void) const 169 { 170 return GetBoolValue("PageOptions", sal_Int32(0)); 171 } 172 173 bool IsBooklet (void) const 174 { 175 return GetBoolValue("PrintProspect", false); 176 } 177 178 bool IsPrintExcluded (void) const 179 { 180 return (IsNotes() || IsDraw() || IsHandout()) && IsHiddenPages(); 181 } 182 183 bool IsPrintFrontPage (void) const 184 { 185 sal_Int32 nInclude = static_cast<sal_Int32>(mrProperties.getIntValue( "PrintProspectInclude", 0 )); 186 return nInclude == 0 || nInclude == 1; 187 } 188 189 bool IsPrintBackPage (void) const 190 { 191 sal_Int32 nInclude = static_cast<sal_Int32>(mrProperties.getIntValue( "PrintProspectInclude", 0 )); 192 return nInclude == 0 || nInclude == 2; 193 } 194 195 bool IsPaperBin (void) const 196 { 197 return GetBoolValue("PrintPaperFromSetup", false); 198 } 199 200 OUString GetPrinterSelection (void) const 201 { 202 sal_Int32 nContent = static_cast<sal_Int32>(mrProperties.getIntValue( "PrintContent", 0 )); 203 OUString sValue( A2S("all") ); 204 if( nContent == 1 ) 205 sValue = mrProperties.getStringValue( "PageRange", A2S( "all" ) ); 206 else if( nContent == 2 ) 207 sValue = A2S( "selection" ); 208 return sValue; 209 } 210 211 private: 212 const vcl::PrinterOptionsHelper& mrProperties; 213 const ::std::vector<sal_Int32> maSlidesPerPage; 214 215 /** When the value of the property with name pName is a boolean then 216 return its value. When the property is unknown then 217 bDefaultValue is returned. Otherwise <FALSE/> is returned. 218 */ 219 bool GetBoolValue ( 220 const sal_Char* pName, 221 const bool bDefaultValue = false) const 222 { 223 sal_Bool bValue = mrProperties.getBoolValue( pName, bDefaultValue ); 224 return bValue; 225 } 226 227 /** Return <TRUE/> when the value of the property with name pName is 228 a string and its value equals pValue. When the property is 229 unknown then bDefaultValue is returned. Otherwise <FALSE/> is 230 returned. 231 */ 232 bool GetBoolValue ( 233 const sal_Char* pName, 234 const sal_Char* pValue, 235 const bool bDefaultValue = false) const 236 { 237 OUString sValue( mrProperties.getStringValue( pName ) ); 238 if (sValue.getLength()) 239 return sValue.equalsAscii(pValue); 240 else 241 return bDefaultValue; 242 } 243 244 /** Return <TRUE/> when the value of the property with name pName is 245 an integer and its value is nTriggerValue. Otherwise <FALSE/> is 246 returned. 247 */ 248 bool GetBoolValue ( 249 const sal_Char* pName, 250 const sal_Int32 nTriggerValue) const 251 { 252 sal_Int32 nValue = static_cast<sal_Int32>(mrProperties.getIntValue( pName )); 253 return nValue == nTriggerValue; 254 } 255 }; 256 257 258 259 /** This class is like MultiSelection but understands two special values. 260 "all" indicates that all pages are selected. "selection" indicates that no 261 pages but a set of shapes is selected. 262 */ 263 class Selection 264 { 265 public: 266 Selection (const OUString& rsSelection, const SdPage* pCurrentPage) 267 : mbAreAllPagesSelected(rsSelection.equalsAscii("all")), 268 mbIsShapeSelection(rsSelection.equalsAscii("selection")), 269 mnCurrentPageIndex(pCurrentPage!=NULL ? (pCurrentPage->GetPageNum()-1)/2 : -1), 270 mpSelectedPages() 271 { 272 if ( ! (mbAreAllPagesSelected || mbIsShapeSelection)) 273 mpSelectedPages.reset(new MultiSelection(rsSelection)); 274 } 275 276 bool IsMarkedOnly (void) const 277 { 278 return mbIsShapeSelection; 279 } 280 281 /** Call with a 0 based page index. 282 */ 283 bool IsSelected (const sal_Int32 nIndex) const 284 { 285 if (mbAreAllPagesSelected) 286 return true; 287 else if (mpSelectedPages) 288 return mpSelectedPages->IsSelected(nIndex+1); 289 else if (mbIsShapeSelection && nIndex==mnCurrentPageIndex) 290 return true; 291 else 292 return false; 293 } 294 295 private: 296 const bool mbAreAllPagesSelected; 297 const bool mbIsShapeSelection; 298 const sal_Int32 mnCurrentPageIndex; 299 ::boost::scoped_ptr<MultiSelection> mpSelectedPages; 300 }; 301 302 /** A collection of values that helps to reduce the number of arguments 303 given to some functions. Note that not all values are set at the 304 same time. 305 */ 306 class PrintInfo 307 { 308 public: 309 PrintInfo ( 310 const Printer* pPrinter, 311 const OUString& rsPrinterSelection, 312 const ::boost::shared_ptr<ViewShell> pView) 313 : mpPrinter(pPrinter), 314 mnDrawMode(DRAWMODE_DEFAULT), 315 msTimeDate(), 316 msPageString(), 317 maPrintSize(0,0), 318 maPageSize(0,0), 319 meOrientation(ORIENTATION_PORTRAIT), 320 maMap(), 321 maSelection(rsPrinterSelection, pView ? pView->getCurrentPage() : NULL), 322 mbPrintMarkedOnly(maSelection.IsMarkedOnly()) 323 {} 324 325 const Printer* mpPrinter; 326 sal_uLong mnDrawMode; 327 ::rtl::OUString msTimeDate; 328 ::rtl::OUString msPageString; 329 Size maPrintSize; 330 Size maPageSize; 331 Orientation meOrientation; 332 MapMode maMap; 333 const Selection maSelection; 334 bool mbPrintMarkedOnly; 335 }; 336 337 338 339 /** Output one page of the document to the given printer. Note that 340 more than one document page may be output to one printer page. 341 */ 342 void PrintPage ( 343 Printer& rPrinter, 344 ::sd::View& rPrintView, 345 SdPage& rPage, 346 View* pView, 347 const bool bPrintMarkedOnly, 348 const SetOfByte& rVisibleLayers, 349 const SetOfByte& rPrintableLayers) 350 { 351 rPrintView.ShowSdrPage(&rPage); 352 353 const MapMode aOriginalMapMode (rPrinter.GetMapMode()); 354 355 // Set the visible layers 356 SdrPageView* pPageView = rPrintView.GetSdrPageView(); 357 OSL_ASSERT(pPageView!=NULL); 358 pPageView->SetVisibleLayers(rVisibleLayers); 359 pPageView->SetPrintableLayers(rPrintableLayers); 360 361 if (pView!=NULL && bPrintMarkedOnly) 362 pView->DrawMarkedObj(rPrinter); 363 else 364 rPrintView.CompleteRedraw(&rPrinter, Rectangle(Point(0,0), rPage.GetSize())); 365 366 rPrinter.SetMapMode(aOriginalMapMode); 367 368 rPrintView.HideSdrPage(); 369 } 370 371 372 373 374 /** Output a string (that typically is not part of a document page) to 375 the given printer. 376 */ 377 void PrintMessage ( 378 Printer& rPrinter, 379 const ::rtl::OUString& rsPageString, 380 const Point& rPageStringOffset) 381 { 382 const Font aOriginalFont (rPrinter.OutputDevice::GetFont()); 383 rPrinter.SetFont(Font(FAMILY_SWISS, Size(0, 423))); 384 rPrinter.DrawText(rPageStringOffset, rsPageString); 385 rPrinter.SetFont(aOriginalFont); 386 } 387 388 389 390 391 /** Read the resource file and process it into a sequence of properties 392 that can be passed to the printing dialog. 393 */ 394 class DialogCreator : Resource 395 { 396 public: 397 DialogCreator (bool bImpress) 398 : Resource(SdResId(_STR_IMPRESS_PRINT_UI_OPTIONS)) 399 , mbImpress(bImpress) 400 { 401 ProcessResource(); 402 } 403 404 Sequence< beans::PropertyValue > GetDialogControls(void) const 405 { 406 if (maProperties.empty()) 407 return Sequence< beans::PropertyValue >(); 408 else 409 { 410 return Sequence<beans::PropertyValue>( 411 &maProperties.front(), 412 maProperties.size()); 413 } 414 } 415 416 ::std::vector<sal_Int32> GetSlidesPerPage (void) const 417 { 418 return maSlidesPerPage; 419 } 420 421 private: 422 Any maDialog; 423 ::std::vector<beans::PropertyValue> maProperties; 424 ::std::vector<sal_Int32> maSlidesPerPage; 425 bool mbImpress; 426 427 void ProcessResource (void) 428 { 429 SvtModuleOptions aOpt; 430 String aAppGroupname( String( SdResId( _STR_IMPRESS_PRINT_UI_GROUP_NAME ) ) ); 431 aAppGroupname.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "%s" ) ), 432 aOpt.GetModuleName( mbImpress ? SvtModuleOptions::E_SIMPRESS : SvtModuleOptions::E_SDRAW ) ); 433 AddDialogControl( vcl::PrinterOptionsHelper::getGroupControlOpt( 434 aAppGroupname, 435 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:TabPage:AppPage" ) ) 436 ) ); 437 438 uno::Sequence< rtl::OUString > aHelpIds; 439 if( mbImpress ) 440 { 441 vcl::PrinterOptionsHelper::UIControlOptions aPrintOpt; 442 aPrintOpt.maGroupHint = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "JobPage" ) ); 443 AddDialogControl( vcl::PrinterOptionsHelper::getSubgroupControlOpt( 444 String( SdResId(_STR_IMPRESS_PRINT_UI_PRINT_GROUP) ), 445 rtl::OUString(), 446 aPrintOpt ) 447 ); 448 449 aHelpIds.realloc( 1 ); 450 aHelpIds[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PageContentType:ListBox" ) ); 451 AddDialogControl( vcl::PrinterOptionsHelper::getChoiceControlOpt( 452 String( SdResId( _STR_IMPRESS_PRINT_UI_CONTENT ) ), 453 aHelpIds, 454 OUString( RTL_CONSTASCII_USTRINGPARAM( "PageContentType" ) ), 455 CreateChoice(_STR_IMPRESS_PRINT_UI_CONTENT_CHOICES), 456 0, 457 OUString( RTL_CONSTASCII_USTRINGPARAM( "List" ) ) 458 ) 459 ); 460 461 aHelpIds[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:SlidesPerPage:ListBox" ) ); 462 vcl::PrinterOptionsHelper::UIControlOptions 463 aContentOpt( OUString( RTL_CONSTASCII_USTRINGPARAM( "PageContentType" ) ), 1 ); 464 AddDialogControl( vcl::PrinterOptionsHelper::getChoiceControlOpt( 465 String( SdResId( _STR_IMPRESS_PRINT_UI_SLIDESPERPAGE ) ), 466 aHelpIds, 467 OUString( RTL_CONSTASCII_USTRINGPARAM( "SlidesPerPage" ) ), 468 GetSlidesPerPageSequence(), 469 0, 470 OUString( RTL_CONSTASCII_USTRINGPARAM( "List" ) ), 471 Sequence< sal_Bool >(), 472 aContentOpt 473 ) 474 ); 475 476 aHelpIds[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:SlidesPerPageOrder:ListBox" ) ); 477 vcl::PrinterOptionsHelper::UIControlOptions 478 aSlidesPerPageOpt( OUString( RTL_CONSTASCII_USTRINGPARAM( "SlidesPerPage" ) ), -1, sal_True ); 479 AddDialogControl( vcl::PrinterOptionsHelper::getChoiceControlOpt( 480 String( SdResId( _STR_IMPRESS_PRINT_UI_ORDER ) ), 481 aHelpIds, 482 OUString( RTL_CONSTASCII_USTRINGPARAM( "SlidesPerPageOrder" ) ), 483 CreateChoice(_STR_IMPRESS_PRINT_UI_ORDER_CHOICES), 484 0, 485 OUString( RTL_CONSTASCII_USTRINGPARAM( "List" ) ), 486 Sequence< sal_Bool >(), 487 aSlidesPerPageOpt ) 488 ); 489 } 490 491 AddDialogControl( vcl::PrinterOptionsHelper::getSubgroupControlOpt( 492 String( SdResId(_STR_IMPRESS_PRINT_UI_INCLUDE_CONTENT) ), rtl::OUString() ) ); 493 494 495 if( mbImpress ) 496 { 497 AddDialogControl( vcl::PrinterOptionsHelper::getBoolControlOpt( 498 String( SdResId(_STR_IMPRESS_PRINT_UI_IS_PRINT_NAME) ), 499 OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:IsPrintName:CheckBox" ) ), 500 OUString( RTL_CONSTASCII_USTRINGPARAM( "IsPrintName" ) ), 501 sal_False 502 ) 503 ); 504 } 505 else 506 { 507 AddDialogControl( vcl::PrinterOptionsHelper::getBoolControlOpt( 508 String( SdResId(_STR_DRAW_PRINT_UI_IS_PRINT_NAME) ), 509 OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:IsPrintName:CheckBox" ) ), 510 OUString( RTL_CONSTASCII_USTRINGPARAM( "IsPrintName" ) ), 511 sal_False 512 ) 513 ); 514 } 515 516 AddDialogControl( vcl::PrinterOptionsHelper::getBoolControlOpt( 517 String( SdResId(_STR_IMPRESS_PRINT_UI_IS_PRINT_DATE) ), 518 OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:IsPrintDateTime:CheckBox" ) ), 519 OUString( RTL_CONSTASCII_USTRINGPARAM( "IsPrintDateTime" ) ), 520 sal_False 521 ) 522 ); 523 524 if( mbImpress ) 525 { 526 AddDialogControl( vcl::PrinterOptionsHelper::getBoolControlOpt( 527 String( SdResId(_STR_IMPRESS_PRINT_UI_IS_PRINT_HIDDEN) ), 528 OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:IsPrintHidden:CheckBox" ) ), 529 OUString( RTL_CONSTASCII_USTRINGPARAM( "IsPrintHidden" ) ), 530 sal_False 531 ) 532 ); 533 } 534 535 AddDialogControl( vcl::PrinterOptionsHelper::getSubgroupControlOpt( 536 String( SdResId(_STR_IMPRESS_PRINT_UI_QUALITY) ), rtl::OUString() ) ); 537 538 aHelpIds.realloc( 3 ); 539 aHelpIds[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:Quality:RadioButton:0" ) ); 540 aHelpIds[1] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:Quality:RadioButton:1" ) ); 541 aHelpIds[2] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:Quality:RadioButton:2" ) ); 542 AddDialogControl( vcl::PrinterOptionsHelper::getChoiceControlOpt( 543 rtl::OUString(), 544 aHelpIds, 545 OUString( RTL_CONSTASCII_USTRINGPARAM( "Quality" ) ), 546 CreateChoice(_STR_IMPRESS_PRINT_UI_QUALITY_CHOICES), 547 0 548 ) 549 ); 550 551 AddDialogControl( vcl::PrinterOptionsHelper::getSubgroupControlOpt( 552 String( SdResId(_STR_IMPRESS_PRINT_UI_PAGE_OPTIONS) ), rtl::OUString() ) ); 553 554 aHelpIds.realloc( 4 ); 555 aHelpIds[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PageOptions:RadioButton:0" ) ); 556 aHelpIds[1] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PageOptions:RadioButton:1" ) ); 557 aHelpIds[2] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PageOptions:RadioButton:2" ) ); 558 aHelpIds[3] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PageOptions:RadioButton:3" ) ); 559 if( mbImpress ) 560 { 561 // FIXME: additional dependency on PrintProspect = false 562 vcl::PrinterOptionsHelper::UIControlOptions 563 aPageOptionsOpt( OUString( RTL_CONSTASCII_USTRINGPARAM( "PageContentType" ) ), 0 ); 564 AddDialogControl( vcl::PrinterOptionsHelper::getChoiceControlOpt( 565 rtl::OUString(), 566 aHelpIds, 567 OUString( RTL_CONSTASCII_USTRINGPARAM( "PageOptions" ) ), 568 CreateChoice(_STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES), 569 0, 570 OUString( RTL_CONSTASCII_USTRINGPARAM( "Radio" ) ), 571 Sequence< sal_Bool >(), 572 aPageOptionsOpt 573 ) 574 ); 575 } 576 else 577 { 578 vcl::PrinterOptionsHelper::UIControlOptions 579 aPageOptionsOpt( OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintProspect" ) ), sal_False ); 580 AddDialogControl( vcl::PrinterOptionsHelper::getChoiceControlOpt( 581 rtl::OUString(), 582 aHelpIds, 583 OUString( RTL_CONSTASCII_USTRINGPARAM( "PageOptions" ) ), 584 CreateChoice(_STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES_DRAW), 585 0, 586 OUString( RTL_CONSTASCII_USTRINGPARAM( "Radio" ) ), 587 Sequence< sal_Bool >(), 588 aPageOptionsOpt 589 ) 590 ); 591 } 592 593 vcl::PrinterOptionsHelper::UIControlOptions aBrochureOpt; 594 aBrochureOpt.maGroupHint = OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutPage" ) ); 595 AddDialogControl( vcl::PrinterOptionsHelper::getSubgroupControlOpt( 596 String( SdResId(_STR_IMPRESS_PRINT_UI_PAGE_SIDES) ), rtl::OUString(), 597 aBrochureOpt ) ); 598 599 // brochure printing 600 AddDialogControl( vcl::PrinterOptionsHelper::getBoolControlOpt( 601 String( SdResId(_STR_IMPRESS_PRINT_UI_BROCHURE) ), 602 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintProspect:CheckBox" ) ), 603 OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintProspect" ) ), 604 sal_False, 605 aBrochureOpt 606 ) 607 ); 608 609 vcl::PrinterOptionsHelper::UIControlOptions 610 aIncludeOpt( OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintProspect" ) ), -1, sal_False ); 611 aIncludeOpt.maGroupHint = OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutPage" ) ); 612 aHelpIds.realloc( 1 ); 613 aHelpIds[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintProspectInclude:ListBox" ) ); 614 AddDialogControl( vcl::PrinterOptionsHelper::getChoiceControlOpt( 615 String( SdResId(_STR_IMPRESS_PRINT_UI_BROCHURE_INCLUDE) ), 616 aHelpIds, 617 OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintProspectInclude" ) ), 618 CreateChoice(_STR_IMPRESS_PRINT_UI_BROCHURE_INCLUDE_LIST), 619 0, 620 OUString( RTL_CONSTASCII_USTRINGPARAM( "List" ) ), 621 Sequence< sal_Bool >(), 622 aIncludeOpt 623 ) 624 ); 625 626 // paper tray (on options page) 627 vcl::PrinterOptionsHelper::UIControlOptions aPaperTrayOpt; 628 aPaperTrayOpt.maGroupHint = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OptionsPageOptGroup" ) ); 629 AddDialogControl( vcl::PrinterOptionsHelper::getBoolControlOpt( 630 String( SdResId(_STR_IMPRESS_PRINT_UI_PAPER_TRAY) ), 631 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintPaperFromSetup:CheckBox" ) ), 632 OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintPaperFromSetup" ) ), 633 sal_False, 634 aPaperTrayOpt 635 ) 636 ); 637 // print range selection 638 vcl::PrinterOptionsHelper::UIControlOptions aPrintRangeOpt; 639 aPrintRangeOpt.mbInternalOnly = sal_True; 640 aPrintRangeOpt.maGroupHint = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintRange" ) ); 641 AddDialogControl( vcl::PrinterOptionsHelper::getSubgroupControlOpt( 642 String( SdResId( _STR_IMPRESS_PRINT_UI_PAGE_RANGE ) ), 643 rtl::OUString(), 644 aPrintRangeOpt ) 645 ); 646 647 // create a choice for the content to create 648 rtl::OUString aPrintRangeName( RTL_CONSTASCII_USTRINGPARAM( "PrintContent" ) ); 649 aHelpIds.realloc( 3 ); 650 aHelpIds[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintContent:RadioButton:0" ) ); 651 aHelpIds[1] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintContent:RadioButton:1" ) ); 652 aHelpIds[2] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PrintContent:RadioButton:2" ) ); 653 AddDialogControl( vcl::PrinterOptionsHelper::getChoiceControlOpt( rtl::OUString(), 654 aHelpIds, 655 aPrintRangeName, 656 CreateChoice(mbImpress 657 ? _STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE 658 : _STR_DRAW_PRINT_UI_PAGE_RANGE_CHOICE), 659 0 ) 660 ); 661 // create a an Edit dependent on "Pages" selected 662 vcl::PrinterOptionsHelper::UIControlOptions aPageRangeOpt( aPrintRangeName, 1, sal_True ); 663 AddDialogControl( vcl::PrinterOptionsHelper::getEditControlOpt( rtl::OUString(), 664 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".HelpID:vcl:PrintDialog:PageRange:Edit" ) ), 665 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PageRange" ) ), 666 rtl::OUString(), 667 aPageRangeOpt ) 668 ); 669 670 FreeResource(); 671 } 672 673 void AddDialogControl( const Any& i_rCtrl ) 674 { 675 beans::PropertyValue aVal; 676 aVal.Value = i_rCtrl; 677 maProperties.push_back( aVal ); 678 } 679 680 Sequence<rtl::OUString> CreateChoice (const sal_uInt16 nResourceId) const 681 { 682 SdResId aResourceId (nResourceId); 683 ResStringArray aChoiceStrings (aResourceId); 684 685 const sal_uInt32 nCount (aChoiceStrings.Count()); 686 Sequence<rtl::OUString> aChoices (nCount); 687 for (sal_uInt32 nIndex=0; nIndex<nCount; ++nIndex) 688 aChoices[nIndex] = aChoiceStrings.GetString(nIndex); 689 690 return aChoices; 691 } 692 693 Sequence<rtl::OUString> GetSlidesPerPageSequence (void) 694 { 695 const Sequence<rtl::OUString> aChoice ( 696 CreateChoice(_STR_IMPRESS_PRINT_UI_SLIDESPERPAGE_CHOICES)); 697 maSlidesPerPage.clear(); 698 maSlidesPerPage.push_back(0); // first is using the default 699 for (sal_Int32 nIndex=1,nCount=aChoice.getLength(); nIndex<nCount; ++nIndex) 700 maSlidesPerPage.push_back(aChoice[nIndex].toInt32()); 701 return aChoice; 702 } 703 }; 704 705 706 707 708 /** The Prepare... methods of the DocumentRenderer::Implementation class 709 create a set of PrinterPage objects that contain all necessary 710 information to do the actual printing. There is one PrinterPage 711 object per printed page. Derived classes implement the actual, mode 712 specific printing. 713 714 This and all derived classes support the asynchronous printing 715 process by not storing pointers to any data with lifetime shorter 716 than the PrinterPage objects, i.e. slides, shapes, (one of) the 717 outliner (of the document). 718 */ 719 class PrinterPage 720 { 721 public: 722 PrinterPage ( 723 const PageKind ePageKind, 724 const MapMode& rMapMode, 725 const bool bPrintMarkedOnly, 726 const ::rtl::OUString& rsPageString, 727 const Point& rPageStringOffset, 728 const sal_uLong nDrawMode, 729 const Orientation eOrientation, 730 const sal_uInt16 nPaperTray) 731 : mePageKind(ePageKind), 732 maMap(rMapMode), 733 mbPrintMarkedOnly(bPrintMarkedOnly), 734 msPageString(rsPageString), 735 maPageStringOffset(rPageStringOffset), 736 mnDrawMode(nDrawMode), 737 meOrientation(eOrientation), 738 mnPaperTray(nPaperTray) 739 { 740 } 741 742 virtual ~PrinterPage (void) {} 743 744 virtual void Print ( 745 Printer& rPrinter, 746 SdDrawDocument& rDocument, 747 ViewShell& rViewShell, 748 View* pView, 749 DrawView& rPrintView, 750 const SetOfByte& rVisibleLayers, 751 const SetOfByte& rPrintableLayers) const = 0; 752 753 sal_uLong GetDrawMode (void) const { return mnDrawMode; } 754 Orientation GetOrientation (void) const { return meOrientation; } 755 sal_uInt16 GetPaperTray (void) const { return mnPaperTray; } 756 757 protected: 758 const PageKind mePageKind; 759 const MapMode maMap; 760 const bool mbPrintMarkedOnly; 761 const ::rtl::OUString msPageString; 762 const Point maPageStringOffset; 763 const sal_uLong mnDrawMode; 764 const Orientation meOrientation; 765 const sal_uInt16 mnPaperTray; 766 }; 767 768 769 770 771 /** The RegularPrinterPage is used for printing one regular slide (no 772 notes, handout, or outline) to one printer page. 773 */ 774 class RegularPrinterPage : public PrinterPage 775 { 776 public: 777 RegularPrinterPage ( 778 const sal_uInt16 nPageIndex, 779 const PageKind ePageKind, 780 const MapMode& rMapMode, 781 const bool bPrintMarkedOnly, 782 const ::rtl::OUString& rsPageString, 783 const Point& rPageStringOffset, 784 const sal_uLong nDrawMode, 785 const Orientation eOrientation, 786 const sal_uInt16 nPaperTray) 787 : PrinterPage(ePageKind, rMapMode, bPrintMarkedOnly, rsPageString, 788 rPageStringOffset, nDrawMode, eOrientation, nPaperTray), 789 mnPageIndex(nPageIndex) 790 { 791 } 792 793 virtual ~RegularPrinterPage (void) {} 794 795 virtual void Print ( 796 Printer& rPrinter, 797 SdDrawDocument& rDocument, 798 ViewShell& rViewShell, 799 View* pView, 800 DrawView& rPrintView, 801 const SetOfByte& rVisibleLayers, 802 const SetOfByte& rPrintableLayers) const 803 { 804 (void)rViewShell; 805 SdPage* pPageToPrint = rDocument.GetSdPage(mnPageIndex, mePageKind); 806 rPrinter.SetMapMode(maMap); 807 PrintPage( 808 rPrinter, 809 rPrintView, 810 *pPageToPrint, 811 pView, 812 mbPrintMarkedOnly, 813 rVisibleLayers, 814 rPrintableLayers); 815 PrintMessage( 816 rPrinter, 817 msPageString, 818 maPageStringOffset); 819 } 820 821 private: 822 const sal_uInt16 mnPageIndex; 823 }; 824 825 826 827 828 /** Print one slide multiple times on a printer page so that the whole 829 printer page is covered. 830 */ 831 class TiledPrinterPage : public PrinterPage 832 { 833 public: 834 TiledPrinterPage ( 835 const sal_uInt16 nPageIndex, 836 const PageKind ePageKind, 837 const sal_Int32 nGap, 838 const bool bPrintMarkedOnly, 839 const ::rtl::OUString& rsPageString, 840 const Point& rPageStringOffset, 841 const sal_uLong nDrawMode, 842 const Orientation eOrientation, 843 const sal_uInt16 nPaperTray) 844 : PrinterPage(ePageKind, MapMode(), bPrintMarkedOnly, rsPageString, 845 rPageStringOffset, nDrawMode, eOrientation, nPaperTray), 846 mnPageIndex(nPageIndex), 847 mnGap(nGap) 848 { 849 } 850 851 virtual ~TiledPrinterPage (void) {} 852 853 virtual void Print ( 854 Printer& rPrinter, 855 SdDrawDocument& rDocument, 856 ViewShell& rViewShell, 857 View* pView, 858 DrawView& rPrintView, 859 const SetOfByte& rVisibleLayers, 860 const SetOfByte& rPrintableLayers) const 861 { 862 (void)rViewShell; 863 SdPage* pPageToPrint = rDocument.GetSdPage(mnPageIndex, mePageKind); 864 if (pPageToPrint==NULL) 865 return; 866 MapMode aMap (rPrinter.GetMapMode()); 867 868 const Size aPageSize (pPageToPrint->GetSize()); 869 const Size aPrintSize (rPrinter.GetOutputSize()); 870 871 const sal_Int32 nPageWidth (aPageSize.Width() + mnGap 872 - pPageToPrint->GetLftBorder() - pPageToPrint->GetRgtBorder()); 873 const sal_Int32 nPageHeight (aPageSize.Height() + mnGap 874 - pPageToPrint->GetUppBorder() - pPageToPrint->GetLwrBorder()); 875 if (nPageWidth<=0 || nPageHeight<=0) 876 return; 877 878 // Print at least two rows and columns. More if the document 879 // page fits completely onto the printer page. 880 const sal_Int32 nColumnCount (::std::max(sal_Int32(2), 881 sal_Int32(aPrintSize.Width() / nPageWidth))); 882 const sal_Int32 nRowCount (::std::max(sal_Int32(2), 883 sal_Int32(aPrintSize.Height() / nPageHeight))); 884 Point aPrintOrigin; 885 for (sal_Int32 nRow=0; nRow<nRowCount; ++nRow) 886 for (sal_Int32 nColumn=0; nColumn<nColumnCount; ++nColumn) 887 { 888 aMap.SetOrigin(Point(nColumn*nPageWidth,nRow*nPageHeight)); 889 rPrinter.SetMapMode(aMap); 890 PrintPage( 891 rPrinter, 892 rPrintView, 893 *pPageToPrint, 894 pView, 895 mbPrintMarkedOnly, 896 rVisibleLayers, 897 rPrintableLayers); 898 } 899 900 PrintMessage( 901 rPrinter, 902 msPageString, 903 maPageStringOffset); 904 } 905 906 private: 907 const sal_uInt16 mnPageIndex; 908 const sal_Int32 mnGap; 909 }; 910 911 /** Print two slides to one printer page so that the resulting pages 912 form a booklet. 913 */ 914 class BookletPrinterPage : public PrinterPage 915 { 916 public: 917 BookletPrinterPage ( 918 const sal_uInt16 nFirstPageIndex, 919 const sal_uInt16 nSecondPageIndex, 920 const Point& rFirstOffset, 921 const Point& rSecondOffset, 922 const PageKind ePageKind, 923 const MapMode& rMapMode, 924 const bool bPrintMarkedOnly, 925 const sal_uLong nDrawMode, 926 const Orientation eOrientation, 927 const sal_uInt16 nPaperTray) 928 : PrinterPage(ePageKind, rMapMode, bPrintMarkedOnly, ::rtl::OUString(), 929 Point(), nDrawMode, eOrientation, nPaperTray), 930 mnFirstPageIndex(nFirstPageIndex), 931 mnSecondPageIndex(nSecondPageIndex), 932 maFirstOffset(rFirstOffset), 933 maSecondOffset(rSecondOffset) 934 { 935 } 936 937 virtual ~BookletPrinterPage (void) {} 938 939 virtual void Print ( 940 Printer& rPrinter, 941 SdDrawDocument& rDocument, 942 ViewShell& rViewShell, 943 View* pView, 944 DrawView& rPrintView, 945 const SetOfByte& rVisibleLayers, 946 const SetOfByte& rPrintableLayers) const 947 { 948 (void)rViewShell; 949 MapMode aMap (maMap); 950 SdPage* pPageToPrint = rDocument.GetSdPage(mnFirstPageIndex, mePageKind); 951 if (pPageToPrint) 952 { 953 aMap.SetOrigin(maFirstOffset); 954 rPrinter.SetMapMode(aMap); 955 PrintPage( 956 rPrinter, 957 rPrintView, 958 *pPageToPrint, 959 pView, 960 mbPrintMarkedOnly, 961 rVisibleLayers, 962 rPrintableLayers); 963 } 964 965 pPageToPrint = rDocument.GetSdPage(mnSecondPageIndex, mePageKind); 966 if( pPageToPrint ) 967 { 968 aMap.SetOrigin(maSecondOffset); 969 rPrinter.SetMapMode(aMap); 970 PrintPage( 971 rPrinter, 972 rPrintView, 973 *pPageToPrint, 974 pView, 975 mbPrintMarkedOnly, 976 rVisibleLayers, 977 rPrintableLayers); 978 } 979 } 980 981 private: 982 const sal_uInt16 mnFirstPageIndex; 983 const sal_uInt16 mnSecondPageIndex; 984 const Point maFirstOffset; 985 const Point maSecondOffset; 986 }; 987 988 989 990 991 /** One handout page displays one to nine slides. 992 */ 993 class HandoutPrinterPage : public PrinterPage 994 { 995 public: 996 HandoutPrinterPage ( 997 const sal_uInt16 nHandoutPageIndex, 998 const ::std::vector<sal_uInt16>& rPageIndices, 999 const MapMode& rMapMode, 1000 const ::rtl::OUString& rsPageString, 1001 const Point& rPageStringOffset, 1002 const sal_uLong nDrawMode, 1003 const Orientation eOrientation, 1004 const sal_uInt16 nPaperTray) 1005 : PrinterPage(PK_HANDOUT, rMapMode, false, rsPageString, 1006 rPageStringOffset, nDrawMode, eOrientation, nPaperTray), 1007 mnHandoutPageIndex(nHandoutPageIndex), 1008 maPageIndices(rPageIndices) 1009 { 1010 } 1011 1012 virtual void Print ( 1013 Printer& rPrinter, 1014 SdDrawDocument& rDocument, 1015 ViewShell& rViewShell, 1016 View* pView, 1017 DrawView& rPrintView, 1018 const SetOfByte& rVisibleLayers, 1019 const SetOfByte& rPrintableLayers) const 1020 { 1021 SdPage& rHandoutPage (*rDocument.GetSdPage(0, PK_HANDOUT)); 1022 1023 Reference< com::sun::star::beans::XPropertySet > xHandoutPage( rHandoutPage.getUnoPage(), UNO_QUERY ); 1024 const rtl::OUString sPageNumber( RTL_CONSTASCII_USTRINGPARAM( "Number" ) ); 1025 1026 // Collect the page objects of the handout master. 1027 std::vector<SdrPageObj*> aHandoutPageObjects; 1028 SdrObjListIter aShapeIter (rHandoutPage); 1029 while (aShapeIter.IsMore()) 1030 { 1031 SdrPageObj* pPageObj = dynamic_cast<SdrPageObj*>(aShapeIter.Next()); 1032 if (pPageObj) 1033 aHandoutPageObjects.push_back(pPageObj); 1034 } 1035 if (aHandoutPageObjects.empty()) 1036 return; 1037 1038 // Connect page objects with pages. 1039 std::vector<SdrPageObj*>::iterator aPageObjIter (aHandoutPageObjects.begin()); 1040 for (std::vector<sal_uInt16>::const_iterator 1041 iPageIndex(maPageIndices.begin()), 1042 iEnd(maPageIndices.end()); 1043 iPageIndex!=iEnd && aPageObjIter!=aHandoutPageObjects.end(); 1044 ++iPageIndex) 1045 { 1046 // Check if the page still exists. 1047 if (*iPageIndex >= rDocument.GetSdPageCount(PK_STANDARD)) 1048 continue; 1049 1050 SdrPageObj* pPageObj = (*aPageObjIter++); 1051 pPageObj->SetReferencedPage(rDocument.GetSdPage(*iPageIndex, PK_STANDARD)); 1052 } 1053 1054 // if there are more page objects than pages left, set the rest to invisible 1055 int nHangoverCount = 0; 1056 while (aPageObjIter != aHandoutPageObjects.end()) 1057 { 1058 (*aPageObjIter++)->SetReferencedPage(0L); 1059 nHangoverCount++; 1060 } 1061 1062 // Hide outlines for objects that have pages attached. 1063 if (nHangoverCount > 0) 1064 { 1065 int nSkip = aHandoutPageObjects.size() - nHangoverCount; 1066 aShapeIter.Reset(); 1067 while (aShapeIter.IsMore()) 1068 { 1069 SdrPathObj* pPathObj = dynamic_cast<SdrPathObj*>(aShapeIter.Next()); 1070 if (pPathObj) 1071 { 1072 if (nSkip > 0) 1073 --nSkip; 1074 else 1075 pPathObj->SetMergedItem(XLineStyleItem(XLINE_NONE)); 1076 } 1077 } 1078 } 1079 1080 if( xHandoutPage.is() ) try 1081 { 1082 xHandoutPage->setPropertyValue( sPageNumber, Any( static_cast<sal_Int16>(mnHandoutPageIndex) ) ); 1083 } 1084 catch( Exception& ) 1085 { 1086 } 1087 rViewShell.SetPrintedHandoutPageNum( mnHandoutPageIndex + 1 ); 1088 1089 MapMode aMap (rPrinter.GetMapMode()); 1090 rPrinter.SetMapMode(maMap); 1091 1092 PrintPage( 1093 rPrinter, 1094 rPrintView, 1095 rHandoutPage, 1096 pView, 1097 false, 1098 rVisibleLayers, 1099 rPrintableLayers); 1100 PrintMessage( 1101 rPrinter, 1102 msPageString, 1103 maPageStringOffset); 1104 1105 if( xHandoutPage.is() ) try 1106 { 1107 xHandoutPage->setPropertyValue( sPageNumber, Any( static_cast<sal_Int16>(0) ) ); 1108 } 1109 catch( Exception& ) 1110 { 1111 } 1112 rViewShell.SetPrintedHandoutPageNum(1); 1113 1114 // Restore outlines. 1115 if (nHangoverCount > 0) 1116 { 1117 aShapeIter.Reset(); 1118 while (aShapeIter.IsMore()) 1119 { 1120 SdrPathObj* pPathObj = dynamic_cast<SdrPathObj*>(aShapeIter.Next()); 1121 if (pPathObj != NULL) 1122 pPathObj->SetMergedItem(XLineStyleItem(XLINE_SOLID)); 1123 } 1124 } 1125 1126 } 1127 1128 private: 1129 const sal_uInt16 mnHandoutPageIndex; 1130 const ::std::vector<sal_uInt16> maPageIndices; 1131 }; 1132 1133 1134 1135 1136 /** The outline information (title, subtitle, outline objects) of the 1137 document. There is no fixed mapping of slides to printer pages. 1138 */ 1139 class OutlinerPrinterPage : public PrinterPage 1140 { 1141 public: 1142 OutlinerPrinterPage ( 1143 OutlinerParaObject* pParaObject, 1144 const MapMode& rMapMode, 1145 const ::rtl::OUString& rsPageString, 1146 const Point& rPageStringOffset, 1147 const sal_uLong nDrawMode, 1148 const Orientation eOrientation, 1149 const sal_uInt16 nPaperTray) 1150 : PrinterPage(PK_HANDOUT, rMapMode, false, rsPageString, 1151 rPageStringOffset, nDrawMode, eOrientation, nPaperTray), 1152 mpParaObject(pParaObject) 1153 { 1154 } 1155 1156 ~OutlinerPrinterPage (void) 1157 { 1158 mpParaObject.reset(); 1159 } 1160 1161 virtual void Print ( 1162 Printer& rPrinter, 1163 SdDrawDocument& rDocument, 1164 ViewShell& rViewShell, 1165 View* pView, 1166 DrawView& rPrintView, 1167 const SetOfByte& rVisibleLayers, 1168 const SetOfByte& rPrintableLayers) const 1169 { 1170 (void)rViewShell; 1171 (void)pView; 1172 (void)rPrintView; 1173 (void)rVisibleLayers; 1174 (void)rPrintableLayers; 1175 1176 // Set up the printer. 1177 rPrinter.SetMapMode(maMap); 1178 1179 // Get and set up the outliner. 1180 const Rectangle aOutRect (rPrinter.GetPageOffset(), rPrinter.GetOutputSize()); 1181 Outliner* pOutliner = rDocument.GetInternalOutliner(); 1182 const sal_uInt16 nSavedOutlMode (pOutliner->GetMode()); 1183 const sal_Bool bSavedUpdateMode (pOutliner->GetUpdateMode()); 1184 const Size aSavedPaperSize (pOutliner->GetPaperSize()); 1185 1186 pOutliner->Init(OUTLINERMODE_OUTLINEVIEW); 1187 pOutliner->SetPaperSize(aOutRect.GetSize()); 1188 pOutliner->SetUpdateMode(sal_True); 1189 pOutliner->Clear(); 1190 pOutliner->SetText(*mpParaObject); 1191 1192 pOutliner->Draw(&rPrinter, aOutRect); 1193 1194 PrintMessage( 1195 rPrinter, 1196 msPageString, 1197 maPageStringOffset); 1198 1199 // Restore outliner and printer. 1200 pOutliner->Clear(); 1201 pOutliner->SetUpdateMode(bSavedUpdateMode); 1202 pOutliner->SetPaperSize(aSavedPaperSize); 1203 pOutliner->Init(nSavedOutlMode); 1204 } 1205 1206 private: 1207 ::boost::scoped_ptr<OutlinerParaObject> mpParaObject; 1208 }; 1209 } 1210 1211 1212 //===== DocumentRenderer::Implementation ====================================== 1213 1214 class DocumentRenderer::Implementation 1215 : public SfxListener, 1216 public vcl::PrinterOptionsHelper 1217 { 1218 public: 1219 Implementation (ViewShellBase& rBase) 1220 : mrBase(rBase), 1221 mbIsDisposed(false), 1222 mpPrinter(NULL), 1223 mpOptions(), 1224 maPrinterPages(), 1225 mpPrintView(), 1226 mbHasOrientationWarningBeenShown(false) 1227 { 1228 DialogCreator aCreator( mrBase.GetDocShell()->GetDocumentType() == DOCUMENT_TYPE_IMPRESS ); 1229 m_aUIProperties = aCreator.GetDialogControls(); 1230 maSlidesPerPage = aCreator.GetSlidesPerPage(); 1231 1232 StartListening(mrBase); 1233 } 1234 1235 1236 1237 1238 virtual ~Implementation (void) 1239 { 1240 EndListening(mrBase); 1241 } 1242 1243 1244 1245 1246 virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint) 1247 { 1248 const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint); 1249 if (pSimpleHint != NULL 1250 && pSimpleHint->GetId() == SFX_HINT_DYING 1251 && &rBroadcaster == &static_cast<SfxBroadcaster&>(mrBase)) 1252 { 1253 Dispose(); 1254 } 1255 } 1256 1257 1258 1259 /** Process the sequence of properties given to one of the XRenderable 1260 methods. 1261 */ 1262 void ProcessProperties (const css::uno::Sequence<css::beans::PropertyValue >& rOptions) 1263 { 1264 OSL_ASSERT(!mbIsDisposed); 1265 if (mbIsDisposed) 1266 return; 1267 1268 bool bIsValueChanged = processProperties( rOptions ); 1269 bool bIsPaperChanged = false; 1270 1271 // The RenderDevice property is handled specially: its value is 1272 // stored in mpPrinter instead of being retrieved on demand. 1273 Any aDev( getValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "RenderDevice" ) ) ) ); 1274 Reference<awt::XDevice> xRenderDevice; 1275 1276 if (aDev >>= xRenderDevice) 1277 { 1278 VCLXDevice* pDevice = VCLXDevice::GetImplementation(xRenderDevice); 1279 OutputDevice* pOut = pDevice ? pDevice->GetOutputDevice() : NULL; 1280 mpPrinter = dynamic_cast<Printer*>(pOut); 1281 Size aPageSizePixel = mpPrinter ? mpPrinter->GetPaperSizePixel() : Size(); 1282 if( aPageSizePixel != maPrinterPageSizePixel ) 1283 { 1284 bIsPaperChanged = true; 1285 maPrinterPageSizePixel = aPageSizePixel; 1286 } 1287 } 1288 1289 if (bIsValueChanged) 1290 { 1291 if ( ! mpOptions ) 1292 mpOptions.reset(new PrintOptions(*this, maSlidesPerPage)); 1293 } 1294 if( bIsValueChanged || bIsPaperChanged ) 1295 PreparePages(); 1296 } 1297 1298 1299 1300 /** Return the number of pages that are to be printed. 1301 */ 1302 sal_Int32 GetPrintPageCount (void) 1303 { 1304 OSL_ASSERT(!mbIsDisposed); 1305 if (mbIsDisposed) 1306 return 0; 1307 else 1308 return maPrinterPages.size(); 1309 } 1310 1311 1312 1313 /** Return a sequence of properties that can be returned by the 1314 XRenderable::getRenderer() method. 1315 */ 1316 css::uno::Sequence<css::beans::PropertyValue> GetProperties ( 1317 const css::uno::Sequence<css::beans::PropertyValue>& rOptions) 1318 { 1319 (void)rOptions; 1320 1321 css::uno::Sequence<css::beans::PropertyValue> aProperties (3); 1322 1323 aProperties[0].Name = A2S("ExtraPrintUIOptions"); 1324 aProperties[0].Value <<= m_aUIProperties; 1325 1326 aProperties[1].Name = A2S("PageSize"); 1327 aProperties[1].Value <<= maPrintSize; 1328 1329 // FIXME: is this always true ? 1330 aProperties[2].Name = A2S("PageIncludesNonprintableArea"); 1331 aProperties[2].Value = makeAny( sal_True ); 1332 1333 return aProperties; 1334 } 1335 1336 1337 1338 1339 /** Print one of the prepared pages. 1340 */ 1341 void PrintPage (const sal_Int32 nIndex) 1342 { 1343 OSL_ASSERT(!mbIsDisposed); 1344 if (mbIsDisposed) 1345 return; 1346 1347 Printer& rPrinter (*mpPrinter); 1348 1349 ::boost::shared_ptr<ViewShell> pViewShell (mrBase.GetMainViewShell()); 1350 if ( ! pViewShell) 1351 return; 1352 1353 SdDrawDocument* pDocument = pViewShell->GetDoc(); 1354 OSL_ASSERT(pDocument!=NULL); 1355 1356 ::boost::shared_ptr<DrawViewShell> pDrawViewShell( 1357 ::boost::dynamic_pointer_cast<DrawViewShell>(mrBase.GetMainViewShell())); 1358 1359 if ( ! mpPrintView) 1360 mpPrintView.reset(new DrawView(mrBase.GetDocShell(), &rPrinter, pDrawViewShell.get())); 1361 1362 if (nIndex<0 || sal::static_int_cast<sal_uInt32>(nIndex)>=maPrinterPages.size()) 1363 return; 1364 1365 const ::boost::shared_ptr<PrinterPage> pPage (maPrinterPages[nIndex]); 1366 OSL_ASSERT(pPage); 1367 if ( ! pPage) 1368 return; 1369 1370 const Orientation eSavedOrientation (rPrinter.GetOrientation()); 1371 const sal_uLong nSavedDrawMode (rPrinter.GetDrawMode()); 1372 const MapMode aSavedMapMode (rPrinter.GetMapMode()); 1373 const sal_uInt16 nSavedPaperBin (rPrinter.GetPaperBin()); 1374 1375 1376 // Set page orientation. 1377 if ( ! rPrinter.SetOrientation(pPage->GetOrientation())) 1378 { 1379 if ( ! mbHasOrientationWarningBeenShown 1380 && mpOptions->IsWarningOrientation()) 1381 { 1382 mbHasOrientationWarningBeenShown = true; 1383 // Show warning that the orientation could not be set. 1384 if (pViewShell) 1385 { 1386 WarningBox aWarnBox( 1387 pViewShell->GetActiveWindow(), 1388 (WinBits)(WB_OK_CANCEL | WB_DEF_CANCEL), 1389 String(SdResId(STR_WARN_PRINTFORMAT_FAILURE))); 1390 if (aWarnBox.Execute() != RET_OK) 1391 return; 1392 } 1393 } 1394 } 1395 1396 // Set the draw mode. 1397 rPrinter.SetDrawMode(pPage->GetDrawMode()); 1398 1399 // Set paper tray. 1400 rPrinter.SetPaperBin(pPage->GetPaperTray()); 1401 1402 // Print the actual page. 1403 pPage->Print( 1404 rPrinter, 1405 *pDocument, 1406 *pViewShell, 1407 pDrawViewShell ? pDrawViewShell->GetView() : NULL, 1408 *mpPrintView, 1409 pViewShell->GetFrameView()->GetVisibleLayers(), 1410 pViewShell->GetFrameView()->GetPrintableLayers()); 1411 1412 rPrinter.SetOrientation(eSavedOrientation); 1413 rPrinter.SetDrawMode(nSavedDrawMode); 1414 rPrinter.SetMapMode(aSavedMapMode); 1415 rPrinter.SetPaperBin(nSavedPaperBin); 1416 } 1417 1418 1419 1420 1421 private: 1422 ViewShellBase& mrBase; 1423 bool mbIsDisposed; 1424 Printer* mpPrinter; 1425 Size maPrinterPageSizePixel; 1426 ::boost::scoped_ptr<PrintOptions> mpOptions; 1427 ::std::vector< ::boost::shared_ptr< ::sd::PrinterPage> > maPrinterPages; 1428 ::boost::scoped_ptr<DrawView> mpPrintView; 1429 bool mbHasOrientationWarningBeenShown; 1430 ::std::vector<sal_Int32> maSlidesPerPage; 1431 awt::Size maPrintSize; 1432 1433 void Dispose (void) 1434 { 1435 mbIsDisposed = true; 1436 } 1437 1438 1439 1440 /** Determine and set the paper orientation. 1441 */ 1442 bool SetupPaperOrientation ( 1443 const PageKind ePageKind, 1444 PrintInfo& rInfo) 1445 { 1446 SdDrawDocument* pDocument = mrBase.GetMainViewShell()->GetDoc(); 1447 rInfo.meOrientation = ORIENTATION_PORTRAIT; 1448 1449 if( ! mpOptions->IsBooklet()) 1450 { 1451 rInfo.meOrientation = pDocument->GetSdPage(0, ePageKind)->GetOrientation(); 1452 } 1453 else if (rInfo.maPageSize.Width() < rInfo.maPageSize.Height()) 1454 rInfo.meOrientation = ORIENTATION_LANDSCAPE; 1455 1456 const Size aPaperSize (rInfo.mpPrinter->GetPaperSize()); 1457 if( (rInfo.meOrientation == ORIENTATION_LANDSCAPE && 1458 (aPaperSize.Width() < aPaperSize.Height())) 1459 || 1460 (rInfo.meOrientation == ORIENTATION_PORTRAIT && 1461 (aPaperSize.Width() > aPaperSize.Height())) 1462 ) 1463 { 1464 maPrintSize = awt::Size(aPaperSize.Height(), aPaperSize.Width()); 1465 // rInfo.maPrintSize = Size(rInfo.maPrintSize.Height(), rInfo.maPrintSize.Width()); 1466 } 1467 else 1468 { 1469 maPrintSize = awt::Size(aPaperSize.Width(), aPaperSize.Height()); 1470 } 1471 1472 return true; 1473 } 1474 1475 1476 1477 /** Top most method for preparing printer pages. In this and the other 1478 Prepare... methods the various special cases are detected and 1479 handled. 1480 For every page that is to be printed (that may contain several 1481 slides) one PrinterPage object is created and inserted into 1482 maPrinterPages. 1483 */ 1484 void PreparePages (void) 1485 { 1486 mpPrintView.reset(); 1487 maPrinterPages.clear(); 1488 mbHasOrientationWarningBeenShown = false; 1489 1490 ViewShell* pShell = mrBase.GetMainViewShell().get(); 1491 1492 PrintInfo aInfo (mpPrinter, mpOptions->GetPrinterSelection(), mrBase.GetMainViewShell()); 1493 1494 if (aInfo.mpPrinter!=NULL && pShell!=NULL) 1495 { 1496 1497 MapMode aMap (aInfo.mpPrinter->GetMapMode()); 1498 aMap.SetMapUnit(MAP_100TH_MM); 1499 aInfo.maMap = aMap; 1500 mpPrinter->SetMapMode(aMap); 1501 1502 ::Outliner& rOutliner = mrBase.GetDocument()->GetDrawOutliner(); 1503 const sal_uLong nSavedControlWord (rOutliner.GetControlWord()); 1504 sal_uLong nCntrl = nSavedControlWord; 1505 nCntrl &= ~EE_CNTRL_MARKFIELDS; 1506 nCntrl &= ~EE_CNTRL_ONLINESPELLING; 1507 rOutliner.SetControlWord( nCntrl ); 1508 1509 // When in outline view then apply all pending changes to the model. 1510 if (pShell->ISA(OutlineViewShell)) 1511 static_cast<OutlineViewShell*>(pShell)->PrepareClose (sal_False, sal_False); 1512 1513 // Collect some frequently used data. 1514 if (mpOptions->IsDate()) 1515 { 1516 aInfo.msTimeDate += GetSdrGlobalData().GetLocaleData()->getDate( Date() ); 1517 aInfo.msTimeDate += ::rtl::OUString((sal_Unicode)' '); 1518 } 1519 1520 if (mpOptions->IsTime()) 1521 aInfo.msTimeDate += GetSdrGlobalData().GetLocaleData()->getTime( Time(), sal_False, sal_False ); 1522 aInfo.maPrintSize = aInfo.mpPrinter->GetOutputSize(); 1523 maPrintSize = awt::Size( 1524 aInfo.mpPrinter->GetPaperSize().Width(), 1525 aInfo.mpPrinter->GetPaperSize().Height()); 1526 1527 switch (mpOptions->GetOutputQuality()) 1528 { 1529 case 1: 1530 aInfo.mnDrawMode = DRAWMODE_GRAYLINE | DRAWMODE_GRAYFILL 1531 | DRAWMODE_BLACKTEXT | DRAWMODE_GRAYBITMAP 1532 | DRAWMODE_GRAYGRADIENT; 1533 break; 1534 1535 case 2: 1536 aInfo.mnDrawMode = DRAWMODE_BLACKLINE | DRAWMODE_BLACKTEXT 1537 | DRAWMODE_WHITEFILL | DRAWMODE_GRAYBITMAP 1538 | DRAWMODE_WHITEGRADIENT; 1539 break; 1540 1541 default: 1542 aInfo.mnDrawMode = DRAWMODE_DEFAULT; 1543 } 1544 1545 // check if selected range of pages contains transparent objects 1546 /* 1547 const bool bPrintPages (bPrintNotes || bPrintDraw || bPrintHandout); 1548 const bool bContainsTransparency (bPrintPages && ContainsTransparency()); 1549 if (pPrinter->InitJob (mrBase.GetWindow(), !bIsAPI && bContainsTransparency)) 1550 */ 1551 1552 if (mpOptions->IsDraw()) 1553 PrepareStdOrNotes(PK_STANDARD, aInfo); 1554 if (mpOptions->IsNotes()) 1555 PrepareStdOrNotes(PK_NOTES, aInfo); 1556 if (mpOptions->IsHandout()) 1557 { 1558 InitHandoutTemplate(); 1559 PrepareHandout(aInfo); 1560 } 1561 if (mpOptions->IsOutline()) 1562 PrepareOutline(aInfo); 1563 1564 rOutliner.SetControlWord(nSavedControlWord); 1565 } 1566 } 1567 1568 1569 1570 1571 /** Create the page objects of the handout template. When the actual 1572 printing takes place then the page objects are assigned different 1573 sets of slides for each printed page (see HandoutPrinterPage::Print). 1574 */ 1575 void InitHandoutTemplate (void) 1576 { 1577 const sal_Int32 nSlidesPerHandout (mpOptions->GetHandoutPageCount()); 1578 const bool bHandoutHorizontal (mpOptions->IsHandoutHorizontal()); 1579 1580 AutoLayout eLayout = AUTOLAYOUT_HANDOUT6; 1581 switch (nSlidesPerHandout) 1582 { 1583 case 0: eLayout = AUTOLAYOUT_NONE; break; // AUTOLAYOUT_HANDOUT1; break; 1584 case 1: eLayout = AUTOLAYOUT_HANDOUT1; break; 1585 case 2: eLayout = AUTOLAYOUT_HANDOUT2; break; 1586 case 3: eLayout = AUTOLAYOUT_HANDOUT3; break; 1587 case 4: eLayout = AUTOLAYOUT_HANDOUT4; break; 1588 default: 1589 case 6: eLayout = AUTOLAYOUT_HANDOUT6; break; 1590 case 9: eLayout = AUTOLAYOUT_HANDOUT9; break; 1591 } 1592 1593 if( !mrBase.GetDocument() ) 1594 return; 1595 1596 SdDrawDocument& rModel = *mrBase.GetDocument(); 1597 1598 // first, prepare handout page (not handout master) 1599 1600 SdPage* pHandout = rModel.GetSdPage(0, PK_HANDOUT); 1601 if( !pHandout ) 1602 return; 1603 1604 // delete all previous shapes from handout page 1605 while( pHandout->GetObjCount() ) 1606 { 1607 SdrObject* pObj = pHandout->NbcRemoveObject(0); 1608 if( pObj ) 1609 SdrObject::Free( pObj ); 1610 } 1611 1612 const bool bDrawLines (eLayout == AUTOLAYOUT_HANDOUT3); 1613 1614 std::vector< Rectangle > aAreas; 1615 SdPage::CalculateHandoutAreas( rModel, eLayout, bHandoutHorizontal, aAreas ); 1616 1617 std::vector< Rectangle >::iterator iter( aAreas.begin() ); 1618 while( iter != aAreas.end() ) 1619 { 1620 pHandout->NbcInsertObject( new SdrPageObj((*iter++)) ); 1621 1622 if( bDrawLines && (iter != aAreas.end()) ) 1623 { 1624 Rectangle aRect( (*iter++) ); 1625 1626 basegfx::B2DPolygon aPoly; 1627 aPoly.insert(0, basegfx::B2DPoint( aRect.Left(), aRect.Top() ) ); 1628 aPoly.insert(1, basegfx::B2DPoint( aRect.Right(), aRect.Top() ) ); 1629 1630 basegfx::B2DHomMatrix aMatrix; 1631 aMatrix.translate( 0.0, static_cast< double >( aRect.GetHeight() / 7 ) ); 1632 1633 basegfx::B2DPolyPolygon aPathPoly; 1634 for( sal_uInt16 nLine = 0; nLine < 7; nLine++ ) 1635 { 1636 aPoly.transform( aMatrix ); 1637 aPathPoly.append( aPoly ); 1638 } 1639 1640 SdrPathObj* pPathObj = new SdrPathObj(OBJ_PATHLINE, aPathPoly ); 1641 pPathObj->SetMergedItem(XLineStyleItem(XLINE_SOLID)); 1642 pPathObj->SetMergedItem(XLineColorItem(String(), Color(COL_BLACK))); 1643 1644 pHandout->NbcInsertObject( pPathObj ); 1645 } 1646 } 1647 } 1648 1649 1650 1651 1652 /** Detect whether any of the slides that are to be printed contains 1653 partially transparent or translucent shapes. 1654 */ 1655 bool ContainsTransparency (const PrintInfo& rInfo) const 1656 { 1657 // const bool bPrintExcluded (mpOptions->IsPrintExcluded()); 1658 bool bContainsTransparency = false; 1659 1660 for (sal_uInt16 1661 nIndex=0, 1662 nCount=mrBase.GetDocument()->GetSdPageCount(PK_STANDARD); 1663 nIndex < nCount && !bContainsTransparency; 1664 ++nIndex) 1665 { 1666 SdPage* pPage = GetFilteredPage(nIndex, PK_STANDARD, rInfo); 1667 if (pPage == NULL) 1668 continue; 1669 1670 bContainsTransparency = pPage->HasTransparentObjects(); 1671 if ( ! bContainsTransparency && pPage->TRG_HasMasterPage()) 1672 bContainsTransparency = pPage->TRG_GetMasterPage().HasTransparentObjects(); 1673 } 1674 1675 return bContainsTransparency; 1676 } 1677 1678 1679 1680 1681 /** Detect whether the specified slide is to be printed. 1682 @return 1683 When the slide is not to be printed then <NULL/> is returned. 1684 Otherwise a pointer to the slide is returned. 1685 */ 1686 SdPage* GetFilteredPage ( 1687 const sal_Int32 nPageIndex, 1688 const PageKind ePageKind, 1689 const PrintInfo& rInfo) const 1690 { 1691 OSL_ASSERT(mrBase.GetDocument() != NULL); 1692 OSL_ASSERT(nPageIndex>=0); 1693 if ( ! rInfo.maSelection.IsSelected(nPageIndex)) 1694 return NULL; 1695 SdPage* pPage = mrBase.GetDocument()->GetSdPage( 1696 sal::static_int_cast<sal_uInt16>(nPageIndex), 1697 ePageKind); 1698 if (pPage == NULL) 1699 return NULL; 1700 if ( ! pPage->IsExcluded() || mpOptions->IsPrintExcluded()) 1701 return pPage; 1702 else 1703 return NULL; 1704 } 1705 1706 1707 1708 1709 /** Prepare the outline of the document for printing. There is no fixed 1710 number of slides whose outline data is put onto one printer page. 1711 If the current printer page has enough room for the outline of the 1712 current slide then that is added. Otherwise a new printer page is 1713 started. 1714 */ 1715 void PrepareOutline (PrintInfo& rInfo) 1716 { 1717 MapMode aMap (rInfo.maMap); 1718 Point aPageOfs (rInfo.mpPrinter->GetPageOffset() ); 1719 // aMap.SetOrigin(Point() - aPageOfs); 1720 aMap.SetScaleX(Fraction(1,2)); 1721 aMap.SetScaleY(Fraction(1,2)); 1722 mpPrinter->SetMapMode(aMap); 1723 1724 Rectangle aOutRect(aPageOfs, rInfo.mpPrinter->GetOutputSize()); 1725 if( aOutRect.GetWidth() > aOutRect.GetHeight() ) 1726 { 1727 Size aPaperSize( rInfo.mpPrinter->PixelToLogic( rInfo.mpPrinter->GetPaperSizePixel(), MapMode( MAP_100TH_MM ) ) ); 1728 maPrintSize.Width = aPaperSize.Height(); 1729 maPrintSize.Height = aPaperSize.Width(); 1730 aOutRect = Rectangle( Point( aPageOfs.Y(), aPageOfs.X() ), 1731 Size( aOutRect.GetHeight(), aOutRect.GetWidth() ) ); 1732 } 1733 1734 Link aOldLink; 1735 Outliner* pOutliner = mrBase.GetDocument()->GetInternalOutliner(); 1736 pOutliner->Init(OUTLINERMODE_OUTLINEVIEW); 1737 const sal_uInt16 nSavedOutlMode (pOutliner->GetMode()); 1738 const sal_Bool bSavedUpdateMode (pOutliner->GetUpdateMode()); 1739 const Size aSavedPaperSize (pOutliner->GetPaperSize()); 1740 const MapMode aSavedMapMode (pOutliner->GetRefMapMode()); 1741 pOutliner->SetPaperSize(aOutRect.GetSize()); 1742 pOutliner->SetUpdateMode(sal_True); 1743 1744 long nPageH = aOutRect.GetHeight(); 1745 1746 for (sal_uInt16 1747 nIndex=0, 1748 nCount=mrBase.GetDocument()->GetSdPageCount(PK_STANDARD); 1749 nIndex < nCount; 1750 ) 1751 { 1752 pOutliner->Clear(); 1753 pOutliner->SetFirstPageNumber(nIndex+1); 1754 1755 Paragraph* pPara = NULL; 1756 sal_Int32 nH (0); 1757 while (nH < nPageH && nIndex<nCount) 1758 { 1759 SdPage* pPage = GetFilteredPage(nIndex, PK_STANDARD, rInfo); 1760 ++nIndex; 1761 if (pPage == NULL) 1762 continue; 1763 1764 SdrTextObj* pTextObj = NULL; 1765 sal_uInt32 nObj (0); 1766 1767 while (pTextObj==NULL && nObj < pPage->GetObjCount()) 1768 { 1769 SdrObject* pObj = pPage->GetObj(nObj++); 1770 if (pObj->GetObjInventor() == SdrInventor 1771 && pObj->GetObjIdentifier() == OBJ_TITLETEXT) 1772 { 1773 pTextObj = dynamic_cast<SdrTextObj*>(pObj); 1774 } 1775 } 1776 1777 pPara = pOutliner->GetParagraph(pOutliner->GetParagraphCount() - 1); 1778 1779 if (pTextObj!=NULL 1780 && !pTextObj->IsEmptyPresObj() 1781 && pTextObj->GetOutlinerParaObject()) 1782 { 1783 pOutliner->AddText(*(pTextObj->GetOutlinerParaObject())); 1784 } 1785 else 1786 pOutliner->Insert(String()); 1787 1788 pTextObj = NULL; 1789 nObj = 0; 1790 1791 while (pTextObj==NULL && nObj<pPage->GetObjCount()) 1792 { 1793 SdrObject* pObj = pPage->GetObj(nObj++); 1794 if (pObj->GetObjInventor() == SdrInventor 1795 && pObj->GetObjIdentifier() == OBJ_OUTLINETEXT) 1796 { 1797 pTextObj = dynamic_cast<SdrTextObj*>(pObj); 1798 } 1799 } 1800 1801 bool bSubTitle (false); 1802 if (!pTextObj) 1803 { 1804 bSubTitle = true; 1805 pTextObj = dynamic_cast<SdrTextObj*>(pPage->GetPresObj(PRESOBJ_TEXT)); // Untertitel vorhanden? 1806 } 1807 1808 sal_uLong nParaCount1 = pOutliner->GetParagraphCount(); 1809 1810 if (pTextObj!=NULL 1811 && !pTextObj->IsEmptyPresObj() 1812 && pTextObj->GetOutlinerParaObject()) 1813 { 1814 pOutliner->AddText(*(pTextObj->GetOutlinerParaObject())); 1815 } 1816 1817 if (bSubTitle ) 1818 { 1819 const sal_Int32 nParaCount2 (pOutliner->GetParagraphCount()); 1820 for (sal_Int32 nPara=nParaCount1; nPara<nParaCount2; ++nPara) 1821 { 1822 Paragraph* pP = pOutliner->GetParagraph(nPara); 1823 if (pP!=NULL && pOutliner->GetDepth((sal_uInt16)nPara) > 0) 1824 pOutliner->SetDepth(pP, 0); 1825 } 1826 } 1827 1828 nH = pOutliner->GetTextHeight(); 1829 } 1830 1831 // Remove the last paragraph when that does not fit completely on 1832 // the current page. 1833 if (nH > nPageH && pPara!=NULL) 1834 { 1835 sal_uLong nCnt = pOutliner->GetAbsPos( 1836 pOutliner->GetParagraph( pOutliner->GetParagraphCount() - 1 ) ); 1837 sal_uLong nParaPos = pOutliner->GetAbsPos( pPara ); 1838 nCnt -= nParaPos; 1839 pPara = pOutliner->GetParagraph( ++nParaPos ); 1840 if ( nCnt && pPara ) 1841 { 1842 pOutliner->Remove(pPara, nCnt); 1843 --nIndex; 1844 } 1845 } 1846 1847 maPrinterPages.push_back( 1848 ::boost::shared_ptr<PrinterPage>( 1849 new OutlinerPrinterPage( 1850 pOutliner->CreateParaObject(), 1851 aMap, 1852 rInfo.msTimeDate, 1853 aPageOfs, 1854 rInfo.mnDrawMode, 1855 rInfo.meOrientation, 1856 rInfo.mpPrinter->GetPaperBin()))); 1857 } 1858 1859 pOutliner->SetRefMapMode(aSavedMapMode); 1860 pOutliner->SetUpdateMode(bSavedUpdateMode); 1861 pOutliner->SetPaperSize(aSavedPaperSize); 1862 pOutliner->Init(nSavedOutlMode); 1863 } 1864 1865 1866 1867 1868 /** Prepare handout pages for slides that are to be printed. 1869 */ 1870 void PrepareHandout (PrintInfo& rInfo) 1871 { 1872 SdDrawDocument* pDocument = mrBase.GetDocument(); 1873 OSL_ASSERT(pDocument != NULL); 1874 SdPage& rHandoutPage (*pDocument->GetSdPage(0, PK_HANDOUT)); 1875 1876 const bool bScalePage (mpOptions->IsPageSize()); 1877 1878 sal_uInt16 nPaperBin; 1879 if ( ! mpOptions->IsPaperBin()) 1880 nPaperBin = rHandoutPage.GetPaperBin(); 1881 else 1882 nPaperBin = rInfo.mpPrinter->GetPaperBin(); 1883 1884 // Change orientation? 1885 SdPage& rMaster (dynamic_cast<SdPage&>(rHandoutPage.TRG_GetMasterPage())); 1886 rInfo.meOrientation = rMaster.GetOrientation(); 1887 1888 const Size aPaperSize (rInfo.mpPrinter->GetPaperSize()); 1889 if( (rInfo.meOrientation == ORIENTATION_LANDSCAPE && 1890 (aPaperSize.Width() < aPaperSize.Height())) 1891 || 1892 (rInfo.meOrientation == ORIENTATION_PORTRAIT && 1893 (aPaperSize.Width() > aPaperSize.Height())) 1894 ) 1895 { 1896 maPrintSize = awt::Size(aPaperSize.Height(), aPaperSize.Width()); 1897 } 1898 else 1899 { 1900 maPrintSize = awt::Size(aPaperSize.Width(), aPaperSize.Height()); 1901 } 1902 1903 MapMode aMap (rInfo.maMap); 1904 const Point aPageOfs (rInfo.mpPrinter->GetPageOffset()); 1905 //DrawView* pPrintView; 1906 1907 // aMap.SetOrigin(Point() - aPageOfs); 1908 1909 if ( bScalePage ) 1910 { 1911 const Size aPageSize (rHandoutPage.GetSize()); 1912 const Size aPrintSize (rInfo.mpPrinter->GetOutputSize()); 1913 1914 const double fHorz = (double) aPrintSize.Width() / aPageSize.Width(); 1915 const double fVert = (double) aPrintSize.Height() / aPageSize.Height(); 1916 1917 Fraction aFract; 1918 if ( fHorz < fVert ) 1919 aFract = Fraction(aPrintSize.Width(), aPageSize.Width()); 1920 else 1921 aFract = Fraction(aPrintSize.Height(), aPageSize.Height()); 1922 1923 aMap.SetScaleX(aFract); 1924 aMap.SetScaleY(aFract); 1925 aMap.SetOrigin(Point()); 1926 } 1927 1928 ::boost::shared_ptr<ViewShell> pViewShell (mrBase.GetMainViewShell()); 1929 pViewShell->WriteFrameViewData(); 1930 1931 // Count page shapes. 1932 sal_uInt32 nShapeCount (0); 1933 SdrObjListIter aShapeIter (rHandoutPage); 1934 while (aShapeIter.IsMore()) 1935 { 1936 SdrPageObj* pPageObj = dynamic_cast<SdrPageObj*>(aShapeIter.Next()); 1937 if (pPageObj) 1938 ++nShapeCount; 1939 } 1940 1941 const sal_uInt16 nPageCount = mrBase.GetDocument()->GetSdPageCount(PK_STANDARD); 1942 const sal_uInt16 nHandoutPageCount = nShapeCount ? (nPageCount + nShapeCount - 1) / nShapeCount : 0; 1943 pViewShell->SetPrintedHandoutPageCount( nHandoutPageCount ); 1944 mrBase.GetDocument()->setHandoutPageCount( nHandoutPageCount ); 1945 1946 // Distribute pages to handout pages. 1947 ::std::vector<sal_uInt16> aPageIndices; 1948 for (sal_uInt16 1949 nIndex=0, 1950 nCount= nPageCount, 1951 nHandoutPageIndex=0; 1952 nIndex <= nCount; 1953 ++nIndex) 1954 { 1955 if (nIndex < nCount) 1956 { 1957 if (GetFilteredPage(nIndex, PK_STANDARD, rInfo) == NULL) 1958 continue; 1959 aPageIndices.push_back(nIndex); 1960 } 1961 1962 // Create a printer page when we have found one page for each 1963 // placeholder or when this is the last (and special) loop. 1964 if (!aPageIndices.empty() && (aPageIndices.size() == nShapeCount || nIndex==nCount)) 1965 { 1966 maPrinterPages.push_back( 1967 ::boost::shared_ptr<PrinterPage>( 1968 new HandoutPrinterPage( 1969 nHandoutPageIndex++, 1970 aPageIndices, 1971 aMap, 1972 rInfo.msTimeDate, 1973 aPageOfs, 1974 rInfo.mnDrawMode, 1975 rInfo.meOrientation, 1976 nPaperBin))); 1977 aPageIndices.clear(); 1978 } 1979 } 1980 } 1981 1982 1983 1984 1985 /** Prepare the notes pages or regular slides. 1986 */ 1987 void PrepareStdOrNotes ( 1988 const PageKind ePageKind, 1989 PrintInfo& rInfo) 1990 { 1991 OSL_ASSERT(rInfo.mpPrinter != NULL); 1992 1993 // Fill in page kind specific data. 1994 SdDrawDocument* pDocument = mrBase.GetMainViewShell()->GetDoc(); 1995 if (pDocument->GetSdPageCount(ePageKind) == 0) 1996 return; 1997 SdPage* pRefPage = pDocument->GetSdPage(0, ePageKind); 1998 rInfo.maPageSize = pRefPage->GetSize(); 1999 2000 if ( ! SetupPaperOrientation(ePageKind, rInfo)) 2001 return; 2002 2003 MapMode aMap (rInfo.maMap); 2004 // aMap.SetOrigin(Point() - rInfo.mpPrinter->GetPageOffset()); 2005 rInfo.maMap = aMap; 2006 2007 if (mpOptions->IsBooklet()) 2008 PrepareBooklet(ePageKind, rInfo); 2009 else 2010 PrepareRegularPages(ePageKind, rInfo); 2011 } 2012 2013 2014 2015 2016 /** Prepare slides in a non-booklet way: one slide per one to many 2017 printer pages. 2018 */ 2019 void PrepareRegularPages ( 2020 const PageKind ePageKind, 2021 PrintInfo& rInfo) 2022 { 2023 ::boost::shared_ptr<ViewShell> pViewShell (mrBase.GetMainViewShell()); 2024 pViewShell->WriteFrameViewData(); 2025 Point aPtZero; 2026 2027 for (sal_uInt16 2028 nIndex=0, 2029 nCount=mrBase.GetDocument()->GetSdPageCount(PK_STANDARD); 2030 nIndex < nCount; 2031 ++nIndex) 2032 { 2033 SdPage* pPage = GetFilteredPage(nIndex, ePageKind, rInfo); 2034 if (pPage == NULL) 2035 continue; 2036 2037 MapMode aMap (rInfo.maMap); 2038 // Kann sich die Seitengroesse geaendert haben? 2039 const Size aPageSize = pPage->GetSize(); 2040 2041 if (mpOptions->IsPageSize()) 2042 { 2043 const double fHorz ((double) rInfo.maPrintSize.Width() / aPageSize.Width()); 2044 const double fVert ((double) rInfo.maPrintSize.Height() / aPageSize.Height()); 2045 2046 Fraction aFract; 2047 if (fHorz < fVert) 2048 aFract = Fraction(rInfo.maPrintSize.Width(), aPageSize.Width()); 2049 else 2050 aFract = Fraction(rInfo.maPrintSize.Height(), aPageSize.Height()); 2051 2052 aMap.SetScaleX(aFract); 2053 aMap.SetScaleY(aFract); 2054 aMap.SetOrigin(Point()); 2055 } 2056 2057 if (mpOptions->IsPrintPageName()) 2058 { 2059 rInfo.msPageString = pPage->GetName(); 2060 rInfo.msPageString += ::rtl::OUString(sal_Unicode(' ')); 2061 } 2062 else 2063 rInfo.msPageString = ::rtl::OUString(); 2064 rInfo.msPageString += rInfo.msTimeDate; 2065 2066 long aPageWidth = aPageSize.Width() - pPage->GetLftBorder() - pPage->GetRgtBorder(); 2067 long aPageHeight = aPageSize.Height() - pPage->GetUppBorder() - pPage->GetLwrBorder(); 2068 // Bugfix zu 44530: 2069 // Falls implizit umgestellt wurde (Landscape/Portrait) 2070 // wird dies beim Kacheln, bzw. aufteilen (Poster) beruecksichtigt 2071 sal_Bool bSwitchPageSize = sal_False; 2072 if( ( rInfo.maPrintSize.Width() > rInfo.maPrintSize.Height() 2073 && aPageWidth < aPageHeight ) 2074 || ( rInfo.maPrintSize.Width() < rInfo.maPrintSize.Height() 2075 && aPageWidth > aPageHeight ) ) 2076 { 2077 bSwitchPageSize = sal_True; 2078 const sal_Int32 nTmp (rInfo.maPrintSize.Width()); 2079 rInfo.maPrintSize.Width() = rInfo.maPrintSize.Height(); 2080 rInfo.maPrintSize.Height() = nTmp; 2081 } 2082 2083 if (mpOptions->IsTilePage() 2084 && aPageWidth < rInfo.maPrintSize.Width() 2085 && aPageHeight < rInfo.maPrintSize.Height()) 2086 { 2087 // Put multiple slides on one printer page. 2088 PrepareTiledPage(nIndex, *pPage, ePageKind, rInfo); 2089 } 2090 else 2091 { 2092 rInfo.maMap = aMap; 2093 PrepareScaledPage(nIndex, *pPage, ePageKind, rInfo); 2094 } 2095 } 2096 } 2097 2098 2099 2100 2101 /** Put two slides on one printer page. 2102 */ 2103 void PrepareBooklet ( 2104 const PageKind ePageKind, 2105 const PrintInfo& rInfo) 2106 { 2107 MapMode aStdMap (rInfo.maMap); 2108 Point aOffset; 2109 Size aPrintSize_2 (rInfo.maPrintSize); 2110 Size aPageSize_2 (rInfo.maPageSize); 2111 2112 if (rInfo.meOrientation == ORIENTATION_LANDSCAPE) 2113 aPrintSize_2.Width() >>= 1; 2114 else 2115 aPrintSize_2.Height() >>= 1; 2116 2117 const double fPageWH = (double) aPageSize_2.Width() / aPageSize_2.Height(); 2118 const double fPrintWH = (double) aPrintSize_2.Width() / aPrintSize_2.Height(); 2119 2120 if( fPageWH < fPrintWH ) 2121 { 2122 aPageSize_2.Width() = (long) ( aPrintSize_2.Height() * fPageWH ); 2123 aPageSize_2.Height()= aPrintSize_2.Height(); 2124 } 2125 else 2126 { 2127 aPageSize_2.Width() = aPrintSize_2.Width(); 2128 aPageSize_2.Height() = (long) ( aPrintSize_2.Width() / fPageWH ); 2129 } 2130 2131 MapMode aMap (rInfo.maMap); 2132 aMap.SetScaleX( Fraction( aPageSize_2.Width(), rInfo.maPageSize.Width() ) ); 2133 aMap.SetScaleY( Fraction( aPageSize_2.Height(), rInfo.maPageSize.Height() ) ); 2134 2135 // calculate adjusted print size 2136 const Size aAdjustedPrintSize (OutputDevice::LogicToLogic( 2137 rInfo.maPrintSize, 2138 aStdMap, 2139 aMap)); 2140 2141 if (rInfo.meOrientation == ORIENTATION_LANDSCAPE) 2142 { 2143 aOffset.X() = ( ( aAdjustedPrintSize.Width() >> 1 ) - rInfo.maPageSize.Width() ) >> 1; 2144 aOffset.Y() = ( aAdjustedPrintSize.Height() - rInfo.maPageSize.Height() ) >> 1; 2145 } 2146 else 2147 { 2148 aOffset.X() = ( aAdjustedPrintSize.Width() - rInfo.maPageSize.Width() ) >> 1; 2149 aOffset.Y() = ( ( aAdjustedPrintSize.Height() >> 1 ) - rInfo.maPageSize.Height() ) >> 1; 2150 } 2151 2152 // create vector of pages to print 2153 ::std::vector< sal_uInt16 > aPageVector; 2154 for (sal_uInt16 2155 nIndex=0, 2156 nCount=mrBase.GetDocument()->GetSdPageCount(ePageKind); 2157 nIndex < nCount; 2158 ++nIndex) 2159 { 2160 SdPage* pPage = GetFilteredPage(nIndex, ePageKind, rInfo); 2161 if (pPage != NULL) 2162 aPageVector.push_back(nIndex); 2163 } 2164 2165 // create pairs of pages to print on each page 2166 typedef ::std::vector< ::std::pair< sal_uInt16, sal_uInt16 > > PairVector; 2167 PairVector aPairVector; 2168 if ( ! aPageVector.empty()) 2169 { 2170 sal_uInt32 nFirstIndex = 0, nLastIndex = aPageVector.size() - 1; 2171 2172 if( aPageVector.size() & 1 ) 2173 aPairVector.push_back( ::std::make_pair( (sal_uInt16) 65535, aPageVector[ nFirstIndex++ ] ) ); 2174 else 2175 aPairVector.push_back( ::std::make_pair( aPageVector[ nLastIndex-- ], aPageVector[ nFirstIndex++ ] ) ); 2176 2177 while( nFirstIndex < nLastIndex ) 2178 { 2179 if( nFirstIndex & 1 ) 2180 aPairVector.push_back( ::std::make_pair( aPageVector[ nFirstIndex++ ], aPageVector[ nLastIndex-- ] ) ); 2181 else 2182 aPairVector.push_back( ::std::make_pair( aPageVector[ nLastIndex-- ], aPageVector[ nFirstIndex++ ] ) ); 2183 } 2184 } 2185 2186 for (sal_uInt32 2187 nIndex=0, 2188 nCount=aPairVector.size(); 2189 nIndex < nCount; 2190 ++nIndex) 2191 { 2192 const bool bIsIndexOdd (nIndex & 1); 2193 if ((!bIsIndexOdd && mpOptions->IsPrintFrontPage()) 2194 || (bIsIndexOdd && mpOptions->IsPrintBackPage())) 2195 { 2196 const ::std::pair<sal_uInt16, sal_uInt16> aPair (aPairVector[nIndex]); 2197 Point aSecondOffset (aOffset); 2198 if (rInfo.meOrientation == ORIENTATION_LANDSCAPE) 2199 aSecondOffset.X() += aAdjustedPrintSize.Width() / 2; 2200 else 2201 aSecondOffset.Y() += aAdjustedPrintSize.Height() / 2; 2202 maPrinterPages.push_back( 2203 ::boost::shared_ptr<PrinterPage>( 2204 new BookletPrinterPage( 2205 aPair.first, 2206 aPair.second, 2207 aOffset, 2208 aSecondOffset, 2209 ePageKind, 2210 aMap, 2211 rInfo.mbPrintMarkedOnly, 2212 rInfo.mnDrawMode, 2213 rInfo.meOrientation, 2214 rInfo.mpPrinter->GetPaperBin()))); 2215 2216 } 2217 } 2218 } 2219 2220 2221 2222 2223 /** Print one slide multiple times on one printer page so that the whole 2224 printer page is covered. 2225 */ 2226 void PrepareTiledPage ( 2227 const sal_Int32 nPageIndex, 2228 const SdPage& rPage, 2229 const PageKind ePageKind, 2230 const PrintInfo& rInfo) 2231 { 2232 sal_uInt16 nPaperBin; 2233 if ( ! mpOptions->IsPaperBin()) 2234 nPaperBin = rPage.GetPaperBin(); 2235 else 2236 nPaperBin = rInfo.mpPrinter->GetPaperBin(); 2237 2238 maPrinterPages.push_back( 2239 ::boost::shared_ptr<PrinterPage>( 2240 new TiledPrinterPage( 2241 sal::static_int_cast<sal_uInt16>(nPageIndex), 2242 ePageKind, 2243 500, 2244 rInfo.mbPrintMarkedOnly, 2245 rInfo.msPageString, 2246 rInfo.mpPrinter->GetPageOffset(), 2247 rInfo.mnDrawMode, 2248 rInfo.meOrientation, 2249 nPaperBin))); 2250 } 2251 2252 2253 2254 /** Print one standard slide or notes page on one to many printer 2255 pages. More than on printer page is used when the slide is larger 2256 than the printable area. 2257 */ 2258 void PrepareScaledPage ( 2259 const sal_Int32 nPageIndex, 2260 const SdPage& rPage, 2261 const PageKind ePageKind, 2262 const PrintInfo& rInfo) 2263 { 2264 const Point aPageOffset (rInfo.mpPrinter->GetPageOffset()); 2265 2266 sal_uInt16 nPaperBin; 2267 if ( ! mpOptions->IsPaperBin()) 2268 nPaperBin = rPage.GetPaperBin(); 2269 else 2270 nPaperBin = rInfo.mpPrinter->GetPaperBin(); 2271 2272 // For pages larger then the printable area there 2273 // are three options: 2274 // 1. Scale down to the page to the printable area. 2275 // 2. Print only the upper left part of the page 2276 // (without the unprintable borders). 2277 // 3. Split the page into parts of the size of the 2278 // printable area. 2279 const bool bScalePage (mpOptions->IsPageSize()); 2280 const bool bCutPage (mpOptions->IsCutPage()); 2281 MapMode aMap (rInfo.maMap); 2282 if (bScalePage || bCutPage) 2283 { 2284 // Handle 1 and 2. 2285 2286 // if CutPage is set then do not move it, otherwise move the 2287 // scaled page to printable area 2288 #if 0 2289 if (bCutPage) 2290 aMap.SetOrigin(Point(-aPageOffset.X(), -aPageOffset.Y())); 2291 else 2292 aMap.SetOrigin(Point(0,0)); 2293 #endif 2294 maPrinterPages.push_back( 2295 ::boost::shared_ptr<PrinterPage>( 2296 new RegularPrinterPage( 2297 sal::static_int_cast<sal_uInt16>(nPageIndex), 2298 ePageKind, 2299 aMap, 2300 rInfo.mbPrintMarkedOnly, 2301 rInfo.msPageString, 2302 aPageOffset, 2303 rInfo.mnDrawMode, 2304 rInfo.meOrientation, 2305 nPaperBin))); 2306 } 2307 else 2308 { 2309 // Handle 3. Print parts of the page in the size of the 2310 // printable area until the whole page is covered. 2311 2312 // keep the page content at its position if it fits, otherwise 2313 // move it to the printable area 2314 const long nPageWidth ( 2315 rInfo.maPageSize.Width() - rPage.GetLftBorder() - rPage.GetRgtBorder()); 2316 const long nPageHeight ( 2317 rInfo.maPageSize.Height() - rPage.GetUppBorder() - rPage.GetLwrBorder()); 2318 #if 0 2319 Point aOrigin ( 2320 nPageWidth < rInfo.maPrintSize.Width() ? -aPageOffset.X() : 0, 2321 nPageHeight < rInfo.maPrintSize.Height() ? -aPageOffset.Y() : 0); 2322 #else 2323 Point aOrigin ( 0, 0 ); 2324 #endif 2325 for (Point aPageOrigin = aOrigin; 2326 -aPageOrigin.Y()<nPageHeight; 2327 aPageOrigin.Y() -= rInfo.maPrintSize.Height()) 2328 { 2329 for (aPageOrigin.X()=aOrigin.X(); 2330 -aPageOrigin.X()<nPageWidth; 2331 aPageOrigin.X() -= rInfo.maPrintSize.Width()) 2332 { 2333 aMap.SetOrigin(aPageOrigin); 2334 maPrinterPages.push_back( 2335 ::boost::shared_ptr<PrinterPage>( 2336 new RegularPrinterPage( 2337 sal::static_int_cast<sal_uInt16>(nPageIndex), 2338 ePageKind, 2339 aMap, 2340 rInfo.mbPrintMarkedOnly, 2341 rInfo.msPageString, 2342 aPageOffset, 2343 rInfo.mnDrawMode, 2344 rInfo.meOrientation, 2345 nPaperBin))); 2346 } 2347 } 2348 } 2349 } 2350 }; 2351 2352 2353 2354 2355 //===== DocumentRenderer ====================================================== 2356 2357 DocumentRenderer::DocumentRenderer (ViewShellBase& rBase) 2358 : DocumentRendererInterfaceBase(m_aMutex), 2359 mpImpl(new Implementation(rBase)) 2360 { 2361 } 2362 2363 2364 2365 2366 DocumentRenderer::~DocumentRenderer (void) 2367 { 2368 } 2369 2370 2371 2372 2373 //----- XRenderable ----------------------------------------------------------- 2374 2375 sal_Int32 SAL_CALL DocumentRenderer::getRendererCount ( 2376 const css::uno::Any& aSelection, 2377 const css::uno::Sequence<css::beans::PropertyValue >& rOptions) 2378 throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) 2379 { 2380 (void)aSelection; 2381 mpImpl->ProcessProperties(rOptions); 2382 return mpImpl->GetPrintPageCount(); 2383 } 2384 2385 2386 2387 2388 Sequence<beans::PropertyValue> SAL_CALL DocumentRenderer::getRenderer ( 2389 sal_Int32 nRenderer, 2390 const css::uno::Any& rSelection, 2391 const css::uno::Sequence<css::beans::PropertyValue>& rOptions) 2392 throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) 2393 { 2394 (void)nRenderer; 2395 (void)rSelection; 2396 mpImpl->ProcessProperties(rOptions); 2397 return mpImpl->GetProperties(rOptions); 2398 } 2399 2400 2401 2402 2403 void SAL_CALL DocumentRenderer::render ( 2404 sal_Int32 nRenderer, 2405 const css::uno::Any& rSelection, 2406 const css::uno::Sequence<css::beans::PropertyValue>& rOptions) 2407 throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) 2408 { 2409 (void)rSelection; 2410 mpImpl->ProcessProperties(rOptions); 2411 mpImpl->PrintPage(nRenderer); 2412 } 2413 2414 2415 2416 } // end of namespace sd 2417