Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/sd/source/ui/view/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 106 kB image not shown  

Quelle  DocumentRenderer.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <com/sun/star/beans/XPropertySet.hpp>

#include <DocumentRenderer.hxx>
#include <DocumentRenderer.hrc>
#include <ViewShellBase.hxx>

#include <drawdoc.hxx>
#include <sdpage.hxx>
#include <sdresid.hxx>
#include <strings.hrc>
#include <drawview.hxx>
#include <DrawViewShell.hxx>
#include <FrameView.hxx>
#include <Outliner.hxx>
#include <OutlineViewShell.hxx>
#include <SlideSorterViewShell.hxx>
#include <DrawDocShell.hxx>

#include <tools/multisel.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <comphelper/propertyvalue.hxx>
#include <comphelper/sequence.hxx>
#include <rtl/ustrbuf.hxx>
#include <editeng/editstat.hxx>
#include <editeng/eeitem.hxx>
#include <editeng/outlobj.hxx>
#include <editeng/ulspitem.hxx>
#include <svx/sdtfsitm.hxx>
#include <svx/sdooitm.hxx>
#include <svx/svdetc.hxx>
#include <svx/svditer.hxx>
#include <svx/svdopage.hxx>
#include <svx/svdopath.hxx>
#include <svx/svdpagv.hxx>
#include <svx/xlineit0.hxx>
#include <svx/xlnclit.hxx>
#include <toolkit/awt/vclxdevice.hxx>
#include <unotools/localedatawrapper.hxx>
#include <utility>
#include <vcl/print.hxx>
#include <vcl/svapp.hxx>
#include <vcl/weld.hxx>
#include <unotools/moduleoptions.hxx>
#include <xmloff/autolayout.hxx>
#include <sfx2/objsh.hxx>

#include <svl/cjkoptions.hxx>
#include <svl/ctloptions.hxx>

#include <officecfg/Office/Draw.hxx>
#include <officecfg/Office/Impress.hxx>

#include <algorithm>
#include <memory>
#include <vector>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

namespace sd {

namespace {

    void lcl_AdjustPageSize(Size& rPageSize, const Size& rPrintPageSize)
    {
        bool bOrientationDiff = (rPageSize.Width() < rPageSize.Height()
                                 && rPrintPageSize.Width() > rPrintPageSize.Height())
                                || (rPageSize.Width() > rPageSize.Height()
                                    && rPrintPageSize.Width() < rPrintPageSize.Height());
        if (bOrientationDiff)
        {
            ::tools::Long nTmp = rPageSize.Width();
            rPageSize.setWidth(rPageSize.Height());
            rPageSize.setHeight(nTmp);
        }
    }

    /** Convenience class to extract values from the sequence of properties
        given to one of the XRenderable methods.
    */

    class PrintOptions
    {
    public:
        PrintOptions (
            const vcl::PrinterOptionsHelper& rHelper,
            std::vector<sal_Int32>&& rSlidesPerPage)
            : mrProperties(rHelper),
              maSlidesPerPage(std::move(rSlidesPerPage))
        {
        }

        bool IsWarningOrientation() const
        {
            return GetBoolValue(nullptr, true);
        }

        bool IsPrintPageName() const
        {
            return GetBoolValue("IsPrintName"false);
        }

        bool IsDate() const
        {
            return GetBoolValue("IsPrintDateTime"false);
        }

        bool IsTime() const
        {
            return GetBoolValue("IsPrintDateTime"false);
        }

        bool IsHiddenPages() const
        {
            return GetBoolValue("IsPrintHidden"false);
        }

        bool IsHandoutHorizontal() const
        {
            return GetBoolValue("SlidesPerPageOrder", sal_Int32(0));
        }

        sal_Int32 GetHandoutPageCount() const
        {
            sal_uInt32 nIndex = static_cast<sal_Int32>(mrProperties.getIntValue("SlidesPerPage", sal_Int32(0)));
            if (nIndex<maSlidesPerPage.size())
                return maSlidesPerPage[nIndex];
            else if ( ! maSlidesPerPage.empty())
                return maSlidesPerPage[0];
            else
                return 0;
        }

        bool IsDraw() const
        {
            return GetBoolValue("PageContentType", sal_Int32(0));
        }

        bool IsHandout() const
        {
            return GetBoolValue("PageContentType", sal_Int32(1));
        }

        bool IsNotes() const
        {
            return GetBoolValue("PageContentType", sal_Int32(2));
        }

        bool IsOutline() const
        {
            return GetBoolValue("PageContentType", sal_Int32(3));
        }

        sal_uLong GetOutputQuality() const
        {
            sal_Int32 nQuality = static_cast<sal_Int32>(mrProperties.getIntValue( "Quality", sal_Int32(0) ));
            return nQuality;
        }

        bool IsPageSize() const
        {
            return GetBoolValue("PageOptions", sal_Int32(1));
        }

        bool IsTilePage() const
        {
            return GetBoolValue("PageOptions", sal_Int32(2)) || GetBoolValue("PageOptions", sal_Int32(3));
        }

        bool IsCutPage() const
        {
            return GetBoolValue("PageOptions", sal_Int32(0));
        }

        bool IsBooklet() const
        {
            return GetBoolValue("PrintProspect"false);
        }

        bool IsProspectRTL() const
        {
            return mrProperties.getIntValue( "PrintProspectRTL",  0 ) != 0;
        }

        bool IsPrinterPreferred(DocumentType eDocType) const
        {
            bool bIsDraw = eDocType == DocumentType::Draw;
            return IsTilePage() || IsPageSize() || IsBooklet() || (!bIsDraw && !IsNotes());
        }

        bool IsPrintExcluded() const
        {
            return (IsNotes() || IsDraw() || IsHandout()) &&  IsHiddenPages();
        }

        bool IsPrintFrontPage() const
        {
            sal_Int32 nInclude = static_cast<sal_Int32>(mrProperties.getIntValue( "EvenOdd", 0 ));
            return nInclude != 2;
        }

        bool IsPrintBackPage() const
        {
            sal_Int32 nInclude = static_cast<sal_Int32>(mrProperties.getIntValue( "EvenOdd", 0 ));
            return nInclude != 1;
        }

        bool IsPaperBin() const
        {
            return GetBoolValue("PrintPaperFromSetup"false);
        }

        bool IsPrintMarkedOnly() const
        {
            return GetBoolValue("PrintContent", sal_Int32(4));
        }

        OUString GetPrinterSelection (sal_Int32 nPageCount, sal_Int32 nCurrentPageIndex) const
        {
            sal_Int32 nContent = static_cast<sal_Int32>(mrProperties.getIntValue( "PrintContent", 0 ));
            OUString sFullRange = "1-" + OUString::number(nPageCount);

            if (nContent == 0) // all pages/slides
            {
                return sFullRange;
            }

            if (nContent == 1) // range
            {
                OUString sValue = mrProperties.getStringValue("PageRange");
                return sValue.isEmpty() ? sFullRange : sValue;
            }

            if (nContent == 2 && // selection
                nCurrentPageIndex >= 0)
            {
                return OUString::number(nCurrentPageIndex + 1);
            }

            return OUString();
        }

    private:
        const vcl::PrinterOptionsHelper& mrProperties;
        const std::vector<sal_Int32> maSlidesPerPage;

        /** When the value of the property with name pName is a boolean then
            return its value. When the property is unknown then
            bDefaultValue is returned.  Otherwise <FALSE/> is returned.
        */

        bool GetBoolValue (
            const char* pName,
            const bool bDefaultValue) const
        {
            bool bValue = mrProperties.getBoolValue( pName, bDefaultValue );
            return bValue;
        }

        /** Return <TRUE/> when the value of the property with name pName is
            an integer and its value is nTriggerValue. Otherwise <FALSE/> is
            returned.
        */

        bool GetBoolValue (
            const char* pName,
            const sal_Int32 nTriggerValue) const
        {
            sal_Int32 nValue = static_cast<sal_Int32>(mrProperties.getIntValue( pName, 0 ));
            return nValue == nTriggerValue;
        }
    };

    /** A collection of values that helps to reduce the number of arguments
        given to some functions.  Note that not all values are set at the
        same time.
    */

    class PrintInfo
    {
    public:
        PrintInfo (
            Printer* pPrinter,
            const bool bPrintMarkedOnly)
            : mpPrinter(pPrinter),
              mnDrawMode(DrawModeFlags::Default),
              maPrintSize(0,0),
              maPageSize(0,0),
              meOrientation(Orientation::Portrait),
              mbPrintMarkedOnly(bPrintMarkedOnly)
        {}

        const VclPtr<Printer> mpPrinter;
        DrawModeFlags mnDrawMode;
        OUString msTimeDate;
        OUString msPageString;
        Size maPrintSize;
        Size maPageSize;
        Orientation meOrientation;
        MapMode maMap;
        const bool mbPrintMarkedOnly;
    };

    /** Output one page of the document to the given printer.  Note that
        more than one document page may be output to one printer page.
    */

    void PrintPage (
        Printer& rPrinter,
        ::sd::View& rPrintView,
        SdPage& rPage,
        View const * pView,
        const bool bPrintMarkedOnly,
        const SdrLayerIDSet& rVisibleLayers,
        const SdrLayerIDSet& rPrintableLayers)
    {
        rPrintView.ShowSdrPage(&rPage);

        const MapMode aOriginalMapMode (rPrinter.GetMapMode());

        // Set the visible layers
        SdrPageView* pPageView = rPrintView.GetSdrPageView();
        OSL_ASSERT(pPageView!=nullptr);
        pPageView->SetVisibleLayers(rVisibleLayers);
        pPageView->SetPrintableLayers(rPrintableLayers);

        if (pView!=nullptr && bPrintMarkedOnly)
            pView->DrawMarkedObj(rPrinter);
        else
            rPrintView.CompleteRedraw(&rPrinter,
                    vcl::Region(::tools::Rectangle(Point(0,0), rPage.GetSize())));

        rPrinter.SetMapMode(aOriginalMapMode);

        rPrintView.HideSdrPage();
    }

    /** Output a string (that typically is not part of a document page) to
        the given printer.
    */

    void PrintMessage (
        Printer& rPrinter,
        const OUString& rsPageString,
        const Point& rPageStringOffset)
    {
        const vcl::Font aOriginalFont (rPrinter.OutputDevice::GetFont());
        rPrinter.SetFont(vcl::Font(FAMILY_SWISS, Size(0, 423)));
        rPrinter.DrawText(rPageStringOffset, rsPageString);
        rPrinter.SetFont(aOriginalFont);
    }

    /** Read the resources and process then into a sequence of properties
        that can be passed to the printing dialog.
    */

    class DialogCreator
    {
    public:
        DialogCreator (ViewShellBase &rBase, bool bImpress, sal_Int32 nCurPage)
            : mrBase(rBase)
            , mbImpress(bImpress)
            , mnCurPage(nCurPage)
        {
            ProcessResource();
        }

        const std::vector< beans::PropertyValue >& GetDialogControls() const
        {
            return maProperties;
        }

        const std::vector<sal_Int32>& GetSlidesPerPage() const
        {
            return maSlidesPerPage;
        }

    private:
        ViewShellBase &mrBase;
        std::vector<beans::PropertyValue> maProperties;
        std::vector<sal_Int32> maSlidesPerPage;
        bool mbImpress;
        sal_Int32 mnCurPage;

        void ProcessResource()
        {
            // load the impress or draw PrinterOptions into the custom tab
            beans::PropertyValue aOptionsUIFile;
            aOptionsUIFile.Name = "OptionsUIFile";
            if( mbImpress )
                aOptionsUIFile.Value <<= u"modules/simpress/ui/impressprinteroptions.ui"_ustr;
            else
                aOptionsUIFile.Value <<= u"modules/sdraw/ui/drawprinteroptions.ui"_ustr;
            maProperties.push_back(aOptionsUIFile);

            SvtModuleOptions aOpt;
            OUString aAppGroupname(SdResId(STR_IMPRESS_PRINT_UI_GROUP_NAME));
            aAppGroupname = aAppGroupname.replaceFirst("%s", aOpt.GetModuleName(
                mbImpress ? SvtModuleOptions::EModule::IMPRESS : SvtModuleOptions::EModule::DRAW));
            AddDialogControl(vcl::PrinterOptionsHelper::setGroupControlOpt(u"tabcontrol-page2"_ustr, aAppGroupname, u".HelpID:vcl:PrintDialog:TabPage:AppPage"_ustr));

            uno::Sequence< OUString > aHelpIds, aWidgetIds;
            if( mbImpress )
            {
                aHelpIds = { u".HelpID:vcl:PrintDialog:PageContentType:ListBox"_ustr };
                AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt(
                                    u"impressdocument"_ustr,
                                    SdResId(STR_IMPRESS_PRINT_UI_CONTENT),
                                    aHelpIds,
                                    u"PageContentType"_ustr ,
                                    CreateChoice(STR_IMPRESS_PRINT_UI_CONTENT_CHOICES, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_CONTENT_CHOICES)),
                                    0)
                                );

                aHelpIds = { u".HelpID:vcl:PrintDialog:SlidesPerPage:ListBox"_ustr };
                vcl::PrinterOptionsHelper::UIControlOptions aContentOpt( u"PageContentType"_ustr , 1 );
                AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt(
                                    u"slidesperpage"_ustr,
                                    SdResId(STR_IMPRESS_PRINT_UI_SLIDESPERPAGE),
                                    aHelpIds,
                                    u"SlidesPerPage"_ustr ,
                                    GetSlidesPerPageSequence(),
                                    0,
                                    Sequence< sal_Bool >(),
                                    aContentOpt
                                    )
                                );

                aHelpIds = { u".HelpID:vcl:PrintDialog:SlidesPerPageOrder:ListBox"_ustr };
                vcl::PrinterOptionsHelper::UIControlOptions aSlidesPerPageOpt( u"SlidesPerPage"_ustr , -1, true );
                AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt(
                                    u"slidesperpageorder"_ustr,
                                    SdResId(STR_IMPRESS_PRINT_UI_ORDER),
                                    aHelpIds,
                                    u"SlidesPerPageOrder"_ustr ,
                                    CreateChoice(STR_IMPRESS_PRINT_UI_ORDER_CHOICES, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_ORDER_CHOICES)),
                                    0,
                                    Sequence< sal_Bool >(),
                                    aSlidesPerPageOpt )
                                );
            }

            AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt(u"contents"_ustr,
                               SdResId(STR_IMPRESS_PRINT_UI_INCLUDE_CONTENT), u""_ustr ) );

            if( mbImpress )
            {
                AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u"printname"_ustr,
                                    SdResId(STR_IMPRESS_PRINT_UI_IS_PRINT_NAME),
                                    u".HelpID:vcl:PrintDialog:IsPrintName:CheckBox"_ustr ,
                                    u"IsPrintName"_ustr ,
                                    officecfg::Office::Impress::Print::Other::PageName::get()
                                    )
                                );
            }
            else
            {
                AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u"printname"_ustr,
                                    SdResId(STR_DRAW_PRINT_UI_IS_PRINT_NAME),
                                    u".HelpID:vcl:PrintDialog:IsPrintName:CheckBox"_ustr ,
                                    u"IsPrintName"_ustr ,
                                    officecfg::Office::Draw::Print::Other::PageName::get()
                                    )
                                );
            }

            AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u"printdatetime"_ustr,
                                SdResId(STR_IMPRESS_PRINT_UI_IS_PRINT_DATE),
                                u".HelpID:vcl:PrintDialog:IsPrintDateTime:CheckBox"_ustr ,
                                u"IsPrintDateTime"_ustr ,
                                // Separate settings for time and date in Impress/Draw -> Print page, check that both are set
                                mbImpress ?
                                officecfg::Office::Impress::Print::Other::Date::get() &&
                                officecfg::Office::Impress::Print::Other::Time::get() :
                                officecfg::Office::Draw::Print::Other::Date::get() &&
                                officecfg::Office::Draw::Print::Other::Time::get()
                                )
                            );

            if( mbImpress )
            {
                AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u"printhidden"_ustr,
                                    SdResId(STR_IMPRESS_PRINT_UI_IS_PRINT_HIDDEN),
                                    u".HelpID:vcl:PrintDialog:IsPrintHidden:CheckBox"_ustr ,
                                    u"IsPrintHidden"_ustr ,
                                    officecfg::Office::Impress::Print::Other::HiddenPage::get()
                                    )
                                );
            }

            AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt(u"color"_ustr,
                               SdResId(STR_IMPRESS_PRINT_UI_QUALITY), u""_ustr ) );

            aHelpIds = { u".HelpID:vcl:PrintDialog:Quality:RadioButton:0"_ustr,
                         u".HelpID:vcl:PrintDialog:Quality:RadioButton:1"_ustr,
                         u".HelpID:vcl:PrintDialog:Quality:RadioButton:2"_ustr };
            aWidgetIds = { u"originalcolors"_ustr, u"grayscale"_ustr, u"blackandwhite"_ustr };
            AddDialogControl( vcl::PrinterOptionsHelper::setChoiceRadiosControlOpt(
                                aWidgetIds,
                                u""_ustr,
                                aHelpIds,
                                u"Quality"_ustr ,
                                CreateChoice(STR_IMPRESS_PRINT_UI_QUALITY_CHOICES, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_QUALITY_CHOICES)),
                                mbImpress ? officecfg::Office::Impress::Print::Other::Quality::get() :
                                            officecfg::Office::Draw::Print::Other::Quality::get() )

                            );

            AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt(u"pagesizes"_ustr,
                               SdResId(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS), u""_ustr ) );

            aHelpIds = { u".HelpID:vcl:PrintDialog:PageOptions:RadioButton:0"_ustr,
                         u".HelpID:vcl:PrintDialog:PageOptions:RadioButton:1"_ustr,
                         u".HelpID:vcl:PrintDialog:PageOptions:RadioButton:2"_ustr,
                         u".HelpID:vcl:PrintDialog:PageOptions:RadioButton:3"_ustr };
            aWidgetIds = { u"originalsize"_ustr, u"fittoprintable"_ustr, u"distributeonmultiple"_ustr, u"tilesheet"_ustr };

            // Mutually exclusive page options settings are stored in separate config keys...
            // TODO: There is no config key to set the distributeonmultiple option as default
            sal_Int32 nDefaultChoice = 0;
            if ( mbImpress ? officecfg::Office::Impress::Print::Page::PageSize::get() :
                             officecfg::Office::Draw::Print::Page::PageSize::get() )
            {
                nDefaultChoice = 1;
            }
            else if ( mbImpress ? officecfg::Office::Impress::Print::Page::PageTile::get() :
                                  officecfg::Office::Draw::Print::Page::PageTile::get() )
            {
                nDefaultChoice = 3;
            }
            vcl::PrinterOptionsHelper::UIControlOptions aPageOptionsOpt(u"PrintProspect"_ustr, 0);
            AddDialogControl( vcl::PrinterOptionsHelper::setChoiceRadiosControlOpt(
                                aWidgetIds,
                                u""_ustr,
                                aHelpIds,
                                u"PageOptions"_ustr ,
                                mbImpress ? CreateChoice(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES)) :
                                            CreateChoice(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES_DRAW, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES_DRAW)),
                                nDefaultChoice,
                                Sequence< sal_Bool >(),
                                aPageOptionsOpt
                                )
                            );

            vcl::PrinterOptionsHelper::UIControlOptions aBrochureOpt;
            aBrochureOpt.maGroupHint = "LayoutPage" ;
            AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt(u"pagesides"_ustr,
                               SdResId(STR_IMPRESS_PRINT_UI_PAGE_SIDES), u""_ustr,
                               aBrochureOpt ) );

            // brochure printing
            AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u"brochure"_ustr,
                                SdResId(STR_IMPRESS_PRINT_UI_BROCHURE),
                                u".HelpID:vcl:PrintDialog:PrintProspect:CheckBox"_ustr ,
                                u"PrintProspect"_ustr ,
                                mbImpress ? officecfg::Office::Impress::Print::Page::Booklet::get() :
                                            officecfg::Office::Draw::Print::Page::Booklet::get(),
                                aBrochureOpt
                                )
                            );

            // check if either CJK or CTL is enabled
            bool bRTL = SvtCJKOptions::IsCJKFontEnabled() || SvtCTLOptions::IsCTLFontEnabled();

            if(bRTL)
            {
                uno::Sequence< OUString > aBRTLChoices{ SdResId(STR_IMPRESS_PRINT_UI_LEFT_SCRIPT),
                                                        SdResId(STR_IMPRESS_PRINT_UI_RIGHT_SCRIPT) };
                vcl::PrinterOptionsHelper::UIControlOptions
                    aIncludeOpt( u"PrintProspect"_ustr , -1, true );
                aIncludeOpt.maGroupHint =  "LayoutPage" ;
                aHelpIds = { u".HelpID:vcl:PrintDialog:PrintProspectRTL:ListBox"_ustr };
                AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt(
                                u"scriptdirection"_ustr,
                                SdResId(STR_IMPRESS_PRINT_UI_BROCHURE_INCLUDE),
                                aHelpIds,
                                u"PrintProspectRTL"_ustr ,
                                aBRTLChoices,
                                0,
                                Sequence< sal_Bool >(),
                                aIncludeOpt
                                )
                            );
            }
            // paper tray (on options page)
            vcl::PrinterOptionsHelper::UIControlOptions aPaperTrayOpt;
            aPaperTrayOpt.maGroupHint = "OptionsPageOptGroup" ;
            AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u"printpaperfromsetup"_ustr,
                                SdResId(STR_IMPRESS_PRINT_UI_PAPER_TRAY),
                                u".HelpID:vcl:PrintDialog:PrintPaperFromSetup:CheckBox"_ustr ,
                                u"PrintPaperFromSetup"_ustr ,
                                false,
                                aPaperTrayOpt
                                )
                            );
            // print range selection
            vcl::PrinterOptionsHelper::UIControlOptions aPrintRangeOpt;
            aPrintRangeOpt.mbInternalOnly = true;
            aPrintRangeOpt.maGroupHint = "PrintRange" ;
            AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt(u"printrange"_ustr,
                                mbImpress ? SdResId(STR_IMPRESS_PRINT_UI_SLIDE_RANGE) : SdResId(STR_IMPRESS_PRINT_UI_PAGE_RANGE),
                                u""_ustr,
                                aPrintRangeOpt )
                             );

            // check if there is a selection of slides
            OUString aPageRange(OUString::number(mnCurPage + 1));
            int nPrintRange(0);
            using sd::slidesorter::SlideSorterViewShell;
            SlideSorterViewShell* const pSSViewSh(SlideSorterViewShell::GetSlideSorter(mrBase));
            if (pSSViewSh)
            {
                const std::shared_ptr<SlideSorterViewShell::PageSelection> pPageSelection(pSSViewSh->GetPageSelection());
                if (bool(pPageSelection) && pPageSelection->size() > 1)
                {
                    OUStringBuffer aBuf;
                    // TODO: this could be improved by writing ranges instead of consecutive page
                    // numbers if appropriate. Do we have a helper function for that somewhere?
                    bool bFirst(true);
                    for (auto pPage: *pPageSelection)
                    {
                        if (bFirst)
                            bFirst = false;
                        else
                            aBuf.append(',');
                        aBuf.append(static_cast<sal_Int32>(pPage->GetPageNum() / 2 + 1));
                    }
                    aPageRange = aBuf.makeStringAndClear();
                    nPrintRange = 1;
                }
            }
/*
            OUString aPrintRangeName( "PrintContent" );
            aHelpIds.realloc( 1 );
            aHelpIds[0] = ".HelpID:vcl:PrintDialog:PageContentType:ListBox";
            AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt( "printpagesbox", OUString(),
                                aHelpIds, aPrintRangeName,
                                mbImpress ? CreateChoice( STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE ) ) :
                                            CreateChoice( STR_DRAW_PRINT_UI_PAGE_RANGE_CHOICE, SAL_N_ELEMENTS(STR_DRAW_PRINT_UI_PAGE_RANGE_CHOICE ) ),
                                nPrintRange ) );
*/

            OUString aPrintRangeName( u"PrintContent"_ustr );
            aHelpIds = { u".HelpID:vcl:PrintDialog:PrintContent:RadioButton:0"_ustr,
                         u".HelpID:vcl:PrintDialog:PrintContent:RadioButton:1"_ustr,
                         u".HelpID:vcl:PrintDialog:PrintContent:RadioButton:2"_ustr };
            aWidgetIds = { u"rbAllPages"_ustr, u"rbRangePages"_ustr, u"rbRangeSelection"_ustr };

            AddDialogControl( vcl::PrinterOptionsHelper::setChoiceRadiosControlOpt(aWidgetIds, OUString(),
                                aHelpIds, aPrintRangeName,
                                mbImpress ? CreateChoice(STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE)) :
                                            CreateChoice(STR_DRAW_PRINT_UI_PAGE_RANGE_CHOICE, SAL_N_ELEMENTS(STR_DRAW_PRINT_UI_PAGE_RANGE_CHOICE)),
                                nPrintRange )
                            );
            // create an Edit dependent on "Pages" selected
            vcl::PrinterOptionsHelper::UIControlOptions aPageRangeOpt( aPrintRangeName, 1, true );
            AddDialogControl(vcl::PrinterOptionsHelper::setEditControlOpt(u"pagerange"_ustr, u""_ustr,
                                u".HelpID:vcl:PrintDialog:PageRange:Edit"_ustr, u"PageRange"_ustr,
                                aPageRange, aPageRangeOpt));
            vcl::PrinterOptionsHelper::UIControlOptions aEvenOddOpt(aPrintRangeName, -1, true);
            AddDialogControl(vcl::PrinterOptionsHelper::setChoiceListControlOpt(u"evenoddbox"_ustr, u""_ustr,
                                uno::Sequence<OUString>(), u"EvenOdd"_ustr, uno::Sequence<OUString>(),
                                0, uno::Sequence<sal_Bool>(), aEvenOddOpt));
        }

        void AddDialogControl( const Any& i_rCtrl )
        {
            beans::PropertyValue aVal;
            aVal.Value = i_rCtrl;
            maProperties.push_back( aVal );
        }

        static Sequence<OUString> CreateChoice(const TranslateId* pResourceId, size_t nCount)
        {
            Sequence<OUString> aChoices (nCount);
            std::transform(pResourceId, pResourceId + nCount, aChoices.getArray(),
                           [](const auto& id) { return SdResId(id); });
            return aChoices;
        }

        Sequence<OUString> GetSlidesPerPageSequence()
        {
            const Sequence<OUString> aChoice (
                CreateChoice(STR_IMPRESS_PRINT_UI_SLIDESPERPAGE_CHOICES, SAL_N_ELEMENTS(STR_IMPRESS_PRINT_UI_SLIDESPERPAGE_CHOICES)));
            maSlidesPerPage.clear();
            maSlidesPerPage.push_back(0); // first is using the default
            std::transform(std::next(aChoice.begin()), aChoice.end(), std::back_inserter(maSlidesPerPage),
                            [](const OUString& rChoice) -> sal_Int32 { return rChoice.toInt32(); });
            return aChoice;
        }
    };

    /** The Prepare... methods of the DocumentRenderer::Implementation class
        create a set of PrinterPage objects that contain all necessary
        information to do the actual printing.  There is one PrinterPage
        object per printed page.  Derived classes implement the actual, mode
        specific printing.

        This and all derived classes support the asynchronous printing
        process by not storing pointers to any data with lifetime shorter
        than the PrinterPage objects, i.e. slides, shapes, (one of) the
        outliner (of the document).
    */

    class PrinterPage
    {
    public:
        PrinterPage (
            const PageKind ePageKind,
            const MapMode& rMapMode,
            const bool bPrintMarkedOnly,
            OUString sPageString,
            const Point& rPageStringOffset,
            const DrawModeFlags nDrawMode,
            const Orientation eOrientation,
            const sal_uInt16 nPaperTray)
            : mePageKind(ePageKind),
              maMap(rMapMode),
              mbPrintMarkedOnly(bPrintMarkedOnly),
              msPageString(std::move(sPageString)),
              maPageStringOffset(rPageStringOffset),
              mnDrawMode(nDrawMode),
              meOrientation(eOrientation),
              mnPaperTray(nPaperTray)
        {
        }

        virtual ~PrinterPage() {}

        virtual void Print (
            Printer& rPrinter,
            SdDrawDocument& rDocument,
            ViewShell& rViewShell,
            View* pView,
            DrawView& rPrintView,
            const SdrLayerIDSet& rVisibleLayers,
            const SdrLayerIDSet& rPrintableLayers) const = 0;

        DrawModeFlags GetDrawMode() const { return mnDrawMode; }
        Orientation GetOrientation() const { return meOrientation; }
        sal_uInt16 GetPaperTray() const { return mnPaperTray; }

    protected:
        const PageKind mePageKind;
        const MapMode maMap;
        const bool mbPrintMarkedOnly;
        const OUString msPageString;
        const Point maPageStringOffset;
        const DrawModeFlags mnDrawMode;
        const Orientation meOrientation;
        const sal_uInt16 mnPaperTray;
    };

    /** The RegularPrinterPage is used for printing one regular slide (no
        notes, handout, or outline) to one printer page.
    */

    class RegularPrinterPage : public PrinterPage
    {
    public:
        RegularPrinterPage (
            const sal_uInt16 nPageIndex,
            const PageKind ePageKind,
            const MapMode& rMapMode,
            const bool bPrintMarkedOnly,
            const OUString& rsPageString,
            const Point& rPageStringOffset,
            const DrawModeFlags nDrawMode,
            const Orientation eOrientation,
            const sal_uInt16 nPaperTray)
            : PrinterPage(ePageKind, rMapMode, bPrintMarkedOnly, rsPageString,
                rPageStringOffset, nDrawMode, eOrientation, nPaperTray),
              mnPageIndex(nPageIndex)
        {
        }

        virtual void Print (
            Printer& rPrinter,
            SdDrawDocument& rDocument,
            ViewShell&,
            View* pView,
            DrawView& rPrintView,
            const SdrLayerIDSet& rVisibleLayers,
            const SdrLayerIDSet& rPrintableLayers) const override
        {
            SdPage* pPageToPrint = rDocument.GetSdPage(mnPageIndex, mePageKind);
            rPrinter.SetMapMode(maMap);
            PrintPage(
                rPrinter,
                rPrintView,
                *pPageToPrint,
                pView,
                mbPrintMarkedOnly,
                rVisibleLayers,
                rPrintableLayers);
            PrintMessage(
                rPrinter,
                msPageString,
                maPageStringOffset);
        }

    private:
        const sal_uInt16 mnPageIndex;
    };

    /** The NotesPrinterPage is used for printing notes pages onto one or more printer pages
    */

    class NotesPrinterPage : public PrinterPage
    {
    public:
        NotesPrinterPage(
            const sal_uInt16 nPageIndex,
            const sal_Int32 nPageNumb,
            const sal_Int32 nPageCount,
            const bool bScaled,
            const PageKind ePageKind,
            const MapMode& rMapMode,
            const bool bPrintMarkedOnly,
            const OUString& rsPageString,
            const Point& rPageStringOffset,
            const DrawModeFlags nDrawMode,
            const Orientation eOrientation,
            const sal_uInt16 nPaperTray)
            : PrinterPage(ePageKind, rMapMode, bPrintMarkedOnly, rsPageString, rPageStringOffset,
                          nDrawMode, eOrientation, nPaperTray),
              mnPageIndex(nPageIndex),
              mnPageNumb(nPageNumb),
              mnPageCount(nPageCount),
              mbScaled(bScaled)
        {
        }

        virtual void Print(
            Printer& rPrinter,
            SdDrawDocument& rDocument,
            ViewShell&,
            View* pView,
            DrawView& rPrintView,
            const SdrLayerIDSet& rVisibleLayers,
            const SdrLayerIDSet& rPrintableLayers) const override
        {
            SdPage* pPageToPrint = rDocument.GetSdPage(mnPageIndex, mePageKind);
            rPrinter.SetMapMode(maMap);

            // Clone the current page to create an independent instance for modifications.
            // This ensures that changes made to pNotesPage do not affect the original page.
            rtl::Reference<SdPage> pNotesPage
                = static_cast<SdPage*>(pPageToPrint->CloneSdrPage(rDocument).get());

            Size aPageSize;
            if (mbScaled)
            {
                aPageSize = pNotesPage->GetSize();
                lcl_AdjustPageSize(aPageSize, rPrinter.GetPrintPageSize());
            }
            else
                aPageSize = rPrinter.GetPrintPageSize();

            // Adjusts the objects on the notes page to fit the new page size.
            ::tools::Rectangle aNewBorderRect(-1, -1, -1, -1);
            pNotesPage->ScaleObjects(aPageSize, aNewBorderRect, true);

            SdrObject* pNotesObj = pNotesPage->GetPresObj(PresObjKind::Notes);
            if (pNotesObj)
            {
                // new page(s) margins
                sal_Int32 nLeft = aPageSize.Width() * 0.1;
                sal_Int32 nRight = nLeft;
                sal_Int32 nTop = aPageSize.Height() * 0.075;
                sal_Int32 nBottom = nTop;

                Point aNotesPt = pNotesObj->GetRelativePos();
                Size aNotesSize = pNotesObj->GetLogicRect().GetSize();

                Outliner* pOut = rDocument.GetInternalOutliner();
                const OutlinerMode nSaveOutlMode(pOut->GetOutlinerMode());
                const bool bSavedUpdateMode(pOut->IsUpdateLayout());
                pOut->SetPaperSize(aNotesSize);
                pOut->SetUpdateLayout(true);
                pOut->Clear();
                if (OutlinerParaObject* pOutlinerParaObject = pNotesObj->GetOutlinerParaObject())
                    pOut->SetText(*pOutlinerParaObject);

                bool bAutoGrow = pNotesObj->GetMergedItem(SDRATTR_TEXT_AUTOGROWHEIGHT).GetValue();

                // If AutoGrowHeight property is enabled and the notes page has a lower border,
                // use the lower border but if there is no lower border, use the bottom margin
                // to determine the first page break position.
                // If AutoGrow is not enabled, the notes object defines the first page break.
                ::tools::Long nNotesPageBottom
                    = bAutoGrow ? (pNotesPage->GetLowerBorder() != 0)
                                      ? aPageSize.Height() - pNotesPage->GetLowerBorder()
                                      : aPageSize.Height() - nBottom
                                : aNotesPt.Y() + aNotesSize.Height();
                if (mbScaled)
                {
                    sal_Int32 nTextHeight = aNotesPt.Y() + pOut->GetTextHeight();
                    if (bAutoGrow && (nTextHeight > nNotesPageBottom))
                    {
                        pNotesObj->SetMergedItem(SdrOnOffItem(SDRATTR_TEXT_AUTOGROWHEIGHT, false));

                        ::tools::Long nObjW = aNotesSize.Width();
                        ::tools::Long nObjH = aPageSize.Height() - aNotesPt.Y() - nBottom;

                        pNotesObj->SetLogicRect(::tools::Rectangle(aNotesPt, Size(nObjW, nObjH)));
                    }
                    SdrTextFitToSizeTypeItem eFitToSize = drawing::TextFitToSizeType_AUTOFIT;
                    pNotesObj->SetMergedItem(eFitToSize);
                }
                else // original size
                {
                    bool bExit = false;
                    sal_Int32 nPrevLineLen = 0;
                    sal_Int32 nPrevParaIdx = 0;
                    sal_uInt16 nActualPageNumb = 1;
                    sal_uInt16 nPrevParaLowerSpace = 0;
                    ::tools::Long nCurrentPosY = aNotesPt.Y();
                    sal_Int32 nParaCount = pOut->GetParagraphCount();
                    std::vector<std::pair<sal_Int32, sal_Int32>> aPageBreaks;

                    for (sal_Int32 i = 0; i < nParaCount && !bExit; ++i)
                    {
                        sal_Int32 nActualLineLen = 0;
                        sal_Int32 nLineCount = pOut->GetLineCount(i);

                        sal_uInt16 nLowerSpace = 0;
                        sal_uInt16 nUpperSpace = nPrevParaLowerSpace;
                        const SfxItemSet* pItemSet = &pOut->GetParaAttribs(i);
                        if(pItemSet->HasItem(EE_PARA_ULSPACE))
                        {
                            nLowerSpace = pItemSet->Get(EE_PARA_ULSPACE).GetLower();
                            nUpperSpace = (i != 0) ? pItemSet->Get(EE_PARA_ULSPACE).GetUpper() : 0;
                            if (nPrevParaLowerSpace > nUpperSpace)
                                nUpperSpace = nPrevParaLowerSpace;
                        }

                        for (sal_Int32 j = 0; j < nLineCount; ++j)
                        {
                            nActualLineLen += pOut->GetLineLen(i, j);
                            sal_Int32 nLineHeight = pOut->GetLineHeight(i, j);

                            if (nUpperSpace != 0 && (i > 0) && (j == 0))
                                nLineHeight += nUpperSpace;

                            sal_Int32 nNextPosY = nCurrentPosY + nLineHeight;

                            if (nNextPosY > nNotesPageBottom)
                            {
                                // If the current or the next page matches the print page
                                // calculate and add a page break, since we only want to add
                                // a page break if the page is relevant.
                                if (mnPageNumb == nActualPageNumb
                                    || mnPageNumb == nActualPageNumb + 1)
                                {
                                    if (!aPageBreaks.empty())
                                    {
                                        // determine the page break at the bottom of the page
                                        // for pages that have both a previous and a following page
                                        aPageBreaks.emplace_back(
                                            nPrevParaIdx - aPageBreaks[0].first, nPrevLineLen);
                                    }
                                    else
                                    {
                                        if (mnPageNumb == 1 || (nLineCount > 1 && j != 0))
                                        {
                                            // first page or multi-line paragraphs
                                            aPageBreaks.emplace_back(nPrevParaIdx, nPrevLineLen);
                                        }
                                        else
                                        {   // single-line paragraphs
                                            aPageBreaks.emplace_back(nPrevParaIdx + 1, 0);
                                        }
                                    }

                                    if (mnPageNumb == nActualPageNumb || mnPageNumb == mnPageCount)
                                    {
                                        bExit = true;
                                        break;
                                    }
                                }

                                if (nUpperSpace > 0)
                                    nLineHeight -= nUpperSpace;

                                nNotesPageBottom = aPageSize.Height() - nBottom;
                                nCurrentPosY = nTop;
                                nActualPageNumb++;
                                nActualLineLen = 0;
                            }
                            nPrevParaIdx = i;
                            nPrevLineLen = nActualLineLen;
                            nCurrentPosY += nLineHeight;
                        }
                        nPrevParaLowerSpace = nLowerSpace;
                    }

                    if (!aPageBreaks.empty())
                    {
                        ESelection aE;
                        if (mnPageNumb == 1)
                        {
                            aE.start.nPara = aPageBreaks[0].first;
                            aE.start.nIndex = aPageBreaks[0].second;
                            aE.end.nPara = pOut->GetParagraphCount() - 1;
                            aE.end.nIndex = pOut->GetText(pOut->GetParagraph(aE.end.nPara)).getLength();
                            pOut->QuickDelete(aE);
                        }
                        else
                        {
                            sal_Int16 nDepth = pOut->GetDepth(aPageBreaks[0].first);
                            SfxItemSet aItemSet = pOut->GetParaAttribs(aPageBreaks[0].first);

                            aE.start.nPara = 0;
                            aE.start.nIndex = 0;
                            aE.end.nPara = aPageBreaks[0].first;
                            aE.end.nIndex = aPageBreaks[0].second;
                            pOut->QuickDelete(aE);

                            Paragraph* pFirstPara = pOut->GetParagraph(0);
                            pOut->SetDepth(pFirstPara, nDepth);
                            pOut->SetParaAttribs(0, aItemSet);

                            if (aPageBreaks.size() > 1)
                            {
                                aE.start.nPara = aPageBreaks[1].first;
                                aE.start.nIndex = aPageBreaks[1].second;
                                aE.end.nPara = pOut->GetParagraphCount() - 1;
                                aE.end.nIndex = pOut->GetText(pOut->GetParagraph(aE.end.nPara)).getLength();
                                pOut->QuickDelete(aE);
                            }
                        }
                    }
                    pNotesObj->SetOutlinerParaObject(pOut->CreateParaObject());

                    Size aObjSize;
                    if (mnPageNumb != 1) // new page(s)
                    {
                        SdrObjListIter aShapeIter(pNotesPage.get());
                        while (aShapeIter.IsMore())
                        {
                            SdrObject* pObj = aShapeIter.Next();
                            if (pObj && pObj->GetObjIdentifier() != SdrObjKind::Text)
                                pNotesPage->RemoveObject(pObj->GetOrdNum());
                        }

                        aNotesPt.setX(nLeft);
                        aNotesPt.setY(nTop);
                        ::tools::Long nWidth = aPageSize.Width() - nLeft - nRight;
                        aObjSize = Size(nWidth, pOut->GetTextHeight());
                    }
                    else // first page
                    {
                        if (!bAutoGrow)
                            aObjSize = aNotesSize;
                        else
                            aObjSize = Size(aNotesSize.Width(), pOut->GetTextHeight());
                    }
                    pNotesObj->SetLogicRect(::tools::Rectangle(aNotesPt, aObjSize));
                }
                pOut->Clear();
                pOut->SetUpdateLayout(bSavedUpdateMode);
                pOut->Init(nSaveOutlMode);
            }
            pNotesPage->SetSize(aPageSize);

            PrintPage(
                rPrinter,
                rPrintView,
                *pNotesPage,
                pView,
                mbPrintMarkedOnly,
                rVisibleLayers,
                rPrintableLayers);
            PrintMessage(
                rPrinter,
                msPageString,
                maPageStringOffset);
        }

    private:
        const sal_uInt16 mnPageIndex;
        const sal_Int32 mnPageNumb;
        const sal_Int32 mnPageCount;
        const bool mbScaled;
    };

    /** Print one slide multiple times on a printer page so that the whole
        printer page is covered.
    */

    class TiledPrinterPage : public PrinterPage
    {
    public:
        TiledPrinterPage (
            const sal_uInt16 nPageIndex,
            const PageKind ePageKind,
            const bool bPrintMarkedOnly,
            const OUString& rsPageString,
            const Point& rPageStringOffset,
            const DrawModeFlags nDrawMode,
            const Orientation eOrientation,
            const sal_uInt16 nPaperTray)
            : PrinterPage(ePageKind, MapMode(), bPrintMarkedOnly, rsPageString,
                rPageStringOffset, nDrawMode, eOrientation, nPaperTray),
              mnPageIndex(nPageIndex)
        {
        }

        virtual void Print (
            Printer& rPrinter,
            SdDrawDocument& rDocument,
            ViewShell&,
            View* pView,
            DrawView& rPrintView,
            const SdrLayerIDSet& rVisibleLayers,
            const SdrLayerIDSet& rPrintableLayers) const override
        {
            SdPage* pPageToPrint = rDocument.GetSdPage(mnPageIndex, mePageKind);
            if (pPageToPrint==nullptr)
                return;
            MapMode aMap (rPrinter.GetMapMode());

            const Size aPageSize (pPageToPrint->GetSize());
            const Size aPrintSize (rPrinter.GetOutputSize());

            const sal_Int32 nPageWidth (aPageSize.Width() + mnGap
                - pPageToPrint->GetLeftBorder() - pPageToPrint->GetRightBorder());
            const sal_Int32 nPageHeight (aPageSize.Height() + mnGap
                - pPageToPrint->GetUpperBorder() - pPageToPrint->GetLowerBorder());
            if (nPageWidth<=0 || nPageHeight<=0)
                return;

            // Print at least two rows and columns.  More if the document
            // page fits completely onto the printer page.
            const sal_Int32 nColumnCount (std::max(sal_Int32(2),
                    sal_Int32(aPrintSize.Width() / nPageWidth)));
            const sal_Int32 nRowCount (std::max(sal_Int32(2),
                    sal_Int32(aPrintSize.Height() / nPageHeight)));
            for (sal_Int32 nRow=0; nRow<nRowCount; ++nRow)
                for (sal_Int32 nColumn=0; nColumn<nColumnCount; ++nColumn)
                {
                    aMap.SetOrigin(Point(nColumn*nPageWidth,nRow*nPageHeight));
                    rPrinter.SetMapMode(aMap);
                    PrintPage(
                        rPrinter,
                        rPrintView,
                        *pPageToPrint,
                        pView,
                        mbPrintMarkedOnly,
                        rVisibleLayers,
                        rPrintableLayers);
                }

            PrintMessage(
                rPrinter,
                msPageString,
                maPageStringOffset);
        }

    private:
        const sal_uInt16 mnPageIndex;
        static const sal_Int32 mnGap = 500;
    };

    /** Print two slides to one printer page so that the resulting pages
        form a booklet.
    */

    class BookletPrinterPage : public PrinterPage
    {
    public:
        BookletPrinterPage (
            const sal_uInt16 nFirstPageIndex,
            const sal_uInt16 nSecondPageIndex,
            const Point& rFirstOffset,
            const Point& rSecondOffset,
            const PageKind ePageKind,
            const MapMode& rMapMode,
            const bool bPrintMarkedOnly,
            const DrawModeFlags nDrawMode,
            const Orientation eOrientation,
            const sal_uInt16 nPaperTray)
            : PrinterPage(ePageKind, rMapMode, bPrintMarkedOnly, u""_ustr,
                Point(), nDrawMode, eOrientation, nPaperTray),
              mnFirstPageIndex(nFirstPageIndex),
              mnSecondPageIndex(nSecondPageIndex),
              maFirstOffset(rFirstOffset),
              maSecondOffset(rSecondOffset)
        {
        }

        virtual void Print (
            Printer& rPrinter,
            SdDrawDocument& rDocument,
            ViewShell&,
            View* pView,
            DrawView& rPrintView,
            const SdrLayerIDSet& rVisibleLayers,
            const SdrLayerIDSet& rPrintableLayers) const override
        {
            MapMode aMap (maMap);
            SdPage* pPageToPrint = rDocument.GetSdPage(mnFirstPageIndex, mePageKind);
            if (pPageToPrint)
            {
                aMap.SetOrigin(maFirstOffset);
                rPrinter.SetMapMode(aMap);
                PrintPage(
                    rPrinter,
                    rPrintView,
                    *pPageToPrint,
                    pView,
                    mbPrintMarkedOnly,
                    rVisibleLayers,
                    rPrintableLayers);
            }

            pPageToPrint = rDocument.GetSdPage(mnSecondPageIndex, mePageKind);
            if( !pPageToPrint )
                return;

            aMap.SetOrigin(maSecondOffset);
            rPrinter.SetMapMode(aMap);
            PrintPage(
                rPrinter,
                rPrintView,
                *pPageToPrint,
                pView,
                mbPrintMarkedOnly,
                rVisibleLayers,
                rPrintableLayers);
        }

    private:
        const sal_uInt16 mnFirstPageIndex;
        const sal_uInt16 mnSecondPageIndex;
        const Point maFirstOffset;
        const Point maSecondOffset;
    };

    /** One handout page displays one to nine slides.
    */

    class HandoutPrinterPage : public PrinterPage
    {
    public:
        HandoutPrinterPage (
            const sal_uInt16 nHandoutPageIndex,
            std::vector<sal_uInt16>&& rPageIndices,
            const MapMode& rMapMode,
            const OUString& rsPageString,
            const Point& rPageStringOffset,
            const DrawModeFlags nDrawMode,
            const Orientation eOrientation,
            const sal_uInt16 nPaperTray)
            : PrinterPage(PageKind::Handout, rMapMode, false, rsPageString,
                rPageStringOffset, nDrawMode, eOrientation, nPaperTray),
              mnHandoutPageIndex(nHandoutPageIndex),
              maPageIndices(std::move(rPageIndices))
        {
        }

        virtual void Print (
            Printer& rPrinter,
            SdDrawDocument& rDocument,
            ViewShell& rViewShell,
            View* pView,
            DrawView& rPrintView,
            const SdrLayerIDSet& rVisibleLayers,
            const SdrLayerIDSet& rPrintableLayers) const override
        {
            SdPage& rHandoutPage (*rDocument.GetSdPage(0, PageKind::Handout));

            Size aPageSize(rHandoutPage.GetSize());
            Size aPrintPageSize = rPrinter.GetPrintPageSize();

            if ((aPageSize.Width() < aPageSize.Height()
                 && aPrintPageSize.Width() > aPrintPageSize.Height())
                || (aPageSize.Width() > aPageSize.Height()
                    && aPrintPageSize.Width() < aPrintPageSize.Height()))
            {
                ::tools::Long nTmp = aPageSize.Width();
                aPageSize.setWidth(aPageSize.Height());
                aPageSize.setHeight(nTmp);

                rHandoutPage.SetSize(aPageSize);
            }

            Reference< css::beans::XPropertySet > xHandoutPage( rHandoutPage.getUnoPage(), UNO_QUERY );
            static constexpr OUString sPageNumber( u"Number"_ustr );

            // Collect the page objects of the handout master.
            std::vector<SdrPageObj*> aHandoutPageObjects;
            SdrObjListIter aShapeIter (&rHandoutPage);
            while (aShapeIter.IsMore())
            {
                SdrPageObj* pPageObj = dynamic_cast<SdrPageObj*>(aShapeIter.Next());
                if (pPageObj)
                    aHandoutPageObjects.push_back(pPageObj);
            }
            if (aHandoutPageObjects.empty())
                return;

            // Connect page objects with pages.
            std::vector<SdrPageObj*>::iterator aPageObjIter (aHandoutPageObjects.begin());
            for (std::vector<sal_uInt16>::const_iterator
                     iPageIndex(maPageIndices.begin()),
                     iEnd(maPageIndices.end());
                 iPageIndex!=iEnd && aPageObjIter!=aHandoutPageObjects.end();
                 ++iPageIndex)
            {
                // Check if the page still exists.
                if (*iPageIndex >= rDocument.GetSdPageCount(PageKind::Standard))
                    continue;

                SdrPageObj* pPageObj = *aPageObjIter++;
                pPageObj->SetReferencedPage(rDocument.GetSdPage(*iPageIndex, PageKind::Standard));
            }

            // if there are more page objects than pages left, set the rest to invisible
            int nHangoverCount = 0;
            while (aPageObjIter != aHandoutPageObjects.end())
            {
                (*aPageObjIter++)->SetReferencedPage(nullptr);
                nHangoverCount++;
            }

            // Hide outlines for objects that have pages attached.
            if (nHangoverCount > 0)
            {
                int nSkip = aHandoutPageObjects.size() - nHangoverCount;
                aShapeIter.Reset();
                while (aShapeIter.IsMore())
                {
                    SdrPathObj* pPathObj = dynamic_cast<SdrPathObj*>(aShapeIter.Next());
                    if (pPathObj)
                    {
                        if (nSkip > 0)
                            --nSkip;
                        else
                            pPathObj->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
                    }
                }
            }

            if( xHandoutPage.is() ) try
            {
                xHandoutPage->setPropertyValue( sPageNumber, Any( static_cast<sal_Int16>(mnHandoutPageIndex) ) );
            }
            catch( Exception& )
            {
            }
            rViewShell.SetPrintedHandoutPageNum( mnHandoutPageIndex + 1 );

            rPrinter.SetMapMode(maMap);

            PrintPage(
                rPrinter,
                rPrintView,
                rHandoutPage,
                pView,
                false,
                rVisibleLayers,
                rPrintableLayers);
            PrintMessage(
                rPrinter,
                msPageString,
                maPageStringOffset);

            if( xHandoutPage.is() ) try
            {
                xHandoutPage->setPropertyValue( sPageNumber, Any( static_cast<sal_Int16>(0) ) );
            }
            catch( Exception& )
            {
            }
            rViewShell.SetPrintedHandoutPageNum(1);

            // Restore outlines.
            if (nHangoverCount > 0)
            {
                aShapeIter.Reset();
                while (aShapeIter.IsMore())
                {
                    SdrPathObj* pPathObj = dynamic_cast<SdrPathObj*>(aShapeIter.Next());
                    if (pPathObj != nullptr)
                        pPathObj->SetMergedItem(XLineStyleItem(drawing::LineStyle_SOLID));
                }
            }

       }

    private:
        const sal_uInt16 mnHandoutPageIndex;
        const std::vector<sal_uInt16> maPageIndices;
    };

    /** The outline information (title, subtitle, outline objects) of the
        document.  There is no fixed mapping of slides to printer pages.
    */

    class OutlinerPrinterPage : public PrinterPage
    {
    public:
        OutlinerPrinterPage (
            std::optional<OutlinerParaObject> pParaObject,
            const MapMode& rMapMode,
            const OUString& rsPageString,
            const Point& rPageStringOffset,
            const DrawModeFlags nDrawMode,
            const Orientation eOrientation,
            const sal_uInt16 nPaperTray)
            : PrinterPage(PageKind::Handout, rMapMode, false, rsPageString,
                rPageStringOffset, nDrawMode, eOrientation, nPaperTray),
              mpParaObject(std::move(pParaObject))
        {
        }

        virtual void Print (
            Printer& rPrinter,
            SdDrawDocument& rDocument,
            ViewShell&,
            View*,
            DrawView&,
            const SdrLayerIDSet&,
            const SdrLayerIDSet&) const override
        {
            // Set up the printer.
            rPrinter.SetMapMode(maMap);

            // Get and set up the outliner.
            const ::tools::Rectangle aOutRect (rPrinter.GetPageOffset(), rPrinter.GetOutputSize());
            Outliner* pOutliner = rDocument.GetInternalOutliner();
            const OutlinerMode nSavedOutlMode (pOutliner->GetOutlinerMode());
            const bool bSavedUpdateMode (pOutliner->IsUpdateLayout());
            const Size aSavedPaperSize (pOutliner->GetPaperSize());

            pOutliner->Init(OutlinerMode::OutlineView);
            pOutliner->SetPaperSize(aOutRect.GetSize());
            pOutliner->SetUpdateLayout(true);
            pOutliner->Clear();
            pOutliner->SetText(*mpParaObject);

            pOutliner->Draw(rPrinter, aOutRect);

            PrintMessage(
                rPrinter,
                msPageString,
                maPageStringOffset);

            // Restore outliner and printer.
            pOutliner->Clear();
            pOutliner->SetUpdateLayout(bSavedUpdateMode);
            pOutliner->SetPaperSize(aSavedPaperSize);
            pOutliner->Init(nSavedOutlMode);
        }

    private:
        std::optional<OutlinerParaObject> mpParaObject;
    };
}

//===== DocumentRenderer::Implementation ======================================

class DocumentRenderer::Implementation
    : public SfxListener,
      public vcl::PrinterOptionsHelper
{
public:
    explicit Implementation (ViewShellBase& rBase)
        : mxObjectShell(rBase.GetDocShell())
        , mrBase(rBase)
        , mbIsDisposed(false)
        , mpPrinter(nullptr)
        , mbHasOrientationWarningBeenShown(false)
    {
        DialogCreator aCreator( mrBase, mrBase.GetDocShell()->GetDocumentType() == DocumentType::Impress, GetCurrentPageIndex() );
        m_aUIProperties = aCreator.GetDialogControls();
        maSlidesPerPage = aCreator.GetSlidesPerPage();

        StartListening(mrBase);
    }

    virtual ~Implementation() override
    {
        EndListening(mrBase);
    }

    virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint) override
    {
        if (&rBroadcaster != &static_cast<SfxBroadcaster&>(mrBase))
            return;

        if (rHint.GetId() == SfxHintId::Dying)
        {
            mbIsDisposed = true;
        }
    }

    /** Process the sequence of properties given to one of the XRenderable
        methods.
    */

    void ProcessProperties (const css::uno::Sequence<css::beans::PropertyValue >& rOptions)
    {
        OSL_ASSERT(!mbIsDisposed);
        if (mbIsDisposed)
            return;

        bool bIsValueChanged = processProperties( rOptions );
        bool bIsPaperChanged = false;

        // The RenderDevice property is handled specially: its value is
        // stored in mpPrinter instead of being retrieved on demand.
        Any aDev( getValue( u"RenderDevice"_ustr ) );
        Reference<awt::XDevice> xRenderDevice;

        if (aDev >>= xRenderDevice)
        {
            VCLXDevice* pDevice = dynamic_cast<VCLXDevice*>(xRenderDevice.get());
            VclPtr< OutputDevice > pOut = pDevice ? pDevice->GetOutputDevice()
                                                  : VclPtr< OutputDevice >();
            mpPrinter = dynamic_cast<Printer*>(pOut.get());
            Size aPageSizePixel = mpPrinter ? mpPrinter->GetPaperSizePixel() : Size();
            Size aPrintPageSize = mpPrinter ? mpPrinter->GetPrintPageSize() : Size();

            lcl_AdjustPageSize(aPageSizePixel, aPrintPageSize);

            if (aPageSizePixel != maPrinterPageSizePixel)
            {
                bIsPaperChanged = true;
                maPrinterPageSizePixel = aPageSizePixel;
            }
        }

        if (bIsValueChanged && ! mpOptions )
            mpOptions.reset(new PrintOptions(*this, std::vector(maSlidesPerPage)));
        if( bIsValueChanged || bIsPaperChanged )
            PreparePages();
    }

    /** Return the number of pages that are to be printed.
    */

    sal_Int32 GetPrintPageCount() const
    {
        OSL_ASSERT(!mbIsDisposed);
        if (mbIsDisposed)
            return 0;
        else
            return maPrinterPages.size();
    }

    /** Return a sequence of properties that can be returned by the
        XRenderable::getRenderer() method.
    */

    css::uno::Sequence<css::beans::PropertyValue> GetProperties () const
    {
        css::uno::Sequence<css::beans::PropertyValue> aProperties{
            comphelper::makePropertyValue(u"ExtraPrintUIOptions"_ustr,
                                          comphelper::containerToSequence(m_aUIProperties)),
            comphelper::makePropertyValue(u"PageSize"_ustr, maPrintSize),
            // FIXME: is this always true ?
            comphelper::makePropertyValue(u"PageIncludesNonprintableArea"_ustr, true)
        };

        return aProperties;
    }

    /** Print one of the prepared pages.
    */

    void PrintPage (const sal_Int32 nIndex)
    {
        OSL_ASSERT(!mbIsDisposed);
        if (mbIsDisposed)
            return;

        Printer& rPrinter (*mpPrinter);

        std::shared_ptr<ViewShell> pViewShell (mrBase.GetMainViewShell());
        if ( ! pViewShell)
            return;

        SdDrawDocument* pDocument = pViewShell->GetDoc();
        assert(pDocument!=nullptr);

        std::shared_ptr<DrawViewShell> pDrawViewShell(
            std::dynamic_pointer_cast<DrawViewShell>(pViewShell));

        if (!mpPrintView)
            mpPrintView.reset(new DrawView(mrBase.GetDocShell(), &rPrinter, nullptr));

        if (nIndex<0 || sal::static_int_cast<sal_uInt32>(nIndex)>=maPrinterPages.size())
            return;

        const std::shared_ptr<PrinterPage> pPage (maPrinterPages[nIndex]);
        OSL_ASSERT(pPage);
        if ( ! pPage)
            return;

        const Orientation eSavedOrientation (rPrinter.GetOrientation());
        const DrawModeFlags nSavedDrawMode (rPrinter.GetDrawMode());
        const MapMode aSavedMapMode (rPrinter.GetMapMode());
        const sal_uInt16 nSavedPaperBin (rPrinter.GetPaperBin());

        // Set page orientation.
        if ( ! rPrinter.SetOrientation(pPage->GetOrientation()))
        {
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=96 H=96 G=95

¤ Dauer der Verarbeitung: 0.27 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.