1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <tools/fract.hxx>
21 #include <osl/diagnose.h>
22 #include <viewsh.hxx>
23 #include <pagefrm.hxx>
24 #include <viewimp.hxx>
25 #include <printdata.hxx>
26 #include <ptqueue.hxx>
27 #include <fntcache.hxx>
28 
29 #include "vprint.hxx"
30 
31 using namespace ::com::sun::star;
32 
PagePreviewLayout()33 SwPagePreviewLayout* SwViewShell::PagePreviewLayout()
34 {
35     return Imp()->PagePreviewLayout();
36 }
37 
ShowPreviewSelection(sal_uInt16 nSelPage)38 void SwViewShell::ShowPreviewSelection( sal_uInt16 nSelPage )
39 {
40     Imp()->InvalidateAccessiblePreviewSelection( nSelPage );
41 }
42 
43 // adjust view options for page preview
AdjustOptionsForPagePreview(SwPrintData const & rPrintOptions)44 void SwViewShell::AdjustOptionsForPagePreview(SwPrintData const& rPrintOptions)
45 {
46     if ( !IsPreview() )
47     {
48         OSL_FAIL( "view shell doesn't belongs to a page preview - no adjustment of its view options");
49         return;
50     }
51 
52     PrepareForPrint( rPrintOptions );
53 }
54 
55 /// print brochure
56 // consider empty pages on calculation of the scaling
57 // for a page to be printed.
PrintProspect(OutputDevice * pOutDev,const SwPrintData & rPrintData,sal_Int32 nRenderer)58 void SwViewShell::PrintProspect(
59     OutputDevice *pOutDev,
60     const SwPrintData &rPrintData,
61     sal_Int32 nRenderer // the index in the vector of prospect pages to be printed
62     )
63 {
64     const sal_Int32 nMaxRenderer = rPrintData.GetRenderData().GetPagePairsForProspectPrinting().size() - 1;
65     OSL_ENSURE( 0 <= nRenderer && nRenderer <= nMaxRenderer, "nRenderer out of bounds");
66     Printer *pPrinter = dynamic_cast< Printer * >(pOutDev);
67     if (!pPrinter || nMaxRenderer < 0 || nRenderer < 0 || nRenderer > nMaxRenderer)
68         return;
69 
70     // save settings of OutputDevice (should be done always since the
71     // output device is now provided by a call from outside the Writer)
72     pPrinter->Push();
73 
74     std::pair< sal_Int32, sal_Int32 > rPagesToPrint =
75             rPrintData.GetRenderData().GetPagePairsForProspectPrinting()[ nRenderer ];
76     OSL_ENSURE( rPagesToPrint.first  == -1 || rPrintData.GetRenderData().GetValidPagesSet().count( rPagesToPrint.first ) == 1, "first Page not valid" );
77     OSL_ENSURE( rPagesToPrint.second == -1 || rPrintData.GetRenderData().GetValidPagesSet().count( rPagesToPrint.second ) == 1, "second Page not valid" );
78 
79     // create a new shell for the printer
80     SwViewShell aShell( *this, nullptr, pPrinter );
81 
82     CurrShell aCurr( &aShell );
83 
84     aShell.PrepareForPrint( rPrintData );
85 
86     //!! applying view options and formatting the document should now only be done in getRendererCount!
87 
88     MapMode aMapMode( MapUnit::MapTwip );
89     Size aPrtSize( pPrinter->PixelToLogic( pPrinter->GetPaperSizePixel(), aMapMode ) );
90 
91     SwTwips nMaxRowSz, nMaxColSz;
92 
93     const SwPageFrame *pStPage    = nullptr;
94     const SwPageFrame *pNxtPage   = nullptr;
95     if (rPagesToPrint.first > 0)
96     {
97         pStPage = sw_getPage(*aShell.GetLayout(), rPagesToPrint.first);
98     }
99     if (rPagesToPrint.second > 0)
100     {
101         pNxtPage = sw_getPage(*aShell.GetLayout(), rPagesToPrint.second);
102     }
103 
104     // i#14016 consider empty pages on calculation
105     // of page size, used for calculation of scaling.
106     Size aSttPageSize;
107     if ( pStPage )
108     {
109         if ( pStPage->IsEmptyPage() )
110         {
111             if ( pStPage->GetPhyPageNum() % 2 == 0 )
112                 aSttPageSize = pStPage->GetPrev()->getFrameArea().SSize();
113             else
114                 aSttPageSize = pStPage->GetNext()->getFrameArea().SSize();
115         }
116         else
117         {
118             aSttPageSize = pStPage->getFrameArea().SSize();
119         }
120     }
121     Size aNxtPageSize;
122     if ( pNxtPage )
123     {
124         if ( pNxtPage->IsEmptyPage() )
125         {
126             if ( pNxtPage->GetPhyPageNum() % 2 == 0 )
127                 aNxtPageSize = pNxtPage->GetPrev()->getFrameArea().SSize();
128             else
129                 aNxtPageSize = pNxtPage->GetNext()->getFrameArea().SSize();
130         }
131         else
132         {
133             aNxtPageSize = pNxtPage->getFrameArea().SSize();
134         }
135     }
136 
137     if( !pStPage )
138     {
139         nMaxColSz = 2 * aNxtPageSize.Width();
140         nMaxRowSz = aNxtPageSize.Height();
141     }
142     else if( !pNxtPage )
143     {
144         nMaxColSz = 2 * aSttPageSize.Width();
145         nMaxRowSz = aSttPageSize.Height();
146     }
147     else
148     {
149         nMaxColSz = aNxtPageSize.Width() + aSttPageSize.Width();
150         nMaxRowSz = std::max( aNxtPageSize.Height(), aSttPageSize.Height() );
151     }
152 
153     // set the MapMode
154     aMapMode.SetOrigin( Point() );
155     {
156         Fraction aScX( aPrtSize.Width(), nMaxColSz );
157         Fraction aScY( aPrtSize.Height(), nMaxRowSz );
158         if( aScX < aScY )
159             aScY = aScX;
160 
161         {
162             // Round percentages for Drawings so that these can paint their objects properly
163             aScY *= Fraction( 1000, 1 );
164             tools::Long nTmp = static_cast<tools::Long>(aScY);
165             if( 1 < nTmp )
166                 --nTmp;
167             else
168                 nTmp = 1;
169             aScY = Fraction( nTmp, 1000 );
170         }
171 
172         aMapMode.SetScaleY( aScY );
173         aMapMode.SetScaleX( aScY );
174     }
175 
176     Size aTmpPrtSize( pPrinter->PixelToLogic( pPrinter->GetPaperSizePixel(), aMapMode ) );
177 
178     // calculate start point for equal border on all sides
179     Point aSttPt( (aTmpPrtSize.Width() - nMaxColSz) / 2,
180                   (aTmpPrtSize.Height() - nMaxRowSz) / 2 );
181     for( int nC = 0; nC < 2; ++nC )
182     {
183         if( pStPage )
184         {
185             aShell.Imp()->SetFirstVisPageInvalid();
186             aShell.maVisArea = pStPage->getFrameArea();
187 
188             Point aPos( aSttPt );
189             aPos -= aShell.maVisArea.Pos();
190             aMapMode.SetOrigin( aPos );
191             pPrinter->SetMapMode( aMapMode );
192             pStPage->GetUpper()->PaintSwFrame( *pOutDev, pStPage->getFrameArea() );
193         }
194 
195         pStPage = pNxtPage;
196         aSttPt.AdjustX(aTmpPrtSize.Width() / 2 );
197     }
198 
199     SwPaintQueue::Repaint();
200 
201     //!! applying/modifying view options and formatting the document should now only be done in getRendererCount!
202 
203     pFntCache->Flush();
204 
205     // restore settings of OutputDevice (should be done always now since the
206     // output device is now provided by a call from outside the Writer)
207     pPrinter->Pop();
208 }
209 
210 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
211