1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/beans/XPropertySet.hpp>
22 #include <DocumentRenderer.hxx>
23 #include <DocumentRenderer.hrc>
24 #include <ViewShellBase.hxx>
26 #include <drawdoc.hxx>
28 #include <sdresid.hxx>
29 #include <strings.hrc>
30 #include <drawview.hxx>
31 #include <DrawViewShell.hxx>
32 #include <FrameView.hxx>
33 #include <Outliner.hxx>
34 #include <OutlineViewShell.hxx>
35 #include <SlideSorterViewShell.hxx>
36 #include <DrawDocShell.hxx>
38 #include <tools/multisel.hxx>
39 #include <basegfx/polygon/b2dpolygon.hxx>
40 #include <basegfx/polygon/b2dpolypolygon.hxx>
41 #include <basegfx/matrix/b2dhommatrix.hxx>
42 #include <comphelper/propertyvalue.hxx>
43 #include <comphelper/sequence.hxx>
44 #include <rtl/ustrbuf.hxx>
45 #include <editeng/editstat.hxx>
46 #include <editeng/eeitem.hxx>
47 #include <editeng/outlobj.hxx>
48 #include <editeng/ulspitem.hxx>
49 #include <svx/sdtfsitm.hxx>
50 #include <svx/sdooitm.hxx>
51 #include <svx/svdetc.hxx>
52 #include <svx/svditer.hxx>
53 #include <svx/svdopage.hxx>
54 #include <svx/svdopath.hxx>
55 #include <svx/svdpagv.hxx>
56 #include <svx/xlineit0.hxx>
57 #include <svx/xlnclit.hxx>
58 #include <toolkit/awt/vclxdevice.hxx>
59 #include <unotools/localedatawrapper.hxx>
61 #include <vcl/print.hxx>
62 #include <vcl/svapp.hxx>
63 #include <vcl/weld.hxx>
64 #include <unotools/moduleoptions.hxx>
65 #include <xmloff/autolayout.hxx>
66 #include <sfx2/objsh.hxx>
68 #include <officecfg/Office/Draw.hxx>
69 #include <officecfg/Office/Impress.hxx>
75 using namespace ::com::sun::star
;
76 using namespace ::com::sun::star::uno
;
82 void lcl_AdjustPageSize(Size
& rPageSize
, const Size
& rPrintPageSize
)
84 bool bOrientationDiff
= (rPageSize
.Width() < rPageSize
.Height()
85 && rPrintPageSize
.Width() > rPrintPageSize
.Height())
86 || (rPageSize
.Width() > rPageSize
.Height()
87 && rPrintPageSize
.Width() < rPrintPageSize
.Height());
90 ::tools::Long nTmp
= rPageSize
.Width();
91 rPageSize
.setWidth(rPageSize
.Height());
92 rPageSize
.setHeight(nTmp
);
96 /** Convenience class to extract values from the sequence of properties
97 given to one of the XRenderable methods.
103 const vcl::PrinterOptionsHelper
& rHelper
,
104 std::vector
<sal_Int32
>&& rSlidesPerPage
)
105 : mrProperties(rHelper
),
106 maSlidesPerPage(std::move(rSlidesPerPage
))
110 bool IsWarningOrientation() const
112 return GetBoolValue(nullptr, true);
115 bool IsPrintPageName() const
117 return GetBoolValue("IsPrintName", false);
122 return GetBoolValue("IsPrintDateTime", false);
127 return GetBoolValue("IsPrintDateTime", false);
130 bool IsHiddenPages() const
132 return GetBoolValue("IsPrintHidden", false);
135 bool IsHandoutHorizontal() const
137 return GetBoolValue("SlidesPerPageOrder", sal_Int32(0));
140 sal_Int32
GetHandoutPageCount() const
142 sal_uInt32 nIndex
= static_cast<sal_Int32
>(mrProperties
.getIntValue("SlidesPerPage", sal_Int32(0)));
143 if (nIndex
<maSlidesPerPage
.size())
144 return maSlidesPerPage
[nIndex
];
145 else if ( ! maSlidesPerPage
.empty())
146 return maSlidesPerPage
[0];
153 return GetBoolValue("PageContentType", sal_Int32(0));
156 bool IsHandout() const
158 return GetBoolValue("PageContentType", sal_Int32(1));
163 return GetBoolValue("PageContentType", sal_Int32(2));
166 bool IsOutline() const
168 return GetBoolValue("PageContentType", sal_Int32(3));
171 sal_uLong
GetOutputQuality() const
173 sal_Int32 nQuality
= static_cast<sal_Int32
>(mrProperties
.getIntValue( "Quality", sal_Int32(0) ));
177 bool IsPageSize() const
179 return GetBoolValue("PageOptions", sal_Int32(1));
182 bool IsTilePage() const
184 return GetBoolValue("PageOptions", sal_Int32(2)) || GetBoolValue("PageOptions", sal_Int32(3));
187 bool IsCutPage() const
189 return GetBoolValue("PageOptions", sal_Int32(0));
192 bool IsBooklet() const
194 return GetBoolValue("PrintProspect", false);
197 bool IsPrinterPreferred(DocumentType eDocType
) const
199 bool bIsDraw
= eDocType
== DocumentType::Draw
;
200 return IsTilePage() || IsPageSize() || IsBooklet() || (!bIsDraw
&& !IsNotes());
203 bool IsPrintExcluded() const
205 return (IsNotes() || IsDraw() || IsHandout()) && IsHiddenPages();
208 bool IsPrintFrontPage() const
210 sal_Int32 nInclude
= static_cast<sal_Int32
>(mrProperties
.getIntValue( "EvenOdd", 0 ));
211 return nInclude
!= 2;
214 bool IsPrintBackPage() const
216 sal_Int32 nInclude
= static_cast<sal_Int32
>(mrProperties
.getIntValue( "EvenOdd", 0 ));
217 return nInclude
!= 1;
220 bool IsPaperBin() const
222 return GetBoolValue("PrintPaperFromSetup", false);
225 bool IsPrintMarkedOnly() const
227 return GetBoolValue("PrintContent", sal_Int32(4));
230 OUString
GetPrinterSelection (sal_Int32 nPageCount
, sal_Int32 nCurrentPageIndex
) const
232 sal_Int32 nContent
= static_cast<sal_Int32
>(mrProperties
.getIntValue( "PrintContent", 0 ));
233 OUString sFullRange
= "1-" + OUString::number(nPageCount
);
235 if (nContent
== 0) // all pages/slides
240 if (nContent
== 1) // range
242 OUString sValue
= mrProperties
.getStringValue("PageRange");
243 return sValue
.isEmpty() ? sFullRange
: sValue
;
246 if (nContent
== 2 && // selection
247 nCurrentPageIndex
>= 0)
249 return OUString::number(nCurrentPageIndex
+ 1);
256 const vcl::PrinterOptionsHelper
& mrProperties
;
257 const std::vector
<sal_Int32
> maSlidesPerPage
;
259 /** When the value of the property with name pName is a boolean then
260 return its value. When the property is unknown then
261 bDefaultValue is returned. Otherwise <FALSE/> is returned.
265 const bool bDefaultValue
) const
267 bool bValue
= mrProperties
.getBoolValue( pName
, bDefaultValue
);
271 /** Return <TRUE/> when the value of the property with name pName is
272 an integer and its value is nTriggerValue. Otherwise <FALSE/> is
277 const sal_Int32 nTriggerValue
) const
279 sal_Int32 nValue
= static_cast<sal_Int32
>(mrProperties
.getIntValue( pName
, 0 ));
280 return nValue
== nTriggerValue
;
284 /** A collection of values that helps to reduce the number of arguments
285 given to some functions. Note that not all values are set at the
293 const bool bPrintMarkedOnly
)
294 : mpPrinter(pPrinter
),
295 mnDrawMode(DrawModeFlags::Default
),
298 meOrientation(Orientation::Portrait
),
299 mbPrintMarkedOnly(bPrintMarkedOnly
)
302 const VclPtr
<Printer
> mpPrinter
;
303 DrawModeFlags mnDrawMode
;
305 OUString msPageString
;
308 Orientation meOrientation
;
310 const bool mbPrintMarkedOnly
;
313 /** Output one page of the document to the given printer. Note that
314 more than one document page may be output to one printer page.
318 ::sd::View
& rPrintView
,
321 const bool bPrintMarkedOnly
,
322 const SdrLayerIDSet
& rVisibleLayers
,
323 const SdrLayerIDSet
& rPrintableLayers
)
325 rPrintView
.ShowSdrPage(&rPage
);
327 const MapMode
aOriginalMapMode (rPrinter
.GetMapMode());
329 // Set the visible layers
330 SdrPageView
* pPageView
= rPrintView
.GetSdrPageView();
331 OSL_ASSERT(pPageView
!=nullptr);
332 pPageView
->SetVisibleLayers(rVisibleLayers
);
333 pPageView
->SetPrintableLayers(rPrintableLayers
);
335 if (pView
!=nullptr && bPrintMarkedOnly
)
336 pView
->DrawMarkedObj(rPrinter
);
338 rPrintView
.CompleteRedraw(&rPrinter
,
339 vcl::Region(::tools::Rectangle(Point(0,0), rPage
.GetSize())));
341 rPrinter
.SetMapMode(aOriginalMapMode
);
343 rPrintView
.HideSdrPage();
346 /** Output a string (that typically is not part of a document page) to
351 const OUString
& rsPageString
,
352 const Point
& rPageStringOffset
)
354 const vcl::Font
aOriginalFont (rPrinter
.OutputDevice::GetFont());
355 rPrinter
.SetFont(vcl::Font(FAMILY_SWISS
, Size(0, 423)));
356 rPrinter
.DrawText(rPageStringOffset
, rsPageString
);
357 rPrinter
.SetFont(aOriginalFont
);
360 /** Read the resources and process then into a sequence of properties
361 that can be passed to the printing dialog.
366 DialogCreator (ViewShellBase
&rBase
, bool bImpress
, sal_Int32 nCurPage
)
368 , mbImpress(bImpress
)
369 , mnCurPage(nCurPage
)
374 const std::vector
< beans::PropertyValue
>& GetDialogControls() const
379 const std::vector
<sal_Int32
>& GetSlidesPerPage() const
381 return maSlidesPerPage
;
385 ViewShellBase
&mrBase
;
386 std::vector
<beans::PropertyValue
> maProperties
;
387 std::vector
<sal_Int32
> maSlidesPerPage
;
391 void ProcessResource()
393 // load the writer PrinterOptions into the custom tab
394 beans::PropertyValue aOptionsUIFile
;
395 aOptionsUIFile
.Name
= "OptionsUIFile";
397 aOptionsUIFile
.Value
<<= u
"modules/simpress/ui/impressprinteroptions.ui"_ustr
;
399 aOptionsUIFile
.Value
<<= u
"modules/sdraw/ui/drawprinteroptions.ui"_ustr
;
400 maProperties
.push_back(aOptionsUIFile
);
402 SvtModuleOptions aOpt
;
403 OUString
aAppGroupname(SdResId(STR_IMPRESS_PRINT_UI_GROUP_NAME
));
404 aAppGroupname
= aAppGroupname
.replaceFirst("%s", aOpt
.GetModuleName(
405 mbImpress
? SvtModuleOptions::EModule::IMPRESS
: SvtModuleOptions::EModule::DRAW
));
406 AddDialogControl(vcl::PrinterOptionsHelper::setGroupControlOpt(u
"tabcontrol-page2"_ustr
, aAppGroupname
, u
".HelpID:vcl:PrintDialog:TabPage:AppPage"_ustr
));
408 uno::Sequence
< OUString
> aHelpIds
, aWidgetIds
;
411 aHelpIds
= { u
".HelpID:vcl:PrintDialog:PageContentType:ListBox"_ustr
};
412 AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt(
413 u
"impressdocument"_ustr
,
414 SdResId(STR_IMPRESS_PRINT_UI_CONTENT
),
416 u
"PageContentType"_ustr
,
417 CreateChoice(STR_IMPRESS_PRINT_UI_CONTENT_CHOICES
, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_CONTENT_CHOICES
)),
421 aHelpIds
= { u
".HelpID:vcl:PrintDialog:SlidesPerPage:ListBox"_ustr
};
422 vcl::PrinterOptionsHelper::UIControlOptions
aContentOpt( u
"PageContentType"_ustr
, 1 );
423 AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt(
424 u
"slidesperpage"_ustr
,
425 SdResId(STR_IMPRESS_PRINT_UI_SLIDESPERPAGE
),
427 u
"SlidesPerPage"_ustr
,
428 GetSlidesPerPageSequence(),
430 Sequence
< sal_Bool
>(),
435 aHelpIds
= { u
".HelpID:vcl:PrintDialog:SlidesPerPageOrder:ListBox"_ustr
};
436 vcl::PrinterOptionsHelper::UIControlOptions
aSlidesPerPageOpt( u
"SlidesPerPage"_ustr
, -1, true );
437 AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt(
438 u
"slidesperpageorder"_ustr
,
439 SdResId(STR_IMPRESS_PRINT_UI_ORDER
),
441 u
"SlidesPerPageOrder"_ustr
,
442 CreateChoice(STR_IMPRESS_PRINT_UI_ORDER_CHOICES
, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_ORDER_CHOICES
)),
444 Sequence
< sal_Bool
>(),
449 AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt(u
"contents"_ustr
,
450 SdResId(STR_IMPRESS_PRINT_UI_INCLUDE_CONTENT
), u
""_ustr
) );
454 AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u
"printname"_ustr
,
455 SdResId(STR_IMPRESS_PRINT_UI_IS_PRINT_NAME
),
456 u
".HelpID:vcl:PrintDialog:IsPrintName:CheckBox"_ustr
,
457 u
"IsPrintName"_ustr
,
458 officecfg::Office::Impress::Print::Other::PageName::get()
464 AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u
"printname"_ustr
,
465 SdResId(STR_DRAW_PRINT_UI_IS_PRINT_NAME
),
466 u
".HelpID:vcl:PrintDialog:IsPrintName:CheckBox"_ustr
,
467 u
"IsPrintName"_ustr
,
468 officecfg::Office::Draw::Print::Other::PageName::get()
473 AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u
"printdatetime"_ustr
,
474 SdResId(STR_IMPRESS_PRINT_UI_IS_PRINT_DATE
),
475 u
".HelpID:vcl:PrintDialog:IsPrintDateTime:CheckBox"_ustr
,
476 u
"IsPrintDateTime"_ustr
,
477 // Separate settings for time and date in Impress/Draw -> Print page, check that both are set
479 officecfg::Office::Impress::Print::Other::Date::get() &&
480 officecfg::Office::Impress::Print::Other::Time::get() :
481 officecfg::Office::Draw::Print::Other::Date::get() &&
482 officecfg::Office::Draw::Print::Other::Time::get()
488 AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u
"printhidden"_ustr
,
489 SdResId(STR_IMPRESS_PRINT_UI_IS_PRINT_HIDDEN
),
490 u
".HelpID:vcl:PrintDialog:IsPrintHidden:CheckBox"_ustr
,
491 u
"IsPrintHidden"_ustr
,
492 officecfg::Office::Impress::Print::Other::HiddenPage::get()
497 AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt(u
"color"_ustr
,
498 SdResId(STR_IMPRESS_PRINT_UI_QUALITY
), u
""_ustr
) );
500 aHelpIds
= { u
".HelpID:vcl:PrintDialog:Quality:RadioButton:0"_ustr
,
501 u
".HelpID:vcl:PrintDialog:Quality:RadioButton:1"_ustr
,
502 u
".HelpID:vcl:PrintDialog:Quality:RadioButton:2"_ustr
};
503 aWidgetIds
= { u
"originalcolors"_ustr
, u
"grayscale"_ustr
, u
"blackandwhite"_ustr
};
504 AddDialogControl( vcl::PrinterOptionsHelper::setChoiceRadiosControlOpt(
509 CreateChoice(STR_IMPRESS_PRINT_UI_QUALITY_CHOICES
, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_QUALITY_CHOICES
)),
510 mbImpress
? officecfg::Office::Impress::Print::Other::Quality::get() :
511 officecfg::Office::Draw::Print::Other::Quality::get() )
515 AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt(u
"pagesizes"_ustr
,
516 SdResId(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS
), u
""_ustr
) );
518 aHelpIds
= { u
".HelpID:vcl:PrintDialog:PageOptions:RadioButton:0"_ustr
,
519 u
".HelpID:vcl:PrintDialog:PageOptions:RadioButton:1"_ustr
,
520 u
".HelpID:vcl:PrintDialog:PageOptions:RadioButton:2"_ustr
,
521 u
".HelpID:vcl:PrintDialog:PageOptions:RadioButton:3"_ustr
};
522 aWidgetIds
= { u
"originalsize"_ustr
, u
"fittoprintable"_ustr
, u
"distributeonmultiple"_ustr
, u
"tilesheet"_ustr
};
524 // Mutually exclusive page options settings are stored in separate config keys...
525 // TODO: There is no config key to set the distributeonmultiple option as default
526 sal_Int32 nDefaultChoice
= 0;
527 if ( mbImpress
? officecfg::Office::Impress::Print::Page::PageSize::get() :
528 officecfg::Office::Draw::Print::Page::PageSize::get() )
532 else if ( mbImpress
? officecfg::Office::Impress::Print::Page::PageTile::get() :
533 officecfg::Office::Draw::Print::Page::PageTile::get() )
537 vcl::PrinterOptionsHelper::UIControlOptions
aPageOptionsOpt(u
"PrintProspect"_ustr
, 0);
538 AddDialogControl( vcl::PrinterOptionsHelper::setChoiceRadiosControlOpt(
542 u
"PageOptions"_ustr
,
543 mbImpress
? CreateChoice(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES
, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES
)) :
544 CreateChoice(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES_DRAW
, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES_DRAW
)),
546 Sequence
< sal_Bool
>(),
551 vcl::PrinterOptionsHelper::UIControlOptions aBrochureOpt
;
552 aBrochureOpt
.maGroupHint
= "LayoutPage" ;
553 AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt(u
"pagesides"_ustr
,
554 SdResId(STR_IMPRESS_PRINT_UI_PAGE_SIDES
), u
""_ustr
,
558 AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u
"brochure"_ustr
,
559 SdResId(STR_IMPRESS_PRINT_UI_BROCHURE
),
560 u
".HelpID:vcl:PrintDialog:PrintProspect:CheckBox"_ustr
,
561 u
"PrintProspect"_ustr
,
562 mbImpress
? officecfg::Office::Impress::Print::Page::Booklet::get() :
563 officecfg::Office::Draw::Print::Page::Booklet::get(),
568 vcl::PrinterOptionsHelper::UIControlOptions
569 aIncludeOpt( u
"PrintProspect"_ustr
, -1, false );
570 aIncludeOpt
.maGroupHint
= "LayoutPage" ;
571 aHelpIds
= { u
".HelpID:vcl:PrintDialog:PrintProspectInclude:ListBox"_ustr
};
572 AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt(
573 u
"brochureinclude"_ustr
,
574 SdResId(STR_IMPRESS_PRINT_UI_BROCHURE_INCLUDE
),
576 u
"PrintProspectInclude"_ustr
,
577 CreateChoice(STR_IMPRESS_PRINT_UI_BROCHURE_INCLUDE_LIST
, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_BROCHURE_INCLUDE_LIST
)),
579 Sequence
< sal_Bool
>(),
584 // paper tray (on options page)
585 vcl::PrinterOptionsHelper::UIControlOptions aPaperTrayOpt
;
586 aPaperTrayOpt
.maGroupHint
= "OptionsPageOptGroup" ;
587 AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u
"printpaperfromsetup"_ustr
,
588 SdResId(STR_IMPRESS_PRINT_UI_PAPER_TRAY
),
589 u
".HelpID:vcl:PrintDialog:PrintPaperFromSetup:CheckBox"_ustr
,
590 u
"PrintPaperFromSetup"_ustr
,
595 // print range selection
596 vcl::PrinterOptionsHelper::UIControlOptions aPrintRangeOpt
;
597 aPrintRangeOpt
.mbInternalOnly
= true;
598 aPrintRangeOpt
.maGroupHint
= "PrintRange" ;
599 AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt(u
"printrange"_ustr
,
600 mbImpress
? SdResId(STR_IMPRESS_PRINT_UI_SLIDE_RANGE
) : SdResId(STR_IMPRESS_PRINT_UI_PAGE_RANGE
),
605 // check if there is a selection of slides
606 OUString
aPageRange(OUString::number(mnCurPage
+ 1));
608 using sd::slidesorter::SlideSorterViewShell
;
609 SlideSorterViewShell
* const pSSViewSh(SlideSorterViewShell::GetSlideSorter(mrBase
));
612 const std::shared_ptr
<SlideSorterViewShell::PageSelection
> pPageSelection(pSSViewSh
->GetPageSelection());
613 if (bool(pPageSelection
) && pPageSelection
->size() > 1)
616 // TODO: this could be improved by writing ranges instead of consecutive page
617 // numbers if appropriate. Do we have a helper function for that somewhere?
619 for (auto pPage
: *pPageSelection
)
625 aBuf
.append(static_cast<sal_Int32
>(pPage
->GetPageNum() / 2 + 1));
627 aPageRange
= aBuf
.makeStringAndClear();
632 OUString aPrintRangeName( "PrintContent" );
633 aHelpIds.realloc( 1 );
634 aHelpIds[0] = ".HelpID:vcl:PrintDialog:PageContentType:ListBox";
635 AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt( "printpagesbox", OUString(),
636 aHelpIds, aPrintRangeName,
637 mbImpress ? CreateChoice( STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE ) ) :
638 CreateChoice( STR_DRAW_PRINT_UI_PAGE_RANGE_CHOICE, SAL_N_ELEMENTS(STR_DRAW_PRINT_UI_PAGE_RANGE_CHOICE ) ),
641 OUString
aPrintRangeName( u
"PrintContent"_ustr
);
642 aHelpIds
= { u
".HelpID:vcl:PrintDialog:PrintContent:RadioButton:0"_ustr
,
643 u
".HelpID:vcl:PrintDialog:PrintContent:RadioButton:1"_ustr
,
644 u
".HelpID:vcl:PrintDialog:PrintContent:RadioButton:2"_ustr
};
645 aWidgetIds
= { u
"rbAllPages"_ustr
, u
"rbRangePages"_ustr
, u
"rbRangeSelection"_ustr
};
647 AddDialogControl( vcl::PrinterOptionsHelper::setChoiceRadiosControlOpt(aWidgetIds
, OUString(),
648 aHelpIds
, aPrintRangeName
,
649 mbImpress
? CreateChoice(STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE
, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE
)) :
650 CreateChoice(STR_DRAW_PRINT_UI_PAGE_RANGE_CHOICE
, SAL_N_ELEMENTS(STR_DRAW_PRINT_UI_PAGE_RANGE_CHOICE
)),
653 // create an Edit dependent on "Pages" selected
654 vcl::PrinterOptionsHelper::UIControlOptions
aPageRangeOpt( aPrintRangeName
, 1, true );
655 AddDialogControl(vcl::PrinterOptionsHelper::setEditControlOpt(u
"pagerange"_ustr
, u
""_ustr
,
656 u
".HelpID:vcl:PrintDialog:PageRange:Edit"_ustr
, u
"PageRange"_ustr
,
657 aPageRange
, aPageRangeOpt
));
658 vcl::PrinterOptionsHelper::UIControlOptions
aEvenOddOpt(aPrintRangeName
, -1, true);
659 AddDialogControl(vcl::PrinterOptionsHelper::setChoiceListControlOpt(u
"evenoddbox"_ustr
, u
""_ustr
,
660 uno::Sequence
<OUString
>(), u
"EvenOdd"_ustr
, uno::Sequence
<OUString
>(),
661 0, uno::Sequence
<sal_Bool
>(), aEvenOddOpt
));
664 void AddDialogControl( const Any
& i_rCtrl
)
666 beans::PropertyValue aVal
;
667 aVal
.Value
= i_rCtrl
;
668 maProperties
.push_back( aVal
);
671 static Sequence
<OUString
> CreateChoice(const TranslateId
* pResourceId
, size_t nCount
)
673 Sequence
<OUString
> aChoices (nCount
);
674 std::transform(pResourceId
, pResourceId
+ nCount
, aChoices
.getArray(),
675 [](const auto& id
) { return SdResId(id
); });
679 Sequence
<OUString
> GetSlidesPerPageSequence()
681 const Sequence
<OUString
> aChoice (
682 CreateChoice(STR_IMPRESS_PRINT_UI_SLIDESPERPAGE_CHOICES
, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_SLIDESPERPAGE_CHOICES
)));
683 maSlidesPerPage
.clear();
684 maSlidesPerPage
.push_back(0); // first is using the default
685 std::transform(std::next(aChoice
.begin()), aChoice
.end(), std::back_inserter(maSlidesPerPage
),
686 [](const OUString
& rChoice
) -> sal_Int32
{ return rChoice
.toInt32(); });
691 /** The Prepare... methods of the DocumentRenderer::Implementation class
692 create a set of PrinterPage objects that contain all necessary
693 information to do the actual printing. There is one PrinterPage
694 object per printed page. Derived classes implement the actual, mode
697 This and all derived classes support the asynchronous printing
698 process by not storing pointers to any data with lifetime shorter
699 than the PrinterPage objects, i.e. slides, shapes, (one of) the
700 outliner (of the document).
706 const PageKind ePageKind
,
707 const MapMode
& rMapMode
,
708 const bool bPrintMarkedOnly
,
709 OUString sPageString
,
710 const Point
& rPageStringOffset
,
711 const DrawModeFlags nDrawMode
,
712 const Orientation eOrientation
,
713 const sal_uInt16 nPaperTray
)
714 : mePageKind(ePageKind
),
716 mbPrintMarkedOnly(bPrintMarkedOnly
),
717 msPageString(std::move(sPageString
)),
718 maPageStringOffset(rPageStringOffset
),
719 mnDrawMode(nDrawMode
),
720 meOrientation(eOrientation
),
721 mnPaperTray(nPaperTray
)
725 virtual ~PrinterPage() {}
729 SdDrawDocument
& rDocument
,
730 ViewShell
& rViewShell
,
732 DrawView
& rPrintView
,
733 const SdrLayerIDSet
& rVisibleLayers
,
734 const SdrLayerIDSet
& rPrintableLayers
) const = 0;
736 DrawModeFlags
GetDrawMode() const { return mnDrawMode
; }
737 Orientation
GetOrientation() const { return meOrientation
; }
738 sal_uInt16
GetPaperTray() const { return mnPaperTray
; }
741 const PageKind mePageKind
;
743 const bool mbPrintMarkedOnly
;
744 const OUString msPageString
;
745 const Point maPageStringOffset
;
746 const DrawModeFlags mnDrawMode
;
747 const Orientation meOrientation
;
748 const sal_uInt16 mnPaperTray
;
751 /** The RegularPrinterPage is used for printing one regular slide (no
752 notes, handout, or outline) to one printer page.
754 class RegularPrinterPage
: public PrinterPage
758 const sal_uInt16 nPageIndex
,
759 const PageKind ePageKind
,
760 const MapMode
& rMapMode
,
761 const bool bPrintMarkedOnly
,
762 const OUString
& rsPageString
,
763 const Point
& rPageStringOffset
,
764 const DrawModeFlags nDrawMode
,
765 const Orientation eOrientation
,
766 const sal_uInt16 nPaperTray
)
767 : PrinterPage(ePageKind
, rMapMode
, bPrintMarkedOnly
, rsPageString
,
768 rPageStringOffset
, nDrawMode
, eOrientation
, nPaperTray
),
769 mnPageIndex(nPageIndex
)
775 SdDrawDocument
& rDocument
,
778 DrawView
& rPrintView
,
779 const SdrLayerIDSet
& rVisibleLayers
,
780 const SdrLayerIDSet
& rPrintableLayers
) const override
782 SdPage
* pPageToPrint
= rDocument
.GetSdPage(mnPageIndex
, mePageKind
);
783 rPrinter
.SetMapMode(maMap
);
799 const sal_uInt16 mnPageIndex
;
802 /** The NotesPrinterPage is used for printing notes pages onto one or more printer pages
804 class NotesPrinterPage
: public PrinterPage
808 const sal_uInt16 nPageIndex
,
809 const sal_Int32 nPageNumb
,
810 const sal_Int32 nPageCount
,
812 const PageKind ePageKind
,
813 const MapMode
& rMapMode
,
814 const bool bPrintMarkedOnly
,
815 const OUString
& rsPageString
,
816 const Point
& rPageStringOffset
,
817 const DrawModeFlags nDrawMode
,
818 const Orientation eOrientation
,
819 const sal_uInt16 nPaperTray
)
820 : PrinterPage(ePageKind
, rMapMode
, bPrintMarkedOnly
, rsPageString
, rPageStringOffset
,
821 nDrawMode
, eOrientation
, nPaperTray
),
822 mnPageIndex(nPageIndex
),
823 mnPageNumb(nPageNumb
),
824 mnPageCount(nPageCount
),
831 SdDrawDocument
& rDocument
,
834 DrawView
& rPrintView
,
835 const SdrLayerIDSet
& rVisibleLayers
,
836 const SdrLayerIDSet
& rPrintableLayers
) const override
838 SdPage
* pPageToPrint
= rDocument
.GetSdPage(mnPageIndex
, mePageKind
);
839 rPrinter
.SetMapMode(maMap
);
841 // Clone the current page to create an independent instance for modifications.
842 // This ensures that changes made to pNotesPage do not affect the original page.
843 rtl::Reference
<SdPage
> pNotesPage
844 = static_cast<SdPage
*>(pPageToPrint
->CloneSdrPage(rDocument
).get());
849 aPageSize
= pNotesPage
->GetSize();
850 lcl_AdjustPageSize(aPageSize
, rPrinter
.GetPrintPageSize());
853 aPageSize
= rPrinter
.GetPrintPageSize();
855 // Adjusts the objects on the notes page to fit the new page size.
856 ::tools::Rectangle
aNewBorderRect(-1, -1, -1, -1);
857 pNotesPage
->ScaleObjects(aPageSize
, aNewBorderRect
, true);
859 SdrObject
* pNotesObj
= pNotesPage
->GetPresObj(PresObjKind::Notes
);
862 // new page(s) margins
863 sal_Int32 nLeft
= aPageSize
.Width() * 0.1;
864 sal_Int32 nRight
= nLeft
;
865 sal_Int32 nTop
= aPageSize
.Height() * 0.075;
866 sal_Int32 nBottom
= nTop
;
868 Point aNotesPt
= pNotesObj
->GetRelativePos();
869 Size aNotesSize
= pNotesObj
->GetLogicRect().GetSize();
871 Outliner
* pOut
= rDocument
.GetInternalOutliner();
872 const OutlinerMode
nSaveOutlMode(pOut
->GetOutlinerMode());
873 const bool bSavedUpdateMode(pOut
->IsUpdateLayout());
874 pOut
->SetPaperSize(aNotesSize
);
875 pOut
->SetUpdateLayout(true);
877 pOut
->SetText(*pNotesObj
->GetOutlinerParaObject());
879 bool bAutoGrow
= pNotesObj
->GetMergedItem(SDRATTR_TEXT_AUTOGROWHEIGHT
).GetValue();
881 // If AutoGrowHeight property is enabled and the notes page has a lower border,
882 // use the lower border but if there is no lower border, use the bottom margin
883 // to determine the first page break position.
884 // If AutoGrow is not enabled, the notes object defines the first page break.
885 ::tools::Long nNotesPageBottom
886 = bAutoGrow
? (pNotesPage
->GetLowerBorder() != 0)
887 ? aPageSize
.Height() - pNotesPage
->GetLowerBorder()
888 : aPageSize
.Height() - nBottom
889 : aNotesPt
.Y() + aNotesSize
.Height();
892 sal_Int32 nTextHeight
= aNotesPt
.Y() + pOut
->GetTextHeight();
893 if (bAutoGrow
&& (nTextHeight
> nNotesPageBottom
))
895 pNotesObj
->SetMergedItem(SdrOnOffItem(SDRATTR_TEXT_AUTOGROWHEIGHT
, false));
897 ::tools::Long nObjW
= aNotesSize
.Width();
898 ::tools::Long nObjH
= aPageSize
.Height() - aNotesPt
.Y() - nBottom
;
900 pNotesObj
->SetLogicRect(::tools::Rectangle(aNotesPt
, Size(nObjW
, nObjH
)));
902 SdrTextFitToSizeTypeItem eFitToSize
= drawing::TextFitToSizeType_AUTOFIT
;
903 pNotesObj
->SetMergedItem(eFitToSize
);
905 else // original size
908 sal_Int32 nPrevLineLen
= 0;
909 sal_Int32 nPrevParaIdx
= 0;
910 sal_uInt16 nActualPageNumb
= 1;
911 sal_uInt16 nPrevParaLowerSpace
= 0;
912 ::tools::Long nCurrentPosY
= aNotesPt
.Y();
913 sal_Int32 nParaCount
= pOut
->GetParagraphCount();
914 std::vector
<std::pair
<sal_Int32
, sal_Int32
>> aPageBreaks
;
916 for (sal_Int32 i
= 0; i
< nParaCount
&& !bExit
; ++i
)
918 sal_Int32 nActualLineLen
= 0;
919 sal_Int32 nLineCount
= pOut
->GetLineCount(i
);
921 sal_uInt16 nLowerSpace
= 0;
922 sal_uInt16 nUpperSpace
= nPrevParaLowerSpace
;
923 const SfxItemSet
* pItemSet
= &pOut
->GetParaAttribs(i
);
924 if(pItemSet
->HasItem(EE_PARA_ULSPACE
))
926 nLowerSpace
= pItemSet
->Get(EE_PARA_ULSPACE
).GetLower();
927 nUpperSpace
= (i
!= 0) ? pItemSet
->Get(EE_PARA_ULSPACE
).GetUpper() : 0;
928 if (nPrevParaLowerSpace
> nUpperSpace
)
929 nUpperSpace
= nPrevParaLowerSpace
;
932 for (sal_Int32 j
= 0; j
< nLineCount
; ++j
)
934 nActualLineLen
+= pOut
->GetLineLen(i
, j
);
935 sal_Int32 nLineHeight
= pOut
->GetLineHeight(i
, j
);
937 if (nUpperSpace
!= 0 && (i
> 0) && (j
== 0))
938 nLineHeight
+= nUpperSpace
;
940 sal_Int32 nNextPosY
= nCurrentPosY
+ nLineHeight
;
942 if (nNextPosY
> nNotesPageBottom
)
944 // If the current or the next page matches the print page
945 // calculate and add a page break, since we only want to add
946 // a page break if the page is relevant.
947 if (mnPageNumb
== nActualPageNumb
948 || mnPageNumb
== nActualPageNumb
+ 1)
950 if (!aPageBreaks
.empty())
952 // determine the page break at the bottom of the page
953 // for pages that have both a previous and a following page
954 aPageBreaks
.emplace_back(
955 nPrevParaIdx
- aPageBreaks
[0].first
, nPrevLineLen
);
959 if (mnPageNumb
== 1 || (nLineCount
> 1 && j
!= 0))
961 // first page or multi-line paragraphs
962 aPageBreaks
.emplace_back(nPrevParaIdx
, nPrevLineLen
);
965 { // single-line paragraphs
966 aPageBreaks
.emplace_back(nPrevParaIdx
+ 1, 0);
970 if (mnPageNumb
== nActualPageNumb
|| mnPageNumb
== mnPageCount
)
978 nLineHeight
-= nUpperSpace
;
980 nNotesPageBottom
= aPageSize
.Height() - nBottom
;
986 nPrevLineLen
= nActualLineLen
;
987 nCurrentPosY
+= nLineHeight
;
989 nPrevParaLowerSpace
= nLowerSpace
;
992 if (!aPageBreaks
.empty())
997 aE
.start
.nPara
= aPageBreaks
[0].first
;
998 aE
.start
.nIndex
= aPageBreaks
[0].second
;
999 aE
.end
.nPara
= pOut
->GetParagraphCount() - 1;
1000 aE
.end
.nIndex
= pOut
->GetText(pOut
->GetParagraph(aE
.end
.nPara
)).getLength();
1001 pOut
->QuickDelete(aE
);
1005 sal_Int16 nDepth
= pOut
->GetDepth(aPageBreaks
[0].first
);
1006 SfxItemSet aItemSet
= pOut
->GetParaAttribs(aPageBreaks
[0].first
);
1009 aE
.start
.nIndex
= 0;
1010 aE
.end
.nPara
= aPageBreaks
[0].first
;
1011 aE
.end
.nIndex
= aPageBreaks
[0].second
;
1012 pOut
->QuickDelete(aE
);
1014 Paragraph
* pFirstPara
= pOut
->GetParagraph(0);
1015 pOut
->SetDepth(pFirstPara
, nDepth
);
1016 pOut
->SetParaAttribs(0, aItemSet
);
1018 if (aPageBreaks
.size() > 1)
1020 aE
.start
.nPara
= aPageBreaks
[1].first
;
1021 aE
.start
.nIndex
= aPageBreaks
[1].second
;
1022 aE
.end
.nPara
= pOut
->GetParagraphCount() - 1;
1023 aE
.end
.nIndex
= pOut
->GetText(pOut
->GetParagraph(aE
.end
.nPara
)).getLength();
1024 pOut
->QuickDelete(aE
);
1028 pNotesObj
->SetOutlinerParaObject(pOut
->CreateParaObject());
1031 if (mnPageNumb
!= 1) // new page(s)
1033 SdrObjListIter
aShapeIter(pNotesPage
.get());
1034 while (aShapeIter
.IsMore())
1036 SdrObject
* pObj
= aShapeIter
.Next();
1037 if (pObj
&& pObj
->GetObjIdentifier() != SdrObjKind::Text
)
1038 pNotesPage
->RemoveObject(pObj
->GetOrdNum());
1041 aNotesPt
.setX(nLeft
);
1042 aNotesPt
.setY(nTop
);
1043 ::tools::Long nWidth
= aPageSize
.Width() - nLeft
- nRight
;
1044 aObjSize
= Size(nWidth
, pOut
->GetTextHeight());
1049 aObjSize
= aNotesSize
;
1051 aObjSize
= Size(aNotesSize
.Width(), pOut
->GetTextHeight());
1053 pNotesObj
->SetLogicRect(::tools::Rectangle(aNotesPt
, aObjSize
));
1056 pOut
->SetUpdateLayout(bSavedUpdateMode
);
1057 pOut
->Init(nSaveOutlMode
);
1059 pNotesPage
->SetSize(aPageSize
);
1072 maPageStringOffset
);
1076 const sal_uInt16 mnPageIndex
;
1077 const sal_Int32 mnPageNumb
;
1078 const sal_Int32 mnPageCount
;
1079 const bool mbScaled
;
1082 /** Print one slide multiple times on a printer page so that the whole
1083 printer page is covered.
1085 class TiledPrinterPage
: public PrinterPage
1089 const sal_uInt16 nPageIndex
,
1090 const PageKind ePageKind
,
1091 const bool bPrintMarkedOnly
,
1092 const OUString
& rsPageString
,
1093 const Point
& rPageStringOffset
,
1094 const DrawModeFlags nDrawMode
,
1095 const Orientation eOrientation
,
1096 const sal_uInt16 nPaperTray
)
1097 : PrinterPage(ePageKind
, MapMode(), bPrintMarkedOnly
, rsPageString
,
1098 rPageStringOffset
, nDrawMode
, eOrientation
, nPaperTray
),
1099 mnPageIndex(nPageIndex
)
1103 virtual void Print (
1105 SdDrawDocument
& rDocument
,
1108 DrawView
& rPrintView
,
1109 const SdrLayerIDSet
& rVisibleLayers
,
1110 const SdrLayerIDSet
& rPrintableLayers
) const override
1112 SdPage
* pPageToPrint
= rDocument
.GetSdPage(mnPageIndex
, mePageKind
);
1113 if (pPageToPrint
==nullptr)
1115 MapMode
aMap (rPrinter
.GetMapMode());
1117 const Size
aPageSize (pPageToPrint
->GetSize());
1118 const Size
aPrintSize (rPrinter
.GetOutputSize());
1120 const sal_Int32
nPageWidth (aPageSize
.Width() + mnGap
1121 - pPageToPrint
->GetLeftBorder() - pPageToPrint
->GetRightBorder());
1122 const sal_Int32
nPageHeight (aPageSize
.Height() + mnGap
1123 - pPageToPrint
->GetUpperBorder() - pPageToPrint
->GetLowerBorder());
1124 if (nPageWidth
<=0 || nPageHeight
<=0)
1127 // Print at least two rows and columns. More if the document
1128 // page fits completely onto the printer page.
1129 const sal_Int32
nColumnCount (std::max(sal_Int32(2),
1130 sal_Int32(aPrintSize
.Width() / nPageWidth
)));
1131 const sal_Int32
nRowCount (std::max(sal_Int32(2),
1132 sal_Int32(aPrintSize
.Height() / nPageHeight
)));
1133 for (sal_Int32 nRow
=0; nRow
<nRowCount
; ++nRow
)
1134 for (sal_Int32 nColumn
=0; nColumn
<nColumnCount
; ++nColumn
)
1136 aMap
.SetOrigin(Point(nColumn
*nPageWidth
,nRow
*nPageHeight
));
1137 rPrinter
.SetMapMode(aMap
);
1151 maPageStringOffset
);
1155 const sal_uInt16 mnPageIndex
;
1156 static const sal_Int32 mnGap
= 500;
1159 /** Print two slides to one printer page so that the resulting pages
1162 class BookletPrinterPage
: public PrinterPage
1165 BookletPrinterPage (
1166 const sal_uInt16 nFirstPageIndex
,
1167 const sal_uInt16 nSecondPageIndex
,
1168 const Point
& rFirstOffset
,
1169 const Point
& rSecondOffset
,
1170 const PageKind ePageKind
,
1171 const MapMode
& rMapMode
,
1172 const bool bPrintMarkedOnly
,
1173 const DrawModeFlags nDrawMode
,
1174 const Orientation eOrientation
,
1175 const sal_uInt16 nPaperTray
)
1176 : PrinterPage(ePageKind
, rMapMode
, bPrintMarkedOnly
, u
""_ustr
,
1177 Point(), nDrawMode
, eOrientation
, nPaperTray
),
1178 mnFirstPageIndex(nFirstPageIndex
),
1179 mnSecondPageIndex(nSecondPageIndex
),
1180 maFirstOffset(rFirstOffset
),
1181 maSecondOffset(rSecondOffset
)
1185 virtual void Print (
1187 SdDrawDocument
& rDocument
,
1190 DrawView
& rPrintView
,
1191 const SdrLayerIDSet
& rVisibleLayers
,
1192 const SdrLayerIDSet
& rPrintableLayers
) const override
1194 MapMode
aMap (maMap
);
1195 SdPage
* pPageToPrint
= rDocument
.GetSdPage(mnFirstPageIndex
, mePageKind
);
1198 aMap
.SetOrigin(maFirstOffset
);
1199 rPrinter
.SetMapMode(aMap
);
1210 pPageToPrint
= rDocument
.GetSdPage(mnSecondPageIndex
, mePageKind
);
1214 aMap
.SetOrigin(maSecondOffset
);
1215 rPrinter
.SetMapMode(aMap
);
1227 const sal_uInt16 mnFirstPageIndex
;
1228 const sal_uInt16 mnSecondPageIndex
;
1229 const Point maFirstOffset
;
1230 const Point maSecondOffset
;
1233 /** One handout page displays one to nine slides.
1235 class HandoutPrinterPage
: public PrinterPage
1238 HandoutPrinterPage (
1239 const sal_uInt16 nHandoutPageIndex
,
1240 std::vector
<sal_uInt16
>&& rPageIndices
,
1241 const MapMode
& rMapMode
,
1242 const OUString
& rsPageString
,
1243 const Point
& rPageStringOffset
,
1244 const DrawModeFlags nDrawMode
,
1245 const Orientation eOrientation
,
1246 const sal_uInt16 nPaperTray
)
1247 : PrinterPage(PageKind::Handout
, rMapMode
, false, rsPageString
,
1248 rPageStringOffset
, nDrawMode
, eOrientation
, nPaperTray
),
1249 mnHandoutPageIndex(nHandoutPageIndex
),
1250 maPageIndices(std::move(rPageIndices
))
1254 virtual void Print (
1256 SdDrawDocument
& rDocument
,
1257 ViewShell
& rViewShell
,
1259 DrawView
& rPrintView
,
1260 const SdrLayerIDSet
& rVisibleLayers
,
1261 const SdrLayerIDSet
& rPrintableLayers
) const override
1263 SdPage
& rHandoutPage (*rDocument
.GetSdPage(0, PageKind::Handout
));
1265 Size
aPageSize(rHandoutPage
.GetSize());
1266 Size aPrintPageSize
= rPrinter
.GetPrintPageSize();
1268 if ((aPageSize
.Width() < aPageSize
.Height()
1269 && aPrintPageSize
.Width() > aPrintPageSize
.Height())
1270 || (aPageSize
.Width() > aPageSize
.Height()
1271 && aPrintPageSize
.Width() < aPrintPageSize
.Height()))
1273 ::tools::Long nTmp
= aPageSize
.Width();
1274 aPageSize
.setWidth(aPageSize
.Height());
1275 aPageSize
.setHeight(nTmp
);
1277 rHandoutPage
.SetSize(aPageSize
);
1280 Reference
< css::beans::XPropertySet
> xHandoutPage( rHandoutPage
.getUnoPage(), UNO_QUERY
);
1281 static constexpr OUString
sPageNumber( u
"Number"_ustr
);
1283 // Collect the page objects of the handout master.
1284 std::vector
<SdrPageObj
*> aHandoutPageObjects
;
1285 SdrObjListIter
aShapeIter (&rHandoutPage
);
1286 while (aShapeIter
.IsMore())
1288 SdrPageObj
* pPageObj
= dynamic_cast<SdrPageObj
*>(aShapeIter
.Next());
1290 aHandoutPageObjects
.push_back(pPageObj
);
1292 if (aHandoutPageObjects
.empty())
1295 // Connect page objects with pages.
1296 std::vector
<SdrPageObj
*>::iterator
aPageObjIter (aHandoutPageObjects
.begin());
1297 for (std::vector
<sal_uInt16
>::const_iterator
1298 iPageIndex(maPageIndices
.begin()),
1299 iEnd(maPageIndices
.end());
1300 iPageIndex
!=iEnd
&& aPageObjIter
!=aHandoutPageObjects
.end();
1303 // Check if the page still exists.
1304 if (*iPageIndex
>= rDocument
.GetSdPageCount(PageKind::Standard
))
1307 SdrPageObj
* pPageObj
= *aPageObjIter
++;
1308 pPageObj
->SetReferencedPage(rDocument
.GetSdPage(*iPageIndex
, PageKind::Standard
));
1311 // if there are more page objects than pages left, set the rest to invisible
1312 int nHangoverCount
= 0;
1313 while (aPageObjIter
!= aHandoutPageObjects
.end())
1315 (*aPageObjIter
++)->SetReferencedPage(nullptr);
1319 // Hide outlines for objects that have pages attached.
1320 if (nHangoverCount
> 0)
1322 int nSkip
= aHandoutPageObjects
.size() - nHangoverCount
;
1324 while (aShapeIter
.IsMore())
1326 SdrPathObj
* pPathObj
= dynamic_cast<SdrPathObj
*>(aShapeIter
.Next());
1332 pPathObj
->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE
));
1337 if( xHandoutPage
.is() ) try
1339 xHandoutPage
->setPropertyValue( sPageNumber
, Any( static_cast<sal_Int16
>(mnHandoutPageIndex
) ) );
1344 rViewShell
.SetPrintedHandoutPageNum( mnHandoutPageIndex
+ 1 );
1346 rPrinter
.SetMapMode(maMap
);
1359 maPageStringOffset
);
1361 if( xHandoutPage
.is() ) try
1363 xHandoutPage
->setPropertyValue( sPageNumber
, Any( static_cast<sal_Int16
>(0) ) );
1368 rViewShell
.SetPrintedHandoutPageNum(1);
1370 // Restore outlines.
1371 if (nHangoverCount
> 0)
1374 while (aShapeIter
.IsMore())
1376 SdrPathObj
* pPathObj
= dynamic_cast<SdrPathObj
*>(aShapeIter
.Next());
1377 if (pPathObj
!= nullptr)
1378 pPathObj
->SetMergedItem(XLineStyleItem(drawing::LineStyle_SOLID
));
1385 const sal_uInt16 mnHandoutPageIndex
;
1386 const std::vector
<sal_uInt16
> maPageIndices
;
1389 /** The outline information (title, subtitle, outline objects) of the
1390 document. There is no fixed mapping of slides to printer pages.
1392 class OutlinerPrinterPage
: public PrinterPage
1395 OutlinerPrinterPage (
1396 std::optional
<OutlinerParaObject
> pParaObject
,
1397 const MapMode
& rMapMode
,
1398 const OUString
& rsPageString
,
1399 const Point
& rPageStringOffset
,
1400 const DrawModeFlags nDrawMode
,
1401 const Orientation eOrientation
,
1402 const sal_uInt16 nPaperTray
)
1403 : PrinterPage(PageKind::Handout
, rMapMode
, false, rsPageString
,
1404 rPageStringOffset
, nDrawMode
, eOrientation
, nPaperTray
),
1405 mpParaObject(std::move(pParaObject
))
1409 virtual void Print (
1411 SdDrawDocument
& rDocument
,
1415 const SdrLayerIDSet
&,
1416 const SdrLayerIDSet
&) const override
1418 // Set up the printer.
1419 rPrinter
.SetMapMode(maMap
);
1421 // Get and set up the outliner.
1422 const ::tools::Rectangle
aOutRect (rPrinter
.GetPageOffset(), rPrinter
.GetOutputSize());
1423 Outliner
* pOutliner
= rDocument
.GetInternalOutliner();
1424 const OutlinerMode
nSavedOutlMode (pOutliner
->GetOutlinerMode());
1425 const bool bSavedUpdateMode (pOutliner
->IsUpdateLayout());
1426 const Size
aSavedPaperSize (pOutliner
->GetPaperSize());
1428 pOutliner
->Init(OutlinerMode::OutlineView
);
1429 pOutliner
->SetPaperSize(aOutRect
.GetSize());
1430 pOutliner
->SetUpdateLayout(true);
1432 pOutliner
->SetText(*mpParaObject
);
1434 pOutliner
->Draw(rPrinter
, aOutRect
);
1439 maPageStringOffset
);
1441 // Restore outliner and printer.
1443 pOutliner
->SetUpdateLayout(bSavedUpdateMode
);
1444 pOutliner
->SetPaperSize(aSavedPaperSize
);
1445 pOutliner
->Init(nSavedOutlMode
);
1449 std::optional
<OutlinerParaObject
> mpParaObject
;
1453 //===== DocumentRenderer::Implementation ======================================
1455 class DocumentRenderer::Implementation
1456 : public SfxListener
,
1457 public vcl::PrinterOptionsHelper
1460 explicit Implementation (ViewShellBase
& rBase
)
1461 : mxObjectShell(rBase
.GetDocShell())
1463 , mbIsDisposed(false)
1464 , mpPrinter(nullptr)
1465 , mbHasOrientationWarningBeenShown(false)
1467 DialogCreator
aCreator( mrBase
, mrBase
.GetDocShell()->GetDocumentType() == DocumentType::Impress
, GetCurrentPageIndex() );
1468 m_aUIProperties
= aCreator
.GetDialogControls();
1469 maSlidesPerPage
= aCreator
.GetSlidesPerPage();
1471 StartListening(mrBase
);
1474 virtual ~Implementation() override
1476 EndListening(mrBase
);
1479 virtual void Notify (SfxBroadcaster
& rBroadcaster
, const SfxHint
& rHint
) override
1481 if (&rBroadcaster
!= &static_cast<SfxBroadcaster
&>(mrBase
))
1484 if (rHint
.GetId() == SfxHintId::Dying
)
1486 mbIsDisposed
= true;
1490 /** Process the sequence of properties given to one of the XRenderable
1493 void ProcessProperties (const css::uno::Sequence
<css::beans::PropertyValue
>& rOptions
)
1495 OSL_ASSERT(!mbIsDisposed
);
1499 bool bIsValueChanged
= processProperties( rOptions
);
1500 bool bIsPaperChanged
= false;
1502 // The RenderDevice property is handled specially: its value is
1503 // stored in mpPrinter instead of being retrieved on demand.
1504 Any
aDev( getValue( u
"RenderDevice"_ustr
) );
1505 Reference
<awt::XDevice
> xRenderDevice
;
1507 if (aDev
>>= xRenderDevice
)
1509 VCLXDevice
* pDevice
= dynamic_cast<VCLXDevice
*>(xRenderDevice
.get());
1510 VclPtr
< OutputDevice
> pOut
= pDevice
? pDevice
->GetOutputDevice()
1511 : VclPtr
< OutputDevice
>();
1512 mpPrinter
= dynamic_cast<Printer
*>(pOut
.get());
1513 Size aPageSizePixel
= mpPrinter
? mpPrinter
->GetPaperSizePixel() : Size();
1514 Size aPrintPageSize
= mpPrinter
? mpPrinter
->GetPrintPageSize() : Size();
1516 lcl_AdjustPageSize(aPageSizePixel
, aPrintPageSize
);
1518 if (aPageSizePixel
!= maPrinterPageSizePixel
)
1520 bIsPaperChanged
= true;
1521 maPrinterPageSizePixel
= aPageSizePixel
;
1525 if (bIsValueChanged
&& ! mpOptions
)
1526 mpOptions
.reset(new PrintOptions(*this, std::vector(maSlidesPerPage
)));
1527 if( bIsValueChanged
|| bIsPaperChanged
)
1531 /** Return the number of pages that are to be printed.
1533 sal_Int32
GetPrintPageCount() const
1535 OSL_ASSERT(!mbIsDisposed
);
1539 return maPrinterPages
.size();
1542 /** Return a sequence of properties that can be returned by the
1543 XRenderable::getRenderer() method.
1545 css::uno::Sequence
<css::beans::PropertyValue
> GetProperties () const
1547 css::uno::Sequence
<css::beans::PropertyValue
> aProperties
{
1548 comphelper::makePropertyValue(u
"ExtraPrintUIOptions"_ustr
,
1549 comphelper::containerToSequence(m_aUIProperties
)),
1550 comphelper::makePropertyValue(u
"PageSize"_ustr
, maPrintSize
),
1551 // FIXME: is this always true ?
1552 comphelper::makePropertyValue(u
"PageIncludesNonprintableArea"_ustr
, true)
1558 /** Print one of the prepared pages.
1560 void PrintPage (const sal_Int32 nIndex
)
1562 OSL_ASSERT(!mbIsDisposed
);
1566 Printer
& rPrinter (*mpPrinter
);
1568 std::shared_ptr
<ViewShell
> pViewShell (mrBase
.GetMainViewShell());
1572 SdDrawDocument
* pDocument
= pViewShell
->GetDoc();
1573 assert(pDocument
!=nullptr);
1575 std::shared_ptr
<DrawViewShell
> pDrawViewShell(
1576 std::dynamic_pointer_cast
<DrawViewShell
>(pViewShell
));
1579 mpPrintView
.reset(new DrawView(mrBase
.GetDocShell(), &rPrinter
, nullptr));
1581 if (nIndex
<0 || sal::static_int_cast
<sal_uInt32
>(nIndex
)>=maPrinterPages
.size())
1584 const std::shared_ptr
<PrinterPage
> pPage (maPrinterPages
[nIndex
]);
1589 const Orientation
eSavedOrientation (rPrinter
.GetOrientation());
1590 const DrawModeFlags
nSavedDrawMode (rPrinter
.GetDrawMode());
1591 const MapMode
aSavedMapMode (rPrinter
.GetMapMode());
1592 const sal_uInt16
nSavedPaperBin (rPrinter
.GetPaperBin());
1594 // Set page orientation.
1595 if ( ! rPrinter
.SetOrientation(pPage
->GetOrientation()))
1597 if ( ! mbHasOrientationWarningBeenShown
1598 && mpOptions
->IsWarningOrientation())
1600 mbHasOrientationWarningBeenShown
= true;
1601 // Show warning that the orientation could not be set.
1602 std::unique_ptr
<weld::MessageDialog
> xWarn(Application::CreateMessageDialog(
1603 pViewShell
->GetFrameWeld(), VclMessageType::Warning
, VclButtonsType::OkCancel
,
1604 SdResId(STR_WARN_PRINTFORMAT_FAILURE
)));
1605 xWarn
->set_default_response(RET_CANCEL
);
1606 if (xWarn
->run() != RET_OK
)
1611 // Set the draw mode.
1612 rPrinter
.SetDrawMode(pPage
->GetDrawMode());
1615 rPrinter
.SetPaperBin(pPage
->GetPaperTray());
1617 // Print the actual page.
1622 pDrawViewShell
? pDrawViewShell
->GetView() : nullptr,
1624 pViewShell
->GetFrameView()->GetVisibleLayers(),
1625 pViewShell
->GetFrameView()->GetPrintableLayers());
1627 rPrinter
.SetOrientation(eSavedOrientation
);
1628 rPrinter
.SetDrawMode(nSavedDrawMode
);
1629 rPrinter
.SetMapMode(aSavedMapMode
);
1630 rPrinter
.SetPaperBin(nSavedPaperBin
);
1634 // rhbz#657394: keep the document alive: prevents crash when
1635 SfxObjectShellRef mxObjectShell
; // destroying mpPrintView
1636 ViewShellBase
& mrBase
;
1638 VclPtr
<Printer
> mpPrinter
;
1639 Size maPrinterPageSizePixel
;
1640 std::unique_ptr
<PrintOptions
> mpOptions
;
1641 std::vector
< std::shared_ptr
< ::sd::PrinterPage
> > maPrinterPages
;
1642 std::unique_ptr
<DrawView
> mpPrintView
;
1643 bool mbHasOrientationWarningBeenShown
;
1644 std::vector
<sal_Int32
> maSlidesPerPage
;
1645 awt::Size maPrintSize
;
1647 sal_Int32
GetCurrentPageIndex() const
1649 const ViewShell
*pShell
= mrBase
.GetMainViewShell().get();
1650 const SdPage
*pCurrentPage
= pShell
? pShell
->getCurrentPage() : nullptr;
1651 return pCurrentPage
? (pCurrentPage
->GetPageNum()-1)/2 : -1;
1654 /** Determine and set the paper orientation.
1656 void SetupPaperOrientation (
1657 const PageKind ePageKind
,
1660 SdDrawDocument
* pDocument
= mrBase
.GetMainViewShell()->GetDoc();
1661 rInfo
.meOrientation
= Orientation::Portrait
;
1663 if( ! mpOptions
->IsBooklet())
1665 rInfo
.meOrientation
= pDocument
->GetSdPage(0, ePageKind
)->GetOrientation();
1667 else if (rInfo
.maPageSize
.Width() < rInfo
.maPageSize
.Height())
1668 rInfo
.meOrientation
= Orientation::Landscape
;
1670 // Draw and Notes should usually abide by their specified paper size
1672 if (!mpOptions
->IsPrinterPreferred(pDocument
->GetDocumentType()))
1674 aPaperSize
.setWidth(rInfo
.maPageSize
.Width());
1675 aPaperSize
.setHeight(rInfo
.maPageSize
.Height());
1679 aPaperSize
.setWidth(rInfo
.mpPrinter
->GetPaperSize().Width());
1680 aPaperSize
.setHeight(rInfo
.mpPrinter
->GetPaperSize().Height());
1682 if (!mpOptions
->IsBooklet())
1683 lcl_AdjustPageSize(aPaperSize
, rInfo
.mpPrinter
->GetPrintPageSize());
1686 maPrintSize
= awt::Size(aPaperSize
.Width(), aPaperSize
.Height());
1688 if (mpOptions
->IsPrinterPreferred(pDocument
->GetDocumentType())
1689 && ePageKind
== PageKind::Standard
&& !mpOptions
->IsBooklet())
1691 if( (rInfo
.meOrientation
== Orientation::Landscape
&&
1692 (aPaperSize
.Width() < aPaperSize
.Height()))
1694 (rInfo
.meOrientation
== Orientation::Portrait
&&
1695 (aPaperSize
.Width() > aPaperSize
.Height()))
1698 maPrintSize
= awt::Size(aPaperSize
.Height(), aPaperSize
.Width());
1703 /** Top most method for preparing printer pages. In this and the other
1704 Prepare... methods the various special cases are detected and
1706 For every page that is to be printed (that may contain several
1707 slides) one PrinterPage object is created and inserted into
1712 mpPrintView
.reset();
1713 maPrinterPages
.clear();
1714 mbHasOrientationWarningBeenShown
= false;
1716 ViewShell
* pShell
= mrBase
.GetMainViewShell().get();
1718 PrintInfo
aInfo (mpPrinter
, mpOptions
->IsPrintMarkedOnly());
1720 if (aInfo
.mpPrinter
==nullptr || pShell
==nullptr)
1723 MapMode
aMap (aInfo
.mpPrinter
->GetMapMode());
1724 aMap
.SetMapUnit(MapUnit::Map100thMM
);
1726 mpPrinter
->SetMapMode(aMap
);
1728 ::Outliner
& rOutliner
= mrBase
.GetDocument()->GetDrawOutliner();
1729 const EEControlBits
nSavedControlWord (rOutliner
.GetControlWord());
1730 EEControlBits nCntrl
= nSavedControlWord
;
1731 nCntrl
&= ~EEControlBits::MARKFIELDS
;
1732 nCntrl
&= ~EEControlBits::ONLINESPELLING
;
1733 rOutliner
.SetControlWord( nCntrl
);
1735 // When in outline view then apply all pending changes to the model.
1736 if( auto pOutlineViewShell
= dynamic_cast< OutlineViewShell
*>( pShell
) )
1737 pOutlineViewShell
->PrepareClose (false);
1739 // Collect some frequently used data.
1740 if (mpOptions
->IsDate())
1742 aInfo
.msTimeDate
+= GetSdrGlobalData().GetLocaleData().getDate( Date( Date::SYSTEM
) );
1743 aInfo
.msTimeDate
+= " ";
1746 if (mpOptions
->IsTime())
1747 aInfo
.msTimeDate
+= GetSdrGlobalData().GetLocaleData().getTime( ::tools::Time( ::tools::Time::SYSTEM
), false );
1749 // Draw and Notes should usually use specified paper size when printing
1750 if (!mpOptions
->IsPrinterPreferred(mrBase
.GetDocShell()->GetDocumentType()))
1752 aInfo
.maPrintSize
= mrBase
.GetDocument()->GetSdPage(0, PageKind::Standard
)->GetSize();
1753 maPrintSize
= awt::Size(aInfo
.maPrintSize
.Width(),
1754 aInfo
.maPrintSize
.Height());
1758 aInfo
.maPrintSize
= aInfo
.mpPrinter
->GetOutputSize();
1759 maPrintSize
= awt::Size(
1760 aInfo
.mpPrinter
->GetPaperSize().Width(),
1761 aInfo
.mpPrinter
->GetPaperSize().Height());
1764 switch (mpOptions
->GetOutputQuality())
1766 case 1: // Grayscale
1767 aInfo
.mnDrawMode
= DrawModeFlags::GrayLine
| DrawModeFlags::GrayFill
1768 | DrawModeFlags::GrayText
| DrawModeFlags::GrayBitmap
1769 | DrawModeFlags::GrayGradient
;
1772 case 2: // Black & White
1773 aInfo
.mnDrawMode
= DrawModeFlags::BlackLine
| DrawModeFlags::WhiteFill
1774 | DrawModeFlags::BlackText
| DrawModeFlags::GrayBitmap
1775 | DrawModeFlags::WhiteGradient
;
1779 aInfo
.mnDrawMode
= DrawModeFlags::Default
;
1782 if (mpOptions
->IsDraw())
1783 PrepareStdOrNotes(PageKind::Standard
, aInfo
);
1784 if (mpOptions
->IsNotes())
1785 PrepareStdOrNotes(PageKind::Notes
, aInfo
);
1786 if (mpOptions
->IsHandout())
1788 InitHandoutTemplate();
1789 PrepareHandout(aInfo
);
1791 if (mpOptions
->IsOutline())
1792 PrepareOutline(aInfo
);
1794 rOutliner
.SetControlWord(nSavedControlWord
);
1797 /** Create the page objects of the handout template. When the actual
1798 printing takes place then the page objects are assigned different
1799 sets of slides for each printed page (see HandoutPrinterPage::Print).
1801 void InitHandoutTemplate()
1803 const sal_Int32
nSlidesPerHandout (mpOptions
->GetHandoutPageCount());
1804 const bool bHandoutHorizontal (mpOptions
->IsHandoutHorizontal());
1806 AutoLayout eLayout
= AUTOLAYOUT_HANDOUT6
;
1807 switch (nSlidesPerHandout
)
1809 case 0: eLayout
= AUTOLAYOUT_NONE
; break; // AUTOLAYOUT_HANDOUT1; break;
1810 case 1: eLayout
= AUTOLAYOUT_HANDOUT1
; break;
1811 case 2: eLayout
= AUTOLAYOUT_HANDOUT2
; break;
1812 case 3: eLayout
= AUTOLAYOUT_HANDOUT3
; break;
1813 case 4: eLayout
= AUTOLAYOUT_HANDOUT4
; break;
1815 case 6: eLayout
= AUTOLAYOUT_HANDOUT6
; break;
1816 case 9: eLayout
= AUTOLAYOUT_HANDOUT9
; break;
1819 if( !mrBase
.GetDocument() )
1822 SdDrawDocument
& rModel
= *mrBase
.GetDocument();
1824 // first, prepare handout page (not handout master)
1826 SdPage
* pHandout
= rModel
.GetSdPage(0, PageKind::Handout
);
1830 // delete all previous shapes from handout page
1831 while( pHandout
->GetObjCount() )
1832 pHandout
->NbcRemoveObject(0);
1834 const bool bDrawLines (eLayout
== AUTOLAYOUT_HANDOUT3
);
1836 Size aHandoutPageSize
= pHandout
->GetSize();
1837 lcl_AdjustPageSize(aHandoutPageSize
, mpPrinter
->GetPrintPageSize());
1838 Orientation eOrient
= aHandoutPageSize
.Width() > aHandoutPageSize
.Height()
1839 ? Orientation::Landscape
1840 : Orientation::Portrait
;
1842 std::vector
< ::tools::Rectangle
> aAreas
;
1843 SdPage::CalculateHandoutAreas( rModel
, eLayout
, bHandoutHorizontal
, aAreas
, eOrient
);
1845 std::vector
< ::tools::Rectangle
>::iterator
iter( aAreas
.begin() );
1846 while( iter
!= aAreas
.end() )
1848 pHandout
->NbcInsertObject(
1853 if( bDrawLines
&& (iter
!= aAreas
.end()) )
1855 ::tools::Rectangle
aRect( *iter
++ );
1857 basegfx::B2DPolygon aPoly
;
1858 aPoly
.insert(0, basegfx::B2DPoint( aRect
.Left(), aRect
.Top() ) );
1859 aPoly
.insert(1, basegfx::B2DPoint( aRect
.Right(), aRect
.Top() ) );
1861 basegfx::B2DHomMatrix aMatrix
;
1862 aMatrix
.translate( 0.0, static_cast< double >( aRect
.GetHeight() / 7 ) );
1864 basegfx::B2DPolyPolygon aPathPoly
;
1865 for( sal_uInt16 nLine
= 0; nLine
< 7; nLine
++ )
1867 aPoly
.transform( aMatrix
);
1868 aPathPoly
.append( aPoly
);
1871 rtl::Reference
<SdrPathObj
> pPathObj
= new SdrPathObj(
1873 SdrObjKind::PathLine
,
1874 std::move(aPathPoly
));
1875 pPathObj
->SetMergedItem(XLineStyleItem(drawing::LineStyle_SOLID
));
1876 pPathObj
->SetMergedItem(XLineColorItem(OUString(), COL_BLACK
));
1878 pHandout
->NbcInsertObject( pPathObj
.get() );
1883 /** Detect whether the specified slide is to be printed.
1885 When the slide is not to be printed then <NULL/> is returned.
1886 Otherwise a pointer to the slide is returned.
1888 SdPage
* GetFilteredPage (
1889 const sal_Int32 nPageIndex
,
1890 const PageKind ePageKind
) const
1892 OSL_ASSERT(mrBase
.GetDocument() != nullptr);
1893 OSL_ASSERT(nPageIndex
>=0);
1894 SdPage
* pPage
= mrBase
.GetDocument()->GetSdPage(
1895 sal::static_int_cast
<sal_uInt16
>(nPageIndex
),
1897 if (pPage
== nullptr)
1899 if ( ! pPage
->IsExcluded() || mpOptions
->IsPrintExcluded())
1905 /** Prepare the outline of the document for printing. There is no fixed
1906 number of slides whose outline data is put onto one printer page.
1907 If the current printer page has enough room for the outline of the
1908 current slide then that is added. Otherwise a new printer page is
1911 void PrepareOutline (PrintInfo
const & rInfo
)
1913 MapMode
aMap (rInfo
.maMap
);
1914 Point
aPageOfs (rInfo
.mpPrinter
->GetPageOffset() );
1915 aMap
.SetScaleX(Fraction(1,2));
1916 aMap
.SetScaleY(Fraction(1,2));
1917 mpPrinter
->SetMapMode(aMap
);
1919 ::tools::Rectangle
aOutRect(aPageOfs
, rInfo
.mpPrinter
->GetOutputSize());
1920 if( aOutRect
.GetWidth() > aOutRect
.GetHeight() )
1922 Size
aPaperSize( rInfo
.mpPrinter
->PixelToLogic( rInfo
.mpPrinter
->GetPaperSizePixel(), MapMode( MapUnit::Map100thMM
) ) );
1923 maPrintSize
.Width
= aPaperSize
.Height();
1924 maPrintSize
.Height
= aPaperSize
.Width();
1925 const auto nRotatedWidth
= aOutRect
.GetHeight();
1926 const auto nRotatedHeight
= aOutRect
.GetWidth();
1927 const auto nRotatedX
= aPageOfs
.Y();
1928 const auto nRotatedY
= aPageOfs
.X();
1929 aOutRect
= ::tools::Rectangle(Point( nRotatedX
, nRotatedY
),
1930 Size(nRotatedWidth
, nRotatedHeight
));
1933 Outliner
* pOutliner
= mrBase
.GetDocument()->GetInternalOutliner();
1934 pOutliner
->Init(OutlinerMode::OutlineView
);
1935 const OutlinerMode
nSavedOutlMode (pOutliner
->GetOutlinerMode());
1936 const bool bSavedUpdateMode (pOutliner
->IsUpdateLayout());
1937 const Size
aSavedPaperSize (pOutliner
->GetPaperSize());
1938 const MapMode
aSavedMapMode (pOutliner
->GetRefMapMode());
1939 pOutliner
->SetPaperSize(aOutRect
.GetSize());
1940 pOutliner
->SetUpdateLayout(true);
1942 ::tools::Long nPageH
= aOutRect
.GetHeight();
1944 std::vector
< sal_Int32
> aPages
;
1945 sal_Int32 nPageCount
= mrBase
.GetDocument()->GetSdPageCount(PageKind::Standard
);
1946 StringRangeEnumerator::getRangesFromString(
1947 mpOptions
->GetPrinterSelection(nPageCount
, GetCurrentPageIndex()),
1948 aPages
, 0, nPageCount
-1);
1950 for (size_t nIndex
= 0, nCount
= aPages
.size(); nIndex
< nCount
;)
1954 Paragraph
* pPara
= nullptr;
1955 ::tools::Long
nH (0);
1956 while (nH
< nPageH
&& nIndex
<nCount
)
1958 SdPage
* pPage
= GetFilteredPage(aPages
[nIndex
], PageKind::Standard
);
1960 if (pPage
== nullptr)
1963 SdrTextObj
* pTextObj
= nullptr;
1965 for (const rtl::Reference
<SdrObject
>& pObj
: *pPage
)
1967 if (pObj
->GetObjInventor() == SdrInventor::Default
1968 && pObj
->GetObjIdentifier() == SdrObjKind::TitleText
)
1970 pTextObj
= DynCastSdrTextObj(pObj
.get());
1976 pPara
= pOutliner
->GetParagraph(pOutliner
->GetParagraphCount() - 1);
1978 if (pTextObj
!=nullptr
1979 && !pTextObj
->IsEmptyPresObj()
1980 && pTextObj
->GetOutlinerParaObject())
1982 pOutliner
->AddText(*(pTextObj
->GetOutlinerParaObject()));
1985 pOutliner
->Insert(OUString());
1989 for (const rtl::Reference
<SdrObject
>& pObj
: *pPage
)
1991 if (pObj
->GetObjInventor() == SdrInventor::Default
1992 && pObj
->GetObjIdentifier() == SdrObjKind::OutlineText
)
1994 pTextObj
= DynCastSdrTextObj(pObj
.get());
2000 bool bSubTitle (false);
2004 pTextObj
= DynCastSdrTextObj(pPage
->GetPresObj(PresObjKind::Text
)); // is there a subtitle?
2007 sal_Int32 nParaCount1
= pOutliner
->GetParagraphCount();
2009 if (pTextObj
!=nullptr
2010 && !pTextObj
->IsEmptyPresObj()
2011 && pTextObj
->GetOutlinerParaObject())
2013 pOutliner
->AddText(*(pTextObj
->GetOutlinerParaObject()));
2018 const sal_Int32
nParaCount2 (pOutliner
->GetParagraphCount());
2019 for (sal_Int32 nPara
=nParaCount1
; nPara
<nParaCount2
; ++nPara
)
2021 Paragraph
* pP
= pOutliner
->GetParagraph(nPara
);
2022 if (pP
!=nullptr && pOutliner
->GetDepth(nPara
) > 0)
2023 pOutliner
->SetDepth(pP
, 0);
2027 nH
= pOutliner
->GetTextHeight();
2030 // Remove the last paragraph when that does not fit completely on
2031 // the current page.
2032 if (nH
> nPageH
&& pPara
!=nullptr)
2034 sal_Int32 nCnt
= pOutliner
->GetAbsPos(
2035 pOutliner
->GetParagraph( pOutliner
->GetParagraphCount() - 1 ) );
2036 sal_Int32 nParaPos
= pOutliner
->GetAbsPos( pPara
);
2038 pPara
= pOutliner
->GetParagraph( ++nParaPos
);
2039 if ( nCnt
&& pPara
)
2041 pOutliner
->Remove(pPara
, nCnt
);
2046 if ( CheckForFrontBackPages( nIndex
) )
2048 maPrinterPages
.push_back(
2049 std::make_shared
<OutlinerPrinterPage
>(
2050 pOutliner
->CreateParaObject(),
2055 rInfo
.meOrientation
,
2056 rInfo
.mpPrinter
->GetPaperBin()));
2060 pOutliner
->SetRefMapMode(aSavedMapMode
);
2061 pOutliner
->SetUpdateLayout(bSavedUpdateMode
);
2062 pOutliner
->SetPaperSize(aSavedPaperSize
);
2063 pOutliner
->Init(nSavedOutlMode
);
2066 /** Prepare handout pages for slides that are to be printed.
2068 void PrepareHandout (PrintInfo
& rInfo
)
2070 SdDrawDocument
* pDocument
= mrBase
.GetDocument();
2071 assert(pDocument
!= nullptr);
2072 SdPage
& rHandoutPage (*pDocument
->GetSdPage(0, PageKind::Handout
));
2074 const bool bScalePage (mpOptions
->IsPageSize());
2076 sal_uInt16 nPaperBin
;
2077 if ( ! mpOptions
->IsPaperBin())
2078 nPaperBin
= rHandoutPage
.GetPaperBin();
2080 nPaperBin
= rInfo
.mpPrinter
->GetPaperBin();
2082 // Change orientation?
2083 SdPage
& rMaster (dynamic_cast<SdPage
&>(rHandoutPage
.TRG_GetMasterPage()));
2084 rInfo
.meOrientation
= rMaster
.GetOrientation();
2086 Size
aPaperSize (rInfo
.mpPrinter
->GetPaperSize());
2087 lcl_AdjustPageSize(aPaperSize
, rInfo
.mpPrinter
->GetPrintPageSize());
2088 maPrintSize
= awt::Size(aPaperSize
.Width(),aPaperSize
.Height());
2090 MapMode
aMap (rInfo
.maMap
);
2091 const Point
aPageOfs (rInfo
.mpPrinter
->GetPageOffset());
2095 Size
aPageSize (rHandoutPage
.GetSize());
2096 Size
aPrintSize (rInfo
.mpPrinter
->GetOutputSize());
2097 lcl_AdjustPageSize(aPageSize
, aPrintSize
);
2099 const double fHorz
= static_cast<double>(aPrintSize
.Width()) / aPageSize
.Width();
2100 const double fVert
= static_cast<double>(aPrintSize
.Height()) / aPageSize
.Height();
2103 if ( fHorz
< fVert
)
2104 aFract
= Fraction(aPrintSize
.Width(), aPageSize
.Width());
2106 aFract
= Fraction(aPrintSize
.Height(), aPageSize
.Height());
2108 aMap
.SetScaleX(aFract
);
2109 aMap
.SetScaleY(aFract
);
2110 aMap
.SetOrigin(Point());
2113 std::shared_ptr
<ViewShell
> pViewShell (mrBase
.GetMainViewShell());
2114 pViewShell
->WriteFrameViewData();
2116 // Count page shapes.
2117 sal_uInt32
nShapeCount (0);
2118 SdrObjListIter
aShapeIter (&rHandoutPage
);
2119 while (aShapeIter
.IsMore())
2121 SdrPageObj
* pPageObj
= dynamic_cast<SdrPageObj
*>(aShapeIter
.Next());
2126 const sal_uInt16 nPageCount
= mrBase
.GetDocument()->GetSdPageCount(PageKind::Standard
);
2127 const sal_uInt16 nHandoutPageCount
= nShapeCount
? (nPageCount
+ nShapeCount
- 1) / nShapeCount
: 0;
2128 pViewShell
->SetPrintedHandoutPageCount( nHandoutPageCount
);
2129 mrBase
.GetDocument()->setHandoutPageCount( nHandoutPageCount
);
2131 // Distribute pages to handout pages.
2132 StringRangeEnumerator
aRangeEnum(
2133 mpOptions
->GetPrinterSelection(nPageCount
, GetCurrentPageIndex()),
2135 std::vector
<sal_uInt16
> aPageIndices
;
2136 sal_uInt16 nPrinterPageIndex
= 0;
2137 StringRangeEnumerator::Iterator it
= aRangeEnum
.begin(), itEnd
= aRangeEnum
.end();
2138 bool bLastLoop
= (it
== itEnd
);
2141 sal_Int32 nPageIndex
= *it
;
2143 bLastLoop
= (it
== itEnd
);
2145 if (GetFilteredPage(nPageIndex
, PageKind::Standard
))
2146 aPageIndices
.push_back(nPageIndex
);
2147 else if (!bLastLoop
)
2150 // Create a printer page when we have found one page for each
2151 // placeholder or when this is the last (and special) loop.
2152 if ( !aPageIndices
.empty() && CheckForFrontBackPages( nPageIndex
)
2153 && (aPageIndices
.size() == nShapeCount
|| bLastLoop
) )
2155 maPrinterPages
.push_back(
2156 std::make_shared
<HandoutPrinterPage
>(
2157 nPrinterPageIndex
++,
2158 std::move(aPageIndices
),
2163 rInfo
.meOrientation
,
2165 aPageIndices
.clear();
2170 /** Prepare the notes pages or regular slides.
2172 void PrepareStdOrNotes (
2173 const PageKind ePageKind
,
2176 OSL_ASSERT(rInfo
.mpPrinter
!= nullptr);
2178 // Fill in page kind specific data.
2179 SdDrawDocument
* pDocument
= mrBase
.GetMainViewShell()->GetDoc();
2180 if (pDocument
->GetSdPageCount(ePageKind
) == 0)
2182 SdPage
* pRefPage
= pDocument
->GetSdPage(0, ePageKind
);
2184 if (!mpOptions
->IsPrinterPreferred(pDocument
->GetDocumentType()) && mpOptions
->IsNotes())
2185 rInfo
.maPageSize
= mpPrinter
->GetPrintPageSize();
2187 rInfo
.maPageSize
= pRefPage
->GetSize();
2189 SetupPaperOrientation(ePageKind
, rInfo
);
2191 if (mpOptions
->IsBooklet())
2192 PrepareBooklet(ePageKind
, rInfo
);
2194 PrepareRegularPages(ePageKind
, rInfo
);
2197 /** Prepare slides in a non-booklet way: one slide per one to many
2200 void PrepareRegularPages (
2201 const PageKind ePageKind
,
2204 std::shared_ptr
<ViewShell
> pViewShell (mrBase
.GetMainViewShell());
2205 pViewShell
->WriteFrameViewData();
2207 sal_Int32 nPageCount
= mrBase
.GetDocument()->GetSdPageCount(PageKind::Standard
);
2208 StringRangeEnumerator
aRangeEnum(
2209 mpOptions
->GetPrinterSelection(nPageCount
, GetCurrentPageIndex()),
2211 for (StringRangeEnumerator::Iterator
2212 it
= aRangeEnum
.begin(),
2213 itEnd
= aRangeEnum
.end();
2217 SdPage
* pPage
= GetFilteredPage(*it
, ePageKind
);
2218 if (pPage
== nullptr)
2221 MapMode
aMap (rInfo
.maMap
);
2223 Size aPageSize
= pPage
->GetSize();
2225 if (mpOptions
->IsPageSize())
2227 Size aPrintSize
= rInfo
.maPrintSize
;
2228 lcl_AdjustPageSize(aPageSize
, aPrintSize
);
2230 const double fHorz(static_cast<double>(aPrintSize
.Width()) / aPageSize
.Width());
2231 const double fVert(static_cast<double>(aPrintSize
.Height()) / aPageSize
.Height());
2235 aFract
= Fraction(aPrintSize
.Width(), aPageSize
.Width());
2237 aFract
= Fraction(aPrintSize
.Height(), aPageSize
.Height());
2239 aMap
.SetScaleX(aFract
);
2240 aMap
.SetScaleY(aFract
);
2241 aMap
.SetOrigin(Point());
2244 if (mpOptions
->IsPrintPageName())
2246 rInfo
.msPageString
= pPage
->GetName() + " ";
2249 rInfo
.msPageString
.clear();
2250 rInfo
.msPageString
+= rInfo
.msTimeDate
;
2252 ::tools::Long aPageWidth
= aPageSize
.Width() - pPage
->GetLeftBorder() - pPage
->GetRightBorder();
2253 ::tools::Long aPageHeight
= aPageSize
.Height() - pPage
->GetUpperBorder() - pPage
->GetLowerBorder();
2254 // Bugfix for 44530:
2255 // if it was implicitly changed (Landscape/Portrait),
2256 // this is considered for tiling, respectively for the splitting up
2258 if( ( rInfo
.maPrintSize
.Width() > rInfo
.maPrintSize
.Height()
2259 && aPageWidth
< aPageHeight
)
2260 || ( rInfo
.maPrintSize
.Width() < rInfo
.maPrintSize
.Height()
2261 && aPageWidth
> aPageHeight
) )
2263 const sal_Int32
nTmp (rInfo
.maPrintSize
.Width());
2264 rInfo
.maPrintSize
.setWidth( rInfo
.maPrintSize
.Height() );
2265 rInfo
.maPrintSize
.setHeight( nTmp
);
2268 if (mpOptions
->IsTilePage()
2269 && aPageWidth
< rInfo
.maPrintSize
.Width()
2270 && aPageHeight
< rInfo
.maPrintSize
.Height())
2272 // Put multiple slides on one printer page.
2273 PrepareTiledPage(*it
, *pPage
, ePageKind
, rInfo
);
2277 rInfo
.maMap
= std::move(aMap
);
2278 PrepareScaledPage(*it
, *pPage
, ePageKind
, rInfo
);
2283 /** Put two slides on one printer page.
2285 void PrepareBooklet (
2286 const PageKind ePageKind
,
2287 const PrintInfo
& rInfo
)
2289 MapMode
aStdMap (rInfo
.maMap
);
2291 Size
aPrintSize_2 (rInfo
.maPrintSize
);
2292 Size
aPageSize_2 (rInfo
.maPageSize
);
2294 if (rInfo
.meOrientation
== Orientation::Landscape
)
2295 aPrintSize_2
.setWidth( aPrintSize_2
.Width() >> 1 );
2297 aPrintSize_2
.setHeight( aPrintSize_2
.Height() >> 1 );
2299 const double fPageWH
= static_cast<double>(aPageSize_2
.Width()) / aPageSize_2
.Height();
2300 const double fPrintWH
= static_cast<double>(aPrintSize_2
.Width()) / aPrintSize_2
.Height();
2302 if( fPageWH
< fPrintWH
)
2304 aPageSize_2
.setWidth( static_cast<::tools::Long
>( aPrintSize_2
.Height() * fPageWH
) );
2305 aPageSize_2
.setHeight( aPrintSize_2
.Height() );
2309 aPageSize_2
.setWidth( aPrintSize_2
.Width() );
2310 aPageSize_2
.setHeight( static_cast<::tools::Long
>( aPrintSize_2
.Width() / fPageWH
) );
2313 MapMode
aMap (rInfo
.maMap
);
2314 aMap
.SetScaleX( Fraction( aPageSize_2
.Width(), rInfo
.maPageSize
.Width() ) );
2315 aMap
.SetScaleY( Fraction( aPageSize_2
.Height(), rInfo
.maPageSize
.Height() ) );
2317 // calculate adjusted print size
2318 const Size
aAdjustedPrintSize (OutputDevice::LogicToLogic(
2323 if (rInfo
.meOrientation
== Orientation::Landscape
)
2325 aOffset
.setX( ( ( aAdjustedPrintSize
.Width() >> 1 ) - rInfo
.maPageSize
.Width() ) >> 1 );
2326 aOffset
.setY( ( aAdjustedPrintSize
.Height() - rInfo
.maPageSize
.Height() ) >> 1 );
2330 aOffset
.setX( ( aAdjustedPrintSize
.Width() - rInfo
.maPageSize
.Width() ) >> 1 );
2331 aOffset
.setY( ( ( aAdjustedPrintSize
.Height() >> 1 ) - rInfo
.maPageSize
.Height() ) >> 1 );
2334 // create vector of pages to print
2335 sal_Int32 nPageCount
= mrBase
.GetDocument()->GetSdPageCount(ePageKind
);
2336 StringRangeEnumerator
aRangeEnum(
2337 mpOptions
->GetPrinterSelection(nPageCount
, GetCurrentPageIndex()),
2339 std::vector
< sal_uInt16
> aPageVector
;
2340 for (StringRangeEnumerator::Iterator
2341 it
= aRangeEnum
.begin(),
2342 itEnd
= aRangeEnum
.end();
2346 SdPage
* pPage
= GetFilteredPage(*it
, ePageKind
);
2347 if (pPage
!= nullptr)
2348 aPageVector
.push_back(*it
);
2351 // create pairs of pages to print on each page
2352 std::vector
< std::pair
< sal_uInt16
, sal_uInt16
> > aPairVector
;
2353 if ( ! aPageVector
.empty())
2355 sal_uInt32 nFirstIndex
= 0, nLastIndex
= aPageVector
.size() - 1;
2357 if( aPageVector
.size() & 1 )
2358 aPairVector
.emplace_back( sal_uInt16(65535), aPageVector
[ nFirstIndex
++ ] );
2360 aPairVector
.emplace_back( aPageVector
[ nLastIndex
-- ], aPageVector
[ nFirstIndex
++ ] );
2362 while( nFirstIndex
< nLastIndex
)
2364 if( nFirstIndex
& 1 )
2365 aPairVector
.emplace_back( aPageVector
[ nFirstIndex
++ ], aPageVector
[ nLastIndex
-- ] );
2367 aPairVector
.emplace_back( aPageVector
[ nLastIndex
-- ], aPageVector
[ nFirstIndex
++ ] );
2373 nCount
=aPairVector
.size();
2377 if ( CheckForFrontBackPages( nIndex
) )
2379 const std::pair
<sal_uInt16
, sal_uInt16
> aPair (aPairVector
[nIndex
]);
2380 Point
aSecondOffset (aOffset
);
2381 if (rInfo
.meOrientation
== Orientation::Landscape
)
2382 aSecondOffset
.AdjustX( aAdjustedPrintSize
.Width() / 2 );
2384 aSecondOffset
.AdjustY( aAdjustedPrintSize
.Height() / 2 );
2385 maPrinterPages
.push_back(
2386 std::make_shared
<BookletPrinterPage
>(
2393 rInfo
.mbPrintMarkedOnly
,
2395 rInfo
.meOrientation
,
2396 rInfo
.mpPrinter
->GetPaperBin()));
2402 /** Print one slide multiple times on one printer page so that the whole
2403 printer page is covered.
2405 void PrepareTiledPage (
2406 const sal_Int32 nPageIndex
,
2407 const SdPage
& rPage
,
2408 const PageKind ePageKind
,
2409 const PrintInfo
& rInfo
)
2411 sal_uInt16 nPaperBin
;
2412 if ( ! mpOptions
->IsPaperBin())
2413 nPaperBin
= rPage
.GetPaperBin();
2415 nPaperBin
= rInfo
.mpPrinter
->GetPaperBin();
2417 if ( !CheckForFrontBackPages( nPageIndex
) )
2420 maPrinterPages
.push_back(
2421 std::make_shared
<TiledPrinterPage
>(
2422 sal::static_int_cast
<sal_uInt16
>(nPageIndex
),
2424 rInfo
.mbPrintMarkedOnly
,
2426 rInfo
.mpPrinter
->GetPageOffset(),
2428 rInfo
.meOrientation
,
2432 /** Print one standard slide or notes page on one to many printer
2433 pages. More than on printer page is used when the slide is larger
2434 than the printable area.
2436 void PrepareScaledPage (
2437 const sal_Int32 nPageIndex
,
2438 const SdPage
& rPage
,
2439 const PageKind ePageKind
,
2440 const PrintInfo
& rInfo
)
2442 const Point
aPageOffset (rInfo
.mpPrinter
->GetPageOffset());
2444 sal_uInt16 nPaperBin
;
2445 if ( ! mpOptions
->IsPaperBin())
2446 nPaperBin
= rPage
.GetPaperBin();
2448 nPaperBin
= rInfo
.mpPrinter
->GetPaperBin();
2450 // For pages larger than the printable area there are three options:
2451 // 1. Scale down to the page to the printable area.
2452 // 2. Print only the upper left part of the page (without the unprintable borders).
2453 // 3. Split the page into parts of the size of the printable area.
2454 const bool bScalePage (mpOptions
->IsPageSize());
2455 const bool bCutPage (mpOptions
->IsCutPage());
2456 MapMode
aMap (rInfo
.maMap
);
2457 if ( (bScalePage
|| bCutPage
) && CheckForFrontBackPages( nPageIndex
) )
2461 // if CutPage is set then do not move it, otherwise move the
2462 // scaled page to printable area
2463 if (ePageKind
== PageKind::Standard
)
2465 maPrinterPages
.push_back(
2466 std::make_shared
<RegularPrinterPage
>(
2467 sal::static_int_cast
<sal_uInt16
>(nPageIndex
),
2470 rInfo
.mbPrintMarkedOnly
,
2474 rInfo
.meOrientation
,
2477 else if (SdPage
* pPage
= GetFilteredPage(nPageIndex
, PageKind::Notes
))// Notes
2479 SdDrawDocument
* pDocument
= mrBase
.GetMainViewShell()->GetDoc();
2481 // Clone the current page to create an independent instance.
2482 // This ensures that changes made to pNotesPage do not affect the original page.
2483 rtl::Reference
<SdPage
> pNotesPage
2484 = static_cast<SdPage
*>(pPage
->CloneSdrPage(*pDocument
).get());
2486 Size aPageSize
= bScalePage
? pNotesPage
->GetSize() : rInfo
.mpPrinter
->GetPrintPageSize();
2487 // Adjusts the objects on the notes page to fit the new page size.
2488 ::tools::Rectangle
aNewBorderRect(-1, -1, -1, -1);
2489 pNotesPage
->ScaleObjects(aPageSize
, aNewBorderRect
, true);
2491 SdrObject
* pNotesObj
= pNotesPage
->GetPresObj(PresObjKind::Notes
);
2492 if (pNotesObj
&& bCutPage
)
2495 sal_Int32 nTopMargin
= aPageSize
.Height() * 0.075;
2496 sal_Int32 nBottomMargin
= nTopMargin
;
2498 Size nNotesObjSize
= pNotesObj
->GetLogicRect().GetSize();
2500 Outliner
* pOut
= pDocument
->GetInternalOutliner();
2501 const OutlinerMode
nSaveOutlMode(pOut
->GetOutlinerMode());
2502 const bool bSavedUpdateMode(pOut
->IsUpdateLayout());
2503 pOut
->Init(OutlinerMode::OutlineView
);
2504 pOut
->SetPaperSize(nNotesObjSize
);
2505 pOut
->SetUpdateLayout(true);
2507 pOut
->SetText(*pNotesObj
->GetOutlinerParaObject());
2509 sal_Int32 nFirstPageBottomMargin
= 0;
2510 ::tools::Long nNotesHeight
= nNotesObjSize
.Height();
2511 bool bAutoGrow
= pNotesObj
->GetMergedItem(SDRATTR_TEXT_AUTOGROWHEIGHT
).GetValue();
2514 nNotesHeight
+= pNotesObj
->GetRelativePos().Y();
2515 nFirstPageBottomMargin
= (pNotesPage
->GetLowerBorder() != 0)
2516 ? pNotesPage
->GetLowerBorder()
2519 double nOverflowedTextHeight
= 0;
2520 ::tools::Long nFirstPageBottom
= aPageSize
.Height() - nFirstPageBottomMargin
;
2521 if (nNotesHeight
> nFirstPageBottom
)
2523 // Calculate the height of the overflow text
2524 // when the AutoGrowHeight property of the notes object is enabled
2525 // and the height of the object exceeds the page height.
2526 nOverflowedTextHeight
= pNotesObj
->GetRelativePos().Y()
2527 + pOut
->GetTextHeight() - nFirstPageBottom
;
2530 nOverflowedTextHeight
= pOut
->GetTextHeight() - nNotesObjSize
.Height();
2532 sal_Int32 nNotePageCount
= 1;
2533 double nNewPageHeight
= aPageSize
.Height() - nTopMargin
- nBottomMargin
;
2534 if (nOverflowedTextHeight
> 0)
2536 nNotePageCount
+= std::ceil(nOverflowedTextHeight
/ nNewPageHeight
);
2539 for (sal_Int32 i
= 1; i
<= nNotePageCount
; i
++)
2542 sal_Int32 nPageNumb
= i
;
2543 OUString sPageNumb
= rInfo
.msPageString
;
2544 if (!sPageNumb
.isEmpty() && nNotePageCount
> 1)
2547 if (!rInfo
.msTimeDate
.isEmpty())
2551 sTmp
+= SdResId(STR_PAGE_NAME
) + " " + OUString::number(i
);
2555 maPrinterPages
.push_back(
2556 std::make_shared
<NotesPrinterPage
>(
2557 sal::static_int_cast
<sal_uInt16
>(nPageIndex
),
2563 rInfo
.mbPrintMarkedOnly
,
2567 rInfo
.meOrientation
,
2571 pOut
->SetUpdateLayout(bSavedUpdateMode
);
2572 pOut
->Init(nSaveOutlMode
);
2576 maPrinterPages
.push_back(
2577 std::make_shared
<NotesPrinterPage
>(
2578 sal::static_int_cast
<sal_uInt16
>(nPageIndex
),
2584 rInfo
.mbPrintMarkedOnly
,
2588 rInfo
.meOrientation
,
2595 // Handle 3. Print parts of the page in the size of the
2596 // printable area until the whole page is covered.
2598 // keep the page content at its position if it fits, otherwise
2599 // move it to the printable area
2600 const ::tools::Long
nPageWidth (
2601 rInfo
.maPageSize
.Width() - rPage
.GetLeftBorder() - rPage
.GetRightBorder());
2602 const ::tools::Long
nPageHeight (
2603 rInfo
.maPageSize
.Height() - rPage
.GetUpperBorder() - rPage
.GetLowerBorder());
2605 Point
aOrigin ( 0, 0 );
2607 for (Point aPageOrigin
= aOrigin
;
2608 -aPageOrigin
.Y()<nPageHeight
;
2609 aPageOrigin
.AdjustY( -rInfo
.maPrintSize
.Height() ))
2611 for (aPageOrigin
.setX(aOrigin
.X());
2612 -aPageOrigin
.X()<nPageWidth
;
2613 aPageOrigin
.AdjustX(-rInfo
.maPrintSize
.Width()))
2615 if ( CheckForFrontBackPages( nPageIndex
) )
2617 aMap
.SetOrigin(aPageOrigin
);
2618 maPrinterPages
.push_back(
2619 std::make_shared
<RegularPrinterPage
>(
2620 sal::static_int_cast
<sal_uInt16
>(nPageIndex
),
2623 rInfo
.mbPrintMarkedOnly
,
2627 rInfo
.meOrientation
,
2635 bool CheckForFrontBackPages( sal_Int32 nPage
)
2637 const bool bIsIndexOdd(nPage
& 1);
2638 if ((!bIsIndexOdd
&& mpOptions
->IsPrintFrontPage())
2639 || (bIsIndexOdd
&& mpOptions
->IsPrintBackPage()))
2648 //===== DocumentRenderer ======================================================
2650 DocumentRenderer::DocumentRenderer (ViewShellBase
& rBase
)
2651 : mpImpl(new Implementation(rBase
))
2655 DocumentRenderer::~DocumentRenderer()
2659 //----- XRenderable -----------------------------------------------------------
2661 sal_Int32 SAL_CALL
DocumentRenderer::getRendererCount (
2662 const css::uno::Any
&,
2663 const css::uno::Sequence
<css::beans::PropertyValue
>& rOptions
)
2665 mpImpl
->ProcessProperties(rOptions
);
2666 return mpImpl
->GetPrintPageCount();
2669 Sequence
<beans::PropertyValue
> SAL_CALL
DocumentRenderer::getRenderer (
2671 const css::uno::Any
&,
2672 const css::uno::Sequence
<css::beans::PropertyValue
>& rOptions
)
2674 mpImpl
->ProcessProperties(rOptions
);
2675 return mpImpl
->GetProperties();
2678 void SAL_CALL
DocumentRenderer::render (
2679 sal_Int32 nRenderer
,
2680 const css::uno::Any
&,
2681 const css::uno::Sequence
<css::beans::PropertyValue
>& rOptions
)
2683 mpImpl
->ProcessProperties(rOptions
);
2684 mpImpl
->PrintPage(nRenderer
);
2687 } // end of namespace sd
2689 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */