Coverage Report

Created: 2026-04-09 11:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sd/source/ui/view/DocumentRenderer.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
20
#include <com/sun/star/beans/XPropertySet.hpp>
21
22
#include <DocumentRenderer.hxx>
23
#include <DocumentRenderer.hrc>
24
#include <ViewShellBase.hxx>
25
26
#include <drawdoc.hxx>
27
#include <sdpage.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>
37
38
#include <tools/multisel.hxx>
39
#include <basegfx/polygon/b2dpolygon.hxx>
40
#include <basegfx/polygon/b2dpolypolygon.hxx>
41
#include <basegfx/matrix/b2dhommatrix.hxx>
42
#include <comphelper/propertyvalue.hxx>
43
#include <comphelper/sequence.hxx>
44
#include <rtl/ustrbuf.hxx>
45
#include <editeng/editstat.hxx>
46
#include <editeng/eeitem.hxx>
47
#include <editeng/outlobj.hxx>
48
#include <editeng/ulspitem.hxx>
49
#include <svx/sdtfsitm.hxx>
50
#include <svx/sdooitm.hxx>
51
#include <svx/svdetc.hxx>
52
#include <svx/svditer.hxx>
53
#include <svx/svdopage.hxx>
54
#include <svx/svdopath.hxx>
55
#include <svx/svdpagv.hxx>
56
#include <svx/xlineit0.hxx>
57
#include <svx/xlnclit.hxx>
58
#include <toolkit/awt/vclxdevice.hxx>
59
#include <unotools/localedatawrapper.hxx>
60
#include <utility>
61
#include <vcl/print.hxx>
62
#include <vcl/svapp.hxx>
63
#include <vcl/weld/MessageDialog.hxx>
64
#include <vcl/weld/weld.hxx>
65
#include <unotools/moduleoptions.hxx>
66
#include <xmloff/autolayout.hxx>
67
#include <sfx2/objsh.hxx>
68
69
#include <svl/cjkoptions.hxx>
70
#include <svl/ctloptions.hxx>
71
72
#include <officecfg/Office/Draw.hxx>
73
#include <officecfg/Office/Impress.hxx>
74
75
#include <algorithm>
76
#include <memory>
77
#include <vector>
78
79
using namespace ::com::sun::star;
80
using namespace ::com::sun::star::uno;
81
82
namespace sd {
83
84
namespace {
85
86
    void lcl_AdjustPageSize(Size& rPageSize, const Size& rPrintPageSize)
87
0
    {
88
0
        bool bOrientationDiff = (rPageSize.Width() < rPageSize.Height()
89
0
                                 && rPrintPageSize.Width() > rPrintPageSize.Height())
90
0
                                || (rPageSize.Width() > rPageSize.Height()
91
0
                                    && rPrintPageSize.Width() < rPrintPageSize.Height());
92
0
        if (bOrientationDiff)
93
0
        {
94
0
            ::tools::Long nTmp = rPageSize.Width();
95
0
            rPageSize.setWidth(rPageSize.Height());
96
0
            rPageSize.setHeight(nTmp);
97
0
        }
98
0
    }
99
100
    /** Convenience class to extract values from the sequence of properties
101
        given to one of the XRenderable methods.
102
    */
103
    class PrintOptions
104
    {
105
    public:
106
        PrintOptions (
107
            const vcl::PrinterOptionsHelper& rHelper,
108
            std::vector<sal_Int32>&& rSlidesPerPage)
109
0
            : mrProperties(rHelper),
110
0
              maSlidesPerPage(std::move(rSlidesPerPage))
111
0
        {
112
0
        }
113
114
        bool IsWarningOrientation() const
115
0
        {
116
0
            return GetBoolValue(nullptr, true);
117
0
        }
118
119
        bool IsPrintPageName() const
120
0
        {
121
0
            return GetBoolValue("IsPrintName", false);
122
0
        }
123
124
        bool IsDate() const
125
0
        {
126
0
            return GetBoolValue("IsPrintDateTime", false);
127
0
        }
128
129
        bool IsTime() const
130
0
        {
131
0
            return GetBoolValue("IsPrintDateTime", false);
132
0
        }
133
134
        bool IsHiddenPages() const
135
0
        {
136
0
            return GetBoolValue("IsPrintHidden", false);
137
0
        }
138
139
        bool IsHandoutHorizontal() const
140
0
        {
141
0
            return GetBoolValue("SlidesPerPageOrder", sal_Int32(0));
142
0
        }
143
144
        sal_Int32 GetHandoutPageCount() const
145
0
        {
146
0
            sal_uInt32 nIndex = static_cast<sal_Int32>(mrProperties.getIntValue("SlidesPerPage", sal_Int32(0)));
147
0
            if (nIndex<maSlidesPerPage.size())
148
0
                return maSlidesPerPage[nIndex];
149
0
            else if ( ! maSlidesPerPage.empty())
150
0
                return maSlidesPerPage[0];
151
0
            else
152
0
                return 0;
153
0
        }
154
155
        bool IsDraw() const
156
0
        {
157
0
            return GetBoolValue("PageContentType", sal_Int32(0));
158
0
        }
159
160
        bool IsHandout() const
161
0
        {
162
0
            return GetBoolValue("PageContentType", sal_Int32(1));
163
0
        }
164
165
        bool IsNotes() const
166
0
        {
167
0
            return GetBoolValue("PageContentType", sal_Int32(2));
168
0
        }
169
170
        bool IsOutline() const
171
0
        {
172
0
            return GetBoolValue("PageContentType", sal_Int32(3));
173
0
        }
174
175
        sal_uLong GetOutputQuality() const
176
0
        {
177
0
            sal_Int32 nQuality = static_cast<sal_Int32>(mrProperties.getIntValue( "Quality", sal_Int32(0) ));
178
0
            return nQuality;
179
0
        }
180
181
        bool IsPageSize() const
182
0
        {
183
0
            return GetBoolValue("PageOptions", sal_Int32(1));
184
0
        }
185
186
        bool IsTilePage() const
187
0
        {
188
0
            return GetBoolValue("PageOptions", sal_Int32(2)) || GetBoolValue("PageOptions", sal_Int32(3));
189
0
        }
190
191
        bool IsCutPage() const
192
0
        {
193
0
            return GetBoolValue("PageOptions", sal_Int32(0));
194
0
        }
195
196
        bool IsBooklet() const
197
0
        {
198
0
            return GetBoolValue("PrintProspect", false);
199
0
        }
200
201
        bool IsProspectRTL() const
202
0
        {
203
0
            return mrProperties.getIntValue( "PrintProspectRTL",  0 ) != 0;
204
0
        }
205
206
        bool IsPrinterPreferred(DocumentType eDocType) const
207
0
        {
208
0
            bool bIsDraw = eDocType == DocumentType::Draw;
209
0
            return IsTilePage() || IsPageSize() || IsBooklet() || (!bIsDraw && !IsNotes());
210
0
        }
211
212
        bool IsPrintExcluded() const
213
0
        {
214
0
            return (IsNotes() || IsDraw() || IsHandout()) &&  IsHiddenPages();
215
0
        }
216
217
        bool IsPrintFrontPage() const
218
0
        {
219
0
            sal_Int32 nInclude = static_cast<sal_Int32>(mrProperties.getIntValue( "EvenOdd", 0 ));
220
0
            return nInclude != 2;
221
0
        }
222
223
        bool IsPrintBackPage() const
224
0
        {
225
0
            sal_Int32 nInclude = static_cast<sal_Int32>(mrProperties.getIntValue( "EvenOdd", 0 ));
226
0
            return nInclude != 1;
227
0
        }
228
229
        bool IsPaperBin() const
230
0
        {
231
0
            return GetBoolValue("PrintPaperFromSetup", false);
232
0
        }
233
234
        bool IsPrintMarkedOnly() const
235
0
        {
236
0
            return GetBoolValue("PrintContent", sal_Int32(4));
237
0
        }
238
239
        OUString GetPrinterSelection (sal_Int32 nPageCount, sal_Int32 nCurrentPageIndex) const
240
0
        {
241
0
            sal_Int32 nContent = static_cast<sal_Int32>(mrProperties.getIntValue( "PrintContent", 0 ));
242
0
            OUString sFullRange = "1-" + OUString::number(nPageCount);
243
244
0
            if (nContent == 0) // all pages/slides
245
0
            {
246
0
                return sFullRange;
247
0
            }
248
249
0
            if (nContent == 1) // range
250
0
            {
251
0
                OUString sValue = mrProperties.getStringValue("PageRange");
252
0
                return sValue.isEmpty() ? sFullRange : sValue;
253
0
            }
254
255
0
            if (nContent == 2 && // selection
256
0
                nCurrentPageIndex >= 0)
257
0
            {
258
0
                return OUString::number(nCurrentPageIndex + 1);
259
0
            }
260
261
0
            return OUString();
262
0
        }
263
264
    private:
265
        const vcl::PrinterOptionsHelper& mrProperties;
266
        const std::vector<sal_Int32> maSlidesPerPage;
267
268
        /** When the value of the property with name pName is a boolean then
269
            return its value. When the property is unknown then
270
            bDefaultValue is returned.  Otherwise <FALSE/> is returned.
271
        */
272
        bool GetBoolValue (
273
            const char* pName,
274
            const bool bDefaultValue) const
275
0
        {
276
0
            bool bValue = mrProperties.getBoolValue( pName, bDefaultValue );
277
0
            return bValue;
278
0
        }
279
280
        /** Return <TRUE/> when the value of the property with name pName is
281
            an integer and its value is nTriggerValue. Otherwise <FALSE/> is
282
            returned.
283
        */
284
        bool GetBoolValue (
285
            const char* pName,
286
            const sal_Int32 nTriggerValue) const
287
0
        {
288
0
            sal_Int32 nValue = static_cast<sal_Int32>(mrProperties.getIntValue( pName, 0 ));
289
0
            return nValue == nTriggerValue;
290
0
        }
291
    };
292
293
    /** A collection of values that helps to reduce the number of arguments
294
        given to some functions.  Note that not all values are set at the
295
        same time.
296
    */
297
    class PrintInfo
298
    {
299
    public:
300
        PrintInfo (
301
            Printer* pPrinter,
302
            const bool bPrintMarkedOnly)
303
0
            : mpPrinter(pPrinter),
304
0
              mnDrawMode(DrawModeFlags::Default),
305
0
              maPrintSize(0,0),
306
0
              maPageSize(0,0),
307
0
              meOrientation(Orientation::Portrait),
308
0
              mbPrintMarkedOnly(bPrintMarkedOnly)
309
0
        {}
310
311
        const VclPtr<Printer> mpPrinter;
312
        DrawModeFlags mnDrawMode;
313
        OUString msTimeDate;
314
        OUString msPageString;
315
        Size maPrintSize;
316
        Size maPageSize;
317
        Orientation meOrientation;
318
        MapMode maMap;
319
        const bool mbPrintMarkedOnly;
320
    };
321
322
    /** Output one page of the document to the given printer.  Note that
323
        more than one document page may be output to one printer page.
324
    */
325
    void PrintPage (
326
        Printer& rPrinter,
327
        ::sd::View& rPrintView,
328
        SdPage& rPage,
329
        View const * pView,
330
        const bool bPrintMarkedOnly,
331
        const SdrLayerIDSet& rVisibleLayers,
332
        const SdrLayerIDSet& rPrintableLayers)
333
0
    {
334
0
        rPrintView.ShowSdrPage(&rPage);
335
336
0
        const MapMode aOriginalMapMode (rPrinter.GetMapMode());
337
338
        // Set the visible layers
339
0
        SdrPageView* pPageView = rPrintView.GetSdrPageView();
340
0
        OSL_ASSERT(pPageView!=nullptr);
341
0
        pPageView->SetVisibleLayers(rVisibleLayers);
342
0
        pPageView->SetPrintableLayers(rPrintableLayers);
343
344
0
        if (pView!=nullptr && bPrintMarkedOnly)
345
0
            pView->DrawMarkedObj(rPrinter);
346
0
        else
347
0
            rPrintView.CompleteRedraw(&rPrinter,
348
0
                    vcl::Region(::tools::Rectangle(Point(0,0), rPage.GetSize())));
349
350
0
        rPrinter.SetMapMode(aOriginalMapMode);
351
352
0
        rPrintView.HideSdrPage();
353
0
    }
354
355
    /** Output a string (that typically is not part of a document page) to
356
        the given printer.
357
    */
358
    void PrintMessage (
359
        Printer& rPrinter,
360
        const OUString& rsPageString,
361
        const Point& rPageStringOffset)
362
0
    {
363
0
        const vcl::Font aOriginalFont (rPrinter.OutputDevice::GetFont());
364
0
        rPrinter.SetFont(vcl::Font(FAMILY_SWISS, Size(0, 423)));
365
0
        rPrinter.DrawText(rPageStringOffset, rsPageString);
366
0
        rPrinter.SetFont(aOriginalFont);
367
0
    }
368
369
    /** Read the resources and process then into a sequence of properties
370
        that can be passed to the printing dialog.
371
    */
372
    class DialogCreator
373
    {
374
    public:
375
        DialogCreator (ViewShellBase &rBase, bool bImpress, sal_Int32 nCurPage)
376
0
            : mrBase(rBase)
377
0
            , mbImpress(bImpress)
378
0
            , mnCurPage(nCurPage)
379
0
        {
380
0
            ProcessResource();
381
0
        }
382
383
        const std::vector< beans::PropertyValue >& GetDialogControls() const
384
0
        {
385
0
            return maProperties;
386
0
        }
387
388
        const std::vector<sal_Int32>& GetSlidesPerPage() const
389
0
        {
390
0
            return maSlidesPerPage;
391
0
        }
392
393
    private:
394
        ViewShellBase &mrBase;
395
        std::vector<beans::PropertyValue> maProperties;
396
        std::vector<sal_Int32> maSlidesPerPage;
397
        bool mbImpress;
398
        sal_Int32 mnCurPage;
399
400
        void ProcessResource()
401
0
        {
402
            // load the impress or draw PrinterOptions into the custom tab
403
0
            beans::PropertyValue aOptionsUIFile;
404
0
            aOptionsUIFile.Name = "OptionsUIFile";
405
0
            if( mbImpress )
406
0
                aOptionsUIFile.Value <<= u"modules/simpress/ui/impressprinteroptions.ui"_ustr;
407
0
            else
408
0
                aOptionsUIFile.Value <<= u"modules/sdraw/ui/drawprinteroptions.ui"_ustr;
409
0
            maProperties.push_back(aOptionsUIFile);
410
411
0
            SvtModuleOptions aOpt;
412
0
            OUString aAppGroupname(SdResId(STR_IMPRESS_PRINT_UI_GROUP_NAME));
413
0
            aAppGroupname = aAppGroupname.replaceFirst("%s", aOpt.GetModuleName(
414
0
                mbImpress ? SvtModuleOptions::EModule::IMPRESS : SvtModuleOptions::EModule::DRAW));
415
0
            AddDialogControl(vcl::PrinterOptionsHelper::setGroupControlOpt(u"tabcontrol-page2"_ustr, aAppGroupname, u".HelpID:vcl:PrintDialog:TabPage:AppPage"_ustr));
416
417
0
            uno::Sequence< OUString > aHelpIds, aWidgetIds;
418
0
            if( mbImpress )
419
0
            {
420
0
                aHelpIds = { u".HelpID:vcl:PrintDialog:PageContentType:ListBox"_ustr };
421
0
                AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt(
422
0
                                    u"impressdocument"_ustr,
423
0
                                    SdResId(STR_IMPRESS_PRINT_UI_CONTENT),
424
0
                                    aHelpIds,
425
0
                                    u"PageContentType"_ustr ,
426
0
                                    CreateChoice(STR_IMPRESS_PRINT_UI_CONTENT_CHOICES, std::size(STR_IMPRESS_PRINT_UI_CONTENT_CHOICES)),
427
0
                                    0)
428
0
                                );
429
430
0
                aHelpIds = { u".HelpID:vcl:PrintDialog:SlidesPerPage:ListBox"_ustr };
431
0
                vcl::PrinterOptionsHelper::UIControlOptions aContentOpt( u"PageContentType"_ustr , 1 );
432
0
                AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt(
433
0
                                    u"slidesperpage"_ustr,
434
0
                                    SdResId(STR_IMPRESS_PRINT_UI_SLIDESPERPAGE),
435
0
                                    aHelpIds,
436
0
                                    u"SlidesPerPage"_ustr ,
437
0
                                    GetSlidesPerPageSequence(),
438
0
                                    0,
439
0
                                    Sequence< sal_Bool >(),
440
0
                                    aContentOpt
441
0
                                    )
442
0
                                );
443
444
0
                aHelpIds = { u".HelpID:vcl:PrintDialog:SlidesPerPageOrder:ListBox"_ustr };
445
0
                vcl::PrinterOptionsHelper::UIControlOptions aSlidesPerPageOpt( u"SlidesPerPage"_ustr , -1, true );
446
0
                AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt(
447
0
                                    u"slidesperpageorder"_ustr,
448
0
                                    SdResId(STR_IMPRESS_PRINT_UI_ORDER),
449
0
                                    aHelpIds,
450
0
                                    u"SlidesPerPageOrder"_ustr ,
451
0
                                    CreateChoice(STR_IMPRESS_PRINT_UI_ORDER_CHOICES, std::size(STR_IMPRESS_PRINT_UI_ORDER_CHOICES)),
452
0
                                    0,
453
0
                                    Sequence< sal_Bool >(),
454
0
                                    aSlidesPerPageOpt )
455
0
                                );
456
0
            }
457
458
0
            AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt(u"contents"_ustr,
459
0
                               SdResId(STR_IMPRESS_PRINT_UI_INCLUDE_CONTENT), u""_ustr ) );
460
461
0
            if( mbImpress )
462
0
            {
463
0
                AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u"printname"_ustr,
464
0
                                    SdResId(STR_IMPRESS_PRINT_UI_IS_PRINT_NAME),
465
0
                                    u".HelpID:vcl:PrintDialog:IsPrintName:CheckBox"_ustr ,
466
0
                                    u"IsPrintName"_ustr ,
467
0
                                    officecfg::Office::Impress::Print::Other::PageName::get()
468
0
                                    )
469
0
                                );
470
0
            }
471
0
            else
472
0
            {
473
0
                AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u"printname"_ustr,
474
0
                                    SdResId(STR_DRAW_PRINT_UI_IS_PRINT_NAME),
475
0
                                    u".HelpID:vcl:PrintDialog:IsPrintName:CheckBox"_ustr ,
476
0
                                    u"IsPrintName"_ustr ,
477
0
                                    officecfg::Office::Draw::Print::Other::PageName::get()
478
0
                                    )
479
0
                                );
480
0
            }
481
482
0
            AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u"printdatetime"_ustr,
483
0
                                SdResId(STR_IMPRESS_PRINT_UI_IS_PRINT_DATE),
484
0
                                u".HelpID:vcl:PrintDialog:IsPrintDateTime:CheckBox"_ustr ,
485
0
                                u"IsPrintDateTime"_ustr ,
486
                                // Separate settings for time and date in Impress/Draw -> Print page, check that both are set
487
0
                                mbImpress ?
488
0
                                officecfg::Office::Impress::Print::Other::Date::get() &&
489
0
                                officecfg::Office::Impress::Print::Other::Time::get() :
490
0
                                officecfg::Office::Draw::Print::Other::Date::get() &&
491
0
                                officecfg::Office::Draw::Print::Other::Time::get()
492
0
                                )
493
0
                            );
494
495
0
            if( mbImpress )
496
0
            {
497
0
                AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u"printhidden"_ustr,
498
0
                                    SdResId(STR_IMPRESS_PRINT_UI_IS_PRINT_HIDDEN),
499
0
                                    u".HelpID:vcl:PrintDialog:IsPrintHidden:CheckBox"_ustr ,
500
0
                                    u"IsPrintHidden"_ustr ,
501
0
                                    officecfg::Office::Impress::Print::Other::HiddenPage::get()
502
0
                                    )
503
0
                                );
504
0
            }
505
506
0
            AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt(u"color"_ustr,
507
0
                               SdResId(STR_IMPRESS_PRINT_UI_QUALITY), u""_ustr ) );
508
509
0
            aHelpIds = { u".HelpID:vcl:PrintDialog:Quality:RadioButton:0"_ustr,
510
0
                         u".HelpID:vcl:PrintDialog:Quality:RadioButton:1"_ustr,
511
0
                         u".HelpID:vcl:PrintDialog:Quality:RadioButton:2"_ustr };
512
0
            aWidgetIds = { u"originalcolors"_ustr, u"grayscale"_ustr, u"blackandwhite"_ustr };
513
0
            AddDialogControl( vcl::PrinterOptionsHelper::setChoiceRadiosControlOpt(
514
0
                                aWidgetIds,
515
0
                                u""_ustr,
516
0
                                aHelpIds,
517
0
                                u"Quality"_ustr ,
518
0
                                CreateChoice(STR_IMPRESS_PRINT_UI_QUALITY_CHOICES, std::size(STR_IMPRESS_PRINT_UI_QUALITY_CHOICES)),
519
0
                                mbImpress ? officecfg::Office::Impress::Print::Other::Quality::get() :
520
0
                                            officecfg::Office::Draw::Print::Other::Quality::get() )
521
522
0
                            );
523
524
0
            AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt(u"pagesizes"_ustr,
525
0
                               SdResId(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS), u""_ustr ) );
526
527
0
            aHelpIds = { u".HelpID:vcl:PrintDialog:PageOptions:RadioButton:0"_ustr,
528
0
                         u".HelpID:vcl:PrintDialog:PageOptions:RadioButton:1"_ustr,
529
0
                         u".HelpID:vcl:PrintDialog:PageOptions:RadioButton:2"_ustr,
530
0
                         u".HelpID:vcl:PrintDialog:PageOptions:RadioButton:3"_ustr };
531
0
            aWidgetIds = { u"originalsize"_ustr, u"fittoprintable"_ustr, u"distributeonmultiple"_ustr, u"tilesheet"_ustr };
532
533
            // Mutually exclusive page options settings are stored in separate config keys...
534
            // TODO: There is no config key to set the distributeonmultiple option as default
535
0
            sal_Int32 nDefaultChoice = 0;
536
0
            if ( mbImpress ? officecfg::Office::Impress::Print::Page::PageSize::get() :
537
0
                             officecfg::Office::Draw::Print::Page::PageSize::get() )
538
0
            {
539
0
                nDefaultChoice = 1;
540
0
            }
541
0
            else if ( mbImpress ? officecfg::Office::Impress::Print::Page::PageTile::get() :
542
0
                                  officecfg::Office::Draw::Print::Page::PageTile::get() )
543
0
            {
544
0
                nDefaultChoice = 3;
545
0
            }
546
0
            vcl::PrinterOptionsHelper::UIControlOptions aPageOptionsOpt(u"PrintProspect"_ustr, 0);
547
0
            AddDialogControl( vcl::PrinterOptionsHelper::setChoiceRadiosControlOpt(
548
0
                                aWidgetIds,
549
0
                                u""_ustr,
550
0
                                aHelpIds,
551
0
                                u"PageOptions"_ustr ,
552
0
                                mbImpress ? CreateChoice(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES, std::size(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES)) :
553
0
                                            CreateChoice(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES_DRAW, std::size(STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES_DRAW)),
554
0
                                nDefaultChoice,
555
0
                                Sequence< sal_Bool >(),
556
0
                                aPageOptionsOpt
557
0
                                )
558
0
                            );
559
560
0
            vcl::PrinterOptionsHelper::UIControlOptions aBrochureOpt;
561
0
            aBrochureOpt.maGroupHint = "LayoutPage" ;
562
0
            AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt(u"pagesides"_ustr,
563
0
                               SdResId(STR_IMPRESS_PRINT_UI_PAGE_SIDES), u""_ustr,
564
0
                               aBrochureOpt ) );
565
566
            // brochure printing
567
0
            AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u"brochure"_ustr,
568
0
                                SdResId(STR_IMPRESS_PRINT_UI_BROCHURE),
569
0
                                u".HelpID:vcl:PrintDialog:PrintProspect:CheckBox"_ustr ,
570
0
                                u"PrintProspect"_ustr ,
571
0
                                mbImpress ? officecfg::Office::Impress::Print::Page::Booklet::get() :
572
0
                                            officecfg::Office::Draw::Print::Page::Booklet::get(),
573
0
                                aBrochureOpt
574
0
                                )
575
0
                            );
576
577
            // check if either CJK or CTL is enabled
578
0
            bool bRTL = SvtCJKOptions::IsCJKFontEnabled() || SvtCTLOptions::IsCTLFontEnabled();
579
580
0
            if(bRTL)
581
0
            {
582
0
                uno::Sequence< OUString > aBRTLChoices{ SdResId(STR_IMPRESS_PRINT_UI_LEFT_SCRIPT),
583
0
                                                        SdResId(STR_IMPRESS_PRINT_UI_RIGHT_SCRIPT) };
584
0
                vcl::PrinterOptionsHelper::UIControlOptions
585
0
                    aIncludeOpt( u"PrintProspect"_ustr , -1, true );
586
0
                aIncludeOpt.maGroupHint =  "LayoutPage" ;
587
0
                aHelpIds = { u".HelpID:vcl:PrintDialog:PrintProspectRTL:ListBox"_ustr };
588
0
                AddDialogControl( vcl::PrinterOptionsHelper::setChoiceListControlOpt(
589
0
                                u"scriptdirection"_ustr,
590
0
                                SdResId(STR_IMPRESS_PRINT_UI_BROCHURE_INCLUDE),
591
0
                                aHelpIds,
592
0
                                u"PrintProspectRTL"_ustr ,
593
0
                                aBRTLChoices,
594
0
                                0,
595
0
                                Sequence< sal_Bool >(),
596
0
                                aIncludeOpt
597
0
                                )
598
0
                            );
599
0
            }
600
            // paper tray (on options page)
601
0
            vcl::PrinterOptionsHelper::UIControlOptions aPaperTrayOpt;
602
0
            aPaperTrayOpt.maGroupHint = "OptionsPageOptGroup" ;
603
0
            AddDialogControl( vcl::PrinterOptionsHelper::setBoolControlOpt(u"printpaperfromsetup"_ustr,
604
0
                                SdResId(STR_IMPRESS_PRINT_UI_PAPER_TRAY),
605
0
                                u".HelpID:vcl:PrintDialog:PrintPaperFromSetup:CheckBox"_ustr ,
606
0
                                u"PrintPaperFromSetup"_ustr ,
607
0
                                false,
608
0
                                aPaperTrayOpt
609
0
                                )
610
0
                            );
611
            // print range selection
612
0
            vcl::PrinterOptionsHelper::UIControlOptions aPrintRangeOpt;
613
0
            aPrintRangeOpt.mbInternalOnly = true;
614
0
            aPrintRangeOpt.maGroupHint = "PrintRange" ;
615
0
            AddDialogControl( vcl::PrinterOptionsHelper::setSubgroupControlOpt(u"printrange"_ustr,
616
0
                                mbImpress ? SdResId(STR_IMPRESS_PRINT_UI_SLIDE_RANGE) : SdResId(STR_IMPRESS_PRINT_UI_PAGE_RANGE),
617
0
                                u""_ustr,
618
0
                                aPrintRangeOpt )
619
0
                             );
620
621
            // check if there is a selection of slides
622
0
            OUString aPageRange(OUString::number(mnCurPage + 1));
623
0
            int nPrintRange(0);
624
0
            using sd::slidesorter::SlideSorterViewShell;
625
0
            SlideSorterViewShell* const pSSViewSh(SlideSorterViewShell::GetSlideSorter(mrBase));
626
0
            if (pSSViewSh)
627
0
            {
628
0
                const std::shared_ptr<SlideSorterViewShell::PageSelection> pPageSelection(pSSViewSh->GetPageSelection());
629
0
                if (bool(pPageSelection) && pPageSelection->size() > 1)
630
0
                {
631
0
                    OUStringBuffer aBuf;
632
                    // TODO: this could be improved by writing ranges instead of consecutive page
633
                    // numbers if appropriate. Do we have a helper function for that somewhere?
634
0
                    bool bFirst(true);
635
0
                    for (auto pPage: *pPageSelection)
636
0
                    {
637
0
                        if (bFirst)
638
0
                            bFirst = false;
639
0
                        else
640
0
                            aBuf.append(',');
641
0
                        aBuf.append(static_cast<sal_Int32>(pPage->GetPageNum() / 2 + 1));
642
0
                    }
643
0
                    aPageRange = aBuf.makeStringAndClear();
644
0
                    nPrintRange = 1;
645
0
                }
646
0
            }
647
648
0
            OUString aPrintRangeName( u"PrintContent"_ustr );
649
0
            aHelpIds = { u".HelpID:vcl:PrintDialog:PrintContent:RadioButton:0"_ustr,
650
0
                         u".HelpID:vcl:PrintDialog:PrintContent:RadioButton:1"_ustr,
651
0
                         u".HelpID:vcl:PrintDialog:PrintContent:RadioButton:2"_ustr };
652
0
            aWidgetIds = { u"rbAllPages"_ustr, u"rbRangePages"_ustr, u"rbRangeSelection"_ustr };
653
654
0
            AddDialogControl( vcl::PrinterOptionsHelper::setChoiceRadiosControlOpt(aWidgetIds, OUString(),
655
0
                                aHelpIds, aPrintRangeName,
656
0
                                mbImpress ? CreateChoice(STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE, std::size(STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE)) :
657
0
                                            CreateChoice(STR_DRAW_PRINT_UI_PAGE_RANGE_CHOICE, std::size(STR_DRAW_PRINT_UI_PAGE_RANGE_CHOICE)),
658
0
                                nPrintRange )
659
0
                            );
660
            // create an Edit dependent on "Pages" selected
661
0
            vcl::PrinterOptionsHelper::UIControlOptions aPageRangeOpt( aPrintRangeName, 1, true );
662
0
            AddDialogControl(vcl::PrinterOptionsHelper::setEditControlOpt(u"pagerange"_ustr, u""_ustr,
663
0
                                u".HelpID:vcl:PrintDialog:PageRange:Edit"_ustr, u"PageRange"_ustr,
664
0
                                aPageRange, aPageRangeOpt));
665
0
            vcl::PrinterOptionsHelper::UIControlOptions aEvenOddOpt(aPrintRangeName, -1, true);
666
0
            AddDialogControl(vcl::PrinterOptionsHelper::setChoiceListControlOpt(u"evenoddbox"_ustr, u""_ustr,
667
0
                                uno::Sequence<OUString>(), u"EvenOdd"_ustr, uno::Sequence<OUString>(),
668
0
                                0, uno::Sequence<sal_Bool>(), aEvenOddOpt));
669
0
        }
670
671
        void AddDialogControl( const Any& i_rCtrl )
672
0
        {
673
0
            beans::PropertyValue aVal;
674
0
            aVal.Value = i_rCtrl;
675
0
            maProperties.push_back( aVal );
676
0
        }
677
678
        static Sequence<OUString> CreateChoice(const TranslateId* pResourceId, size_t nCount)
679
0
        {
680
0
            Sequence<OUString> aChoices (nCount);
681
0
            std::transform(pResourceId, pResourceId + nCount, aChoices.getArray(),
682
0
                           [](const auto& id) { return SdResId(id); });
683
0
            return aChoices;
684
0
        }
685
686
        Sequence<OUString> GetSlidesPerPageSequence()
687
0
        {
688
0
            const Sequence<OUString> aChoice (
689
0
                CreateChoice(STR_IMPRESS_PRINT_UI_SLIDESPERPAGE_CHOICES, std::size(STR_IMPRESS_PRINT_UI_SLIDESPERPAGE_CHOICES)));
690
0
            maSlidesPerPage.clear();
691
0
            maSlidesPerPage.push_back(0); // first is using the default
692
0
            std::transform(std::next(aChoice.begin()), aChoice.end(), std::back_inserter(maSlidesPerPage),
693
0
                            [](const OUString& rChoice) -> sal_Int32 { return rChoice.toInt32(); });
694
0
            return aChoice;
695
0
        }
696
    };
697
698
    /** The Prepare... methods of the DocumentRenderer::Implementation class
699
        create a set of PrinterPage objects that contain all necessary
700
        information to do the actual printing.  There is one PrinterPage
701
        object per printed page.  Derived classes implement the actual, mode
702
        specific printing.
703
704
        This and all derived classes support the asynchronous printing
705
        process by not storing pointers to any data with lifetime shorter
706
        than the PrinterPage objects, i.e. slides, shapes, (one of) the
707
        outliner (of the document).
708
    */
709
    class PrinterPage
710
    {
711
    public:
712
        PrinterPage (
713
            const PageKind ePageKind,
714
            const MapMode& rMapMode,
715
            const bool bPrintMarkedOnly,
716
            OUString sPageString,
717
            const Point& rPageStringOffset,
718
            const DrawModeFlags nDrawMode,
719
            const Orientation eOrientation,
720
            const sal_uInt16 nPaperTray)
721
0
            : mePageKind(ePageKind),
722
0
              maMap(rMapMode),
723
0
              mbPrintMarkedOnly(bPrintMarkedOnly),
724
0
              msPageString(std::move(sPageString)),
725
0
              maPageStringOffset(rPageStringOffset),
726
0
              mnDrawMode(nDrawMode),
727
0
              meOrientation(eOrientation),
728
0
              mnPaperTray(nPaperTray)
729
0
        {
730
0
        }
731
732
0
        virtual ~PrinterPage() {}
733
734
        virtual void Print (
735
            Printer& rPrinter,
736
            SdDrawDocument& rDocument,
737
            ViewShell& rViewShell,
738
            View* pView,
739
            DrawView& rPrintView,
740
            const SdrLayerIDSet& rVisibleLayers,
741
            const SdrLayerIDSet& rPrintableLayers) const = 0;
742
743
0
        DrawModeFlags GetDrawMode() const { return mnDrawMode; }
744
0
        Orientation GetOrientation() const { return meOrientation; }
745
0
        sal_uInt16 GetPaperTray() const { return mnPaperTray; }
746
747
    protected:
748
        const PageKind mePageKind;
749
        const MapMode maMap;
750
        const bool mbPrintMarkedOnly;
751
        const OUString msPageString;
752
        const Point maPageStringOffset;
753
        const DrawModeFlags mnDrawMode;
754
        const Orientation meOrientation;
755
        const sal_uInt16 mnPaperTray;
756
    };
757
758
    /** The RegularPrinterPage is used for printing one regular slide (no
759
        notes, handout, or outline) to one printer page.
760
    */
761
    class RegularPrinterPage : public PrinterPage
762
    {
763
    public:
764
        RegularPrinterPage (
765
            const sal_uInt16 nPageIndex,
766
            const PageKind ePageKind,
767
            const MapMode& rMapMode,
768
            const bool bPrintMarkedOnly,
769
            const OUString& rsPageString,
770
            const Point& rPageStringOffset,
771
            const DrawModeFlags nDrawMode,
772
            const Orientation eOrientation,
773
            const sal_uInt16 nPaperTray)
774
0
            : PrinterPage(ePageKind, rMapMode, bPrintMarkedOnly, rsPageString,
775
0
                rPageStringOffset, nDrawMode, eOrientation, nPaperTray),
776
0
              mnPageIndex(nPageIndex)
777
0
        {
778
0
        }
779
780
        virtual void Print (
781
            Printer& rPrinter,
782
            SdDrawDocument& rDocument,
783
            ViewShell&,
784
            View* pView,
785
            DrawView& rPrintView,
786
            const SdrLayerIDSet& rVisibleLayers,
787
            const SdrLayerIDSet& rPrintableLayers) const override
788
0
        {
789
0
            SdPage* pPageToPrint = rDocument.GetSdPage(mnPageIndex, mePageKind);
790
0
            rPrinter.SetMapMode(maMap);
791
0
            PrintPage(
792
0
                rPrinter,
793
0
                rPrintView,
794
0
                *pPageToPrint,
795
0
                pView,
796
0
                mbPrintMarkedOnly,
797
0
                rVisibleLayers,
798
0
                rPrintableLayers);
799
0
            PrintMessage(
800
0
                rPrinter,
801
0
                msPageString,
802
0
                maPageStringOffset);
803
0
        }
804
805
    private:
806
        const sal_uInt16 mnPageIndex;
807
    };
808
809
    /** The NotesPrinterPage is used for printing notes pages onto one or more printer pages
810
    */
811
    class NotesPrinterPage : public PrinterPage
812
    {
813
    public:
814
        NotesPrinterPage(
815
            const sal_uInt16 nPageIndex,
816
            const sal_Int32 nPageNumb,
817
            const sal_Int32 nPageCount,
818
            const bool bScaled,
819
            const PageKind ePageKind,
820
            const MapMode& rMapMode,
821
            const bool bPrintMarkedOnly,
822
            const OUString& rsPageString,
823
            const Point& rPageStringOffset,
824
            const DrawModeFlags nDrawMode,
825
            const Orientation eOrientation,
826
            const sal_uInt16 nPaperTray)
827
0
            : PrinterPage(ePageKind, rMapMode, bPrintMarkedOnly, rsPageString, rPageStringOffset,
828
0
                          nDrawMode, eOrientation, nPaperTray),
829
0
              mnPageIndex(nPageIndex),
830
0
              mnPageNumb(nPageNumb),
831
0
              mnPageCount(nPageCount),
832
0
              mbScaled(bScaled)
833
0
        {
834
0
        }
835
836
        virtual void Print(
837
            Printer& rPrinter,
838
            SdDrawDocument& rDocument,
839
            ViewShell&,
840
            View* pView,
841
            DrawView& rPrintView,
842
            const SdrLayerIDSet& rVisibleLayers,
843
            const SdrLayerIDSet& rPrintableLayers) const override
844
0
        {
845
0
            SdPage* pPageToPrint = rDocument.GetSdPage(mnPageIndex, mePageKind);
846
0
            rPrinter.SetMapMode(maMap);
847
848
            // Clone the current page to create an independent instance for modifications.
849
            // This ensures that changes made to pNotesPage do not affect the original page.
850
0
            rtl::Reference<SdPage> pNotesPage
851
0
                = static_cast<SdPage*>(pPageToPrint->CloneSdrPage(rDocument).get());
852
853
0
            Size aPageSize;
854
0
            if (mbScaled)
855
0
            {
856
0
                aPageSize = pNotesPage->GetSize();
857
0
                lcl_AdjustPageSize(aPageSize, rPrinter.GetPrintPageSize());
858
0
            }
859
0
            else
860
0
                aPageSize = rPrinter.GetPrintPageSize();
861
862
            // Adjusts the objects on the notes page to fit the new page size.
863
0
            ::tools::Rectangle aNewBorderRect(-1, -1, -1, -1);
864
0
            pNotesPage->ScaleObjects(aPageSize, aNewBorderRect, true);
865
866
0
            SdrObject* pNotesObj = pNotesPage->GetPresObj(PresObjKind::Notes);
867
0
            if (pNotesObj)
868
0
            {
869
                // new page(s) margins
870
0
                sal_Int32 nLeft = aPageSize.Width() * 0.1;
871
0
                sal_Int32 nRight = nLeft;
872
0
                sal_Int32 nTop = aPageSize.Height() * 0.075;
873
0
                sal_Int32 nBottom = nTop;
874
875
0
                Point aNotesPt = pNotesObj->GetRelativePos();
876
0
                Size aNotesSize = pNotesObj->GetLogicRect().GetSize();
877
878
0
                Outliner* pOut = rDocument.GetInternalOutliner();
879
0
                const OutlinerMode nSaveOutlMode(pOut->GetOutlinerMode());
880
0
                const bool bSavedUpdateMode(pOut->IsUpdateLayout());
881
0
                pOut->SetPaperSize(aNotesSize);
882
0
                pOut->SetUpdateLayout(true);
883
0
                pOut->Clear();
884
0
                if (OutlinerParaObject* pOutlinerParaObject = pNotesObj->GetOutlinerParaObject())
885
0
                    pOut->SetText(*pOutlinerParaObject);
886
887
0
                bool bAutoGrow = pNotesObj->GetMergedItem(SDRATTR_TEXT_AUTOGROWHEIGHT).GetValue();
888
889
                // If AutoGrowHeight property is enabled and the notes page has a lower border,
890
                // use the lower border but if there is no lower border, use the bottom margin
891
                // to determine the first page break position.
892
                // If AutoGrow is not enabled, the notes object defines the first page break.
893
0
                ::tools::Long nNotesPageBottom
894
0
                    = bAutoGrow ? (pNotesPage->GetLowerBorder() != 0)
895
0
                                      ? aPageSize.Height() - pNotesPage->GetLowerBorder()
896
0
                                      : aPageSize.Height() - nBottom
897
0
                                : aNotesPt.Y() + aNotesSize.Height();
898
0
                if (mbScaled)
899
0
                {
900
0
                    sal_Int32 nTextHeight = aNotesPt.Y() + pOut->GetTextHeight();
901
0
                    if (bAutoGrow && (nTextHeight > nNotesPageBottom))
902
0
                    {
903
0
                        pNotesObj->SetMergedItem(SdrOnOffItem(SDRATTR_TEXT_AUTOGROWHEIGHT, false));
904
905
0
                        ::tools::Long nObjW = aNotesSize.Width();
906
0
                        ::tools::Long nObjH = aPageSize.Height() - aNotesPt.Y() - nBottom;
907
908
0
                        pNotesObj->SetLogicRect(::tools::Rectangle(aNotesPt, Size(nObjW, nObjH)));
909
0
                    }
910
0
                    SdrTextFitToSizeTypeItem eFitToSize = drawing::TextFitToSizeType_AUTOFIT;
911
0
                    pNotesObj->SetMergedItem(eFitToSize);
912
0
                }
913
0
                else // original size
914
0
                {
915
0
                    bool bExit = false;
916
0
                    sal_Int32 nPrevLineLen = 0;
917
0
                    sal_Int32 nPrevParaIdx = 0;
918
0
                    sal_uInt16 nActualPageNumb = 1;
919
0
                    sal_uInt16 nPrevParaLowerSpace = 0;
920
0
                    ::tools::Long nCurrentPosY = aNotesPt.Y();
921
0
                    sal_Int32 nParaCount = pOut->GetParagraphCount();
922
0
                    std::vector<std::pair<sal_Int32, sal_Int32>> aPageBreaks;
923
924
0
                    for (sal_Int32 i = 0; i < nParaCount && !bExit; ++i)
925
0
                    {
926
0
                        sal_Int32 nActualLineLen = 0;
927
0
                        sal_Int32 nLineCount = pOut->GetLineCount(i);
928
929
0
                        sal_uInt16 nLowerSpace = 0;
930
0
                        sal_uInt16 nUpperSpace = nPrevParaLowerSpace;
931
0
                        const SfxItemSet* pItemSet = &pOut->GetParaAttribs(i);
932
0
                        if(pItemSet->HasItem(EE_PARA_ULSPACE))
933
0
                        {
934
0
                            nLowerSpace = pItemSet->Get(EE_PARA_ULSPACE).GetLower();
935
0
                            nUpperSpace = (i != 0) ? pItemSet->Get(EE_PARA_ULSPACE).GetUpper() : 0;
936
0
                            if (nPrevParaLowerSpace > nUpperSpace)
937
0
                                nUpperSpace = nPrevParaLowerSpace;
938
0
                        }
939
940
0
                        for (sal_Int32 j = 0; j < nLineCount; ++j)
941
0
                        {
942
0
                            nActualLineLen += pOut->GetLineLen(i, j);
943
0
                            sal_Int32 nLineHeight = pOut->GetLineHeight(i, j);
944
945
0
                            if (nUpperSpace != 0 && (i > 0) && (j == 0))
946
0
                                nLineHeight += nUpperSpace;
947
948
0
                            sal_Int32 nNextPosY = nCurrentPosY + nLineHeight;
949
950
0
                            if (nNextPosY > nNotesPageBottom)
951
0
                            {
952
                                // If the current or the next page matches the print page
953
                                // calculate and add a page break, since we only want to add
954
                                // a page break if the page is relevant.
955
0
                                if (mnPageNumb == nActualPageNumb
956
0
                                    || mnPageNumb == nActualPageNumb + 1)
957
0
                                {
958
0
                                    if (!aPageBreaks.empty())
959
0
                                    {
960
                                        // determine the page break at the bottom of the page
961
                                        // for pages that have both a previous and a following page
962
0
                                        aPageBreaks.emplace_back(
963
0
                                            nPrevParaIdx - aPageBreaks[0].first, nPrevLineLen);
964
0
                                    }
965
0
                                    else
966
0
                                    {
967
0
                                        if (mnPageNumb == 1 || (nLineCount > 1 && j != 0))
968
0
                                        {
969
                                            // first page or multi-line paragraphs
970
0
                                            aPageBreaks.emplace_back(nPrevParaIdx, nPrevLineLen);
971
0
                                        }
972
0
                                        else
973
0
                                        {   // single-line paragraphs
974
0
                                            aPageBreaks.emplace_back(nPrevParaIdx + 1, 0);
975
0
                                        }
976
0
                                    }
977
978
0
                                    if (mnPageNumb == nActualPageNumb || mnPageNumb == mnPageCount)
979
0
                                    {
980
0
                                        bExit = true;
981
0
                                        break;
982
0
                                    }
983
0
                                }
984
985
0
                                if (nUpperSpace > 0)
986
0
                                    nLineHeight -= nUpperSpace;
987
988
0
                                nNotesPageBottom = aPageSize.Height() - nBottom;
989
0
                                nCurrentPosY = nTop;
990
0
                                nActualPageNumb++;
991
0
                                nActualLineLen = 0;
992
0
                            }
993
0
                            nPrevParaIdx = i;
994
0
                            nPrevLineLen = nActualLineLen;
995
0
                            nCurrentPosY += nLineHeight;
996
0
                        }
997
0
                        nPrevParaLowerSpace = nLowerSpace;
998
0
                    }
999
1000
0
                    if (!aPageBreaks.empty())
1001
0
                    {
1002
0
                        ESelection aE;
1003
0
                        if (mnPageNumb == 1)
1004
0
                        {
1005
0
                            aE.start.nPara = aPageBreaks[0].first;
1006
0
                            aE.start.nIndex = aPageBreaks[0].second;
1007
0
                            aE.end.nPara = pOut->GetParagraphCount() - 1;
1008
0
                            aE.end.nIndex = pOut->GetText(pOut->GetParagraph(aE.end.nPara)).getLength();
1009
0
                            pOut->QuickDelete(aE);
1010
0
                        }
1011
0
                        else
1012
0
                        {
1013
0
                            sal_Int16 nDepth = pOut->GetDepth(aPageBreaks[0].first);
1014
0
                            SfxItemSet aItemSet = pOut->GetParaAttribs(aPageBreaks[0].first);
1015
1016
0
                            aE.start.nPara = 0;
1017
0
                            aE.start.nIndex = 0;
1018
0
                            aE.end.nPara = aPageBreaks[0].first;
1019
0
                            aE.end.nIndex = aPageBreaks[0].second;
1020
0
                            pOut->QuickDelete(aE);
1021
1022
0
                            Paragraph* pFirstPara = pOut->GetParagraph(0);
1023
0
                            pOut->SetDepth(pFirstPara, nDepth);
1024
0
                            pOut->SetParaAttribs(0, aItemSet);
1025
1026
0
                            if (aPageBreaks.size() > 1)
1027
0
                            {
1028
0
                                aE.start.nPara = aPageBreaks[1].first;
1029
0
                                aE.start.nIndex = aPageBreaks[1].second;
1030
0
                                aE.end.nPara = pOut->GetParagraphCount() - 1;
1031
0
                                aE.end.nIndex = pOut->GetText(pOut->GetParagraph(aE.end.nPara)).getLength();
1032
0
                                pOut->QuickDelete(aE);
1033
0
                            }
1034
0
                        }
1035
0
                    }
1036
0
                    pNotesObj->SetOutlinerParaObject(pOut->CreateParaObject());
1037
1038
0
                    Size aObjSize;
1039
0
                    if (mnPageNumb != 1) // new page(s)
1040
0
                    {
1041
0
                        SdrObjListIter aShapeIter(pNotesPage.get());
1042
0
                        while (aShapeIter.IsMore())
1043
0
                        {
1044
0
                            SdrObject* pObj = aShapeIter.Next();
1045
0
                            if (pObj && pObj->GetObjIdentifier() != SdrObjKind::Text)
1046
0
                                pNotesPage->RemoveObject(pObj->GetOrdNum());
1047
0
                        }
1048
1049
0
                        aNotesPt.setX(nLeft);
1050
0
                        aNotesPt.setY(nTop);
1051
0
                        ::tools::Long nWidth = aPageSize.Width() - nLeft - nRight;
1052
0
                        aObjSize = Size(nWidth, pOut->GetTextHeight());
1053
0
                    }
1054
0
                    else // first page
1055
0
                    {
1056
0
                        if (!bAutoGrow)
1057
0
                            aObjSize = aNotesSize;
1058
0
                        else
1059
0
                            aObjSize = Size(aNotesSize.Width(), pOut->GetTextHeight());
1060
0
                    }
1061
0
                    pNotesObj->SetLogicRect(::tools::Rectangle(aNotesPt, aObjSize));
1062
0
                }
1063
0
                pOut->Clear();
1064
0
                pOut->SetUpdateLayout(bSavedUpdateMode);
1065
0
                pOut->Init(nSaveOutlMode);
1066
0
            }
1067
0
            pNotesPage->SetSize(aPageSize);
1068
1069
0
            PrintPage(
1070
0
                rPrinter,
1071
0
                rPrintView,
1072
0
                *pNotesPage,
1073
0
                pView,
1074
0
                mbPrintMarkedOnly,
1075
0
                rVisibleLayers,
1076
0
                rPrintableLayers);
1077
0
            PrintMessage(
1078
0
                rPrinter,
1079
0
                msPageString,
1080
0
                maPageStringOffset);
1081
0
        }
1082
1083
    private:
1084
        const sal_uInt16 mnPageIndex;
1085
        const sal_Int32 mnPageNumb;
1086
        const sal_Int32 mnPageCount;
1087
        const bool mbScaled;
1088
    };
1089
1090
    /** Print one slide multiple times on a printer page so that the whole
1091
        printer page is covered.
1092
    */
1093
    class TiledPrinterPage : public PrinterPage
1094
    {
1095
    public:
1096
        TiledPrinterPage (
1097
            const sal_uInt16 nPageIndex,
1098
            const PageKind ePageKind,
1099
            const bool bPrintMarkedOnly,
1100
            const OUString& rsPageString,
1101
            const Point& rPageStringOffset,
1102
            const DrawModeFlags nDrawMode,
1103
            const Orientation eOrientation,
1104
            const sal_uInt16 nPaperTray)
1105
0
            : PrinterPage(ePageKind, MapMode(), bPrintMarkedOnly, rsPageString,
1106
0
                rPageStringOffset, nDrawMode, eOrientation, nPaperTray),
1107
0
              mnPageIndex(nPageIndex)
1108
0
        {
1109
0
        }
1110
1111
        virtual void Print (
1112
            Printer& rPrinter,
1113
            SdDrawDocument& rDocument,
1114
            ViewShell&,
1115
            View* pView,
1116
            DrawView& rPrintView,
1117
            const SdrLayerIDSet& rVisibleLayers,
1118
            const SdrLayerIDSet& rPrintableLayers) const override
1119
0
        {
1120
0
            SdPage* pPageToPrint = rDocument.GetSdPage(mnPageIndex, mePageKind);
1121
0
            if (pPageToPrint==nullptr)
1122
0
                return;
1123
0
            MapMode aMap (rPrinter.GetMapMode());
1124
1125
0
            const Size aPageSize (pPageToPrint->GetSize());
1126
0
            const Size aPrintSize (rPrinter.GetOutputSize());
1127
1128
0
            const sal_Int32 nPageWidth (aPageSize.Width() + mnGap
1129
0
                - pPageToPrint->GetLeftBorder() - pPageToPrint->GetRightBorder());
1130
0
            const sal_Int32 nPageHeight (aPageSize.Height() + mnGap
1131
0
                - pPageToPrint->GetUpperBorder() - pPageToPrint->GetLowerBorder());
1132
0
            if (nPageWidth<=0 || nPageHeight<=0)
1133
0
                return;
1134
1135
            // Print at least two rows and columns.  More if the document
1136
            // page fits completely onto the printer page.
1137
0
            const sal_Int32 nColumnCount (std::max(sal_Int32(2),
1138
0
                    sal_Int32(aPrintSize.Width() / nPageWidth)));
1139
0
            const sal_Int32 nRowCount (std::max(sal_Int32(2),
1140
0
                    sal_Int32(aPrintSize.Height() / nPageHeight)));
1141
0
            for (sal_Int32 nRow=0; nRow<nRowCount; ++nRow)
1142
0
                for (sal_Int32 nColumn=0; nColumn<nColumnCount; ++nColumn)
1143
0
                {
1144
0
                    aMap.SetOrigin(Point(nColumn*nPageWidth,nRow*nPageHeight));
1145
0
                    rPrinter.SetMapMode(aMap);
1146
0
                    PrintPage(
1147
0
                        rPrinter,
1148
0
                        rPrintView,
1149
0
                        *pPageToPrint,
1150
0
                        pView,
1151
0
                        mbPrintMarkedOnly,
1152
0
                        rVisibleLayers,
1153
0
                        rPrintableLayers);
1154
0
                }
1155
1156
0
            PrintMessage(
1157
0
                rPrinter,
1158
0
                msPageString,
1159
0
                maPageStringOffset);
1160
0
        }
1161
1162
    private:
1163
        const sal_uInt16 mnPageIndex;
1164
        static const sal_Int32 mnGap = 500;
1165
    };
1166
1167
    /** Print two slides to one printer page so that the resulting pages
1168
        form a booklet.
1169
    */
1170
    class BookletPrinterPage : public PrinterPage
1171
    {
1172
    public:
1173
        BookletPrinterPage (
1174
            const sal_uInt16 nFirstPageIndex,
1175
            const sal_uInt16 nSecondPageIndex,
1176
            const Point& rFirstOffset,
1177
            const Point& rSecondOffset,
1178
            const PageKind ePageKind,
1179
            const MapMode& rMapMode,
1180
            const bool bPrintMarkedOnly,
1181
            const DrawModeFlags nDrawMode,
1182
            const Orientation eOrientation,
1183
            const sal_uInt16 nPaperTray)
1184
0
            : PrinterPage(ePageKind, rMapMode, bPrintMarkedOnly, u""_ustr,
1185
0
                Point(), nDrawMode, eOrientation, nPaperTray),
1186
0
              mnFirstPageIndex(nFirstPageIndex),
1187
0
              mnSecondPageIndex(nSecondPageIndex),
1188
0
              maFirstOffset(rFirstOffset),
1189
0
              maSecondOffset(rSecondOffset)
1190
0
        {
1191
0
        }
1192
1193
        virtual void Print (
1194
            Printer& rPrinter,
1195
            SdDrawDocument& rDocument,
1196
            ViewShell&,
1197
            View* pView,
1198
            DrawView& rPrintView,
1199
            const SdrLayerIDSet& rVisibleLayers,
1200
            const SdrLayerIDSet& rPrintableLayers) const override
1201
0
        {
1202
0
            MapMode aMap (maMap);
1203
0
            SdPage* pPageToPrint = rDocument.GetSdPage(mnFirstPageIndex, mePageKind);
1204
0
            if (pPageToPrint)
1205
0
            {
1206
0
                aMap.SetOrigin(maFirstOffset);
1207
0
                rPrinter.SetMapMode(aMap);
1208
0
                PrintPage(
1209
0
                    rPrinter,
1210
0
                    rPrintView,
1211
0
                    *pPageToPrint,
1212
0
                    pView,
1213
0
                    mbPrintMarkedOnly,
1214
0
                    rVisibleLayers,
1215
0
                    rPrintableLayers);
1216
0
            }
1217
1218
0
            pPageToPrint = rDocument.GetSdPage(mnSecondPageIndex, mePageKind);
1219
0
            if( !pPageToPrint )
1220
0
                return;
1221
1222
0
            aMap.SetOrigin(maSecondOffset);
1223
0
            rPrinter.SetMapMode(aMap);
1224
0
            PrintPage(
1225
0
                rPrinter,
1226
0
                rPrintView,
1227
0
                *pPageToPrint,
1228
0
                pView,
1229
0
                mbPrintMarkedOnly,
1230
0
                rVisibleLayers,
1231
0
                rPrintableLayers);
1232
0
        }
1233
1234
    private:
1235
        const sal_uInt16 mnFirstPageIndex;
1236
        const sal_uInt16 mnSecondPageIndex;
1237
        const Point maFirstOffset;
1238
        const Point maSecondOffset;
1239
    };
1240
1241
    /** One handout page displays one to nine slides.
1242
    */
1243
    class HandoutPrinterPage : public PrinterPage
1244
    {
1245
    public:
1246
        HandoutPrinterPage (
1247
            const sal_uInt16 nHandoutPageIndex,
1248
            std::vector<sal_uInt16>&& rPageIndices,
1249
            const MapMode& rMapMode,
1250
            const OUString& rsPageString,
1251
            const Point& rPageStringOffset,
1252
            const DrawModeFlags nDrawMode,
1253
            const Orientation eOrientation,
1254
            const sal_uInt16 nPaperTray)
1255
0
            : PrinterPage(PageKind::Handout, rMapMode, false, rsPageString,
1256
0
                rPageStringOffset, nDrawMode, eOrientation, nPaperTray),
1257
0
              mnHandoutPageIndex(nHandoutPageIndex),
1258
0
              maPageIndices(std::move(rPageIndices))
1259
0
        {
1260
0
        }
1261
1262
        virtual void Print (
1263
            Printer& rPrinter,
1264
            SdDrawDocument& rDocument,
1265
            ViewShell& rViewShell,
1266
            View* pView,
1267
            DrawView& rPrintView,
1268
            const SdrLayerIDSet& rVisibleLayers,
1269
            const SdrLayerIDSet& rPrintableLayers) const override
1270
0
        {
1271
0
            SdPage& rHandoutPage (*rDocument.GetSdPage(0, PageKind::Handout));
1272
1273
0
            Size aPageSize(rHandoutPage.GetSize());
1274
0
            Size aPrintPageSize = rPrinter.GetPrintPageSize();
1275
1276
0
            if ((aPageSize.Width() < aPageSize.Height()
1277
0
                 && aPrintPageSize.Width() > aPrintPageSize.Height())
1278
0
                || (aPageSize.Width() > aPageSize.Height()
1279
0
                    && aPrintPageSize.Width() < aPrintPageSize.Height()))
1280
0
            {
1281
0
                ::tools::Long nTmp = aPageSize.Width();
1282
0
                aPageSize.setWidth(aPageSize.Height());
1283
0
                aPageSize.setHeight(nTmp);
1284
1285
0
                rHandoutPage.SetSize(aPageSize);
1286
0
            }
1287
1288
0
            Reference< css::beans::XPropertySet > xHandoutPage( rHandoutPage.getUnoPage(), UNO_QUERY );
1289
0
            static constexpr OUString sPageNumber( u"Number"_ustr );
1290
1291
            // Collect the page objects of the handout master.
1292
0
            std::vector<SdrPageObj*> aHandoutPageObjects;
1293
0
            SdrObjListIter aShapeIter (&rHandoutPage);
1294
0
            while (aShapeIter.IsMore())
1295
0
            {
1296
0
                SdrPageObj* pPageObj = dynamic_cast<SdrPageObj*>(aShapeIter.Next());
1297
0
                if (pPageObj)
1298
0
                    aHandoutPageObjects.push_back(pPageObj);
1299
0
            }
1300
0
            if (aHandoutPageObjects.empty())
1301
0
                return;
1302
1303
            // Connect page objects with pages.
1304
0
            std::vector<SdrPageObj*>::iterator aPageObjIter (aHandoutPageObjects.begin());
1305
0
            for (std::vector<sal_uInt16>::const_iterator
1306
0
                     iPageIndex(maPageIndices.begin()),
1307
0
                     iEnd(maPageIndices.end());
1308
0
                 iPageIndex!=iEnd && aPageObjIter!=aHandoutPageObjects.end();
1309
0
                 ++iPageIndex)
1310
0
            {
1311
                // Check if the page still exists.
1312
0
                if (*iPageIndex >= rDocument.GetSdPageCount(PageKind::Standard))
1313
0
                    continue;
1314
1315
0
                SdrPageObj* pPageObj = *aPageObjIter++;
1316
0
                pPageObj->SetReferencedPage(rDocument.GetSdPage(*iPageIndex, PageKind::Standard));
1317
0
            }
1318
1319
            // if there are more page objects than pages left, set the rest to invisible
1320
0
            int nHangoverCount = 0;
1321
0
            while (aPageObjIter != aHandoutPageObjects.end())
1322
0
            {
1323
0
                (*aPageObjIter++)->SetReferencedPage(nullptr);
1324
0
                nHangoverCount++;
1325
0
            }
1326
1327
            // Hide outlines for objects that have pages attached.
1328
0
            if (nHangoverCount > 0)
1329
0
            {
1330
0
                int nSkip = aHandoutPageObjects.size() - nHangoverCount;
1331
0
                aShapeIter.Reset();
1332
0
                while (aShapeIter.IsMore())
1333
0
                {
1334
0
                    SdrPathObj* pPathObj = dynamic_cast<SdrPathObj*>(aShapeIter.Next());
1335
0
                    if (pPathObj)
1336
0
                    {
1337
0
                        if (nSkip > 0)
1338
0
                            --nSkip;
1339
0
                        else
1340
0
                            pPathObj->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1341
0
                    }
1342
0
                }
1343
0
            }
1344
1345
0
            if( xHandoutPage.is() ) try
1346
0
            {
1347
0
                xHandoutPage->setPropertyValue( sPageNumber, Any( static_cast<sal_Int16>(mnHandoutPageIndex) ) );
1348
0
            }
1349
0
            catch( Exception& )
1350
0
            {
1351
0
            }
1352
0
            rViewShell.SetPrintedHandoutPageNum( mnHandoutPageIndex + 1 );
1353
1354
0
            rPrinter.SetMapMode(maMap);
1355
1356
0
            PrintPage(
1357
0
                rPrinter,
1358
0
                rPrintView,
1359
0
                rHandoutPage,
1360
0
                pView,
1361
0
                false,
1362
0
                rVisibleLayers,
1363
0
                rPrintableLayers);
1364
0
            PrintMessage(
1365
0
                rPrinter,
1366
0
                msPageString,
1367
0
                maPageStringOffset);
1368
1369
0
            if( xHandoutPage.is() ) try
1370
0
            {
1371
0
                xHandoutPage->setPropertyValue( sPageNumber, Any( static_cast<sal_Int16>(0) ) );
1372
0
            }
1373
0
            catch( Exception& )
1374
0
            {
1375
0
            }
1376
0
            rViewShell.SetPrintedHandoutPageNum(1);
1377
1378
            // Restore outlines.
1379
0
            if (nHangoverCount > 0)
1380
0
            {
1381
0
                aShapeIter.Reset();
1382
0
                while (aShapeIter.IsMore())
1383
0
                {
1384
0
                    SdrPathObj* pPathObj = dynamic_cast<SdrPathObj*>(aShapeIter.Next());
1385
0
                    if (pPathObj != nullptr)
1386
0
                        pPathObj->SetMergedItem(XLineStyleItem(drawing::LineStyle_SOLID));
1387
0
                }
1388
0
            }
1389
1390
0
       }
1391
1392
    private:
1393
        const sal_uInt16 mnHandoutPageIndex;
1394
        const std::vector<sal_uInt16> maPageIndices;
1395
    };
1396
1397
    /** The outline information (title, subtitle, outline objects) of the
1398
        document.  There is no fixed mapping of slides to printer pages.
1399
    */
1400
    class OutlinerPrinterPage : public PrinterPage
1401
    {
1402
    public:
1403
        OutlinerPrinterPage (
1404
            std::optional<OutlinerParaObject> pParaObject,
1405
            const MapMode& rMapMode,
1406
            const OUString& rsPageString,
1407
            const Point& rPageStringOffset,
1408
            const DrawModeFlags nDrawMode,
1409
            const Orientation eOrientation,
1410
            const sal_uInt16 nPaperTray)
1411
0
            : PrinterPage(PageKind::Handout, rMapMode, false, rsPageString,
1412
0
                rPageStringOffset, nDrawMode, eOrientation, nPaperTray),
1413
0
              mpParaObject(std::move(pParaObject))
1414
0
        {
1415
0
        }
1416
1417
        virtual void Print (
1418
            Printer& rPrinter,
1419
            SdDrawDocument& rDocument,
1420
            ViewShell&,
1421
            View*,
1422
            DrawView&,
1423
            const SdrLayerIDSet&,
1424
            const SdrLayerIDSet&) const override
1425
0
        {
1426
            // Set up the printer.
1427
0
            rPrinter.SetMapMode(maMap);
1428
1429
            // Get and set up the outliner.
1430
0
            const ::tools::Rectangle aOutRect (rPrinter.GetPageOffset(), rPrinter.GetOutputSize());
1431
0
            Outliner* pOutliner = rDocument.GetInternalOutliner();
1432
0
            const OutlinerMode nSavedOutlMode (pOutliner->GetOutlinerMode());
1433
0
            const bool bSavedUpdateMode (pOutliner->IsUpdateLayout());
1434
0
            const Size aSavedPaperSize (pOutliner->GetPaperSize());
1435
1436
0
            pOutliner->Init(OutlinerMode::OutlineView);
1437
0
            pOutliner->SetPaperSize(aOutRect.GetSize());
1438
0
            pOutliner->SetUpdateLayout(true);
1439
0
            pOutliner->Clear();
1440
0
            pOutliner->SetText(*mpParaObject);
1441
1442
0
            pOutliner->DrawText_ToRectangle(rPrinter, aOutRect);
1443
1444
0
            PrintMessage(
1445
0
                rPrinter,
1446
0
                msPageString,
1447
0
                maPageStringOffset);
1448
1449
            // Restore outliner and printer.
1450
0
            pOutliner->Clear();
1451
0
            pOutliner->SetUpdateLayout(bSavedUpdateMode);
1452
0
            pOutliner->SetPaperSize(aSavedPaperSize);
1453
0
            pOutliner->Init(nSavedOutlMode);
1454
0
        }
1455
1456
    private:
1457
        std::optional<OutlinerParaObject> mpParaObject;
1458
    };
1459
}
1460
1461
//===== DocumentRenderer::Implementation ======================================
1462
1463
class DocumentRenderer::Implementation
1464
    : public SfxListener,
1465
      public vcl::PrinterOptionsHelper
1466
{
1467
public:
1468
    explicit Implementation (ViewShellBase& rBase)
1469
0
        : mxObjectShell(rBase.GetDocShell())
1470
0
        , mrBase(rBase)
1471
0
        , mbIsDisposed(false)
1472
0
        , mpPrinter(nullptr)
1473
0
        , mbHasOrientationWarningBeenShown(false)
1474
0
    {
1475
0
        DialogCreator aCreator( mrBase, mrBase.GetDocShell()->GetDocumentType() == DocumentType::Impress, GetCurrentPageIndex() );
1476
0
        m_aUIProperties = aCreator.GetDialogControls();
1477
0
        maSlidesPerPage = aCreator.GetSlidesPerPage();
1478
1479
0
        StartListening(mrBase);
1480
0
    }
1481
1482
    virtual ~Implementation() override
1483
0
    {
1484
0
        EndListening(mrBase);
1485
0
    }
1486
1487
    virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint) override
1488
0
    {
1489
0
        if (&rBroadcaster != &static_cast<SfxBroadcaster&>(mrBase))
1490
0
            return;
1491
1492
0
        if (rHint.GetId() == SfxHintId::Dying)
1493
0
        {
1494
0
            mbIsDisposed = true;
1495
0
        }
1496
0
    }
1497
1498
    /** Process the sequence of properties given to one of the XRenderable
1499
        methods.
1500
    */
1501
    void ProcessProperties (const css::uno::Sequence<css::beans::PropertyValue >& rOptions)
1502
0
    {
1503
0
        OSL_ASSERT(!mbIsDisposed);
1504
0
        if (mbIsDisposed)
1505
0
            return;
1506
1507
0
        bool bIsValueChanged = processProperties( rOptions );
1508
0
        bool bIsPaperChanged = false;
1509
1510
        // The RenderDevice property is handled specially: its value is
1511
        // stored in mpPrinter instead of being retrieved on demand.
1512
0
        Any aDev( getValue( u"RenderDevice"_ustr ) );
1513
0
        Reference<awt::XDevice> xRenderDevice;
1514
1515
0
        if (aDev >>= xRenderDevice)
1516
0
        {
1517
0
            VCLXDevice* pDevice = dynamic_cast<VCLXDevice*>(xRenderDevice.get());
1518
0
            VclPtr< OutputDevice > pOut = pDevice ? pDevice->GetOutputDevice()
1519
0
                                                  : VclPtr< OutputDevice >();
1520
0
            mpPrinter = dynamic_cast<Printer*>(pOut.get());
1521
0
            Size aPageSizePixel = mpPrinter ? mpPrinter->GetPaperSizePixel() : Size();
1522
0
            Size aPrintPageSize = mpPrinter ? mpPrinter->GetPrintPageSize() : Size();
1523
1524
0
            lcl_AdjustPageSize(aPageSizePixel, aPrintPageSize);
1525
1526
0
            if (aPageSizePixel != maPrinterPageSizePixel)
1527
0
            {
1528
0
                bIsPaperChanged = true;
1529
0
                maPrinterPageSizePixel = aPageSizePixel;
1530
0
            }
1531
0
        }
1532
1533
0
        if (bIsValueChanged && ! mpOptions )
1534
0
            mpOptions.reset(new PrintOptions(*this, std::vector(maSlidesPerPage)));
1535
0
        if( bIsValueChanged || bIsPaperChanged )
1536
0
            PreparePages();
1537
0
    }
1538
1539
    /** Return the number of pages that are to be printed.
1540
    */
1541
    sal_Int32 GetPrintPageCount() const
1542
0
    {
1543
0
        OSL_ASSERT(!mbIsDisposed);
1544
0
        if (mbIsDisposed)
1545
0
            return 0;
1546
0
        else
1547
0
            return maPrinterPages.size();
1548
0
    }
1549
1550
    /** Return a sequence of properties that can be returned by the
1551
        XRenderable::getRenderer() method.
1552
    */
1553
    css::uno::Sequence<css::beans::PropertyValue> GetProperties () const
1554
0
    {
1555
0
        css::uno::Sequence<css::beans::PropertyValue> aProperties{
1556
0
            comphelper::makePropertyValue(u"ExtraPrintUIOptions"_ustr,
1557
0
                                          comphelper::containerToSequence(m_aUIProperties)),
1558
0
            comphelper::makePropertyValue(u"PageSize"_ustr, maPrintSize),
1559
            // FIXME: is this always true ?
1560
0
            comphelper::makePropertyValue(u"PageIncludesNonprintableArea"_ustr, true)
1561
0
        };
1562
1563
0
        return aProperties;
1564
0
    }
1565
1566
    /** Print one of the prepared pages.
1567
    */
1568
    void PrintPage (const sal_Int32 nIndex)
1569
0
    {
1570
0
        OSL_ASSERT(!mbIsDisposed);
1571
0
        if (mbIsDisposed)
1572
0
            return;
1573
1574
0
        Printer& rPrinter (*mpPrinter);
1575
1576
0
        std::shared_ptr<ViewShell> pViewShell (mrBase.GetMainViewShell());
1577
0
        if ( ! pViewShell)
1578
0
            return;
1579
1580
0
        SdDrawDocument* pDocument = pViewShell->GetDoc();
1581
0
        assert(pDocument!=nullptr);
1582
1583
0
        std::shared_ptr<DrawViewShell> pDrawViewShell(
1584
0
            std::dynamic_pointer_cast<DrawViewShell>(pViewShell));
1585
1586
0
        if (!mpPrintView)
1587
0
            mpPrintView.reset(new DrawView(mrBase.GetDocShell(), &rPrinter, nullptr));
1588
1589
0
        if (nIndex<0 || sal::static_int_cast<sal_uInt32>(nIndex)>=maPrinterPages.size())
1590
0
            return;
1591
1592
0
        const std::shared_ptr<PrinterPage> pPage (maPrinterPages[nIndex]);
1593
0
        OSL_ASSERT(pPage);
1594
0
        if ( ! pPage)
1595
0
            return;
1596
1597
0
        const Orientation eSavedOrientation (rPrinter.GetOrientation());
1598
0
        const DrawModeFlags nSavedDrawMode (rPrinter.GetDrawMode());
1599
0
        const MapMode aSavedMapMode (rPrinter.GetMapMode());
1600
0
        const sal_uInt16 nSavedPaperBin (rPrinter.GetPaperBin());
1601
1602
        // Set page orientation.
1603
0
        if ( ! rPrinter.SetOrientation(pPage->GetOrientation()))
1604
0
        {
1605
0
            if ( ! mbHasOrientationWarningBeenShown
1606
0
                && mpOptions->IsWarningOrientation())
1607
0
            {
1608
0
                mbHasOrientationWarningBeenShown = true;
1609
                // Show warning that the orientation could not be set.
1610
0
                std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(
1611
0
                    pViewShell->GetFrameWeld(), VclMessageType::Warning, VclButtonsType::OkCancel,
1612
0
                    SdResId(STR_WARN_PRINTFORMAT_FAILURE)));
1613
0
                xWarn->set_default_response(RET_CANCEL);
1614
0
                if (xWarn->run() != RET_OK)
1615
0
                    return;
1616
0
            }
1617
0
        }
1618
1619
        // Set the draw mode.
1620
0
        rPrinter.SetDrawMode(pPage->GetDrawMode());
1621
1622
        // Set paper tray.
1623
0
        rPrinter.SetPaperBin(pPage->GetPaperTray());
1624
1625
        // Print the actual page.
1626
0
        pPage->Print(
1627
0
            rPrinter,
1628
0
            *pDocument,
1629
0
            *pViewShell,
1630
0
            pDrawViewShell ? pDrawViewShell->GetView() : nullptr,
1631
0
            *mpPrintView,
1632
0
            pViewShell->GetFrameView()->GetVisibleLayers(),
1633
0
            pViewShell->GetFrameView()->GetPrintableLayers());
1634
1635
0
        rPrinter.SetOrientation(eSavedOrientation);
1636
0
        rPrinter.SetDrawMode(nSavedDrawMode);
1637
0
        rPrinter.SetMapMode(aSavedMapMode);
1638
0
        rPrinter.SetPaperBin(nSavedPaperBin);
1639
0
    }
1640
1641
private:
1642
    // rhbz#657394: keep the document alive: prevents crash when
1643
    SfxObjectShellRef mxObjectShell; // destroying mpPrintView
1644
    ViewShellBase& mrBase;
1645
    bool mbIsDisposed;
1646
    VclPtr<Printer> mpPrinter;
1647
    Size maPrinterPageSizePixel;
1648
    std::unique_ptr<PrintOptions> mpOptions;
1649
    std::vector< std::shared_ptr< ::sd::PrinterPage> > maPrinterPages;
1650
    std::unique_ptr<DrawView> mpPrintView;
1651
    bool mbHasOrientationWarningBeenShown;
1652
    std::vector<sal_Int32> maSlidesPerPage;
1653
    awt::Size maPrintSize;
1654
1655
    sal_Int32 GetCurrentPageIndex() const
1656
0
    {
1657
0
        const ViewShell *pShell = mrBase.GetMainViewShell().get();
1658
0
        const SdPage *pCurrentPage = pShell ? pShell->getCurrentPage() : nullptr;
1659
0
        return pCurrentPage ? (pCurrentPage->GetPageNum()-1)/2 : -1;
1660
0
    }
1661
1662
    /** Determine and set the paper orientation.
1663
    */
1664
    void SetupPaperOrientation (
1665
        const PageKind ePageKind,
1666
        PrintInfo& rInfo)
1667
0
    {
1668
0
        SdDrawDocument* pDocument = mrBase.GetMainViewShell()->GetDoc();
1669
0
        rInfo.meOrientation = Orientation::Portrait;
1670
1671
0
        if( ! mpOptions->IsBooklet())
1672
0
        {
1673
0
            rInfo.meOrientation = pDocument->GetSdPage(0, ePageKind)->GetOrientation();
1674
0
        }
1675
0
        else if (rInfo.maPageSize.Width() < rInfo.maPageSize.Height())
1676
0
            rInfo.meOrientation = Orientation::Landscape;
1677
1678
        // Draw and Notes should usually abide by their specified paper size
1679
0
        Size aPaperSize;
1680
0
        if (!mpOptions->IsPrinterPreferred(pDocument->GetDocumentType()))
1681
0
        {
1682
0
            aPaperSize.setWidth(rInfo.maPageSize.Width());
1683
0
            aPaperSize.setHeight(rInfo.maPageSize.Height());
1684
0
        }
1685
0
        else
1686
0
        {
1687
0
            aPaperSize.setWidth(rInfo.mpPrinter->GetPaperSize().Width());
1688
0
            aPaperSize.setHeight(rInfo.mpPrinter->GetPaperSize().Height());
1689
1690
0
            if (!mpOptions->IsBooklet())
1691
0
                lcl_AdjustPageSize(aPaperSize, rInfo.mpPrinter->GetPrintPageSize());
1692
0
        }
1693
1694
0
        maPrintSize = awt::Size(aPaperSize.Width(), aPaperSize.Height());
1695
1696
0
        if (mpOptions->IsPrinterPreferred(pDocument->GetDocumentType())
1697
0
            && ePageKind == PageKind::Standard && !mpOptions->IsBooklet())
1698
0
        {
1699
0
            if( (rInfo.meOrientation == Orientation::Landscape &&
1700
0
                  (aPaperSize.Width() < aPaperSize.Height()))
1701
0
               ||
1702
0
                (rInfo.meOrientation == Orientation::Portrait &&
1703
0
                  (aPaperSize.Width() > aPaperSize.Height()))
1704
0
              )
1705
0
            {
1706
0
                maPrintSize = awt::Size(aPaperSize.Height(), aPaperSize.Width());
1707
0
            }
1708
0
        }
1709
0
    }
1710
1711
    /** Top most method for preparing printer pages.  In this and the other
1712
        Prepare... methods the various special cases are detected and
1713
        handled.
1714
        For every page that is to be printed (that may contain several
1715
        slides) one PrinterPage object is created and inserted into
1716
        maPrinterPages.
1717
    */
1718
    void PreparePages()
1719
0
    {
1720
0
        mpPrintView.reset();
1721
0
        maPrinterPages.clear();
1722
0
        mbHasOrientationWarningBeenShown = false;
1723
1724
0
        ViewShell* pShell = mrBase.GetMainViewShell().get();
1725
1726
0
        PrintInfo aInfo (mpPrinter, mpOptions->IsPrintMarkedOnly());
1727
1728
0
        if (aInfo.mpPrinter==nullptr || pShell==nullptr)
1729
0
            return;
1730
1731
0
        MapMode aMap (aInfo.mpPrinter->GetMapMode());
1732
0
        aMap.SetMapUnit(MapUnit::Map100thMM);
1733
0
        aInfo.maMap = aMap;
1734
0
        mpPrinter->SetMapMode(aMap);
1735
1736
0
        ::Outliner& rOutliner = mrBase.GetDocument()->GetDrawOutliner();
1737
0
        const EEControlBits nSavedControlWord (rOutliner.GetControlWord());
1738
0
        EEControlBits nCntrl = nSavedControlWord;
1739
0
        nCntrl &= ~EEControlBits::MARKFIELDS;
1740
0
        nCntrl &= ~EEControlBits::ONLINESPELLING;
1741
0
        rOutliner.SetControlWord( nCntrl );
1742
1743
        // When in outline view then apply all pending changes to the model.
1744
0
        if( auto pOutlineViewShell = dynamic_cast< OutlineViewShell *>( pShell ) )
1745
0
            pOutlineViewShell->PrepareClose (false);
1746
1747
        // Collect some frequently used data.
1748
0
        if (mpOptions->IsDate())
1749
0
        {
1750
0
            aInfo.msTimeDate += GetSdrGlobalData().GetLocaleData().getDate( Date( Date::SYSTEM ) );
1751
0
            aInfo.msTimeDate += " ";
1752
0
        }
1753
1754
0
        if (mpOptions->IsTime())
1755
0
            aInfo.msTimeDate += GetSdrGlobalData().GetLocaleData().getTime( ::tools::Time( ::tools::Time::SYSTEM ), false );
1756
1757
        // Draw and Notes should usually use specified paper size when printing
1758
0
        if (!mpOptions->IsPrinterPreferred(mrBase.GetDocShell()->GetDocumentType()))
1759
0
        {
1760
0
            aInfo.maPrintSize = mrBase.GetDocument()->GetSdPage(0, PageKind::Standard)->GetSize();
1761
0
            maPrintSize = awt::Size(aInfo.maPrintSize.Width(),
1762
0
                                    aInfo.maPrintSize.Height());
1763
0
        }
1764
0
        else
1765
0
        {
1766
0
            aInfo.maPrintSize = aInfo.mpPrinter->GetOutputSize();
1767
0
            maPrintSize = awt::Size(
1768
0
                aInfo.mpPrinter->GetPaperSize().Width(),
1769
0
                aInfo.mpPrinter->GetPaperSize().Height());
1770
0
        }
1771
1772
0
        switch (mpOptions->GetOutputQuality())
1773
0
        {
1774
0
            case 1: // Grayscale
1775
0
                aInfo.mnDrawMode = DrawModeFlags::GrayLine | DrawModeFlags::GrayFill
1776
0
                    | DrawModeFlags::GrayText | DrawModeFlags::GrayBitmap
1777
0
                    | DrawModeFlags::GrayGradient;
1778
0
                break;
1779
1780
0
            case 2: // Black & White
1781
0
                aInfo.mnDrawMode = DrawModeFlags::BlackLine | DrawModeFlags::WhiteFill
1782
0
                    | DrawModeFlags::BlackText | DrawModeFlags::GrayBitmap
1783
0
                    | DrawModeFlags::WhiteGradient;
1784
0
                break;
1785
1786
0
            default:
1787
0
                aInfo.mnDrawMode = DrawModeFlags::Default;
1788
0
        }
1789
1790
0
        if (mpOptions->IsDraw())
1791
0
            PrepareStdOrNotes(PageKind::Standard, aInfo);
1792
0
        if (mpOptions->IsNotes())
1793
0
            PrepareStdOrNotes(PageKind::Notes, aInfo);
1794
0
        if (mpOptions->IsHandout())
1795
0
        {
1796
0
            InitHandoutTemplate();
1797
0
            PrepareHandout(aInfo);
1798
0
        }
1799
0
        if (mpOptions->IsOutline())
1800
0
            PrepareOutline(aInfo);
1801
1802
0
        rOutliner.SetControlWord(nSavedControlWord);
1803
0
    }
1804
1805
    /** Create the page objects of the handout template.  When the actual
1806
        printing takes place then the page objects are assigned different
1807
        sets of slides for each printed page (see HandoutPrinterPage::Print).
1808
    */
1809
    void InitHandoutTemplate()
1810
0
    {
1811
0
        const sal_Int32 nSlidesPerHandout (mpOptions->GetHandoutPageCount());
1812
0
        const bool bHandoutHorizontal (mpOptions->IsHandoutHorizontal());
1813
1814
0
        AutoLayout eLayout = AUTOLAYOUT_HANDOUT6;
1815
0
        switch (nSlidesPerHandout)
1816
0
        {
1817
0
            case 0: eLayout = AUTOLAYOUT_NONE; break; // AUTOLAYOUT_HANDOUT1; break;
1818
0
            case 1: eLayout = AUTOLAYOUT_HANDOUT1; break;
1819
0
            case 2: eLayout = AUTOLAYOUT_HANDOUT2; break;
1820
0
            case 3: eLayout = AUTOLAYOUT_HANDOUT3; break;
1821
0
            case 4: eLayout = AUTOLAYOUT_HANDOUT4; break;
1822
0
            default:
1823
0
            case 6: eLayout = AUTOLAYOUT_HANDOUT6; break;
1824
0
            case 9: eLayout = AUTOLAYOUT_HANDOUT9; break;
1825
0
        }
1826
1827
0
        if( !mrBase.GetDocument() )
1828
0
            return;
1829
1830
0
        SdDrawDocument& rModel = *mrBase.GetDocument();
1831
1832
        // first, prepare handout page (not handout master)
1833
1834
0
        SdPage* pHandout = rModel.GetSdPage(0, PageKind::Handout);
1835
0
        if( !pHandout )
1836
0
            return;
1837
1838
        // delete all previous shapes from handout page
1839
0
        while( pHandout->GetObjCount() )
1840
0
            pHandout->NbcRemoveObject(0);
1841
1842
0
        const bool bDrawLines (eLayout == AUTOLAYOUT_HANDOUT3);
1843
1844
0
        Size aHandoutPageSize = pHandout->GetSize();
1845
0
        lcl_AdjustPageSize(aHandoutPageSize, mpPrinter->GetPrintPageSize());
1846
0
        Orientation eOrient = aHandoutPageSize.Width() > aHandoutPageSize.Height()
1847
0
                                  ? Orientation::Landscape
1848
0
                                  : Orientation::Portrait;
1849
1850
0
        std::vector< ::tools::Rectangle > aAreas;
1851
0
        SdPage::CalculateHandoutAreas( rModel, eLayout, bHandoutHorizontal, aAreas, eOrient );
1852
1853
0
        std::vector< ::tools::Rectangle >::iterator iter( aAreas.begin() );
1854
0
        while( iter != aAreas.end() )
1855
0
        {
1856
0
            pHandout->NbcInsertObject(
1857
0
                new SdrPageObj(
1858
0
                    rModel,
1859
0
                    (*iter++)));
1860
1861
0
            if( bDrawLines && (iter != aAreas.end())  )
1862
0
            {
1863
0
                ::tools::Rectangle aRect( *iter++ );
1864
1865
0
                basegfx::B2DPolygon aPoly;
1866
0
                aPoly.insert(0, basegfx::B2DPoint( aRect.Left(), aRect.Top() ) );
1867
0
                aPoly.insert(1, basegfx::B2DPoint( aRect.Right(), aRect.Top() ) );
1868
1869
0
                basegfx::B2DHomMatrix aMatrix;
1870
0
                aMatrix.translate( 0.0, static_cast< double >( aRect.GetHeight() / 7 ) );
1871
1872
0
                basegfx::B2DPolyPolygon aPathPoly;
1873
0
                for( sal_uInt16 nLine = 0; nLine < 7; nLine++ )
1874
0
                {
1875
0
                    aPoly.transform( aMatrix );
1876
0
                    aPathPoly.append( aPoly );
1877
0
                }
1878
1879
0
                rtl::Reference<SdrPathObj> pPathObj = new SdrPathObj(
1880
0
                    rModel,
1881
0
                    SdrObjKind::PathLine,
1882
0
                    std::move(aPathPoly));
1883
0
                pPathObj->SetMergedItem(XLineStyleItem(drawing::LineStyle_SOLID));
1884
0
                pPathObj->SetMergedItem(XLineColorItem(OUString(), COL_BLACK));
1885
1886
0
                pHandout->NbcInsertObject( pPathObj.get() );
1887
0
            }
1888
0
        }
1889
0
    }
1890
1891
    /** Detect whether the specified slide is to be printed.
1892
        @return
1893
            When the slide is not to be printed then <NULL/> is returned.
1894
            Otherwise a pointer to the slide is returned.
1895
    */
1896
    SdPage* GetFilteredPage (
1897
        const sal_Int32 nPageIndex,
1898
        const PageKind ePageKind) const
1899
0
    {
1900
0
        OSL_ASSERT(mrBase.GetDocument() != nullptr);
1901
0
        OSL_ASSERT(nPageIndex>=0);
1902
0
        SdPage* pPage = mrBase.GetDocument()->GetSdPage(
1903
0
            sal::static_int_cast<sal_uInt16>(nPageIndex),
1904
0
            ePageKind);
1905
0
        if (pPage == nullptr)
1906
0
            return nullptr;
1907
0
        if ( ! pPage->IsExcluded() || mpOptions->IsPrintExcluded())
1908
0
            return pPage;
1909
0
        else
1910
0
            return nullptr;
1911
0
    }
1912
1913
    /** Prepare the outline of the document for printing.  There is no fixed
1914
        number of slides whose outline data is put onto one printer page.
1915
        If the current printer page has enough room for the outline of the
1916
        current slide then that is added.  Otherwise a new printer page is
1917
        started.
1918
    */
1919
    void PrepareOutline (PrintInfo const & rInfo)
1920
0
    {
1921
0
        MapMode aMap (rInfo.maMap);
1922
0
        Point aPageOfs (rInfo.mpPrinter->GetPageOffset() );
1923
0
        aMap.SetScaleX(0.5);
1924
0
        aMap.SetScaleY(0.5);
1925
0
        mpPrinter->SetMapMode(aMap);
1926
1927
0
        ::tools::Rectangle aOutRect(aPageOfs, rInfo.mpPrinter->GetOutputSize());
1928
0
        if( aOutRect.GetWidth() > aOutRect.GetHeight() )
1929
0
        {
1930
0
            Size aPaperSize( rInfo.mpPrinter->PixelToLogic( rInfo.mpPrinter->GetPaperSizePixel(), MapMode( MapUnit::Map100thMM ) ) );
1931
0
            maPrintSize.Width  = aPaperSize.Height();
1932
0
            maPrintSize.Height = aPaperSize.Width();
1933
0
            const auto nRotatedWidth = aOutRect.GetHeight();
1934
0
            const auto nRotatedHeight = aOutRect.GetWidth();
1935
0
            const auto nRotatedX = aPageOfs.Y();
1936
0
            const auto nRotatedY = aPageOfs.X();
1937
0
            aOutRect = ::tools::Rectangle(Point( nRotatedX, nRotatedY),
1938
0
                                  Size(nRotatedWidth, nRotatedHeight));
1939
0
        }
1940
1941
0
        Outliner* pOutliner = mrBase.GetDocument()->GetInternalOutliner();
1942
0
        pOutliner->Init(OutlinerMode::OutlineView);
1943
0
        const OutlinerMode nSavedOutlMode (pOutliner->GetOutlinerMode());
1944
0
        const bool bSavedUpdateMode (pOutliner->IsUpdateLayout());
1945
0
        const Size aSavedPaperSize (pOutliner->GetPaperSize());
1946
0
        const MapMode aSavedMapMode (pOutliner->GetRefMapMode());
1947
0
        pOutliner->SetPaperSize(aOutRect.GetSize());
1948
0
        pOutliner->SetUpdateLayout(true);
1949
1950
0
        ::tools::Long nPageH = aOutRect.GetHeight();
1951
1952
0
        std::vector< sal_Int32 > aPages;
1953
0
        sal_Int32 nPageCount = mrBase.GetDocument()->GetSdPageCount(PageKind::Standard);
1954
0
        StringRangeEnumerator::getRangesFromString(
1955
0
            mpOptions->GetPrinterSelection(nPageCount, GetCurrentPageIndex()),
1956
0
            aPages, 0, nPageCount-1);
1957
1958
0
        for (size_t nIndex = 0, nCount = aPages.size(); nIndex < nCount;)
1959
0
        {
1960
0
            pOutliner->Clear();
1961
1962
0
            Paragraph* pPara = nullptr;
1963
0
            ::tools::Long nH (0);
1964
0
            while (nH < nPageH && nIndex<nCount)
1965
0
            {
1966
0
                SdPage* pPage = GetFilteredPage(aPages[nIndex], PageKind::Standard);
1967
0
                ++nIndex;
1968
0
                if (pPage == nullptr)
1969
0
                    continue;
1970
1971
0
                SdrTextObj* pTextObj = nullptr;
1972
1973
0
                for (const rtl::Reference<SdrObject>& pObj : *pPage)
1974
0
                {
1975
0
                    if (pObj->GetObjInventor() == SdrInventor::Default
1976
0
                        && pObj->GetObjIdentifier() == SdrObjKind::TitleText)
1977
0
                    {
1978
0
                        pTextObj = DynCastSdrTextObj(pObj.get());
1979
0
                        if (pTextObj)
1980
0
                            break;
1981
0
                    }
1982
0
                }
1983
1984
0
                pPara = pOutliner->GetParagraph(pOutliner->GetParagraphCount() - 1);
1985
1986
0
                if (pTextObj!=nullptr
1987
0
                    && !pTextObj->IsEmptyPresObj()
1988
0
                    && pTextObj->GetOutlinerParaObject())
1989
0
                {
1990
0
                    pOutliner->AddText(*(pTextObj->GetOutlinerParaObject()));
1991
0
                }
1992
0
                else
1993
0
                    pOutliner->Insert(OUString());
1994
1995
0
                pTextObj = nullptr;
1996
1997
0
                for (const rtl::Reference<SdrObject>& pObj : *pPage)
1998
0
                {
1999
0
                    if (pObj->GetObjInventor() == SdrInventor::Default
2000
0
                        && pObj->GetObjIdentifier() == SdrObjKind::OutlineText)
2001
0
                    {
2002
0
                        pTextObj = DynCastSdrTextObj(pObj.get());
2003
0
                        if (pTextObj)
2004
0
                            break;
2005
0
                    }
2006
0
                }
2007
2008
0
                bool bSubTitle (false);
2009
0
                if (!pTextObj)
2010
0
                {
2011
0
                    bSubTitle = true;
2012
0
                    pTextObj = DynCastSdrTextObj(pPage->GetPresObj(PresObjKind::Text));  // is there a subtitle?
2013
0
                }
2014
2015
0
                sal_Int32 nParaCount1 = pOutliner->GetParagraphCount();
2016
2017
0
                if (pTextObj!=nullptr
2018
0
                    && !pTextObj->IsEmptyPresObj()
2019
0
                    && pTextObj->GetOutlinerParaObject())
2020
0
                {
2021
0
                    pOutliner->AddText(*(pTextObj->GetOutlinerParaObject()));
2022
0
                }
2023
2024
0
                if (bSubTitle )
2025
0
                {
2026
0
                    const sal_Int32 nParaCount2 (pOutliner->GetParagraphCount());
2027
0
                    for (sal_Int32 nPara=nParaCount1; nPara<nParaCount2; ++nPara)
2028
0
                    {
2029
0
                        Paragraph* pP = pOutliner->GetParagraph(nPara);
2030
0
                        if (pP!=nullptr && pOutliner->GetDepth(nPara) > 0)
2031
0
                            pOutliner->SetDepth(pP, 0);
2032
0
                    }
2033
0
                }
2034
2035
0
                nH = pOutliner->GetTextHeight();
2036
0
            }
2037
2038
            // Remove the last paragraph when that does not fit completely on
2039
            // the current page.
2040
0
            if (nH > nPageH && pPara!=nullptr)
2041
0
            {
2042
0
                sal_Int32 nCnt = pOutliner->GetAbsPos(
2043
0
                    pOutliner->GetParagraph( pOutliner->GetParagraphCount() - 1 ) );
2044
0
                sal_Int32 nParaPos = pOutliner->GetAbsPos( pPara );
2045
0
                nCnt -= nParaPos;
2046
0
                pPara = pOutliner->GetParagraph( ++nParaPos );
2047
0
                if ( nCnt && pPara )
2048
0
                {
2049
0
                    pOutliner->Remove(pPara, nCnt);
2050
0
                    --nIndex;
2051
0
                }
2052
0
            }
2053
2054
0
            if ( CheckForFrontBackPages( nIndex ) )
2055
0
            {
2056
0
                maPrinterPages.push_back(
2057
0
                    std::make_shared<OutlinerPrinterPage>(
2058
0
                        pOutliner->CreateParaObject(),
2059
0
                        aMap,
2060
0
                        rInfo.msTimeDate,
2061
0
                        aPageOfs,
2062
0
                        rInfo.mnDrawMode,
2063
0
                        rInfo.meOrientation,
2064
0
                        rInfo.mpPrinter->GetPaperBin()));
2065
0
            }
2066
0
        }
2067
2068
0
        pOutliner->SetRefMapMode(aSavedMapMode);
2069
0
        pOutliner->SetUpdateLayout(bSavedUpdateMode);
2070
0
        pOutliner->SetPaperSize(aSavedPaperSize);
2071
0
        pOutliner->Init(nSavedOutlMode);
2072
0
    }
2073
2074
    /** Prepare handout pages for slides that are to be printed.
2075
    */
2076
    void PrepareHandout (PrintInfo& rInfo)
2077
0
    {
2078
0
        SdDrawDocument* pDocument = mrBase.GetDocument();
2079
0
        assert(pDocument != nullptr);
2080
0
        SdPage& rHandoutPage (*pDocument->GetSdPage(0, PageKind::Handout));
2081
2082
0
        const bool bScalePage (mpOptions->IsPageSize());
2083
2084
0
        sal_uInt16 nPaperBin;
2085
0
        if ( ! mpOptions->IsPaperBin())
2086
0
            nPaperBin = rHandoutPage.GetPaperBin();
2087
0
        else
2088
0
            nPaperBin = rInfo.mpPrinter->GetPaperBin();
2089
2090
        // Change orientation?
2091
0
        SdPage& rMaster (dynamic_cast<SdPage&>(rHandoutPage.TRG_GetMasterPage()));
2092
0
        rInfo.meOrientation = rMaster.GetOrientation();
2093
2094
0
        Size aPaperSize (rInfo.mpPrinter->GetPaperSize());
2095
0
        lcl_AdjustPageSize(aPaperSize, rInfo.mpPrinter->GetPrintPageSize());
2096
0
        maPrintSize = awt::Size(aPaperSize.Width(),aPaperSize.Height());
2097
2098
0
        MapMode aMap (rInfo.maMap);
2099
0
        const Point aPageOfs (rInfo.mpPrinter->GetPageOffset());
2100
2101
0
        if ( bScalePage )
2102
0
        {
2103
0
            Size aPageSize (rHandoutPage.GetSize());
2104
0
            Size aPrintSize (rInfo.mpPrinter->GetOutputSize());
2105
0
            lcl_AdjustPageSize(aPageSize, aPrintSize);
2106
2107
0
            const double fHorz = static_cast<double>(aPrintSize.Width())    / aPageSize.Width();
2108
0
            const double fVert = static_cast<double>(aPrintSize.Height()) / aPageSize.Height();
2109
2110
0
            double    fFract;
2111
0
            if ( fHorz < fVert )
2112
0
                fFract = double(aPrintSize.Width()) / aPageSize.Width();
2113
0
            else
2114
0
                fFract = double(aPrintSize.Height()) / aPageSize.Height();
2115
2116
0
            aMap.SetScaleX(fFract);
2117
0
            aMap.SetScaleY(fFract);
2118
0
            aMap.SetOrigin(Point());
2119
0
        }
2120
2121
0
        std::shared_ptr<ViewShell> pViewShell (mrBase.GetMainViewShell());
2122
0
        pViewShell->WriteFrameViewData();
2123
2124
        // Count page shapes.
2125
0
        sal_uInt32 nShapeCount (0);
2126
0
        SdrObjListIter aShapeIter (&rHandoutPage);
2127
0
        while (aShapeIter.IsMore())
2128
0
        {
2129
0
            SdrPageObj* pPageObj = dynamic_cast<SdrPageObj*>(aShapeIter.Next());
2130
0
            if (pPageObj)
2131
0
                ++nShapeCount;
2132
0
        }
2133
2134
0
        const sal_uInt16 nPageCount = mrBase.GetDocument()->GetSdPageCount(PageKind::Standard);
2135
0
        const sal_uInt16 nHandoutPageCount = nShapeCount ? (nPageCount + nShapeCount - 1) / nShapeCount : 0;
2136
0
        pViewShell->SetPrintedHandoutPageCount( nHandoutPageCount );
2137
0
        mrBase.GetDocument()->setHandoutPageCount( nHandoutPageCount );
2138
2139
        // Distribute pages to handout pages.
2140
0
        StringRangeEnumerator aRangeEnum(
2141
0
            mpOptions->GetPrinterSelection(nPageCount, GetCurrentPageIndex()),
2142
0
            0, nPageCount-1);
2143
0
        std::vector<sal_uInt16> aPageIndices;
2144
0
        sal_uInt16 nPrinterPageIndex = 0;
2145
0
        StringRangeEnumerator::Iterator it = aRangeEnum.begin(), itEnd = aRangeEnum.end();
2146
0
        bool bLastLoop = (it == itEnd);
2147
0
        while (!bLastLoop)
2148
0
        {
2149
0
            sal_Int32 nPageIndex = *it;
2150
0
            ++it;
2151
0
            bLastLoop = (it == itEnd);
2152
2153
0
            if (GetFilteredPage(nPageIndex, PageKind::Standard))
2154
0
                aPageIndices.push_back(nPageIndex);
2155
0
            else if (!bLastLoop)
2156
0
                continue;
2157
2158
            // Create a printer page when we have found one page for each
2159
            // placeholder or when this is the last (and special) loop.
2160
0
            if ( !aPageIndices.empty() && CheckForFrontBackPages( nPageIndex )
2161
0
                && (aPageIndices.size() == nShapeCount || bLastLoop) )
2162
0
            {
2163
0
                maPrinterPages.push_back(
2164
0
                    std::make_shared<HandoutPrinterPage>(
2165
0
                            nPrinterPageIndex++,
2166
0
                            std::move(aPageIndices),
2167
0
                            aMap,
2168
0
                            rInfo.msTimeDate,
2169
0
                            aPageOfs,
2170
0
                            rInfo.mnDrawMode,
2171
0
                            rInfo.meOrientation,
2172
0
                            nPaperBin));
2173
0
                aPageIndices.clear();
2174
0
            }
2175
0
        }
2176
0
    }
2177
2178
    /** Prepare the notes pages or regular slides.
2179
    */
2180
    void PrepareStdOrNotes (
2181
        const PageKind ePageKind,
2182
        PrintInfo& rInfo)
2183
0
    {
2184
0
        OSL_ASSERT(rInfo.mpPrinter != nullptr);
2185
2186
        // Fill in page kind specific data.
2187
0
        SdDrawDocument* pDocument = mrBase.GetMainViewShell()->GetDoc();
2188
0
        if (pDocument->GetSdPageCount(ePageKind) == 0)
2189
0
            return;
2190
0
        SdPage* pRefPage = pDocument->GetSdPage(0, ePageKind);
2191
2192
0
        if (!mpOptions->IsPrinterPreferred(pDocument->GetDocumentType()) && mpOptions->IsNotes())
2193
0
            rInfo.maPageSize = mpPrinter->GetPrintPageSize();
2194
0
        else
2195
0
            rInfo.maPageSize = pRefPage->GetSize();
2196
2197
0
        SetupPaperOrientation(ePageKind, rInfo);
2198
2199
0
        if (mpOptions->IsBooklet())
2200
0
            PrepareBooklet(ePageKind, rInfo);
2201
0
        else
2202
0
            PrepareRegularPages(ePageKind, rInfo);
2203
0
    }
2204
2205
    /** Prepare slides in a non-booklet way: one slide per one to many
2206
        printer pages.
2207
    */
2208
    void PrepareRegularPages (
2209
        const PageKind ePageKind,
2210
        PrintInfo& rInfo)
2211
0
    {
2212
0
        std::shared_ptr<ViewShell> pViewShell (mrBase.GetMainViewShell());
2213
0
        pViewShell->WriteFrameViewData();
2214
2215
0
        sal_Int32 nPageCount = mrBase.GetDocument()->GetSdPageCount(PageKind::Standard);
2216
0
        StringRangeEnumerator aRangeEnum(
2217
0
            mpOptions->GetPrinterSelection(nPageCount, GetCurrentPageIndex()),
2218
0
            0, nPageCount-1);
2219
0
        for (StringRangeEnumerator::Iterator
2220
0
                 it = aRangeEnum.begin(),
2221
0
                 itEnd = aRangeEnum.end();
2222
0
             it != itEnd;
2223
0
             ++it)
2224
0
        {
2225
0
            SdPage* pPage = GetFilteredPage(*it, ePageKind);
2226
0
            if (pPage == nullptr)
2227
0
                continue;
2228
2229
0
            MapMode aMap (rInfo.maMap);
2230
2231
0
            Size aPageSize = pPage->GetSize();
2232
2233
0
            if (mpOptions->IsPageSize())
2234
0
            {
2235
0
                Size aPrintSize = rInfo.maPrintSize;
2236
0
                lcl_AdjustPageSize(aPageSize, aPrintSize);
2237
2238
0
                const double fHorz(static_cast<double>(aPrintSize.Width()) / aPageSize.Width());
2239
0
                const double fVert(static_cast<double>(aPrintSize.Height()) / aPageSize.Height());
2240
2241
0
                double fFract;
2242
0
                if (fHorz < fVert)
2243
0
                    fFract = double(aPrintSize.Width()) / aPageSize.Width();
2244
0
                else
2245
0
                    fFract = double(aPrintSize.Height()) / aPageSize.Height();
2246
2247
0
                aMap.SetScaleX(fFract);
2248
0
                aMap.SetScaleY(fFract);
2249
0
                aMap.SetOrigin(Point());
2250
0
            }
2251
2252
0
            if (mpOptions->IsPrintPageName())
2253
0
            {
2254
0
                rInfo.msPageString = pPage->GetName() + " ";
2255
0
            }
2256
0
            else
2257
0
                rInfo.msPageString.clear();
2258
0
            rInfo.msPageString += rInfo.msTimeDate;
2259
2260
0
            ::tools::Long aPageWidth   = aPageSize.Width() - pPage->GetLeftBorder() - pPage->GetRightBorder();
2261
0
            ::tools::Long aPageHeight  = aPageSize.Height() - pPage->GetUpperBorder() - pPage->GetLowerBorder();
2262
            // Bugfix for 44530:
2263
            // if it was implicitly changed (Landscape/Portrait),
2264
            // this is considered for tiling, respectively for the splitting up
2265
            // (Poster)
2266
0
            if( ( rInfo.maPrintSize.Width() > rInfo.maPrintSize.Height()
2267
0
                    && aPageWidth < aPageHeight )
2268
0
                || ( rInfo.maPrintSize.Width() < rInfo.maPrintSize.Height()
2269
0
                    && aPageWidth > aPageHeight ) )
2270
0
            {
2271
0
                const sal_Int32 nTmp (rInfo.maPrintSize.Width());
2272
0
                rInfo.maPrintSize.setWidth( rInfo.maPrintSize.Height() );
2273
0
                rInfo.maPrintSize.setHeight( nTmp );
2274
0
            }
2275
2276
0
            if (mpOptions->IsTilePage()
2277
0
                && aPageWidth < rInfo.maPrintSize.Width()
2278
0
                && aPageHeight < rInfo.maPrintSize.Height())
2279
0
            {
2280
                // Put multiple slides on one printer page.
2281
0
                PrepareTiledPage(*it, *pPage, ePageKind, rInfo);
2282
0
            }
2283
0
            else
2284
0
            {
2285
0
                rInfo.maMap = std::move(aMap);
2286
0
                PrepareScaledPage(*it, *pPage, ePageKind, rInfo);
2287
0
            }
2288
0
        }
2289
0
    }
2290
2291
    /** Put two slides on one printer page.
2292
    */
2293
    void PrepareBooklet (
2294
        const PageKind ePageKind,
2295
        const PrintInfo& rInfo)
2296
0
    {
2297
0
        MapMode aStdMap (rInfo.maMap);
2298
0
        Point aOffset;
2299
0
        Size aPrintSize_2 (rInfo.maPrintSize);
2300
0
        Size aPageSize_2 (rInfo.maPageSize);
2301
2302
0
        if (rInfo.meOrientation == Orientation::Landscape)
2303
0
            aPrintSize_2.setWidth( aPrintSize_2.Width() >> 1 );
2304
0
        else
2305
0
            aPrintSize_2.setHeight( aPrintSize_2.Height() >> 1 );
2306
2307
0
        const double fPageWH = static_cast<double>(aPageSize_2.Width()) / aPageSize_2.Height();
2308
0
        const double fPrintWH = static_cast<double>(aPrintSize_2.Width()) / aPrintSize_2.Height();
2309
2310
0
        if( fPageWH < fPrintWH )
2311
0
        {
2312
0
            aPageSize_2.setWidth(  static_cast<::tools::Long>( aPrintSize_2.Height() * fPageWH ) );
2313
0
            aPageSize_2.setHeight( aPrintSize_2.Height() );
2314
0
        }
2315
0
        else
2316
0
        {
2317
0
            aPageSize_2.setWidth( aPrintSize_2.Width() );
2318
0
            aPageSize_2.setHeight( static_cast<::tools::Long>( aPrintSize_2.Width() / fPageWH ) );
2319
0
        }
2320
2321
0
        MapMode aMap (rInfo.maMap);
2322
0
        aMap.SetScaleX( double(aPageSize_2.Width()) / rInfo.maPageSize.Width() );
2323
0
        aMap.SetScaleY( double(aPageSize_2.Height()) / rInfo.maPageSize.Height() );
2324
2325
        // calculate adjusted print size
2326
0
        const Size aAdjustedPrintSize (OutputDevice::LogicToLogic(
2327
0
            rInfo.maPrintSize,
2328
0
            aStdMap,
2329
0
            aMap));
2330
2331
0
        if (rInfo.meOrientation == Orientation::Landscape)
2332
0
        {
2333
0
            aOffset.setX( ( ( aAdjustedPrintSize.Width() >> 1 ) - rInfo.maPageSize.Width() ) >> 1 );
2334
0
            aOffset.setY( ( aAdjustedPrintSize.Height() - rInfo.maPageSize.Height() ) >> 1 );
2335
0
        }
2336
0
        else
2337
0
        {
2338
0
            aOffset.setX( ( aAdjustedPrintSize.Width() - rInfo.maPageSize.Width() ) >> 1 );
2339
0
            aOffset.setY( ( ( aAdjustedPrintSize.Height() >> 1 ) - rInfo.maPageSize.Height() ) >> 1 );
2340
0
        }
2341
2342
        // create vector of pages to print
2343
0
        sal_Int32 nPageCount = mrBase.GetDocument()->GetSdPageCount(ePageKind);
2344
0
        StringRangeEnumerator aRangeEnum(
2345
0
            mpOptions->GetPrinterSelection(nPageCount, GetCurrentPageIndex()),
2346
0
            0, nPageCount-1);
2347
0
        std::vector< sal_uInt16 > aPageVector;
2348
0
        for (StringRangeEnumerator::Iterator
2349
0
                 it = aRangeEnum.begin(),
2350
0
                 itEnd = aRangeEnum.end();
2351
0
             it != itEnd;
2352
0
             ++it)
2353
0
        {
2354
0
            SdPage* pPage = GetFilteredPage(*it, ePageKind);
2355
0
            if (pPage != nullptr)
2356
0
                aPageVector.push_back(*it);
2357
0
        }
2358
2359
        // create pairs of pages to print on each page
2360
0
        std::vector< std::pair< sal_uInt16, sal_uInt16 > > aPairVector;
2361
0
        if ( ! aPageVector.empty())
2362
0
        {
2363
0
            sal_uInt32 nFirstIndex = 0, nLastIndex = aPageVector.size() - 1;
2364
2365
0
            if( aPageVector.size() & 1 )
2366
0
                aPairVector.emplace_back( sal_uInt16(65535), aPageVector[ nFirstIndex++ ] );
2367
0
            else
2368
0
                aPairVector.emplace_back( aPageVector[ nLastIndex-- ], aPageVector[ nFirstIndex++ ] );
2369
2370
0
            while( nFirstIndex < nLastIndex )
2371
0
            {
2372
0
                if( nFirstIndex & 1 )
2373
0
                    aPairVector.emplace_back( aPageVector[ nFirstIndex++ ], aPageVector[ nLastIndex-- ] );
2374
0
                else
2375
0
                    aPairVector.emplace_back( aPageVector[ nLastIndex-- ], aPageVector[ nFirstIndex++ ] );
2376
0
            }
2377
0
        }
2378
2379
0
        bool bPrintBookletRTL = mpOptions->IsProspectRTL();
2380
2381
0
        for (sal_uInt32
2382
0
                 nIndex=0,
2383
0
                 nCount=aPairVector.size();
2384
0
             nIndex < nCount;
2385
0
             ++nIndex)
2386
0
        {
2387
0
            if ( CheckForFrontBackPages( nIndex ) )
2388
0
            {
2389
0
                std::pair<sal_uInt16, sal_uInt16> aPair (aPairVector[nIndex]);
2390
0
                if( bPrintBookletRTL )
2391
0
                    std::swap(aPair.first, aPair.second);
2392
0
                Point aSecondOffset (aOffset);
2393
0
                if (rInfo.meOrientation == Orientation::Landscape)
2394
0
                    aSecondOffset.AdjustX( aAdjustedPrintSize.Width() / 2 );
2395
0
                else
2396
0
                    aSecondOffset.AdjustY( aAdjustedPrintSize.Height() / 2 );
2397
0
                maPrinterPages.push_back(
2398
0
                    std::make_shared<BookletPrinterPage>(
2399
0
                            aPair.first,
2400
0
                            aPair.second,
2401
0
                            aOffset,
2402
0
                            aSecondOffset,
2403
0
                            ePageKind,
2404
0
                            aMap,
2405
0
                            rInfo.mbPrintMarkedOnly,
2406
0
                            rInfo.mnDrawMode,
2407
0
                            rInfo.meOrientation,
2408
0
                            rInfo.mpPrinter->GetPaperBin()));
2409
2410
0
            }
2411
0
        }
2412
0
    }
2413
2414
    /** Print one slide multiple times on one printer page so that the whole
2415
        printer page is covered.
2416
    */
2417
    void PrepareTiledPage (
2418
        const sal_Int32 nPageIndex,
2419
        const SdPage& rPage,
2420
        const PageKind ePageKind,
2421
        const PrintInfo& rInfo)
2422
0
    {
2423
0
        sal_uInt16 nPaperBin;
2424
0
        if ( ! mpOptions->IsPaperBin())
2425
0
            nPaperBin = rPage.GetPaperBin();
2426
0
        else
2427
0
            nPaperBin = rInfo.mpPrinter->GetPaperBin();
2428
2429
0
        if ( !CheckForFrontBackPages( nPageIndex ) )
2430
0
            return;
2431
2432
0
        maPrinterPages.push_back(
2433
0
            std::make_shared<TiledPrinterPage>(
2434
0
                sal::static_int_cast<sal_uInt16>(nPageIndex),
2435
0
                ePageKind,
2436
0
                rInfo.mbPrintMarkedOnly,
2437
0
                rInfo.msPageString,
2438
0
                rInfo.mpPrinter->GetPageOffset(),
2439
0
                rInfo.mnDrawMode,
2440
0
                rInfo.meOrientation,
2441
0
                nPaperBin));
2442
0
    }
2443
2444
    /** Print one standard slide or notes page on one to many printer
2445
        pages.  More than on printer page is used when the slide is larger
2446
        than the printable area.
2447
    */
2448
    void PrepareScaledPage (
2449
        const sal_Int32 nPageIndex,
2450
        const SdPage& rPage,
2451
        const PageKind ePageKind,
2452
        const PrintInfo& rInfo)
2453
0
    {
2454
0
        const Point aPageOffset (rInfo.mpPrinter->GetPageOffset());
2455
2456
0
        sal_uInt16 nPaperBin;
2457
0
        if ( ! mpOptions->IsPaperBin())
2458
0
            nPaperBin = rPage.GetPaperBin();
2459
0
        else
2460
0
            nPaperBin = rInfo.mpPrinter->GetPaperBin();
2461
2462
        // For pages larger than the printable area there are three options:
2463
        // 1. Scale down to the page to the printable area.
2464
        // 2. Print only the upper left part of the page (without the unprintable borders).
2465
        // 3. Split the page into parts of the size of the printable area.
2466
0
        const bool bScalePage (mpOptions->IsPageSize());
2467
0
        const bool bCutPage (mpOptions->IsCutPage());
2468
0
        MapMode aMap (rInfo.maMap);
2469
0
        if ( (bScalePage || bCutPage) && CheckForFrontBackPages( nPageIndex ) )
2470
0
        {
2471
            // Handle 1 and 2.
2472
2473
            // if CutPage is set then do not move it, otherwise move the
2474
            // scaled page to printable area
2475
0
            if (ePageKind == PageKind::Standard)
2476
0
            {
2477
0
                maPrinterPages.push_back(
2478
0
                    std::make_shared<RegularPrinterPage>(
2479
0
                            sal::static_int_cast<sal_uInt16>(nPageIndex),
2480
0
                            ePageKind,
2481
0
                            aMap,
2482
0
                            rInfo.mbPrintMarkedOnly,
2483
0
                            rInfo.msPageString,
2484
0
                            aPageOffset,
2485
0
                            rInfo.mnDrawMode,
2486
0
                            rInfo.meOrientation,
2487
0
                            nPaperBin));
2488
0
            }
2489
0
            else if (SdPage* pPage = GetFilteredPage(nPageIndex, PageKind::Notes))// Notes
2490
0
            {
2491
0
                SdDrawDocument* pDocument = mrBase.GetMainViewShell()->GetDoc();
2492
2493
                // Clone the current page to create an independent instance.
2494
                // This ensures that changes made to pNotesPage do not affect the original page.
2495
0
                rtl::Reference<SdPage> pNotesPage
2496
0
                    = static_cast<SdPage*>(pPage->CloneSdrPage(*pDocument).get());
2497
2498
0
                Size aPageSize = bScalePage ? pNotesPage->GetSize() : rInfo.mpPrinter->GetPrintPageSize();
2499
                // Adjusts the objects on the notes page to fit the new page size.
2500
0
                ::tools::Rectangle aNewBorderRect(-1, -1, -1, -1);
2501
0
                pNotesPage->ScaleObjects(aPageSize, aNewBorderRect, true);
2502
2503
0
                SdrObject* pNotesObj = pNotesPage->GetPresObj(PresObjKind::Notes);
2504
0
                if (pNotesObj && bCutPage)
2505
0
                {
2506
                    // default margins
2507
0
                    sal_Int32 nTopMargin = aPageSize.Height() * 0.075;
2508
0
                    sal_Int32 nBottomMargin = nTopMargin;
2509
2510
0
                    Size nNotesObjSize = pNotesObj->GetLogicRect().GetSize();
2511
2512
0
                    Outliner* pOut = pDocument->GetInternalOutliner();
2513
0
                    const OutlinerMode nSaveOutlMode(pOut->GetOutlinerMode());
2514
0
                    const bool bSavedUpdateMode(pOut->IsUpdateLayout());
2515
0
                    pOut->Init(OutlinerMode::OutlineView);
2516
0
                    pOut->SetPaperSize(nNotesObjSize);
2517
0
                    pOut->SetUpdateLayout(true);
2518
0
                    pOut->Clear();
2519
0
                    if (OutlinerParaObject* pOutlinerParaObject = pNotesObj->GetOutlinerParaObject())
2520
0
                        pOut->SetText(*pOutlinerParaObject);
2521
2522
0
                    sal_Int32 nFirstPageBottomMargin = 0;
2523
0
                    ::tools::Long nNotesHeight = nNotesObjSize.Height();
2524
0
                    bool bAutoGrow = pNotesObj->GetMergedItem(SDRATTR_TEXT_AUTOGROWHEIGHT).GetValue();
2525
0
                    if (bAutoGrow)
2526
0
                    {
2527
0
                        nNotesHeight += pNotesObj->GetRelativePos().Y();
2528
0
                        nFirstPageBottomMargin = (pNotesPage->GetLowerBorder() != 0)
2529
0
                                                     ? pNotesPage->GetLowerBorder()
2530
0
                                                     : nBottomMargin;
2531
0
                    }
2532
0
                    double nOverflowedTextHeight = 0;
2533
0
                    ::tools::Long nFirstPageBottom = aPageSize.Height() - nFirstPageBottomMargin;
2534
0
                    if (nNotesHeight > nFirstPageBottom)
2535
0
                    {
2536
                        // Calculate the height of the overflow text
2537
                        // when the AutoGrowHeight property of the notes object is enabled
2538
                        // and the height of the object exceeds the page height.
2539
0
                        nOverflowedTextHeight = pNotesObj->GetRelativePos().Y()
2540
0
                                                + pOut->GetTextHeight() - nFirstPageBottom;
2541
0
                    }
2542
0
                    else
2543
0
                        nOverflowedTextHeight = pOut->GetTextHeight() - nNotesObjSize.Height();
2544
2545
0
                    sal_Int32 nNotePageCount = 1;
2546
0
                    double nNewPageHeight = aPageSize.Height() - nTopMargin - nBottomMargin;
2547
0
                    if (nOverflowedTextHeight > 0)
2548
0
                    {
2549
0
                        nNotePageCount += std::ceil(nOverflowedTextHeight / nNewPageHeight);
2550
0
                    }
2551
2552
0
                    for (sal_Int32 i = 1; i <= nNotePageCount; i++)
2553
0
                    {
2554
                        // set page numbers
2555
0
                        sal_Int32 nPageNumb = i;
2556
0
                        OUString sPageNumb = rInfo.msPageString;
2557
0
                        if (!sPageNumb.isEmpty() && nNotePageCount > 1)
2558
0
                        {
2559
0
                            OUString sTmp;
2560
0
                            if (!rInfo.msTimeDate.isEmpty())
2561
0
                            {
2562
0
                                sTmp += " ";
2563
0
                            }
2564
0
                            sTmp += SdResId(STR_PAGE_NAME) + " " + OUString::number(i);
2565
0
                            sPageNumb += sTmp;
2566
0
                        }
2567
2568
0
                        maPrinterPages.push_back(
2569
0
                            std::make_shared<NotesPrinterPage>(
2570
0
                                    sal::static_int_cast<sal_uInt16>(nPageIndex),
2571
0
                                    nPageNumb,
2572
0
                                    nNotePageCount,
2573
0
                                    bScalePage,
2574
0
                                    PageKind::Notes,
2575
0
                                    aMap,
2576
0
                                    rInfo.mbPrintMarkedOnly,
2577
0
                                    sPageNumb,
2578
0
                                    aPageOffset,
2579
0
                                    rInfo.mnDrawMode,
2580
0
                                    rInfo.meOrientation,
2581
0
                                    nPaperBin));
2582
0
                    }
2583
0
                    pOut->Clear();
2584
0
                    pOut->SetUpdateLayout(bSavedUpdateMode);
2585
0
                    pOut->Init(nSaveOutlMode);
2586
0
                }
2587
0
                else // scaled page
2588
0
                {
2589
0
                    maPrinterPages.push_back(
2590
0
                        std::make_shared<NotesPrinterPage>(
2591
0
                                sal::static_int_cast<sal_uInt16>(nPageIndex),
2592
0
                                sal_Int32(0),
2593
0
                                sal_Int32(0),
2594
0
                                bScalePage,
2595
0
                                PageKind::Notes,
2596
0
                                aMap,
2597
0
                                rInfo.mbPrintMarkedOnly,
2598
0
                                rInfo.msPageString,
2599
0
                                aPageOffset,
2600
0
                                rInfo.mnDrawMode,
2601
0
                                rInfo.meOrientation,
2602
0
                                nPaperBin));
2603
0
                }
2604
0
            }
2605
0
        }
2606
0
        else
2607
0
        {
2608
            // Handle 3.  Print parts of the page in the size of the
2609
            // printable area until the whole page is covered.
2610
2611
            // keep the page content at its position if it fits, otherwise
2612
            // move it to the printable area
2613
0
            const ::tools::Long nPageWidth (
2614
0
                rInfo.maPageSize.Width() - rPage.GetLeftBorder() - rPage.GetRightBorder());
2615
0
            const ::tools::Long nPageHeight (
2616
0
                rInfo.maPageSize.Height() - rPage.GetUpperBorder() - rPage.GetLowerBorder());
2617
2618
0
            Point aOrigin ( 0, 0 );
2619
2620
0
            for (Point aPageOrigin = aOrigin;
2621
0
                 -aPageOrigin.Y()<nPageHeight;
2622
0
                 aPageOrigin.AdjustY( -rInfo.maPrintSize.Height() ))
2623
0
            {
2624
0
                for (aPageOrigin.setX(aOrigin.X());
2625
0
                     -aPageOrigin.X()<nPageWidth;
2626
0
                     aPageOrigin.AdjustX(-rInfo.maPrintSize.Width()))
2627
0
                {
2628
0
                    if ( CheckForFrontBackPages( nPageIndex ) )
2629
0
                    {
2630
0
                        aMap.SetOrigin(aPageOrigin);
2631
0
                        maPrinterPages.push_back(
2632
0
                            std::make_shared<RegularPrinterPage>(
2633
0
                                    sal::static_int_cast<sal_uInt16>(nPageIndex),
2634
0
                                    ePageKind,
2635
0
                                    aMap,
2636
0
                                    rInfo.mbPrintMarkedOnly,
2637
0
                                    rInfo.msPageString,
2638
0
                                    aPageOffset,
2639
0
                                    rInfo.mnDrawMode,
2640
0
                                    rInfo.meOrientation,
2641
0
                                    nPaperBin));
2642
0
                    }
2643
0
                }
2644
0
            }
2645
0
        }
2646
0
    }
2647
2648
bool CheckForFrontBackPages( sal_Int32 nPage )
2649
0
{
2650
0
    const bool bIsIndexOdd(nPage & 1);
2651
0
    if ((!bIsIndexOdd && mpOptions->IsPrintFrontPage())
2652
0
        || (bIsIndexOdd && mpOptions->IsPrintBackPage()))
2653
0
    {
2654
0
        return true;
2655
0
    }
2656
0
    else
2657
0
        return false;
2658
0
}
2659
};
2660
2661
//===== DocumentRenderer ======================================================
2662
2663
DocumentRenderer::DocumentRenderer (ViewShellBase& rBase)
2664
0
    : mpImpl(new Implementation(rBase))
2665
0
{
2666
0
}
Unexecuted instantiation: sd::DocumentRenderer::DocumentRenderer(sd::ViewShellBase&)
Unexecuted instantiation: sd::DocumentRenderer::DocumentRenderer(sd::ViewShellBase&)
2667
2668
DocumentRenderer::~DocumentRenderer()
2669
0
{
2670
0
}
2671
2672
//----- XRenderable -----------------------------------------------------------
2673
2674
sal_Int32 SAL_CALL DocumentRenderer::getRendererCount (
2675
    const css::uno::Any&,
2676
    const css::uno::Sequence<css::beans::PropertyValue >& rOptions)
2677
0
{
2678
0
    mpImpl->ProcessProperties(rOptions);
2679
0
    return mpImpl->GetPrintPageCount();
2680
0
}
2681
2682
Sequence<beans::PropertyValue> SAL_CALL DocumentRenderer::getRenderer (
2683
    sal_Int32,
2684
    const css::uno::Any&,
2685
    const css::uno::Sequence<css::beans::PropertyValue>& rOptions)
2686
0
{
2687
0
    mpImpl->ProcessProperties(rOptions);
2688
0
    return mpImpl->GetProperties();
2689
0
}
2690
2691
void SAL_CALL DocumentRenderer::render (
2692
    sal_Int32 nRenderer,
2693
    const css::uno::Any&,
2694
    const css::uno::Sequence<css::beans::PropertyValue>& rOptions)
2695
0
{
2696
0
    mpImpl->ProcessProperties(rOptions);
2697
0
    mpImpl->PrintPage(nRenderer);
2698
0
}
2699
2700
} // end of namespace sd
2701
2702
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */