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