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/outlobj.hxx>
47 #include <svx/svdetc.hxx>
48 #include <svx/svditer.hxx>
49 #include <svx/svdopage.hxx>
50 #include <svx/svdopath.hxx>
51 #include <svx/svdpagv.hxx>
52 #include <svx/xlineit0.hxx>
53 #include <svx/xlnclit.hxx>
54 #include <toolkit/awt/vclxdevice.hxx>
55 #include <unotools/localedatawrapper.hxx>
57 #include <vcl/print.hxx>
58 #include <vcl/svapp.hxx>
59 #include <vcl/weld.hxx>
60 #include <unotools/moduleoptions.hxx>
61 #include <xmloff/autolayout.hxx>
62 #include <sfx2/objsh.hxx>
64 #include <officecfg/Office/Draw.hxx>
65 #include <officecfg/Office/Impress.hxx>
71 using namespace ::com::sun::star
;
72 using namespace ::com::sun::star::uno
;
78 /** Convenience class to extract values from the sequence of properties
79 given to one of the XRenderable methods.
85 const vcl::PrinterOptionsHelper
& rHelper
,
86 std::vector
<sal_Int32
>&& rSlidesPerPage
)
87 : mrProperties(rHelper
),
88 maSlidesPerPage(std::move(rSlidesPerPage
))
92 bool IsWarningOrientation() const
94 return GetBoolValue(nullptr, true);
97 bool IsPrintPageName() const
99 return GetBoolValue("IsPrintName", false);
104 return GetBoolValue("IsPrintDateTime", false);
109 return GetBoolValue("IsPrintDateTime", false);
112 bool IsHiddenPages() const
114 return GetBoolValue("IsPrintHidden", false);
117 bool IsHandoutHorizontal() const
119 return GetBoolValue("SlidesPerPageOrder", sal_Int32(0));
122 sal_Int32
GetHandoutPageCount() const
124 sal_uInt32 nIndex
= static_cast<sal_Int32
>(mrProperties
.getIntValue("SlidesPerPage", sal_Int32(0)));
125 if (nIndex
<maSlidesPerPage
.size())
126 return maSlidesPerPage
[nIndex
];
127 else if ( ! maSlidesPerPage
.empty())
128 return maSlidesPerPage
[0];
135 return GetBoolValue("PageContentType", sal_Int32(0));
138 bool IsHandout() const
140 return GetBoolValue("PageContentType", sal_Int32(1));
145 return GetBoolValue("PageContentType", sal_Int32(2));
148 bool IsOutline() const
150 return GetBoolValue("PageContentType", sal_Int32(3));
153 sal_uLong
GetOutputQuality() const
155 sal_Int32 nQuality
= static_cast<sal_Int32
>(mrProperties
.getIntValue( "Quality", sal_Int32(0) ));
159 bool IsPageSize() const
161 return GetBoolValue("PageOptions", sal_Int32(1));
164 bool IsTilePage() const
166 return GetBoolValue("PageOptions", sal_Int32(2)) || GetBoolValue("PageOptions", sal_Int32(3));
169 bool IsCutPage() const
171 return GetBoolValue("PageOptions", sal_Int32(0));
174 bool IsBooklet() const
176 return GetBoolValue("PrintProspect", false);
179 bool IsPrinterPreferred(DocumentType eDocType
) const
181 bool bIsDraw
= eDocType
== DocumentType::Draw
;
182 return IsTilePage() || IsPageSize() || IsBooklet() || (!bIsDraw
&& !IsNotes());
185 bool IsPrintExcluded() const
187 return (IsNotes() || IsDraw() || IsHandout()) && IsHiddenPages();
190 bool IsPrintFrontPage() const
192 sal_Int32 nInclude
= static_cast<sal_Int32
>(mrProperties
.getIntValue( "EvenOdd", 0 ));
193 return nInclude
!= 2;
196 bool IsPrintBackPage() const
198 sal_Int32 nInclude
= static_cast<sal_Int32
>(mrProperties
.getIntValue( "EvenOdd", 0 ));
199 return nInclude
!= 1;
202 bool IsPaperBin() const
204 return GetBoolValue("PrintPaperFromSetup", false);
207 bool IsPrintMarkedOnly() const
209 return GetBoolValue("PrintContent", sal_Int32(4));
212 OUString
GetPrinterSelection (sal_Int32 nPageCount
, sal_Int32 nCurrentPageIndex
) const
214 sal_Int32 nContent
= static_cast<sal_Int32
>(mrProperties
.getIntValue( "PrintContent", 0 ));
215 OUString sFullRange
= "1-" + OUString::number(nPageCount
);
217 if (nContent
== 0) // all pages/slides
222 if (nContent
== 1) // range
224 OUString sValue
= mrProperties
.getStringValue("PageRange");
225 return sValue
.isEmpty() ? sFullRange
: sValue
;
228 if (nContent
== 2 && // selection
229 nCurrentPageIndex
>= 0)
231 return OUString::number(nCurrentPageIndex
+ 1);
238 const vcl::PrinterOptionsHelper
& mrProperties
;
239 const std::vector
<sal_Int32
> maSlidesPerPage
;
241 /** When the value of the property with name pName is a boolean then
242 return its value. When the property is unknown then
243 bDefaultValue is returned. Otherwise <FALSE/> is returned.
247 const bool bDefaultValue
) const
249 bool bValue
= mrProperties
.getBoolValue( pName
, bDefaultValue
);
253 /** Return <TRUE/> when the value of the property with name pName is
254 an integer and its value is nTriggerValue. Otherwise <FALSE/> is
259 const sal_Int32 nTriggerValue
) const
261 sal_Int32 nValue
= static_cast<sal_Int32
>(mrProperties
.getIntValue( pName
, 0 ));
262 return nValue
== nTriggerValue
;
266 /** A collection of values that helps to reduce the number of arguments
267 given to some functions. Note that not all values are set at the
275 const bool bPrintMarkedOnly
)
276 : mpPrinter(pPrinter
),
277 mnDrawMode(DrawModeFlags::Default
),
280 meOrientation(Orientation::Portrait
),
281 mbPrintMarkedOnly(bPrintMarkedOnly
)
284 const VclPtr
<Printer
> mpPrinter
;
285 DrawModeFlags mnDrawMode
;
287 OUString msPageString
;
290 Orientation meOrientation
;
292 const bool mbPrintMarkedOnly
;
295 /** Output one page of the document to the given printer. Note that
296 more than one document page may be output to one printer page.
300 ::sd::View
& rPrintView
,
303 const bool bPrintMarkedOnly
,
304 const SdrLayerIDSet
& rVisibleLayers
,
305 const SdrLayerIDSet
& rPrintableLayers
)
307 rPrintView
.ShowSdrPage(&rPage
);
309 const MapMode
aOriginalMapMode (rPrinter
.GetMapMode());
311 // Set the visible layers
312 SdrPageView
* pPageView
= rPrintView
.GetSdrPageView();
313 OSL_ASSERT(pPageView
!=nullptr);
314 pPageView
->SetVisibleLayers(rVisibleLayers
);
315 pPageView
->SetPrintableLayers(rPrintableLayers
);
317 if (pView
!=nullptr && bPrintMarkedOnly
)
318 pView
->DrawMarkedObj(rPrinter
);
320 rPrintView
.CompleteRedraw(&rPrinter
,
321 vcl::Region(::tools::Rectangle(Point(0,0), rPage
.GetSize())));
323 rPrinter
.SetMapMode(aOriginalMapMode
);
325 rPrintView
.HideSdrPage();
328 /** Output a string (that typically is not part of a document page) to
333 const OUString
& rsPageString
,
334 const Point
& rPageStringOffset
)
336 const vcl::Font
aOriginalFont (rPrinter
.OutputDevice::GetFont());
337 rPrinter
.SetFont(vcl::Font(FAMILY_SWISS
, Size(0, 423)));
338 rPrinter
.DrawText(rPageStringOffset
, rsPageString
);
339 rPrinter
.SetFont(aOriginalFont
);
342 /** Read the resources and process then into a sequence of properties
343 that can be passed to the printing dialog.
348 DialogCreator (ViewShellBase
&rBase
, bool bImpress
, sal_Int32 nCurPage
)
350 , mbImpress(bImpress
)
351 , mnCurPage(nCurPage
)
356 const std::vector
< beans::PropertyValue
>& GetDialogControls() const
361 const std::vector
<sal_Int32
>& GetSlidesPerPage() const
363 return maSlidesPerPage
;
367 ViewShellBase
&mrBase
;
368 std::vector
<beans::PropertyValue
> maProperties
;
369 std::vector
<sal_Int32
> maSlidesPerPage
;
373 void ProcessResource()
375 // load the writer PrinterOptions into the custom tab
376 beans::PropertyValue aOptionsUIFile
;
377 aOptionsUIFile
.Name
= "OptionsUIFile";
379 aOptionsUIFile
.Value
<<= OUString("modules/simpress/ui/impressprinteroptions.ui");
381 aOptionsUIFile
.Value
<<= OUString("modules/sdraw/ui/drawprinteroptions.ui");
382 maProperties
.push_back(aOptionsUIFile
);
384 SvtModuleOptions aOpt
;
385 OUString
aAppGroupname(SdResId(STR_IMPRESS_PRINT_UI_GROUP_NAME
));
386 aAppGroupname
= aAppGroupname
.replaceFirst("%s", aOpt
.GetModuleName(
387 mbImpress
? SvtModuleOptions::EModule::IMPRESS
: SvtModuleOptions::EModule::DRAW
));
388 AddDialogControl(vcl::PrinterOptionsHelper::setGroupControlOpt("tabcontrol-page2", aAppGroupname
, ".HelpID:vcl:PrintDialog:TabPage:AppPage"));
390 uno::Sequence
< OUString
> aHelpIds
, aWidgetIds
;
393 aHelpIds
= { ".HelpID:vcl:PrintDialog:PageContentType:ListBox" };
394 AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt(
396 SdResId(STR_IMPRESS_PRINT_UI_CONTENT
),
399 CreateChoice(STR_IMPRESS_PRINT_UI_CONTENT_CHOICES
, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_CONTENT_CHOICES
)),
403 aHelpIds
= { ".HelpID:vcl:PrintDialog:SlidesPerPage:ListBox" };
404 vcl::PrinterOptionsHelper::UIControlOptions
aContentOpt( "PageContentType" , 1 );
405 AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt(
407 SdResId(STR_IMPRESS_PRINT_UI_SLIDESPERPAGE
),
410 GetSlidesPerPageSequence(),
412 Sequence
< sal_Bool
>(),
417 aHelpIds
= { ".HelpID:vcl:PrintDialog:SlidesPerPageOrder:ListBox" };
418 vcl::PrinterOptionsHelper::UIControlOptions
aSlidesPerPageOpt( "SlidesPerPage" , -1, true );
419 AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt(
420 "slidesperpageorder",
421 SdResId(STR_IMPRESS_PRINT_UI_ORDER
),
423 "SlidesPerPageOrder" ,
424 CreateChoice(STR_IMPRESS_PRINT_UI_ORDER_CHOICES
, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_ORDER_CHOICES
)),
426 Sequence
< sal_Bool
>(),
431 AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt("contents",
432 SdResId(STR_IMPRESS_PRINT_UI_INCLUDE_CONTENT
), "" ) );
436 AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt("printname",
437 SdResId(STR_IMPRESS_PRINT_UI_IS_PRINT_NAME
),
438 ".HelpID:vcl:PrintDialog:IsPrintName:CheckBox" ,
440 officecfg::Office::Impress::Print::Other::PageName::get()
446 AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt("printname",
447 SdResId(STR_DRAW_PRINT_UI_IS_PRINT_NAME
),
448 ".HelpID:vcl:PrintDialog:IsPrintName:CheckBox" ,
450 officecfg::Office::Draw::Print::Other::PageName::get()
455 AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt("printdatetime",
456 SdResId(STR_IMPRESS_PRINT_UI_IS_PRINT_DATE
),
457 ".HelpID:vcl:PrintDialog:IsPrintDateTime:CheckBox" ,
459 // Separate settings for time and date in Impress/Draw -> Print page, check that both are set
461 officecfg::Office::Impress::Print::Other::Date::get() &&
462 officecfg::Office::Impress::Print::Other::Time::get() :
463 officecfg::Office::Draw::Print::Other::Date::get() &&
464 officecfg::Office::Draw::Print::Other::Time::get()
470 AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt("printhidden",
471 SdResId(STR_IMPRESS_PRINT_UI_IS_PRINT_HIDDEN
),
472 ".HelpID:vcl:PrintDialog:IsPrintHidden:CheckBox" ,
474 officecfg::Office::Impress::Print::Other::HiddenPage::get()
479 AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt("color",
480 SdResId(STR_IMPRESS_PRINT_UI_QUALITY
), "" ) );
482 aHelpIds
= { ".HelpID:vcl:PrintDialog:Quality:RadioButton:0",
483 ".HelpID:vcl:PrintDialog:Quality:RadioButton:1",
484 ".HelpID:vcl:PrintDialog:Quality:RadioButton:2" };
485 aWidgetIds
= { "originalcolors", "grayscale", "blackandwhite" };
486 AddDialogControl( vcl::PrinterOptionsHelper::setChoiceRadiosControlOpt(
491 CreateChoice(STR_IMPRESS_PRINT_UI_QUALITY_CHOICES
, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_QUALITY_CHOICES
)),
492 mbImpress
? officecfg::Office::Impress::Print::Other::Quality::get() :
493 officecfg::Office::Draw::Print::Other::Quality::get() )
497 AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt("pagesizes",
498 SdResId(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS
), "" ) );
500 aHelpIds
= { ".HelpID:vcl:PrintDialog:PageOptions:RadioButton:0",
501 ".HelpID:vcl:PrintDialog:PageOptions:RadioButton:1",
502 ".HelpID:vcl:PrintDialog:PageOptions:RadioButton:2",
503 ".HelpID:vcl:PrintDialog:PageOptions:RadioButton:3" };
504 aWidgetIds
= { "originalsize", "fittoprintable", "distributeonmultiple", "tilesheet" };
506 // Mutually exclusive page options settings are stored in separate config keys...
507 // TODO: There is no config key to set the distributeonmultiple option as default
508 sal_Int32 nDefaultChoice
= 0;
509 if ( mbImpress
? officecfg::Office::Impress::Print::Page::PageSize::get() :
510 officecfg::Office::Draw::Print::Page::PageSize::get() )
514 else if ( mbImpress
? officecfg::Office::Impress::Print::Page::PageTile::get() :
515 officecfg::Office::Draw::Print::Page::PageTile::get() )
519 vcl::PrinterOptionsHelper::UIControlOptions
aPageOptionsOpt("PrintProspect", 0);
520 AddDialogControl( vcl::PrinterOptionsHelper::setChoiceRadiosControlOpt(
525 mbImpress
? CreateChoice(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES
, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES
)) :
526 CreateChoice(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES_DRAW
, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES_DRAW
)),
528 Sequence
< sal_Bool
>(),
533 vcl::PrinterOptionsHelper::UIControlOptions aBrochureOpt
;
534 aBrochureOpt
.maGroupHint
= "LayoutPage" ;
535 AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt("pagesides",
536 SdResId(STR_IMPRESS_PRINT_UI_PAGE_SIDES
), "",
540 AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt("brochure",
541 SdResId(STR_IMPRESS_PRINT_UI_BROCHURE
),
542 ".HelpID:vcl:PrintDialog:PrintProspect:CheckBox" ,
544 mbImpress
? officecfg::Office::Impress::Print::Page::Booklet::get() :
545 officecfg::Office::Draw::Print::Page::Booklet::get(),
550 vcl::PrinterOptionsHelper::UIControlOptions
551 aIncludeOpt( "PrintProspect" , -1, false );
552 aIncludeOpt
.maGroupHint
= "LayoutPage" ;
553 aHelpIds
= { ".HelpID:vcl:PrintDialog:PrintProspectInclude:ListBox" };
554 AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt(
556 SdResId(STR_IMPRESS_PRINT_UI_BROCHURE_INCLUDE
),
558 "PrintProspectInclude" ,
559 CreateChoice(STR_IMPRESS_PRINT_UI_BROCHURE_INCLUDE_LIST
, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_BROCHURE_INCLUDE_LIST
)),
561 Sequence
< sal_Bool
>(),
566 // paper tray (on options page)
567 vcl::PrinterOptionsHelper::UIControlOptions aPaperTrayOpt
;
568 aPaperTrayOpt
.maGroupHint
= "OptionsPageOptGroup" ;
569 AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt("printpaperfromsetup",
570 SdResId(STR_IMPRESS_PRINT_UI_PAPER_TRAY
),
571 ".HelpID:vcl:PrintDialog:PrintPaperFromSetup:CheckBox" ,
572 "PrintPaperFromSetup" ,
577 // print range selection
578 vcl::PrinterOptionsHelper::UIControlOptions aPrintRangeOpt
;
579 aPrintRangeOpt
.mbInternalOnly
= true;
580 aPrintRangeOpt
.maGroupHint
= "PrintRange" ;
581 AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt("printrange",
582 mbImpress
? SdResId(STR_IMPRESS_PRINT_UI_SLIDE_RANGE
) : SdResId(STR_IMPRESS_PRINT_UI_PAGE_RANGE
),
587 // check if there is a selection of slides
588 OUString
aPageRange(OUString::number(mnCurPage
+ 1));
590 using sd::slidesorter::SlideSorterViewShell
;
591 SlideSorterViewShell
* const pSSViewSh(SlideSorterViewShell::GetSlideSorter(mrBase
));
594 const std::shared_ptr
<SlideSorterViewShell::PageSelection
> pPageSelection(pSSViewSh
->GetPageSelection());
595 if (bool(pPageSelection
) && pPageSelection
->size() > 1)
598 // TODO: this could be improved by writing ranges instead of consecutive page
599 // numbers if appropriate. Do we have a helper function for that somewhere?
601 for (auto pPage
: *pPageSelection
)
607 aBuf
.append(static_cast<sal_Int32
>(pPage
->GetPageNum() / 2 + 1));
609 aPageRange
= aBuf
.makeStringAndClear();
614 OUString aPrintRangeName( "PrintContent" );
615 aHelpIds.realloc( 1 );
616 aHelpIds[0] = ".HelpID:vcl:PrintDialog:PageContentType:ListBox";
617 AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt( "printpagesbox", OUString(),
618 aHelpIds, aPrintRangeName,
619 mbImpress ? CreateChoice( STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE ) ) :
620 CreateChoice( STR_DRAW_PRINT_UI_PAGE_RANGE_CHOICE, SAL_N_ELEMENTS(STR_DRAW_PRINT_UI_PAGE_RANGE_CHOICE ) ),
623 OUString
aPrintRangeName( "PrintContent" );
624 aHelpIds
= { ".HelpID:vcl:PrintDialog:PrintContent:RadioButton:0",
625 ".HelpID:vcl:PrintDialog:PrintContent:RadioButton:1",
626 ".HelpID:vcl:PrintDialog:PrintContent:RadioButton:2" };
627 aWidgetIds
= { "rbAllPages", "rbRangePages", "rbRangeSelection" };
629 AddDialogControl( vcl::PrinterOptionsHelper::setChoiceRadiosControlOpt(aWidgetIds
, OUString(),
630 aHelpIds
, aPrintRangeName
,
631 mbImpress
? CreateChoice(STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE
, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE
)) :
632 CreateChoice(STR_DRAW_PRINT_UI_PAGE_RANGE_CHOICE
, SAL_N_ELEMENTS(STR_DRAW_PRINT_UI_PAGE_RANGE_CHOICE
)),
635 // create an Edit dependent on "Pages" selected
636 vcl::PrinterOptionsHelper::UIControlOptions
aPageRangeOpt( aPrintRangeName
, 1, true );
637 AddDialogControl(vcl::PrinterOptionsHelper::setEditControlOpt("pagerange", "",
638 ".HelpID:vcl:PrintDialog:PageRange:Edit", "PageRange",
639 aPageRange
, aPageRangeOpt
));
640 vcl::PrinterOptionsHelper::UIControlOptions
aEvenOddOpt(aPrintRangeName
, -1, true);
641 AddDialogControl(vcl::PrinterOptionsHelper::setChoiceListControlOpt("evenoddbox", "",
642 uno::Sequence
<OUString
>(), "EvenOdd", uno::Sequence
<OUString
>(),
643 0, uno::Sequence
<sal_Bool
>(), aEvenOddOpt
));
646 void AddDialogControl( const Any
& i_rCtrl
)
648 beans::PropertyValue aVal
;
649 aVal
.Value
= i_rCtrl
;
650 maProperties
.push_back( aVal
);
653 static Sequence
<OUString
> CreateChoice(const TranslateId
* pResourceId
, size_t nCount
)
655 Sequence
<OUString
> aChoices (nCount
);
656 std::transform(pResourceId
, pResourceId
+ nCount
, aChoices
.getArray(),
657 [](const auto& id
) { return SdResId(id
); });
661 Sequence
<OUString
> GetSlidesPerPageSequence()
663 const Sequence
<OUString
> aChoice (
664 CreateChoice(STR_IMPRESS_PRINT_UI_SLIDESPERPAGE_CHOICES
, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_SLIDESPERPAGE_CHOICES
)));
665 maSlidesPerPage
.clear();
666 maSlidesPerPage
.push_back(0); // first is using the default
667 std::transform(std::next(aChoice
.begin()), aChoice
.end(), std::back_inserter(maSlidesPerPage
),
668 [](const OUString
& rChoice
) -> sal_Int32
{ return rChoice
.toInt32(); });
673 /** The Prepare... methods of the DocumentRenderer::Implementation class
674 create a set of PrinterPage objects that contain all necessary
675 information to do the actual printing. There is one PrinterPage
676 object per printed page. Derived classes implement the actual, mode
679 This and all derived classes support the asynchronous printing
680 process by not storing pointers to any data with lifetime shorter
681 than the PrinterPage objects, i.e. slides, shapes, (one of) the
682 outliner (of the document).
688 const PageKind ePageKind
,
689 const MapMode
& rMapMode
,
690 const bool bPrintMarkedOnly
,
691 OUString sPageString
,
692 const Point
& rPageStringOffset
,
693 const DrawModeFlags nDrawMode
,
694 const Orientation eOrientation
,
695 const sal_uInt16 nPaperTray
)
696 : mePageKind(ePageKind
),
698 mbPrintMarkedOnly(bPrintMarkedOnly
),
699 msPageString(std::move(sPageString
)),
700 maPageStringOffset(rPageStringOffset
),
701 mnDrawMode(nDrawMode
),
702 meOrientation(eOrientation
),
703 mnPaperTray(nPaperTray
)
707 virtual ~PrinterPage() {}
711 SdDrawDocument
& rDocument
,
712 ViewShell
& rViewShell
,
714 DrawView
& rPrintView
,
715 const SdrLayerIDSet
& rVisibleLayers
,
716 const SdrLayerIDSet
& rPrintableLayers
) const = 0;
718 DrawModeFlags
GetDrawMode() const { return mnDrawMode
; }
719 Orientation
GetOrientation() const { return meOrientation
; }
720 sal_uInt16
GetPaperTray() const { return mnPaperTray
; }
723 const PageKind mePageKind
;
725 const bool mbPrintMarkedOnly
;
726 const OUString msPageString
;
727 const Point maPageStringOffset
;
728 const DrawModeFlags mnDrawMode
;
729 const Orientation meOrientation
;
730 const sal_uInt16 mnPaperTray
;
733 /** The RegularPrinterPage is used for printing one regular slide (no
734 notes, handout, or outline) to one printer page.
736 class RegularPrinterPage
: public PrinterPage
740 const sal_uInt16 nPageIndex
,
741 const PageKind ePageKind
,
742 const MapMode
& rMapMode
,
743 const bool bPrintMarkedOnly
,
744 const OUString
& rsPageString
,
745 const Point
& rPageStringOffset
,
746 const DrawModeFlags nDrawMode
,
747 const Orientation eOrientation
,
748 const sal_uInt16 nPaperTray
)
749 : PrinterPage(ePageKind
, rMapMode
, bPrintMarkedOnly
, rsPageString
,
750 rPageStringOffset
, nDrawMode
, eOrientation
, nPaperTray
),
751 mnPageIndex(nPageIndex
)
757 SdDrawDocument
& rDocument
,
760 DrawView
& rPrintView
,
761 const SdrLayerIDSet
& rVisibleLayers
,
762 const SdrLayerIDSet
& rPrintableLayers
) const override
764 SdPage
* pPageToPrint
= rDocument
.GetSdPage(mnPageIndex
, mePageKind
);
765 rPrinter
.SetMapMode(maMap
);
781 const sal_uInt16 mnPageIndex
;
784 /** Print one slide multiple times on a printer page so that the whole
785 printer page is covered.
787 class TiledPrinterPage
: public PrinterPage
791 const sal_uInt16 nPageIndex
,
792 const PageKind ePageKind
,
793 const bool bPrintMarkedOnly
,
794 const OUString
& rsPageString
,
795 const Point
& rPageStringOffset
,
796 const DrawModeFlags nDrawMode
,
797 const Orientation eOrientation
,
798 const sal_uInt16 nPaperTray
)
799 : PrinterPage(ePageKind
, MapMode(), bPrintMarkedOnly
, rsPageString
,
800 rPageStringOffset
, nDrawMode
, eOrientation
, nPaperTray
),
801 mnPageIndex(nPageIndex
)
807 SdDrawDocument
& rDocument
,
810 DrawView
& rPrintView
,
811 const SdrLayerIDSet
& rVisibleLayers
,
812 const SdrLayerIDSet
& rPrintableLayers
) const override
814 SdPage
* pPageToPrint
= rDocument
.GetSdPage(mnPageIndex
, mePageKind
);
815 if (pPageToPrint
==nullptr)
817 MapMode
aMap (rPrinter
.GetMapMode());
819 const Size
aPageSize (pPageToPrint
->GetSize());
820 const Size
aPrintSize (rPrinter
.GetOutputSize());
822 const sal_Int32
nPageWidth (aPageSize
.Width() + mnGap
823 - pPageToPrint
->GetLeftBorder() - pPageToPrint
->GetRightBorder());
824 const sal_Int32
nPageHeight (aPageSize
.Height() + mnGap
825 - pPageToPrint
->GetUpperBorder() - pPageToPrint
->GetLowerBorder());
826 if (nPageWidth
<=0 || nPageHeight
<=0)
829 // Print at least two rows and columns. More if the document
830 // page fits completely onto the printer page.
831 const sal_Int32
nColumnCount (std::max(sal_Int32(2),
832 sal_Int32(aPrintSize
.Width() / nPageWidth
)));
833 const sal_Int32
nRowCount (std::max(sal_Int32(2),
834 sal_Int32(aPrintSize
.Height() / nPageHeight
)));
835 for (sal_Int32 nRow
=0; nRow
<nRowCount
; ++nRow
)
836 for (sal_Int32 nColumn
=0; nColumn
<nColumnCount
; ++nColumn
)
838 aMap
.SetOrigin(Point(nColumn
*nPageWidth
,nRow
*nPageHeight
));
839 rPrinter
.SetMapMode(aMap
);
857 const sal_uInt16 mnPageIndex
;
858 static const sal_Int32 mnGap
= 500;
861 /** Print two slides to one printer page so that the resulting pages
864 class BookletPrinterPage
: public PrinterPage
868 const sal_uInt16 nFirstPageIndex
,
869 const sal_uInt16 nSecondPageIndex
,
870 const Point
& rFirstOffset
,
871 const Point
& rSecondOffset
,
872 const PageKind ePageKind
,
873 const MapMode
& rMapMode
,
874 const bool bPrintMarkedOnly
,
875 const DrawModeFlags nDrawMode
,
876 const Orientation eOrientation
,
877 const sal_uInt16 nPaperTray
)
878 : PrinterPage(ePageKind
, rMapMode
, bPrintMarkedOnly
, "",
879 Point(), nDrawMode
, eOrientation
, nPaperTray
),
880 mnFirstPageIndex(nFirstPageIndex
),
881 mnSecondPageIndex(nSecondPageIndex
),
882 maFirstOffset(rFirstOffset
),
883 maSecondOffset(rSecondOffset
)
889 SdDrawDocument
& rDocument
,
892 DrawView
& rPrintView
,
893 const SdrLayerIDSet
& rVisibleLayers
,
894 const SdrLayerIDSet
& rPrintableLayers
) const override
896 MapMode
aMap (maMap
);
897 SdPage
* pPageToPrint
= rDocument
.GetSdPage(mnFirstPageIndex
, mePageKind
);
900 aMap
.SetOrigin(maFirstOffset
);
901 rPrinter
.SetMapMode(aMap
);
912 pPageToPrint
= rDocument
.GetSdPage(mnSecondPageIndex
, mePageKind
);
916 aMap
.SetOrigin(maSecondOffset
);
917 rPrinter
.SetMapMode(aMap
);
929 const sal_uInt16 mnFirstPageIndex
;
930 const sal_uInt16 mnSecondPageIndex
;
931 const Point maFirstOffset
;
932 const Point maSecondOffset
;
935 /** One handout page displays one to nine slides.
937 class HandoutPrinterPage
: public PrinterPage
941 const sal_uInt16 nHandoutPageIndex
,
942 std::vector
<sal_uInt16
>&& rPageIndices
,
943 const MapMode
& rMapMode
,
944 const OUString
& rsPageString
,
945 const Point
& rPageStringOffset
,
946 const DrawModeFlags nDrawMode
,
947 const Orientation eOrientation
,
948 const sal_uInt16 nPaperTray
)
949 : PrinterPage(PageKind::Handout
, rMapMode
, false, rsPageString
,
950 rPageStringOffset
, nDrawMode
, eOrientation
, nPaperTray
),
951 mnHandoutPageIndex(nHandoutPageIndex
),
952 maPageIndices(std::move(rPageIndices
))
958 SdDrawDocument
& rDocument
,
959 ViewShell
& rViewShell
,
961 DrawView
& rPrintView
,
962 const SdrLayerIDSet
& rVisibleLayers
,
963 const SdrLayerIDSet
& rPrintableLayers
) const override
965 SdPage
& rHandoutPage (*rDocument
.GetSdPage(0, PageKind::Handout
));
967 Reference
< css::beans::XPropertySet
> xHandoutPage( rHandoutPage
.getUnoPage(), UNO_QUERY
);
968 static const OUStringLiteral
sPageNumber( u
"Number" );
970 // Collect the page objects of the handout master.
971 std::vector
<SdrPageObj
*> aHandoutPageObjects
;
972 SdrObjListIter
aShapeIter (&rHandoutPage
);
973 while (aShapeIter
.IsMore())
975 SdrPageObj
* pPageObj
= dynamic_cast<SdrPageObj
*>(aShapeIter
.Next());
977 aHandoutPageObjects
.push_back(pPageObj
);
979 if (aHandoutPageObjects
.empty())
982 // Connect page objects with pages.
983 std::vector
<SdrPageObj
*>::iterator
aPageObjIter (aHandoutPageObjects
.begin());
984 for (std::vector
<sal_uInt16
>::const_iterator
985 iPageIndex(maPageIndices
.begin()),
986 iEnd(maPageIndices
.end());
987 iPageIndex
!=iEnd
&& aPageObjIter
!=aHandoutPageObjects
.end();
990 // Check if the page still exists.
991 if (*iPageIndex
>= rDocument
.GetSdPageCount(PageKind::Standard
))
994 SdrPageObj
* pPageObj
= *aPageObjIter
++;
995 pPageObj
->SetReferencedPage(rDocument
.GetSdPage(*iPageIndex
, PageKind::Standard
));
998 // if there are more page objects than pages left, set the rest to invisible
999 int nHangoverCount
= 0;
1000 while (aPageObjIter
!= aHandoutPageObjects
.end())
1002 (*aPageObjIter
++)->SetReferencedPage(nullptr);
1006 // Hide outlines for objects that have pages attached.
1007 if (nHangoverCount
> 0)
1009 int nSkip
= aHandoutPageObjects
.size() - nHangoverCount
;
1011 while (aShapeIter
.IsMore())
1013 SdrPathObj
* pPathObj
= dynamic_cast<SdrPathObj
*>(aShapeIter
.Next());
1019 pPathObj
->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE
));
1024 if( xHandoutPage
.is() ) try
1026 xHandoutPage
->setPropertyValue( sPageNumber
, Any( static_cast<sal_Int16
>(mnHandoutPageIndex
) ) );
1031 rViewShell
.SetPrintedHandoutPageNum( mnHandoutPageIndex
+ 1 );
1033 rPrinter
.SetMapMode(maMap
);
1046 maPageStringOffset
);
1048 if( xHandoutPage
.is() ) try
1050 xHandoutPage
->setPropertyValue( sPageNumber
, Any( static_cast<sal_Int16
>(0) ) );
1055 rViewShell
.SetPrintedHandoutPageNum(1);
1057 // Restore outlines.
1058 if (nHangoverCount
> 0)
1061 while (aShapeIter
.IsMore())
1063 SdrPathObj
* pPathObj
= dynamic_cast<SdrPathObj
*>(aShapeIter
.Next());
1064 if (pPathObj
!= nullptr)
1065 pPathObj
->SetMergedItem(XLineStyleItem(drawing::LineStyle_SOLID
));
1072 const sal_uInt16 mnHandoutPageIndex
;
1073 const std::vector
<sal_uInt16
> maPageIndices
;
1076 /** The outline information (title, subtitle, outline objects) of the
1077 document. There is no fixed mapping of slides to printer pages.
1079 class OutlinerPrinterPage
: public PrinterPage
1082 OutlinerPrinterPage (
1083 std::optional
<OutlinerParaObject
> pParaObject
,
1084 const MapMode
& rMapMode
,
1085 const OUString
& rsPageString
,
1086 const Point
& rPageStringOffset
,
1087 const DrawModeFlags nDrawMode
,
1088 const Orientation eOrientation
,
1089 const sal_uInt16 nPaperTray
)
1090 : PrinterPage(PageKind::Handout
, rMapMode
, false, rsPageString
,
1091 rPageStringOffset
, nDrawMode
, eOrientation
, nPaperTray
),
1092 mpParaObject(std::move(pParaObject
))
1096 virtual void Print (
1098 SdDrawDocument
& rDocument
,
1102 const SdrLayerIDSet
&,
1103 const SdrLayerIDSet
&) const override
1105 // Set up the printer.
1106 rPrinter
.SetMapMode(maMap
);
1108 // Get and set up the outliner.
1109 const ::tools::Rectangle
aOutRect (rPrinter
.GetPageOffset(), rPrinter
.GetOutputSize());
1110 Outliner
* pOutliner
= rDocument
.GetInternalOutliner();
1111 const OutlinerMode
nSavedOutlMode (pOutliner
->GetOutlinerMode());
1112 const bool bSavedUpdateMode (pOutliner
->IsUpdateLayout());
1113 const Size
aSavedPaperSize (pOutliner
->GetPaperSize());
1115 pOutliner
->Init(OutlinerMode::OutlineView
);
1116 pOutliner
->SetPaperSize(aOutRect
.GetSize());
1117 pOutliner
->SetUpdateLayout(true);
1119 pOutliner
->SetText(*mpParaObject
);
1121 pOutliner
->Draw(rPrinter
, aOutRect
);
1126 maPageStringOffset
);
1128 // Restore outliner and printer.
1130 pOutliner
->SetUpdateLayout(bSavedUpdateMode
);
1131 pOutliner
->SetPaperSize(aSavedPaperSize
);
1132 pOutliner
->Init(nSavedOutlMode
);
1136 std::optional
<OutlinerParaObject
> mpParaObject
;
1140 //===== DocumentRenderer::Implementation ======================================
1142 class DocumentRenderer::Implementation
1143 : public SfxListener
,
1144 public vcl::PrinterOptionsHelper
1147 explicit Implementation (ViewShellBase
& rBase
)
1148 : mxObjectShell(rBase
.GetDocShell())
1150 , mbIsDisposed(false)
1151 , mpPrinter(nullptr)
1152 , mbHasOrientationWarningBeenShown(false)
1154 DialogCreator
aCreator( mrBase
, mrBase
.GetDocShell()->GetDocumentType() == DocumentType::Impress
, GetCurrentPageIndex() );
1155 m_aUIProperties
= aCreator
.GetDialogControls();
1156 maSlidesPerPage
= aCreator
.GetSlidesPerPage();
1158 StartListening(mrBase
);
1161 virtual ~Implementation() override
1163 EndListening(mrBase
);
1166 virtual void Notify (SfxBroadcaster
& rBroadcaster
, const SfxHint
& rHint
) override
1168 if (&rBroadcaster
!= &static_cast<SfxBroadcaster
&>(mrBase
))
1171 if (rHint
.GetId() == SfxHintId::Dying
)
1173 mbIsDisposed
= true;
1177 /** Process the sequence of properties given to one of the XRenderable
1180 void ProcessProperties (const css::uno::Sequence
<css::beans::PropertyValue
>& rOptions
)
1182 OSL_ASSERT(!mbIsDisposed
);
1186 bool bIsValueChanged
= processProperties( rOptions
);
1187 bool bIsPaperChanged
= false;
1189 // The RenderDevice property is handled specially: its value is
1190 // stored in mpPrinter instead of being retrieved on demand.
1191 Any
aDev( getValue( "RenderDevice" ) );
1192 Reference
<awt::XDevice
> xRenderDevice
;
1194 if (aDev
>>= xRenderDevice
)
1196 VCLXDevice
* pDevice
= dynamic_cast<VCLXDevice
*>(xRenderDevice
.get());
1197 VclPtr
< OutputDevice
> pOut
= pDevice
? pDevice
->GetOutputDevice()
1198 : VclPtr
< OutputDevice
>();
1199 mpPrinter
= dynamic_cast<Printer
*>(pOut
.get());
1200 Size aPageSizePixel
= mpPrinter
? mpPrinter
->GetPaperSizePixel() : Size();
1201 if( aPageSizePixel
!= maPrinterPageSizePixel
)
1203 bIsPaperChanged
= true;
1204 maPrinterPageSizePixel
= aPageSizePixel
;
1208 if (bIsValueChanged
&& ! mpOptions
)
1209 mpOptions
.reset(new PrintOptions(*this, std::vector(maSlidesPerPage
)));
1210 if( bIsValueChanged
|| bIsPaperChanged
)
1214 /** Return the number of pages that are to be printed.
1216 sal_Int32
GetPrintPageCount() const
1218 OSL_ASSERT(!mbIsDisposed
);
1222 return maPrinterPages
.size();
1225 /** Return a sequence of properties that can be returned by the
1226 XRenderable::getRenderer() method.
1228 css::uno::Sequence
<css::beans::PropertyValue
> GetProperties () const
1230 css::uno::Sequence
<css::beans::PropertyValue
> aProperties
{
1231 comphelper::makePropertyValue("ExtraPrintUIOptions",
1232 comphelper::containerToSequence(m_aUIProperties
)),
1233 comphelper::makePropertyValue("PageSize", maPrintSize
),
1234 // FIXME: is this always true ?
1235 comphelper::makePropertyValue("PageIncludesNonprintableArea", true)
1241 /** Print one of the prepared pages.
1243 void PrintPage (const sal_Int32 nIndex
)
1245 OSL_ASSERT(!mbIsDisposed
);
1249 Printer
& rPrinter (*mpPrinter
);
1251 std::shared_ptr
<ViewShell
> pViewShell (mrBase
.GetMainViewShell());
1255 SdDrawDocument
* pDocument
= pViewShell
->GetDoc();
1256 OSL_ASSERT(pDocument
!=nullptr);
1258 std::shared_ptr
<DrawViewShell
> pDrawViewShell(
1259 std::dynamic_pointer_cast
<DrawViewShell
>(mrBase
.GetMainViewShell()));
1262 mpPrintView
.reset(new DrawView(mrBase
.GetDocShell(), &rPrinter
, nullptr));
1264 if (nIndex
<0 || sal::static_int_cast
<sal_uInt32
>(nIndex
)>=maPrinterPages
.size())
1267 const std::shared_ptr
<PrinterPage
> pPage (maPrinterPages
[nIndex
]);
1272 const Orientation
eSavedOrientation (rPrinter
.GetOrientation());
1273 const DrawModeFlags
nSavedDrawMode (rPrinter
.GetDrawMode());
1274 const MapMode
aSavedMapMode (rPrinter
.GetMapMode());
1275 const sal_uInt16
nSavedPaperBin (rPrinter
.GetPaperBin());
1277 // Set page orientation.
1278 if ( ! rPrinter
.SetOrientation(pPage
->GetOrientation()))
1280 if ( ! mbHasOrientationWarningBeenShown
1281 && mpOptions
->IsWarningOrientation())
1283 mbHasOrientationWarningBeenShown
= true;
1284 // Show warning that the orientation could not be set.
1285 std::unique_ptr
<weld::MessageDialog
> xWarn(Application::CreateMessageDialog(
1286 pViewShell
->GetFrameWeld(), VclMessageType::Warning
, VclButtonsType::OkCancel
,
1287 SdResId(STR_WARN_PRINTFORMAT_FAILURE
)));
1288 xWarn
->set_default_response(RET_CANCEL
);
1289 if (xWarn
->run() != RET_OK
)
1294 // Set the draw mode.
1295 rPrinter
.SetDrawMode(pPage
->GetDrawMode());
1298 rPrinter
.SetPaperBin(pPage
->GetPaperTray());
1300 // Print the actual page.
1305 pDrawViewShell
? pDrawViewShell
->GetView() : nullptr,
1307 pViewShell
->GetFrameView()->GetVisibleLayers(),
1308 pViewShell
->GetFrameView()->GetPrintableLayers());
1310 rPrinter
.SetOrientation(eSavedOrientation
);
1311 rPrinter
.SetDrawMode(nSavedDrawMode
);
1312 rPrinter
.SetMapMode(aSavedMapMode
);
1313 rPrinter
.SetPaperBin(nSavedPaperBin
);
1317 // rhbz#657394: keep the document alive: prevents crash when
1318 SfxObjectShellRef mxObjectShell
; // destroying mpPrintView
1319 ViewShellBase
& mrBase
;
1321 VclPtr
<Printer
> mpPrinter
;
1322 Size maPrinterPageSizePixel
;
1323 std::unique_ptr
<PrintOptions
> mpOptions
;
1324 std::vector
< std::shared_ptr
< ::sd::PrinterPage
> > maPrinterPages
;
1325 std::unique_ptr
<DrawView
> mpPrintView
;
1326 bool mbHasOrientationWarningBeenShown
;
1327 std::vector
<sal_Int32
> maSlidesPerPage
;
1328 awt::Size maPrintSize
;
1330 sal_Int32
GetCurrentPageIndex() const
1332 const ViewShell
*pShell
= mrBase
.GetMainViewShell().get();
1333 const SdPage
*pCurrentPage
= pShell
? pShell
->getCurrentPage() : nullptr;
1334 return pCurrentPage
? (pCurrentPage
->GetPageNum()-1)/2 : -1;
1337 /** Determine and set the paper orientation.
1339 void SetupPaperOrientation (
1340 const PageKind ePageKind
,
1343 SdDrawDocument
* pDocument
= mrBase
.GetMainViewShell()->GetDoc();
1344 rInfo
.meOrientation
= Orientation::Portrait
;
1346 if( ! mpOptions
->IsBooklet())
1348 rInfo
.meOrientation
= pDocument
->GetSdPage(0, ePageKind
)->GetOrientation();
1350 else if (rInfo
.maPageSize
.Width() < rInfo
.maPageSize
.Height())
1351 rInfo
.meOrientation
= Orientation::Landscape
;
1353 // Draw and Notes should usually abide by their specified paper size
1355 if (!mpOptions
->IsPrinterPreferred(pDocument
->GetDocumentType()))
1357 aPaperSize
.setWidth(rInfo
.maPageSize
.Width());
1358 aPaperSize
.setHeight(rInfo
.maPageSize
.Height());
1362 aPaperSize
.setWidth(rInfo
.mpPrinter
->GetPaperSize().Width());
1363 aPaperSize
.setHeight(rInfo
.mpPrinter
->GetPaperSize().Height());
1366 maPrintSize
= awt::Size(aPaperSize
.Width(), aPaperSize
.Height());
1368 if (mpOptions
->IsPrinterPreferred(pDocument
->GetDocumentType()))
1370 if( (rInfo
.meOrientation
== Orientation::Landscape
&&
1371 (aPaperSize
.Width() < aPaperSize
.Height()))
1373 (rInfo
.meOrientation
== Orientation::Portrait
&&
1374 (aPaperSize
.Width() > aPaperSize
.Height()))
1377 maPrintSize
= awt::Size(aPaperSize
.Height(), aPaperSize
.Width());
1382 /** Top most method for preparing printer pages. In this and the other
1383 Prepare... methods the various special cases are detected and
1385 For every page that is to be printed (that may contain several
1386 slides) one PrinterPage object is created and inserted into
1391 mpPrintView
.reset();
1392 maPrinterPages
.clear();
1393 mbHasOrientationWarningBeenShown
= false;
1395 ViewShell
* pShell
= mrBase
.GetMainViewShell().get();
1397 PrintInfo
aInfo (mpPrinter
, mpOptions
->IsPrintMarkedOnly());
1399 if (aInfo
.mpPrinter
==nullptr || pShell
==nullptr)
1402 MapMode
aMap (aInfo
.mpPrinter
->GetMapMode());
1403 aMap
.SetMapUnit(MapUnit::Map100thMM
);
1405 mpPrinter
->SetMapMode(aMap
);
1407 ::Outliner
& rOutliner
= mrBase
.GetDocument()->GetDrawOutliner();
1408 const EEControlBits
nSavedControlWord (rOutliner
.GetControlWord());
1409 EEControlBits nCntrl
= nSavedControlWord
;
1410 nCntrl
&= ~EEControlBits::MARKFIELDS
;
1411 nCntrl
&= ~EEControlBits::ONLINESPELLING
;
1412 rOutliner
.SetControlWord( nCntrl
);
1414 // When in outline view then apply all pending changes to the model.
1415 if( auto pOutlineViewShell
= dynamic_cast< OutlineViewShell
*>( pShell
) )
1416 pOutlineViewShell
->PrepareClose (false);
1418 // Collect some frequently used data.
1419 if (mpOptions
->IsDate())
1421 aInfo
.msTimeDate
+= GetSdrGlobalData().GetLocaleData().getDate( Date( Date::SYSTEM
) );
1422 aInfo
.msTimeDate
+= " ";
1425 if (mpOptions
->IsTime())
1426 aInfo
.msTimeDate
+= GetSdrGlobalData().GetLocaleData().getTime( ::tools::Time( ::tools::Time::SYSTEM
), false );
1428 // Draw and Notes should usually use specified paper size when printing
1429 if (!mpOptions
->IsPrinterPreferred(mrBase
.GetDocShell()->GetDocumentType()))
1431 aInfo
.maPrintSize
= mrBase
.GetDocument()->GetSdPage(0, PageKind::Standard
)->GetSize();
1432 maPrintSize
= awt::Size(aInfo
.maPrintSize
.Width(),
1433 aInfo
.maPrintSize
.Height());
1437 aInfo
.maPrintSize
= aInfo
.mpPrinter
->GetOutputSize();
1438 maPrintSize
= awt::Size(
1439 aInfo
.mpPrinter
->GetPaperSize().Width(),
1440 aInfo
.mpPrinter
->GetPaperSize().Height());
1443 switch (mpOptions
->GetOutputQuality())
1445 case 1: // Grayscale
1446 aInfo
.mnDrawMode
= DrawModeFlags::GrayLine
| DrawModeFlags::GrayFill
1447 | DrawModeFlags::GrayText
| DrawModeFlags::GrayBitmap
1448 | DrawModeFlags::GrayGradient
;
1451 case 2: // Black & White
1452 aInfo
.mnDrawMode
= DrawModeFlags::BlackLine
| DrawModeFlags::WhiteFill
1453 | DrawModeFlags::BlackText
| DrawModeFlags::GrayBitmap
1454 | DrawModeFlags::WhiteGradient
;
1458 aInfo
.mnDrawMode
= DrawModeFlags::Default
;
1461 if (mpOptions
->IsDraw())
1462 PrepareStdOrNotes(PageKind::Standard
, aInfo
);
1463 if (mpOptions
->IsNotes())
1464 PrepareStdOrNotes(PageKind::Notes
, aInfo
);
1465 if (mpOptions
->IsHandout())
1467 InitHandoutTemplate();
1468 PrepareHandout(aInfo
);
1470 if (mpOptions
->IsOutline())
1471 PrepareOutline(aInfo
);
1473 rOutliner
.SetControlWord(nSavedControlWord
);
1476 /** Create the page objects of the handout template. When the actual
1477 printing takes place then the page objects are assigned different
1478 sets of slides for each printed page (see HandoutPrinterPage::Print).
1480 void InitHandoutTemplate()
1482 const sal_Int32
nSlidesPerHandout (mpOptions
->GetHandoutPageCount());
1483 const bool bHandoutHorizontal (mpOptions
->IsHandoutHorizontal());
1485 AutoLayout eLayout
= AUTOLAYOUT_HANDOUT6
;
1486 switch (nSlidesPerHandout
)
1488 case 0: eLayout
= AUTOLAYOUT_NONE
; break; // AUTOLAYOUT_HANDOUT1; break;
1489 case 1: eLayout
= AUTOLAYOUT_HANDOUT1
; break;
1490 case 2: eLayout
= AUTOLAYOUT_HANDOUT2
; break;
1491 case 3: eLayout
= AUTOLAYOUT_HANDOUT3
; break;
1492 case 4: eLayout
= AUTOLAYOUT_HANDOUT4
; break;
1494 case 6: eLayout
= AUTOLAYOUT_HANDOUT6
; break;
1495 case 9: eLayout
= AUTOLAYOUT_HANDOUT9
; break;
1498 if( !mrBase
.GetDocument() )
1501 SdDrawDocument
& rModel
= *mrBase
.GetDocument();
1503 // first, prepare handout page (not handout master)
1505 SdPage
* pHandout
= rModel
.GetSdPage(0, PageKind::Handout
);
1509 // delete all previous shapes from handout page
1510 while( pHandout
->GetObjCount() )
1511 pHandout
->NbcRemoveObject(0);
1513 const bool bDrawLines (eLayout
== AUTOLAYOUT_HANDOUT3
);
1515 std::vector
< ::tools::Rectangle
> aAreas
;
1516 SdPage::CalculateHandoutAreas( rModel
, eLayout
, bHandoutHorizontal
, aAreas
);
1518 std::vector
< ::tools::Rectangle
>::iterator
iter( aAreas
.begin() );
1519 while( iter
!= aAreas
.end() )
1521 pHandout
->NbcInsertObject(
1526 if( bDrawLines
&& (iter
!= aAreas
.end()) )
1528 ::tools::Rectangle
aRect( *iter
++ );
1530 basegfx::B2DPolygon aPoly
;
1531 aPoly
.insert(0, basegfx::B2DPoint( aRect
.Left(), aRect
.Top() ) );
1532 aPoly
.insert(1, basegfx::B2DPoint( aRect
.Right(), aRect
.Top() ) );
1534 basegfx::B2DHomMatrix aMatrix
;
1535 aMatrix
.translate( 0.0, static_cast< double >( aRect
.GetHeight() / 7 ) );
1537 basegfx::B2DPolyPolygon aPathPoly
;
1538 for( sal_uInt16 nLine
= 0; nLine
< 7; nLine
++ )
1540 aPoly
.transform( aMatrix
);
1541 aPathPoly
.append( aPoly
);
1544 rtl::Reference
<SdrPathObj
> pPathObj
= new SdrPathObj(
1546 SdrObjKind::PathLine
,
1547 std::move(aPathPoly
));
1548 pPathObj
->SetMergedItem(XLineStyleItem(drawing::LineStyle_SOLID
));
1549 pPathObj
->SetMergedItem(XLineColorItem(OUString(), COL_BLACK
));
1551 pHandout
->NbcInsertObject( pPathObj
.get() );
1556 /** Detect whether the specified slide is to be printed.
1558 When the slide is not to be printed then <NULL/> is returned.
1559 Otherwise a pointer to the slide is returned.
1561 SdPage
* GetFilteredPage (
1562 const sal_Int32 nPageIndex
,
1563 const PageKind ePageKind
) const
1565 OSL_ASSERT(mrBase
.GetDocument() != nullptr);
1566 OSL_ASSERT(nPageIndex
>=0);
1567 SdPage
* pPage
= mrBase
.GetDocument()->GetSdPage(
1568 sal::static_int_cast
<sal_uInt16
>(nPageIndex
),
1570 if (pPage
== nullptr)
1572 if ( ! pPage
->IsExcluded() || mpOptions
->IsPrintExcluded())
1578 /** Prepare the outline of the document for printing. There is no fixed
1579 number of slides whose outline data is put onto one printer page.
1580 If the current printer page has enough room for the outline of the
1581 current slide then that is added. Otherwise a new printer page is
1584 void PrepareOutline (PrintInfo
const & rInfo
)
1586 MapMode
aMap (rInfo
.maMap
);
1587 Point
aPageOfs (rInfo
.mpPrinter
->GetPageOffset() );
1588 aMap
.SetScaleX(Fraction(1,2));
1589 aMap
.SetScaleY(Fraction(1,2));
1590 mpPrinter
->SetMapMode(aMap
);
1592 ::tools::Rectangle
aOutRect(aPageOfs
, rInfo
.mpPrinter
->GetOutputSize());
1593 if( aOutRect
.GetWidth() > aOutRect
.GetHeight() )
1595 Size
aPaperSize( rInfo
.mpPrinter
->PixelToLogic( rInfo
.mpPrinter
->GetPaperSizePixel(), MapMode( MapUnit::Map100thMM
) ) );
1596 maPrintSize
.Width
= aPaperSize
.Height();
1597 maPrintSize
.Height
= aPaperSize
.Width();
1598 const auto nRotatedWidth
= aOutRect
.GetHeight();
1599 const auto nRotatedHeight
= aOutRect
.GetWidth();
1600 const auto nRotatedX
= aPageOfs
.Y();
1601 const auto nRotatedY
= aPageOfs
.X();
1602 aOutRect
= ::tools::Rectangle(Point( nRotatedX
, nRotatedY
),
1603 Size(nRotatedWidth
, nRotatedHeight
));
1606 Outliner
* pOutliner
= mrBase
.GetDocument()->GetInternalOutliner();
1607 pOutliner
->Init(OutlinerMode::OutlineView
);
1608 const OutlinerMode
nSavedOutlMode (pOutliner
->GetOutlinerMode());
1609 const bool bSavedUpdateMode (pOutliner
->IsUpdateLayout());
1610 const Size
aSavedPaperSize (pOutliner
->GetPaperSize());
1611 const MapMode
aSavedMapMode (pOutliner
->GetRefMapMode());
1612 pOutliner
->SetPaperSize(aOutRect
.GetSize());
1613 pOutliner
->SetUpdateLayout(true);
1615 ::tools::Long nPageH
= aOutRect
.GetHeight();
1617 std::vector
< sal_Int32
> aPages
;
1618 sal_Int32 nPageCount
= mrBase
.GetDocument()->GetSdPageCount(PageKind::Standard
);
1619 StringRangeEnumerator::getRangesFromString(
1620 mpOptions
->GetPrinterSelection(nPageCount
, GetCurrentPageIndex()),
1621 aPages
, 0, nPageCount
-1);
1623 for (size_t nIndex
= 0, nCount
= aPages
.size(); nIndex
< nCount
;)
1627 Paragraph
* pPara
= nullptr;
1628 ::tools::Long
nH (0);
1629 while (nH
< nPageH
&& nIndex
<nCount
)
1631 SdPage
* pPage
= GetFilteredPage(aPages
[nIndex
], PageKind::Standard
);
1633 if (pPage
== nullptr)
1636 SdrTextObj
* pTextObj
= nullptr;
1639 while (pTextObj
==nullptr && nObj
< pPage
->GetObjCount())
1641 SdrObject
* pObj
= pPage
->GetObj(nObj
++);
1642 if (pObj
->GetObjInventor() == SdrInventor::Default
1643 && pObj
->GetObjIdentifier() == SdrObjKind::TitleText
)
1645 pTextObj
= DynCastSdrTextObj(pObj
);
1649 pPara
= pOutliner
->GetParagraph(pOutliner
->GetParagraphCount() - 1);
1651 if (pTextObj
!=nullptr
1652 && !pTextObj
->IsEmptyPresObj()
1653 && pTextObj
->GetOutlinerParaObject())
1655 pOutliner
->AddText(*(pTextObj
->GetOutlinerParaObject()));
1658 pOutliner
->Insert(OUString());
1663 while (pTextObj
==nullptr && nObj
<pPage
->GetObjCount())
1665 SdrObject
* pObj
= pPage
->GetObj(nObj
++);
1666 if (pObj
->GetObjInventor() == SdrInventor::Default
1667 && pObj
->GetObjIdentifier() == SdrObjKind::OutlineText
)
1669 pTextObj
= DynCastSdrTextObj(pObj
);
1673 bool bSubTitle (false);
1677 pTextObj
= DynCastSdrTextObj(pPage
->GetPresObj(PresObjKind::Text
)); // is there a subtitle?
1680 sal_Int32 nParaCount1
= pOutliner
->GetParagraphCount();
1682 if (pTextObj
!=nullptr
1683 && !pTextObj
->IsEmptyPresObj()
1684 && pTextObj
->GetOutlinerParaObject())
1686 pOutliner
->AddText(*(pTextObj
->GetOutlinerParaObject()));
1691 const sal_Int32
nParaCount2 (pOutliner
->GetParagraphCount());
1692 for (sal_Int32 nPara
=nParaCount1
; nPara
<nParaCount2
; ++nPara
)
1694 Paragraph
* pP
= pOutliner
->GetParagraph(nPara
);
1695 if (pP
!=nullptr && pOutliner
->GetDepth(nPara
) > 0)
1696 pOutliner
->SetDepth(pP
, 0);
1700 nH
= pOutliner
->GetTextHeight();
1703 // Remove the last paragraph when that does not fit completely on
1704 // the current page.
1705 if (nH
> nPageH
&& pPara
!=nullptr)
1707 sal_Int32 nCnt
= pOutliner
->GetAbsPos(
1708 pOutliner
->GetParagraph( pOutliner
->GetParagraphCount() - 1 ) );
1709 sal_Int32 nParaPos
= pOutliner
->GetAbsPos( pPara
);
1711 pPara
= pOutliner
->GetParagraph( ++nParaPos
);
1712 if ( nCnt
&& pPara
)
1714 pOutliner
->Remove(pPara
, nCnt
);
1719 if ( CheckForFrontBackPages( nIndex
) )
1721 maPrinterPages
.push_back(
1722 std::make_shared
<OutlinerPrinterPage
>(
1723 pOutliner
->CreateParaObject(),
1728 rInfo
.meOrientation
,
1729 rInfo
.mpPrinter
->GetPaperBin()));
1733 pOutliner
->SetRefMapMode(aSavedMapMode
);
1734 pOutliner
->SetUpdateLayout(bSavedUpdateMode
);
1735 pOutliner
->SetPaperSize(aSavedPaperSize
);
1736 pOutliner
->Init(nSavedOutlMode
);
1739 /** Prepare handout pages for slides that are to be printed.
1741 void PrepareHandout (PrintInfo
& rInfo
)
1743 SdDrawDocument
* pDocument
= mrBase
.GetDocument();
1744 OSL_ASSERT(pDocument
!= nullptr);
1745 SdPage
& rHandoutPage (*pDocument
->GetSdPage(0, PageKind::Handout
));
1747 const bool bScalePage (mpOptions
->IsPageSize());
1749 sal_uInt16 nPaperBin
;
1750 if ( ! mpOptions
->IsPaperBin())
1751 nPaperBin
= rHandoutPage
.GetPaperBin();
1753 nPaperBin
= rInfo
.mpPrinter
->GetPaperBin();
1755 // Change orientation?
1756 SdPage
& rMaster (dynamic_cast<SdPage
&>(rHandoutPage
.TRG_GetMasterPage()));
1757 rInfo
.meOrientation
= rMaster
.GetOrientation();
1759 const Size
aPaperSize (rInfo
.mpPrinter
->GetPaperSize());
1760 if( (rInfo
.meOrientation
== Orientation::Landscape
&&
1761 (aPaperSize
.Width() < aPaperSize
.Height()))
1763 (rInfo
.meOrientation
== Orientation::Portrait
&&
1764 (aPaperSize
.Width() > aPaperSize
.Height()))
1767 maPrintSize
= awt::Size(aPaperSize
.Height(), aPaperSize
.Width());
1771 maPrintSize
= awt::Size(aPaperSize
.Width(), aPaperSize
.Height());
1774 MapMode
aMap (rInfo
.maMap
);
1775 const Point
aPageOfs (rInfo
.mpPrinter
->GetPageOffset());
1779 const Size
aPageSize (rHandoutPage
.GetSize());
1780 const Size
aPrintSize (rInfo
.mpPrinter
->GetOutputSize());
1782 const double fHorz
= static_cast<double>(aPrintSize
.Width()) / aPageSize
.Width();
1783 const double fVert
= static_cast<double>(aPrintSize
.Height()) / aPageSize
.Height();
1786 if ( fHorz
< fVert
)
1787 aFract
= Fraction(aPrintSize
.Width(), aPageSize
.Width());
1789 aFract
= Fraction(aPrintSize
.Height(), aPageSize
.Height());
1791 aMap
.SetScaleX(aFract
);
1792 aMap
.SetScaleY(aFract
);
1793 aMap
.SetOrigin(Point());
1796 std::shared_ptr
<ViewShell
> pViewShell (mrBase
.GetMainViewShell());
1797 pViewShell
->WriteFrameViewData();
1799 // Count page shapes.
1800 sal_uInt32
nShapeCount (0);
1801 SdrObjListIter
aShapeIter (&rHandoutPage
);
1802 while (aShapeIter
.IsMore())
1804 SdrPageObj
* pPageObj
= dynamic_cast<SdrPageObj
*>(aShapeIter
.Next());
1809 const sal_uInt16 nPageCount
= mrBase
.GetDocument()->GetSdPageCount(PageKind::Standard
);
1810 const sal_uInt16 nHandoutPageCount
= nShapeCount
? (nPageCount
+ nShapeCount
- 1) / nShapeCount
: 0;
1811 pViewShell
->SetPrintedHandoutPageCount( nHandoutPageCount
);
1812 mrBase
.GetDocument()->setHandoutPageCount( nHandoutPageCount
);
1814 // Distribute pages to handout pages.
1815 StringRangeEnumerator
aRangeEnum(
1816 mpOptions
->GetPrinterSelection(nPageCount
, GetCurrentPageIndex()),
1818 std::vector
<sal_uInt16
> aPageIndices
;
1819 sal_uInt16 nPrinterPageIndex
= 0;
1820 StringRangeEnumerator::Iterator it
= aRangeEnum
.begin(), itEnd
= aRangeEnum
.end();
1821 bool bLastLoop
= (it
== itEnd
);
1824 sal_Int32 nPageIndex
= *it
;
1826 bLastLoop
= (it
== itEnd
);
1828 if (GetFilteredPage(nPageIndex
, PageKind::Standard
))
1829 aPageIndices
.push_back(nPageIndex
);
1830 else if (!bLastLoop
)
1833 // Create a printer page when we have found one page for each
1834 // placeholder or when this is the last (and special) loop.
1835 if ( !aPageIndices
.empty() && CheckForFrontBackPages( nPageIndex
)
1836 && (aPageIndices
.size() == nShapeCount
|| bLastLoop
) )
1838 maPrinterPages
.push_back(
1839 std::make_shared
<HandoutPrinterPage
>(
1840 nPrinterPageIndex
++,
1841 std::move(aPageIndices
),
1846 rInfo
.meOrientation
,
1848 aPageIndices
.clear();
1853 /** Prepare the notes pages or regular slides.
1855 void PrepareStdOrNotes (
1856 const PageKind ePageKind
,
1859 OSL_ASSERT(rInfo
.mpPrinter
!= nullptr);
1861 // Fill in page kind specific data.
1862 SdDrawDocument
* pDocument
= mrBase
.GetMainViewShell()->GetDoc();
1863 if (pDocument
->GetSdPageCount(ePageKind
) == 0)
1865 SdPage
* pRefPage
= pDocument
->GetSdPage(0, ePageKind
);
1866 rInfo
.maPageSize
= pRefPage
->GetSize();
1868 SetupPaperOrientation(ePageKind
, rInfo
);
1870 MapMode
aMap (rInfo
.maMap
);
1873 if (mpOptions
->IsBooklet())
1874 PrepareBooklet(ePageKind
, rInfo
);
1876 PrepareRegularPages(ePageKind
, rInfo
);
1879 /** Prepare slides in a non-booklet way: one slide per one to many
1882 void PrepareRegularPages (
1883 const PageKind ePageKind
,
1886 std::shared_ptr
<ViewShell
> pViewShell (mrBase
.GetMainViewShell());
1887 pViewShell
->WriteFrameViewData();
1889 sal_Int32 nPageCount
= mrBase
.GetDocument()->GetSdPageCount(PageKind::Standard
);
1890 StringRangeEnumerator
aRangeEnum(
1891 mpOptions
->GetPrinterSelection(nPageCount
, GetCurrentPageIndex()),
1893 for (StringRangeEnumerator::Iterator
1894 it
= aRangeEnum
.begin(),
1895 itEnd
= aRangeEnum
.end();
1899 SdPage
* pPage
= GetFilteredPage(*it
, ePageKind
);
1900 if (pPage
== nullptr)
1903 MapMode
aMap (rInfo
.maMap
);
1904 // is it possible that the page size changed?
1905 const Size aPageSize
= pPage
->GetSize();
1907 if (mpOptions
->IsPageSize())
1909 const double fHorz (static_cast<double>(rInfo
.maPrintSize
.Width()) / aPageSize
.Width());
1910 const double fVert (static_cast<double>(rInfo
.maPrintSize
.Height()) / aPageSize
.Height());
1914 aFract
= Fraction(rInfo
.maPrintSize
.Width(), aPageSize
.Width());
1916 aFract
= Fraction(rInfo
.maPrintSize
.Height(), aPageSize
.Height());
1918 aMap
.SetScaleX(aFract
);
1919 aMap
.SetScaleY(aFract
);
1920 aMap
.SetOrigin(Point());
1923 if (mpOptions
->IsPrintPageName())
1925 rInfo
.msPageString
= pPage
->GetName() + " ";
1928 rInfo
.msPageString
.clear();
1929 rInfo
.msPageString
+= rInfo
.msTimeDate
;
1931 ::tools::Long aPageWidth
= aPageSize
.Width() - pPage
->GetLeftBorder() - pPage
->GetRightBorder();
1932 ::tools::Long aPageHeight
= aPageSize
.Height() - pPage
->GetUpperBorder() - pPage
->GetLowerBorder();
1933 // Bugfix for 44530:
1934 // if it was implicitly changed (Landscape/Portrait),
1935 // this is considered for tiling, respectively for the splitting up
1937 if( ( rInfo
.maPrintSize
.Width() > rInfo
.maPrintSize
.Height()
1938 && aPageWidth
< aPageHeight
)
1939 || ( rInfo
.maPrintSize
.Width() < rInfo
.maPrintSize
.Height()
1940 && aPageWidth
> aPageHeight
) )
1942 const sal_Int32
nTmp (rInfo
.maPrintSize
.Width());
1943 rInfo
.maPrintSize
.setWidth( rInfo
.maPrintSize
.Height() );
1944 rInfo
.maPrintSize
.setHeight( nTmp
);
1947 if (mpOptions
->IsTilePage()
1948 && aPageWidth
< rInfo
.maPrintSize
.Width()
1949 && aPageHeight
< rInfo
.maPrintSize
.Height())
1951 // Put multiple slides on one printer page.
1952 PrepareTiledPage(*it
, *pPage
, ePageKind
, rInfo
);
1957 PrepareScaledPage(*it
, *pPage
, ePageKind
, rInfo
);
1962 /** Put two slides on one printer page.
1964 void PrepareBooklet (
1965 const PageKind ePageKind
,
1966 const PrintInfo
& rInfo
)
1968 MapMode
aStdMap (rInfo
.maMap
);
1970 Size
aPrintSize_2 (rInfo
.maPrintSize
);
1971 Size
aPageSize_2 (rInfo
.maPageSize
);
1973 if (rInfo
.meOrientation
== Orientation::Landscape
)
1974 aPrintSize_2
.setWidth( aPrintSize_2
.Width() >> 1 );
1976 aPrintSize_2
.setHeight( aPrintSize_2
.Height() >> 1 );
1978 const double fPageWH
= static_cast<double>(aPageSize_2
.Width()) / aPageSize_2
.Height();
1979 const double fPrintWH
= static_cast<double>(aPrintSize_2
.Width()) / aPrintSize_2
.Height();
1981 if( fPageWH
< fPrintWH
)
1983 aPageSize_2
.setWidth( static_cast<::tools::Long
>( aPrintSize_2
.Height() * fPageWH
) );
1984 aPageSize_2
.setHeight( aPrintSize_2
.Height() );
1988 aPageSize_2
.setWidth( aPrintSize_2
.Width() );
1989 aPageSize_2
.setHeight( static_cast<::tools::Long
>( aPrintSize_2
.Width() / fPageWH
) );
1992 MapMode
aMap (rInfo
.maMap
);
1993 aMap
.SetScaleX( Fraction( aPageSize_2
.Width(), rInfo
.maPageSize
.Width() ) );
1994 aMap
.SetScaleY( Fraction( aPageSize_2
.Height(), rInfo
.maPageSize
.Height() ) );
1996 // calculate adjusted print size
1997 const Size
aAdjustedPrintSize (OutputDevice::LogicToLogic(
2002 if (rInfo
.meOrientation
== Orientation::Landscape
)
2004 aOffset
.setX( ( ( aAdjustedPrintSize
.Width() >> 1 ) - rInfo
.maPageSize
.Width() ) >> 1 );
2005 aOffset
.setY( ( aAdjustedPrintSize
.Height() - rInfo
.maPageSize
.Height() ) >> 1 );
2009 aOffset
.setX( ( aAdjustedPrintSize
.Width() - rInfo
.maPageSize
.Width() ) >> 1 );
2010 aOffset
.setY( ( ( aAdjustedPrintSize
.Height() >> 1 ) - rInfo
.maPageSize
.Height() ) >> 1 );
2013 // create vector of pages to print
2014 sal_Int32 nPageCount
= mrBase
.GetDocument()->GetSdPageCount(ePageKind
);
2015 StringRangeEnumerator
aRangeEnum(
2016 mpOptions
->GetPrinterSelection(nPageCount
, GetCurrentPageIndex()),
2018 std::vector
< sal_uInt16
> aPageVector
;
2019 for (StringRangeEnumerator::Iterator
2020 it
= aRangeEnum
.begin(),
2021 itEnd
= aRangeEnum
.end();
2025 SdPage
* pPage
= GetFilteredPage(*it
, ePageKind
);
2026 if (pPage
!= nullptr)
2027 aPageVector
.push_back(*it
);
2030 // create pairs of pages to print on each page
2031 std::vector
< std::pair
< sal_uInt16
, sal_uInt16
> > aPairVector
;
2032 if ( ! aPageVector
.empty())
2034 sal_uInt32 nFirstIndex
= 0, nLastIndex
= aPageVector
.size() - 1;
2036 if( aPageVector
.size() & 1 )
2037 aPairVector
.emplace_back( sal_uInt16(65535), aPageVector
[ nFirstIndex
++ ] );
2039 aPairVector
.emplace_back( aPageVector
[ nLastIndex
-- ], aPageVector
[ nFirstIndex
++ ] );
2041 while( nFirstIndex
< nLastIndex
)
2043 if( nFirstIndex
& 1 )
2044 aPairVector
.emplace_back( aPageVector
[ nFirstIndex
++ ], aPageVector
[ nLastIndex
-- ] );
2046 aPairVector
.emplace_back( aPageVector
[ nLastIndex
-- ], aPageVector
[ nFirstIndex
++ ] );
2052 nCount
=aPairVector
.size();
2056 if ( CheckForFrontBackPages( nIndex
) )
2058 const std::pair
<sal_uInt16
, sal_uInt16
> aPair (aPairVector
[nIndex
]);
2059 Point
aSecondOffset (aOffset
);
2060 if (rInfo
.meOrientation
== Orientation::Landscape
)
2061 aSecondOffset
.AdjustX( aAdjustedPrintSize
.Width() / 2 );
2063 aSecondOffset
.AdjustY( aAdjustedPrintSize
.Height() / 2 );
2064 maPrinterPages
.push_back(
2065 std::make_shared
<BookletPrinterPage
>(
2072 rInfo
.mbPrintMarkedOnly
,
2074 rInfo
.meOrientation
,
2075 rInfo
.mpPrinter
->GetPaperBin()));
2081 /** Print one slide multiple times on one printer page so that the whole
2082 printer page is covered.
2084 void PrepareTiledPage (
2085 const sal_Int32 nPageIndex
,
2086 const SdPage
& rPage
,
2087 const PageKind ePageKind
,
2088 const PrintInfo
& rInfo
)
2090 sal_uInt16 nPaperBin
;
2091 if ( ! mpOptions
->IsPaperBin())
2092 nPaperBin
= rPage
.GetPaperBin();
2094 nPaperBin
= rInfo
.mpPrinter
->GetPaperBin();
2096 if ( !CheckForFrontBackPages( nPageIndex
) )
2099 maPrinterPages
.push_back(
2100 std::make_shared
<TiledPrinterPage
>(
2101 sal::static_int_cast
<sal_uInt16
>(nPageIndex
),
2103 rInfo
.mbPrintMarkedOnly
,
2105 rInfo
.mpPrinter
->GetPageOffset(),
2107 rInfo
.meOrientation
,
2111 /** Print one standard slide or notes page on one to many printer
2112 pages. More than on printer page is used when the slide is larger
2113 than the printable area.
2115 void PrepareScaledPage (
2116 const sal_Int32 nPageIndex
,
2117 const SdPage
& rPage
,
2118 const PageKind ePageKind
,
2119 const PrintInfo
& rInfo
)
2121 const Point
aPageOffset (rInfo
.mpPrinter
->GetPageOffset());
2123 sal_uInt16 nPaperBin
;
2124 if ( ! mpOptions
->IsPaperBin())
2125 nPaperBin
= rPage
.GetPaperBin();
2127 nPaperBin
= rInfo
.mpPrinter
->GetPaperBin();
2129 // For pages larger then the printable area there
2130 // are three options:
2131 // 1. Scale down to the page to the printable area.
2132 // 2. Print only the upper left part of the page
2133 // (without the unprintable borders).
2134 // 3. Split the page into parts of the size of the
2136 const bool bScalePage (mpOptions
->IsPageSize());
2137 const bool bCutPage (mpOptions
->IsCutPage());
2138 MapMode
aMap (rInfo
.maMap
);
2139 if ( (bScalePage
|| bCutPage
) && CheckForFrontBackPages( nPageIndex
) )
2143 // if CutPage is set then do not move it, otherwise move the
2144 // scaled page to printable area
2145 maPrinterPages
.push_back(
2146 std::make_shared
<RegularPrinterPage
>(
2147 sal::static_int_cast
<sal_uInt16
>(nPageIndex
),
2150 rInfo
.mbPrintMarkedOnly
,
2154 rInfo
.meOrientation
,
2159 // Handle 3. Print parts of the page in the size of the
2160 // printable area until the whole page is covered.
2162 // keep the page content at its position if it fits, otherwise
2163 // move it to the printable area
2164 const ::tools::Long
nPageWidth (
2165 rInfo
.maPageSize
.Width() - rPage
.GetLeftBorder() - rPage
.GetRightBorder());
2166 const ::tools::Long
nPageHeight (
2167 rInfo
.maPageSize
.Height() - rPage
.GetUpperBorder() - rPage
.GetLowerBorder());
2169 Point
aOrigin ( 0, 0 );
2171 for (Point aPageOrigin
= aOrigin
;
2172 -aPageOrigin
.Y()<nPageHeight
;
2173 aPageOrigin
.AdjustY( -rInfo
.maPrintSize
.Height() ))
2175 for (aPageOrigin
.setX(aOrigin
.X());
2176 -aPageOrigin
.X()<nPageWidth
;
2177 aPageOrigin
.AdjustX(-rInfo
.maPrintSize
.Width()))
2179 if ( CheckForFrontBackPages( nPageIndex
) )
2181 aMap
.SetOrigin(aPageOrigin
);
2182 maPrinterPages
.push_back(
2183 std::make_shared
<RegularPrinterPage
>(
2184 sal::static_int_cast
<sal_uInt16
>(nPageIndex
),
2187 rInfo
.mbPrintMarkedOnly
,
2191 rInfo
.meOrientation
,
2199 bool CheckForFrontBackPages( sal_Int32 nPage
)
2201 const bool bIsIndexOdd(nPage
& 1);
2202 if ((!bIsIndexOdd
&& mpOptions
->IsPrintFrontPage())
2203 || (bIsIndexOdd
&& mpOptions
->IsPrintBackPage()))
2212 //===== DocumentRenderer ======================================================
2214 DocumentRenderer::DocumentRenderer (ViewShellBase
& rBase
)
2215 : mpImpl(new Implementation(rBase
))
2219 DocumentRenderer::~DocumentRenderer()
2223 //----- XRenderable -----------------------------------------------------------
2225 sal_Int32 SAL_CALL
DocumentRenderer::getRendererCount (
2226 const css::uno::Any
&,
2227 const css::uno::Sequence
<css::beans::PropertyValue
>& rOptions
)
2229 mpImpl
->ProcessProperties(rOptions
);
2230 return mpImpl
->GetPrintPageCount();
2233 Sequence
<beans::PropertyValue
> SAL_CALL
DocumentRenderer::getRenderer (
2235 const css::uno::Any
&,
2236 const css::uno::Sequence
<css::beans::PropertyValue
>& rOptions
)
2238 mpImpl
->ProcessProperties(rOptions
);
2239 return mpImpl
->GetProperties();
2242 void SAL_CALL
DocumentRenderer::render (
2243 sal_Int32 nRenderer
,
2244 const css::uno::Any
&,
2245 const css::uno::Sequence
<css::beans::PropertyValue
>& rOptions
)
2247 mpImpl
->ProcessProperties(rOptions
);
2248 mpImpl
->PrintPage(nRenderer
);
2251 } // end of namespace sd
2253 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */