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