summaryrefslogtreecommitdiff
path: root/sd/source/ui/view/DocumentRenderer.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/view/DocumentRenderer.cxx')
-rwxr-xr-xsd/source/ui/view/DocumentRenderer.cxx2388
1 files changed, 2388 insertions, 0 deletions
diff --git a/sd/source/ui/view/DocumentRenderer.cxx b/sd/source/ui/view/DocumentRenderer.cxx
new file mode 100755
index 000000000000..1660c05a124f
--- /dev/null
+++ b/sd/source/ui/view/DocumentRenderer.cxx
@@ -0,0 +1,2388 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include "DocumentRenderer.hxx"
+#include "DocumentRenderer.hrc"
+
+#include "drawdoc.hxx"
+#include "optsitem.hxx"
+#include "sdresid.hxx"
+#include "strings.hrc"
+#include "sdattr.hxx"
+#include "Window.hxx"
+#include "drawview.hxx"
+#include "DrawViewShell.hxx"
+#include "FrameView.hxx"
+#include "Outliner.hxx"
+#include "OutlineViewShell.hxx"
+
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <sfx2/printer.hxx>
+#include <editeng/editstat.hxx>
+#include <editeng/outlobj.hxx>
+#include <svx/svdetc.hxx>
+#include <svx/svditer.hxx>
+#include <svx/svdopage.hxx>
+#include <svx/svdopath.hxx>
+#include <svx/xlnclit.hxx>
+#include <toolkit/awt/vclxdevice.hxx>
+#include <tools/resary.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <vcl/msgbox.hxx>
+#include <unotools/moduleoptions.hxx>
+
+#include <vector>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using ::rtl::OUString;
+
+
+namespace sd {
+
+namespace {
+ OUString A2S (const char* pString)
+ {
+ return OUString::createFromAscii(pString);
+ }
+
+
+
+ /** Convenience class to extract values from the sequence of properties
+ given to one of the XRenderable methods.
+ */
+ class PrintOptions
+ {
+ public:
+ PrintOptions (
+ const vcl::PrinterOptionsHelper& rHelper,
+ const ::std::vector<sal_Int32>& rSlidesPerPage)
+ : mrProperties(rHelper),
+ maSlidesPerPage(rSlidesPerPage)
+ {
+ }
+
+ bool IsWarningOrientation (void) const
+ {
+ return GetBoolValue(NULL, true);
+ }
+
+ bool IsPrintPageName (void) const
+ {
+ return GetBoolValue("IsPrintName");
+ }
+
+ bool IsDate (void) const
+ {
+ return GetBoolValue("IsPrintDateTime");
+ }
+
+ bool IsTime (void) const
+ {
+ return GetBoolValue("IsPrintDateTime");
+ }
+
+ bool IsHiddenPages (void) const
+ {
+ return GetBoolValue("IsPrintHidden");
+ }
+
+ bool IsHandoutHorizontal (void) const
+ {
+ return GetBoolValue("SlidesPerPageOrder", sal_Int32(0), true);
+ }
+
+ sal_Int32 GetHandoutPageCount (void) const
+ {
+ sal_uInt32 nIndex = static_cast<sal_Int32>(mrProperties.getIntValue("SlidesPerPage", sal_Int32(0)));
+ if (nIndex<maSlidesPerPage.size())
+ return maSlidesPerPage[nIndex];
+ else if ( ! maSlidesPerPage.empty())
+ return maSlidesPerPage[0];
+ else
+ return 0;
+ }
+
+ bool IsDraw (void) const
+ {
+ return GetBoolValue("PageContentType", sal_Int32(0));
+ }
+
+ bool IsHandout (void) const
+ {
+ return GetBoolValue("PageContentType", sal_Int32(1));
+ }
+
+ bool IsNotes (void) const
+ {
+ return GetBoolValue("PageContentType", sal_Int32(2));
+ }
+
+ bool IsOutline (void) const
+ {
+ return GetBoolValue("PageContentType", sal_Int32(3));
+ }
+
+ ULONG GetOutputQuality (void) const
+ {
+ sal_Int32 nQuality = static_cast<sal_Int32>(mrProperties.getIntValue( "Quality", sal_Int32(0) ));
+ return nQuality;
+ }
+
+ bool IsPageSize (void) const
+ {
+ return GetBoolValue("PageOptions", sal_Int32(1));
+ }
+
+ bool IsTilePage (void) const
+ {
+ return GetBoolValue("PageOptions", sal_Int32(2)) || GetBoolValue("PageOptions", sal_Int32(3));
+ }
+
+ bool IsCutPage (void) const
+ {
+ return GetBoolValue("PageOptions", sal_Int32(0));
+ }
+
+ bool IsBooklet (void) const
+ {
+ return GetBoolValue("PrintProspect", false);
+ }
+
+ bool IsPrintExcluded (void) const
+ {
+ return (IsNotes() || IsDraw() || IsHandout()) && IsHiddenPages();
+ }
+
+ bool IsPrintFrontPage (void) const
+ {
+ sal_Int32 nInclude = static_cast<sal_Int32>(mrProperties.getIntValue( "PrintProspectInclude", 0 ));
+ return nInclude == 0 || nInclude == 1;
+ }
+
+ bool IsPrintBackPage (void) const
+ {
+ sal_Int32 nInclude = static_cast<sal_Int32>(mrProperties.getIntValue( "PrintProspectInclude", 0 ));
+ return nInclude == 0 || nInclude == 2;
+ }
+
+ bool IsPaperBin (void) const
+ {
+ return GetBoolValue("PrintPaperFromSetup", false);
+ }
+
+ OUString GetPrinterSelection (void) const
+ {
+ sal_Int32 nContent = static_cast<sal_Int32>(mrProperties.getIntValue( "PrintContent", 0 ));
+ OUString sValue( A2S("all") );
+ if( nContent == 1 )
+ sValue = mrProperties.getStringValue( "PageRange", A2S( "all" ) );
+ else if( nContent == 2 )
+ sValue = A2S( "selection" );
+ return sValue;
+ }
+
+ private:
+ const vcl::PrinterOptionsHelper& mrProperties;
+ const ::std::vector<sal_Int32> maSlidesPerPage;
+
+ /** When the value of the property with name pName is a boolean then
+ return its value. When the property is unknown then
+ bDefaultValue is returned. Otherwise <FALSE/> is returned.
+ */
+ bool GetBoolValue (
+ const sal_Char* pName,
+ const bool bDefaultValue = false) const
+ {
+ sal_Bool bValue = mrProperties.getBoolValue( pName, bDefaultValue );
+ return bValue;
+ }
+
+ /** Return <TRUE/> when the value of the property with name pName is
+ a string and its value equals pValue. When the property is
+ unknown then bDefaultValue is returned. Otherwise <FALSE/> is
+ returned.
+ */
+ bool GetBoolValue (
+ const sal_Char* pName,
+ const sal_Char* pValue,
+ const bool bDefaultValue = false) const
+ {
+ OUString sValue( mrProperties.getStringValue( pName ) );
+ if (sValue.getLength())
+ return sValue.equalsAscii(pValue);
+ else
+ return bDefaultValue;
+ }
+
+ /** Return <TRUE/> when the value of the property with name pName is
+ an integer and its value is nTriggerValue. Otherwise <FALSE/> is
+ returned.
+ */
+ bool GetBoolValue (
+ const sal_Char* pName,
+ const sal_Int32 nTriggerValue) const
+ {
+ sal_Int32 nValue = static_cast<sal_Int32>(mrProperties.getIntValue( pName ));
+ return nValue == nTriggerValue;
+ }
+ };
+
+
+
+ /** This class is like MultiSelection but understands two special values.
+ "all" indicates that all pages are selected. "selection" indicates that no
+ pages but a set of shapes is selected.
+ */
+ class Selection
+ {
+ public:
+ Selection (const OUString& rsSelection, const SdPage* pCurrentPage)
+ : mbAreAllPagesSelected(rsSelection.equalsAscii("all")),
+ mbIsShapeSelection(rsSelection.equalsAscii("selection")),
+ mnCurrentPageIndex(pCurrentPage!=NULL ? (pCurrentPage->GetPageNum()-1)/2 : -1),
+ mpSelectedPages()
+ {
+ if ( ! (mbAreAllPagesSelected || mbIsShapeSelection))
+ mpSelectedPages.reset(new MultiSelection(rsSelection));
+ }
+
+ bool IsMarkedOnly (void) const
+ {
+ return mbIsShapeSelection;
+ }
+
+ /** Call with a 0 based page index.
+ */
+ bool IsSelected (const sal_Int32 nIndex) const
+ {
+ if (mbAreAllPagesSelected)
+ return true;
+ else if (mpSelectedPages)
+ return mpSelectedPages->IsSelected(nIndex+1);
+ else if (mbIsShapeSelection && nIndex==mnCurrentPageIndex)
+ return true;
+ else
+ return false;
+ }
+
+ private:
+ const bool mbAreAllPagesSelected;
+ const bool mbIsShapeSelection;
+ const sal_Int32 mnCurrentPageIndex;
+ ::boost::scoped_ptr<MultiSelection> mpSelectedPages;
+ };
+
+ /** A collection of values that helps to reduce the number of arguments
+ given to some functions. Note that not all values are set at the
+ same time.
+ */
+ class PrintInfo
+ {
+ public:
+ PrintInfo (
+ const Printer* pPrinter,
+ const OUString& rsPrinterSelection,
+ const ::boost::shared_ptr<ViewShell> pView)
+ : mpPrinter(pPrinter),
+ mnDrawMode(DRAWMODE_DEFAULT),
+ msTimeDate(),
+ msPageString(),
+ maPrintSize(0,0),
+ maPageSize(0,0),
+ meOrientation(ORIENTATION_PORTRAIT),
+ maMap(),
+ maSelection(rsPrinterSelection, pView ? pView->getCurrentPage() : NULL),
+ mbPrintMarkedOnly(maSelection.IsMarkedOnly())
+ {}
+
+ const Printer* mpPrinter;
+ ULONG mnDrawMode;
+ ::rtl::OUString msTimeDate;
+ ::rtl::OUString msPageString;
+ Size maPrintSize;
+ Size maPageSize;
+ Orientation meOrientation;
+ MapMode maMap;
+ const Selection maSelection;
+ bool mbPrintMarkedOnly;
+ };
+
+
+
+ /** Output one page of the document to the given printer. Note that
+ more than one document page may be output to one printer page.
+ */
+ void PrintPage (
+ Printer& rPrinter,
+ ::sd::View& rPrintView,
+ SdPage& rPage,
+ View* pView,
+ const bool bPrintMarkedOnly,
+ const SetOfByte& rVisibleLayers,
+ const SetOfByte& rPrintableLayers)
+ {
+ rPrintView.ShowSdrPage(&rPage);
+
+ const MapMode aOriginalMapMode (rPrinter.GetMapMode());
+
+ // Set the visible layers
+ SdrPageView* pPageView = rPrintView.GetSdrPageView();
+ OSL_ASSERT(pPageView!=NULL);
+ pPageView->SetVisibleLayers(rVisibleLayers);
+ pPageView->SetPrintableLayers(rPrintableLayers);
+
+ if (pView!=NULL && bPrintMarkedOnly)
+ pView->DrawMarkedObj(rPrinter);
+ else
+ rPrintView.CompleteRedraw(&rPrinter, Rectangle(Point(0,0), rPage.GetSize()));
+
+ rPrinter.SetMapMode(aOriginalMapMode);
+
+ rPrintView.HideSdrPage();
+ }
+
+
+
+
+ /** Output a string (that typically is not part of a document page) to
+ the given printer.
+ */
+ void PrintMessage (
+ Printer& rPrinter,
+ const ::rtl::OUString& rsPageString,
+ const Point& rPageStringOffset)
+ {
+ const Font aOriginalFont (rPrinter.OutputDevice::GetFont());
+ rPrinter.SetFont(Font(FAMILY_SWISS, Size(0, 423)));
+ rPrinter.DrawText(rPageStringOffset, rsPageString);
+ rPrinter.SetFont(aOriginalFont);
+ }
+
+
+
+
+ /** Read the resource file and process it into a sequence of properties
+ that can be passed to the printing dialog.
+ */
+ class DialogCreator : Resource
+ {
+ public:
+ DialogCreator (bool bImpress)
+ : Resource(SdResId(_STR_IMPRESS_PRINT_UI_OPTIONS))
+ , mbImpress(bImpress)
+ {
+ ProcessResource();
+ }
+
+ Sequence< beans::PropertyValue > GetDialogControls(void) const
+ {
+ if (maProperties.empty())
+ return Sequence< beans::PropertyValue >();
+ else
+ {
+ return Sequence<beans::PropertyValue>(
+ &maProperties.front(),
+ maProperties.size());
+ }
+ }
+
+ ::std::vector<sal_Int32> GetSlidesPerPage (void) const
+ {
+ return maSlidesPerPage;
+ }
+
+ private:
+ Any maDialog;
+ ::std::vector<beans::PropertyValue> maProperties;
+ ::std::vector<sal_Int32> maSlidesPerPage;
+ bool mbImpress;
+
+ void ProcessResource (void)
+ {
+ SvtModuleOptions aOpt;
+ String aAppGroupname( String( SdResId( _STR_IMPRESS_PRINT_UI_GROUP_NAME ) ) );
+ aAppGroupname.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "%s" ) ),
+ aOpt.GetModuleName( mbImpress ? SvtModuleOptions::E_SIMPRESS : SvtModuleOptions::E_SDRAW ) );
+ AddDialogControl( vcl::PrinterOptionsHelper::getGroupControlOpt(
+ aAppGroupname,
+ rtl::OUString()
+ ) );
+
+ if( mbImpress )
+ {
+ vcl::PrinterOptionsHelper::UIControlOptions aPrintOpt;
+ aPrintOpt.maGroupHint = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "JobPage" ) );
+ AddDialogControl( vcl::PrinterOptionsHelper::getSubgroupControlOpt(
+ String( SdResId(_STR_IMPRESS_PRINT_UI_PRINT_GROUP) ),
+ rtl::OUString(),
+ aPrintOpt )
+ );
+
+ AddDialogControl( vcl::PrinterOptionsHelper::getChoiceControlOpt(
+ String( SdResId( _STR_IMPRESS_PRINT_UI_CONTENT ) ),
+ CreateChoice(_STR_IMPRESS_PRINT_UI_CONTENT_HELP),
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "PageContentType" ) ),
+ CreateChoice(_STR_IMPRESS_PRINT_UI_CONTENT_CHOICES),
+ 0,
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "List" ) )
+ )
+ );
+
+ vcl::PrinterOptionsHelper::UIControlOptions
+ aContentOpt( OUString( RTL_CONSTASCII_USTRINGPARAM( "PageContentType" ) ), 1 );
+ AddDialogControl( vcl::PrinterOptionsHelper::getChoiceControlOpt(
+ String( SdResId( _STR_IMPRESS_PRINT_UI_SLIDESPERPAGE ) ),
+ CreateChoice(_STR_IMPRESS_PRINT_UI_SLIDESPERPAGE_CHOICES_HELP),
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "SlidesPerPage" ) ),
+ GetSlidesPerPageSequence(),
+ 0,
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "List" ) ),
+ aContentOpt
+ )
+ );
+
+ vcl::PrinterOptionsHelper::UIControlOptions
+ aSlidesPerPageOpt( OUString( RTL_CONSTASCII_USTRINGPARAM( "SlidesPerPage" ) ), -1, sal_True );
+ AddDialogControl( vcl::PrinterOptionsHelper::getChoiceControlOpt(
+ String( SdResId( _STR_IMPRESS_PRINT_UI_ORDER ) ),
+ CreateChoice(_STR_IMPRESS_PRINT_UI_ORDER_CHOICES_HELP),
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "SlidesPerPageOrder" ) ),
+ CreateChoice(_STR_IMPRESS_PRINT_UI_ORDER_CHOICES),
+ 0,
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "List" ) ),
+ aSlidesPerPageOpt )
+ );
+ }
+
+ AddDialogControl( vcl::PrinterOptionsHelper::getSubgroupControlOpt(
+ String( SdResId(_STR_IMPRESS_PRINT_UI_INCLUDE_CONTENT) ), rtl::OUString() ) );
+
+
+ if( mbImpress )
+ {
+ AddDialogControl( vcl::PrinterOptionsHelper::getBoolControlOpt(
+ String( SdResId(_STR_IMPRESS_PRINT_UI_IS_PRINT_NAME) ),
+ String( SdResId(_STR_IMPRESS_PRINT_UI_IS_PRINT_NAME_HELP) ),
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "IsPrintName" ) ),
+ sal_False
+ )
+ );
+ }
+ else
+ {
+ AddDialogControl( vcl::PrinterOptionsHelper::getBoolControlOpt(
+ String( SdResId(_STR_DRAW_PRINT_UI_IS_PRINT_NAME) ),
+ String( SdResId(_STR_DRAW_PRINT_UI_IS_PRINT_NAME_HELP) ),
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "IsPrintName" ) ),
+ sal_False
+ )
+ );
+ }
+
+ AddDialogControl( vcl::PrinterOptionsHelper::getBoolControlOpt(
+ String( SdResId(_STR_IMPRESS_PRINT_UI_IS_PRINT_DATE) ),
+ String( SdResId(_STR_IMPRESS_PRINT_UI_IS_PRINT_DATE_HELP) ),
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "IsPrintDateTime" ) ),
+ sal_False
+ )
+ );
+
+ if( mbImpress )
+ {
+ AddDialogControl( vcl::PrinterOptionsHelper::getBoolControlOpt(
+ String( SdResId(_STR_IMPRESS_PRINT_UI_IS_PRINT_HIDDEN) ),
+ String( SdResId(_STR_IMPRESS_PRINT_UI_IS_PRINT_HIDDEN_HELP) ),
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "IsPrintHidden" ) ),
+ sal_False
+ )
+ );
+ }
+
+ AddDialogControl( vcl::PrinterOptionsHelper::getSubgroupControlOpt(
+ String( SdResId(_STR_IMPRESS_PRINT_UI_QUALITY) ), rtl::OUString() ) );
+
+ AddDialogControl( vcl::PrinterOptionsHelper::getChoiceControlOpt(
+ rtl::OUString(),
+ CreateChoice(_STR_IMPRESS_PRINT_UI_QUALITY_CHOICES_HELP),
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "Quality" ) ),
+ CreateChoice(_STR_IMPRESS_PRINT_UI_QUALITY_CHOICES),
+ 0
+ )
+ );
+
+ AddDialogControl( vcl::PrinterOptionsHelper::getSubgroupControlOpt(
+ String( SdResId(_STR_IMPRESS_PRINT_UI_PAGE_OPTIONS) ), rtl::OUString() ) );
+
+ if( mbImpress )
+ {
+ // FIXME: additional dependency on PrintProspect = false
+ vcl::PrinterOptionsHelper::UIControlOptions
+ aPageOptionsOpt( OUString( RTL_CONSTASCII_USTRINGPARAM( "PageContentType" ) ), 0 );
+ AddDialogControl( vcl::PrinterOptionsHelper::getChoiceControlOpt(
+ rtl::OUString(),
+ CreateChoice(_STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES_HELP),
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "PageOptions" ) ),
+ CreateChoice(_STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES),
+ 0,
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "Radio" ) ),
+ aPageOptionsOpt
+ )
+ );
+ }
+ else
+ {
+ vcl::PrinterOptionsHelper::UIControlOptions
+ aPageOptionsOpt( OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintProspect" ) ), sal_False );
+ AddDialogControl( vcl::PrinterOptionsHelper::getChoiceControlOpt(
+ rtl::OUString(),
+ CreateChoice(_STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES_HELP),
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "PageOptions" ) ),
+ CreateChoice(_STR_IMPRESS_PRINT_UI_PAGE_OPTIONS_CHOICES_DRAW),
+ 0,
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "Radio" ) ),
+ aPageOptionsOpt
+ )
+ );
+ }
+
+ vcl::PrinterOptionsHelper::UIControlOptions aBrochureOpt;
+ aBrochureOpt.maGroupHint = OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutPage" ) );
+ AddDialogControl( vcl::PrinterOptionsHelper::getSubgroupControlOpt(
+ String( SdResId(_STR_IMPRESS_PRINT_UI_PAGE_SIDES) ), rtl::OUString(),
+ aBrochureOpt ) );
+
+ // brochure printing
+ AddDialogControl( vcl::PrinterOptionsHelper::getBoolControlOpt(
+ String( SdResId(_STR_IMPRESS_PRINT_UI_BROCHURE) ),
+ String( SdResId(_STR_IMPRESS_PRINT_UI_BROCHURE_HELP) ),
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintProspect" ) ),
+ sal_False,
+ aBrochureOpt
+ )
+ );
+
+ vcl::PrinterOptionsHelper::UIControlOptions
+ aIncludeOpt( OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintProspect" ) ), -1, sal_False );
+ aIncludeOpt.maGroupHint = OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutPage" ) );
+ AddDialogControl( vcl::PrinterOptionsHelper::getChoiceControlOpt(
+ String( SdResId(_STR_IMPRESS_PRINT_UI_BROCHURE_INCLUDE) ),
+ CreateChoice(_STR_IMPRESS_PRINT_UI_BROCHURE_INCLUDE_LIST_HELP),
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintProspectInclude" ) ),
+ CreateChoice(_STR_IMPRESS_PRINT_UI_BROCHURE_INCLUDE_LIST),
+ 0,
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "List" ) ),
+ aIncludeOpt
+ )
+ );
+
+ // paper tray (on options page)
+ vcl::PrinterOptionsHelper::UIControlOptions aPaperTrayOpt;
+ aPaperTrayOpt.maGroupHint = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OptionsPageOptGroup" ) );
+ AddDialogControl( vcl::PrinterOptionsHelper::getBoolControlOpt(
+ String( SdResId(_STR_IMPRESS_PRINT_UI_PAPER_TRAY) ),
+ String( SdResId(_STR_IMPRESS_PRINT_UI_PAPER_TRAY_HELP) ),
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintPaperFromSetup" ) ),
+ sal_False,
+ aPaperTrayOpt
+ )
+ );
+ // print range selection
+ vcl::PrinterOptionsHelper::UIControlOptions aPrintRangeOpt;
+ aPrintRangeOpt.mbInternalOnly = sal_True;
+ aPrintRangeOpt.maGroupHint = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintRange" ) );
+ AddDialogControl( vcl::PrinterOptionsHelper::getSubgroupControlOpt(
+ String( SdResId( _STR_IMPRESS_PRINT_UI_PAGE_RANGE ) ),
+ rtl::OUString(),
+ aPrintRangeOpt )
+ );
+
+ // create a choice for the content to create
+ rtl::OUString aPrintRangeName( RTL_CONSTASCII_USTRINGPARAM( "PrintContent" ) );
+ AddDialogControl( vcl::PrinterOptionsHelper::getChoiceControlOpt( rtl::OUString(),
+ CreateChoice(_STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE_HELP),
+ aPrintRangeName,
+ CreateChoice(mbImpress
+ ? _STR_IMPRESS_PRINT_UI_PAGE_RANGE_CHOICE
+ : _STR_DRAW_PRINT_UI_PAGE_RANGE_CHOICE),
+ 0 )
+ );
+ // create a an Edit dependent on "Pages" selected
+ vcl::PrinterOptionsHelper::UIControlOptions aPageRangeOpt( aPrintRangeName, 1, sal_True );
+ AddDialogControl( vcl::PrinterOptionsHelper::getEditControlOpt( rtl::OUString(),
+ rtl::OUString(),
+ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PageRange" ) ),
+ rtl::OUString(),
+ aPageRangeOpt )
+ );
+
+ FreeResource();
+ }
+
+ void AddDialogControl( const Any& i_rCtrl )
+ {
+ beans::PropertyValue aVal;
+ aVal.Value = i_rCtrl;
+ maProperties.push_back( aVal );
+ }
+
+ Sequence<rtl::OUString> CreateChoice (const USHORT nResourceId) const
+ {
+ SdResId aResourceId (nResourceId);
+ ResStringArray aChoiceStrings (aResourceId);
+
+ const sal_uInt32 nCount (aChoiceStrings.Count());
+ Sequence<rtl::OUString> aChoices (nCount);
+ for (sal_uInt32 nIndex=0; nIndex<nCount; ++nIndex)
+ aChoices[nIndex] = aChoiceStrings.GetString(nIndex);
+
+ return aChoices;
+ }
+
+ Sequence<rtl::OUString> GetSlidesPerPageSequence (void)
+ {
+ const Sequence<rtl::OUString> aChoice (
+ CreateChoice(_STR_IMPRESS_PRINT_UI_SLIDESPERPAGE_CHOICES));
+ maSlidesPerPage.clear();
+ maSlidesPerPage.push_back(0); // first is using the default
+ for (sal_Int32 nIndex=1,nCount=aChoice.getLength(); nIndex<nCount; ++nIndex)
+ maSlidesPerPage.push_back(aChoice[nIndex].toInt32());
+ return aChoice;
+ }
+ };
+
+
+
+
+ /** The Prepare... methods of the DocumentRenderer::Implementation class
+ create a set of PrinterPage objects that contain all necessary
+ information to do the actual printing. There is one PrinterPage
+ object per printed page. Derived classes implement the actual, mode
+ specific printing.
+
+ This and all derived classes support the asynchronous printing
+ process by not storing pointers to any data with lifetime shorter
+ than the PrinterPage objects, i.e. slides, shapes, (one of) the
+ outliner (of the document).
+ */
+ class PrinterPage
+ {
+ public:
+ PrinterPage (
+ const PageKind ePageKind,
+ const MapMode& rMapMode,
+ const bool bPrintMarkedOnly,
+ const ::rtl::OUString& rsPageString,
+ const Point& rPageStringOffset,
+ const ULONG nDrawMode,
+ const Orientation eOrientation,
+ const USHORT nPaperTray)
+ : mePageKind(ePageKind),
+ maMap(rMapMode),
+ mbPrintMarkedOnly(bPrintMarkedOnly),
+ msPageString(rsPageString),
+ maPageStringOffset(rPageStringOffset),
+ mnDrawMode(nDrawMode),
+ meOrientation(eOrientation),
+ mnPaperTray(nPaperTray)
+ {
+ }
+
+ virtual ~PrinterPage (void) {}
+
+ virtual void Print (
+ Printer& rPrinter,
+ SdDrawDocument& rDocument,
+ ViewShell& rViewShell,
+ View* pView,
+ DrawView& rPrintView,
+ const SetOfByte& rVisibleLayers,
+ const SetOfByte& rPrintableLayers) const = 0;
+
+ ULONG GetDrawMode (void) const { return mnDrawMode; }
+ Orientation GetOrientation (void) const { return meOrientation; }
+ USHORT GetPaperTray (void) const { return mnPaperTray; }
+
+ protected:
+ const PageKind mePageKind;
+ const MapMode maMap;
+ const bool mbPrintMarkedOnly;
+ const ::rtl::OUString msPageString;
+ const Point maPageStringOffset;
+ const ULONG mnDrawMode;
+ const Orientation meOrientation;
+ const USHORT mnPaperTray;
+ };
+
+
+
+
+ /** The RegularPrinterPage is used for printing one regular slide (no
+ notes, handout, or outline) to one printer page.
+ */
+ class RegularPrinterPage : public PrinterPage
+ {
+ public:
+ RegularPrinterPage (
+ const USHORT nPageIndex,
+ const PageKind ePageKind,
+ const MapMode& rMapMode,
+ const bool bPrintMarkedOnly,
+ const ::rtl::OUString& rsPageString,
+ const Point& rPageStringOffset,
+ const ULONG nDrawMode,
+ const Orientation eOrientation,
+ const USHORT nPaperTray)
+ : PrinterPage(ePageKind, rMapMode, bPrintMarkedOnly, rsPageString,
+ rPageStringOffset, nDrawMode, eOrientation, nPaperTray),
+ mnPageIndex(nPageIndex)
+ {
+ }
+
+ virtual ~RegularPrinterPage (void) {}
+
+ virtual void Print (
+ Printer& rPrinter,
+ SdDrawDocument& rDocument,
+ ViewShell& rViewShell,
+ View* pView,
+ DrawView& rPrintView,
+ const SetOfByte& rVisibleLayers,
+ const SetOfByte& rPrintableLayers) const
+ {
+ (void)rViewShell;
+ SdPage* pPageToPrint = rDocument.GetSdPage(mnPageIndex, mePageKind);
+ rPrinter.SetMapMode(maMap);
+ PrintPage(
+ rPrinter,
+ rPrintView,
+ *pPageToPrint,
+ pView,
+ mbPrintMarkedOnly,
+ rVisibleLayers,
+ rPrintableLayers);
+ PrintMessage(
+ rPrinter,
+ msPageString,
+ maPageStringOffset);
+ }
+
+ private:
+ const USHORT mnPageIndex;
+ };
+
+
+
+
+ /** Print one slide multiple times on a printer page so that the whole
+ printer page is covered.
+ */
+ class TiledPrinterPage : public PrinterPage
+ {
+ public:
+ TiledPrinterPage (
+ const USHORT nPageIndex,
+ const PageKind ePageKind,
+ const sal_Int32 nGap,
+ const bool bPrintMarkedOnly,
+ const ::rtl::OUString& rsPageString,
+ const Point& rPageStringOffset,
+ const ULONG nDrawMode,
+ const Orientation eOrientation,
+ const USHORT nPaperTray)
+ : PrinterPage(ePageKind, MapMode(), bPrintMarkedOnly, rsPageString,
+ rPageStringOffset, nDrawMode, eOrientation, nPaperTray),
+ mnPageIndex(nPageIndex),
+ mnGap(nGap)
+ {
+ }
+
+ virtual ~TiledPrinterPage (void) {}
+
+ virtual void Print (
+ Printer& rPrinter,
+ SdDrawDocument& rDocument,
+ ViewShell& rViewShell,
+ View* pView,
+ DrawView& rPrintView,
+ const SetOfByte& rVisibleLayers,
+ const SetOfByte& rPrintableLayers) const
+ {
+ (void)rViewShell;
+ SdPage* pPageToPrint = rDocument.GetSdPage(mnPageIndex, mePageKind);
+ if (pPageToPrint==NULL)
+ return;
+ MapMode aMap (rPrinter.GetMapMode());
+
+ const Size aPageSize (pPageToPrint->GetSize());
+ const Size aPrintSize (rPrinter.GetOutputSize());
+
+ const sal_Int32 nPageWidth (aPageSize.Width() + mnGap
+ - pPageToPrint->GetLftBorder() - pPageToPrint->GetRgtBorder());
+ const sal_Int32 nPageHeight (aPageSize.Height() + mnGap
+ - pPageToPrint->GetUppBorder() - pPageToPrint->GetLwrBorder());
+ if (nPageWidth<=0 || nPageHeight<=0)
+ return;
+
+ // Print at least two rows and columns. More if the document
+ // page fits completely onto the printer page.
+ const sal_Int32 nColumnCount (::std::max(sal_Int32(2),
+ sal_Int32(aPrintSize.Width() / nPageWidth)));
+ const sal_Int32 nRowCount (::std::max(sal_Int32(2),
+ sal_Int32(aPrintSize.Height() / nPageHeight)));
+ Point aPrintOrigin;
+ for (sal_Int32 nRow=0; nRow<nRowCount; ++nRow)
+ for (sal_Int32 nColumn=0; nColumn<nColumnCount; ++nColumn)
+ {
+ aMap.SetOrigin(Point(nColumn*nPageWidth,nRow*nPageHeight));
+ rPrinter.SetMapMode(aMap);
+ PrintPage(
+ rPrinter,
+ rPrintView,
+ *pPageToPrint,
+ pView,
+ mbPrintMarkedOnly,
+ rVisibleLayers,
+ rPrintableLayers);
+ }
+
+ PrintMessage(
+ rPrinter,
+ msPageString,
+ maPageStringOffset);
+ }
+
+ private:
+ const USHORT mnPageIndex;
+ const sal_Int32 mnGap;
+ };
+
+ /** Print two slides to one printer page so that the resulting pages
+ form a booklet.
+ */
+ class BookletPrinterPage : public PrinterPage
+ {
+ public:
+ BookletPrinterPage (
+ const USHORT nFirstPageIndex,
+ const USHORT nSecondPageIndex,
+ const Point& rFirstOffset,
+ const Point& rSecondOffset,
+ const PageKind ePageKind,
+ const MapMode& rMapMode,
+ const bool bPrintMarkedOnly,
+ const ULONG nDrawMode,
+ const Orientation eOrientation,
+ const USHORT nPaperTray)
+ : PrinterPage(ePageKind, rMapMode, bPrintMarkedOnly, ::rtl::OUString(),
+ Point(), nDrawMode, eOrientation, nPaperTray),
+ mnFirstPageIndex(nFirstPageIndex),
+ mnSecondPageIndex(nSecondPageIndex),
+ maFirstOffset(rFirstOffset),
+ maSecondOffset(rSecondOffset)
+ {
+ }
+
+ virtual ~BookletPrinterPage (void) {}
+
+ virtual void Print (
+ Printer& rPrinter,
+ SdDrawDocument& rDocument,
+ ViewShell& rViewShell,
+ View* pView,
+ DrawView& rPrintView,
+ const SetOfByte& rVisibleLayers,
+ const SetOfByte& rPrintableLayers) const
+ {
+ (void)rViewShell;
+ MapMode aMap (maMap);
+ SdPage* pPageToPrint = rDocument.GetSdPage(mnFirstPageIndex, mePageKind);
+ if (pPageToPrint)
+ {
+ aMap.SetOrigin(maFirstOffset);
+ rPrinter.SetMapMode(aMap);
+ PrintPage(
+ rPrinter,
+ rPrintView,
+ *pPageToPrint,
+ pView,
+ mbPrintMarkedOnly,
+ rVisibleLayers,
+ rPrintableLayers);
+ }
+
+ pPageToPrint = rDocument.GetSdPage(mnSecondPageIndex, mePageKind);
+ if( pPageToPrint )
+ {
+ aMap.SetOrigin(maSecondOffset);
+ rPrinter.SetMapMode(aMap);
+ PrintPage(
+ rPrinter,
+ rPrintView,
+ *pPageToPrint,
+ pView,
+ mbPrintMarkedOnly,
+ rVisibleLayers,
+ rPrintableLayers);
+ }
+ }
+
+ private:
+ const USHORT mnFirstPageIndex;
+ const USHORT mnSecondPageIndex;
+ const Point maFirstOffset;
+ const Point maSecondOffset;
+ };
+
+
+
+
+ /** One handout page displays one to nine slides.
+ */
+ class HandoutPrinterPage : public PrinterPage
+ {
+ public:
+ HandoutPrinterPage (
+ const USHORT nHandoutPageIndex,
+ const ::std::vector<USHORT>& rPageIndices,
+ const MapMode& rMapMode,
+ const ::rtl::OUString& rsPageString,
+ const Point& rPageStringOffset,
+ const ULONG nDrawMode,
+ const Orientation eOrientation,
+ const USHORT nPaperTray)
+ : PrinterPage(PK_HANDOUT, rMapMode, false, rsPageString,
+ rPageStringOffset, nDrawMode, eOrientation, nPaperTray),
+ mnHandoutPageIndex(nHandoutPageIndex),
+ maPageIndices(rPageIndices)
+ {
+ }
+
+ virtual void Print (
+ Printer& rPrinter,
+ SdDrawDocument& rDocument,
+ ViewShell& rViewShell,
+ View* pView,
+ DrawView& rPrintView,
+ const SetOfByte& rVisibleLayers,
+ const SetOfByte& rPrintableLayers) const
+ {
+ SdPage& rHandoutPage (*rDocument.GetSdPage(0, PK_HANDOUT));
+
+ Reference< com::sun::star::beans::XPropertySet > xHandoutPage( rHandoutPage.getUnoPage(), UNO_QUERY );
+ const rtl::OUString sPageNumber( RTL_CONSTASCII_USTRINGPARAM( "Number" ) );
+
+ // Collect the page objects of the handout master.
+ std::vector<SdrPageObj*> aHandoutPageObjects;
+ SdrObjListIter aShapeIter (rHandoutPage);
+ while (aShapeIter.IsMore())
+ {
+ SdrPageObj* pPageObj = dynamic_cast<SdrPageObj*>(aShapeIter.Next());
+ if (pPageObj)
+ aHandoutPageObjects.push_back(pPageObj);
+ }
+ if (aHandoutPageObjects.empty())
+ return;
+
+ // Connect page objects with pages.
+ std::vector<SdrPageObj*>::iterator aPageObjIter (aHandoutPageObjects.begin());
+ for (std::vector<USHORT>::const_iterator
+ iPageIndex(maPageIndices.begin()),
+ iEnd(maPageIndices.end());
+ iPageIndex!=iEnd && aPageObjIter!=aHandoutPageObjects.end();
+ ++iPageIndex)
+ {
+ // Check if the page still exists.
+ if (*iPageIndex >= rDocument.GetSdPageCount(PK_STANDARD))
+ continue;
+
+ SdrPageObj* pPageObj = (*aPageObjIter++);
+ pPageObj->SetReferencedPage(rDocument.GetSdPage(*iPageIndex, PK_STANDARD));
+ }
+
+ // if there are more page objects than pages left, set the rest to invisible
+ int nHangoverCount = 0;
+ while (aPageObjIter != aHandoutPageObjects.end())
+ {
+ (*aPageObjIter++)->SetReferencedPage(0L);
+ nHangoverCount++;
+ }
+
+ // Hide outlines for objects that have pages attached.
+ if (nHangoverCount > 0)
+ {
+ int nSkip = aHandoutPageObjects.size() - nHangoverCount;
+ aShapeIter.Reset();
+ while (aShapeIter.IsMore())
+ {
+ SdrPathObj* pPathObj = dynamic_cast<SdrPathObj*>(aShapeIter.Next());
+ if (pPathObj)
+ {
+ if (nSkip > 0)
+ --nSkip;
+ else
+ pPathObj->SetMergedItem(XLineStyleItem(XLINE_NONE));
+ }
+ }
+ }
+
+ if( xHandoutPage.is() ) try
+ {
+ xHandoutPage->setPropertyValue( sPageNumber, Any( static_cast<sal_Int16>(mnHandoutPageIndex) ) );
+ }
+ catch( Exception& )
+ {
+ }
+ rViewShell.SetPrintedHandoutPageNum( mnHandoutPageIndex + 1 );
+
+ MapMode aMap (rPrinter.GetMapMode());
+ rPrinter.SetMapMode(maMap);
+
+ PrintPage(
+ rPrinter,
+ rPrintView,
+ rHandoutPage,
+ pView,
+ false,
+ rVisibleLayers,
+ rPrintableLayers);
+ PrintMessage(
+ rPrinter,
+ msPageString,
+ maPageStringOffset);
+
+ if( xHandoutPage.is() ) try
+ {
+ xHandoutPage->setPropertyValue( sPageNumber, Any( static_cast<sal_Int16>(0) ) );
+ }
+ catch( Exception& )
+ {
+ }
+ rViewShell.SetPrintedHandoutPageNum(1);
+
+ // Restore outlines.
+ if (nHangoverCount > 0)
+ {
+ aShapeIter.Reset();
+ while (aShapeIter.IsMore())
+ {
+ SdrPathObj* pPathObj = dynamic_cast<SdrPathObj*>(aShapeIter.Next());
+ if (pPathObj != NULL)
+ pPathObj->SetMergedItem(XLineStyleItem(XLINE_SOLID));
+ }
+ }
+
+ }
+
+ private:
+ const USHORT mnHandoutPageIndex;
+ const ::std::vector<USHORT> maPageIndices;
+ };
+
+
+
+
+ /** The outline information (title, subtitle, outline objects) of the
+ document. There is no fixed mapping of slides to printer pages.
+ */
+ class OutlinerPrinterPage : public PrinterPage
+ {
+ public:
+ OutlinerPrinterPage (
+ OutlinerParaObject* pParaObject,
+ const MapMode& rMapMode,
+ const ::rtl::OUString& rsPageString,
+ const Point& rPageStringOffset,
+ const ULONG nDrawMode,
+ const Orientation eOrientation,
+ const USHORT nPaperTray)
+ : PrinterPage(PK_HANDOUT, rMapMode, false, rsPageString,
+ rPageStringOffset, nDrawMode, eOrientation, nPaperTray),
+ mpParaObject(pParaObject)
+ {
+ }
+
+ ~OutlinerPrinterPage (void)
+ {
+ mpParaObject.reset();
+ }
+
+ virtual void Print (
+ Printer& rPrinter,
+ SdDrawDocument& rDocument,
+ ViewShell& rViewShell,
+ View* pView,
+ DrawView& rPrintView,
+ const SetOfByte& rVisibleLayers,
+ const SetOfByte& rPrintableLayers) const
+ {
+ (void)rViewShell;
+ (void)pView;
+ (void)rPrintView;
+ (void)rVisibleLayers;
+ (void)rPrintableLayers;
+
+ // Set up the printer.
+ rPrinter.SetMapMode(maMap);
+
+ // Get and set up the outliner.
+ const Rectangle aOutRect (rPrinter.GetPageOffset(), rPrinter.GetOutputSize());
+ Outliner* pOutliner = rDocument.GetInternalOutliner();
+ const USHORT nSavedOutlMode (pOutliner->GetMode());
+ const BOOL bSavedUpdateMode (pOutliner->GetUpdateMode());
+ const Size aSavedPaperSize (pOutliner->GetPaperSize());
+
+ pOutliner->Init(OUTLINERMODE_OUTLINEVIEW);
+ pOutliner->SetPaperSize(aOutRect.GetSize());
+ pOutliner->SetUpdateMode(TRUE);
+ pOutliner->Clear();
+ pOutliner->SetText(*mpParaObject);
+
+ pOutliner->Draw(&rPrinter, aOutRect);
+
+ PrintMessage(
+ rPrinter,
+ msPageString,
+ maPageStringOffset);
+
+ // Restore outliner and printer.
+ pOutliner->Clear();
+ pOutliner->SetUpdateMode(bSavedUpdateMode);
+ pOutliner->SetPaperSize(aSavedPaperSize);
+ pOutliner->Init(nSavedOutlMode);
+ }
+
+ private:
+ ::boost::scoped_ptr<OutlinerParaObject> mpParaObject;
+ };
+}
+
+
+//===== DocumentRenderer::Implementation ======================================
+
+class DocumentRenderer::Implementation
+ : public SfxListener,
+ public vcl::PrinterOptionsHelper
+{
+public:
+ Implementation (ViewShellBase& rBase)
+ : mrBase(rBase),
+ mbIsDisposed(false),
+ mpPrinter(NULL),
+ mpOptions(),
+ maPrinterPages(),
+ mpPrintView(),
+ mbHasOrientationWarningBeenShown(false)
+ {
+ DialogCreator aCreator( mrBase.GetDocShell()->GetDocumentType() == DOCUMENT_TYPE_IMPRESS );
+ m_aUIProperties = aCreator.GetDialogControls();
+ maSlidesPerPage = aCreator.GetSlidesPerPage();
+
+ StartListening(mrBase);
+ }
+
+
+
+
+ virtual ~Implementation (void)
+ {
+ EndListening(mrBase);
+ }
+
+
+
+
+ virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint)
+ {
+ const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
+ if (pSimpleHint != NULL
+ && pSimpleHint->GetId() == SFX_HINT_DYING
+ && &rBroadcaster == &static_cast<SfxBroadcaster&>(mrBase))
+ {
+ Dispose();
+ }
+ }
+
+
+
+ /** Process the sequence of properties given to one of the XRenderable
+ methods.
+ */
+ void ProcessProperties (const css::uno::Sequence<css::beans::PropertyValue >& rOptions)
+ {
+ OSL_ASSERT(!mbIsDisposed);
+ if (mbIsDisposed)
+ return;
+
+ bool bIsValueChanged = processProperties( rOptions );
+
+ // The RenderDevice property is handled specially: its value is
+ // stored in mpPrinter instead of being retrieved on demand.
+ Any aDev( getValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "RenderDevice" ) ) ) );
+ Reference<awt::XDevice> xRenderDevice;
+
+ if (aDev >>= xRenderDevice)
+ {
+ VCLXDevice* pDevice = VCLXDevice::GetImplementation(xRenderDevice);
+ OutputDevice* pOut = pDevice ? pDevice->GetOutputDevice() : NULL;
+ mpPrinter = dynamic_cast<Printer*>(pOut);
+ }
+
+ if (bIsValueChanged)
+ {
+ if ( ! mpOptions )
+ mpOptions.reset(new PrintOptions(*this, maSlidesPerPage));
+ PreparePages();
+ }
+ }
+
+
+
+ /** Return the number of pages that are to be printed.
+ */
+ sal_Int32 GetPrintPageCount (void)
+ {
+ OSL_ASSERT(!mbIsDisposed);
+ if (mbIsDisposed)
+ return 0;
+ else
+ return maPrinterPages.size();
+ }
+
+
+
+ /** Return a sequence of properties that can be returned by the
+ XRenderable::getRenderer() method.
+ */
+ css::uno::Sequence<css::beans::PropertyValue> GetProperties (
+ const css::uno::Sequence<css::beans::PropertyValue>& rOptions)
+ {
+ (void)rOptions;
+
+ css::uno::Sequence<css::beans::PropertyValue> aProperties (3);
+
+ aProperties[0].Name = A2S("ExtraPrintUIOptions");
+ aProperties[0].Value <<= m_aUIProperties;
+
+ aProperties[1].Name = A2S("PageSize");
+ aProperties[1].Value <<= maPrintSize;
+
+ // FIXME: is this always true ?
+ aProperties[2].Name = A2S("PageIncludesNonprintableArea");
+ aProperties[2].Value = makeAny( sal_True );
+
+ return aProperties;
+ }
+
+
+
+
+ /** Print one of the prepared pages.
+ */
+ void PrintPage (const sal_Int32 nIndex)
+ {
+ OSL_ASSERT(!mbIsDisposed);
+ if (mbIsDisposed)
+ return;
+
+ Printer& rPrinter (*mpPrinter);
+
+ ::boost::shared_ptr<ViewShell> pViewShell (mrBase.GetMainViewShell());
+ if ( ! pViewShell)
+ return;
+
+ SdDrawDocument* pDocument = pViewShell->GetDoc();
+ OSL_ASSERT(pDocument!=NULL);
+
+ ::boost::shared_ptr<DrawViewShell> pDrawViewShell(
+ ::boost::dynamic_pointer_cast<DrawViewShell>(mrBase.GetMainViewShell()));
+
+ if ( ! mpPrintView)
+ mpPrintView.reset(new DrawView(mrBase.GetDocShell(), &rPrinter, pDrawViewShell.get()));
+
+ if (nIndex<0 || sal::static_int_cast<sal_uInt32>(nIndex)>=maPrinterPages.size())
+ return;
+
+ const ::boost::shared_ptr<PrinterPage> pPage (maPrinterPages[nIndex]);
+ OSL_ASSERT(pPage);
+ if ( ! pPage)
+ return;
+
+ const Orientation eSavedOrientation (rPrinter.GetOrientation());
+ const ULONG nSavedDrawMode (rPrinter.GetDrawMode());
+ const MapMode aSavedMapMode (rPrinter.GetMapMode());
+ const USHORT nSavedPaperBin (rPrinter.GetPaperBin());
+
+
+ // Set page orientation.
+ if ( ! rPrinter.SetOrientation(pPage->GetOrientation()))
+ {
+ if ( ! mbHasOrientationWarningBeenShown
+ && mpOptions->IsWarningOrientation())
+ {
+ mbHasOrientationWarningBeenShown = true;
+ // Show warning that the orientation could not be set.
+ if (pViewShell)
+ {
+ WarningBox aWarnBox(
+ pViewShell->GetActiveWindow(),
+ (WinBits)(WB_OK_CANCEL | WB_DEF_CANCEL),
+ String(SdResId(STR_WARN_PRINTFORMAT_FAILURE)));
+ if (aWarnBox.Execute() != RET_OK)
+ return;
+ }
+ }
+ }
+
+ // Set the draw mode.
+ rPrinter.SetDrawMode(pPage->GetDrawMode());
+
+ // Set paper tray.
+ rPrinter.SetPaperBin(pPage->GetPaperTray());
+
+ // Print the actual page.
+ pPage->Print(
+ rPrinter,
+ *pDocument,
+ *pViewShell,
+ pDrawViewShell ? pDrawViewShell->GetView() : NULL,
+ *mpPrintView,
+ pViewShell->GetFrameView()->GetVisibleLayers(),
+ pViewShell->GetFrameView()->GetPrintableLayers());
+
+ rPrinter.SetOrientation(eSavedOrientation);
+ rPrinter.SetDrawMode(nSavedDrawMode);
+ rPrinter.SetMapMode(aSavedMapMode);
+ rPrinter.SetPaperBin(nSavedPaperBin);
+ }
+
+
+
+
+private:
+ ViewShellBase& mrBase;
+ bool mbIsDisposed;
+ Printer* mpPrinter;
+ ::boost::scoped_ptr<PrintOptions> mpOptions;
+ ::std::vector< ::boost::shared_ptr< ::sd::PrinterPage> > maPrinterPages;
+ ::boost::scoped_ptr<DrawView> mpPrintView;
+ bool mbHasOrientationWarningBeenShown;
+ ::std::vector<sal_Int32> maSlidesPerPage;
+ awt::Size maPrintSize;
+
+ void Dispose (void)
+ {
+ mbIsDisposed = true;
+ }
+
+
+
+ /** Determine and set the paper orientation.
+ */
+ bool SetupPaperOrientation (
+ const PageKind ePageKind,
+ PrintInfo& rInfo)
+ {
+ SdDrawDocument* pDocument = mrBase.GetMainViewShell()->GetDoc();
+ rInfo.meOrientation = ORIENTATION_PORTRAIT;
+
+ if( ! mpOptions->IsBooklet())
+ {
+ rInfo.meOrientation = pDocument->GetSdPage(0, ePageKind)->GetOrientation();
+ }
+ else if (rInfo.maPageSize.Width() < rInfo.maPageSize.Height())
+ rInfo.meOrientation = ORIENTATION_LANDSCAPE;
+
+ const Size aPaperSize (rInfo.mpPrinter->GetPaperSize());
+ if( (rInfo.meOrientation == ORIENTATION_LANDSCAPE &&
+ (aPaperSize.Width() < aPaperSize.Height()))
+ ||
+ (rInfo.meOrientation == ORIENTATION_PORTRAIT &&
+ (aPaperSize.Width() > aPaperSize.Height()))
+ )
+ {
+ maPrintSize = awt::Size(aPaperSize.Height(), aPaperSize.Width());
+ // rInfo.maPrintSize = Size(rInfo.maPrintSize.Height(), rInfo.maPrintSize.Width());
+ }
+ else
+ {
+ maPrintSize = awt::Size(aPaperSize.Width(), aPaperSize.Height());
+ }
+
+ return true;
+ }
+
+
+
+ /** Top most method for preparing printer pages. In this and the other
+ Prepare... methods the various special cases are detected and
+ handled.
+ For every page that is to be printed (that may contain several
+ slides) one PrinterPage object is created and inserted into
+ maPrinterPages.
+ */
+ void PreparePages (void)
+ {
+ mpPrintView.reset();
+ maPrinterPages.clear();
+ mbHasOrientationWarningBeenShown = false;
+
+ ViewShell* pShell = mrBase.GetMainViewShell().get();
+
+ PrintInfo aInfo (mpPrinter, mpOptions->GetPrinterSelection(), mrBase.GetMainViewShell());
+
+ if (aInfo.mpPrinter!=NULL && pShell!=NULL)
+ {
+
+ MapMode aMap (aInfo.mpPrinter->GetMapMode());
+ aMap.SetMapUnit(MAP_100TH_MM);
+ aInfo.maMap = aMap;
+ mpPrinter->SetMapMode(aMap);
+
+ ::Outliner& rOutliner = mrBase.GetDocument()->GetDrawOutliner();
+ const ULONG nSavedControlWord (rOutliner.GetControlWord());
+ ULONG nCntrl = nSavedControlWord;
+ nCntrl &= ~EE_CNTRL_MARKFIELDS;
+ nCntrl &= ~EE_CNTRL_ONLINESPELLING;
+ rOutliner.SetControlWord( nCntrl );
+
+ // When in outline view then apply all pending changes to the model.
+ if (pShell->ISA(OutlineViewShell))
+ static_cast<OutlineViewShell*>(pShell)->PrepareClose (FALSE, FALSE);
+
+ // Collect some frequently used data.
+ if (mpOptions->IsDate())
+ {
+ aInfo.msTimeDate += GetSdrGlobalData().GetLocaleData()->getDate( Date() );
+ aInfo.msTimeDate += ::rtl::OUString((sal_Unicode)' ');
+ }
+
+ if (mpOptions->IsTime())
+ aInfo.msTimeDate += GetSdrGlobalData().GetLocaleData()->getTime( Time(), FALSE, FALSE );
+ aInfo.maPrintSize = aInfo.mpPrinter->GetOutputSize();
+ maPrintSize = awt::Size(
+ aInfo.mpPrinter->GetPaperSize().Width(),
+ aInfo.mpPrinter->GetPaperSize().Height());
+
+ switch (mpOptions->GetOutputQuality())
+ {
+ case 1:
+ aInfo.mnDrawMode = DRAWMODE_GRAYLINE | DRAWMODE_GRAYFILL
+ | DRAWMODE_BLACKTEXT | DRAWMODE_GRAYBITMAP
+ | DRAWMODE_GRAYGRADIENT;
+ break;
+
+ case 2:
+ aInfo.mnDrawMode = DRAWMODE_BLACKLINE | DRAWMODE_BLACKTEXT
+ | DRAWMODE_WHITEFILL | DRAWMODE_GRAYBITMAP
+ | DRAWMODE_WHITEGRADIENT;
+ break;
+
+ default:
+ aInfo.mnDrawMode = DRAWMODE_DEFAULT;
+ }
+
+ // check if selected range of pages contains transparent objects
+ /*
+ const bool bPrintPages (bPrintNotes || bPrintDraw || bPrintHandout);
+ const bool bContainsTransparency (bPrintPages && ContainsTransparency());
+ if (pPrinter->InitJob (mrBase.GetWindow(), !bIsAPI && bContainsTransparency))
+ */
+
+ if (mpOptions->IsDraw())
+ PrepareStdOrNotes(PK_STANDARD, aInfo);
+ if (mpOptions->IsNotes())
+ PrepareStdOrNotes(PK_NOTES, aInfo);
+ if (mpOptions->IsHandout())
+ {
+ InitHandoutTemplate();
+ PrepareHandout(aInfo);
+ }
+ if (mpOptions->IsOutline())
+ PrepareOutline(aInfo);
+
+ rOutliner.SetControlWord(nSavedControlWord);
+ }
+ }
+
+
+
+
+ /** Create the page objects of the handout template. When the actual
+ printing takes place then the page objects are assigned different
+ sets of slides for each printed page (see HandoutPrinterPage::Print).
+ */
+ void InitHandoutTemplate (void)
+ {
+ const sal_Int32 nSlidesPerHandout (mpOptions->GetHandoutPageCount());
+ const bool bHandoutHorizontal (mpOptions->IsHandoutHorizontal());
+
+ AutoLayout eLayout = AUTOLAYOUT_HANDOUT6;
+ switch (nSlidesPerHandout)
+ {
+ case 0: eLayout = AUTOLAYOUT_NONE; break; // AUTOLAYOUT_HANDOUT1; break;
+ case 1: eLayout = AUTOLAYOUT_HANDOUT1; break;
+ case 2: eLayout = AUTOLAYOUT_HANDOUT2; break;
+ case 3: eLayout = AUTOLAYOUT_HANDOUT3; break;
+ case 4: eLayout = AUTOLAYOUT_HANDOUT4; break;
+ default:
+ case 6: eLayout = AUTOLAYOUT_HANDOUT6; break;
+ case 9: eLayout = AUTOLAYOUT_HANDOUT9; break;
+ }
+
+ if( !mrBase.GetDocument() )
+ return;
+
+ SdDrawDocument& rModel = *mrBase.GetDocument();
+
+ // first, prepare handout page (not handout master)
+
+ SdPage* pHandout = rModel.GetSdPage(0, PK_HANDOUT);
+ if( !pHandout )
+ return;
+
+ // delete all previous shapes from handout page
+ while( pHandout->GetObjCount() )
+ {
+ SdrObject* pObj = pHandout->NbcRemoveObject(0);
+ if( pObj )
+ SdrObject::Free( pObj );
+ }
+
+ const bool bDrawLines (eLayout == AUTOLAYOUT_HANDOUT3);
+
+ std::vector< Rectangle > aAreas;
+ SdPage::CalculateHandoutAreas( rModel, eLayout, bHandoutHorizontal, aAreas );
+
+ std::vector< Rectangle >::iterator iter( aAreas.begin() );
+ while( iter != aAreas.end() )
+ {
+ pHandout->NbcInsertObject( new SdrPageObj((*iter++)) );
+
+ if( bDrawLines && (iter != aAreas.end()) )
+ {
+ Rectangle aRect( (*iter++) );
+
+ basegfx::B2DPolygon aPoly;
+ aPoly.insert(0, basegfx::B2DPoint( aRect.Left(), aRect.Top() ) );
+ aPoly.insert(1, basegfx::B2DPoint( aRect.Right(), aRect.Top() ) );
+
+ basegfx::B2DHomMatrix aMatrix;
+ aMatrix.translate( 0.0, static_cast< double >( aRect.GetHeight() / 7 ) );
+
+ basegfx::B2DPolyPolygon aPathPoly;
+ for( sal_uInt16 nLine = 0; nLine < 7; nLine++ )
+ {
+ aPoly.transform( aMatrix );
+ aPathPoly.append( aPoly );
+ }
+
+ SdrPathObj* pPathObj = new SdrPathObj(OBJ_PATHLINE, aPathPoly );
+ pPathObj->SetMergedItem(XLineStyleItem(XLINE_SOLID));
+ pPathObj->SetMergedItem(XLineColorItem(String(), Color(COL_BLACK)));
+
+ pHandout->NbcInsertObject( pPathObj );
+ }
+ }
+ }
+
+
+
+
+ /** Detect whether any of the slides that are to be printed contains
+ partially transparent or translucent shapes.
+ */
+ bool ContainsTransparency (const PrintInfo& rInfo) const
+ {
+ // const bool bPrintExcluded (mpOptions->IsPrintExcluded());
+ bool bContainsTransparency = false;
+
+ for (USHORT
+ nIndex=0,
+ nCount=mrBase.GetDocument()->GetSdPageCount(PK_STANDARD);
+ nIndex < nCount && !bContainsTransparency;
+ ++nIndex)
+ {
+ SdPage* pPage = GetFilteredPage(nIndex, PK_STANDARD, rInfo);
+ if (pPage == NULL)
+ continue;
+
+ bContainsTransparency = pPage->HasTransparentObjects();
+ if ( ! bContainsTransparency && pPage->TRG_HasMasterPage())
+ bContainsTransparency = pPage->TRG_GetMasterPage().HasTransparentObjects();
+ }
+
+ return bContainsTransparency;
+ }
+
+
+
+
+ /** Detect whether the specified slide is to be printed.
+ @return
+ When the slide is not to be printed then <NULL/> is returned.
+ Otherwise a pointer to the slide is returned.
+ */
+ SdPage* GetFilteredPage (
+ const sal_Int32 nPageIndex,
+ const PageKind ePageKind,
+ const PrintInfo& rInfo) const
+ {
+ OSL_ASSERT(mrBase.GetDocument() != NULL);
+ OSL_ASSERT(nPageIndex>=0);
+ if ( ! rInfo.maSelection.IsSelected(nPageIndex))
+ return NULL;
+ SdPage* pPage = mrBase.GetDocument()->GetSdPage(
+ sal::static_int_cast<USHORT>(nPageIndex),
+ ePageKind);
+ if (pPage == NULL)
+ return NULL;
+ if ( ! pPage->IsExcluded() || mpOptions->IsPrintExcluded())
+ return pPage;
+ else
+ return NULL;
+ }
+
+
+
+
+ /** Prepare the outline of the document for printing. There is no fixed
+ number of slides whose outline data is put onto one printer page.
+ If the current printer page has enough room for the outline of the
+ current slide then that is added. Otherwise a new printer page is
+ started.
+ */
+ void PrepareOutline (PrintInfo& rInfo)
+ {
+ MapMode aMap (rInfo.maMap);
+ Point aPageOfs (rInfo.mpPrinter->GetPageOffset() );
+ // aMap.SetOrigin(Point() - aPageOfs);
+ aMap.SetScaleX(Fraction(1,2));
+ aMap.SetScaleY(Fraction(1,2));
+ mpPrinter->SetMapMode(aMap);
+
+ Rectangle aOutRect(aPageOfs, rInfo.mpPrinter->GetOutputSize());
+ if( aOutRect.GetWidth() > aOutRect.GetHeight() )
+ {
+ Size aPaperSize( rInfo.mpPrinter->PixelToLogic( rInfo.mpPrinter->GetPaperSizePixel(), MapMode( MAP_100TH_MM ) ) );
+ maPrintSize.Width = aPaperSize.Height();
+ maPrintSize.Height = aPaperSize.Width();
+ aOutRect = Rectangle( Point( aPageOfs.Y(), aPageOfs.X() ),
+ Size( aOutRect.GetHeight(), aOutRect.GetWidth() ) );
+ }
+
+ Link aOldLink;
+ Outliner* pOutliner = mrBase.GetDocument()->GetInternalOutliner();
+ pOutliner->Init(OUTLINERMODE_OUTLINEVIEW);
+ const USHORT nSavedOutlMode (pOutliner->GetMode());
+ const BOOL bSavedUpdateMode (pOutliner->GetUpdateMode());
+ const Size aSavedPaperSize (pOutliner->GetPaperSize());
+ const MapMode aSavedMapMode (pOutliner->GetRefMapMode());
+ pOutliner->SetPaperSize(aOutRect.GetSize());
+ pOutliner->SetUpdateMode(TRUE);
+
+ long nPageH = aOutRect.GetHeight();
+
+ for (USHORT
+ nIndex=0,
+ nCount=mrBase.GetDocument()->GetSdPageCount(PK_STANDARD);
+ nIndex < nCount;
+ )
+ {
+ pOutliner->Clear();
+ pOutliner->SetFirstPageNumber(nIndex+1);
+
+ Paragraph* pPara = NULL;
+ sal_Int32 nH (0);
+ while (nH < nPageH && nIndex<nCount)
+ {
+ SdPage* pPage = GetFilteredPage(nIndex, PK_STANDARD, rInfo);
+ ++nIndex;
+ if (pPage == NULL)
+ continue;
+
+ SdrTextObj* pTextObj = NULL;
+ sal_uInt32 nObj (0);
+
+ while (pTextObj==NULL && nObj < pPage->GetObjCount())
+ {
+ SdrObject* pObj = pPage->GetObj(nObj++);
+ if (pObj->GetObjInventor() == SdrInventor
+ && pObj->GetObjIdentifier() == OBJ_TITLETEXT)
+ {
+ pTextObj = dynamic_cast<SdrTextObj*>(pObj);
+ }
+ }
+
+ pPara = pOutliner->GetParagraph(pOutliner->GetParagraphCount() - 1);
+
+ if (pTextObj!=NULL
+ && !pTextObj->IsEmptyPresObj()
+ && pTextObj->GetOutlinerParaObject())
+ {
+ pOutliner->AddText(*(pTextObj->GetOutlinerParaObject()));
+ }
+ else
+ pOutliner->Insert(String());
+
+ pTextObj = NULL;
+ nObj = 0;
+
+ while (pTextObj==NULL && nObj<pPage->GetObjCount())
+ {
+ SdrObject* pObj = pPage->GetObj(nObj++);
+ if (pObj->GetObjInventor() == SdrInventor
+ && pObj->GetObjIdentifier() == OBJ_OUTLINETEXT)
+ {
+ pTextObj = dynamic_cast<SdrTextObj*>(pObj);
+ }
+ }
+
+ bool bSubTitle (false);
+ if (!pTextObj)
+ {
+ bSubTitle = true;
+ pTextObj = dynamic_cast<SdrTextObj*>(pPage->GetPresObj(PRESOBJ_TEXT)); // Untertitel vorhanden?
+ }
+
+ ULONG nParaCount1 = pOutliner->GetParagraphCount();
+
+ if (pTextObj!=NULL
+ && !pTextObj->IsEmptyPresObj()
+ && pTextObj->GetOutlinerParaObject())
+ {
+ pOutliner->AddText(*(pTextObj->GetOutlinerParaObject()));
+ }
+
+ if (bSubTitle )
+ {
+ const sal_Int32 nParaCount2 (pOutliner->GetParagraphCount());
+ for (sal_Int32 nPara=nParaCount1; nPara<nParaCount2; ++nPara)
+ {
+ Paragraph* pP = pOutliner->GetParagraph(nPara);
+ if (pP!=NULL && pOutliner->GetDepth((USHORT)nPara) > 0)
+ pOutliner->SetDepth(pP, 0);
+ }
+ }
+
+ nH = pOutliner->GetTextHeight();
+ }
+
+ // Remove the last paragraph when that does not fit completely on
+ // the current page.
+ if (nH > nPageH && pPara!=NULL)
+ {
+ ULONG nCnt = pOutliner->GetAbsPos(
+ pOutliner->GetParagraph( pOutliner->GetParagraphCount() - 1 ) );
+ ULONG nParaPos = pOutliner->GetAbsPos( pPara );
+ nCnt -= nParaPos;
+ pPara = pOutliner->GetParagraph( ++nParaPos );
+ if ( nCnt && pPara )
+ {
+ pOutliner->Remove(pPara, nCnt);
+ --nIndex;
+ }
+ }
+
+ maPrinterPages.push_back(
+ ::boost::shared_ptr<PrinterPage>(
+ new OutlinerPrinterPage(
+ pOutliner->CreateParaObject(),
+ aMap,
+ rInfo.msTimeDate,
+ aPageOfs,
+ rInfo.mnDrawMode,
+ rInfo.meOrientation,
+ rInfo.mpPrinter->GetPaperBin())));
+ }
+
+ pOutliner->SetRefMapMode(aSavedMapMode);
+ pOutliner->SetUpdateMode(bSavedUpdateMode);
+ pOutliner->SetPaperSize(aSavedPaperSize);
+ pOutliner->Init(nSavedOutlMode);
+ }
+
+
+
+
+ /** Prepare handout pages for slides that are to be printed.
+ */
+ void PrepareHandout (PrintInfo& rInfo)
+ {
+ SdDrawDocument* pDocument = mrBase.GetDocument();
+ OSL_ASSERT(pDocument != NULL);
+ SdPage& rHandoutPage (*pDocument->GetSdPage(0, PK_HANDOUT));
+
+ const bool bScalePage (mpOptions->IsPageSize());
+
+ USHORT nPaperBin;
+ if ( ! mpOptions->IsPaperBin())
+ nPaperBin = rHandoutPage.GetPaperBin();
+ else
+ nPaperBin = rInfo.mpPrinter->GetPaperBin();
+
+ // Change orientation?
+ SdPage& rMaster (dynamic_cast<SdPage&>(rHandoutPage.TRG_GetMasterPage()));
+ rInfo.meOrientation = rMaster.GetOrientation();
+
+ const Size aPaperSize (rInfo.mpPrinter->GetPaperSize());
+ if( (rInfo.meOrientation == ORIENTATION_LANDSCAPE &&
+ (aPaperSize.Width() < aPaperSize.Height()))
+ ||
+ (rInfo.meOrientation == ORIENTATION_PORTRAIT &&
+ (aPaperSize.Width() > aPaperSize.Height()))
+ )
+ {
+ maPrintSize = awt::Size(aPaperSize.Height(), aPaperSize.Width());
+ }
+ else
+ {
+ maPrintSize = awt::Size(aPaperSize.Width(), aPaperSize.Height());
+ }
+
+ MapMode aMap (rInfo.maMap);
+ const Point aPageOfs (rInfo.mpPrinter->GetPageOffset());
+ //DrawView* pPrintView;
+
+ // aMap.SetOrigin(Point() - aPageOfs);
+
+ if ( bScalePage )
+ {
+ const Size aPageSize (rHandoutPage.GetSize());
+ const Size aPrintSize (rInfo.mpPrinter->GetOutputSize());
+
+ const double fHorz = (double) aPrintSize.Width() / aPageSize.Width();
+ const double fVert = (double) aPrintSize.Height() / aPageSize.Height();
+
+ Fraction aFract;
+ if ( fHorz < fVert )
+ aFract = Fraction(aPrintSize.Width(), aPageSize.Width());
+ else
+ aFract = Fraction(aPrintSize.Height(), aPageSize.Height());
+
+ aMap.SetScaleX(aFract);
+ aMap.SetScaleY(aFract);
+ aMap.SetOrigin(Point());
+ }
+
+ ::boost::shared_ptr<ViewShell> pViewShell (mrBase.GetMainViewShell());
+ pViewShell->WriteFrameViewData();
+
+ // Count page shapes.
+ sal_uInt32 nShapeCount (0);
+ SdrObjListIter aShapeIter (rHandoutPage);
+ while (aShapeIter.IsMore())
+ {
+ SdrPageObj* pPageObj = dynamic_cast<SdrPageObj*>(aShapeIter.Next());
+ if (pPageObj)
+ ++nShapeCount;
+ }
+
+ const USHORT nPageCount = mrBase.GetDocument()->GetSdPageCount(PK_STANDARD);
+ const USHORT nHandoutPageCount = nShapeCount ? (nPageCount + nShapeCount - 1) / nShapeCount : 0;
+ pViewShell->SetPrintedHandoutPageCount( nHandoutPageCount );
+ mrBase.GetDocument()->setHandoutPageCount( nHandoutPageCount );
+
+ // Distribute pages to handout pages.
+ ::std::vector<USHORT> aPageIndices;
+ std::vector<SdPage*> aPagesVector;
+ for (USHORT
+ nIndex=0,
+ nCount= nPageCount,
+ nHandoutPageIndex=0;
+ nIndex <= nCount;
+ ++nIndex)
+ {
+ if (nIndex < nCount)
+ {
+ if (GetFilteredPage(nIndex, PK_STANDARD, rInfo) == NULL)
+ continue;
+ aPageIndices.push_back(nIndex);
+ }
+
+ // Create a printer page when we have found one page for each
+ // placeholder or when this is the last (and special) loop.
+ if (aPageIndices.size() == nShapeCount
+ || nIndex==nCount)
+ {
+ maPrinterPages.push_back(
+ ::boost::shared_ptr<PrinterPage>(
+ new HandoutPrinterPage(
+ nHandoutPageIndex++,
+ aPageIndices,
+ aMap,
+ rInfo.msTimeDate,
+ aPageOfs,
+ rInfo.mnDrawMode,
+ rInfo.meOrientation,
+ nPaperBin)));
+ aPageIndices.clear();
+ }
+ }
+ }
+
+
+
+
+ /** Prepare the notes pages or regular slides.
+ */
+ void PrepareStdOrNotes (
+ const PageKind ePageKind,
+ PrintInfo& rInfo)
+ {
+ OSL_ASSERT(rInfo.mpPrinter != NULL);
+
+ // Fill in page kind specific data.
+ SdDrawDocument* pDocument = mrBase.GetMainViewShell()->GetDoc();
+ if (pDocument->GetSdPageCount(ePageKind) == 0)
+ return;
+ SdPage* pRefPage = pDocument->GetSdPage(0, ePageKind);
+ rInfo.maPageSize = pRefPage->GetSize();
+
+ if ( ! SetupPaperOrientation(ePageKind, rInfo))
+ return;
+
+ MapMode aMap (rInfo.maMap);
+ // aMap.SetOrigin(Point() - rInfo.mpPrinter->GetPageOffset());
+ rInfo.maMap = aMap;
+
+ if (mpOptions->IsBooklet())
+ PrepareBooklet(ePageKind, rInfo);
+ else
+ PrepareRegularPages(ePageKind, rInfo);
+ }
+
+
+
+
+ /** Prepare slides in a non-booklet way: one slide per one to many
+ printer pages.
+ */
+ void PrepareRegularPages (
+ const PageKind ePageKind,
+ PrintInfo& rInfo)
+ {
+ ::boost::shared_ptr<ViewShell> pViewShell (mrBase.GetMainViewShell());
+ pViewShell->WriteFrameViewData();
+ Point aPtZero;
+
+ for (USHORT
+ nIndex=0,
+ nCount=mrBase.GetDocument()->GetSdPageCount(PK_STANDARD);
+ nIndex < nCount;
+ ++nIndex)
+ {
+ SdPage* pPage = GetFilteredPage(nIndex, ePageKind, rInfo);
+ if (pPage == NULL)
+ continue;
+
+ MapMode aMap (rInfo.maMap);
+ // Kann sich die Seitengroesse geaendert haben?
+ const Size aPageSize = pPage->GetSize();
+
+ if (mpOptions->IsPageSize())
+ {
+ const double fHorz ((double) rInfo.maPrintSize.Width() / aPageSize.Width());
+ const double fVert ((double) rInfo.maPrintSize.Height() / aPageSize.Height());
+
+ Fraction aFract;
+ if (fHorz < fVert)
+ aFract = Fraction(rInfo.maPrintSize.Width(), aPageSize.Width());
+ else
+ aFract = Fraction(rInfo.maPrintSize.Height(), aPageSize.Height());
+
+ aMap.SetScaleX(aFract);
+ aMap.SetScaleY(aFract);
+ aMap.SetOrigin(Point());
+ }
+
+ if (mpOptions->IsPrintPageName())
+ {
+ rInfo.msPageString = pPage->GetName();
+ rInfo.msPageString += ::rtl::OUString(sal_Unicode(' '));
+ }
+ else
+ rInfo.msPageString = ::rtl::OUString();
+ rInfo.msPageString += rInfo.msTimeDate;
+
+ long aPageWidth = aPageSize.Width() - pPage->GetLftBorder() - pPage->GetRgtBorder();
+ long aPageHeight = aPageSize.Height() - pPage->GetUppBorder() - pPage->GetLwrBorder();
+ // Bugfix zu 44530:
+ // Falls implizit umgestellt wurde (Landscape/Portrait)
+ // wird dies beim Kacheln, bzw. aufteilen (Poster) beruecksichtigt
+ BOOL bSwitchPageSize = FALSE;
+ if( ( rInfo.maPrintSize.Width() > rInfo.maPrintSize.Height()
+ && aPageWidth < aPageHeight )
+ || ( rInfo.maPrintSize.Width() < rInfo.maPrintSize.Height()
+ && aPageWidth > aPageHeight ) )
+ {
+ bSwitchPageSize = TRUE;
+ const sal_Int32 nTmp (rInfo.maPrintSize.Width());
+ rInfo.maPrintSize.Width() = rInfo.maPrintSize.Height();
+ rInfo.maPrintSize.Height() = nTmp;
+ }
+
+ if (mpOptions->IsTilePage()
+ && aPageWidth < rInfo.maPrintSize.Width()
+ && aPageHeight < rInfo.maPrintSize.Height())
+ {
+ // Put multiple slides on one printer page.
+ PrepareTiledPage(nIndex, *pPage, ePageKind, rInfo);
+ }
+ else
+ {
+ rInfo.maMap = aMap;
+ PrepareScaledPage(nIndex, *pPage, ePageKind, rInfo);
+ }
+ }
+ }
+
+
+
+
+ /** Put two slides on one printer page.
+ */
+ void PrepareBooklet (
+ const PageKind ePageKind,
+ const PrintInfo& rInfo)
+ {
+ MapMode aStdMap (rInfo.maMap);
+ Point aOffset;
+ Size aPrintSize_2 (rInfo.maPrintSize);
+ Size aPageSize_2 (rInfo.maPageSize);
+
+ if (rInfo.meOrientation == ORIENTATION_LANDSCAPE)
+ aPrintSize_2.Width() >>= 1;
+ else
+ aPrintSize_2.Height() >>= 1;
+
+ const double fPageWH = (double) aPageSize_2.Width() / aPageSize_2.Height();
+ const double fPrintWH = (double) aPrintSize_2.Width() / aPrintSize_2.Height();
+
+ if( fPageWH < fPrintWH )
+ {
+ aPageSize_2.Width() = (long) ( aPrintSize_2.Height() * fPageWH );
+ aPageSize_2.Height()= aPrintSize_2.Height();
+ }
+ else
+ {
+ aPageSize_2.Width() = aPrintSize_2.Width();
+ aPageSize_2.Height() = (long) ( aPrintSize_2.Width() / fPageWH );
+ }
+
+ MapMode aMap (rInfo.maMap);
+ aMap.SetScaleX( Fraction( aPageSize_2.Width(), rInfo.maPageSize.Width() ) );
+ aMap.SetScaleY( Fraction( aPageSize_2.Height(), rInfo.maPageSize.Height() ) );
+
+ // calculate adjusted print size
+ const Size aAdjustedPrintSize (OutputDevice::LogicToLogic(
+ rInfo.maPrintSize,
+ aStdMap,
+ aMap));
+
+ if (rInfo.meOrientation == ORIENTATION_LANDSCAPE)
+ {
+ aOffset.X() = ( ( aAdjustedPrintSize.Width() >> 1 ) - rInfo.maPageSize.Width() ) >> 1;
+ aOffset.Y() = ( aAdjustedPrintSize.Height() - rInfo.maPageSize.Height() ) >> 1;
+ }
+ else
+ {
+ aOffset.X() = ( aAdjustedPrintSize.Width() - rInfo.maPageSize.Width() ) >> 1;
+ aOffset.Y() = ( ( aAdjustedPrintSize.Height() >> 1 ) - rInfo.maPageSize.Height() ) >> 1;
+ }
+
+ // create vector of pages to print
+ ::std::vector< USHORT > aPageVector;
+ for (USHORT
+ nIndex=0,
+ nCount=mrBase.GetDocument()->GetSdPageCount(ePageKind);
+ nIndex < nCount;
+ ++nIndex)
+ {
+ SdPage* pPage = GetFilteredPage(nIndex, ePageKind, rInfo);
+ if (pPage != NULL)
+ aPageVector.push_back(nIndex);
+ }
+
+ // create pairs of pages to print on each page
+ typedef ::std::vector< ::std::pair< USHORT, USHORT > > PairVector;
+ PairVector aPairVector;
+ if ( ! aPageVector.empty())
+ {
+ sal_uInt32 nFirstIndex = 0, nLastIndex = aPageVector.size() - 1;
+
+ if( aPageVector.size() & 1 )
+ aPairVector.push_back( ::std::make_pair( (USHORT) 65535, aPageVector[ nFirstIndex++ ] ) );
+ else
+ aPairVector.push_back( ::std::make_pair( aPageVector[ nLastIndex-- ], aPageVector[ nFirstIndex++ ] ) );
+
+ while( nFirstIndex < nLastIndex )
+ {
+ if( nFirstIndex & 1 )
+ aPairVector.push_back( ::std::make_pair( aPageVector[ nFirstIndex++ ], aPageVector[ nLastIndex-- ] ) );
+ else
+ aPairVector.push_back( ::std::make_pair( aPageVector[ nLastIndex-- ], aPageVector[ nFirstIndex++ ] ) );
+ }
+ }
+
+ for (sal_uInt32
+ nIndex=0,
+ nCount=aPairVector.size();
+ nIndex < nCount;
+ ++nIndex)
+ {
+ const bool bIsIndexOdd (nIndex & 1);
+ if ((!bIsIndexOdd && mpOptions->IsPrintFrontPage())
+ || (bIsIndexOdd && mpOptions->IsPrintBackPage()))
+ {
+ const ::std::pair<USHORT, USHORT> aPair (aPairVector[nIndex]);
+ Point aSecondOffset (aOffset);
+ if (rInfo.meOrientation == ORIENTATION_LANDSCAPE)
+ aSecondOffset.X() += aAdjustedPrintSize.Width() / 2;
+ else
+ aSecondOffset.Y() += aAdjustedPrintSize.Height() / 2;
+ maPrinterPages.push_back(
+ ::boost::shared_ptr<PrinterPage>(
+ new BookletPrinterPage(
+ aPair.first,
+ aPair.second,
+ aOffset,
+ aSecondOffset,
+ ePageKind,
+ aMap,
+ rInfo.mbPrintMarkedOnly,
+ rInfo.mnDrawMode,
+ rInfo.meOrientation,
+ rInfo.mpPrinter->GetPaperBin())));
+
+ }
+ }
+ }
+
+
+
+
+ /** Print one slide multiple times on one printer page so that the whole
+ printer page is covered.
+ */
+ void PrepareTiledPage (
+ const sal_Int32 nPageIndex,
+ const SdPage& rPage,
+ const PageKind ePageKind,
+ const PrintInfo& rInfo)
+ {
+ USHORT nPaperBin;
+ if ( ! mpOptions->IsPaperBin())
+ nPaperBin = rPage.GetPaperBin();
+ else
+ nPaperBin = rInfo.mpPrinter->GetPaperBin();
+
+ maPrinterPages.push_back(
+ ::boost::shared_ptr<PrinterPage>(
+ new TiledPrinterPage(
+ sal::static_int_cast<USHORT>(nPageIndex),
+ ePageKind,
+ 500,
+ rInfo.mbPrintMarkedOnly,
+ rInfo.msPageString,
+ rInfo.mpPrinter->GetPageOffset(),
+ rInfo.mnDrawMode,
+ rInfo.meOrientation,
+ nPaperBin)));
+ }
+
+
+
+ /** Print one standard slide or notes page on one to many printer
+ pages. More than on printer page is used when the slide is larger
+ than the printable area.
+ */
+ void PrepareScaledPage (
+ const sal_Int32 nPageIndex,
+ const SdPage& rPage,
+ const PageKind ePageKind,
+ const PrintInfo& rInfo)
+ {
+ const Point aPageOffset (rInfo.mpPrinter->GetPageOffset());
+
+ USHORT nPaperBin;
+ if ( ! mpOptions->IsPaperBin())
+ nPaperBin = rPage.GetPaperBin();
+ else
+ nPaperBin = rInfo.mpPrinter->GetPaperBin();
+
+ // For pages larger then the printable area there
+ // are three options:
+ // 1. Scale down to the page to the printable area.
+ // 2. Print only the upper left part of the page
+ // (without the unprintable borders).
+ // 3. Split the page into parts of the size of the
+ // printable area.
+ const bool bScalePage (mpOptions->IsPageSize());
+ const bool bCutPage (mpOptions->IsCutPage());
+ MapMode aMap (rInfo.maMap);
+ if (bScalePage || bCutPage)
+ {
+ // Handle 1 and 2.
+
+ // if CutPage is set then do not move it, otherwise move the
+ // scaled page to printable area
+ #if 0
+ if (bCutPage)
+ aMap.SetOrigin(Point(-aPageOffset.X(), -aPageOffset.Y()));
+ else
+ aMap.SetOrigin(Point(0,0));
+ #endif
+ maPrinterPages.push_back(
+ ::boost::shared_ptr<PrinterPage>(
+ new RegularPrinterPage(
+ sal::static_int_cast<USHORT>(nPageIndex),
+ ePageKind,
+ aMap,
+ rInfo.mbPrintMarkedOnly,
+ rInfo.msPageString,
+ aPageOffset,
+ rInfo.mnDrawMode,
+ rInfo.meOrientation,
+ nPaperBin)));
+ }
+ else
+ {
+ // Handle 3. Print parts of the page in the size of the
+ // printable area until the whole page is covered.
+
+ // keep the page content at its position if it fits, otherwise
+ // move it to the printable area
+ const long nPageWidth (
+ rInfo.maPageSize.Width() - rPage.GetLftBorder() - rPage.GetRgtBorder());
+ const long nPageHeight (
+ rInfo.maPageSize.Height() - rPage.GetUppBorder() - rPage.GetLwrBorder());
+ #if 0
+ Point aOrigin (
+ nPageWidth < rInfo.maPrintSize.Width() ? -aPageOffset.X() : 0,
+ nPageHeight < rInfo.maPrintSize.Height() ? -aPageOffset.Y() : 0);
+ #else
+ Point aOrigin ( 0, 0 );
+ #endif
+ for (Point aPageOrigin = aOrigin;
+ -aPageOrigin.Y()<nPageHeight;
+ aPageOrigin.Y() -= rInfo.maPrintSize.Height())
+ {
+ for (aPageOrigin.X()=aOrigin.X();
+ -aPageOrigin.X()<nPageWidth;
+ aPageOrigin.X() -= rInfo.maPrintSize.Width())
+ {
+ aMap.SetOrigin(aPageOrigin);
+ maPrinterPages.push_back(
+ ::boost::shared_ptr<PrinterPage>(
+ new RegularPrinterPage(
+ sal::static_int_cast<USHORT>(nPageIndex),
+ ePageKind,
+ aMap,
+ rInfo.mbPrintMarkedOnly,
+ rInfo.msPageString,
+ aPageOffset,
+ rInfo.mnDrawMode,
+ rInfo.meOrientation,
+ nPaperBin)));
+ }
+ }
+ }
+ }
+};
+
+
+
+
+//===== DocumentRenderer ======================================================
+
+DocumentRenderer::DocumentRenderer (ViewShellBase& rBase)
+ : DocumentRendererInterfaceBase(m_aMutex),
+ mpImpl(new Implementation(rBase))
+{
+}
+
+
+
+
+DocumentRenderer::~DocumentRenderer (void)
+{
+}
+
+
+
+
+//----- XRenderable -----------------------------------------------------------
+
+sal_Int32 SAL_CALL DocumentRenderer::getRendererCount (
+ const css::uno::Any& aSelection,
+ const css::uno::Sequence<css::beans::PropertyValue >& rOptions)
+ throw (css::lang::IllegalArgumentException, css::uno::RuntimeException)
+{
+ (void)aSelection;
+ mpImpl->ProcessProperties(rOptions);
+ return mpImpl->GetPrintPageCount();
+}
+
+
+
+
+Sequence<beans::PropertyValue> SAL_CALL DocumentRenderer::getRenderer (
+ sal_Int32 nRenderer,
+ const css::uno::Any& rSelection,
+ const css::uno::Sequence<css::beans::PropertyValue>& rOptions)
+ throw (css::lang::IllegalArgumentException, css::uno::RuntimeException)
+{
+ (void)nRenderer;
+ (void)rSelection;
+ mpImpl->ProcessProperties(rOptions);
+ return mpImpl->GetProperties(rOptions);
+}
+
+
+
+
+void SAL_CALL DocumentRenderer::render (
+ sal_Int32 nRenderer,
+ const css::uno::Any& rSelection,
+ const css::uno::Sequence<css::beans::PropertyValue>& rOptions)
+ throw (css::lang::IllegalArgumentException, css::uno::RuntimeException)
+{
+ (void)rSelection;
+ mpImpl->ProcessProperties(rOptions);
+ mpImpl->PrintPage(nRenderer);
+}
+
+
+
+} // end of namespace sd