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 <scitems.hxx>
21 #include <editeng/eeitem.hxx>
22
23 #include <printfun.hxx>
24
25 #include <editeng/adjustitem.hxx>
26 #include <editeng/borderline.hxx>
27 #include <editeng/boxitem.hxx>
28 #include <editeng/brushitem.hxx>
29 #include <svtools/colorcfg.hxx>
30 #include <editeng/editstat.hxx>
31 #include <svx/fmview.hxx>
32 #include <editeng/frmdiritem.hxx>
33 #include <editeng/lrspitem.hxx>
34 #include <editeng/paperinf.hxx>
35 #include <editeng/pbinitem.hxx>
36 #include <editeng/shaditem.hxx>
37 #include <editeng/sizeitem.hxx>
38 #include <editeng/fhgtitem.hxx>
39 #include <editeng/ulspitem.hxx>
40 #include <sfx2/printer.hxx>
41 #include <tools/multisel.hxx>
42 #include <sfx2/docfile.hxx>
43 #include <tools/urlobj.hxx>
44 #include <osl/diagnose.h>
45
46 #include <editutil.hxx>
47 #include <docsh.hxx>
48 #include <output.hxx>
49 #include <viewdata.hxx>
50 #include <viewopti.hxx>
51 #include <stlpool.hxx>
52 #include <pagepar.hxx>
53 #include <attrib.hxx>
54 #include <patattr.hxx>
55 #include <docpool.hxx>
56 #include <dociter.hxx>
57 #include <globstr.hrc>
58 #include <scresid.hxx>
59 #include <pagedata.hxx>
60 #include <printopt.hxx>
61 #include <prevloc.hxx>
62 #include <scmod.hxx>
63 #include <drwlayer.hxx>
64 #include <fillinfo.hxx>
65 #include <postit.hxx>
66
67 #include <memory>
68 #include <com/sun/star/document/XDocumentProperties.hpp>
69
70 #define ZOOM_MIN 10
71
72 namespace{
73
lcl_GetBool(const SfxItemSet * pSet,sal_uInt16 nWhich)74 bool lcl_GetBool(const SfxItemSet* pSet, sal_uInt16 nWhich)
75 {
76 return static_cast<const SfxBoolItem&>(pSet->Get(nWhich)).GetValue();
77 }
78
lcl_GetUShort(const SfxItemSet * pSet,sal_uInt16 nWhich)79 sal_uInt16 lcl_GetUShort(const SfxItemSet* pSet, sal_uInt16 nWhich)
80 {
81 return static_cast<const SfxUInt16Item&>(pSet->Get(nWhich)).GetValue();
82 }
83
lcl_GetShow(const SfxItemSet * pSet,sal_uInt16 nWhich)84 bool lcl_GetShow(const SfxItemSet* pSet, sal_uInt16 nWhich)
85 {
86 return ScVObjMode::VOBJ_MODE_SHOW == static_cast<const ScViewObjectModeItem&>(pSet->Get(nWhich)).GetValue();
87 }
88
89
90 } // namespace
91
ScPageRowEntry(const ScPageRowEntry & r)92 ScPageRowEntry::ScPageRowEntry(const ScPageRowEntry& r)
93 {
94 nStartRow = r.nStartRow;
95 nEndRow = r.nEndRow;
96 nPagesX = r.nPagesX;
97 aHidden = r.aHidden;
98 aHidden.resize(nPagesX, false);
99 }
100
operator =(const ScPageRowEntry & r)101 ScPageRowEntry& ScPageRowEntry::operator=(const ScPageRowEntry& r)
102 {
103 nStartRow = r.nStartRow;
104 nEndRow = r.nEndRow;
105 nPagesX = r.nPagesX;
106 aHidden = r.aHidden;
107 aHidden.resize(nPagesX, false);
108 return *this;
109 }
110
SetPagesX(size_t nNew)111 void ScPageRowEntry::SetPagesX(size_t nNew)
112 {
113 nPagesX = nNew;
114 aHidden.resize(nPagesX, false);
115 }
116
SetHidden(size_t nX)117 void ScPageRowEntry::SetHidden(size_t nX)
118 {
119 if ( nX < nPagesX )
120 {
121 if ( nX+1 == nPagesX ) // last page?
122 --nPagesX;
123 else
124 {
125 aHidden.resize(nPagesX, false);
126 aHidden[nX] = true;
127 }
128 }
129 }
130
IsHidden(size_t nX) const131 bool ScPageRowEntry::IsHidden(size_t nX) const
132 {
133 return nX >= nPagesX || aHidden[nX]; //! inline?
134 }
135
CountVisible() const136 size_t ScPageRowEntry::CountVisible() const
137 {
138 if (!aHidden.empty())
139 {
140 size_t nVis = 0;
141 for (size_t i=0; i<nPagesX; i++)
142 if (!aHidden[i])
143 ++nVis;
144 return nVis;
145 }
146 else
147 return nPagesX;
148 }
149
lcl_LineTotal(const::editeng::SvxBorderLine * pLine)150 static tools::Long lcl_LineTotal(const ::editeng::SvxBorderLine* pLine)
151 {
152 return pLine ? ( pLine->GetScaledWidth() ) : 0;
153 }
154
Construct(const ScPrintOptions * pOptions)155 void ScPrintFunc::Construct( const ScPrintOptions* pOptions )
156 {
157 pDocShell->UpdatePendingRowHeights( nPrintTab );
158
159 SfxPrinter* pDocPrinter = rDoc.GetPrinter(); // use the printer, even for preview
160 if (pDocPrinter)
161 aOldPrinterMode = pDocPrinter->GetMapMode();
162
163 // unified MapMode for all calls (e.g. Repaint!!!)
164 // else, EditEngine outputs different text heights
165 pDev->SetMapMode(MapMode(MapUnit::MapPixel));
166
167 pBorderItem = nullptr;
168 pBackgroundItem = nullptr;
169 pShadowItem = nullptr;
170
171 pEditEngine = nullptr;
172 pEditDefaults = nullptr;
173
174 ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool();
175 SfxStyleSheetBase* pStyleSheet = pStylePool->Find(
176 rDoc.GetPageStyle( nPrintTab ),
177 SfxStyleFamily::Page );
178 if (pStyleSheet)
179 pParamSet = &pStyleSheet->GetItemSet();
180 else
181 {
182 OSL_FAIL("Template not found" );
183 pParamSet = nullptr;
184 }
185
186 if (!bFromPrintState)
187 nZoom = 100;
188 nManualZoom = 100;
189 bClearWin = false;
190 bUseStyleColor = false;
191 bIsRender = false;
192
193 InitParam(pOptions);
194
195 pPageData = nullptr; // is only needed for initialisation
196 }
197
ScPrintFunc(ScDocShell * pShell,SfxPrinter * pNewPrinter,SCTAB nTab,tools::Long nPage,tools::Long nDocP,const ScRange * pArea,const ScPrintOptions * pOptions,ScPageBreakData * pData)198 ScPrintFunc::ScPrintFunc( ScDocShell* pShell, SfxPrinter* pNewPrinter, SCTAB nTab,
199 tools::Long nPage, tools::Long nDocP, const ScRange* pArea,
200 const ScPrintOptions* pOptions,
201 ScPageBreakData* pData )
202 : pDocShell ( pShell ),
203 rDoc(pDocShell->GetDocument()),
204 pPrinter ( pNewPrinter ),
205 pDrawView ( nullptr ),
206 nPrintTab ( nTab ),
207 nPageStart ( nPage ),
208 nDocPages ( nDocP ),
209 pUserArea ( pArea ),
210 bFromPrintState ( false ),
211 bSourceRangeValid ( false ),
212 bPrintCurrentTable ( false ),
213 bMultiArea ( false ),
214 mbHasPrintRange(true),
215 nTabPages ( 0 ),
216 nTotalPages ( 0 ),
217 bPrintAreaValid ( false ),
218 pPageData ( pData )
219 {
220 pDev = pPrinter.get();
221 aSrcOffset = pPrinter->PixelToLogic(pPrinter->GetPageOffsetPixel(), MapMode(MapUnit::Map100thMM));
222 m_aRanges.m_xPageEndX = std::make_shared<std::vector<SCCOL>>();
223 m_aRanges.m_xPageEndY = std::make_shared<std::vector<SCROW>>();
224 m_aRanges.m_xPageRows = std::make_shared<std::map<size_t, ScPageRowEntry>>();
225 Construct( pOptions );
226 }
227
ScPrintFunc(ScDocShell * pShell,SfxPrinter * pNewPrinter,const ScPrintState & rState,const ScPrintOptions * pOptions)228 ScPrintFunc::ScPrintFunc(ScDocShell* pShell, SfxPrinter* pNewPrinter,
229 const ScPrintState& rState, const ScPrintOptions* pOptions)
230 : pDocShell ( pShell ),
231 rDoc(pDocShell->GetDocument()),
232 pPrinter ( pNewPrinter ),
233 pDrawView ( nullptr ),
234 pUserArea ( nullptr ),
235 bSourceRangeValid ( false ),
236 bPrintCurrentTable ( false ),
237 bMultiArea ( false ),
238 mbHasPrintRange(true),
239 pPageData ( nullptr )
240 {
241 pDev = pPrinter.get();
242
243 nPrintTab = rState.nPrintTab;
244 nStartCol = rState.nStartCol;
245 nStartRow = rState.nStartRow;
246 nEndCol = rState.nEndCol;
247 nEndRow = rState.nEndRow;
248 bPrintAreaValid = rState.bPrintAreaValid;
249 nZoom = rState.nZoom;
250 m_aRanges.m_nPagesX = rState.nPagesX;
251 m_aRanges.m_nPagesY = rState.nPagesY;
252 nTabPages = rState.nTabPages;
253 nTotalPages = rState.nTotalPages;
254 nPageStart = rState.nPageStart;
255 nDocPages = rState.nDocPages;
256 bFromPrintState = true;
257
258 if (rState.bSavedStateRanges)
259 {
260 m_aRanges.m_nTotalY = rState.nTotalY;
261 m_aRanges.m_xPageEndX = rState.xPageEndX;
262 m_aRanges.m_xPageEndY = rState.xPageEndY;
263 m_aRanges.m_xPageRows = rState.xPageRows;
264 m_aRanges.m_aInput = rState.aPrintPageRangesInput;
265 }
266 else
267 {
268 m_aRanges.m_xPageEndX = std::make_shared<std::vector<SCCOL>>();
269 m_aRanges.m_xPageEndY = std::make_shared<std::vector<SCROW>>();
270 m_aRanges.m_xPageRows = std::make_shared<std::map<size_t, ScPageRowEntry>>();
271 }
272
273 aSrcOffset = pPrinter->PixelToLogic(pPrinter->GetPageOffsetPixel(), MapMode(MapUnit::Map100thMM));
274 Construct( pOptions );
275 }
276
ScPrintFunc(OutputDevice * pOutDev,ScDocShell * pShell,SCTAB nTab,tools::Long nPage,tools::Long nDocP,const ScRange * pArea,const ScPrintOptions * pOptions)277 ScPrintFunc::ScPrintFunc( OutputDevice* pOutDev, ScDocShell* pShell, SCTAB nTab,
278 tools::Long nPage, tools::Long nDocP, const ScRange* pArea,
279 const ScPrintOptions* pOptions )
280 : pDocShell ( pShell ),
281 rDoc(pDocShell->GetDocument()),
282 pPrinter ( nullptr ),
283 pDrawView ( nullptr ),
284 nPrintTab ( nTab ),
285 nPageStart ( nPage ),
286 nDocPages ( nDocP ),
287 pUserArea ( pArea ),
288 bFromPrintState ( false ),
289 bSourceRangeValid ( false ),
290 bPrintCurrentTable ( false ),
291 bMultiArea ( false ),
292 mbHasPrintRange(true),
293 nTabPages ( 0 ),
294 nTotalPages ( 0 ),
295 bPrintAreaValid ( false ),
296 pPageData ( nullptr )
297 {
298 pDev = pOutDev;
299 m_aRanges.m_xPageEndX = std::make_shared<std::vector<SCCOL>>();
300 m_aRanges.m_xPageEndY = std::make_shared<std::vector<SCROW>>();
301 m_aRanges.m_xPageRows = std::make_shared<std::map<size_t, ScPageRowEntry>>();
302 Construct( pOptions );
303 }
304
ScPrintFunc(OutputDevice * pOutDev,ScDocShell * pShell,const ScPrintState & rState,const ScPrintOptions * pOptions)305 ScPrintFunc::ScPrintFunc( OutputDevice* pOutDev, ScDocShell* pShell,
306 const ScPrintState& rState, const ScPrintOptions* pOptions )
307 : pDocShell ( pShell ),
308 rDoc(pDocShell->GetDocument()),
309 pPrinter ( nullptr ),
310 pDrawView ( nullptr ),
311 pUserArea ( nullptr ),
312 bSourceRangeValid ( false ),
313 bPrintCurrentTable ( false ),
314 bMultiArea ( false ),
315 mbHasPrintRange(true),
316 pPageData ( nullptr )
317 {
318 pDev = pOutDev;
319
320 nPrintTab = rState.nPrintTab;
321 nStartCol = rState.nStartCol;
322 nStartRow = rState.nStartRow;
323 nEndCol = rState.nEndCol;
324 nEndRow = rState.nEndRow;
325 bPrintAreaValid = rState.bPrintAreaValid;
326 nZoom = rState.nZoom;
327 m_aRanges.m_nPagesX = rState.nPagesX;
328 m_aRanges.m_nPagesY = rState.nPagesY;
329 nTabPages = rState.nTabPages;
330 nTotalPages = rState.nTotalPages;
331 nPageStart = rState.nPageStart;
332 nDocPages = rState.nDocPages;
333 bFromPrintState = true;
334
335 if (rState.bSavedStateRanges)
336 {
337 m_aRanges.m_nTotalY = rState.nTotalY;
338 m_aRanges.m_xPageEndX = rState.xPageEndX;
339 m_aRanges.m_xPageEndY = rState.xPageEndY;
340 m_aRanges.m_xPageRows = rState.xPageRows;
341 m_aRanges.m_aInput = rState.aPrintPageRangesInput;
342 }
343 else
344 {
345 m_aRanges.m_xPageEndX = std::make_shared<std::vector<SCCOL>>();
346 m_aRanges.m_xPageEndY = std::make_shared<std::vector<SCROW>>();
347 m_aRanges.m_xPageRows = std::make_shared<std::map<size_t, ScPageRowEntry>>();
348 }
349
350 Construct( pOptions );
351 }
352
GetPrintState(ScPrintState & rState,bool bSavePageRanges)353 void ScPrintFunc::GetPrintState(ScPrintState& rState, bool bSavePageRanges)
354 {
355 rState.nPrintTab = nPrintTab;
356 rState.nStartCol = nStartCol;
357 rState.nStartRow = nStartRow;
358 rState.nEndCol = nEndCol;
359 rState.nEndRow = nEndRow;
360 rState.bPrintAreaValid = bPrintAreaValid;
361 rState.nZoom = nZoom;
362 rState.nPagesX = m_aRanges.m_nPagesX;
363 rState.nPagesY = m_aRanges.m_nPagesY;
364 rState.nTabPages = nTabPages;
365 rState.nTotalPages = nTotalPages;
366 rState.nPageStart = nPageStart;
367 rState.nDocPages = nDocPages;
368 if (bSavePageRanges)
369 {
370 rState.bSavedStateRanges = true;
371 rState.nTotalY = m_aRanges.m_nTotalY;
372 rState.xPageEndX = m_aRanges.m_xPageEndX;
373 rState.xPageEndY = m_aRanges.m_xPageEndY;
374 rState.xPageRows = m_aRanges.m_xPageRows;
375 rState.aPrintPageRangesInput = m_aRanges.m_aInput;
376 }
377 }
378
GetLastSourceRange(ScRange & rRange) const379 bool ScPrintFunc::GetLastSourceRange( ScRange& rRange ) const
380 {
381 rRange = aLastSourceRange;
382 return bSourceRangeValid;
383 }
384
FillPageData()385 void ScPrintFunc::FillPageData()
386 {
387 if (!pPageData)
388 return;
389
390 sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( pPageData->GetCount() );
391 ScPrintRangeData& rData = pPageData->GetData(nCount); // count up
392
393 assert( bPrintAreaValid );
394 rData.SetPrintRange( ScRange( nStartCol, nStartRow, nPrintTab,
395 nEndCol, nEndRow, nPrintTab ) );
396 // #i123672#
397 if(m_aRanges.m_xPageEndX->empty())
398 {
399 OSL_ENSURE(false, "vector access error for maPageEndX (!)");
400 }
401 else
402 {
403 rData.SetPagesX( m_aRanges.m_nPagesX, m_aRanges.m_xPageEndX->data());
404 }
405
406 // #i123672#
407 if(m_aRanges.m_xPageEndY->empty())
408 {
409 OSL_ENSURE(false, "vector access error for maPageEndY (!)");
410 }
411 else
412 {
413 rData.SetPagesY( m_aRanges.m_nTotalY, m_aRanges.m_xPageEndY->data());
414 }
415
416 // Settings
417 rData.SetTopDown( aTableParam.bTopDown );
418 rData.SetAutomatic( !aAreaParam.bPrintArea );
419 }
420
~ScPrintFunc()421 ScPrintFunc::~ScPrintFunc()
422 {
423 pEditDefaults.reset();
424 pEditEngine.reset();
425
426 // Printer settings are now restored from outside
427
428 // For DrawingLayer/Charts, the MapMode of the printer (RefDevice) must always be correct
429 SfxPrinter* pDocPrinter = rDoc.GetPrinter(); // use Preview also for the printer
430 if (pDocPrinter)
431 pDocPrinter->SetMapMode(aOldPrinterMode);
432 }
433
SetDrawView(FmFormView * pNew)434 void ScPrintFunc::SetDrawView( FmFormView* pNew )
435 {
436 pDrawView = pNew;
437 }
438
lcl_HidePrint(const ScTableInfo & rTabInfo,SCCOL nX1,SCCOL nX2)439 static void lcl_HidePrint( const ScTableInfo& rTabInfo, SCCOL nX1, SCCOL nX2 )
440 {
441 for (SCSIZE nArrY=1; nArrY+1<rTabInfo.mnArrCount; nArrY++)
442 {
443 RowInfo* pThisRowInfo = &rTabInfo.mpRowInfo[nArrY];
444 for (SCCOL nX=nX1; nX<=nX2; nX++)
445 {
446 CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nX+1];
447 if (!rCellInfo.bEmptyCellText)
448 if (rCellInfo.pPatternAttr->
449 GetItem(ATTR_PROTECTION, rCellInfo.pConditionSet).GetHidePrint())
450 {
451 rCellInfo.maCell.clear();
452 rCellInfo.bEmptyCellText = true;
453 }
454 }
455 }
456 }
457
458 // output to Device (static)
459 //
460 // us used for:
461 // - Clipboard/Bitmap
462 // - Ole-Object (DocShell::Draw)
463 // - Preview of templates
464
DrawToDev(ScDocument & rDoc,OutputDevice * pDev,double,const tools::Rectangle & rBound,ScViewData * pViewData,bool bMetaFile)465 void ScPrintFunc::DrawToDev(ScDocument& rDoc, OutputDevice* pDev, double /* nPrintFactor */,
466 const tools::Rectangle& rBound, ScViewData* pViewData, bool bMetaFile)
467 {
468 //! evaluate nPrintFactor !!!
469
470 SCTAB nTab = 0;
471 if (pViewData)
472 nTab = pViewData->GetTabNo();
473
474 bool bDoGrid, bNullVal, bFormula;
475 ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool();
476 SfxStyleSheetBase* pStyleSheet = pStylePool->Find( rDoc.GetPageStyle( nTab ), SfxStyleFamily::Page );
477 if (pStyleSheet)
478 {
479 SfxItemSet& rSet = pStyleSheet->GetItemSet();
480 bDoGrid = rSet.Get(ATTR_PAGE_GRID).GetValue();
481 bNullVal = rSet.Get(ATTR_PAGE_NULLVALS).GetValue();
482 bFormula = rSet.Get(ATTR_PAGE_FORMULAS).GetValue();
483 }
484 else
485 {
486 const ScViewOptions& rOpt = rDoc.GetViewOptions();
487 bDoGrid = rOpt.GetOption(VOPT_GRID);
488 bNullVal = rOpt.GetOption(VOPT_NULLVALS);
489 bFormula = rOpt.GetOption(VOPT_FORMULAS);
490 }
491
492 MapMode aMode = pDev->GetMapMode();
493
494 tools::Rectangle aRect = rBound;
495
496 if (aRect.Right() < aRect.Left() || aRect.Bottom() < aRect.Top())
497 aRect = tools::Rectangle( Point(), pDev->GetOutputSize() );
498
499 SCCOL nX1 = 0;
500 SCROW nY1 = 0;
501 SCCOL nX2 = OLE_STD_CELLS_X - 1;
502 SCROW nY2 = OLE_STD_CELLS_Y - 1;
503 if (bMetaFile)
504 {
505 ScRange aRange = rDoc.GetRange( nTab, rBound );
506 nX1 = aRange.aStart.Col();
507 nY1 = aRange.aStart.Row();
508 nX2 = aRange.aEnd.Col();
509 nY2 = aRange.aEnd.Row();
510 }
511 else if (pViewData)
512 {
513 ScSplitPos eWhich = pViewData->GetActivePart();
514 ScHSplitPos eHWhich = WhichH(eWhich);
515 ScVSplitPos eVWhich = WhichV(eWhich);
516 nX1 = pViewData->GetPosX(eHWhich);
517 nY1 = pViewData->GetPosY(eVWhich);
518 nX2 = nX1 + pViewData->VisibleCellsX(eHWhich);
519 if (nX2>nX1) --nX2;
520 nY2 = nY1 + pViewData->VisibleCellsY(eVWhich);
521 if (nY2>nY1) --nY2;
522 }
523
524 if (nX1 > rDoc.MaxCol()) nX1 = rDoc.MaxCol();
525 if (nX2 > rDoc.MaxCol()) nX2 = rDoc.MaxCol();
526 if (nY1 > rDoc.MaxRow()) nY1 = rDoc.MaxRow();
527 if (nY2 > rDoc.MaxRow()) nY2 = rDoc.MaxRow();
528
529 tools::Long nDevSizeX = aRect.Right()-aRect.Left()+1;
530 tools::Long nDevSizeY = aRect.Bottom()-aRect.Top()+1;
531
532 tools::Long nTwipsSizeX = 0;
533 for (SCCOL i=nX1; i<=nX2; i++)
534 nTwipsSizeX += rDoc.GetColWidth( i, nTab );
535 tools::Long nTwipsSizeY = static_cast<tools::Long>(rDoc.GetRowHeight( nY1, nY2, nTab ));
536
537 // if no lines, still space for the outline frame (20 Twips = 1pt)
538 // (HasLines initializes aLines to 0,0,0,0)
539 nTwipsSizeX += 20;
540 nTwipsSizeY += 20;
541
542 double nScaleX = static_cast<double>(nDevSizeX) / nTwipsSizeX;
543 double nScaleY = static_cast<double>(nDevSizeY) / nTwipsSizeY;
544
545 //! hand over Flag at FillInfo !!!!!
546 ScRange aERange;
547 bool bEmbed = rDoc.IsEmbedded();
548 if (bEmbed)
549 {
550 rDoc.GetEmbedded(aERange);
551 rDoc.ResetEmbedded();
552 }
553
554 // Assemble data
555
556 ScTableInfo aTabInfo;
557 rDoc.FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab,
558 nScaleX, nScaleY, false, bFormula );
559 lcl_HidePrint( aTabInfo, nX1, nX2 );
560
561 if (bEmbed)
562 rDoc.SetEmbedded(aERange);
563
564 tools::Long nScrX = aRect.Left();
565 tools::Long nScrY = aRect.Top();
566
567 // If no lines, still leave space for grid lines
568 // (would be elseways cut away)
569 nScrX += 1;
570 nScrY += 1;
571
572 ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, &rDoc, nTab,
573 nScrX, nScrY, nX1, nY1, nX2, nY2, nScaleX, nScaleY );
574 aOutputData.SetMetaFileMode(bMetaFile);
575 aOutputData.SetShowNullValues(bNullVal);
576 aOutputData.SetShowFormulas(bFormula);
577
578 ScDrawLayer* pModel = rDoc.GetDrawLayer();
579 std::unique_ptr<FmFormView> pDrawView;
580
581 if( pModel )
582 {
583 pDrawView.reset(
584 new FmFormView(
585 *pModel,
586 pDev));
587 pDrawView->ShowSdrPage(pDrawView->GetModel()->GetPage(nTab));
588 pDrawView->SetPrintPreview();
589 aOutputData.SetDrawView( pDrawView.get() );
590 }
591
592 //! SetUseStyleColor ??
593
594 if ( bMetaFile && pDev->IsVirtual() )
595 aOutputData.SetSnapPixel();
596
597 Point aLogStart = pDev->PixelToLogic(Point(nScrX, nScrY), MapMode(MapUnit::Map100thMM));
598 tools::Long nLogStX = aLogStart.X();
599 tools::Long nLogStY = aLogStart.Y();
600
601 //! nZoom for GetFont in OutputData ???
602
603 if (!bMetaFile && pViewData)
604 pDev->SetMapMode(pViewData->GetLogicMode(pViewData->GetActivePart()));
605
606 // #i72502#
607 const Point aMMOffset(aOutputData.PrePrintDrawingLayer(nLogStX, nLogStY));
608 aOutputData.PrintDrawingLayer(SC_LAYER_BACK, aMMOffset);
609
610 if (!bMetaFile && pViewData)
611 pDev->SetMapMode(aMode);
612
613 aOutputData.DrawBackground(*pDev);
614
615 aOutputData.DrawShadow();
616 aOutputData.DrawFrame(*pDev);
617 aOutputData.DrawStrings();
618
619 if (!bMetaFile && pViewData)
620 pDev->SetMapMode(pViewData->GetLogicMode(pViewData->GetActivePart()));
621
622 aOutputData.DrawEdit(!bMetaFile);
623
624 if (bDoGrid)
625 {
626 if (!bMetaFile && pViewData)
627 pDev->SetMapMode(aMode);
628
629 aOutputData.DrawGrid(*pDev, true, false); // no page breaks
630
631 pDev->SetLineColor( COL_BLACK );
632
633 Size aOne = pDev->PixelToLogic( Size(1,1) );
634 if (bMetaFile)
635 aOne = Size(1,1); // compatible with DrawGrid
636 tools::Long nRight = nScrX + aOutputData.GetScrW() - aOne.Width();
637 tools::Long nBottom = nScrY + aOutputData.GetScrH() - aOne.Height();
638
639 bool bLayoutRTL = rDoc.IsLayoutRTL( nTab );
640
641 // extra line at the left edge for left-to-right, right for right-to-left
642 if ( bLayoutRTL )
643 pDev->DrawLine( Point(nRight,nScrY), Point(nRight,nBottom) );
644 else
645 pDev->DrawLine( Point(nScrX,nScrY), Point(nScrX,nBottom) );
646 // extra line at the top in both cases
647 pDev->DrawLine( Point(nScrX,nScrY), Point(nRight,nScrY) );
648 }
649
650 // #i72502#
651 aOutputData.PrintDrawingLayer(SC_LAYER_FRONT, aMMOffset);
652 aOutputData.PrintDrawingLayer(SC_LAYER_INTERN, aMMOffset);
653 aOutputData.PostPrintDrawingLayer(aMMOffset); // #i74768#
654 }
655
656 // Printing
657
lcl_FillHFParam(ScPrintHFParam & rParam,const SfxItemSet * pHFSet)658 static void lcl_FillHFParam( ScPrintHFParam& rParam, const SfxItemSet* pHFSet )
659 {
660 // nDistance must be initialized differently before
661
662 if ( pHFSet == nullptr )
663 {
664 rParam.bEnable = false;
665 rParam.pBorder = nullptr;
666 rParam.pBack = nullptr;
667 rParam.pShadow = nullptr;
668 }
669 else
670 {
671 rParam.bEnable = pHFSet->Get(ATTR_PAGE_ON).GetValue();
672 rParam.bDynamic = pHFSet->Get(ATTR_PAGE_DYNAMIC).GetValue();
673 rParam.bShared = pHFSet->Get(ATTR_PAGE_SHARED).GetValue();
674 rParam.bSharedFirst = pHFSet->Get(ATTR_PAGE_SHARED_FIRST).GetValue();
675 rParam.nHeight = pHFSet->Get(ATTR_PAGE_SIZE).GetSize().Height();
676 const SvxLRSpaceItem* pHFLR = &pHFSet->Get(ATTR_LRSPACE);
677 tools::Long nTmp;
678 nTmp = pHFLR->GetLeft();
679 rParam.nLeft = nTmp < 0 ? 0 : sal_uInt16(nTmp);
680 nTmp = pHFLR->GetRight();
681 rParam.nRight = nTmp < 0 ? 0 : sal_uInt16(nTmp);
682 rParam.pBorder = &pHFSet->Get(ATTR_BORDER);
683 rParam.pBack = &pHFSet->Get(ATTR_BACKGROUND);
684 rParam.pShadow = &pHFSet->Get(ATTR_SHADOW);
685
686 // now back in the dialog:
687 // rParam.nHeight += rParam.nDistance; // not in the dialog any more ???
688
689 rParam.nHeight += lcl_LineTotal( rParam.pBorder->GetTop() ) +
690 lcl_LineTotal( rParam.pBorder->GetBottom() );
691
692 rParam.nManHeight = rParam.nHeight;
693 }
694
695 if (!rParam.bEnable)
696 rParam.nHeight = 0;
697 }
698
699 // bNew = TRUE: search for used part of the document
700 // bNew = FALSE: only limit whole lines/columns
701
AdjustPrintArea(bool bNew)702 bool ScPrintFunc::AdjustPrintArea( bool bNew )
703 {
704 SCCOL nOldEndCol = nEndCol; // only important for !bNew
705 SCROW nOldEndRow = nEndRow;
706 bool bChangeCol = true; // at bNew both are being adjusted
707 bool bChangeRow = true;
708
709 bool bNotes = aTableParam.bNotes;
710 if ( bNew )
711 {
712 nStartCol = 0;
713 nStartRow = 0;
714 if (!rDoc.GetPrintArea( nPrintTab, nEndCol, nEndRow, bNotes ))
715 return false; // nothing
716 bPrintAreaValid = true;
717 }
718 else
719 {
720 bool bFound = true;
721 bChangeCol = ( nStartCol == 0 && nEndCol == rDoc.MaxCol() );
722 bChangeRow = ( nStartRow == 0 && nEndRow == rDoc.MaxRow() );
723 bool bForcedChangeRow = false;
724
725 // #i53558# Crop entire column of old row limit to real print area with
726 // some fuzzyness.
727 if (!bChangeRow && nStartRow == 0)
728 {
729 SCROW nPAEndRow;
730 bFound = rDoc.GetPrintAreaVer( nPrintTab, nStartCol, nEndCol, nPAEndRow, bNotes );
731 // Say we don't want to print more than ~1000 empty rows, which are
732 // about 14 pages intentionally left blank...
733 const SCROW nFuzzy = 23*42;
734 if (nPAEndRow + nFuzzy < nEndRow)
735 {
736 bForcedChangeRow = true;
737 nEndRow = nPAEndRow;
738 }
739 else
740 bFound = true; // user seems to _want_ to print some empty rows
741 }
742 // TODO: in case we extend the number of columns we may have to do the
743 // same for horizontal cropping.
744
745 if ( bChangeCol && bChangeRow )
746 bFound = rDoc.GetPrintArea( nPrintTab, nEndCol, nEndRow, bNotes );
747 else if ( bChangeCol )
748 bFound = rDoc.GetPrintAreaHor( nPrintTab, nStartRow, nEndRow, nEndCol );
749 else if ( bChangeRow )
750 bFound = rDoc.GetPrintAreaVer( nPrintTab, nStartCol, nEndCol, nEndRow, bNotes );
751
752 if (!bFound)
753 return false; // empty
754
755 bPrintAreaValid = true;
756 if (bForcedChangeRow)
757 bChangeRow = true;
758 }
759
760 assert( bPrintAreaValid );
761 rDoc.ExtendMerge( nStartCol,nStartRow, nEndCol,nEndRow, nPrintTab ); // no Refresh, incl. Attrs
762
763 if ( bChangeCol )
764 {
765 OutputDevice* pRefDev = rDoc.GetPrinter(); // use the printer also for Preview
766 pRefDev->SetMapMode(MapMode(MapUnit::MapPixel)); // important for GetNeededSize
767
768 rDoc.ExtendPrintArea( pRefDev,
769 nPrintTab, nStartCol, nStartRow, nEndCol, nEndRow );
770 // changing nEndCol
771 }
772
773 if ( nEndCol < rDoc.MaxCol() && rDoc.HasAttrib(
774 nEndCol,nStartRow,nPrintTab, nEndCol,nEndRow,nPrintTab, HasAttrFlags::ShadowRight ) )
775 ++nEndCol;
776 if ( nEndRow < rDoc.MaxRow() && rDoc.HasAttrib(
777 nStartCol,nEndRow,nPrintTab, nEndCol,nEndRow,nPrintTab, HasAttrFlags::ShadowDown ) )
778 ++nEndRow;
779
780 if (!bChangeCol) nEndCol = nOldEndCol;
781 if (!bChangeRow) nEndRow = nOldEndRow;
782
783 return true;
784 }
785
TextHeight(const EditTextObject * pObject)786 tools::Long ScPrintFunc::TextHeight( const EditTextObject* pObject )
787 {
788 if (!pObject)
789 return 0;
790
791 pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, false );
792
793 return static_cast<tools::Long>(pEditEngine->GetTextHeight());
794 }
795
796 // nZoom must be set !!!
797 // and the respective Twip-MapMode configured
798
UpdateHFHeight(ScPrintHFParam & rParam)799 void ScPrintFunc::UpdateHFHeight( ScPrintHFParam& rParam )
800 {
801 OSL_ENSURE( aPageSize.Width(), "UpdateHFHeight without aPageSize");
802
803 if (!(rParam.bEnable && rParam.bDynamic))
804 return;
805
806 // calculate nHeight from content
807
808 MakeEditEngine();
809 tools::Long nPaperWidth = ( aPageSize.Width() - nLeftMargin - nRightMargin -
810 rParam.nLeft - rParam.nRight ) * 100 / nZoom;
811 if (rParam.pBorder)
812 nPaperWidth -= ( rParam.pBorder->GetDistance(SvxBoxItemLine::LEFT) +
813 rParam.pBorder->GetDistance(SvxBoxItemLine::RIGHT) +
814 lcl_LineTotal(rParam.pBorder->GetLeft()) +
815 lcl_LineTotal(rParam.pBorder->GetRight()) ) * 100 / nZoom;
816
817 if (rParam.pShadow && rParam.pShadow->GetLocation() != SvxShadowLocation::NONE)
818 nPaperWidth -= ( rParam.pShadow->CalcShadowSpace(SvxShadowItemSide::LEFT) +
819 rParam.pShadow->CalcShadowSpace(SvxShadowItemSide::RIGHT) ) * 100 / nZoom;
820
821 pEditEngine->SetPaperSize( Size( nPaperWidth, 10000 ) );
822
823 tools::Long nMaxHeight = 0;
824 if ( rParam.pLeft )
825 {
826 nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pLeft->GetLeftArea() ) );
827 nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pLeft->GetCenterArea() ) );
828 nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pLeft->GetRightArea() ) );
829 }
830 if ( rParam.pRight )
831 {
832 nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pRight->GetLeftArea() ) );
833 nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pRight->GetCenterArea() ) );
834 nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pRight->GetRightArea() ) );
835 }
836 if ( rParam.pFirst )
837 {
838 nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pFirst->GetLeftArea() ) );
839 nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pFirst->GetCenterArea() ) );
840 nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pFirst->GetRightArea() ) );
841 }
842
843 rParam.nHeight = nMaxHeight + rParam.nDistance;
844 if (rParam.pBorder)
845 rParam.nHeight += rParam.pBorder->GetDistance(SvxBoxItemLine::TOP) +
846 rParam.pBorder->GetDistance(SvxBoxItemLine::BOTTOM) +
847 lcl_LineTotal( rParam.pBorder->GetTop() ) +
848 lcl_LineTotal( rParam.pBorder->GetBottom() );
849 if (rParam.pShadow && rParam.pShadow->GetLocation() != SvxShadowLocation::NONE)
850 rParam.nHeight += rParam.pShadow->CalcShadowSpace(SvxShadowItemSide::TOP) +
851 rParam.pShadow->CalcShadowSpace(SvxShadowItemSide::BOTTOM);
852
853 if (rParam.nHeight < rParam.nManHeight)
854 rParam.nHeight = rParam.nManHeight; // configured minimum
855 }
856
InitParam(const ScPrintOptions * pOptions)857 void ScPrintFunc::InitParam( const ScPrintOptions* pOptions )
858 {
859 if (!pParamSet)
860 return;
861
862 // TabPage "Page"
863 const SvxLRSpaceItem* pLRItem = &pParamSet->Get( ATTR_LRSPACE );
864 tools::Long nTmp;
865 nTmp = pLRItem->GetLeft();
866 nLeftMargin = nTmp < 0 ? 0 : sal_uInt16(nTmp);
867 nTmp = pLRItem->GetRight();
868 nRightMargin = nTmp < 0 ? 0 : sal_uInt16(nTmp);
869 const SvxULSpaceItem* pULItem = &pParamSet->Get( ATTR_ULSPACE );
870 nTopMargin = pULItem->GetUpper();
871 nBottomMargin = pULItem->GetLower();
872
873 const SvxPageItem* pPageItem = &pParamSet->Get( ATTR_PAGE );
874 nPageUsage = pPageItem->GetPageUsage();
875 bLandscape = pPageItem->IsLandscape();
876 aFieldData.eNumType = pPageItem->GetNumType();
877
878 bCenterHor = pParamSet->Get(ATTR_PAGE_HORCENTER).GetValue();
879 bCenterVer = pParamSet->Get(ATTR_PAGE_VERCENTER).GetValue();
880
881 aPageSize = pParamSet->Get(ATTR_PAGE_SIZE).GetSize();
882 if ( !aPageSize.Width() || !aPageSize.Height() )
883 {
884 OSL_FAIL("PageSize Null ?!?!?");
885 aPageSize = SvxPaperInfo::GetPaperSize( PAPER_A4 );
886 }
887
888 pBorderItem = &pParamSet->Get(ATTR_BORDER);
889 pBackgroundItem = &pParamSet->Get(ATTR_BACKGROUND);
890 pShadowItem = &pParamSet->Get(ATTR_SHADOW);
891
892 // TabPage "Headline"
893
894 aHdr.pLeft = &pParamSet->Get(ATTR_PAGE_HEADERLEFT); // Content
895 aHdr.pRight = &pParamSet->Get(ATTR_PAGE_HEADERRIGHT);
896 aHdr.pFirst = &pParamSet->Get(ATTR_PAGE_HEADERFIRST);
897
898 const SvxSetItem* pHeaderSetItem;
899 const SfxItemSet* pHeaderSet = nullptr;
900 if ( pParamSet->GetItemState( ATTR_PAGE_HEADERSET, false,
901 reinterpret_cast<const SfxPoolItem**>(&pHeaderSetItem) ) == SfxItemState::SET )
902 {
903 pHeaderSet = &pHeaderSetItem->GetItemSet();
904 // Headline has space below
905 aHdr.nDistance = pHeaderSet->Get(ATTR_ULSPACE).GetLower();
906 }
907 lcl_FillHFParam( aHdr, pHeaderSet );
908
909 // TabPage "Footline"
910
911 aFtr.pLeft = &pParamSet->Get(ATTR_PAGE_FOOTERLEFT); // Content
912 aFtr.pRight = &pParamSet->Get(ATTR_PAGE_FOOTERRIGHT);
913 aFtr.pFirst = &pParamSet->Get(ATTR_PAGE_FOOTERFIRST);
914
915 const SvxSetItem* pFooterSetItem;
916 const SfxItemSet* pFooterSet = nullptr;
917 if ( pParamSet->GetItemState( ATTR_PAGE_FOOTERSET, false,
918 reinterpret_cast<const SfxPoolItem**>(&pFooterSetItem) ) == SfxItemState::SET )
919 {
920 pFooterSet = &pFooterSetItem->GetItemSet();
921 // Footline has space above
922 aFtr.nDistance = pFooterSet->Get(ATTR_ULSPACE).GetUpper();
923 }
924 lcl_FillHFParam( aFtr, pFooterSet );
925
926 // Compile Table-/Area-Params from single Items
927
928 // TabPage "Table"
929
930 const SfxUInt16Item* pScaleItem = nullptr;
931 const ScPageScaleToItem* pScaleToItem = nullptr;
932 const SfxUInt16Item* pScaleToPagesItem = nullptr;
933 SfxItemState eState;
934
935 eState = pParamSet->GetItemState( ATTR_PAGE_SCALE, false,
936 reinterpret_cast<const SfxPoolItem**>(&pScaleItem) );
937 if ( SfxItemState::DEFAULT == eState )
938 pScaleItem = &pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALE );
939
940 eState = pParamSet->GetItemState( ATTR_PAGE_SCALETO, false,
941 reinterpret_cast<const SfxPoolItem**>(&pScaleToItem) );
942 if ( SfxItemState::DEFAULT == eState )
943 pScaleToItem = &pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALETO );
944
945 eState = pParamSet->GetItemState( ATTR_PAGE_SCALETOPAGES, false,
946 reinterpret_cast<const SfxPoolItem**>(&pScaleToPagesItem) );
947 if ( SfxItemState::DEFAULT == eState )
948 pScaleToPagesItem = &pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALETOPAGES );
949
950 OSL_ENSURE( pScaleItem && pScaleToItem && pScaleToPagesItem, "Missing ScaleItem! :-/" );
951
952 aTableParam.bCellContent = true;
953 aTableParam.bNotes = lcl_GetBool(pParamSet,ATTR_PAGE_NOTES);
954 aTableParam.bGrid = lcl_GetBool(pParamSet,ATTR_PAGE_GRID);
955 aTableParam.bHeaders = lcl_GetBool(pParamSet,ATTR_PAGE_HEADERS);
956 aTableParam.bFormulas = lcl_GetBool(pParamSet,ATTR_PAGE_FORMULAS);
957 aTableParam.bNullVals = lcl_GetBool(pParamSet,ATTR_PAGE_NULLVALS);
958 aTableParam.bCharts = lcl_GetShow(pParamSet,ATTR_PAGE_CHARTS);
959 aTableParam.bObjects = lcl_GetShow(pParamSet,ATTR_PAGE_OBJECTS);
960 aTableParam.bDrawings = lcl_GetShow(pParamSet,ATTR_PAGE_DRAWINGS);
961 aTableParam.bTopDown = lcl_GetBool(pParamSet,ATTR_PAGE_TOPDOWN);
962 aTableParam.bLeftRight = !aTableParam.bLeftRight;
963 aTableParam.nFirstPageNo = lcl_GetUShort(pParamSet,ATTR_PAGE_FIRSTPAGENO);
964 if (!aTableParam.nFirstPageNo)
965 aTableParam.nFirstPageNo = static_cast<sal_uInt16>(nPageStart); // from previous table
966
967 if ( pScaleItem && pScaleToItem && pScaleToPagesItem )
968 {
969 sal_uInt16 nScaleAll = pScaleItem->GetValue();
970 sal_uInt16 nScaleToPages = pScaleToPagesItem->GetValue();
971
972 aTableParam.bScaleNone = (nScaleAll == 100);
973 aTableParam.bScaleAll = (nScaleAll > 0 );
974 aTableParam.bScaleTo = pScaleToItem->IsValid();
975 aTableParam.bScalePageNum = (nScaleToPages > 0 );
976 aTableParam.nScaleAll = nScaleAll;
977 aTableParam.nScaleWidth = pScaleToItem->GetWidth();
978 aTableParam.nScaleHeight = pScaleToItem->GetHeight();
979 aTableParam.nScalePageNum = nScaleToPages;
980 }
981 else
982 {
983 aTableParam.bScaleNone = true;
984 aTableParam.bScaleAll = false;
985 aTableParam.bScaleTo = false;
986 aTableParam.bScalePageNum = false;
987 aTableParam.nScaleAll = 0;
988 aTableParam.nScaleWidth = 0;
989 aTableParam.nScaleHeight = 0;
990 aTableParam.nScalePageNum = 0;
991 }
992
993 // skip empty pages only if options with that flag are passed
994 aTableParam.bSkipEmpty = pOptions && pOptions->GetSkipEmpty();
995 if ( pPageData )
996 aTableParam.bSkipEmpty = false;
997 // If pPageData is set, only the breaks are interesting for the
998 // pagebreak preview, empty pages are not addressed separately.
999
1000 aTableParam.bForceBreaks = pOptions && pOptions->GetForceBreaks();
1001
1002 // TabPage "Parts":
1003
1004 //! walk through all PrintAreas of the table !!!
1005 const ScRange* pPrintArea = rDoc.GetPrintRange( nPrintTab, 0 );
1006 const ScRange* pRepeatCol = rDoc.GetRepeatColRange( nPrintTab );
1007 const ScRange* pRepeatRow = rDoc.GetRepeatRowRange( nPrintTab );
1008
1009 // ignoring ATTR_PAGE_PRINTTABLES
1010
1011 bool bHasPrintRange = rDoc.HasPrintRange();
1012 sal_uInt16 nPrintRangeCount = rDoc.GetPrintRangeCount(nPrintTab);
1013 bool bPrintEntireSheet = rDoc.IsPrintEntireSheet(nPrintTab);
1014
1015 if (!bPrintEntireSheet && !nPrintRangeCount)
1016 mbHasPrintRange = false;
1017
1018 if ( pUserArea ) // UserArea (selection) has priority
1019 {
1020 bPrintCurrentTable =
1021 aAreaParam.bPrintArea = true; // Selection
1022 aAreaParam.aPrintArea = *pUserArea;
1023
1024 // The table-query is already in DocShell::Print, here always
1025 aAreaParam.aPrintArea.aStart.SetTab(nPrintTab);
1026 aAreaParam.aPrintArea.aEnd.SetTab(nPrintTab);
1027 }
1028 else if (bHasPrintRange)
1029 {
1030 if ( pPrintArea ) // at least one set?
1031 {
1032 bPrintCurrentTable =
1033 aAreaParam.bPrintArea = true;
1034 aAreaParam.aPrintArea = *pPrintArea;
1035
1036 bMultiArea = nPrintRangeCount > 1;
1037 }
1038 else
1039 {
1040 // do not print hidden sheets with "Print entire sheet" flag
1041 bPrintCurrentTable = rDoc.IsPrintEntireSheet( nPrintTab ) && rDoc.IsVisible( nPrintTab );
1042 aAreaParam.bPrintArea = !bPrintCurrentTable; // otherwise the table is always counted
1043 }
1044 }
1045 else
1046 {
1047 // don't print hidden tables if there's no print range defined there
1048 if ( rDoc.IsVisible( nPrintTab ) )
1049 {
1050 aAreaParam.bPrintArea = false;
1051 bPrintCurrentTable = true;
1052 }
1053 else
1054 {
1055 aAreaParam.bPrintArea = true; // otherwise the table is always counted
1056 bPrintCurrentTable = false;
1057 }
1058 }
1059
1060 if ( pRepeatCol )
1061 {
1062 aAreaParam.bRepeatCol = true;
1063 nRepeatStartCol = pRepeatCol->aStart.Col();
1064 nRepeatEndCol = pRepeatCol->aEnd .Col();
1065 }
1066 else
1067 {
1068 aAreaParam.bRepeatCol = false;
1069 nRepeatStartCol = nRepeatEndCol = SCCOL_REPEAT_NONE;
1070 }
1071
1072 if ( pRepeatRow )
1073 {
1074 aAreaParam.bRepeatRow = true;
1075 nRepeatStartRow = pRepeatRow->aStart.Row();
1076 nRepeatEndRow = pRepeatRow->aEnd .Row();
1077 }
1078 else
1079 {
1080 aAreaParam.bRepeatRow = false;
1081 nRepeatStartRow = nRepeatEndRow = SCROW_REPEAT_NONE;
1082 }
1083
1084 // Split pages
1085
1086 if (!bPrintAreaValid)
1087 {
1088 nTabPages = CountPages(); // also calculates zoom
1089 nTotalPages = nTabPages;
1090 nTotalPages += CountNotePages();
1091 }
1092 else
1093 {
1094 CalcPages(); // search breaks only
1095 CountNotePages(); // Count notes, even if number of pages is already known
1096 }
1097
1098 if (nDocPages)
1099 aFieldData.nTotalPages = nDocPages;
1100 else
1101 aFieldData.nTotalPages = nTotalPages;
1102
1103 SetDateTime( DateTime( DateTime::SYSTEM ) );
1104
1105 if( pDocShell->getDocProperties()->getTitle().getLength() != 0 )
1106 aFieldData.aTitle = pDocShell->getDocProperties()->getTitle();
1107 else
1108 aFieldData.aTitle = pDocShell->GetTitle();
1109
1110 const INetURLObject& rURLObj = pDocShell->GetMedium()->GetURLObject();
1111 aFieldData.aLongDocName = rURLObj.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous );
1112 if ( !aFieldData.aLongDocName.isEmpty() )
1113 aFieldData.aShortDocName = rURLObj.GetLastName(INetURLObject::DecodeMechanism::Unambiguous);
1114 else
1115 aFieldData.aShortDocName = aFieldData.aLongDocName = aFieldData.aTitle;
1116
1117 // Printer settings (Orientation, Paper) at DoPrint
1118 }
1119
GetDataSize() const1120 Size ScPrintFunc::GetDataSize() const
1121 {
1122 Size aSize = aPageSize;
1123 aSize.AdjustWidth( -(nLeftMargin + nRightMargin) );
1124 aSize.AdjustHeight( -(nTopMargin + nBottomMargin) );
1125 aSize.AdjustHeight( -(aHdr.nHeight + aFtr.nHeight) );
1126 return aSize;
1127 }
1128
GetScaleData(Size & rPhysSize,tools::Long & rDocHdr,tools::Long & rDocFtr)1129 void ScPrintFunc::GetScaleData( Size& rPhysSize, tools::Long& rDocHdr, tools::Long& rDocFtr )
1130 {
1131 rPhysSize = aPageSize;
1132 rPhysSize.AdjustWidth( -(nLeftMargin + nRightMargin) );
1133 rPhysSize.AdjustHeight( -(nTopMargin + nBottomMargin) );
1134
1135 rDocHdr = aHdr.nHeight;
1136 rDocFtr = aFtr.nHeight;
1137 }
1138
SetDateTime(const DateTime & rDateTime)1139 void ScPrintFunc::SetDateTime( const DateTime& rDateTime )
1140 {
1141 aFieldData.aDateTime = rDateTime;
1142 }
1143
lcl_DrawGraphic(const Graphic & rGraphic,vcl::RenderContext & rOutDev,const tools::Rectangle & rGrf,const tools::Rectangle & rOut)1144 static void lcl_DrawGraphic( const Graphic &rGraphic, vcl::RenderContext& rOutDev,
1145 const tools::Rectangle &rGrf, const tools::Rectangle &rOut )
1146 {
1147 const bool bNotInside = !rOut.IsInside( rGrf );
1148 if ( bNotInside )
1149 {
1150 rOutDev.Push();
1151 rOutDev.IntersectClipRegion( rOut );
1152 }
1153
1154 rGraphic.Draw(rOutDev, rGrf.TopLeft(), rGrf.GetSize());
1155
1156 if ( bNotInside )
1157 rOutDev.Pop();
1158 }
1159
lcl_DrawGraphic(const SvxBrushItem & rBrush,vcl::RenderContext & rOutDev,const OutputDevice * pRefDev,const tools::Rectangle & rOrg,const tools::Rectangle & rOut,OUString const & referer)1160 static void lcl_DrawGraphic( const SvxBrushItem &rBrush, vcl::RenderContext& rOutDev, const OutputDevice* pRefDev,
1161 const tools::Rectangle &rOrg, const tools::Rectangle &rOut,
1162 OUString const & referer )
1163 {
1164 Size aGrfSize(0,0);
1165 const Graphic *pGraphic = rBrush.GetGraphic(referer);
1166 SvxGraphicPosition ePos;
1167 if ( pGraphic && pGraphic->IsSupportedGraphic() )
1168 {
1169 const MapMode aMapMM( MapUnit::Map100thMM );
1170 if ( pGraphic->GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel )
1171 aGrfSize = pRefDev->PixelToLogic( pGraphic->GetPrefSize(), aMapMM );
1172 else
1173 aGrfSize = OutputDevice::LogicToLogic( pGraphic->GetPrefSize(),
1174 pGraphic->GetPrefMapMode(), aMapMM );
1175 ePos = rBrush.GetGraphicPos();
1176 }
1177 else
1178 ePos = GPOS_NONE;
1179
1180 Point aPos;
1181 Size aDrawSize = aGrfSize;
1182
1183 bool bDraw = true;
1184 switch ( ePos )
1185 {
1186 case GPOS_LT: aPos = rOrg.TopLeft();
1187 break;
1188 case GPOS_MT: aPos.setY( rOrg.Top() );
1189 aPos.setX( rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2 );
1190 break;
1191 case GPOS_RT: aPos.setY( rOrg.Top() );
1192 aPos.setX( rOrg.Right() - aGrfSize.Width() );
1193 break;
1194
1195 case GPOS_LM: aPos.setY( rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2 );
1196 aPos.setX( rOrg.Left() );
1197 break;
1198 case GPOS_MM: aPos.setY( rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2 );
1199 aPos.setX( rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2 );
1200 break;
1201 case GPOS_RM: aPos.setY( rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2 );
1202 aPos.setX( rOrg.Right() - aGrfSize.Width() );
1203 break;
1204
1205 case GPOS_LB: aPos.setY( rOrg.Bottom() - aGrfSize.Height() );
1206 aPos.setX( rOrg.Left() );
1207 break;
1208 case GPOS_MB: aPos.setY( rOrg.Bottom() - aGrfSize.Height() );
1209 aPos.setX( rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2 );
1210 break;
1211 case GPOS_RB: aPos.setY( rOrg.Bottom() - aGrfSize.Height() );
1212 aPos.setX( rOrg.Right() - aGrfSize.Width() );
1213 break;
1214
1215 case GPOS_AREA:
1216 aPos = rOrg.TopLeft();
1217 aDrawSize = rOrg.GetSize();
1218 break;
1219 case GPOS_TILED:
1220 {
1221 // use GraphicObject::DrawTiled instead of an own loop
1222 // (pixel rounding is handled correctly, and a very small bitmap
1223 // is duplicated into a bigger one for better performance)
1224
1225 GraphicObject aObject( *pGraphic );
1226
1227 if( rOutDev.GetOutDevType() == OUTDEV_PDF &&
1228 (aObject.GetType() == GraphicType::Bitmap || aObject.GetType() == GraphicType::Default) )
1229 {
1230 // For PDF export, every draw
1231 // operation for bitmaps takes a noticeable
1232 // amount of place (~50 characters). Thus,
1233 // optimize between tile bitmap size and
1234 // number of drawing operations here.
1235 //
1236 // A_out
1237 // n_chars = k1 * ---------- + k2 * A_bitmap
1238 // A_bitmap
1239 //
1240 // minimum n_chars is obtained for (derive for
1241 // A_bitmap, set to 0, take positive
1242 // solution):
1243 // k1
1244 // A_bitmap = Sqrt( ---- A_out )
1245 // k2
1246 //
1247 // where k1 is the number of chars per draw
1248 // operation, and k2 is the number of chars
1249 // per bitmap pixel. This is approximately 50
1250 // and 7 for current PDF writer, respectively.
1251
1252 const double k1( 50 );
1253 const double k2( 7 );
1254 const Size aSize( rOrg.GetSize() );
1255 const double Abitmap( k1/k2 * aSize.Width()*aSize.Height() );
1256
1257 aObject.DrawTiled( rOutDev, rOrg, aGrfSize, Size(0,0),
1258 ::std::max( 128, static_cast<int>( sqrt(sqrt( Abitmap)) + .5 ) ) );
1259 }
1260 else
1261 {
1262 aObject.DrawTiled( rOutDev, rOrg, aGrfSize, Size(0,0) );
1263 }
1264
1265 bDraw = false;
1266 }
1267 break;
1268
1269 case GPOS_NONE:
1270 bDraw = false;
1271 break;
1272
1273 default: OSL_ENSURE( false, "new Graphic position?" );
1274 }
1275 tools::Rectangle aGrf( aPos,aDrawSize );
1276 if ( bDraw && aGrf.IsOver( rOut ) )
1277 {
1278 lcl_DrawGraphic( *pGraphic, rOutDev, aGrf, rOut );
1279 }
1280 }
1281
1282 // The frame is drawn inwards
1283
DrawBorder(tools::Long nScrX,tools::Long nScrY,tools::Long nScrW,tools::Long nScrH,const SvxBoxItem * pBorderData,const SvxBrushItem * pBackground,const SvxShadowItem * pShadow)1284 void ScPrintFunc::DrawBorder( tools::Long nScrX, tools::Long nScrY, tools::Long nScrW, tools::Long nScrH,
1285 const SvxBoxItem* pBorderData, const SvxBrushItem* pBackground,
1286 const SvxShadowItem* pShadow )
1287 {
1288 //! direct output from SvxBoxItem !!!
1289
1290 if (pBorderData)
1291 if ( !pBorderData->GetTop() && !pBorderData->GetBottom() && !pBorderData->GetLeft() &&
1292 !pBorderData->GetRight() )
1293 pBorderData = nullptr;
1294
1295 if (!pBorderData && !pBackground && !pShadow)
1296 return; // nothing to do
1297
1298 tools::Long nLeft = 0;
1299 tools::Long nRight = 0;
1300 tools::Long nTop = 0;
1301 tools::Long nBottom = 0;
1302
1303 // aFrameRect - outside around frame, without shadow
1304 if ( pShadow && pShadow->GetLocation() != SvxShadowLocation::NONE )
1305 {
1306 nLeft += static_cast<tools::Long>( pShadow->CalcShadowSpace(SvxShadowItemSide::LEFT) * nScaleX );
1307 nRight += static_cast<tools::Long>( pShadow->CalcShadowSpace(SvxShadowItemSide::RIGHT) * nScaleX );
1308 nTop += static_cast<tools::Long>( pShadow->CalcShadowSpace(SvxShadowItemSide::TOP) * nScaleY );
1309 nBottom += static_cast<tools::Long>( pShadow->CalcShadowSpace(SvxShadowItemSide::BOTTOM) * nScaleY );
1310 }
1311 tools::Rectangle aFrameRect( Point(nScrX+nLeft, nScrY+nTop),
1312 Size(nScrW-nLeft-nRight, nScrH-nTop-nBottom) );
1313
1314 // center of frame, to paint lines through OutputData
1315 if (pBorderData)
1316 {
1317 nLeft += static_cast<tools::Long>( lcl_LineTotal(pBorderData->GetLeft()) * nScaleX / 2 );
1318 nRight += static_cast<tools::Long>( lcl_LineTotal(pBorderData->GetRight()) * nScaleX / 2 );
1319 nTop += static_cast<tools::Long>( lcl_LineTotal(pBorderData->GetTop()) * nScaleY / 2 );
1320 nBottom += static_cast<tools::Long>( lcl_LineTotal(pBorderData->GetBottom()) * nScaleY / 2 );
1321 }
1322 tools::Long nEffHeight = nScrH - nTop - nBottom;
1323 tools::Long nEffWidth = nScrW - nLeft - nRight;
1324 if (nEffHeight<=0 || nEffWidth<=0)
1325 return; // empty
1326
1327 if ( pBackground )
1328 {
1329 if (pBackground->GetGraphicPos() != GPOS_NONE)
1330 {
1331 OutputDevice* pRefDev;
1332 if ( bIsRender )
1333 pRefDev = pDev; // don't use printer for PDF
1334 else
1335 pRefDev = rDoc.GetPrinter(); // use printer also for preview
1336 OUString referer;
1337 if (pDocShell->HasName()) {
1338 referer = pDocShell->GetMedium()->GetName();
1339 }
1340 lcl_DrawGraphic(*pBackground, *pDev, pRefDev, aFrameRect, aFrameRect, referer);
1341 }
1342 else
1343 {
1344 pDev->SetFillColor(pBackground->GetColor());
1345 pDev->SetLineColor();
1346 pDev->DrawRect(aFrameRect);
1347 }
1348 }
1349
1350 if ( pShadow && pShadow->GetLocation() != SvxShadowLocation::NONE )
1351 {
1352 pDev->SetFillColor(pShadow->GetColor());
1353 pDev->SetLineColor();
1354 tools::Long nShadowX = static_cast<tools::Long>( pShadow->GetWidth() * nScaleX );
1355 tools::Long nShadowY = static_cast<tools::Long>( pShadow->GetWidth() * nScaleY );
1356 switch (pShadow->GetLocation())
1357 {
1358 case SvxShadowLocation::TopLeft:
1359 pDev->DrawRect( tools::Rectangle(
1360 aFrameRect.Left()-nShadowX, aFrameRect.Top()-nShadowY,
1361 aFrameRect.Right()-nShadowX, aFrameRect.Top() ) );
1362 pDev->DrawRect( tools::Rectangle(
1363 aFrameRect.Left()-nShadowX, aFrameRect.Top()-nShadowY,
1364 aFrameRect.Left(), aFrameRect.Bottom()-nShadowY ) );
1365 break;
1366 case SvxShadowLocation::TopRight:
1367 pDev->DrawRect( tools::Rectangle(
1368 aFrameRect.Left()+nShadowX, aFrameRect.Top()-nShadowY,
1369 aFrameRect.Right()+nShadowX, aFrameRect.Top() ) );
1370 pDev->DrawRect( tools::Rectangle(
1371 aFrameRect.Right(), aFrameRect.Top()-nShadowY,
1372 aFrameRect.Right()+nShadowX, aFrameRect.Bottom()-nShadowY ) );
1373 break;
1374 case SvxShadowLocation::BottomLeft:
1375 pDev->DrawRect( tools::Rectangle(
1376 aFrameRect.Left()-nShadowX, aFrameRect.Bottom(),
1377 aFrameRect.Right()-nShadowX, aFrameRect.Bottom()+nShadowY ) );
1378 pDev->DrawRect( tools::Rectangle(
1379 aFrameRect.Left()-nShadowX, aFrameRect.Top()+nShadowY,
1380 aFrameRect.Left(), aFrameRect.Bottom()+nShadowY ) );
1381 break;
1382 case SvxShadowLocation::BottomRight:
1383 pDev->DrawRect( tools::Rectangle(
1384 aFrameRect.Left()+nShadowX, aFrameRect.Bottom(),
1385 aFrameRect.Right()+nShadowX, aFrameRect.Bottom()+nShadowY ) );
1386 pDev->DrawRect( tools::Rectangle(
1387 aFrameRect.Right(), aFrameRect.Top()+nShadowY,
1388 aFrameRect.Right()+nShadowX, aFrameRect.Bottom()+nShadowY ) );
1389 break;
1390 default:
1391 {
1392 // added to avoid warnings
1393 }
1394 }
1395 }
1396
1397 if (!pBorderData)
1398 return;
1399
1400 ScDocumentUniquePtr pBorderDoc(new ScDocument( SCDOCMODE_UNDO ));
1401 pBorderDoc->InitUndo( rDoc, 0,0, true,true );
1402 pBorderDoc->ApplyAttr( 0,0,0, *pBorderData );
1403
1404 ScTableInfo aTabInfo;
1405 pBorderDoc->FillInfo( aTabInfo, 0,0, 0,0, 0,
1406 nScaleX, nScaleY, false, false );
1407 OSL_ENSURE(aTabInfo.mnArrCount,"nArrCount == 0");
1408
1409 aTabInfo.mpRowInfo[1].nHeight = static_cast<sal_uInt16>(nEffHeight);
1410 aTabInfo.mpRowInfo[0].pCellInfo[1].nWidth =
1411 aTabInfo.mpRowInfo[1].pCellInfo[1].nWidth = static_cast<sal_uInt16>(nEffWidth);
1412
1413 ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pBorderDoc.get(), 0,
1414 nScrX+nLeft, nScrY+nTop, 0,0, 0,0, nScaleX, nScaleY );
1415 aOutputData.SetUseStyleColor( bUseStyleColor );
1416
1417 aOutputData.DrawFrame(*pDev);
1418 }
1419
PrintColHdr(SCCOL nX1,SCCOL nX2,tools::Long nScrX,tools::Long nScrY)1420 void ScPrintFunc::PrintColHdr( SCCOL nX1, SCCOL nX2, tools::Long nScrX, tools::Long nScrY )
1421 {
1422 bool bLayoutRTL = rDoc.IsLayoutRTL( nPrintTab );
1423 tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
1424
1425 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1426 tools::Long nOneX = aOnePixel.Width();
1427 tools::Long nOneY = aOnePixel.Height();
1428 SCCOL nCol;
1429
1430 tools::Long nHeight = static_cast<tools::Long>(PRINT_HEADER_HEIGHT * nScaleY);
1431 tools::Long nEndY = nScrY + nHeight - nOneY;
1432
1433 tools::Long nPosX = nScrX;
1434 if ( bLayoutRTL )
1435 {
1436 for (nCol=nX1; nCol<=nX2; nCol++)
1437 nPosX += static_cast<tools::Long>( rDoc.GetColWidth( nCol, nPrintTab ) * nScaleX );
1438 }
1439 else
1440 nPosX -= nOneX;
1441 tools::Long nPosY = nScrY - nOneY;
1442 OUString aText;
1443
1444 for (nCol=nX1; nCol<=nX2; nCol++)
1445 {
1446 sal_uInt16 nDocW = rDoc.GetColWidth( nCol, nPrintTab );
1447 if (nDocW)
1448 {
1449 tools::Long nWidth = static_cast<tools::Long>(nDocW * nScaleX);
1450 tools::Long nEndX = nPosX + nWidth * nLayoutSign;
1451
1452 pDev->DrawRect( tools::Rectangle( nPosX,nPosY,nEndX,nEndY ) );
1453
1454 aText = ::ScColToAlpha( nCol);
1455 tools::Long nTextWidth = pDev->GetTextWidth(aText);
1456 tools::Long nTextHeight = pDev->GetTextHeight();
1457 tools::Long nAddX = ( nWidth - nTextWidth ) / 2;
1458 tools::Long nAddY = ( nHeight - nTextHeight ) / 2;
1459 tools::Long nTextPosX = nPosX+nAddX;
1460 if ( bLayoutRTL )
1461 nTextPosX -= nWidth;
1462 pDev->DrawText( Point( nTextPosX,nPosY+nAddY ), aText );
1463
1464 nPosX = nEndX;
1465 }
1466 }
1467 }
1468
PrintRowHdr(SCROW nY1,SCROW nY2,tools::Long nScrX,tools::Long nScrY)1469 void ScPrintFunc::PrintRowHdr( SCROW nY1, SCROW nY2, tools::Long nScrX, tools::Long nScrY )
1470 {
1471 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1472 tools::Long nOneX = aOnePixel.Width();
1473 tools::Long nOneY = aOnePixel.Height();
1474
1475 bool bLayoutRTL = rDoc.IsLayoutRTL( nPrintTab );
1476
1477 tools::Long nWidth = static_cast<tools::Long>(PRINT_HEADER_WIDTH * nScaleX);
1478 tools::Long nEndX = nScrX + nWidth;
1479 tools::Long nPosX = nScrX;
1480 if ( !bLayoutRTL )
1481 {
1482 nEndX -= nOneX;
1483 nPosX -= nOneX;
1484 }
1485 tools::Long nPosY = nScrY - nOneY;
1486 OUString aText;
1487
1488 for (SCROW nRow=nY1; nRow<=nY2; nRow++)
1489 {
1490 sal_uInt16 nDocH = rDoc.GetRowHeight( nRow, nPrintTab );
1491 if (nDocH)
1492 {
1493 tools::Long nHeight = static_cast<tools::Long>(nDocH * nScaleY);
1494 tools::Long nEndY = nPosY + nHeight;
1495
1496 pDev->DrawRect( tools::Rectangle( nPosX,nPosY,nEndX,nEndY ) );
1497
1498 aText = OUString::number( nRow+1 );
1499 tools::Long nTextWidth = pDev->GetTextWidth(aText);
1500 tools::Long nTextHeight = pDev->GetTextHeight();
1501 tools::Long nAddX = ( nWidth - nTextWidth ) / 2;
1502 tools::Long nAddY = ( nHeight - nTextHeight ) / 2;
1503 pDev->DrawText( Point( nPosX+nAddX,nPosY+nAddY ), aText );
1504
1505 nPosY = nEndY;
1506 }
1507 }
1508 }
1509
LocateColHdr(SCCOL nX1,SCCOL nX2,tools::Long nScrX,tools::Long nScrY,bool bRepCol,ScPreviewLocationData & rLocationData)1510 void ScPrintFunc::LocateColHdr( SCCOL nX1, SCCOL nX2, tools::Long nScrX, tools::Long nScrY,
1511 bool bRepCol, ScPreviewLocationData& rLocationData )
1512 {
1513 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1514 tools::Long nOneX = aOnePixel.Width();
1515 tools::Long nOneY = aOnePixel.Height();
1516
1517 tools::Long nHeight = static_cast<tools::Long>(PRINT_HEADER_HEIGHT * nScaleY);
1518 tools::Long nEndY = nScrY + nHeight - nOneY;
1519
1520 tools::Long nPosX = nScrX - nOneX;
1521 for (SCCOL nCol=nX1; nCol<=nX2; nCol++)
1522 {
1523 sal_uInt16 nDocW = rDoc.GetColWidth( nCol, nPrintTab );
1524 if (nDocW)
1525 nPosX += static_cast<tools::Long>(nDocW * nScaleX);
1526 }
1527 tools::Rectangle aCellRect( nScrX, nScrY, nPosX, nEndY );
1528 rLocationData.AddColHeaders( aCellRect, nX1, nX2, bRepCol );
1529 }
1530
LocateRowHdr(SCROW nY1,SCROW nY2,tools::Long nScrX,tools::Long nScrY,bool bRepRow,ScPreviewLocationData & rLocationData)1531 void ScPrintFunc::LocateRowHdr( SCROW nY1, SCROW nY2, tools::Long nScrX, tools::Long nScrY,
1532 bool bRepRow, ScPreviewLocationData& rLocationData )
1533 {
1534 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1535 tools::Long nOneX = aOnePixel.Width();
1536 tools::Long nOneY = aOnePixel.Height();
1537
1538 bool bLayoutRTL = rDoc.IsLayoutRTL( nPrintTab );
1539
1540 tools::Long nWidth = static_cast<tools::Long>(PRINT_HEADER_WIDTH * nScaleX);
1541 tools::Long nEndX = nScrX + nWidth;
1542 if ( !bLayoutRTL )
1543 nEndX -= nOneX;
1544
1545 tools::Long nPosY = nScrY - nOneY;
1546 nPosY += rDoc.GetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY);
1547 tools::Rectangle aCellRect( nScrX, nScrY, nEndX, nPosY );
1548 rLocationData.AddRowHeaders( aCellRect, nY1, nY2, bRepRow );
1549 }
1550
LocateArea(SCCOL nX1,SCROW nY1,SCCOL nX2,SCROW nY2,tools::Long nScrX,tools::Long nScrY,bool bRepCol,bool bRepRow,ScPreviewLocationData & rLocationData)1551 void ScPrintFunc::LocateArea( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
1552 tools::Long nScrX, tools::Long nScrY, bool bRepCol, bool bRepRow,
1553 ScPreviewLocationData& rLocationData )
1554 {
1555 // get MapMode for drawing objects (same MapMode as in ScOutputData::PrintDrawingLayer)
1556
1557 Point aLogPos = OutputDevice::LogicToLogic(Point(nScrX,nScrY), aOffsetMode, aLogicMode);
1558 tools::Long nLogStX = aLogPos.X();
1559 tools::Long nLogStY = aLogPos.Y();
1560
1561 SCCOL nCol;
1562 Point aTwipOffset;
1563 for (nCol=0; nCol<nX1; nCol++)
1564 aTwipOffset.AdjustX( -(rDoc.GetColWidth( nCol, nPrintTab )) );
1565 aTwipOffset.AdjustY( -sal_Int32(rDoc.GetRowHeight( 0, nY1-1, nPrintTab )) );
1566
1567 Point aMMOffset( aTwipOffset );
1568 aMMOffset.setX( static_cast<tools::Long>(aMMOffset.X() * HMM_PER_TWIPS) );
1569 aMMOffset.setY( static_cast<tools::Long>(aMMOffset.Y() * HMM_PER_TWIPS) );
1570 aMMOffset += Point( nLogStX, nLogStY );
1571 MapMode aDrawMapMode( MapUnit::Map100thMM, aMMOffset, aLogicMode.GetScaleX(), aLogicMode.GetScaleY() );
1572
1573 // get pixel rectangle
1574
1575 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1576 tools::Long nOneX = aOnePixel.Width();
1577 tools::Long nOneY = aOnePixel.Height();
1578
1579 tools::Long nPosX = nScrX - nOneX;
1580 for (nCol=nX1; nCol<=nX2; nCol++)
1581 {
1582 sal_uInt16 nDocW = rDoc.GetColWidth( nCol, nPrintTab );
1583 if (nDocW)
1584 nPosX += static_cast<tools::Long>(nDocW * nScaleX);
1585 }
1586
1587 tools::Long nPosY = nScrY - nOneY;
1588 nPosY += rDoc.GetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY);
1589 tools::Rectangle aCellRect( nScrX, nScrY, nPosX, nPosY );
1590 rLocationData.AddCellRange( aCellRect, ScRange( nX1,nY1,nPrintTab, nX2,nY2,nPrintTab ),
1591 bRepCol, bRepRow, aDrawMapMode );
1592 }
1593
PrintArea(SCCOL nX1,SCROW nY1,SCCOL nX2,SCROW nY2,tools::Long nScrX,tools::Long nScrY,bool bShLeft,bool bShTop,bool bShRight,bool bShBottom)1594 void ScPrintFunc::PrintArea( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
1595 tools::Long nScrX, tools::Long nScrY,
1596 bool bShLeft, bool bShTop, bool bShRight, bool bShBottom )
1597 {
1598 // #i47547# nothing to do if the end of the print area is before the end of
1599 // the repeat columns/rows (don't use negative size for ScOutputData)
1600 if ( nX2 < nX1 || nY2 < nY1 )
1601 return;
1602
1603 //! hand over Flag at FillInfo !!!!!
1604 ScRange aERange;
1605 bool bEmbed = rDoc.IsEmbedded();
1606 if (bEmbed)
1607 {
1608 rDoc.GetEmbedded(aERange);
1609 rDoc.ResetEmbedded();
1610 }
1611
1612 Point aPos = OutputDevice::LogicToLogic(Point(nScrX,nScrY), aOffsetMode, aLogicMode);
1613 tools::Long nLogStX = aPos.X();
1614 tools::Long nLogStY = aPos.Y();
1615
1616 // Assemble data
1617
1618 ScTableInfo aTabInfo;
1619 rDoc.FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nPrintTab,
1620 nScaleX, nScaleY, true, aTableParam.bFormulas );
1621 lcl_HidePrint( aTabInfo, nX1, nX2 );
1622
1623 if (bEmbed)
1624 rDoc.SetEmbedded(aERange);
1625
1626 ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, &rDoc, nPrintTab,
1627 nScrX, nScrY, nX1, nY1, nX2, nY2, nScaleX, nScaleY );
1628
1629 aOutputData.SetDrawView( pDrawView );
1630
1631 // test if all paint parts are hidden, then a paint is not necessary at all
1632 const Point aMMOffset(aOutputData.PrePrintDrawingLayer(nLogStX, nLogStY));
1633 const bool bHideAllDrawingLayer( pDrawView && pDrawView->getHideOle() && pDrawView->getHideChart()
1634 && pDrawView->getHideDraw() && pDrawView->getHideFormControl() );
1635
1636 if(!bHideAllDrawingLayer)
1637 {
1638 pDev->SetMapMode(aLogicMode);
1639 // don's set Clipping here (Mapmode is being moved)
1640
1641 // #i72502#
1642 aOutputData.PrintDrawingLayer(SC_LAYER_BACK, aMMOffset);
1643 }
1644
1645 pDev->SetMapMode(aOffsetMode);
1646
1647 aOutputData.SetShowFormulas( aTableParam.bFormulas );
1648 aOutputData.SetShowNullValues( aTableParam.bNullVals );
1649 aOutputData.SetUseStyleColor( bUseStyleColor );
1650
1651 Color aGridColor( COL_BLACK );
1652 if ( bUseStyleColor )
1653 aGridColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor;
1654 aOutputData.SetGridColor( aGridColor );
1655
1656 if ( !pPrinter )
1657 {
1658 OutputDevice* pRefDev = rDoc.GetPrinter(); // use the printer also for Preview
1659 Fraction aPrintFrac( nZoom, 100 ); // without nManualZoom
1660 // MapMode, as it would arrive at the printer:
1661 pRefDev->SetMapMode( MapMode( MapUnit::Map100thMM, Point(), aPrintFrac, aPrintFrac ) );
1662
1663 // when rendering (PDF), don't use printer as ref device, but printer's MapMode
1664 // has to be set anyway, as charts still use it (#106409#)
1665 if ( !bIsRender )
1666 aOutputData.SetRefDevice( pRefDev );
1667 }
1668
1669 if( aTableParam.bCellContent )
1670 aOutputData.DrawBackground(*pDev);
1671
1672 pDev->SetClipRegion(vcl::Region(tools::Rectangle(
1673 aPos, Size(aOutputData.GetScrW(), aOutputData.GetScrH()))));
1674 pDev->SetClipRegion();
1675
1676 if( aTableParam.bCellContent )
1677 {
1678 aOutputData.DrawExtraShadow( bShLeft, bShTop, bShRight, bShBottom );
1679 aOutputData.DrawFrame(*pDev);
1680 aOutputData.DrawStrings();
1681 aOutputData.DrawEdit(false);
1682 }
1683
1684 if (aTableParam.bGrid)
1685 aOutputData.DrawGrid(*pDev, true, false); // no page breaks
1686
1687 aOutputData.AddPDFNotes(); // has no effect if not rendering PDF with notes enabled
1688
1689 // test if all paint parts are hidden, then a paint is not necessary at all
1690 if(!bHideAllDrawingLayer)
1691 {
1692 // #i72502#
1693 aOutputData.PrintDrawingLayer(SC_LAYER_FRONT, aMMOffset);
1694 }
1695
1696 // #i72502#
1697 aOutputData.PrintDrawingLayer(SC_LAYER_INTERN, aMMOffset);
1698 aOutputData.PostPrintDrawingLayer(aMMOffset); // #i74768#
1699 }
1700
IsMirror(tools::Long nPageNo)1701 bool ScPrintFunc::IsMirror( tools::Long nPageNo ) // Mirror margins?
1702 {
1703 return nPageUsage == SvxPageUsage::Mirror && (nPageNo & 1);
1704 }
1705
IsLeft(tools::Long nPageNo)1706 bool ScPrintFunc::IsLeft( tools::Long nPageNo ) // left foot notes?
1707 {
1708 bool bLeft;
1709 if (nPageUsage == SvxPageUsage::Left)
1710 bLeft = true;
1711 else if (nPageUsage == SvxPageUsage::Right)
1712 bLeft = false;
1713 else
1714 bLeft = (nPageNo & 1) != 0;
1715 return bLeft;
1716 }
1717
MakeTableString()1718 void ScPrintFunc::MakeTableString()
1719 {
1720 OUString aTmp;
1721 rDoc.GetName(nPrintTab, aTmp);
1722 aFieldData.aTabName = aTmp;
1723 }
1724
MakeEditEngine()1725 void ScPrintFunc::MakeEditEngine()
1726 {
1727 if (!pEditEngine)
1728 {
1729 // can't use document's edit engine pool here,
1730 // because pool must have twips as default metric
1731 pEditEngine.reset( new ScHeaderEditEngine( EditEngine::CreatePool().get() ) );
1732
1733 pEditEngine->EnableUndo(false);
1734 //fdo#45869 we want text to be positioned as it would be for the
1735 //high dpi printed output, not as would be ideal for the 96dpi preview
1736 //window itself
1737 pEditEngine->SetRefDevice(pPrinter ? pPrinter : rDoc.GetRefDevice());
1738 pEditEngine->SetWordDelimiters(
1739 ScEditUtil::ModifyDelimiters( pEditEngine->GetWordDelimiters() ) );
1740 pEditEngine->SetControlWord( pEditEngine->GetControlWord() & ~EEControlBits::RTFSTYLESHEETS );
1741 rDoc.ApplyAsianEditSettings( *pEditEngine );
1742 pEditEngine->EnableAutoColor( bUseStyleColor );
1743
1744 // Default-Set for alignment
1745 pEditDefaults.reset( new SfxItemSet( pEditEngine->GetEmptyItemSet() ) );
1746
1747 const ScPatternAttr& rPattern = rDoc.GetPool()->GetDefaultItem(ATTR_PATTERN);
1748 rPattern.FillEditItemSet( pEditDefaults.get() );
1749 // FillEditItemSet adjusts font height to 1/100th mm,
1750 // but for header/footer twips is needed, as in the PatternAttr:
1751 pEditDefaults->Put( rPattern.GetItem(ATTR_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT) );
1752 pEditDefaults->Put( rPattern.GetItem(ATTR_CJK_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT_CJK) );
1753 pEditDefaults->Put( rPattern.GetItem(ATTR_CTL_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT_CTL) );
1754 // don't use font color, because background color is not used
1755 //! there's no way to set the background for note pages
1756 pEditDefaults->ClearItem( EE_CHAR_COLOR );
1757 if (ScGlobal::IsSystemRTL())
1758 pEditDefaults->Put( SvxFrameDirectionItem( SvxFrameDirection::Horizontal_RL_TB, EE_PARA_WRITINGDIR ) );
1759 }
1760
1761 pEditEngine->SetData( aFieldData ); // Set page count etc.
1762 }
1763
1764 // nStartY = logic
PrintHF(tools::Long nPageNo,bool bHeader,tools::Long nStartY,bool bDoPrint,ScPreviewLocationData * pLocationData)1765 void ScPrintFunc::PrintHF( tools::Long nPageNo, bool bHeader, tools::Long nStartY,
1766 bool bDoPrint, ScPreviewLocationData* pLocationData )
1767 {
1768 const ScPrintHFParam& rParam = bHeader ? aHdr : aFtr;
1769
1770 pDev->SetMapMode( aTwipMode ); // Head-/Footlines in Twips
1771
1772 bool bFirst = 0 == nPageNo && !rParam.bSharedFirst;
1773 bool bLeft = IsLeft(nPageNo) && !rParam.bShared;
1774 const ScPageHFItem* pHFItem = bFirst ? rParam.pFirst : (bLeft ? rParam.pLeft : rParam.pRight);
1775
1776 tools::Long nLineStartX = aPageRect.Left() + rParam.nLeft;
1777 tools::Long nLineEndX = aPageRect.Right() - rParam.nRight;
1778 tools::Long nLineWidth = nLineEndX - nLineStartX + 1;
1779
1780 // Edit-Engine
1781
1782 Point aStart( nLineStartX, nStartY );
1783 Size aPaperSize( nLineWidth, rParam.nHeight-rParam.nDistance );
1784 if ( rParam.pBorder )
1785 {
1786 tools::Long nLeft = lcl_LineTotal( rParam.pBorder->GetLeft() ) + rParam.pBorder->GetDistance(SvxBoxItemLine::LEFT);
1787 tools::Long nTop = lcl_LineTotal( rParam.pBorder->GetTop() ) + rParam.pBorder->GetDistance(SvxBoxItemLine::TOP);
1788 aStart.AdjustX(nLeft );
1789 aStart.AdjustY(nTop );
1790 aPaperSize.AdjustWidth( -(nLeft + lcl_LineTotal( rParam.pBorder->GetRight() ) + rParam.pBorder->GetDistance(SvxBoxItemLine::RIGHT)) );
1791 aPaperSize.AdjustHeight( -(nTop + lcl_LineTotal( rParam.pBorder->GetBottom() ) + rParam.pBorder->GetDistance(SvxBoxItemLine::BOTTOM)) );
1792 }
1793
1794 if ( rParam.pShadow && rParam.pShadow->GetLocation() != SvxShadowLocation::NONE )
1795 {
1796 tools::Long nLeft = rParam.pShadow->CalcShadowSpace(SvxShadowItemSide::LEFT);
1797 tools::Long nTop = rParam.pShadow->CalcShadowSpace(SvxShadowItemSide::TOP);
1798 aStart.AdjustX(nLeft );
1799 aStart.AdjustY(nTop );
1800 aPaperSize.AdjustWidth( -(nLeft + rParam.pShadow->CalcShadowSpace(SvxShadowItemSide::RIGHT)) );
1801 aPaperSize.AdjustHeight( -(nTop + rParam.pShadow->CalcShadowSpace(SvxShadowItemSide::BOTTOM)) );
1802 }
1803
1804 aFieldData.nPageNo = nPageNo+aTableParam.nFirstPageNo;
1805 MakeEditEngine();
1806
1807 pEditEngine->SetPaperSize(aPaperSize);
1808
1809 // Frame / Background
1810
1811 Point aBorderStart( nLineStartX, nStartY );
1812 Size aBorderSize( nLineWidth, rParam.nHeight-rParam.nDistance );
1813 if ( rParam.bDynamic )
1814 {
1815 // adjust here again, for even/odd head-/footlines
1816 // and probably other breaks by variable (page number etc.)
1817
1818 tools::Long nMaxHeight = 0;
1819 nMaxHeight = std::max( nMaxHeight, TextHeight( pHFItem->GetLeftArea() ) );
1820 nMaxHeight = std::max( nMaxHeight, TextHeight( pHFItem->GetCenterArea() ) );
1821 nMaxHeight = std::max( nMaxHeight, TextHeight( pHFItem->GetRightArea() ) );
1822 if (rParam.pBorder)
1823 nMaxHeight += lcl_LineTotal( rParam.pBorder->GetTop() ) +
1824 lcl_LineTotal( rParam.pBorder->GetBottom() ) +
1825 rParam.pBorder->GetDistance(SvxBoxItemLine::TOP) +
1826 rParam.pBorder->GetDistance(SvxBoxItemLine::BOTTOM);
1827 if (rParam.pShadow && rParam.pShadow->GetLocation() != SvxShadowLocation::NONE)
1828 nMaxHeight += rParam.pShadow->CalcShadowSpace(SvxShadowItemSide::TOP) +
1829 rParam.pShadow->CalcShadowSpace(SvxShadowItemSide::BOTTOM);
1830
1831 if (nMaxHeight < rParam.nManHeight-rParam.nDistance)
1832 nMaxHeight = rParam.nManHeight-rParam.nDistance; // configured Minimum
1833
1834 aBorderSize.setHeight( nMaxHeight );
1835 }
1836
1837 if ( bDoPrint )
1838 {
1839 double nOldScaleX = nScaleX;
1840 double nOldScaleY = nScaleY;
1841 nScaleX = nScaleY = 1.0; // output directly in Twips
1842 DrawBorder( aBorderStart.X(), aBorderStart.Y(), aBorderSize.Width(), aBorderSize.Height(),
1843 rParam.pBorder, rParam.pBack, rParam.pShadow );
1844 nScaleX = nOldScaleX;
1845 nScaleY = nOldScaleY;
1846
1847 // Clipping for Text
1848
1849 pDev->SetClipRegion(vcl::Region(tools::Rectangle(aStart, aPaperSize)));
1850
1851 // left
1852
1853 const EditTextObject* pObject = pHFItem->GetLeftArea();
1854 if (pObject)
1855 {
1856 pEditDefaults->Put( SvxAdjustItem( SvxAdjust::Left, EE_PARA_JUST ) );
1857 pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, false );
1858 Point aDraw = aStart;
1859 tools::Long nDif = aPaperSize.Height() - static_cast<tools::Long>(pEditEngine->GetTextHeight());
1860 if (nDif > 0)
1861 aDraw.AdjustY(nDif / 2 );
1862 pEditEngine->Draw(*pDev, aDraw);
1863 }
1864
1865 // center
1866
1867 pObject = pHFItem->GetCenterArea();
1868 if (pObject)
1869 {
1870 pEditDefaults->Put( SvxAdjustItem( SvxAdjust::Center, EE_PARA_JUST ) );
1871 pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, false );
1872 Point aDraw = aStart;
1873 tools::Long nDif = aPaperSize.Height() - static_cast<tools::Long>(pEditEngine->GetTextHeight());
1874 if (nDif > 0)
1875 aDraw.AdjustY(nDif / 2 );
1876 pEditEngine->Draw(*pDev, aDraw);
1877 }
1878
1879 // right
1880
1881 pObject = pHFItem->GetRightArea();
1882 if (pObject)
1883 {
1884 pEditDefaults->Put( SvxAdjustItem( SvxAdjust::Right, EE_PARA_JUST ) );
1885 pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, false );
1886 Point aDraw = aStart;
1887 tools::Long nDif = aPaperSize.Height() - static_cast<tools::Long>(pEditEngine->GetTextHeight());
1888 if (nDif > 0)
1889 aDraw.AdjustY(nDif / 2 );
1890 pEditEngine->Draw(*pDev, aDraw);
1891 }
1892
1893 pDev->SetClipRegion();
1894 }
1895
1896 if ( pLocationData )
1897 {
1898 tools::Rectangle aHeaderRect( aBorderStart, aBorderSize );
1899 pLocationData->AddHeaderFooter( aHeaderRect, bHeader, bLeft );
1900 }
1901 }
1902
DoNotes(tools::Long nNoteStart,bool bDoPrint,ScPreviewLocationData * pLocationData)1903 tools::Long ScPrintFunc::DoNotes( tools::Long nNoteStart, bool bDoPrint, ScPreviewLocationData* pLocationData )
1904 {
1905 if (bDoPrint)
1906 pDev->SetMapMode(aTwipMode);
1907
1908 MakeEditEngine();
1909 pEditDefaults->Put( SvxAdjustItem( SvxAdjust::Left, EE_PARA_JUST ) );
1910 pEditEngine->SetDefaults( *pEditDefaults );
1911
1912 vcl::Font aMarkFont;
1913 ScAutoFontColorMode eColorMode = bUseStyleColor ? SC_AUTOCOL_DISPLAY : SC_AUTOCOL_PRINT;
1914 rDoc.GetPool()->GetDefaultItem(ATTR_PATTERN).GetFont( aMarkFont, eColorMode );
1915 pDev->SetFont( aMarkFont );
1916 tools::Long nMarkLen = pDev->GetTextWidth("GW99999:");
1917 // without Space-Char, because it rarely arrives there
1918
1919 Size aDataSize = aPageRect.GetSize();
1920 if ( nMarkLen > aDataSize.Width() / 2 ) // everything much too small?
1921 nMarkLen = aDataSize.Width() / 2; // split the page appropriately
1922 aDataSize.AdjustWidth( -nMarkLen );
1923
1924 pEditEngine->SetPaperSize( aDataSize );
1925 tools::Long nPosX = aPageRect.Left() + nMarkLen;
1926 tools::Long nPosY = aPageRect.Top();
1927
1928 tools::Long nCount = 0;
1929 tools::Long nSize = aNotePosList.size();
1930 bool bOk;
1931 do
1932 {
1933 bOk = false;
1934 if ( nNoteStart + nCount < nSize)
1935 {
1936 ScAddress &rPos = aNotePosList[ nNoteStart + nCount ];
1937
1938 if( const ScPostIt* pNote = rDoc.GetNote( rPos ) )
1939 {
1940 if(const EditTextObject *pEditText = pNote->GetEditTextObject())
1941 pEditEngine->SetTextCurrentDefaults(*pEditText);
1942 tools::Long nTextHeight = pEditEngine->GetTextHeight();
1943 if ( nPosY + nTextHeight < aPageRect.Bottom() )
1944 {
1945 if (bDoPrint)
1946 {
1947 pEditEngine->Draw(*pDev, Point(nPosX, nPosY));
1948
1949 OUString aMarkStr(rPos.Format(ScRefFlags::VALID, &rDoc, rDoc.GetAddressConvention()) + ":");
1950
1951 // cell position also via EditEngine, for correct positioning
1952 pEditEngine->SetTextCurrentDefaults(aMarkStr);
1953 pEditEngine->Draw(*pDev, Point(aPageRect.Left(), nPosY));
1954 }
1955
1956 if ( pLocationData )
1957 {
1958 tools::Rectangle aTextRect( Point( nPosX, nPosY ), Size( aDataSize.Width(), nTextHeight ) );
1959 pLocationData->AddNoteText( aTextRect, rPos );
1960 tools::Rectangle aMarkRect( Point( aPageRect.Left(), nPosY ), Size( nMarkLen, nTextHeight ) );
1961 pLocationData->AddNoteMark( aMarkRect, rPos );
1962 }
1963
1964 nPosY += nTextHeight;
1965 nPosY += 200; // Distance
1966 ++nCount;
1967 bOk = true;
1968 }
1969 }
1970 }
1971 }
1972 while (bOk);
1973
1974 return nCount;
1975 }
1976
PrintNotes(tools::Long nPageNo,tools::Long nNoteStart,bool bDoPrint,ScPreviewLocationData * pLocationData)1977 tools::Long ScPrintFunc::PrintNotes( tools::Long nPageNo, tools::Long nNoteStart, bool bDoPrint, ScPreviewLocationData* pLocationData )
1978 {
1979 if ( nNoteStart >= static_cast<tools::Long>(aNotePosList.size()) || !aTableParam.bNotes )
1980 return 0;
1981
1982 if ( bDoPrint && bClearWin )
1983 {
1984 //! aggregate PrintPage !!!
1985
1986 Color aBackgroundColor( COL_WHITE );
1987 if ( bUseStyleColor )
1988 aBackgroundColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
1989
1990 pDev->SetMapMode(aOffsetMode);
1991 pDev->SetLineColor();
1992 pDev->SetFillColor(aBackgroundColor);
1993 pDev->DrawRect(tools::Rectangle(Point(),
1994 Size(static_cast<tools::Long>(aPageSize.Width() * nScaleX * 100 / nZoom),
1995 static_cast<tools::Long>(aPageSize.Height() * nScaleY * 100 / nZoom))));
1996 }
1997
1998 // adjust aPageRect for left/right page
1999
2000 tools::Rectangle aTempRect( Point(), aPageSize );
2001 if (IsMirror(nPageNo))
2002 {
2003 aPageRect.SetLeft( ( aTempRect.Left() + nRightMargin ) * 100 / nZoom );
2004 aPageRect.SetRight( ( aTempRect.Right() - nLeftMargin ) * 100 / nZoom );
2005 }
2006 else
2007 {
2008 aPageRect.SetLeft( ( aTempRect.Left() + nLeftMargin ) * 100 / nZoom );
2009 aPageRect.SetRight( ( aTempRect.Right() - nRightMargin ) * 100 / nZoom );
2010 }
2011
2012 if ( pPrinter && bDoPrint )
2013 {
2014 OSL_FAIL( "StartPage does not exist anymore" );
2015 }
2016
2017 if ( bDoPrint || pLocationData )
2018 {
2019 // Head and foot lines
2020
2021 if (aHdr.bEnable)
2022 {
2023 tools::Long nHeaderY = aPageRect.Top()-aHdr.nHeight;
2024 PrintHF( nPageNo, true, nHeaderY, bDoPrint, pLocationData );
2025 }
2026 if (aFtr.bEnable)
2027 {
2028 tools::Long nFooterY = aPageRect.Bottom()+aFtr.nDistance;
2029 PrintHF( nPageNo, false, nFooterY, bDoPrint, pLocationData );
2030 }
2031 }
2032
2033 tools::Long nCount = DoNotes( nNoteStart, bDoPrint, pLocationData );
2034
2035 if ( pPrinter && bDoPrint )
2036 {
2037 OSL_FAIL( "EndPage does not exist anymore" );
2038 }
2039
2040 return nCount;
2041 }
2042
PrintPage(tools::Long nPageNo,SCCOL nX1,SCROW nY1,SCCOL nX2,SCROW nY2,bool bDoPrint,ScPreviewLocationData * pLocationData)2043 void ScPrintFunc::PrintPage( tools::Long nPageNo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
2044 bool bDoPrint, ScPreviewLocationData* pLocationData )
2045 {
2046 bool bLayoutRTL = rDoc.IsLayoutRTL( nPrintTab );
2047 tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
2048
2049 // nPageNo is the page number within all sheets of one "start page" setting
2050
2051 if ( bClearWin && bDoPrint )
2052 {
2053 // must exactly fit to painting the frame in preview.cxx !!!
2054
2055 Color aBackgroundColor( COL_WHITE );
2056 if ( bUseStyleColor )
2057 aBackgroundColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
2058
2059 pDev->SetMapMode(aOffsetMode);
2060 pDev->SetLineColor();
2061 pDev->SetFillColor(aBackgroundColor);
2062 pDev->DrawRect(tools::Rectangle(Point(),
2063 Size(static_cast<tools::Long>(aPageSize.Width() * nScaleX * 100 / nZoom),
2064 static_cast<tools::Long>(aPageSize.Height() * nScaleY * 100 / nZoom))));
2065 }
2066
2067 // adjust aPageRect for left/right page
2068
2069 tools::Rectangle aTempRect( Point(), aPageSize );
2070 if (IsMirror(nPageNo))
2071 {
2072 aPageRect.SetLeft( ( aTempRect.Left() + nRightMargin ) * 100 / nZoom );
2073 aPageRect.SetRight( ( aTempRect.Right() - nLeftMargin ) * 100 / nZoom );
2074 }
2075 else
2076 {
2077 aPageRect.SetLeft( ( aTempRect.Left() + nLeftMargin ) * 100 / nZoom );
2078 aPageRect.SetRight( ( aTempRect.Right() - nRightMargin ) * 100 / nZoom );
2079 }
2080
2081 if ( aAreaParam.bRepeatCol )
2082 if ( nX1 > nRepeatStartCol && nX1 <= nRepeatEndCol )
2083 nX1 = nRepeatEndCol + 1;
2084 bool bDoRepCol = (aAreaParam.bRepeatCol && nX1 > nRepeatEndCol);
2085 if ( aAreaParam.bRepeatRow )
2086 if ( nY1 > nRepeatStartRow && nY1 <= nRepeatEndRow )
2087 nY1 = nRepeatEndRow + 1;
2088 bool bDoRepRow = (aAreaParam.bRepeatRow && nY1 > nRepeatEndRow);
2089
2090 // use new object hide flags in SdrPaintView
2091 if(pDrawView)
2092 {
2093 pDrawView->setHideOle(!aTableParam.bObjects);
2094 pDrawView->setHideChart(!aTableParam.bCharts);
2095 pDrawView->setHideDraw(!aTableParam.bDrawings);
2096 pDrawView->setHideFormControl(!aTableParam.bDrawings);
2097 }
2098
2099 if ( pPrinter && bDoPrint )
2100 {
2101 OSL_FAIL( "StartPage does not exist anymore" );
2102 }
2103
2104 // head and foot lines (without centering)
2105
2106 if (aHdr.bEnable)
2107 {
2108 tools::Long nHeaderY = aPageRect.Top()-aHdr.nHeight;
2109 PrintHF( nPageNo, true, nHeaderY, bDoPrint, pLocationData );
2110 }
2111 if (aFtr.bEnable)
2112 {
2113 tools::Long nFooterY = aPageRect.Bottom()+aFtr.nDistance;
2114 PrintHF( nPageNo, false, nFooterY, bDoPrint, pLocationData );
2115 }
2116
2117 // Position ( margins / centering )
2118
2119 tools::Long nLeftSpace = aPageRect.Left(); // Document-Twips
2120 tools::Long nTopSpace = aPageRect.Top();
2121 if ( bCenterHor || bLayoutRTL )
2122 {
2123 tools::Long nDataWidth = 0;
2124 SCCOL i;
2125 for (i=nX1; i<=nX2; i++)
2126 nDataWidth += rDoc.GetColWidth( i,nPrintTab );
2127 if (bDoRepCol)
2128 for (i=nRepeatStartCol; i<=nRepeatEndCol; i++)
2129 nDataWidth += rDoc.GetColWidth( i,nPrintTab );
2130 if (aTableParam.bHeaders)
2131 nDataWidth += tools::Long(PRINT_HEADER_WIDTH);
2132 if (pBorderItem)
2133 nDataWidth += pBorderItem->GetDistance(SvxBoxItemLine::LEFT) +
2134 pBorderItem->GetDistance(SvxBoxItemLine::RIGHT); //! Line width?
2135 if (pShadowItem && pShadowItem->GetLocation() != SvxShadowLocation::NONE)
2136 nDataWidth += pShadowItem->CalcShadowSpace(SvxShadowItemSide::LEFT) +
2137 pShadowItem->CalcShadowSpace(SvxShadowItemSide::RIGHT);
2138 if ( bCenterHor )
2139 {
2140 nLeftSpace += ( aPageRect.GetWidth() - nDataWidth ) / 2; // LTR or RTL
2141 if (pBorderItem)
2142 nLeftSpace -= lcl_LineTotal(pBorderItem->GetLeft());
2143 }
2144 else if ( bLayoutRTL )
2145 nLeftSpace += aPageRect.GetWidth() - nDataWidth; // align to the right edge of the page
2146 }
2147 if ( bCenterVer )
2148 {
2149 tools::Long nDataHeight = rDoc.GetRowHeight( nY1, nY2, nPrintTab);
2150 if (bDoRepRow)
2151 nDataHeight += rDoc.GetRowHeight( nRepeatStartRow,
2152 nRepeatEndRow, nPrintTab);
2153 if (aTableParam.bHeaders)
2154 nDataHeight += tools::Long(PRINT_HEADER_HEIGHT);
2155 if (pBorderItem)
2156 nDataHeight += pBorderItem->GetDistance(SvxBoxItemLine::TOP) +
2157 pBorderItem->GetDistance(SvxBoxItemLine::BOTTOM); //! Line width?
2158 if (pShadowItem && pShadowItem->GetLocation() != SvxShadowLocation::NONE)
2159 nDataHeight += pShadowItem->CalcShadowSpace(SvxShadowItemSide::TOP) +
2160 pShadowItem->CalcShadowSpace(SvxShadowItemSide::BOTTOM);
2161 nTopSpace += ( aPageRect.GetHeight() - nDataHeight ) / 2;
2162 if (pBorderItem)
2163 nTopSpace -= lcl_LineTotal(pBorderItem->GetTop());
2164 }
2165
2166 // calculate sizes of the elements for partitioning
2167 // (header, repeat, data)
2168
2169 tools::Long nHeaderWidth = 0;
2170 tools::Long nHeaderHeight = 0;
2171 tools::Long nRepeatWidth = 0;
2172 tools::Long nRepeatHeight = 0;
2173 tools::Long nContentWidth = 0; // scaled - not the same as nDataWidth above
2174 tools::Long nContentHeight = 0;
2175 if (aTableParam.bHeaders)
2176 {
2177 nHeaderWidth = static_cast<tools::Long>(PRINT_HEADER_WIDTH * nScaleX);
2178 nHeaderHeight = static_cast<tools::Long>(PRINT_HEADER_HEIGHT * nScaleY);
2179 }
2180 if (bDoRepCol)
2181 for (SCCOL i=nRepeatStartCol; i<=nRepeatEndCol; i++)
2182 nRepeatWidth += static_cast<tools::Long>(rDoc.GetColWidth(i,nPrintTab) * nScaleX);
2183 if (bDoRepRow)
2184 nRepeatHeight += rDoc.GetScaledRowHeight( nRepeatStartRow,
2185 nRepeatEndRow, nPrintTab, nScaleY);
2186 for (SCCOL i=nX1; i<=nX2; i++)
2187 nContentWidth += static_cast<tools::Long>(rDoc.GetColWidth(i,nPrintTab) * nScaleX);
2188 nContentHeight += rDoc.GetScaledRowHeight( nY1, nY2, nPrintTab,
2189 nScaleY);
2190
2191 // partition the page
2192
2193 tools::Long nStartX = static_cast<tools::Long>( nLeftSpace * nScaleX );
2194 tools::Long nStartY = static_cast<tools::Long>( nTopSpace * nScaleY );
2195 tools::Long nInnerStartX = nStartX;
2196 tools::Long nInnerStartY = nStartY;
2197 if (pBorderItem)
2198 {
2199 nInnerStartX += static_cast<tools::Long>( ( lcl_LineTotal(pBorderItem->GetLeft()) +
2200 pBorderItem->GetDistance(SvxBoxItemLine::LEFT) ) * nScaleX );
2201 nInnerStartY += static_cast<tools::Long>( ( lcl_LineTotal(pBorderItem->GetTop()) +
2202 pBorderItem->GetDistance(SvxBoxItemLine::TOP) ) * nScaleY );
2203 }
2204 if (pShadowItem && pShadowItem->GetLocation() != SvxShadowLocation::NONE)
2205 {
2206 nInnerStartX += static_cast<tools::Long>( pShadowItem->CalcShadowSpace(SvxShadowItemSide::LEFT) * nScaleX );
2207 nInnerStartY += static_cast<tools::Long>( pShadowItem->CalcShadowSpace(SvxShadowItemSide::TOP) * nScaleY );
2208 }
2209
2210 if ( bLayoutRTL )
2211 {
2212 // arrange elements starting from the right edge
2213 nInnerStartX += nHeaderWidth + nRepeatWidth + nContentWidth;
2214
2215 // make rounding easier so the elements are really next to each other in preview
2216 Size aOffsetOnePixel = pDev->PixelToLogic( Size(1,1), aOffsetMode );
2217 tools::Long nOffsetOneX = aOffsetOnePixel.Width();
2218 nInnerStartX += nOffsetOneX / 2;
2219 }
2220
2221 tools::Long nFrameStartX = nInnerStartX;
2222 tools::Long nFrameStartY = nInnerStartY;
2223
2224 tools::Long nRepStartX = nInnerStartX + nHeaderWidth * nLayoutSign; // widths/heights are 0 if not used
2225 tools::Long nRepStartY = nInnerStartY + nHeaderHeight;
2226 tools::Long nDataX = nRepStartX + nRepeatWidth * nLayoutSign;
2227 tools::Long nDataY = nRepStartY + nRepeatHeight;
2228 tools::Long nEndX = nDataX + nContentWidth * nLayoutSign;
2229 tools::Long nEndY = nDataY + nContentHeight;
2230 tools::Long nFrameEndX = nEndX;
2231 tools::Long nFrameEndY = nEndY;
2232
2233 if ( bLayoutRTL )
2234 {
2235 // each element's start position is its left edge
2236 //! subtract one pixel less?
2237 nInnerStartX -= nHeaderWidth; // used for header
2238 nRepStartX -= nRepeatWidth;
2239 nDataX -= nContentWidth;
2240
2241 // continue right of the main elements again
2242 nEndX += nHeaderWidth + nRepeatWidth + nContentWidth;
2243 }
2244
2245 // Page frame / background
2246
2247 //! adjust nEndX/Y
2248
2249 tools::Long nBorderEndX = nEndX;
2250 tools::Long nBorderEndY = nEndY;
2251 if (pBorderItem)
2252 {
2253 nBorderEndX += static_cast<tools::Long>( ( lcl_LineTotal(pBorderItem->GetRight()) +
2254 pBorderItem->GetDistance(SvxBoxItemLine::RIGHT) ) * nScaleX );
2255 nBorderEndY += static_cast<tools::Long>( ( lcl_LineTotal(pBorderItem->GetBottom()) +
2256 pBorderItem->GetDistance(SvxBoxItemLine::BOTTOM) ) * nScaleY );
2257 }
2258 if (pShadowItem && pShadowItem->GetLocation() != SvxShadowLocation::NONE)
2259 {
2260 nBorderEndX += static_cast<tools::Long>( pShadowItem->CalcShadowSpace(SvxShadowItemSide::RIGHT) * nScaleX );
2261 nBorderEndY += static_cast<tools::Long>( pShadowItem->CalcShadowSpace(SvxShadowItemSide::BOTTOM) * nScaleY );
2262 }
2263
2264 if ( bDoPrint )
2265 {
2266 pDev->SetMapMode( aOffsetMode );
2267 DrawBorder( nStartX, nStartY, nBorderEndX-nStartX, nBorderEndY-nStartY,
2268 pBorderItem, pBackgroundItem, pShadowItem );
2269
2270 pDev->SetMapMode( aTwipMode );
2271 }
2272
2273 pDev->SetMapMode( aOffsetMode );
2274
2275 // Output repeating rows/columns
2276
2277 if (bDoRepCol && bDoRepRow)
2278 {
2279 if ( bDoPrint )
2280 PrintArea( nRepeatStartCol,nRepeatStartRow, nRepeatEndCol,nRepeatEndRow,
2281 nRepStartX,nRepStartY, true, true, false, false );
2282 if ( pLocationData )
2283 LocateArea( nRepeatStartCol,nRepeatStartRow, nRepeatEndCol,nRepeatEndRow,
2284 nRepStartX,nRepStartY, true, true, *pLocationData );
2285 }
2286 if (bDoRepCol)
2287 {
2288 if ( bDoPrint )
2289 PrintArea( nRepeatStartCol,nY1, nRepeatEndCol,nY2, nRepStartX,nDataY,
2290 true, !bDoRepRow, false, true );
2291 if ( pLocationData )
2292 LocateArea( nRepeatStartCol,nY1, nRepeatEndCol,nY2, nRepStartX,nDataY, true, false, *pLocationData );
2293 }
2294 if (bDoRepRow)
2295 {
2296 if ( bDoPrint )
2297 PrintArea( nX1,nRepeatStartRow, nX2,nRepeatEndRow, nDataX,nRepStartY,
2298 !bDoRepCol, true, true, false );
2299 if ( pLocationData )
2300 LocateArea( nX1,nRepeatStartRow, nX2,nRepeatEndRow, nDataX,nRepStartY, false, true, *pLocationData );
2301 }
2302
2303 // output data
2304
2305 if ( bDoPrint )
2306 PrintArea( nX1,nY1, nX2,nY2, nDataX,nDataY, !bDoRepCol,!bDoRepRow, true, true );
2307 if ( pLocationData )
2308 LocateArea( nX1,nY1, nX2,nY2, nDataX,nDataY, false,false, *pLocationData );
2309
2310 // output column/row headers
2311 // after data (through probably shadow)
2312
2313 Color aGridColor( COL_BLACK );
2314 if ( bUseStyleColor )
2315 aGridColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor;
2316
2317 if (aTableParam.bHeaders)
2318 {
2319 if ( bDoPrint )
2320 {
2321 pDev->SetLineColor( aGridColor );
2322 pDev->SetFillColor();
2323 pDev->SetMapMode(aOffsetMode);
2324 }
2325
2326 ScPatternAttr aPattern( rDoc.GetPool() );
2327 vcl::Font aFont;
2328 ScAutoFontColorMode eColorMode = bUseStyleColor ? SC_AUTOCOL_DISPLAY : SC_AUTOCOL_PRINT;
2329 aPattern.GetFont( aFont, eColorMode, pDev );
2330 pDev->SetFont( aFont );
2331
2332 if (bDoRepCol)
2333 {
2334 if ( bDoPrint )
2335 PrintColHdr( nRepeatStartCol,nRepeatEndCol, nRepStartX,nInnerStartY );
2336 if ( pLocationData )
2337 LocateColHdr( nRepeatStartCol,nRepeatEndCol, nRepStartX,nInnerStartY, true, *pLocationData );
2338 }
2339 if ( bDoPrint )
2340 PrintColHdr( nX1,nX2, nDataX,nInnerStartY );
2341 if ( pLocationData )
2342 LocateColHdr( nX1,nX2, nDataX,nInnerStartY, false, *pLocationData );
2343 if (bDoRepRow)
2344 {
2345 if ( bDoPrint )
2346 PrintRowHdr( nRepeatStartRow,nRepeatEndRow, nInnerStartX,nRepStartY );
2347 if ( pLocationData )
2348 LocateRowHdr( nRepeatStartRow,nRepeatEndRow, nInnerStartX,nRepStartY, true, *pLocationData );
2349 }
2350 if ( bDoPrint )
2351 PrintRowHdr( nY1,nY2, nInnerStartX,nDataY );
2352 if ( pLocationData )
2353 LocateRowHdr( nY1,nY2, nInnerStartX,nDataY, false, *pLocationData );
2354 }
2355
2356 // simple frame
2357
2358 if ( bDoPrint && ( aTableParam.bGrid || aTableParam.bHeaders ) )
2359 {
2360 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
2361 tools::Long nOneX = aOnePixel.Width();
2362 tools::Long nOneY = aOnePixel.Height();
2363
2364 tools::Long nLeftX = nFrameStartX;
2365 tools::Long nTopY = nFrameStartY - nOneY;
2366 tools::Long nRightX = nFrameEndX;
2367 tools::Long nBottomY = nFrameEndY - nOneY;
2368 if ( !bLayoutRTL )
2369 {
2370 nLeftX -= nOneX;
2371 nRightX -= nOneX;
2372 }
2373 pDev->SetMapMode(aOffsetMode);
2374 pDev->SetLineColor( aGridColor );
2375 pDev->SetFillColor();
2376 pDev->DrawRect( tools::Rectangle( nLeftX, nTopY, nRightX, nBottomY ) );
2377 // nEndX/Y without frame-adaptation
2378 }
2379
2380 if ( pPrinter && bDoPrint )
2381 {
2382 OSL_FAIL( "EndPage does not exist anymore" );
2383 }
2384
2385 aLastSourceRange = ScRange( nX1, nY1, nPrintTab, nX2, nY2, nPrintTab );
2386 bSourceRangeValid = true;
2387 }
2388
SetOffset(const Point & rOfs)2389 void ScPrintFunc::SetOffset( const Point& rOfs )
2390 {
2391 aSrcOffset = rOfs;
2392 }
2393
SetManualZoom(sal_uInt16 nNewZoom)2394 void ScPrintFunc::SetManualZoom( sal_uInt16 nNewZoom )
2395 {
2396 nManualZoom = nNewZoom;
2397 }
2398
SetClearFlag(bool bFlag)2399 void ScPrintFunc::SetClearFlag( bool bFlag )
2400 {
2401 bClearWin = bFlag;
2402 }
2403
SetUseStyleColor(bool bFlag)2404 void ScPrintFunc::SetUseStyleColor( bool bFlag )
2405 {
2406 bUseStyleColor = bFlag;
2407 if (pEditEngine)
2408 pEditEngine->EnableAutoColor( bUseStyleColor );
2409 }
2410
SetRenderFlag(bool bFlag)2411 void ScPrintFunc::SetRenderFlag( bool bFlag )
2412 {
2413 bIsRender = bFlag; // set when using XRenderable (PDF)
2414 }
2415
SetExclusivelyDrawOleAndDrawObjects()2416 void ScPrintFunc::SetExclusivelyDrawOleAndDrawObjects()
2417 {
2418 aTableParam.bCellContent = false;
2419 aTableParam.bNotes = false;
2420 aTableParam.bGrid = false;
2421 aTableParam.bHeaders = false;
2422 aTableParam.bFormulas = false;
2423 aTableParam.bNullVals = false;
2424 }
2425
2426 // UpdatePages is only called from outside to set the breaks correctly for viewing
2427 // - always without UserArea
2428
UpdatePages()2429 bool ScPrintFunc::UpdatePages()
2430 {
2431 if (!pParamSet)
2432 return false;
2433
2434 // Zoom
2435
2436 nZoom = 100;
2437 if (aTableParam.bScalePageNum || aTableParam.bScaleTo)
2438 nZoom = ZOOM_MIN; // correct for breaks
2439 else if (aTableParam.bScaleAll)
2440 {
2441 nZoom = aTableParam.nScaleAll;
2442 if ( nZoom <= ZOOM_MIN )
2443 nZoom = ZOOM_MIN;
2444 }
2445
2446 OUString aName = rDoc.GetPageStyle( nPrintTab );
2447 SCTAB nTabCount = rDoc.GetTableCount();
2448 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
2449 if ( nTab==nPrintTab || rDoc.GetPageStyle(nTab)==aName )
2450 {
2451 // Repeating rows/columns
2452 rDoc.SetRepeatArea( nTab, nRepeatStartCol,nRepeatEndCol, nRepeatStartRow,nRepeatEndRow );
2453
2454 // set breaks
2455 ResetBreaks(nTab);
2456 pDocShell->PostPaint(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab, PaintPartFlags::Grid);
2457 }
2458
2459 return true;
2460 }
2461
CountPages()2462 tools::Long ScPrintFunc::CountPages() // sets also nPagesX, nPagesY
2463 {
2464 bool bAreaOk = false;
2465
2466 if (rDoc.HasTable( nPrintTab ))
2467 {
2468 if (aAreaParam.bPrintArea) // Specify print area?
2469 {
2470 if ( bPrintCurrentTable )
2471 {
2472 ScRange& rRange = aAreaParam.aPrintArea;
2473
2474 // Here, no comparison of the tables any more. Area is always valid for this table
2475 // If comparison should be done here, the table of print ranges must be adjusted
2476 // when inserting tables etc.!
2477
2478 nStartCol = rRange.aStart.Col();
2479 nStartRow = rRange.aStart.Row();
2480 nEndCol = rRange.aEnd .Col();
2481 nEndRow = rRange.aEnd .Row();
2482 bAreaOk = AdjustPrintArea(false); // limit
2483 }
2484 else
2485 bAreaOk = false;
2486 }
2487 else // search from document
2488 bAreaOk = AdjustPrintArea(true);
2489 }
2490
2491 if (bAreaOk)
2492 {
2493 tools::Long nPages = 0;
2494 size_t nY;
2495 if (bMultiArea)
2496 {
2497 sal_uInt16 nRCount = rDoc.GetPrintRangeCount( nPrintTab );
2498 for (sal_uInt16 i=0; i<nRCount; i++)
2499 {
2500 CalcZoom(i);
2501 if ( aTableParam.bSkipEmpty )
2502 for (nY=0; nY< m_aRanges.m_nPagesY; nY++)
2503 nPages += (*m_aRanges.m_xPageRows)[nY].CountVisible();
2504 else
2505 nPages += static_cast<tools::Long>(m_aRanges.m_nPagesX) * m_aRanges.m_nPagesY;
2506 if ( pPageData )
2507 FillPageData();
2508 }
2509 }
2510 else
2511 {
2512 CalcZoom(RANGENO_NORANGE); // calculate Zoom
2513 if ( aTableParam.bSkipEmpty )
2514 for (nY=0; nY<m_aRanges.m_nPagesY; nY++)
2515 nPages += (*m_aRanges.m_xPageRows)[nY].CountVisible();
2516 else
2517 nPages += static_cast<tools::Long>(m_aRanges.m_nPagesX) * m_aRanges.m_nPagesY;
2518 if ( pPageData )
2519 FillPageData();
2520 }
2521 return nPages;
2522 }
2523 else
2524 {
2525 m_aRanges.m_nPagesX = m_aRanges.m_nPagesY = m_aRanges.m_nTotalY = 0;
2526 return 0;
2527 }
2528 }
2529
CountNotePages()2530 tools::Long ScPrintFunc::CountNotePages()
2531 {
2532 if ( !aTableParam.bNotes || !bPrintCurrentTable )
2533 return 0;
2534
2535 bool bError = false;
2536 if (!aAreaParam.bPrintArea)
2537 bError = !AdjustPrintArea(true); // completely search in Doc
2538
2539 sal_uInt16 nRepeats = 1; // how often go through it ?
2540 if (bMultiArea)
2541 nRepeats = rDoc.GetPrintRangeCount(nPrintTab);
2542 if (bError)
2543 nRepeats = 0;
2544
2545 for (sal_uInt16 nStep=0; nStep<nRepeats; nStep++)
2546 {
2547 bool bDoThis = true;
2548 if (bMultiArea) // go through all Areas
2549 {
2550 const ScRange* pThisRange = rDoc.GetPrintRange( nPrintTab, nStep );
2551 if ( pThisRange )
2552 {
2553 nStartCol = pThisRange->aStart.Col();
2554 nStartRow = pThisRange->aStart.Row();
2555 nEndCol = pThisRange->aEnd .Col();
2556 nEndRow = pThisRange->aEnd .Row();
2557 bDoThis = AdjustPrintArea(false);
2558 }
2559 }
2560
2561 if (bDoThis)
2562 {
2563 assert( bPrintAreaValid );
2564 for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
2565 {
2566 if (rDoc.HasColNotes(nCol, nPrintTab))
2567 {
2568 for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow )
2569 {
2570 if ( rDoc.HasNote(nCol, nRow, nPrintTab) )
2571 aNotePosList.emplace_back( nCol, nRow, nPrintTab );
2572 }
2573 }
2574 }
2575 }
2576 }
2577
2578 tools::Long nPages = 0;
2579 tools::Long nNoteNr = 0;
2580 tools::Long nNoteAdd;
2581 do
2582 {
2583 nNoteAdd = PrintNotes( nPages, nNoteNr, false, nullptr );
2584 if (nNoteAdd)
2585 {
2586 nNoteNr += nNoteAdd;
2587 ++nPages;
2588 }
2589 }
2590 while (nNoteAdd);
2591
2592 return nPages;
2593 }
2594
InitModes()2595 void ScPrintFunc::InitModes() // set MapModes from nZoom etc.
2596 {
2597 aOffset = Point( aSrcOffset.X()*100/nZoom, aSrcOffset.Y()*100/nZoom );
2598
2599 tools::Long nEffZoom = nZoom * static_cast<tools::Long>(nManualZoom);
2600 nScaleX = nScaleY = HMM_PER_TWIPS; // output in 1/100 mm
2601
2602 Fraction aZoomFract( nEffZoom,10000 );
2603 Fraction aHorFract = aZoomFract;
2604
2605 if ( !pPrinter && !bIsRender ) // adjust scale for preview
2606 {
2607 double nFact = pDocShell->GetOutputFactor();
2608 aHorFract = Fraction( static_cast<tools::Long>( nEffZoom / nFact ), 10000 );
2609 }
2610
2611 aLogicMode = MapMode( MapUnit::Map100thMM, Point(), aHorFract, aZoomFract );
2612
2613 Point aLogicOfs( -aOffset.X(), -aOffset.Y() );
2614 aOffsetMode = MapMode( MapUnit::Map100thMM, aLogicOfs, aHorFract, aZoomFract );
2615
2616 Point aTwipsOfs( static_cast<tools::Long>( -aOffset.X() / nScaleX + 0.5 ), static_cast<tools::Long>( -aOffset.Y() / nScaleY + 0.5 ) );
2617 aTwipMode = MapMode( MapUnit::MapTwip, aTwipsOfs, aHorFract, aZoomFract );
2618 }
2619
ApplyPrintSettings()2620 void ScPrintFunc::ApplyPrintSettings()
2621 {
2622 if ( !pPrinter )
2623 return;
2624
2625 // Configure Printer to Printing
2626
2627 Size aEnumSize = aPageSize;
2628
2629 pPrinter->SetOrientation( bLandscape ? Orientation::Landscape : Orientation::Portrait );
2630 if ( bLandscape )
2631 {
2632 // landscape is always interpreted as a rotation by 90 degrees !
2633 // this leads to non WYSIWIG but at least it prints!
2634 // #i21775#
2635 tools::Long nTemp = aEnumSize.Width();
2636 aEnumSize.setWidth( aEnumSize.Height() );
2637 aEnumSize.setHeight( nTemp );
2638 }
2639 Paper ePaper = SvxPaperInfo::GetSvxPaper( aEnumSize, MapUnit::MapTwip );
2640 sal_uInt16 nPaperBin = pParamSet->Get(ATTR_PAGE_PAPERBIN).GetValue();
2641
2642 pPrinter->SetPaper( ePaper );
2643 if ( PAPER_USER == ePaper )
2644 {
2645 MapMode aPrinterMode = pPrinter->GetMapMode();
2646 MapMode aLocalMode( MapUnit::MapTwip );
2647 pPrinter->SetMapMode( aLocalMode );
2648 pPrinter->SetPaperSizeUser( aEnumSize );
2649 pPrinter->SetMapMode( aPrinterMode );
2650 }
2651
2652 pPrinter->SetPaperBin( nPaperBin );
2653 }
2654
2655 // rPageRanges = range for all tables
2656 // nStartPage = rPageRanges starts at nStartPage
2657 // nDisplayStart = continuous number for displaying the page number
2658
DoPrint(const MultiSelection & rPageRanges,tools::Long nStartPage,tools::Long nDisplayStart,bool bDoPrint,ScPreviewLocationData * pLocationData)2659 tools::Long ScPrintFunc::DoPrint( const MultiSelection& rPageRanges,
2660 tools::Long nStartPage, tools::Long nDisplayStart, bool bDoPrint,
2661 ScPreviewLocationData* pLocationData )
2662 {
2663 OSL_ENSURE(pDev,"Device == NULL");
2664 if (!pParamSet)
2665 return 0;
2666
2667 if ( pPrinter && bDoPrint )
2668 ApplyPrintSettings();
2669
2670 InitModes();
2671 if ( pLocationData )
2672 {
2673 pLocationData->SetCellMapMode( aOffsetMode );
2674 pLocationData->SetPrintTab( nPrintTab );
2675 }
2676
2677 MakeTableString();
2678
2679 tools::Long nPageNo = 0;
2680 tools::Long nPrinted = 0;
2681 tools::Long nEndPage = rPageRanges.GetTotalRange().Max();
2682
2683 sal_uInt16 nRepeats = 1;
2684 if (bMultiArea)
2685 nRepeats = rDoc.GetPrintRangeCount(nPrintTab);
2686 for (sal_uInt16 nStep=0; nStep<nRepeats; nStep++)
2687 {
2688 if (bMultiArea) // replace area
2689 {
2690 CalcZoom(nStep); // also sets nStartCol etc. new
2691 InitModes();
2692 }
2693
2694 SCCOL nX1;
2695 SCROW nY1;
2696 SCCOL nX2;
2697 SCROW nY2;
2698 size_t nCountX;
2699 size_t nCountY;
2700
2701 if (aTableParam.bTopDown) // top-bottom
2702 {
2703 nX1 = nStartCol;
2704 for (nCountX=0; nCountX<m_aRanges.m_nPagesX; nCountX++)
2705 {
2706 OSL_ENSURE(nCountX < m_aRanges.m_xPageEndX->size(), "vector access error for aPageEndX (!)");
2707 nX2 = (*m_aRanges.m_xPageEndX)[nCountX];
2708 for (nCountY=0; nCountY<m_aRanges.m_nPagesY; nCountY++)
2709 {
2710 auto& rPageRow = (*m_aRanges.m_xPageRows)[nCountY];
2711 nY1 = rPageRow.GetStartRow();
2712 nY2 = rPageRow.GetEndRow();
2713 if ( !aTableParam.bSkipEmpty || !rPageRow.IsHidden(nCountX) )
2714 {
2715 if ( rPageRanges.IsSelected( nPageNo+nStartPage+1 ) )
2716 {
2717 PrintPage( nPageNo+nDisplayStart, nX1, nY1, nX2, nY2,
2718 bDoPrint, pLocationData );
2719 ++nPrinted;
2720 }
2721 ++nPageNo;
2722 }
2723 }
2724 nX1 = nX2 + 1;
2725 }
2726 }
2727 else // left to right
2728 {
2729 for (nCountY=0; nCountY<m_aRanges.m_nPagesY; nCountY++)
2730 {
2731 auto& rPageRow = (*m_aRanges.m_xPageRows)[nCountY];
2732 nY1 = rPageRow.GetStartRow();
2733 nY2 = rPageRow.GetEndRow();
2734 nX1 = nStartCol;
2735 for (nCountX=0; nCountX<m_aRanges.m_nPagesX; nCountX++)
2736 {
2737 OSL_ENSURE(nCountX < m_aRanges.m_xPageEndX->size(), "vector access error for aPageEndX");
2738 nX2 = (*m_aRanges.m_xPageEndX)[nCountX];
2739 if ( !aTableParam.bSkipEmpty || !rPageRow.IsHidden(nCountX) )
2740 {
2741 if ( rPageRanges.IsSelected( nPageNo+nStartPage+1 ) )
2742 {
2743 PrintPage( nPageNo+nDisplayStart, nX1, nY1, nX2, nY2,
2744 bDoPrint, pLocationData );
2745 ++nPrinted;
2746 }
2747 ++nPageNo;
2748 }
2749 nX1 = nX2 + 1;
2750 }
2751 }
2752 }
2753 }
2754
2755 aFieldData.aTabName = ScResId( STR_NOTES );
2756
2757 tools::Long nNoteNr = 0;
2758 tools::Long nNoteAdd;
2759 do
2760 {
2761 if ( nPageNo+nStartPage <= nEndPage )
2762 {
2763 bool bPageSelected = rPageRanges.IsSelected( nPageNo+nStartPage+1 );
2764 nNoteAdd = PrintNotes( nPageNo+nStartPage, nNoteNr, bDoPrint && bPageSelected,
2765 ( bPageSelected ? pLocationData : nullptr ) );
2766 if ( nNoteAdd )
2767 {
2768 nNoteNr += nNoteAdd;
2769 if (bPageSelected)
2770 {
2771 ++nPrinted;
2772 bSourceRangeValid = false; // last page was no cell range
2773 }
2774 ++nPageNo;
2775 }
2776 }
2777 else
2778 nNoteAdd = 0;
2779 }
2780 while (nNoteAdd);
2781
2782 if ( bMultiArea )
2783 ResetBreaks(nPrintTab); //breaks correct for displaying
2784
2785 return nPrinted;
2786 }
2787
CalcZoom(sal_uInt16 nRangeNo)2788 void ScPrintFunc::CalcZoom( sal_uInt16 nRangeNo ) // calculate zoom
2789 {
2790 sal_uInt16 nRCount = rDoc.GetPrintRangeCount( nPrintTab );
2791 const ScRange* pThisRange = nullptr;
2792 if (nRangeNo != RANGENO_NORANGE && nRangeNo < nRCount)
2793 pThisRange = rDoc.GetPrintRange( nPrintTab, nRangeNo );
2794 if ( pThisRange )
2795 {
2796 nStartCol = pThisRange->aStart.Col();
2797 nStartRow = pThisRange->aStart.Row();
2798 nEndCol = pThisRange->aEnd .Col();
2799 nEndRow = pThisRange->aEnd .Row();
2800 }
2801
2802 if (!AdjustPrintArea(false)) // empty
2803 {
2804 nZoom = 100;
2805 m_aRanges.m_nPagesX = m_aRanges.m_nPagesY = m_aRanges.m_nTotalY = 0;
2806 return;
2807 }
2808
2809 rDoc.SetRepeatArea( nPrintTab, nRepeatStartCol,nRepeatEndCol, nRepeatStartRow,nRepeatEndRow );
2810
2811 if (aTableParam.bScalePageNum)
2812 {
2813 nZoom = 100;
2814 sal_uInt16 nPagesToFit = aTableParam.nScalePageNum;
2815
2816 // If manual breaks are forced, calculate minimum # pages required
2817 if (aTableParam.bForceBreaks)
2818 {
2819 sal_uInt16 nMinPages = 0;
2820 std::set<SCROW> aRowBreaks;
2821 std::set<SCCOL> aColBreaks;
2822 rDoc.GetAllRowBreaks(aRowBreaks, nPrintTab, false, true);
2823 rDoc.GetAllColBreaks(aColBreaks, nPrintTab, false, true);
2824 nMinPages = (aRowBreaks.size() + 1) * (aColBreaks.size() + 1);
2825
2826 // #i54993# use min forced by breaks if it's > # pages in
2827 // scale parameter to avoid bottoming out at <= ZOOM_MIN
2828 nPagesToFit = std::max(nMinPages, nPagesToFit);
2829 }
2830
2831 sal_uInt16 nLastFitZoom = 0, nLastNonFitZoom = 0;
2832 while (true)
2833 {
2834 if (nZoom <= ZOOM_MIN)
2835 break;
2836
2837 CalcPages();
2838 bool bFitsPage = (m_aRanges.m_nPagesX * m_aRanges.m_nPagesY <= nPagesToFit);
2839
2840 if (bFitsPage)
2841 {
2842 if (nZoom == 100)
2843 // If it fits at 100%, it's good enough for me.
2844 break;
2845
2846 nLastFitZoom = nZoom;
2847 nZoom = (nLastNonFitZoom + nZoom) / 2;
2848
2849 if (nLastFitZoom == nZoom)
2850 // It converged. Use this zoom level.
2851 break;
2852 }
2853 else
2854 {
2855 if (nZoom - nLastFitZoom <= 1)
2856 {
2857 nZoom = nLastFitZoom;
2858 CalcPages();
2859 break;
2860 }
2861
2862 nLastNonFitZoom = nZoom;
2863 nZoom = (nLastFitZoom + nZoom) / 2;
2864 }
2865 }
2866 }
2867 else if (aTableParam.bScaleTo)
2868 {
2869 nZoom = 100;
2870 sal_uInt16 nW = aTableParam.nScaleWidth;
2871 sal_uInt16 nH = aTableParam.nScaleHeight;
2872
2873 // If manual breaks are forced, calculate minimum # pages required
2874 if (aTableParam.bForceBreaks)
2875 {
2876 sal_uInt16 nMinPagesW = 0, nMinPagesH = 0;
2877 std::set<SCROW> aRowBreaks;
2878 std::set<SCCOL> aColBreaks;
2879 rDoc.GetAllRowBreaks(aRowBreaks, nPrintTab, false, true);
2880 rDoc.GetAllColBreaks(aColBreaks, nPrintTab, false, true);
2881 nMinPagesW = aColBreaks.size() + 1;
2882 nMinPagesH = aRowBreaks.size() + 1;
2883
2884 // #i54993# use min forced by breaks if it's > # pages in
2885 // scale parameters to avoid bottoming out at <= ZOOM_MIN
2886 nW = std::max(nMinPagesW, nW);
2887 nH = std::max(nMinPagesH, nH);
2888 }
2889
2890 sal_uInt16 nLastFitZoom = 0, nLastNonFitZoom = 0;
2891 while (true)
2892 {
2893 if (nZoom <= ZOOM_MIN)
2894 break;
2895
2896 CalcPages();
2897 bool bFitsPage = ((!nW || (m_aRanges.m_nPagesX <= nW)) && (!nH || (m_aRanges.m_nPagesY <= nH)));
2898
2899 if (bFitsPage)
2900 {
2901 if (nZoom == 100)
2902 // If it fits at 100%, it's good enough for me.
2903 break;
2904
2905 nLastFitZoom = nZoom;
2906 nZoom = (nLastNonFitZoom + nZoom) / 2;
2907
2908 if (nLastFitZoom == nZoom)
2909 // It converged. Use this zoom level.
2910 break;
2911 }
2912 else
2913 {
2914 if (nZoom - nLastFitZoom <= 1)
2915 {
2916 nZoom = nLastFitZoom;
2917 CalcPages();
2918 break;
2919 }
2920
2921 nLastNonFitZoom = nZoom;
2922 nZoom = (nLastFitZoom + nZoom) / 2;
2923 }
2924 }
2925 // tdf#103516 remove the almost blank page(s) for better
2926 // interoperability by using slightly smaller zoom
2927 if (nW > 0 && nH == 0 && m_aRanges.m_nPagesY > 1)
2928 {
2929 sal_uInt32 nLastPagesY = m_aRanges.m_nPagesY;
2930 nLastFitZoom = nZoom;
2931 nZoom *= 0.98;
2932 if (nZoom < nLastFitZoom)
2933 {
2934 CalcPages();
2935 // same page count with smaller zoom: use the original zoom
2936 if (m_aRanges.m_nPagesY == nLastPagesY)
2937 {
2938 nZoom = nLastFitZoom;
2939 CalcPages();
2940 }
2941 }
2942 }
2943 }
2944 else if (aTableParam.bScaleAll)
2945 {
2946 nZoom = aTableParam.nScaleAll;
2947 if ( nZoom <= ZOOM_MIN )
2948 nZoom = ZOOM_MIN;
2949 CalcPages();
2950 }
2951 else
2952 {
2953 OSL_ENSURE( aTableParam.bScaleNone, "no scale flag is set" );
2954 nZoom = 100;
2955 CalcPages();
2956 }
2957 }
2958
GetDocPageSize()2959 Size ScPrintFunc::GetDocPageSize()
2960 {
2961 // Adjust height of head/foot line
2962
2963 InitModes(); // initialize aTwipMode from nZoom
2964 pDev->SetMapMode( aTwipMode ); // head/foot line in Twips
2965 UpdateHFHeight( aHdr );
2966 UpdateHFHeight( aFtr );
2967
2968 // Page size in Document-Twips
2969 // Calculating Left / Right also in PrintPage
2970
2971 aPageRect = tools::Rectangle( Point(), aPageSize );
2972 aPageRect.SetLeft( ( aPageRect.Left() + nLeftMargin ) * 100 / nZoom );
2973 aPageRect.SetRight( ( aPageRect.Right() - nRightMargin ) * 100 / nZoom );
2974 aPageRect.SetTop( ( aPageRect.Top() + nTopMargin ) * 100 / nZoom + aHdr.nHeight );
2975 aPageRect.SetBottom( ( aPageRect.Bottom() - nBottomMargin ) * 100 / nZoom - aFtr.nHeight );
2976
2977 Size aDocPageSize = aPageRect.GetSize();
2978 if (aTableParam.bHeaders)
2979 {
2980 aDocPageSize.AdjustWidth( -(tools::Long(PRINT_HEADER_WIDTH)) );
2981 aDocPageSize.AdjustHeight( -(tools::Long(PRINT_HEADER_HEIGHT)) );
2982 }
2983 if (pBorderItem)
2984 {
2985 aDocPageSize.AdjustWidth( -(lcl_LineTotal(pBorderItem->GetLeft()) +
2986 lcl_LineTotal(pBorderItem->GetRight()) +
2987 pBorderItem->GetDistance(SvxBoxItemLine::LEFT) +
2988 pBorderItem->GetDistance(SvxBoxItemLine::RIGHT)) );
2989 aDocPageSize.AdjustHeight( -(lcl_LineTotal(pBorderItem->GetTop()) +
2990 lcl_LineTotal(pBorderItem->GetBottom()) +
2991 pBorderItem->GetDistance(SvxBoxItemLine::TOP) +
2992 pBorderItem->GetDistance(SvxBoxItemLine::BOTTOM)) );
2993 }
2994 if (pShadowItem && pShadowItem->GetLocation() != SvxShadowLocation::NONE)
2995 {
2996 aDocPageSize.AdjustWidth( -(pShadowItem->CalcShadowSpace(SvxShadowItemSide::LEFT) +
2997 pShadowItem->CalcShadowSpace(SvxShadowItemSide::RIGHT)) );
2998 aDocPageSize.AdjustHeight( -(pShadowItem->CalcShadowSpace(SvxShadowItemSide::TOP) +
2999 pShadowItem->CalcShadowSpace(SvxShadowItemSide::BOTTOM)) );
3000 }
3001 return aDocPageSize;
3002 }
3003
ResetBreaks(SCTAB nTab)3004 void ScPrintFunc::ResetBreaks( SCTAB nTab ) // Set Breaks correctly for view
3005 {
3006 rDoc.SetPageSize( nTab, GetDocPageSize() );
3007 rDoc.UpdatePageBreaks( nTab );
3008 }
3009
lcl_SetHidden(const ScDocument & rDoc,SCTAB nPrintTab,ScPageRowEntry & rPageRowEntry,SCCOL nStartCol,const std::vector<SCCOL> & rPageEndX)3010 static void lcl_SetHidden( const ScDocument& rDoc, SCTAB nPrintTab, ScPageRowEntry& rPageRowEntry,
3011 SCCOL nStartCol, const std::vector< SCCOL >& rPageEndX )
3012 {
3013 size_t nPagesX = rPageRowEntry.GetPagesX();
3014 SCROW nStartRow = rPageRowEntry.GetStartRow();
3015 SCROW nEndRow = rPageRowEntry.GetEndRow();
3016
3017 bool bLeftIsEmpty = false;
3018 ScRange aTempRange;
3019 tools::Rectangle aTempRect = rDoc.GetMMRect( 0,0, 0,0, 0 );
3020
3021 for (size_t i=0; i<nPagesX; i++)
3022 {
3023 OSL_ENSURE(i < rPageEndX.size(), "vector access error for aPageEndX");
3024 SCCOL nEndCol = rPageEndX[i];
3025 if ( rDoc.IsPrintEmpty( nPrintTab, nStartCol, nStartRow, nEndCol, nEndRow,
3026 bLeftIsEmpty, &aTempRange, &aTempRect ) )
3027 {
3028 rPageRowEntry.SetHidden(i);
3029 bLeftIsEmpty = true;
3030 }
3031 else
3032 bLeftIsEmpty = false;
3033
3034 nStartCol = nEndCol+1;
3035 }
3036 }
3037
CalcPages()3038 void ScPrintFunc::CalcPages() // calculates aPageRect and pages from nZoom
3039 {
3040 assert( bPrintAreaValid );
3041 m_aRanges.calculate(rDoc, aTableParam.bSkipEmpty, aAreaParam.bPrintArea, nStartRow, nEndRow, nStartCol, nEndCol, nPrintTab, GetDocPageSize());
3042 }
3043
3044 namespace sc
3045 {
3046
PrintPageRanges()3047 PrintPageRanges::PrintPageRanges()
3048 : m_nPagesX(0)
3049 , m_nPagesY(0)
3050 , m_nTotalY(0)
3051 {}
3052
checkIfAlreadyCalculatedAndSet(bool bSkipEmpty,bool bPrintArea,SCROW nStartRow,SCROW nEndRow,SCCOL nStartCol,SCCOL nEndCol,SCTAB nPrintTab,Size const & rDocSize)3053 bool PrintPageRanges::checkIfAlreadyCalculatedAndSet(
3054 bool bSkipEmpty, bool bPrintArea,
3055 SCROW nStartRow, SCROW nEndRow,
3056 SCCOL nStartCol, SCCOL nEndCol,
3057 SCTAB nPrintTab, Size const & rDocSize)
3058 {
3059 if (bSkipEmpty == m_aInput.m_bSkipEmpty &&
3060 bPrintArea == m_aInput.m_bPrintArea &&
3061 nStartRow == m_aInput.m_nStartRow && nEndRow == m_aInput.m_nEndRow &&
3062 nStartCol == m_aInput.m_nStartCol && nEndCol == m_aInput.m_nEndCol &&
3063 nPrintTab == m_aInput.m_nPrintTab &&
3064 rDocSize == m_aInput.m_aDocSize)
3065 {
3066 return true;
3067 }
3068
3069 m_aInput.m_bSkipEmpty = bSkipEmpty;
3070 m_aInput.m_bPrintArea = bPrintArea;
3071 m_aInput.m_nStartRow = nStartRow;
3072 m_aInput.m_nEndRow = nEndRow;
3073 m_aInput.m_nStartCol = nStartCol;
3074 m_aInput.m_nEndCol = nEndCol;
3075 m_aInput.m_nPrintTab = nPrintTab;
3076 m_aInput.m_aDocSize = rDocSize;
3077
3078 return false;
3079 }
3080
calculate(ScDocument & rDoc,bool bSkipEmpty,bool bPrintArea,SCROW nStartRow,SCROW nEndRow,SCCOL nStartCol,SCCOL nEndCol,SCTAB nPrintTab,Size const & rDocSize)3081 void PrintPageRanges::calculate(ScDocument& rDoc,
3082 bool bSkipEmpty, bool bPrintArea,
3083 SCROW nStartRow, SCROW nEndRow,
3084 SCCOL nStartCol, SCCOL nEndCol,
3085 SCTAB nPrintTab, Size const & rDocSize)
3086 {
3087 // Already calculated?
3088 if (checkIfAlreadyCalculatedAndSet(bSkipEmpty, bPrintArea,
3089 nStartRow, nEndRow, nStartCol, nEndCol,
3090 nPrintTab, rDocSize))
3091 return;
3092
3093 rDoc.SetPageSize(nPrintTab, rDocSize);
3094
3095 // #i123672# use dynamic mem to react on size changes
3096 if (m_xPageEndX->size() < static_cast<size_t>(rDoc.MaxCol()) + 1)
3097 {
3098 m_xPageEndX->resize(rDoc.MaxCol()+1, SCCOL());
3099 }
3100
3101 if (bPrintArea)
3102 {
3103 ScRange aRange(nStartCol, nStartRow, nPrintTab, nEndCol, nEndRow, nPrintTab);
3104 rDoc.UpdatePageBreaks(nPrintTab, &aRange);
3105 }
3106 else
3107 {
3108 rDoc.UpdatePageBreaks(nPrintTab); // else, end is marked
3109 }
3110
3111 const size_t nRealCnt = nEndRow - nStartRow + 1;
3112
3113 // #i123672# use dynamic mem to react on size changes
3114 if (m_xPageEndY->size() < nRealCnt+1)
3115 {
3116 m_xPageEndY->resize(nRealCnt + 1, SCROW());
3117 }
3118
3119 // Page alignment/splitting after breaks in Col/RowFlags
3120 // Of several breaks in a hidden area, only one counts.
3121
3122 m_nPagesX = 0;
3123 m_nPagesY = 0;
3124 m_nTotalY = 0;
3125
3126 bool bVisCol = false;
3127 for (SCCOL i = nStartCol; i <= nEndCol; i++)
3128 {
3129 bool bHidden = rDoc.ColHidden(i, nPrintTab);
3130 bool bPageBreak(rDoc.HasColBreak(i, nPrintTab) & ScBreakType::Page);
3131 if (i > nStartCol && bVisCol && bPageBreak)
3132 {
3133 OSL_ENSURE(m_nPagesX < m_xPageEndX->size(), "vector access error for aPageEndX");
3134 (*m_xPageEndX)[m_nPagesX] = i-1;
3135 ++m_nPagesX;
3136 bVisCol = false;
3137 }
3138 if (!bHidden)
3139 bVisCol = true;
3140 }
3141 if (bVisCol) // also at the end, no empty pages
3142 {
3143 OSL_ENSURE(m_nPagesX < m_xPageEndX->size(), "vector access error for aPageEndX");
3144 (*m_xPageEndX)[m_nPagesX] = nEndCol;
3145 ++m_nPagesX;
3146 }
3147
3148 bool bVisRow = false;
3149 SCROW nPageStartRow = nStartRow;
3150 SCROW nLastVisibleRow = -1;
3151
3152 std::unique_ptr<ScRowBreakIterator> pRowBreakIter(rDoc.GetRowBreakIterator(nPrintTab));
3153 SCROW nNextPageBreak = pRowBreakIter->first();
3154 while (nNextPageBreak != ScRowBreakIterator::NOT_FOUND && nNextPageBreak < nStartRow)
3155 // Skip until the page break position is at the start row or greater.
3156 nNextPageBreak = pRowBreakIter->next();
3157
3158 for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
3159 {
3160 bool bPageBreak = (nNextPageBreak == nRow);
3161 if (bPageBreak)
3162 nNextPageBreak = pRowBreakIter->next();
3163
3164 if (nRow > nStartRow && bVisRow && bPageBreak)
3165 {
3166 OSL_ENSURE(m_nTotalY < m_xPageEndY->size(), "vector access error for rPageEndY");
3167 (*m_xPageEndY)[m_nTotalY] = nRow - 1;
3168 ++m_nTotalY;
3169
3170 if (!bSkipEmpty || !rDoc.IsPrintEmpty(nPrintTab, nStartCol, nPageStartRow, nEndCol, nRow-1))
3171 {
3172 auto& rPageRow = (*m_xPageRows)[m_nPagesY];
3173 rPageRow.SetStartRow(nPageStartRow);
3174 rPageRow.SetEndRow(nRow - 1);
3175 rPageRow.SetPagesX(m_nPagesX);
3176 if (bSkipEmpty)
3177 lcl_SetHidden(rDoc, nPrintTab, rPageRow, nStartCol, *m_xPageEndX);
3178 ++m_nPagesY;
3179 }
3180
3181 nPageStartRow = nRow;
3182 bVisRow = false;
3183 }
3184
3185 if (nRow <= nLastVisibleRow)
3186 {
3187 // This row is still visible. Don't bother calling RowHidden() to
3188 // find out, for speed optimization.
3189 bVisRow = true;
3190 continue;
3191 }
3192
3193 SCROW nLastRow = -1;
3194 if (!rDoc.RowHidden(nRow, nPrintTab, nullptr, &nLastRow))
3195 {
3196 bVisRow = true;
3197 nLastVisibleRow = nLastRow;
3198 }
3199 else
3200 {
3201 // Skip all hidden rows until next pagebreak.
3202 nRow = ((nNextPageBreak == ScRowBreakIterator::NOT_FOUND) ? nLastRow :
3203 std::min(nLastRow, nNextPageBreak - 1));
3204 }
3205 }
3206
3207 if (!bVisRow)
3208 return;
3209
3210 OSL_ENSURE(m_nTotalY < m_xPageEndY->size(), "vector access error for maPageEndY");
3211 (*m_xPageEndY)[m_nTotalY] = nEndRow;
3212 ++m_nTotalY;
3213
3214 if (!bSkipEmpty || !rDoc.IsPrintEmpty(nPrintTab, nStartCol, nPageStartRow, nEndCol, nEndRow))
3215 {
3216 auto& rPageRow = (*m_xPageRows)[m_nPagesY];
3217 rPageRow.SetStartRow(nPageStartRow);
3218 rPageRow.SetEndRow(nEndRow);
3219 rPageRow.SetPagesX(m_nPagesX);
3220 if (bSkipEmpty)
3221 lcl_SetHidden(rDoc, nPrintTab, rPageRow, nStartCol, *m_xPageEndX);
3222 ++m_nPagesY;
3223 }
3224 }
3225
3226 } // end namespace sc
3227 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
3228