1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <scitems.hxx>
21 #include <editeng/eeitem.hxx>
23 #include <printfun.hxx>
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 <vcl/pdfextoutdevdata.hxx>
33 #include <editeng/frmdiritem.hxx>
34 #include <editeng/lrspitem.hxx>
35 #include <editeng/paperinf.hxx>
36 #include <editeng/pbinitem.hxx>
37 #include <editeng/shaditem.hxx>
38 #include <editeng/sizeitem.hxx>
39 #include <editeng/fhgtitem.hxx>
40 #include <editeng/ulspitem.hxx>
41 #include <sfx2/printer.hxx>
42 #include <tools/multisel.hxx>
43 #include <sfx2/docfile.hxx>
44 #include <tools/urlobj.hxx>
45 #include <osl/diagnose.h>
47 #include <editutil.hxx>
50 #include <viewdata.hxx>
51 #include <viewopti.hxx>
52 #include <stlpool.hxx>
53 #include <pagepar.hxx>
55 #include <patattr.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>
63 #include <drwlayer.hxx>
64 #include <fillinfo.hxx>
68 #include <com/sun/star/document/XDocumentProperties.hpp>
74 bool lcl_GetBool(const SfxItemSet
* pSet
, sal_uInt16 nWhich
)
76 return static_cast<const SfxBoolItem
&>(pSet
->Get(nWhich
)).GetValue();
79 sal_uInt16
lcl_GetUShort(const SfxItemSet
* pSet
, sal_uInt16 nWhich
)
81 return static_cast<const SfxUInt16Item
&>(pSet
->Get(nWhich
)).GetValue();
84 bool lcl_GetShow(const SfxItemSet
* pSet
, sal_uInt16 nWhich
)
86 return ScVObjMode::VOBJ_MODE_SHOW
== static_cast<const ScViewObjectModeItem
&>(pSet
->Get(nWhich
)).GetValue();
92 ScPageRowEntry::ScPageRowEntry(const ScPageRowEntry
& r
)
94 nStartRow
= r
.nStartRow
;
98 aHidden
.resize(nPagesX
, false);
101 ScPageRowEntry
& ScPageRowEntry::operator=(const ScPageRowEntry
& r
)
103 nStartRow
= r
.nStartRow
;
107 aHidden
.resize(nPagesX
, false);
111 void ScPageRowEntry::SetPagesX(size_t nNew
)
114 aHidden
.resize(nPagesX
, false);
117 void ScPageRowEntry::SetHidden(size_t nX
)
121 if ( nX
+1 == nPagesX
) // last page?
125 aHidden
.resize(nPagesX
, false);
131 bool ScPageRowEntry::IsHidden(size_t nX
) const
133 return nX
>= nPagesX
|| aHidden
[nX
]; //! inline?
136 size_t ScPageRowEntry::CountVisible() const
138 if (!aHidden
.empty())
141 for (size_t i
=0; i
<nPagesX
; i
++)
150 static tools::Long
lcl_LineTotal(const ::editeng::SvxBorderLine
* pLine
)
152 return pLine
? ( pLine
->GetScaledWidth() ) : 0;
155 void ScPrintFunc::Construct( const ScPrintOptions
* pOptions
)
157 pDocShell
->UpdatePendingRowHeights( nPrintTab
);
159 SfxPrinter
* pDocPrinter
= rDoc
.GetPrinter(); // use the printer, even for preview
161 aOldPrinterMode
= pDocPrinter
->GetMapMode();
163 // unified MapMode for all calls (e.g. Repaint!!!)
164 // else, EditEngine outputs different text heights
165 pDev
->SetMapMode(MapMode(MapUnit::MapPixel
));
167 pBorderItem
= nullptr;
168 pBackgroundItem
= nullptr;
169 pShadowItem
= nullptr;
171 pEditEngine
= nullptr;
172 pEditDefaults
= nullptr;
174 ScStyleSheetPool
* pStylePool
= rDoc
.GetStyleSheetPool();
175 SfxStyleSheetBase
* pStyleSheet
= pStylePool
->Find(
176 rDoc
.GetPageStyle( nPrintTab
),
177 SfxStyleFamily::Page
);
179 pParamSet
= &pStyleSheet
->GetItemSet();
182 OSL_FAIL("Template not found" );
186 if (!bFromPrintState
)
190 bUseStyleColor
= false;
195 pPageData
= nullptr; // is only needed for initialisation
198 ScPrintFunc::ScPrintFunc(ScDocShell
* pShell
, SfxPrinter
* pNewPrinter
, SCTAB nTab
, tools::Long nPage
,
199 tools::Long nDocP
, const ScRange
* pArea
, const ScPrintOptions
* pOptions
,
200 ScPageBreakData
* pData
, Size aSize
, bool bPrintLandscape
, bool bUsed
)
201 : pDocShell ( pShell
),
202 rDoc(pDocShell
->GetDocument()),
203 pPrinter ( pNewPrinter
),
204 pDrawView ( nullptr ),
206 nPageStart ( nPage
),
209 bFromPrintState ( false ),
210 bSourceRangeValid ( false ),
211 bPrintCurrentTable ( false ),
212 bMultiArea ( false ),
213 mbHasPrintRange(true),
216 bPrintAreaValid ( false ),
218 aPrintPageSize ( aSize
),
219 bPrintPageLandscape ( bPrintLandscape
),
220 bUsePrintDialogSetting ( bUsed
)
222 pDev
= pPrinter
.get();
223 aSrcOffset
= pPrinter
->PixelToLogic(pPrinter
->GetPageOffsetPixel(), MapMode(MapUnit::Map100thMM
));
224 m_aRanges
.m_xPageEndX
= std::make_shared
<std::vector
<SCCOL
>>();
225 m_aRanges
.m_xPageEndY
= std::make_shared
<std::vector
<SCROW
>>();
226 m_aRanges
.m_xPageRows
= std::make_shared
<std::map
<size_t, ScPageRowEntry
>>();
227 Construct( pOptions
);
230 ScPrintFunc::ScPrintFunc(ScDocShell
* pShell
, SfxPrinter
* pNewPrinter
, const ScPrintState
& rState
,
231 const ScPrintOptions
* pOptions
, Size aSize
, bool bPrintLandscape
,
233 : pDocShell ( pShell
),
234 rDoc(pDocShell
->GetDocument()),
235 pPrinter ( pNewPrinter
),
236 pDrawView ( nullptr ),
237 pUserArea ( nullptr ),
238 bSourceRangeValid ( false ),
239 bPrintCurrentTable ( false ),
240 bMultiArea ( false ),
241 mbHasPrintRange(true),
242 pPageData ( nullptr ),
243 aPrintPageSize ( aSize
),
244 bPrintPageLandscape ( bPrintLandscape
),
245 bUsePrintDialogSetting ( bUsed
)
247 pDev
= pPrinter
.get();
249 nPrintTab
= rState
.nPrintTab
;
250 nStartCol
= rState
.nStartCol
;
251 nStartRow
= rState
.nStartRow
;
252 nEndCol
= rState
.nEndCol
;
253 nEndRow
= rState
.nEndRow
;
254 bPrintAreaValid
= rState
.bPrintAreaValid
;
255 nZoom
= rState
.nZoom
;
256 m_aRanges
= rState
.m_aRanges
;
257 nTabPages
= rState
.nTabPages
;
258 nTotalPages
= rState
.nTotalPages
;
259 nPageStart
= rState
.nPageStart
;
260 nDocPages
= rState
.nDocPages
;
261 bFromPrintState
= true;
263 aSrcOffset
= pPrinter
->PixelToLogic(pPrinter
->GetPageOffsetPixel(), MapMode(MapUnit::Map100thMM
));
264 Construct( pOptions
);
267 ScPrintFunc::ScPrintFunc( OutputDevice
* pOutDev
, ScDocShell
* pShell
, SCTAB nTab
,
268 tools::Long nPage
, tools::Long nDocP
, const ScRange
* pArea
,
269 const ScPrintOptions
* pOptions
)
270 : pDocShell ( pShell
),
271 rDoc(pDocShell
->GetDocument()),
272 pPrinter ( nullptr ),
273 pDrawView ( nullptr ),
275 nPageStart ( nPage
),
278 bFromPrintState ( false ),
279 bSourceRangeValid ( false ),
280 bPrintCurrentTable ( false ),
281 bMultiArea ( false ),
282 mbHasPrintRange(true),
285 bPrintAreaValid ( false ),
286 pPageData ( nullptr ),
287 aPrintPageSize ( Size() ),
288 bPrintPageLandscape ( false ),
289 bUsePrintDialogSetting ( false )
292 m_aRanges
.m_xPageEndX
= std::make_shared
<std::vector
<SCCOL
>>();
293 m_aRanges
.m_xPageEndY
= std::make_shared
<std::vector
<SCROW
>>();
294 m_aRanges
.m_xPageRows
= std::make_shared
<std::map
<size_t, ScPageRowEntry
>>();
295 Construct( pOptions
);
298 ScPrintFunc::ScPrintFunc(OutputDevice
* pOutDev
, ScDocShell
* pShell
, const ScPrintState
& rState
,
299 const ScPrintOptions
* pOptions
, Size aSize
, bool bPrintLandscape
,
301 : pDocShell ( pShell
),
302 rDoc(pDocShell
->GetDocument()),
303 pPrinter ( nullptr ),
304 pDrawView ( nullptr ),
305 pUserArea ( nullptr ),
306 bSourceRangeValid ( false ),
307 bPrintCurrentTable ( false ),
308 bMultiArea ( false ),
309 mbHasPrintRange(true),
310 pPageData ( nullptr ),
311 aPrintPageSize ( aSize
),
312 bPrintPageLandscape ( bPrintLandscape
),
313 bUsePrintDialogSetting ( bUsed
)
317 nPrintTab
= rState
.nPrintTab
;
318 nStartCol
= rState
.nStartCol
;
319 nStartRow
= rState
.nStartRow
;
320 nEndCol
= rState
.nEndCol
;
321 nEndRow
= rState
.nEndRow
;
322 bPrintAreaValid
= rState
.bPrintAreaValid
;
323 nZoom
= rState
.nZoom
;
324 m_aRanges
= rState
.m_aRanges
;
325 nTabPages
= rState
.nTabPages
;
326 nTotalPages
= rState
.nTotalPages
;
327 nPageStart
= rState
.nPageStart
;
328 nDocPages
= rState
.nDocPages
;
329 bFromPrintState
= true;
331 Construct( pOptions
);
334 void ScPrintFunc::GetPrintState(ScPrintState
& rState
)
336 rState
.nPrintTab
= nPrintTab
;
337 rState
.nStartCol
= nStartCol
;
338 rState
.nStartRow
= nStartRow
;
339 rState
.nEndCol
= nEndCol
;
340 rState
.nEndRow
= nEndRow
;
341 rState
.bPrintAreaValid
= bPrintAreaValid
;
342 rState
.nZoom
= nZoom
;
343 rState
.nTabPages
= nTabPages
;
344 rState
.nTotalPages
= nTotalPages
;
345 rState
.nPageStart
= nPageStart
;
346 rState
.nDocPages
= nDocPages
;
347 rState
.m_aRanges
= m_aRanges
;
350 bool ScPrintFunc::GetLastSourceRange( ScRange
& rRange
) const
352 rRange
= aLastSourceRange
;
353 return bSourceRangeValid
;
356 void ScPrintFunc::FillPageData()
361 sal_uInt16 nCount
= sal::static_int_cast
<sal_uInt16
>( pPageData
->GetCount() );
362 ScPrintRangeData
& rData
= pPageData
->GetData(nCount
); // count up
364 assert( bPrintAreaValid
);
365 rData
.SetPrintRange( ScRange( nStartCol
, nStartRow
, nPrintTab
,
366 nEndCol
, nEndRow
, nPrintTab
) );
368 if(m_aRanges
.m_xPageEndX
->empty())
370 OSL_ENSURE(false, "vector access error for maPageEndX (!)");
374 rData
.SetPagesX( m_aRanges
.m_nPagesX
, m_aRanges
.m_xPageEndX
->data());
378 if(m_aRanges
.m_xPageEndY
->empty())
380 OSL_ENSURE(false, "vector access error for maPageEndY (!)");
384 rData
.SetPagesY( m_aRanges
.m_nTotalY
, m_aRanges
.m_xPageEndY
->data());
388 rData
.SetTopDown( aTableParam
.bTopDown
);
389 rData
.SetAutomatic( !aAreaParam
.bPrintArea
);
392 ScPrintFunc::~ScPrintFunc()
394 pEditDefaults
.reset();
397 // Printer settings are now restored from outside
399 // For DrawingLayer/Charts, the MapMode of the printer (RefDevice) must always be correct
400 SfxPrinter
* pDocPrinter
= rDoc
.GetPrinter(); // use Preview also for the printer
402 pDocPrinter
->SetMapMode(aOldPrinterMode
);
405 void ScPrintFunc::SetDrawView( FmFormView
* pNew
)
410 static void lcl_HidePrint( const ScTableInfo
& rTabInfo
, SCCOL nX1
, SCCOL nX2
)
412 for (SCSIZE nArrY
=1; nArrY
+1<rTabInfo
.mnArrCount
; nArrY
++)
414 RowInfo
* pThisRowInfo
= &rTabInfo
.mpRowInfo
[nArrY
];
415 for (SCCOL nX
=nX1
; nX
<=nX2
; nX
++)
417 ScCellInfo
& rCellInfo
= pThisRowInfo
->cellInfo(nX
);
418 ScBasicCellInfo
& rBasicCellInfo
= pThisRowInfo
->basicCellInfo(nX
);
419 if (!rBasicCellInfo
.bEmptyCellText
)
420 if (rCellInfo
.pPatternAttr
->
421 GetItem(ATTR_PROTECTION
, rCellInfo
.pConditionSet
).GetHidePrint())
423 rCellInfo
.maCell
.clear();
424 rBasicCellInfo
.bEmptyCellText
= true;
430 // output to Device (static)
433 // - Clipboard/Bitmap
434 // - Ole-Object (DocShell::Draw)
435 // - Preview of templates
437 void ScPrintFunc::DrawToDev(ScDocument
& rDoc
, OutputDevice
* pDev
, double /* nPrintFactor */,
438 const tools::Rectangle
& rBound
, ScViewData
* pViewData
, bool bMetaFile
)
440 if (rDoc
.GetMaxTableNumber() < 0)
443 //! evaluate nPrintFactor !!!
447 nTab
= pViewData
->GetTabNo();
449 bool bDoGrid
, bNullVal
, bFormula
;
450 ScStyleSheetPool
* pStylePool
= rDoc
.GetStyleSheetPool();
451 SfxStyleSheetBase
* pStyleSheet
= pStylePool
->Find( rDoc
.GetPageStyle( nTab
), SfxStyleFamily::Page
);
454 SfxItemSet
& rSet
= pStyleSheet
->GetItemSet();
455 bDoGrid
= rSet
.Get(ATTR_PAGE_GRID
).GetValue();
456 bNullVal
= rSet
.Get(ATTR_PAGE_NULLVALS
).GetValue();
457 bFormula
= rSet
.Get(ATTR_PAGE_FORMULAS
).GetValue();
461 const ScViewOptions
& rOpt
= rDoc
.GetViewOptions();
462 bDoGrid
= rOpt
.GetOption(VOPT_GRID
);
463 bNullVal
= rOpt
.GetOption(VOPT_NULLVALS
);
464 bFormula
= rOpt
.GetOption(VOPT_FORMULAS
);
467 MapMode aMode
= pDev
->GetMapMode();
469 tools::Rectangle aRect
= rBound
;
471 if (aRect
.Right() < aRect
.Left() || aRect
.Bottom() < aRect
.Top())
472 aRect
= tools::Rectangle( Point(), pDev
->GetOutputSize() );
476 SCCOL nX2
= OLE_STD_CELLS_X
- 1;
477 SCROW nY2
= OLE_STD_CELLS_Y
- 1;
480 ScRange aRange
= rDoc
.GetRange( nTab
, rBound
);
481 nX1
= aRange
.aStart
.Col();
482 nY1
= aRange
.aStart
.Row();
483 nX2
= aRange
.aEnd
.Col();
484 nY2
= aRange
.aEnd
.Row();
488 ScSplitPos eWhich
= pViewData
->GetActivePart();
489 ScHSplitPos eHWhich
= WhichH(eWhich
);
490 ScVSplitPos eVWhich
= WhichV(eWhich
);
491 nX1
= pViewData
->GetPosX(eHWhich
);
492 nY1
= pViewData
->GetPosY(eVWhich
);
493 nX2
= nX1
+ pViewData
->VisibleCellsX(eHWhich
);
495 nY2
= nY1
+ pViewData
->VisibleCellsY(eVWhich
);
499 if (nX1
> rDoc
.MaxCol()) nX1
= rDoc
.MaxCol();
500 if (nX2
> rDoc
.MaxCol()) nX2
= rDoc
.MaxCol();
501 if (nY1
> rDoc
.MaxRow()) nY1
= rDoc
.MaxRow();
502 if (nY2
> rDoc
.MaxRow()) nY2
= rDoc
.MaxRow();
504 tools::Long nDevSizeX
= aRect
.Right()-aRect
.Left()+1;
505 tools::Long nDevSizeY
= aRect
.Bottom()-aRect
.Top()+1;
507 tools::Long nTwipsSizeX
= 0;
508 for (SCCOL i
=nX1
; i
<=nX2
; i
++)
509 nTwipsSizeX
+= rDoc
.GetColWidth( i
, nTab
);
510 tools::Long nTwipsSizeY
= rDoc
.GetRowHeight( nY1
, nY2
, nTab
);
512 // if no lines, still space for the outline frame (20 Twips = 1pt)
513 // (HasLines initializes aLines to 0,0,0,0)
517 double nScaleX
= static_cast<double>(nDevSizeX
) / nTwipsSizeX
;
518 double nScaleY
= static_cast<double>(nDevSizeY
) / nTwipsSizeY
;
520 //! hand over Flag at FillInfo !!!!!
522 bool bEmbed
= rDoc
.IsEmbedded();
525 rDoc
.GetEmbedded(aERange
);
526 rDoc
.ResetEmbedded();
531 ScTableInfo
aTabInfo(nY1
, nY2
, true);
532 rDoc
.FillInfo( aTabInfo
, nX1
, nY1
, nX2
, nY2
, nTab
,
533 nScaleX
, nScaleY
, false, bFormula
);
534 lcl_HidePrint( aTabInfo
, nX1
, nX2
);
537 rDoc
.SetEmbedded(aERange
);
539 tools::Long nScrX
= aRect
.Left();
540 tools::Long nScrY
= aRect
.Top();
542 // If no lines, still leave space for grid lines
543 // (would be elseways cut away)
547 ScOutputData
aOutputData( pDev
, OUTTYPE_PRINTER
, aTabInfo
, &rDoc
, nTab
,
548 nScrX
, nScrY
, nX1
, nY1
, nX2
, nY2
, nScaleX
, nScaleY
);
549 aOutputData
.SetMetaFileMode(bMetaFile
);
550 aOutputData
.SetShowNullValues(bNullVal
);
551 aOutputData
.SetShowFormulas(bFormula
);
553 vcl::PDFExtOutDevData
* pPDF
= dynamic_cast<vcl::PDFExtOutDevData
*>(pDev
->GetExtOutDevData());
554 bool bTaggedPDF
= pPDF
&& pPDF
->GetIsExportTaggedPDF();
557 bool bReopen
= aOutputData
.ReopenPDFStructureElement(vcl::PDFWriter::Part
);
560 sal_Int32 nId
= pPDF
->EnsureStructureElement(nullptr);
561 pPDF
->InitStructureElement(nId
, vcl::PDFWriter::Part
, u
"Worksheet"_ustr
);
562 pPDF
->BeginStructureElement(nId
);
563 pPDF
->GetScPDFState()->m_WorksheetId
= nId
;
567 ScDrawLayer
* pModel
= rDoc
.GetDrawLayer();
568 std::unique_ptr
<FmFormView
> pDrawView
;
576 pDrawView
->ShowSdrPage(pDrawView
->GetModel().GetPage(nTab
));
577 pDrawView
->SetPrintPreview();
578 aOutputData
.SetDrawView( pDrawView
.get() );
581 //! SetUseStyleColor ??
583 if ( bMetaFile
&& pDev
->IsVirtual() )
584 aOutputData
.SetSnapPixel();
586 Point aLogStart
= pDev
->PixelToLogic(Point(nScrX
, nScrY
), MapMode(MapUnit::Map100thMM
));
587 tools::Long nLogStX
= aLogStart
.X();
588 tools::Long nLogStY
= aLogStart
.Y();
590 //! nZoom for GetFont in OutputData ???
592 if (!bMetaFile
&& pViewData
)
593 pDev
->SetMapMode(pViewData
->GetLogicMode(pViewData
->GetActivePart()));
596 const Point
aMMOffset(aOutputData
.PrePrintDrawingLayer(nLogStX
, nLogStY
));
597 aOutputData
.PrintDrawingLayer(SC_LAYER_BACK
, aMMOffset
);
599 if (!bMetaFile
&& pViewData
)
600 pDev
->SetMapMode(aMode
);
602 aOutputData
.DrawBackground(*pDev
);
604 aOutputData
.DrawShadow();
605 aOutputData
.DrawFrame(*pDev
);
606 aOutputData
.DrawSparklines(*pDev
);
607 aOutputData
.DrawStrings();
609 if (!bMetaFile
&& pViewData
)
610 pDev
->SetMapMode(pViewData
->GetLogicMode(pViewData
->GetActivePart()));
612 aOutputData
.DrawEdit(!bMetaFile
);
616 if (!bMetaFile
&& pViewData
)
617 pDev
->SetMapMode(aMode
);
619 aOutputData
.DrawGrid(*pDev
, true, false); // no page breaks
621 pDev
->SetLineColor( COL_BLACK
);
623 Size aOne
= pDev
->PixelToLogic( Size(1,1) );
625 aOne
= Size(1,1); // compatible with DrawGrid
626 tools::Long nRight
= nScrX
+ aOutputData
.GetScrW() - aOne
.Width();
627 tools::Long nBottom
= nScrY
+ aOutputData
.GetScrH() - aOne
.Height();
629 bool bLayoutRTL
= rDoc
.IsLayoutRTL( nTab
);
631 // extra line at the left edge for left-to-right, right for right-to-left
633 pDev
->DrawLine( Point(nRight
,nScrY
), Point(nRight
,nBottom
) );
635 pDev
->DrawLine( Point(nScrX
,nScrY
), Point(nScrX
,nBottom
) );
636 // extra line at the top in both cases
637 pDev
->DrawLine( Point(nScrX
,nScrY
), Point(nRight
,nScrY
) );
641 aOutputData
.PrintDrawingLayer(SC_LAYER_FRONT
, aMMOffset
);
644 pPDF
->EndStructureElement();
646 aOutputData
.PrintDrawingLayer(SC_LAYER_INTERN
, aMMOffset
);
647 aOutputData
.PostPrintDrawingLayer(aMMOffset
); // #i74768#
652 static void lcl_FillHFParam( ScPrintHFParam
& rParam
, const SfxItemSet
* pHFSet
)
654 // nDistance must be initialized differently before
656 if ( pHFSet
== nullptr )
658 rParam
.bEnable
= false;
659 rParam
.pBorder
= nullptr;
660 rParam
.pBack
= nullptr;
661 rParam
.pShadow
= nullptr;
665 rParam
.bEnable
= pHFSet
->Get(ATTR_PAGE_ON
).GetValue();
666 rParam
.bDynamic
= pHFSet
->Get(ATTR_PAGE_DYNAMIC
).GetValue();
667 rParam
.bShared
= pHFSet
->Get(ATTR_PAGE_SHARED
).GetValue();
668 rParam
.bSharedFirst
= pHFSet
->Get(ATTR_PAGE_SHARED_FIRST
).GetValue();
669 rParam
.nHeight
= pHFSet
->Get(ATTR_PAGE_SIZE
).GetSize().Height();
670 const SvxLRSpaceItem
* pHFLR
= &pHFSet
->Get(ATTR_LRSPACE
);
672 nTmp
= pHFLR
->ResolveLeft({});
673 rParam
.nLeft
= nTmp
< 0 ? 0 : sal_uInt16(nTmp
);
674 nTmp
= pHFLR
->ResolveRight({});
675 rParam
.nRight
= nTmp
< 0 ? 0 : sal_uInt16(nTmp
);
676 rParam
.pBorder
= &pHFSet
->Get(ATTR_BORDER
);
677 rParam
.pBack
= &pHFSet
->Get(ATTR_BACKGROUND
);
678 rParam
.pShadow
= &pHFSet
->Get(ATTR_SHADOW
);
680 // now back in the dialog:
681 // rParam.nHeight += rParam.nDistance; // not in the dialog any more ???
683 rParam
.nHeight
+= lcl_LineTotal( rParam
.pBorder
->GetTop() ) +
684 lcl_LineTotal( rParam
.pBorder
->GetBottom() );
686 rParam
.nManHeight
= rParam
.nHeight
;
693 // bNew = TRUE: search for used part of the document
694 // bNew = FALSE: only limit whole lines/columns
696 bool ScPrintFunc::AdjustPrintArea( bool bNew
)
698 SCCOL nOldEndCol
= nEndCol
; // only important for !bNew
699 SCROW nOldEndRow
= nEndRow
;
700 bool bChangeCol
= true; // at bNew both are being adjusted
701 bool bChangeRow
= true;
703 bool bNotes
= aTableParam
.bNotes
;
708 if (!rDoc
.GetPrintArea( nPrintTab
, nEndCol
, nEndRow
, bNotes
) && aTableParam
.bSkipEmpty
)
709 return false; // nothing
710 bPrintAreaValid
= true;
715 bChangeCol
= ( nStartCol
== 0 && nEndCol
== rDoc
.MaxCol() );
716 bChangeRow
= ( nStartRow
== 0 && nEndRow
== rDoc
.MaxRow() );
717 bool bForcedChangeRow
= false;
719 // #i53558# Crop entire column of old row limit to real print area with
721 if (!bChangeRow
&& nStartRow
== 0)
724 bFound
= rDoc
.GetPrintAreaVer( nPrintTab
, nStartCol
, nEndCol
, nPAEndRow
, bNotes
);
725 // Say we don't want to print more than ~1000 empty rows, which are
726 // about 14 pages intentionally left blank...
727 const SCROW nFuzzy
= 23*42;
728 if (nPAEndRow
+ nFuzzy
< nEndRow
)
730 bForcedChangeRow
= true;
734 bFound
= true; // user seems to _want_ to print some empty rows
736 // TODO: in case we extend the number of columns we may have to do the
737 // same for horizontal cropping.
739 if ( bChangeCol
&& bChangeRow
)
740 bFound
= rDoc
.GetPrintArea( nPrintTab
, nEndCol
, nEndRow
, bNotes
);
741 else if ( bChangeCol
)
742 bFound
= rDoc
.GetPrintAreaHor( nPrintTab
, nStartRow
, nEndRow
, nEndCol
);
743 else if ( bChangeRow
)
744 bFound
= rDoc
.GetPrintAreaVer( nPrintTab
, nStartCol
, nEndCol
, nEndRow
, bNotes
);
747 return false; // empty
749 bPrintAreaValid
= true;
750 if (bForcedChangeRow
)
754 assert( bPrintAreaValid
);
755 rDoc
.ExtendMerge( nStartCol
,nStartRow
, nEndCol
,nEndRow
, nPrintTab
); // no Refresh, incl. Attrs
759 OutputDevice
* pRefDev
= rDoc
.GetPrinter(); // use the printer also for Preview
760 pRefDev
->SetMapMode(MapMode(MapUnit::MapPixel
)); // important for GetNeededSize
762 rDoc
.ExtendPrintArea( pRefDev
,
763 nPrintTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
);
767 if ( nEndCol
< rDoc
.MaxCol() && rDoc
.HasAttrib(
768 nEndCol
,nStartRow
,nPrintTab
, nEndCol
,nEndRow
,nPrintTab
, HasAttrFlags::ShadowRight
) )
770 if ( nEndRow
< rDoc
.MaxRow() && rDoc
.HasAttrib(
771 nStartCol
,nEndRow
,nPrintTab
, nEndCol
,nEndRow
,nPrintTab
, HasAttrFlags::ShadowDown
) )
774 if (!bChangeCol
) nEndCol
= nOldEndCol
;
775 if (!bChangeRow
) nEndRow
= nOldEndRow
;
780 tools::Long
ScPrintFunc::TextHeight( const EditTextObject
* pObject
)
785 pEditEngine
->SetTextTempDefaults(*pObject
, *pEditDefaults
);
787 return static_cast<tools::Long
>(pEditEngine
->GetTextHeight());
790 // nZoom must be set !!!
791 // and the respective Twip-MapMode configured
793 void ScPrintFunc::UpdateHFHeight( ScPrintHFParam
& rParam
)
795 OSL_ENSURE( aPageSize
.Width(), "UpdateHFHeight without aPageSize");
797 if (!(rParam
.bEnable
&& rParam
.bDynamic
))
800 // calculate nHeight from content
803 tools::Long nPaperWidth
= ( aPageSize
.Width() - nLeftMargin
- nRightMargin
-
804 rParam
.nLeft
- rParam
.nRight
) * 100 / nZoom
;
806 nPaperWidth
-= ( rParam
.pBorder
->GetDistance(SvxBoxItemLine::LEFT
) +
807 rParam
.pBorder
->GetDistance(SvxBoxItemLine::RIGHT
) +
808 lcl_LineTotal(rParam
.pBorder
->GetLeft()) +
809 lcl_LineTotal(rParam
.pBorder
->GetRight()) ) * 100 / nZoom
;
811 if (rParam
.pShadow
&& rParam
.pShadow
->GetLocation() != SvxShadowLocation::NONE
)
812 nPaperWidth
-= ( rParam
.pShadow
->CalcShadowSpace(SvxShadowItemSide::LEFT
) +
813 rParam
.pShadow
->CalcShadowSpace(SvxShadowItemSide::RIGHT
) ) * 100 / nZoom
;
815 if (nPaperWidth
<= 0)
817 SAL_WARN("sc.ui", "Header/Footer unreasonably narrow width of: " << nPaperWidth
<< ", cannot calculate height");
821 pEditEngine
->SetPaperSize( Size( nPaperWidth
, 10000 ) );
823 tools::Long nMaxHeight
= 0;
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() ) );
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() ) );
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() ) );
843 rParam
.nHeight
= nMaxHeight
+ rParam
.nDistance
;
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
);
853 if (rParam
.nHeight
< rParam
.nManHeight
)
854 rParam
.nHeight
= rParam
.nManHeight
; // configured minimum
857 void ScPrintFunc::InitParam( const ScPrintOptions
* pOptions
)
863 const SvxLRSpaceItem
* pLRItem
= &pParamSet
->Get( ATTR_LRSPACE
);
865 nTmp
= pLRItem
->ResolveLeft({});
866 nLeftMargin
= nTmp
< 0 ? 0 : sal_uInt16(nTmp
);
867 nTmp
= pLRItem
->ResolveRight({});
868 nRightMargin
= nTmp
< 0 ? 0 : sal_uInt16(nTmp
);
869 const SvxULSpaceItem
* pULItem
= &pParamSet
->Get( ATTR_ULSPACE
);
870 nTopMargin
= pULItem
->GetUpper();
871 nBottomMargin
= pULItem
->GetLower();
873 const SvxPageItem
* pPageItem
= &pParamSet
->Get( ATTR_PAGE
);
874 nPageUsage
= pPageItem
->GetPageUsage();
875 bLandscape
= bUsePrintDialogSetting
? bPrintPageLandscape
: pPageItem
->IsLandscape();
876 aFieldData
.eNumType
= pPageItem
->GetNumType();
878 bCenterHor
= pParamSet
->Get(ATTR_PAGE_HORCENTER
).GetValue();
879 bCenterVer
= pParamSet
->Get(ATTR_PAGE_VERCENTER
).GetValue();
881 aPageSize
= bUsePrintDialogSetting
? aPrintPageSize
: pParamSet
->Get(ATTR_PAGE_SIZE
).GetSize();
882 if ( !aPageSize
.Width() || !aPageSize
.Height() )
884 OSL_FAIL("PageSize Null ?!?!?");
885 aPageSize
= SvxPaperInfo::GetPaperSize( PAPER_A4
);
888 pBorderItem
= &pParamSet
->Get(ATTR_BORDER
);
889 pBackgroundItem
= &pParamSet
->Get(ATTR_BACKGROUND
);
890 pShadowItem
= &pParamSet
->Get(ATTR_SHADOW
);
892 // TabPage "Headline"
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
);
898 const SfxItemSet
* pHeaderSet
= nullptr;
899 if ( const SvxSetItem
* pHeaderSetItem
= pParamSet
->GetItemIfSet( ATTR_PAGE_HEADERSET
, false ) )
901 pHeaderSet
= &pHeaderSetItem
->GetItemSet();
902 // Headline has space below
903 aHdr
.nDistance
= pHeaderSet
->Get(ATTR_ULSPACE
).GetLower();
905 lcl_FillHFParam( aHdr
, pHeaderSet
);
907 // TabPage "Footline"
909 aFtr
.pLeft
= &pParamSet
->Get(ATTR_PAGE_FOOTERLEFT
); // Content
910 aFtr
.pRight
= &pParamSet
->Get(ATTR_PAGE_FOOTERRIGHT
);
911 aFtr
.pFirst
= &pParamSet
->Get(ATTR_PAGE_FOOTERFIRST
);
913 const SfxItemSet
* pFooterSet
= nullptr;
914 if ( const SvxSetItem
* pFooterSetItem
= pParamSet
->GetItemIfSet( ATTR_PAGE_FOOTERSET
, false ) )
916 pFooterSet
= &pFooterSetItem
->GetItemSet();
917 // Footline has space above
918 aFtr
.nDistance
= pFooterSet
->Get(ATTR_ULSPACE
).GetUpper();
920 lcl_FillHFParam( aFtr
, pFooterSet
);
922 // Compile Table-/Area-Params from single Items
926 const SfxUInt16Item
* pScaleItem
= nullptr;
927 const ScPageScaleToItem
* pScaleToItem
= nullptr;
928 const SfxUInt16Item
* pScaleToPagesItem
= nullptr;
931 eState
= pParamSet
->GetItemState( ATTR_PAGE_SCALE
, false,
932 reinterpret_cast<const SfxPoolItem
**>(&pScaleItem
) );
933 if ( SfxItemState::DEFAULT
== eState
)
934 pScaleItem
= &pParamSet
->GetPool()->GetUserOrPoolDefaultItem( ATTR_PAGE_SCALE
);
936 eState
= pParamSet
->GetItemState( ATTR_PAGE_SCALETO
, false,
937 reinterpret_cast<const SfxPoolItem
**>(&pScaleToItem
) );
938 if ( SfxItemState::DEFAULT
== eState
)
939 pScaleToItem
= &pParamSet
->GetPool()->GetUserOrPoolDefaultItem( ATTR_PAGE_SCALETO
);
941 eState
= pParamSet
->GetItemState( ATTR_PAGE_SCALETOPAGES
, false,
942 reinterpret_cast<const SfxPoolItem
**>(&pScaleToPagesItem
) );
943 if ( SfxItemState::DEFAULT
== eState
)
944 pScaleToPagesItem
= &pParamSet
->GetPool()->GetUserOrPoolDefaultItem( ATTR_PAGE_SCALETOPAGES
);
946 OSL_ENSURE( pScaleItem
&& pScaleToItem
&& pScaleToPagesItem
, "Missing ScaleItem! :-/" );
948 aTableParam
.bCellContent
= true;
949 aTableParam
.bNotes
= lcl_GetBool(pParamSet
,ATTR_PAGE_NOTES
);
950 aTableParam
.bGrid
= lcl_GetBool(pParamSet
,ATTR_PAGE_GRID
);
951 aTableParam
.bHeaders
= lcl_GetBool(pParamSet
,ATTR_PAGE_HEADERS
);
952 aTableParam
.bFormulas
= lcl_GetBool(pParamSet
,ATTR_PAGE_FORMULAS
);
953 aTableParam
.bNullVals
= lcl_GetBool(pParamSet
,ATTR_PAGE_NULLVALS
);
954 aTableParam
.bCharts
= lcl_GetShow(pParamSet
,ATTR_PAGE_CHARTS
);
955 aTableParam
.bObjects
= lcl_GetShow(pParamSet
,ATTR_PAGE_OBJECTS
);
956 aTableParam
.bDrawings
= lcl_GetShow(pParamSet
,ATTR_PAGE_DRAWINGS
);
957 aTableParam
.bTopDown
= lcl_GetBool(pParamSet
,ATTR_PAGE_TOPDOWN
);
958 aTableParam
.bLeftRight
= !aTableParam
.bLeftRight
;
959 aTableParam
.nFirstPageNo
= lcl_GetUShort(pParamSet
,ATTR_PAGE_FIRSTPAGENO
);
960 if (!aTableParam
.nFirstPageNo
)
961 aTableParam
.nFirstPageNo
= static_cast<sal_uInt16
>(nPageStart
); // from previous table
963 if ( pScaleItem
&& pScaleToItem
&& pScaleToPagesItem
)
965 sal_uInt16 nScaleAll
= pScaleItem
->GetValue();
966 sal_uInt16 nScaleToPages
= pScaleToPagesItem
->GetValue();
968 aTableParam
.bScaleNone
= (nScaleAll
== 100);
969 aTableParam
.bScaleAll
= (nScaleAll
> 0 );
970 aTableParam
.bScaleTo
= pScaleToItem
->IsValid();
971 aTableParam
.bScalePageNum
= (nScaleToPages
> 0 );
972 aTableParam
.nScaleAll
= nScaleAll
;
973 aTableParam
.nScaleWidth
= pScaleToItem
->GetWidth();
974 aTableParam
.nScaleHeight
= pScaleToItem
->GetHeight();
975 aTableParam
.nScalePageNum
= nScaleToPages
;
979 aTableParam
.bScaleNone
= true;
980 aTableParam
.bScaleAll
= false;
981 aTableParam
.bScaleTo
= false;
982 aTableParam
.bScalePageNum
= false;
983 aTableParam
.nScaleAll
= 0;
984 aTableParam
.nScaleWidth
= 0;
985 aTableParam
.nScaleHeight
= 0;
986 aTableParam
.nScalePageNum
= 0;
989 // skip empty pages only if options with that flag are passed
990 aTableParam
.bSkipEmpty
= pOptions
&& pOptions
->GetSkipEmpty();
992 aTableParam
.bSkipEmpty
= false;
993 // If pPageData is set, only the breaks are interesting for the
994 // pagebreak preview, empty pages are not addressed separately.
996 aTableParam
.bForceBreaks
= pOptions
&& pOptions
->GetForceBreaks();
1000 //! walk through all PrintAreas of the table !!!
1001 const ScRange
* pPrintArea
= rDoc
.GetPrintRange( nPrintTab
, 0 );
1002 std::optional
<ScRange
> oRepeatCol
= rDoc
.GetRepeatColRange( nPrintTab
);
1003 std::optional
<ScRange
> oRepeatRow
= rDoc
.GetRepeatRowRange( nPrintTab
);
1005 // ignoring ATTR_PAGE_PRINTTABLES
1007 bool bHasPrintRange
= rDoc
.HasPrintRange();
1008 sal_uInt16 nPrintRangeCount
= rDoc
.GetPrintRangeCount(nPrintTab
);
1009 bool bPrintEntireSheet
= rDoc
.IsPrintEntireSheet(nPrintTab
);
1011 if (!bPrintEntireSheet
&& !nPrintRangeCount
)
1012 mbHasPrintRange
= false;
1014 if ( pUserArea
) // UserArea (selection) has priority
1016 bPrintCurrentTable
=
1017 aAreaParam
.bPrintArea
= true; // Selection
1018 aAreaParam
.aPrintArea
= *pUserArea
;
1020 // The table-query is already in DocShell::Print, here always
1021 aAreaParam
.aPrintArea
.aStart
.SetTab(nPrintTab
);
1022 aAreaParam
.aPrintArea
.aEnd
.SetTab(nPrintTab
);
1024 else if (bHasPrintRange
)
1026 if ( pPrintArea
) // at least one set?
1028 bPrintCurrentTable
=
1029 aAreaParam
.bPrintArea
= true;
1030 aAreaParam
.aPrintArea
= *pPrintArea
;
1032 bMultiArea
= nPrintRangeCount
> 1;
1036 // do not print hidden sheets with "Print entire sheet" flag
1037 bPrintCurrentTable
= rDoc
.IsPrintEntireSheet( nPrintTab
) && rDoc
.IsVisible( nPrintTab
);
1038 aAreaParam
.bPrintArea
= !bPrintCurrentTable
; // otherwise the table is always counted
1043 // don't print hidden tables if there's no print range defined there
1044 if ( rDoc
.IsVisible( nPrintTab
) )
1046 aAreaParam
.bPrintArea
= false;
1047 bPrintCurrentTable
= true;
1051 aAreaParam
.bPrintArea
= true; // otherwise the table is always counted
1052 bPrintCurrentTable
= false;
1058 aAreaParam
.bRepeatCol
= true;
1059 nRepeatStartCol
= oRepeatCol
->aStart
.Col();
1060 nRepeatEndCol
= oRepeatCol
->aEnd
.Col();
1064 aAreaParam
.bRepeatCol
= false;
1065 nRepeatStartCol
= nRepeatEndCol
= SCCOL_REPEAT_NONE
;
1070 aAreaParam
.bRepeatRow
= true;
1071 nRepeatStartRow
= oRepeatRow
->aStart
.Row();
1072 nRepeatEndRow
= oRepeatRow
->aEnd
.Row();
1076 aAreaParam
.bRepeatRow
= false;
1077 nRepeatStartRow
= nRepeatEndRow
= SCROW_REPEAT_NONE
;
1082 if (!bPrintAreaValid
)
1084 nTabPages
= CountPages(); // also calculates zoom
1085 nTotalPages
= nTabPages
;
1086 nTotalPages
+= CountNotePages();
1090 CalcPages(); // search breaks only
1091 CountNotePages(); // Count notes, even if number of pages is already known
1095 aFieldData
.nTotalPages
= nDocPages
;
1097 aFieldData
.nTotalPages
= nTotalPages
;
1099 SetDateTime( DateTime( DateTime::SYSTEM
) );
1101 if( pDocShell
->getDocProperties()->getTitle().getLength() != 0 )
1102 aFieldData
.aTitle
= pDocShell
->getDocProperties()->getTitle();
1104 aFieldData
.aTitle
= pDocShell
->GetTitle();
1106 const INetURLObject
& rURLObj
= pDocShell
->GetMedium()->GetURLObject();
1107 aFieldData
.aLongDocName
= rURLObj
.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous
);
1108 if ( !aFieldData
.aLongDocName
.isEmpty() )
1109 aFieldData
.aShortDocName
= rURLObj
.GetLastName(INetURLObject::DecodeMechanism::Unambiguous
);
1111 aFieldData
.aShortDocName
= aFieldData
.aLongDocName
= aFieldData
.aTitle
;
1113 // Printer settings (Orientation, Paper) at DoPrint
1116 Size
ScPrintFunc::GetDataSize() const
1118 Size aSize
= aPageSize
;
1119 aSize
.AdjustWidth( -(nLeftMargin
+ nRightMargin
) );
1120 aSize
.AdjustHeight( -(nTopMargin
+ nBottomMargin
) );
1121 aSize
.AdjustHeight( -(aHdr
.nHeight
+ aFtr
.nHeight
) );
1125 void ScPrintFunc::GetScaleData( Size
& rPhysSize
, tools::Long
& rDocHdr
, tools::Long
& rDocFtr
)
1127 rPhysSize
= aPageSize
;
1128 rPhysSize
.AdjustWidth( -(nLeftMargin
+ nRightMargin
) );
1129 rPhysSize
.AdjustHeight( -(nTopMargin
+ nBottomMargin
) );
1131 rDocHdr
= aHdr
.nHeight
;
1132 rDocFtr
= aFtr
.nHeight
;
1135 void ScPrintFunc::SetDateTime( const DateTime
& rDateTime
)
1137 aFieldData
.aDateTime
= rDateTime
;
1140 static void lcl_DrawGraphic( const Graphic
&rGraphic
, vcl::RenderContext
& rOutDev
,
1141 const tools::Rectangle
&rGrf
, const tools::Rectangle
&rOut
)
1143 const bool bNotInside
= !rOut
.Contains( rGrf
);
1147 rOutDev
.IntersectClipRegion( rOut
);
1150 rGraphic
.Draw(rOutDev
, rGrf
.TopLeft(), rGrf
.GetSize());
1156 static void lcl_DrawGraphic( const SvxBrushItem
&rBrush
, vcl::RenderContext
& rOutDev
, const OutputDevice
* pRefDev
,
1157 const tools::Rectangle
&rOrg
, const tools::Rectangle
&rOut
,
1158 OUString
const & referer
)
1161 const Graphic
*pGraphic
= rBrush
.GetGraphic(referer
);
1162 SvxGraphicPosition ePos
;
1163 if ( pGraphic
&& pGraphic
->IsSupportedGraphic() )
1165 const MapMode
aMapMM( MapUnit::Map100thMM
);
1166 if ( pGraphic
->GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel
)
1167 aGrfSize
= pRefDev
->PixelToLogic( pGraphic
->GetPrefSize(), aMapMM
);
1169 aGrfSize
= OutputDevice::LogicToLogic( pGraphic
->GetPrefSize(),
1170 pGraphic
->GetPrefMapMode(), aMapMM
);
1171 ePos
= rBrush
.GetGraphicPos();
1177 Size aDrawSize
= aGrfSize
;
1182 case GPOS_LT
: aPos
= rOrg
.TopLeft();
1184 case GPOS_MT
: aPos
.setY( rOrg
.Top() );
1185 aPos
.setX( rOrg
.Left() + rOrg
.GetSize().Width()/2 - aGrfSize
.Width()/2 );
1187 case GPOS_RT
: aPos
.setY( rOrg
.Top() );
1188 aPos
.setX( rOrg
.Right() - aGrfSize
.Width() );
1191 case GPOS_LM
: aPos
.setY( rOrg
.Top() + rOrg
.GetSize().Height()/2 - aGrfSize
.Height()/2 );
1192 aPos
.setX( rOrg
.Left() );
1194 case GPOS_MM
: aPos
.setY( rOrg
.Top() + rOrg
.GetSize().Height()/2 - aGrfSize
.Height()/2 );
1195 aPos
.setX( rOrg
.Left() + rOrg
.GetSize().Width()/2 - aGrfSize
.Width()/2 );
1197 case GPOS_RM
: aPos
.setY( rOrg
.Top() + rOrg
.GetSize().Height()/2 - aGrfSize
.Height()/2 );
1198 aPos
.setX( rOrg
.Right() - aGrfSize
.Width() );
1201 case GPOS_LB
: aPos
.setY( rOrg
.Bottom() - aGrfSize
.Height() );
1202 aPos
.setX( rOrg
.Left() );
1204 case GPOS_MB
: aPos
.setY( rOrg
.Bottom() - aGrfSize
.Height() );
1205 aPos
.setX( rOrg
.Left() + rOrg
.GetSize().Width()/2 - aGrfSize
.Width()/2 );
1207 case GPOS_RB
: aPos
.setY( rOrg
.Bottom() - aGrfSize
.Height() );
1208 aPos
.setX( rOrg
.Right() - aGrfSize
.Width() );
1212 aPos
= rOrg
.TopLeft();
1213 aDrawSize
= rOrg
.GetSize();
1217 // use GraphicObject::DrawTiled instead of an own loop
1218 // (pixel rounding is handled correctly, and a very small bitmap
1219 // is duplicated into a bigger one for better performance)
1221 GraphicObject
aObject( *pGraphic
);
1223 if( rOutDev
.GetOutDevType() == OUTDEV_PDF
&&
1224 (aObject
.GetType() == GraphicType::Bitmap
|| aObject
.GetType() == GraphicType::Default
) )
1226 // For PDF export, every draw
1227 // operation for bitmaps takes a noticeable
1228 // amount of place (~50 characters). Thus,
1229 // optimize between tile bitmap size and
1230 // number of drawing operations here.
1233 // n_chars = k1 * ---------- + k2 * A_bitmap
1236 // minimum n_chars is obtained for (derive for
1237 // A_bitmap, set to 0, take positive
1240 // A_bitmap = Sqrt( ---- A_out )
1243 // where k1 is the number of chars per draw
1244 // operation, and k2 is the number of chars
1245 // per bitmap pixel. This is approximately 50
1246 // and 7 for current PDF writer, respectively.
1248 const double k1( 50 );
1249 const double k2( 7 );
1250 const Size
aSize( rOrg
.GetSize() );
1251 const double Abitmap( k1
/k2
* aSize
.Width()*aSize
.Height() );
1253 aObject
.DrawTiled( rOutDev
, rOrg
, aGrfSize
, Size(0,0),
1254 ::std::max( 128, static_cast<int>( sqrt(sqrt( Abitmap
)) + .5 ) ) );
1258 aObject
.DrawTiled( rOutDev
, rOrg
, aGrfSize
, Size(0,0) );
1269 default: OSL_ENSURE( false, "new Graphic position?" );
1271 tools::Rectangle
aGrf( aPos
,aDrawSize
);
1272 if ( bDraw
&& aGrf
.Overlaps( rOut
) )
1274 lcl_DrawGraphic( *pGraphic
, rOutDev
, aGrf
, rOut
);
1278 // The frame is drawn inwards
1280 void ScPrintFunc::DrawBorder( tools::Long nScrX
, tools::Long nScrY
, tools::Long nScrW
, tools::Long nScrH
,
1281 const SvxBoxItem
* pBorderData
, const SvxBrushItem
* pBackground
,
1282 const SvxShadowItem
* pShadow
)
1284 //! direct output from SvxBoxItem !!!
1287 if ( !pBorderData
->GetTop() && !pBorderData
->GetBottom() && !pBorderData
->GetLeft() &&
1288 !pBorderData
->GetRight() )
1289 pBorderData
= nullptr;
1291 if (!pBorderData
&& !pBackground
&& !pShadow
)
1292 return; // nothing to do
1294 tools::Long nLeft
= 0;
1295 tools::Long nRight
= 0;
1296 tools::Long nTop
= 0;
1297 tools::Long nBottom
= 0;
1299 // aFrameRect - outside around frame, without shadow
1300 if ( pShadow
&& pShadow
->GetLocation() != SvxShadowLocation::NONE
)
1302 nLeft
+= static_cast<tools::Long
>( pShadow
->CalcShadowSpace(SvxShadowItemSide::LEFT
) * nScaleX
);
1303 nRight
+= static_cast<tools::Long
>( pShadow
->CalcShadowSpace(SvxShadowItemSide::RIGHT
) * nScaleX
);
1304 nTop
+= static_cast<tools::Long
>( pShadow
->CalcShadowSpace(SvxShadowItemSide::TOP
) * nScaleY
);
1305 nBottom
+= static_cast<tools::Long
>( pShadow
->CalcShadowSpace(SvxShadowItemSide::BOTTOM
) * nScaleY
);
1307 tools::Rectangle
aFrameRect( Point(nScrX
+nLeft
, nScrY
+nTop
),
1308 Size(nScrW
-nLeft
-nRight
, nScrH
-nTop
-nBottom
) );
1310 // center of frame, to paint lines through OutputData
1313 nLeft
+= static_cast<tools::Long
>( lcl_LineTotal(pBorderData
->GetLeft()) * nScaleX
/ 2 );
1314 nRight
+= static_cast<tools::Long
>( lcl_LineTotal(pBorderData
->GetRight()) * nScaleX
/ 2 );
1315 nTop
+= static_cast<tools::Long
>( lcl_LineTotal(pBorderData
->GetTop()) * nScaleY
/ 2 );
1316 nBottom
+= static_cast<tools::Long
>( lcl_LineTotal(pBorderData
->GetBottom()) * nScaleY
/ 2 );
1318 tools::Long nEffHeight
= nScrH
- nTop
- nBottom
;
1319 tools::Long nEffWidth
= nScrW
- nLeft
- nRight
;
1320 if (nEffHeight
<=0 || nEffWidth
<=0)
1325 if (pBackground
->GetGraphicPos() != GPOS_NONE
)
1327 OutputDevice
* pRefDev
;
1329 pRefDev
= pDev
; // don't use printer for PDF
1331 pRefDev
= rDoc
.GetPrinter(); // use printer also for preview
1333 if (pDocShell
->HasName()) {
1334 referer
= pDocShell
->GetMedium()->GetName();
1336 lcl_DrawGraphic(*pBackground
, *pDev
, pRefDev
, aFrameRect
, aFrameRect
, referer
);
1340 pDev
->SetFillColor(pBackground
->GetColor());
1341 pDev
->SetLineColor();
1342 pDev
->DrawRect(aFrameRect
);
1346 if ( pShadow
&& pShadow
->GetLocation() != SvxShadowLocation::NONE
)
1348 pDev
->SetFillColor(pShadow
->GetColor());
1349 pDev
->SetLineColor();
1350 tools::Long nShadowX
= static_cast<tools::Long
>( pShadow
->GetWidth() * nScaleX
);
1351 tools::Long nShadowY
= static_cast<tools::Long
>( pShadow
->GetWidth() * nScaleY
);
1352 switch (pShadow
->GetLocation())
1354 case SvxShadowLocation::TopLeft
:
1355 pDev
->DrawRect( tools::Rectangle(
1356 aFrameRect
.Left()-nShadowX
, aFrameRect
.Top()-nShadowY
,
1357 aFrameRect
.Right()-nShadowX
, aFrameRect
.Top() ) );
1358 pDev
->DrawRect( tools::Rectangle(
1359 aFrameRect
.Left()-nShadowX
, aFrameRect
.Top()-nShadowY
,
1360 aFrameRect
.Left(), aFrameRect
.Bottom()-nShadowY
) );
1362 case SvxShadowLocation::TopRight
:
1363 pDev
->DrawRect( tools::Rectangle(
1364 aFrameRect
.Left()+nShadowX
, aFrameRect
.Top()-nShadowY
,
1365 aFrameRect
.Right()+nShadowX
, aFrameRect
.Top() ) );
1366 pDev
->DrawRect( tools::Rectangle(
1367 aFrameRect
.Right(), aFrameRect
.Top()-nShadowY
,
1368 aFrameRect
.Right()+nShadowX
, aFrameRect
.Bottom()-nShadowY
) );
1370 case SvxShadowLocation::BottomLeft
:
1371 pDev
->DrawRect( tools::Rectangle(
1372 aFrameRect
.Left()-nShadowX
, aFrameRect
.Bottom(),
1373 aFrameRect
.Right()-nShadowX
, aFrameRect
.Bottom()+nShadowY
) );
1374 pDev
->DrawRect( tools::Rectangle(
1375 aFrameRect
.Left()-nShadowX
, aFrameRect
.Top()+nShadowY
,
1376 aFrameRect
.Left(), aFrameRect
.Bottom()+nShadowY
) );
1378 case SvxShadowLocation::BottomRight
:
1379 pDev
->DrawRect( tools::Rectangle(
1380 aFrameRect
.Left()+nShadowX
, aFrameRect
.Bottom(),
1381 aFrameRect
.Right()+nShadowX
, aFrameRect
.Bottom()+nShadowY
) );
1382 pDev
->DrawRect( tools::Rectangle(
1383 aFrameRect
.Right(), aFrameRect
.Top()+nShadowY
,
1384 aFrameRect
.Right()+nShadowX
, aFrameRect
.Bottom()+nShadowY
) );
1388 // added to avoid warnings
1396 ScDocumentUniquePtr
pBorderDoc(new ScDocument( SCDOCMODE_UNDO
));
1397 pBorderDoc
->InitUndo( rDoc
, 0,0, true,true );
1398 pBorderDoc
->ApplyAttr( 0,0,0, *pBorderData
);
1400 ScTableInfo
aTabInfo(0, 1, false);
1401 pBorderDoc
->FillInfo( aTabInfo
, 0,0, 0,0, 0,
1402 nScaleX
, nScaleY
, false, false );
1403 OSL_ENSURE(aTabInfo
.mnArrCount
,"nArrCount == 0");
1405 aTabInfo
.mpRowInfo
[1].nHeight
= static_cast<sal_uInt16
>(nEffHeight
);
1406 aTabInfo
.mpRowInfo
[0].basicCellInfo(0).nWidth
=
1407 aTabInfo
.mpRowInfo
[1].basicCellInfo(0).nWidth
= static_cast<sal_uInt16
>(nEffWidth
);
1409 ScOutputData
aOutputData( pDev
, OUTTYPE_PRINTER
, aTabInfo
, pBorderDoc
.get(), 0,
1410 nScrX
+nLeft
, nScrY
+nTop
, 0,0, 0,0, nScaleX
, nScaleY
);
1411 aOutputData
.SetUseStyleColor( bUseStyleColor
);
1413 aOutputData
.DrawFrame(*pDev
);
1416 void ScPrintFunc::PrintColHdr( SCCOL nX1
, SCCOL nX2
, tools::Long nScrX
, tools::Long nScrY
)
1418 bool bLayoutRTL
= rDoc
.IsLayoutRTL( nPrintTab
);
1419 tools::Long nLayoutSign
= bLayoutRTL
? -1 : 1;
1421 Size aOnePixel
= pDev
->PixelToLogic(Size(1,1));
1422 tools::Long nOneX
= aOnePixel
.Width();
1423 tools::Long nOneY
= aOnePixel
.Height();
1426 tools::Long nHeight
= static_cast<tools::Long
>(PRINT_HEADER_HEIGHT
* nScaleY
);
1427 tools::Long nEndY
= nScrY
+ nHeight
- nOneY
;
1429 tools::Long nPosX
= nScrX
;
1432 for (nCol
=nX1
; nCol
<=nX2
; nCol
++)
1433 nPosX
+= static_cast<tools::Long
>( rDoc
.GetColWidth( nCol
, nPrintTab
) * nScaleX
);
1437 tools::Long nPosY
= nScrY
- nOneY
;
1440 for (nCol
=nX1
; nCol
<=nX2
; nCol
++)
1442 sal_uInt16 nDocW
= rDoc
.GetColWidth( nCol
, nPrintTab
);
1445 tools::Long nWidth
= static_cast<tools::Long
>(nDocW
* nScaleX
);
1446 tools::Long nEndX
= nPosX
+ nWidth
* nLayoutSign
;
1448 pDev
->DrawRect( tools::Rectangle( nPosX
,nPosY
,nEndX
,nEndY
) );
1450 aText
= ::ScColToAlpha( nCol
);
1451 tools::Long nTextWidth
= pDev
->GetTextWidth(aText
);
1452 tools::Long nTextHeight
= pDev
->GetTextHeight();
1453 tools::Long nAddX
= ( nWidth
- nTextWidth
) / 2;
1454 tools::Long nAddY
= ( nHeight
- nTextHeight
) / 2;
1455 tools::Long nTextPosX
= nPosX
+nAddX
;
1457 nTextPosX
-= nWidth
;
1458 pDev
->DrawText( Point( nTextPosX
,nPosY
+nAddY
), aText
);
1465 void ScPrintFunc::PrintRowHdr( SCROW nY1
, SCROW nY2
, tools::Long nScrX
, tools::Long nScrY
)
1467 Size aOnePixel
= pDev
->PixelToLogic(Size(1,1));
1468 tools::Long nOneX
= aOnePixel
.Width();
1469 tools::Long nOneY
= aOnePixel
.Height();
1471 bool bLayoutRTL
= rDoc
.IsLayoutRTL( nPrintTab
);
1473 tools::Long nWidth
= static_cast<tools::Long
>(PRINT_HEADER_WIDTH
* nScaleX
);
1474 tools::Long nEndX
= nScrX
+ nWidth
;
1475 tools::Long nPosX
= nScrX
;
1481 tools::Long nPosY
= nScrY
- nOneY
;
1484 for (SCROW nRow
=nY1
; nRow
<=nY2
; nRow
++)
1486 sal_uInt16 nDocH
= rDoc
.GetRowHeight( nRow
, nPrintTab
);
1489 tools::Long nHeight
= static_cast<tools::Long
>(nDocH
* nScaleY
);
1490 tools::Long nEndY
= nPosY
+ nHeight
;
1492 pDev
->DrawRect( tools::Rectangle( nPosX
,nPosY
,nEndX
,nEndY
) );
1494 aText
= OUString::number( nRow
+1 );
1495 tools::Long nTextWidth
= pDev
->GetTextWidth(aText
);
1496 tools::Long nTextHeight
= pDev
->GetTextHeight();
1497 tools::Long nAddX
= ( nWidth
- nTextWidth
) / 2;
1498 tools::Long nAddY
= ( nHeight
- nTextHeight
) / 2;
1499 pDev
->DrawText( Point( nPosX
+nAddX
,nPosY
+nAddY
), aText
);
1506 void ScPrintFunc::LocateColHdr( SCCOL nX1
, SCCOL nX2
, tools::Long nScrX
, tools::Long nScrY
,
1507 bool bRepCol
, ScPreviewLocationData
& rLocationData
)
1509 Size aOnePixel
= pDev
->PixelToLogic(Size(1,1));
1510 tools::Long nOneX
= aOnePixel
.Width();
1511 tools::Long nOneY
= aOnePixel
.Height();
1513 tools::Long nHeight
= static_cast<tools::Long
>(PRINT_HEADER_HEIGHT
* nScaleY
);
1514 tools::Long nEndY
= nScrY
+ nHeight
- nOneY
;
1516 tools::Long nPosX
= nScrX
- nOneX
;
1517 for (SCCOL nCol
=nX1
; nCol
<=nX2
; nCol
++)
1519 sal_uInt16 nDocW
= rDoc
.GetColWidth( nCol
, nPrintTab
);
1521 nPosX
+= static_cast<tools::Long
>(nDocW
* nScaleX
);
1523 tools::Rectangle
aCellRect( nScrX
, nScrY
, nPosX
, nEndY
);
1524 rLocationData
.AddColHeaders( aCellRect
, nX1
, nX2
, bRepCol
);
1527 void ScPrintFunc::LocateRowHdr( SCROW nY1
, SCROW nY2
, tools::Long nScrX
, tools::Long nScrY
,
1528 bool bRepRow
, ScPreviewLocationData
& rLocationData
)
1530 Size aOnePixel
= pDev
->PixelToLogic(Size(1,1));
1531 tools::Long nOneX
= aOnePixel
.Width();
1532 tools::Long nOneY
= aOnePixel
.Height();
1534 bool bLayoutRTL
= rDoc
.IsLayoutRTL( nPrintTab
);
1536 tools::Long nWidth
= static_cast<tools::Long
>(PRINT_HEADER_WIDTH
* nScaleX
);
1537 tools::Long nEndX
= nScrX
+ nWidth
;
1541 tools::Long nPosY
= nScrY
- nOneY
;
1542 nPosY
+= rDoc
.GetScaledRowHeight( nY1
, nY2
, nPrintTab
, nScaleY
);
1543 tools::Rectangle
aCellRect( nScrX
, nScrY
, nEndX
, nPosY
);
1544 rLocationData
.AddRowHeaders( aCellRect
, nY1
, nY2
, bRepRow
);
1547 void ScPrintFunc::LocateArea( SCCOL nX1
, SCROW nY1
, SCCOL nX2
, SCROW nY2
,
1548 tools::Long nScrX
, tools::Long nScrY
, bool bRepCol
, bool bRepRow
,
1549 ScPreviewLocationData
& rLocationData
)
1551 // get MapMode for drawing objects (same MapMode as in ScOutputData::PrintDrawingLayer)
1553 Point aLogPos
= OutputDevice::LogicToLogic(Point(nScrX
,nScrY
), aOffsetMode
, aLogicMode
);
1554 tools::Long nLogStX
= aLogPos
.X();
1555 tools::Long nLogStY
= aLogPos
.Y();
1559 for (nCol
=0; nCol
<nX1
; nCol
++)
1560 aTwipOffset
.AdjustX( -(rDoc
.GetColWidth( nCol
, nPrintTab
)) );
1561 aTwipOffset
.AdjustY( -sal_Int32(rDoc
.GetRowHeight( 0, nY1
-1, nPrintTab
)) );
1563 Point
aMMOffset(o3tl::convert(aTwipOffset
, o3tl::Length::twip
, o3tl::Length::mm100
));
1564 aMMOffset
+= Point( nLogStX
, nLogStY
);
1565 MapMode
aDrawMapMode( MapUnit::Map100thMM
, aMMOffset
, aLogicMode
.GetScaleX(), aLogicMode
.GetScaleY() );
1567 // get pixel rectangle
1569 Size aOnePixel
= pDev
->PixelToLogic(Size(1,1));
1570 tools::Long nOneX
= aOnePixel
.Width();
1571 tools::Long nOneY
= aOnePixel
.Height();
1573 tools::Long nPosX
= nScrX
- nOneX
;
1574 for (nCol
=nX1
; nCol
<=nX2
; nCol
++)
1576 sal_uInt16 nDocW
= rDoc
.GetColWidth( nCol
, nPrintTab
);
1578 nPosX
+= static_cast<tools::Long
>(nDocW
* nScaleX
);
1581 tools::Long nPosY
= nScrY
- nOneY
;
1582 nPosY
+= rDoc
.GetScaledRowHeight( nY1
, nY2
, nPrintTab
, nScaleY
);
1583 tools::Rectangle
aCellRect( nScrX
, nScrY
, nPosX
, nPosY
);
1584 rLocationData
.AddCellRange( aCellRect
, ScRange( nX1
,nY1
,nPrintTab
, nX2
,nY2
,nPrintTab
),
1585 bRepCol
, bRepRow
, aDrawMapMode
);
1588 void ScPrintFunc::PrintArea( SCCOL nX1
, SCROW nY1
, SCCOL nX2
, SCROW nY2
,
1589 tools::Long nScrX
, tools::Long nScrY
,
1590 bool bShLeft
, bool bShTop
, bool bShRight
, bool bShBottom
)
1592 // #i47547# nothing to do if the end of the print area is before the end of
1593 // the repeat columns/rows (don't use negative size for ScOutputData)
1594 if ( nX2
< nX1
|| nY2
< nY1
)
1597 //! hand over Flag at FillInfo !!!!!
1599 bool bEmbed
= rDoc
.IsEmbedded();
1602 rDoc
.GetEmbedded(aERange
);
1603 rDoc
.ResetEmbedded();
1606 Point aPos
= OutputDevice::LogicToLogic(Point(nScrX
,nScrY
), aOffsetMode
, aLogicMode
);
1607 tools::Long nLogStX
= aPos
.X();
1608 tools::Long nLogStY
= aPos
.Y();
1612 ScTableInfo
aTabInfo(nY1
, nY2
, true);
1613 rDoc
.FillInfo( aTabInfo
, nX1
, nY1
, nX2
, nY2
, nPrintTab
,
1614 nScaleX
, nScaleY
, true, aTableParam
.bFormulas
);
1615 lcl_HidePrint( aTabInfo
, nX1
, nX2
);
1618 rDoc
.SetEmbedded(aERange
);
1620 ScOutputData
aOutputData( pDev
, OUTTYPE_PRINTER
, aTabInfo
, &rDoc
, nPrintTab
,
1621 nScrX
, nScrY
, nX1
, nY1
, nX2
, nY2
, nScaleX
, nScaleY
);
1623 vcl::PDFExtOutDevData
* pPDF
= dynamic_cast<vcl::PDFExtOutDevData
*>(pDev
->GetExtOutDevData());
1624 bool bTaggedPDF
= pPDF
&& pPDF
->GetIsExportTaggedPDF();
1627 bool bReopen
= aOutputData
.ReopenPDFStructureElement(vcl::PDFWriter::Part
);
1630 sal_Int32 nId
= pPDF
->EnsureStructureElement(nullptr);
1631 pPDF
->InitStructureElement(nId
, vcl::PDFWriter::Part
, u
"Worksheet"_ustr
);
1632 pPDF
->BeginStructureElement(nId
);
1633 pPDF
->GetScPDFState()->m_WorksheetId
= nId
;
1637 aOutputData
.SetDrawView( pDrawView
);
1639 // test if all paint parts are hidden, then a paint is not necessary at all
1640 const Point
aMMOffset(aOutputData
.PrePrintDrawingLayer(nLogStX
, nLogStY
));
1641 const bool bHideAllDrawingLayer( pDrawView
&& pDrawView
->getHideOle() && pDrawView
->getHideChart()
1642 && pDrawView
->getHideDraw() && pDrawView
->getHideFormControl() );
1644 if(!bHideAllDrawingLayer
)
1646 pDev
->SetMapMode(aLogicMode
);
1647 // don's set Clipping here (Mapmode is being moved)
1650 aOutputData
.PrintDrawingLayer(SC_LAYER_BACK
, aMMOffset
);
1653 pDev
->SetMapMode(aOffsetMode
);
1655 aOutputData
.SetShowFormulas( aTableParam
.bFormulas
);
1656 aOutputData
.SetShowNullValues( aTableParam
.bNullVals
);
1657 aOutputData
.SetUseStyleColor( bUseStyleColor
);
1659 Color
aGridColor( COL_BLACK
);
1660 if ( bUseStyleColor
)
1661 aGridColor
= ScModule::get()->GetColorConfig().GetColorValue(svtools::FONTCOLOR
).nColor
;
1662 aOutputData
.SetGridColor( aGridColor
);
1666 OutputDevice
* pRefDev
= rDoc
.GetPrinter(); // use the printer also for Preview
1667 Fraction
aPrintFrac( nZoom
, 100 ); // without nManualZoom
1668 // MapMode, as it would arrive at the printer:
1669 pRefDev
->SetMapMode( MapMode( MapUnit::Map100thMM
, Point(), aPrintFrac
, aPrintFrac
) );
1671 // when rendering (PDF), don't use printer as ref device, but printer's MapMode
1672 // has to be set anyway, as charts still use it (#106409#)
1674 aOutputData
.SetRefDevice( pRefDev
);
1677 if( aTableParam
.bCellContent
)
1678 aOutputData
.DrawBackground(*pDev
);
1680 pDev
->SetClipRegion(vcl::Region(tools::Rectangle(
1681 aPos
, Size(aOutputData
.GetScrW(), aOutputData
.GetScrH()))));
1682 pDev
->SetClipRegion();
1684 if( aTableParam
.bCellContent
)
1686 aOutputData
.DrawExtraShadow( bShLeft
, bShTop
, bShRight
, bShBottom
);
1687 aOutputData
.DrawFrame(*pDev
);
1688 aOutputData
.DrawSparklines(*pDev
);
1689 aOutputData
.DrawStrings();
1690 aOutputData
.DrawEdit(false);
1693 if (aTableParam
.bGrid
)
1694 aOutputData
.DrawGrid(*pDev
, true, false); // no page breaks
1696 aOutputData
.AddPDFNotes(); // has no effect if not rendering PDF with notes enabled
1698 // test if all paint parts are hidden, then a paint is not necessary at all
1699 if(!bHideAllDrawingLayer
)
1702 aOutputData
.PrintDrawingLayer(SC_LAYER_FRONT
, aMMOffset
);
1707 aOutputData
.PrintDrawingLayer(SC_LAYER_CONTROLS
, aMMOffset
);
1708 pPDF
->EndStructureElement();
1712 aOutputData
.PrintDrawingLayer(SC_LAYER_INTERN
, aMMOffset
);
1715 aOutputData
.PostPrintDrawingLayer(aMMOffset
); // #i74768#
1718 bool ScPrintFunc::IsMirror( tools::Long nPageNo
) // Mirror margins?
1720 return nPageUsage
== SvxPageUsage::Mirror
&& (nPageNo
& 1);
1723 bool ScPrintFunc::IsLeft( tools::Long nPageNo
) // left foot notes?
1726 if (nPageUsage
== SvxPageUsage::Left
)
1728 else if (nPageUsage
== SvxPageUsage::Right
)
1731 bLeft
= (nPageNo
& 1) != 0;
1735 void ScPrintFunc::MakeTableString()
1738 rDoc
.GetName(nPrintTab
, aTmp
);
1739 aFieldData
.aTabName
= aTmp
;
1742 void ScPrintFunc::MakeEditEngine()
1746 // can't use document's edit engine pool here,
1747 // because pool must have twips as default metric
1748 pEditEngine
.reset( new ScHeaderEditEngine( EditEngine::CreatePool().get() ) );
1750 pEditEngine
->EnableUndo(false);
1751 //fdo#45869 we want text to be positioned as it would be for the
1752 //high dpi printed output, not as would be ideal for the 96dpi preview
1754 pEditEngine
->SetRefDevice(pPrinter
? pPrinter
: rDoc
.GetRefDevice());
1755 pEditEngine
->SetWordDelimiters(
1756 ScEditUtil::ModifyDelimiters( pEditEngine
->GetWordDelimiters() ) );
1757 pEditEngine
->SetControlWord( pEditEngine
->GetControlWord() & ~EEControlBits::RTFSTYLESHEETS
);
1758 rDoc
.ApplyAsianEditSettings( *pEditEngine
);
1759 pEditEngine
->EnableAutoColor( bUseStyleColor
);
1761 // Default-Set for alignment
1762 pEditDefaults
.reset( new SfxItemSet( pEditEngine
->GetEmptyItemSet() ) );
1764 const ScPatternAttr
& rPattern(rDoc
.getCellAttributeHelper().getDefaultCellAttribute());
1766 rPattern
.FillEditItemSet( pEditDefaults
.get() );
1767 // FillEditItemSet adjusts font height to 1/100th mm,
1768 // but for header/footer twips is needed, as in the PatternAttr:
1769 pEditDefaults
->Put( rPattern
.GetItem(ATTR_FONT_HEIGHT
).CloneSetWhich(EE_CHAR_FONTHEIGHT
) );
1770 pEditDefaults
->Put( rPattern
.GetItem(ATTR_CJK_FONT_HEIGHT
).CloneSetWhich(EE_CHAR_FONTHEIGHT_CJK
) );
1771 pEditDefaults
->Put( rPattern
.GetItem(ATTR_CTL_FONT_HEIGHT
).CloneSetWhich(EE_CHAR_FONTHEIGHT_CTL
) );
1772 // don't use font color, because background color is not used
1773 //! there's no way to set the background for note pages
1774 pEditDefaults
->ClearItem( EE_CHAR_COLOR
);
1775 if (ScGlobal::IsSystemRTL())
1776 pEditDefaults
->Put( SvxFrameDirectionItem( SvxFrameDirection::Horizontal_RL_TB
, EE_PARA_WRITINGDIR
) );
1779 pEditEngine
->SetData( aFieldData
); // Set page count etc.
1783 void ScPrintFunc::PrintHF( tools::Long nPageNo
, bool bHeader
, tools::Long nStartY
,
1784 bool bDoPrint
, ScPreviewLocationData
* pLocationData
)
1786 vcl::PDFExtOutDevData
* pPDF
= dynamic_cast<vcl::PDFExtOutDevData
*>(pDev
->GetExtOutDevData());
1787 bool bTaggedPDF
= pPDF
&& pPDF
->GetIsExportTaggedPDF();
1789 pPDF
->WrapBeginStructureElement(vcl::PDFWriter::NonStructElement
);
1791 const ScPrintHFParam
& rParam
= bHeader
? aHdr
: aFtr
;
1793 pDev
->SetMapMode( aTwipMode
); // Head-/Footlines in Twips
1795 bool bFirst
= 0 == nPageNo
&& !rParam
.bSharedFirst
;
1796 bool bLeft
= IsLeft(nPageNo
) && !rParam
.bShared
;
1797 const ScPageHFItem
* pHFItem
= bFirst
? rParam
.pFirst
: (bLeft
? rParam
.pLeft
: rParam
.pRight
);
1799 tools::Long nLineStartX
= aPageRect
.Left() + rParam
.nLeft
;
1800 tools::Long nLineEndX
= aPageRect
.Right() - rParam
.nRight
;
1801 tools::Long nLineWidth
= nLineEndX
- nLineStartX
+ 1;
1805 Point
aStart( nLineStartX
, nStartY
);
1806 Size
aPaperSize( nLineWidth
, rParam
.nHeight
-rParam
.nDistance
);
1807 if ( rParam
.pBorder
)
1809 tools::Long nLeft
= lcl_LineTotal( rParam
.pBorder
->GetLeft() ) + rParam
.pBorder
->GetDistance(SvxBoxItemLine::LEFT
);
1810 tools::Long nTop
= lcl_LineTotal( rParam
.pBorder
->GetTop() ) + rParam
.pBorder
->GetDistance(SvxBoxItemLine::TOP
);
1811 aStart
.AdjustX(nLeft
);
1812 aStart
.AdjustY(nTop
);
1813 aPaperSize
.AdjustWidth( -(nLeft
+ lcl_LineTotal( rParam
.pBorder
->GetRight() ) + rParam
.pBorder
->GetDistance(SvxBoxItemLine::RIGHT
)) );
1814 aPaperSize
.AdjustHeight( -(nTop
+ lcl_LineTotal( rParam
.pBorder
->GetBottom() ) + rParam
.pBorder
->GetDistance(SvxBoxItemLine::BOTTOM
)) );
1817 if ( rParam
.pShadow
&& rParam
.pShadow
->GetLocation() != SvxShadowLocation::NONE
)
1819 tools::Long nLeft
= rParam
.pShadow
->CalcShadowSpace(SvxShadowItemSide::LEFT
);
1820 tools::Long nTop
= rParam
.pShadow
->CalcShadowSpace(SvxShadowItemSide::TOP
);
1821 aStart
.AdjustX(nLeft
);
1822 aStart
.AdjustY(nTop
);
1823 aPaperSize
.AdjustWidth( -(nLeft
+ rParam
.pShadow
->CalcShadowSpace(SvxShadowItemSide::RIGHT
)) );
1824 aPaperSize
.AdjustHeight( -(nTop
+ rParam
.pShadow
->CalcShadowSpace(SvxShadowItemSide::BOTTOM
)) );
1827 aFieldData
.nPageNo
= nPageNo
+aTableParam
.nFirstPageNo
;
1830 pEditEngine
->SetPaperSize(aPaperSize
);
1832 // Frame / Background
1834 Point
aBorderStart( nLineStartX
, nStartY
);
1835 Size
aBorderSize( nLineWidth
, rParam
.nHeight
-rParam
.nDistance
);
1836 if ( rParam
.bDynamic
)
1838 // adjust here again, for even/odd head-/footlines
1839 // and probably other breaks by variable (page number etc.)
1841 tools::Long nMaxHeight
= 0;
1842 nMaxHeight
= std::max( nMaxHeight
, TextHeight( pHFItem
->GetLeftArea() ) );
1843 nMaxHeight
= std::max( nMaxHeight
, TextHeight( pHFItem
->GetCenterArea() ) );
1844 nMaxHeight
= std::max( nMaxHeight
, TextHeight( pHFItem
->GetRightArea() ) );
1846 nMaxHeight
+= lcl_LineTotal( rParam
.pBorder
->GetTop() ) +
1847 lcl_LineTotal( rParam
.pBorder
->GetBottom() ) +
1848 rParam
.pBorder
->GetDistance(SvxBoxItemLine::TOP
) +
1849 rParam
.pBorder
->GetDistance(SvxBoxItemLine::BOTTOM
);
1850 if (rParam
.pShadow
&& rParam
.pShadow
->GetLocation() != SvxShadowLocation::NONE
)
1851 nMaxHeight
+= rParam
.pShadow
->CalcShadowSpace(SvxShadowItemSide::TOP
) +
1852 rParam
.pShadow
->CalcShadowSpace(SvxShadowItemSide::BOTTOM
);
1854 if (nMaxHeight
< rParam
.nManHeight
-rParam
.nDistance
)
1855 nMaxHeight
= rParam
.nManHeight
-rParam
.nDistance
; // configured Minimum
1857 aBorderSize
.setHeight( nMaxHeight
);
1862 double nOldScaleX
= nScaleX
;
1863 double nOldScaleY
= nScaleY
;
1864 nScaleX
= nScaleY
= 1.0; // output directly in Twips
1865 DrawBorder( aBorderStart
.X(), aBorderStart
.Y(), aBorderSize
.Width(), aBorderSize
.Height(),
1866 rParam
.pBorder
, rParam
.pBack
, rParam
.pShadow
);
1867 nScaleX
= nOldScaleX
;
1868 nScaleY
= nOldScaleY
;
1870 // Clipping for Text
1872 pDev
->SetClipRegion(vcl::Region(tools::Rectangle(aStart
, aPaperSize
)));
1876 const EditTextObject
* pObject
= pHFItem
->GetLeftArea();
1879 pEditDefaults
->Put( SvxAdjustItem( SvxAdjust::Left
, EE_PARA_JUST
) );
1880 pEditEngine
->SetTextTempDefaults(*pObject
, *pEditDefaults
);
1881 Point aDraw
= aStart
;
1882 tools::Long nDif
= aPaperSize
.Height() - static_cast<tools::Long
>(pEditEngine
->GetTextHeight());
1884 aDraw
.AdjustY(nDif
/ 2 );
1885 pEditEngine
->Draw(*pDev
, aDraw
);
1890 pObject
= pHFItem
->GetCenterArea();
1893 pEditDefaults
->Put( SvxAdjustItem( SvxAdjust::Center
, EE_PARA_JUST
) );
1894 pEditEngine
->SetTextTempDefaults(*pObject
, *pEditDefaults
);
1895 Point aDraw
= aStart
;
1896 tools::Long nDif
= aPaperSize
.Height() - static_cast<tools::Long
>(pEditEngine
->GetTextHeight());
1898 aDraw
.AdjustY(nDif
/ 2 );
1899 pEditEngine
->Draw(*pDev
, aDraw
);
1904 pObject
= pHFItem
->GetRightArea();
1907 pEditDefaults
->Put( SvxAdjustItem( SvxAdjust::Right
, EE_PARA_JUST
) );
1908 pEditEngine
->SetTextTempDefaults(*pObject
, *pEditDefaults
);
1909 Point aDraw
= aStart
;
1910 tools::Long nDif
= aPaperSize
.Height() - static_cast<tools::Long
>(pEditEngine
->GetTextHeight());
1912 aDraw
.AdjustY(nDif
/ 2 );
1913 pEditEngine
->Draw(*pDev
, aDraw
);
1916 pDev
->SetClipRegion();
1919 if ( pLocationData
)
1921 tools::Rectangle
aHeaderRect( aBorderStart
, aBorderSize
);
1922 pLocationData
->AddHeaderFooter( aHeaderRect
, bHeader
, bLeft
);
1926 pPDF
->EndStructureElement();
1929 tools::Long
ScPrintFunc::DoNotes( tools::Long nNoteStart
, bool bDoPrint
, ScPreviewLocationData
* pLocationData
)
1932 pDev
->SetMapMode(aTwipMode
);
1935 pEditDefaults
->Put( SvxAdjustItem( SvxAdjust::Left
, EE_PARA_JUST
) );
1936 pEditEngine
->SetDefaults( *pEditDefaults
);
1938 vcl::Font aMarkFont
;
1939 ScAutoFontColorMode eColorMode
= bUseStyleColor
? ScAutoFontColorMode::Display
: ScAutoFontColorMode::Print
;
1940 rDoc
.getCellAttributeHelper().getDefaultCellAttribute().fillFont(aMarkFont
, eColorMode
);
1941 pDev
->SetFont(aMarkFont
);
1942 tools::Long nMarkLen
= pDev
->GetTextWidth(u
"GW99999:"_ustr
);
1943 // without Space-Char, because it rarely arrives there
1945 Size aDataSize
= aPageRect
.GetSize();
1946 if ( nMarkLen
> aDataSize
.Width() / 2 ) // everything much too small?
1947 nMarkLen
= aDataSize
.Width() / 2; // split the page appropriately
1948 aDataSize
.AdjustWidth( -nMarkLen
);
1950 pEditEngine
->SetPaperSize( aDataSize
);
1951 tools::Long nPosX
= aPageRect
.Left() + nMarkLen
;
1952 tools::Long nPosY
= aPageRect
.Top();
1954 tools::Long nCount
= 0;
1955 tools::Long nSize
= aNotePosList
.size();
1960 if ( nNoteStart
+ nCount
< nSize
)
1962 ScAddress
&rPos
= aNotePosList
[ nNoteStart
+ nCount
];
1964 if( const ScPostIt
* pNote
= rDoc
.GetNote( rPos
) )
1966 if(const EditTextObject
*pEditText
= pNote
->GetEditTextObject())
1967 pEditEngine
->SetTextCurrentDefaults(*pEditText
);
1968 tools::Long nTextHeight
= pEditEngine
->GetTextHeight();
1969 if ( nPosY
+ nTextHeight
< aPageRect
.Bottom() )
1973 pEditEngine
->Draw(*pDev
, Point(nPosX
, nPosY
));
1975 OUString
aMarkStr(rPos
.Format(ScRefFlags::VALID
, &rDoc
, rDoc
.GetAddressConvention()) + ":");
1977 // cell position also via EditEngine, for correct positioning
1978 pEditEngine
->SetTextCurrentDefaults(aMarkStr
);
1979 pEditEngine
->Draw(*pDev
, Point(aPageRect
.Left(), nPosY
));
1982 if ( pLocationData
)
1984 tools::Rectangle
aTextRect( Point( nPosX
, nPosY
), Size( aDataSize
.Width(), nTextHeight
) );
1985 pLocationData
->AddNoteText( aTextRect
, rPos
);
1986 tools::Rectangle
aMarkRect( Point( aPageRect
.Left(), nPosY
), Size( nMarkLen
, nTextHeight
) );
1987 pLocationData
->AddNoteMark( aMarkRect
, rPos
);
1990 nPosY
+= nTextHeight
;
1991 nPosY
+= 200; // Distance
2003 tools::Long
ScPrintFunc::PrintNotes( tools::Long nPageNo
, tools::Long nNoteStart
, bool bDoPrint
, ScPreviewLocationData
* pLocationData
)
2005 if ( nNoteStart
>= static_cast<tools::Long
>(aNotePosList
.size()) || !aTableParam
.bNotes
)
2008 if ( bDoPrint
&& bClearWin
)
2010 //! aggregate PrintPage !!!
2012 Color
aBackgroundColor( COL_WHITE
);
2013 if ( bUseStyleColor
)
2014 aBackgroundColor
= ScModule::get()->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
;
2016 pDev
->SetMapMode(aOffsetMode
);
2017 pDev
->SetLineColor();
2018 pDev
->SetFillColor(aBackgroundColor
);
2019 pDev
->DrawRect(tools::Rectangle(Point(),
2020 Size(static_cast<tools::Long
>(aPageSize
.Width() * nScaleX
* 100 / nZoom
),
2021 static_cast<tools::Long
>(aPageSize
.Height() * nScaleY
* 100 / nZoom
))));
2024 // adjust aPageRect for left/right page
2026 tools::Rectangle
aTempRect( Point(), aPageSize
);
2027 if (IsMirror(nPageNo
))
2029 aPageRect
.SetLeft( ( aTempRect
.Left() + nRightMargin
) * 100 / nZoom
);
2030 aPageRect
.SetRight( ( aTempRect
.Right() - nLeftMargin
) * 100 / nZoom
);
2034 aPageRect
.SetLeft( ( aTempRect
.Left() + nLeftMargin
) * 100 / nZoom
);
2035 aPageRect
.SetRight( ( aTempRect
.Right() - nRightMargin
) * 100 / nZoom
);
2038 if ( pPrinter
&& bDoPrint
)
2040 OSL_FAIL( "StartPage does not exist anymore" );
2043 if ( bDoPrint
|| pLocationData
)
2045 // Head and foot lines
2049 tools::Long nHeaderY
= aPageRect
.Top()-aHdr
.nHeight
;
2050 PrintHF( nPageNo
, true, nHeaderY
, bDoPrint
, pLocationData
);
2054 tools::Long nFooterY
= aPageRect
.Bottom()+aFtr
.nDistance
;
2055 PrintHF( nPageNo
, false, nFooterY
, bDoPrint
, pLocationData
);
2059 tools::Long nCount
= DoNotes( nNoteStart
, bDoPrint
, pLocationData
);
2061 if ( pPrinter
&& bDoPrint
)
2063 OSL_FAIL( "EndPage does not exist anymore" );
2069 void ScPrintFunc::PrintPage( tools::Long nPageNo
, SCCOL nX1
, SCROW nY1
, SCCOL nX2
, SCROW nY2
,
2070 bool bDoPrint
, ScPreviewLocationData
* pLocationData
)
2072 bool bLayoutRTL
= rDoc
.IsLayoutRTL( nPrintTab
);
2073 tools::Long nLayoutSign
= bLayoutRTL
? -1 : 1;
2075 // nPageNo is the page number within all sheets of one "start page" setting
2077 if ( bClearWin
&& bDoPrint
)
2079 // must exactly fit to painting the frame in preview.cxx !!!
2081 Color
aBackgroundColor( COL_WHITE
);
2082 if ( bUseStyleColor
)
2083 aBackgroundColor
= ScModule::get()->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
;
2085 pDev
->SetMapMode(aOffsetMode
);
2086 pDev
->SetLineColor();
2087 pDev
->SetFillColor(aBackgroundColor
);
2088 pDev
->DrawRect(tools::Rectangle(Point(),
2089 Size(static_cast<tools::Long
>(aPageSize
.Width() * nScaleX
* 100 / nZoom
),
2090 static_cast<tools::Long
>(aPageSize
.Height() * nScaleY
* 100 / nZoom
))));
2093 // adjust aPageRect for left/right page
2095 tools::Rectangle
aTempRect( Point(), aPageSize
);
2096 if (IsMirror(nPageNo
))
2098 aPageRect
.SetLeft( ( aTempRect
.Left() + nRightMargin
) * 100 / nZoom
);
2099 aPageRect
.SetRight( ( aTempRect
.Right() - nLeftMargin
) * 100 / nZoom
);
2103 aPageRect
.SetLeft( ( aTempRect
.Left() + nLeftMargin
) * 100 / nZoom
);
2104 aPageRect
.SetRight( ( aTempRect
.Right() - nRightMargin
) * 100 / nZoom
);
2107 if ( aAreaParam
.bRepeatCol
)
2108 if ( nX1
> nRepeatStartCol
&& nX1
<= nRepeatEndCol
)
2109 nX1
= nRepeatEndCol
+ 1;
2110 bool bDoRepCol
= (aAreaParam
.bRepeatCol
&& nX1
> nRepeatEndCol
);
2111 if ( aAreaParam
.bRepeatRow
)
2112 if ( nY1
> nRepeatStartRow
&& nY1
<= nRepeatEndRow
)
2113 nY1
= nRepeatEndRow
+ 1;
2114 bool bDoRepRow
= (aAreaParam
.bRepeatRow
&& nY1
> nRepeatEndRow
);
2116 // use new object hide flags in SdrPaintView
2119 pDrawView
->setHideOle(!aTableParam
.bObjects
);
2120 pDrawView
->setHideChart(!aTableParam
.bCharts
);
2121 pDrawView
->setHideDraw(!aTableParam
.bDrawings
);
2122 pDrawView
->setHideFormControl(!aTableParam
.bDrawings
);
2125 if ( pPrinter
&& bDoPrint
)
2127 OSL_FAIL( "StartPage does not exist anymore" );
2130 // head and foot lines (without centering)
2134 tools::Long nHeaderY
= aPageRect
.Top()-aHdr
.nHeight
;
2135 PrintHF( nPageNo
, true, nHeaderY
, bDoPrint
, pLocationData
);
2139 tools::Long nFooterY
= aPageRect
.Bottom()+aFtr
.nDistance
;
2140 PrintHF( nPageNo
, false, nFooterY
, bDoPrint
, pLocationData
);
2143 // Position ( margins / centering )
2145 tools::Long nLeftSpace
= aPageRect
.Left(); // Document-Twips
2146 tools::Long nTopSpace
= aPageRect
.Top();
2147 if ( bCenterHor
|| bLayoutRTL
)
2149 tools::Long nDataWidth
= 0;
2151 for (i
=nX1
; i
<=nX2
; i
++)
2152 nDataWidth
+= rDoc
.GetColWidth( i
,nPrintTab
);
2154 for (i
=nRepeatStartCol
; i
<=nRepeatEndCol
; i
++)
2155 nDataWidth
+= rDoc
.GetColWidth( i
,nPrintTab
);
2156 if (aTableParam
.bHeaders
)
2157 nDataWidth
+= tools::Long(PRINT_HEADER_WIDTH
);
2159 nDataWidth
+= pBorderItem
->GetDistance(SvxBoxItemLine::LEFT
) +
2160 pBorderItem
->GetDistance(SvxBoxItemLine::RIGHT
); //! Line width?
2161 if (pShadowItem
&& pShadowItem
->GetLocation() != SvxShadowLocation::NONE
)
2162 nDataWidth
+= pShadowItem
->CalcShadowSpace(SvxShadowItemSide::LEFT
) +
2163 pShadowItem
->CalcShadowSpace(SvxShadowItemSide::RIGHT
);
2166 nLeftSpace
+= ( aPageRect
.GetWidth() - nDataWidth
) / 2; // LTR or RTL
2168 nLeftSpace
-= lcl_LineTotal(pBorderItem
->GetLeft());
2170 else if ( bLayoutRTL
)
2171 nLeftSpace
+= aPageRect
.GetWidth() - nDataWidth
; // align to the right edge of the page
2175 tools::Long nDataHeight
= rDoc
.GetRowHeight( nY1
, nY2
, nPrintTab
);
2177 nDataHeight
+= rDoc
.GetRowHeight( nRepeatStartRow
,
2178 nRepeatEndRow
, nPrintTab
);
2179 if (aTableParam
.bHeaders
)
2180 nDataHeight
+= tools::Long(PRINT_HEADER_HEIGHT
);
2182 nDataHeight
+= pBorderItem
->GetDistance(SvxBoxItemLine::TOP
) +
2183 pBorderItem
->GetDistance(SvxBoxItemLine::BOTTOM
); //! Line width?
2184 if (pShadowItem
&& pShadowItem
->GetLocation() != SvxShadowLocation::NONE
)
2185 nDataHeight
+= pShadowItem
->CalcShadowSpace(SvxShadowItemSide::TOP
) +
2186 pShadowItem
->CalcShadowSpace(SvxShadowItemSide::BOTTOM
);
2187 nTopSpace
+= ( aPageRect
.GetHeight() - nDataHeight
) / 2;
2189 nTopSpace
-= lcl_LineTotal(pBorderItem
->GetTop());
2192 // calculate sizes of the elements for partitioning
2193 // (header, repeat, data)
2195 tools::Long nHeaderWidth
= 0;
2196 tools::Long nHeaderHeight
= 0;
2197 tools::Long nRepeatWidth
= 0;
2198 tools::Long nRepeatHeight
= 0;
2199 tools::Long nContentWidth
= 0; // scaled - not the same as nDataWidth above
2200 tools::Long nContentHeight
= 0;
2201 if (aTableParam
.bHeaders
)
2203 nHeaderWidth
= static_cast<tools::Long
>(PRINT_HEADER_WIDTH
* nScaleX
);
2204 nHeaderHeight
= static_cast<tools::Long
>(PRINT_HEADER_HEIGHT
* nScaleY
);
2207 for (SCCOL i
=nRepeatStartCol
; i
<=nRepeatEndCol
; i
++)
2208 nRepeatWidth
+= static_cast<tools::Long
>(rDoc
.GetColWidth(i
,nPrintTab
) * nScaleX
);
2210 nRepeatHeight
+= rDoc
.GetScaledRowHeight( nRepeatStartRow
,
2211 nRepeatEndRow
, nPrintTab
, nScaleY
);
2212 for (SCCOL i
=nX1
; i
<=nX2
; i
++)
2213 nContentWidth
+= static_cast<tools::Long
>(rDoc
.GetColWidth(i
,nPrintTab
) * nScaleX
);
2214 nContentHeight
+= rDoc
.GetScaledRowHeight( nY1
, nY2
, nPrintTab
,
2217 // partition the page
2219 tools::Long nStartX
= static_cast<tools::Long
>( nLeftSpace
* nScaleX
);
2220 tools::Long nStartY
= static_cast<tools::Long
>( nTopSpace
* nScaleY
);
2221 tools::Long nInnerStartX
= nStartX
;
2222 tools::Long nInnerStartY
= nStartY
;
2225 nInnerStartX
+= static_cast<tools::Long
>( ( lcl_LineTotal(pBorderItem
->GetLeft()) +
2226 pBorderItem
->GetDistance(SvxBoxItemLine::LEFT
) ) * nScaleX
);
2227 nInnerStartY
+= static_cast<tools::Long
>( ( lcl_LineTotal(pBorderItem
->GetTop()) +
2228 pBorderItem
->GetDistance(SvxBoxItemLine::TOP
) ) * nScaleY
);
2230 if (pShadowItem
&& pShadowItem
->GetLocation() != SvxShadowLocation::NONE
)
2232 nInnerStartX
+= static_cast<tools::Long
>( pShadowItem
->CalcShadowSpace(SvxShadowItemSide::LEFT
) * nScaleX
);
2233 nInnerStartY
+= static_cast<tools::Long
>( pShadowItem
->CalcShadowSpace(SvxShadowItemSide::TOP
) * nScaleY
);
2238 // arrange elements starting from the right edge
2239 nInnerStartX
+= nHeaderWidth
+ nRepeatWidth
+ nContentWidth
;
2241 // make rounding easier so the elements are really next to each other in preview
2242 Size aOffsetOnePixel
= pDev
->PixelToLogic( Size(1,1), aOffsetMode
);
2243 tools::Long nOffsetOneX
= aOffsetOnePixel
.Width();
2244 nInnerStartX
+= nOffsetOneX
/ 2;
2247 tools::Long nFrameStartX
= nInnerStartX
;
2248 tools::Long nFrameStartY
= nInnerStartY
;
2250 tools::Long nRepStartX
= nInnerStartX
+ nHeaderWidth
* nLayoutSign
; // widths/heights are 0 if not used
2251 tools::Long nRepStartY
= nInnerStartY
+ nHeaderHeight
;
2252 tools::Long nDataX
= nRepStartX
+ nRepeatWidth
* nLayoutSign
;
2253 tools::Long nDataY
= nRepStartY
+ nRepeatHeight
;
2254 tools::Long nEndX
= nDataX
+ nContentWidth
* nLayoutSign
;
2255 tools::Long nEndY
= nDataY
+ nContentHeight
;
2256 tools::Long nFrameEndX
= nEndX
;
2257 tools::Long nFrameEndY
= nEndY
;
2261 // each element's start position is its left edge
2262 //! subtract one pixel less?
2263 nInnerStartX
-= nHeaderWidth
; // used for header
2264 nRepStartX
-= nRepeatWidth
;
2265 nDataX
-= nContentWidth
;
2267 // continue right of the main elements again
2268 nEndX
+= nHeaderWidth
+ nRepeatWidth
+ nContentWidth
;
2271 // Page frame / background
2275 tools::Long nBorderEndX
= nEndX
;
2276 tools::Long nBorderEndY
= nEndY
;
2279 nBorderEndX
+= static_cast<tools::Long
>( ( lcl_LineTotal(pBorderItem
->GetRight()) +
2280 pBorderItem
->GetDistance(SvxBoxItemLine::RIGHT
) ) * nScaleX
);
2281 nBorderEndY
+= static_cast<tools::Long
>( ( lcl_LineTotal(pBorderItem
->GetBottom()) +
2282 pBorderItem
->GetDistance(SvxBoxItemLine::BOTTOM
) ) * nScaleY
);
2284 if (pShadowItem
&& pShadowItem
->GetLocation() != SvxShadowLocation::NONE
)
2286 nBorderEndX
+= static_cast<tools::Long
>( pShadowItem
->CalcShadowSpace(SvxShadowItemSide::RIGHT
) * nScaleX
);
2287 nBorderEndY
+= static_cast<tools::Long
>( pShadowItem
->CalcShadowSpace(SvxShadowItemSide::BOTTOM
) * nScaleY
);
2292 pDev
->SetMapMode( aOffsetMode
);
2293 DrawBorder( nStartX
, nStartY
, nBorderEndX
-nStartX
, nBorderEndY
-nStartY
,
2294 pBorderItem
, pBackgroundItem
, pShadowItem
);
2296 pDev
->SetMapMode( aTwipMode
);
2299 pDev
->SetMapMode( aOffsetMode
);
2301 // Output repeating rows/columns
2303 if (bDoRepCol
&& bDoRepRow
)
2306 PrintArea( nRepeatStartCol
,nRepeatStartRow
, nRepeatEndCol
,nRepeatEndRow
,
2307 nRepStartX
,nRepStartY
, true, true, false, false );
2308 if ( pLocationData
)
2309 LocateArea( nRepeatStartCol
,nRepeatStartRow
, nRepeatEndCol
,nRepeatEndRow
,
2310 nRepStartX
,nRepStartY
, true, true, *pLocationData
);
2315 PrintArea( nRepeatStartCol
,nY1
, nRepeatEndCol
,nY2
, nRepStartX
,nDataY
,
2316 true, !bDoRepRow
, false, true );
2317 if ( pLocationData
)
2318 LocateArea( nRepeatStartCol
,nY1
, nRepeatEndCol
,nY2
, nRepStartX
,nDataY
, true, false, *pLocationData
);
2323 PrintArea( nX1
,nRepeatStartRow
, nX2
,nRepeatEndRow
, nDataX
,nRepStartY
,
2324 !bDoRepCol
, true, true, false );
2325 if ( pLocationData
)
2326 LocateArea( nX1
,nRepeatStartRow
, nX2
,nRepeatEndRow
, nDataX
,nRepStartY
, false, true, *pLocationData
);
2332 PrintArea( nX1
,nY1
, nX2
,nY2
, nDataX
,nDataY
, !bDoRepCol
,!bDoRepRow
, true, true );
2333 if ( pLocationData
)
2334 LocateArea( nX1
,nY1
, nX2
,nY2
, nDataX
,nDataY
, false,false, *pLocationData
);
2336 // output column/row headers
2337 // after data (through probably shadow)
2339 Color
aGridColor( COL_BLACK
);
2340 if ( bUseStyleColor
)
2341 aGridColor
= ScModule::get()->GetColorConfig().GetColorValue(svtools::FONTCOLOR
).nColor
;
2343 if (aTableParam
.bHeaders
)
2347 pDev
->SetLineColor( aGridColor
);
2348 pDev
->SetFillColor();
2349 pDev
->SetMapMode(aOffsetMode
);
2352 ScPatternAttr
aPattern(rDoc
.getCellAttributeHelper());
2354 ScAutoFontColorMode eColorMode
= bUseStyleColor
? ScAutoFontColorMode::Display
: ScAutoFontColorMode::Print
;
2355 aPattern
.fillFont(aFont
, eColorMode
, pDev
);
2356 pDev
->SetFont(aFont
);
2361 PrintColHdr( nRepeatStartCol
,nRepeatEndCol
, nRepStartX
,nInnerStartY
);
2362 if ( pLocationData
)
2363 LocateColHdr( nRepeatStartCol
,nRepeatEndCol
, nRepStartX
,nInnerStartY
, true, *pLocationData
);
2366 PrintColHdr( nX1
,nX2
, nDataX
,nInnerStartY
);
2367 if ( pLocationData
)
2368 LocateColHdr( nX1
,nX2
, nDataX
,nInnerStartY
, false, *pLocationData
);
2372 PrintRowHdr( nRepeatStartRow
,nRepeatEndRow
, nInnerStartX
,nRepStartY
);
2373 if ( pLocationData
)
2374 LocateRowHdr( nRepeatStartRow
,nRepeatEndRow
, nInnerStartX
,nRepStartY
, true, *pLocationData
);
2377 PrintRowHdr( nY1
,nY2
, nInnerStartX
,nDataY
);
2378 if ( pLocationData
)
2379 LocateRowHdr( nY1
,nY2
, nInnerStartX
,nDataY
, false, *pLocationData
);
2384 if ( bDoPrint
&& ( aTableParam
.bGrid
|| aTableParam
.bHeaders
) )
2386 Size aOnePixel
= pDev
->PixelToLogic(Size(1,1));
2387 tools::Long nOneX
= aOnePixel
.Width();
2388 tools::Long nOneY
= aOnePixel
.Height();
2390 tools::Long nLeftX
= nFrameStartX
;
2391 tools::Long nTopY
= nFrameStartY
- nOneY
;
2392 tools::Long nRightX
= nFrameEndX
;
2393 tools::Long nBottomY
= nFrameEndY
- nOneY
;
2399 pDev
->SetMapMode(aOffsetMode
);
2400 pDev
->SetLineColor( aGridColor
);
2401 pDev
->SetFillColor();
2402 pDev
->DrawRect( tools::Rectangle( nLeftX
, nTopY
, nRightX
, nBottomY
) );
2403 // nEndX/Y without frame-adaptation
2406 if ( pPrinter
&& bDoPrint
)
2408 OSL_FAIL( "EndPage does not exist anymore" );
2411 aLastSourceRange
= ScRange( nX1
, nY1
, nPrintTab
, nX2
, nY2
, nPrintTab
);
2412 bSourceRangeValid
= true;
2415 void ScPrintFunc::SetOffset( const Point
& rOfs
)
2420 void ScPrintFunc::SetManualZoom( sal_uInt16 nNewZoom
)
2422 nManualZoom
= nNewZoom
;
2425 void ScPrintFunc::SetClearFlag( bool bFlag
)
2430 void ScPrintFunc::SetUseStyleColor( bool bFlag
)
2432 bUseStyleColor
= bFlag
;
2434 pEditEngine
->EnableAutoColor( bUseStyleColor
);
2437 void ScPrintFunc::SetRenderFlag( bool bFlag
)
2439 bIsRender
= bFlag
; // set when using XRenderable (PDF)
2442 void ScPrintFunc::SetExclusivelyDrawOleAndDrawObjects()
2444 aTableParam
.bCellContent
= false;
2445 aTableParam
.bNotes
= false;
2446 aTableParam
.bGrid
= false;
2447 aTableParam
.bHeaders
= false;
2448 aTableParam
.bFormulas
= false;
2449 aTableParam
.bNullVals
= false;
2452 // UpdatePages is only called from outside to set the breaks correctly for viewing
2453 // - always without UserArea
2455 bool ScPrintFunc::UpdatePages()
2463 if (aTableParam
.bScalePageNum
|| aTableParam
.bScaleTo
)
2464 nZoom
= ZOOM_MIN
; // correct for breaks
2465 else if (aTableParam
.bScaleAll
)
2467 nZoom
= aTableParam
.nScaleAll
;
2468 if ( nZoom
<= ZOOM_MIN
)
2472 OUString aName
= rDoc
.GetPageStyle( nPrintTab
);
2473 SCTAB nTabCount
= rDoc
.GetTableCount();
2474 for (SCTAB nTab
=0; nTab
<nTabCount
; nTab
++)
2475 if ( nTab
==nPrintTab
|| rDoc
.GetPageStyle(nTab
)==aName
)
2477 // Repeating rows/columns
2478 rDoc
.SetRepeatArea( nTab
, nRepeatStartCol
,nRepeatEndCol
, nRepeatStartRow
,nRepeatEndRow
);
2482 pDocShell
->PostPaint(0,0,nTab
,rDoc
.MaxCol(),rDoc
.MaxRow(),nTab
, PaintPartFlags::Grid
);
2488 tools::Long
ScPrintFunc::CountPages() // sets also nPagesX, nPagesY
2490 bool bAreaOk
= false;
2492 if (rDoc
.HasTable( nPrintTab
))
2494 if (aAreaParam
.bPrintArea
) // Specify print area?
2496 if ( bPrintCurrentTable
)
2498 ScRange
& rRange
= aAreaParam
.aPrintArea
;
2500 // Here, no comparison of the tables any more. Area is always valid for this table
2501 // If comparison should be done here, the table of print ranges must be adjusted
2502 // when inserting tables etc.!
2504 nStartCol
= rRange
.aStart
.Col();
2505 nStartRow
= rRange
.aStart
.Row();
2506 nEndCol
= rRange
.aEnd
.Col();
2507 nEndRow
= rRange
.aEnd
.Row();
2508 bAreaOk
= AdjustPrintArea(false); // limit
2513 else // search from document
2514 bAreaOk
= AdjustPrintArea(true);
2519 tools::Long nPages
= 0;
2523 sal_uInt16 nRCount
= rDoc
.GetPrintRangeCount( nPrintTab
);
2524 for (sal_uInt16 i
=0; i
<nRCount
; i
++)
2527 if ( aTableParam
.bSkipEmpty
)
2528 for (nY
=0; nY
< m_aRanges
.m_nPagesY
; nY
++)
2529 nPages
+= (*m_aRanges
.m_xPageRows
)[nY
].CountVisible();
2531 nPages
+= static_cast<tools::Long
>(m_aRanges
.m_nPagesX
) * m_aRanges
.m_nPagesY
;
2538 CalcZoom(RANGENO_NORANGE
); // calculate Zoom
2539 if ( aTableParam
.bSkipEmpty
)
2540 for (nY
=0; nY
<m_aRanges
.m_nPagesY
; nY
++)
2541 nPages
+= (*m_aRanges
.m_xPageRows
)[nY
].CountVisible();
2543 nPages
+= static_cast<tools::Long
>(m_aRanges
.m_nPagesX
) * m_aRanges
.m_nPagesY
;
2551 m_aRanges
.m_nPagesX
= m_aRanges
.m_nPagesY
= m_aRanges
.m_nTotalY
= 0;
2556 tools::Long
ScPrintFunc::CountNotePages()
2558 if ( !aTableParam
.bNotes
|| !bPrintCurrentTable
)
2561 bool bError
= false;
2562 if (!aAreaParam
.bPrintArea
)
2563 bError
= !AdjustPrintArea(true); // completely search in Doc
2565 sal_uInt16 nRepeats
= 1; // how often go through it ?
2567 nRepeats
= rDoc
.GetPrintRangeCount(nPrintTab
);
2571 for (sal_uInt16 nStep
=0; nStep
<nRepeats
; nStep
++)
2573 bool bDoThis
= true;
2574 if (bMultiArea
) // go through all Areas
2576 const ScRange
* pThisRange
= rDoc
.GetPrintRange( nPrintTab
, nStep
);
2579 nStartCol
= pThisRange
->aStart
.Col();
2580 nStartRow
= pThisRange
->aStart
.Row();
2581 nEndCol
= pThisRange
->aEnd
.Col();
2582 nEndRow
= pThisRange
->aEnd
.Row();
2583 bDoThis
= AdjustPrintArea(false);
2589 assert( bPrintAreaValid
);
2590 for ( SCCOL nCol
= nStartCol
; nCol
<= nEndCol
; ++nCol
)
2592 if (rDoc
.HasColNotes(nCol
, nPrintTab
))
2594 for ( SCROW nRow
= nStartRow
; nRow
<= nEndRow
; ++nRow
)
2596 if ( rDoc
.HasNote(nCol
, nRow
, nPrintTab
) )
2597 aNotePosList
.emplace_back( nCol
, nRow
, nPrintTab
);
2604 tools::Long nPages
= 0;
2605 tools::Long nNoteNr
= 0;
2606 tools::Long nNoteAdd
;
2609 nNoteAdd
= PrintNotes( nPages
, nNoteNr
, false, nullptr );
2612 nNoteNr
+= nNoteAdd
;
2621 void ScPrintFunc::InitModes() // set MapModes from nZoom etc.
2623 aOffset
= Point( aSrcOffset
.X()*100/nZoom
, aSrcOffset
.Y()*100/nZoom
);
2625 tools::Long nEffZoom
= nZoom
* static_cast<tools::Long
>(nManualZoom
);
2626 constexpr auto HMM_PER_TWIPS
= o3tl::convert(1.0, o3tl::Length::twip
, o3tl::Length::mm100
);
2627 nScaleX
= nScaleY
= HMM_PER_TWIPS
; // output in 1/100 mm
2629 Fraction
aZoomFract( nEffZoom
,10000 );
2630 Fraction aHorFract
= aZoomFract
;
2632 if ( !pPrinter
&& !bIsRender
) // adjust scale for preview
2634 double nFact
= pDocShell
->GetOutputFactor();
2635 aHorFract
= Fraction( static_cast<tools::Long
>( nEffZoom
/ nFact
), 10000 );
2638 aLogicMode
= MapMode( MapUnit::Map100thMM
, Point(), aHorFract
, aZoomFract
);
2640 Point
aLogicOfs( -aOffset
.X(), -aOffset
.Y() );
2641 aOffsetMode
= MapMode( MapUnit::Map100thMM
, aLogicOfs
, aHorFract
, aZoomFract
);
2643 Point
aTwipsOfs( static_cast<tools::Long
>( -aOffset
.X() / nScaleX
+ 0.5 ), static_cast<tools::Long
>( -aOffset
.Y() / nScaleY
+ 0.5 ) );
2644 aTwipMode
= MapMode( MapUnit::MapTwip
, aTwipsOfs
, aHorFract
, aZoomFract
);
2647 void ScPrintFunc::ApplyPrintSettings()
2652 // Configure Printer to Printing
2654 Size aEnumSize
= aPageSize
;
2656 pPrinter
->SetOrientation( bLandscape
? Orientation::Landscape
: Orientation::Portrait
);
2659 // landscape is always interpreted as a rotation by 90 degrees !
2660 // this leads to non WYSIWIG but at least it prints!
2662 tools::Long nTemp
= aEnumSize
.Width();
2663 aEnumSize
.setWidth( aEnumSize
.Height() );
2664 aEnumSize
.setHeight( nTemp
);
2666 Paper ePaper
= SvxPaperInfo::GetSvxPaper( aEnumSize
, MapUnit::MapTwip
);
2667 sal_uInt16 nPaperBin
= pParamSet
->Get(ATTR_PAGE_PAPERBIN
).GetValue();
2669 pPrinter
->SetPaper( ePaper
);
2670 if ( PAPER_USER
== ePaper
)
2672 MapMode aPrinterMode
= pPrinter
->GetMapMode();
2673 MapMode
aLocalMode( MapUnit::MapTwip
);
2674 pPrinter
->SetMapMode( aLocalMode
);
2675 pPrinter
->SetPaperSizeUser( aEnumSize
);
2676 pPrinter
->SetMapMode( aPrinterMode
);
2679 pPrinter
->SetPaperBin( nPaperBin
);
2682 // rPageRanges = range for all tables
2683 // nStartPage = rPageRanges starts at nStartPage
2684 // nDisplayStart = continuous number for displaying the page number
2686 tools::Long
ScPrintFunc::DoPrint( const MultiSelection
& rPageRanges
,
2687 tools::Long nStartPage
, tools::Long nDisplayStart
, bool bDoPrint
,
2688 ScPreviewLocationData
* pLocationData
)
2690 OSL_ENSURE(pDev
,"Device == NULL");
2694 if ( pPrinter
&& bDoPrint
)
2695 ApplyPrintSettings();
2698 if ( pLocationData
)
2700 pLocationData
->SetCellMapMode( aOffsetMode
);
2701 pLocationData
->SetPrintTab( nPrintTab
);
2706 tools::Long nPageNo
= 0;
2707 tools::Long nPrinted
= 0;
2708 tools::Long nEndPage
= rPageRanges
.GetTotalRange().Max();
2710 sal_uInt16 nRepeats
= 1;
2712 nRepeats
= rDoc
.GetPrintRangeCount(nPrintTab
);
2713 for (sal_uInt16 nStep
=0; nStep
<nRepeats
; nStep
++)
2715 if (bMultiArea
) // replace area
2717 CalcZoom(nStep
); // also sets nStartCol etc. new
2728 if (aTableParam
.bTopDown
) // top-bottom
2731 for (nCountX
=0; nCountX
<m_aRanges
.m_nPagesX
; nCountX
++)
2733 OSL_ENSURE(nCountX
< m_aRanges
.m_xPageEndX
->size(), "vector access error for aPageEndX (!)");
2734 nX2
= (*m_aRanges
.m_xPageEndX
)[nCountX
];
2735 for (nCountY
=0; nCountY
<m_aRanges
.m_nPagesY
; nCountY
++)
2737 auto& rPageRow
= (*m_aRanges
.m_xPageRows
)[nCountY
];
2738 nY1
= rPageRow
.GetStartRow();
2739 nY2
= rPageRow
.GetEndRow();
2740 if ( !aTableParam
.bSkipEmpty
|| !rPageRow
.IsHidden(nCountX
) )
2742 if ( rPageRanges
.IsSelected( nPageNo
+nStartPage
+1 ) )
2744 PrintPage( nPageNo
+nDisplayStart
, nX1
, nY1
, nX2
, nY2
,
2745 bDoPrint
, pLocationData
);
2754 else // left to right
2756 for (nCountY
=0; nCountY
<m_aRanges
.m_nPagesY
; nCountY
++)
2758 auto& rPageRow
= (*m_aRanges
.m_xPageRows
)[nCountY
];
2759 nY1
= rPageRow
.GetStartRow();
2760 nY2
= rPageRow
.GetEndRow();
2762 for (nCountX
=0; nCountX
<m_aRanges
.m_nPagesX
; nCountX
++)
2764 OSL_ENSURE(nCountX
< m_aRanges
.m_xPageEndX
->size(), "vector access error for aPageEndX");
2765 nX2
= (*m_aRanges
.m_xPageEndX
)[nCountX
];
2766 if ( !aTableParam
.bSkipEmpty
|| !rPageRow
.IsHidden(nCountX
) )
2768 if ( rPageRanges
.IsSelected( nPageNo
+nStartPage
+1 ) )
2770 PrintPage( nPageNo
+nDisplayStart
, nX1
, nY1
, nX2
, nY2
,
2771 bDoPrint
, pLocationData
);
2782 aFieldData
.aTabName
= ScResId( STR_NOTES
);
2784 tools::Long nNoteNr
= 0;
2785 tools::Long nNoteAdd
;
2788 if ( nPageNo
+nStartPage
<= nEndPage
)
2790 bool bPageSelected
= rPageRanges
.IsSelected( nPageNo
+nStartPage
+1 );
2791 nNoteAdd
= PrintNotes( nPageNo
+nStartPage
, nNoteNr
, bDoPrint
&& bPageSelected
,
2792 ( bPageSelected
? pLocationData
: nullptr ) );
2795 nNoteNr
+= nNoteAdd
;
2799 bSourceRangeValid
= false; // last page was no cell range
2810 ResetBreaks(nPrintTab
); //breaks correct for displaying
2815 void ScPrintFunc::CalcZoom( sal_uInt16 nRangeNo
) // calculate zoom
2817 sal_uInt16 nRCount
= rDoc
.GetPrintRangeCount( nPrintTab
);
2818 const ScRange
* pThisRange
= nullptr;
2819 if (nRangeNo
!= RANGENO_NORANGE
&& nRangeNo
< nRCount
)
2820 pThisRange
= rDoc
.GetPrintRange( nPrintTab
, nRangeNo
);
2823 nStartCol
= pThisRange
->aStart
.Col();
2824 nStartRow
= pThisRange
->aStart
.Row();
2825 nEndCol
= pThisRange
->aEnd
.Col();
2826 nEndRow
= pThisRange
->aEnd
.Row();
2829 if (!AdjustPrintArea(false)) // empty
2832 m_aRanges
.m_nPagesX
= m_aRanges
.m_nPagesY
= m_aRanges
.m_nTotalY
= 0;
2836 rDoc
.SetRepeatArea( nPrintTab
, nRepeatStartCol
,nRepeatEndCol
, nRepeatStartRow
,nRepeatEndRow
);
2838 if (aTableParam
.bScalePageNum
)
2841 sal_uInt16 nPagesToFit
= aTableParam
.nScalePageNum
;
2843 // If manual breaks are forced, calculate minimum # pages required
2844 if (aTableParam
.bForceBreaks
)
2846 sal_uInt16 nMinPages
= 0;
2847 std::set
<SCROW
> aRowBreaks
;
2848 std::set
<SCCOL
> aColBreaks
;
2849 rDoc
.GetAllRowBreaks(aRowBreaks
, nPrintTab
, false, true);
2850 rDoc
.GetAllColBreaks(aColBreaks
, nPrintTab
, false, true);
2851 nMinPages
= (aRowBreaks
.size() + 1) * (aColBreaks
.size() + 1);
2853 // #i54993# use min forced by breaks if it's > # pages in
2854 // scale parameter to avoid bottoming out at <= ZOOM_MIN
2855 nPagesToFit
= std::max(nMinPages
, nPagesToFit
);
2858 sal_uInt16 nLastFitZoom
= 0, nLastNonFitZoom
= 0;
2861 if (nZoom
<= ZOOM_MIN
)
2865 bool bFitsPage
= (m_aRanges
.m_nPagesX
* m_aRanges
.m_nPagesY
<= nPagesToFit
);
2870 // If it fits at 100%, it's good enough for me.
2873 nLastFitZoom
= nZoom
;
2874 nZoom
= (nLastNonFitZoom
+ nZoom
) / 2;
2876 if (nLastFitZoom
== nZoom
)
2877 // It converged. Use this zoom level.
2882 if (nZoom
- nLastFitZoom
<= 1)
2884 nZoom
= nLastFitZoom
;
2889 nLastNonFitZoom
= nZoom
;
2890 nZoom
= (nLastFitZoom
+ nZoom
) / 2;
2894 else if (aTableParam
.bScaleTo
)
2897 sal_uInt16 nW
= aTableParam
.nScaleWidth
;
2898 sal_uInt16 nH
= aTableParam
.nScaleHeight
;
2900 // If manual breaks are forced, calculate minimum # pages required
2901 if (aTableParam
.bForceBreaks
)
2903 sal_uInt16 nMinPagesW
= 0, nMinPagesH
= 0;
2904 std::set
<SCROW
> aRowBreaks
;
2905 std::set
<SCCOL
> aColBreaks
;
2906 rDoc
.GetAllRowBreaks(aRowBreaks
, nPrintTab
, false, true);
2907 rDoc
.GetAllColBreaks(aColBreaks
, nPrintTab
, false, true);
2908 nMinPagesW
= aColBreaks
.size() + 1;
2909 nMinPagesH
= aRowBreaks
.size() + 1;
2911 // #i54993# use min forced by breaks if it's > # pages in
2912 // scale parameters to avoid bottoming out at <= ZOOM_MIN
2913 nW
= std::max(nMinPagesW
, nW
);
2914 nH
= std::max(nMinPagesH
, nH
);
2917 sal_uInt16 nLastFitZoom
= 0, nLastNonFitZoom
= 0;
2920 if (nZoom
<= ZOOM_MIN
)
2924 bool bFitsPage
= ((!nW
|| (m_aRanges
.m_nPagesX
<= nW
)) && (!nH
|| (m_aRanges
.m_nPagesY
<= nH
)));
2929 // If it fits at 100%, it's good enough for me.
2932 nLastFitZoom
= nZoom
;
2933 nZoom
= (nLastNonFitZoom
+ nZoom
) / 2;
2935 if (nLastFitZoom
== nZoom
)
2936 // It converged. Use this zoom level.
2941 if (nZoom
- nLastFitZoom
<= 1)
2943 nZoom
= nLastFitZoom
;
2948 nLastNonFitZoom
= nZoom
;
2949 nZoom
= (nLastFitZoom
+ nZoom
) / 2;
2952 // tdf#103516 remove the almost blank page(s) for better
2953 // interoperability by using slightly smaller zoom
2954 if (nW
> 0 && nH
== 0 && m_aRanges
.m_nPagesY
> 1)
2956 sal_uInt32 nLastPagesY
= m_aRanges
.m_nPagesY
;
2957 nLastFitZoom
= nZoom
;
2959 if (nZoom
< nLastFitZoom
)
2962 // same page count with smaller zoom: use the original zoom
2963 if (m_aRanges
.m_nPagesY
== nLastPagesY
)
2965 nZoom
= nLastFitZoom
;
2971 else if (aTableParam
.bScaleAll
)
2973 nZoom
= aTableParam
.nScaleAll
;
2974 if ( nZoom
<= ZOOM_MIN
)
2980 OSL_ENSURE( aTableParam
.bScaleNone
, "no scale flag is set" );
2986 Size
ScPrintFunc::GetDocPageSize()
2988 // Adjust height of head/foot line
2990 InitModes(); // initialize aTwipMode from nZoom
2991 pDev
->SetMapMode( aTwipMode
); // head/foot line in Twips
2992 UpdateHFHeight( aHdr
);
2993 UpdateHFHeight( aFtr
);
2995 // Page size in Document-Twips
2996 // Calculating Left / Right also in PrintPage
2998 aPageRect
= tools::Rectangle( Point(), aPageSize
);
2999 aPageRect
.SetLeft( ( aPageRect
.Left() + nLeftMargin
) * 100 / nZoom
);
3000 aPageRect
.SetRight( ( aPageRect
.Right() - nRightMargin
) * 100 / nZoom
);
3001 aPageRect
.SetTop( ( aPageRect
.Top() + nTopMargin
) * 100 / nZoom
+ aHdr
.nHeight
);
3002 aPageRect
.SetBottom( ( aPageRect
.Bottom() - nBottomMargin
) * 100 / nZoom
- aFtr
.nHeight
);
3004 Size aDocPageSize
= aPageRect
.GetSize();
3005 if (aTableParam
.bHeaders
)
3007 aDocPageSize
.AdjustWidth( -(tools::Long(PRINT_HEADER_WIDTH
)) );
3008 aDocPageSize
.AdjustHeight( -(tools::Long(PRINT_HEADER_HEIGHT
)) );
3012 aDocPageSize
.AdjustWidth( -(lcl_LineTotal(pBorderItem
->GetLeft()) +
3013 lcl_LineTotal(pBorderItem
->GetRight()) +
3014 pBorderItem
->GetDistance(SvxBoxItemLine::LEFT
) +
3015 pBorderItem
->GetDistance(SvxBoxItemLine::RIGHT
)) );
3016 aDocPageSize
.AdjustHeight( -(lcl_LineTotal(pBorderItem
->GetTop()) +
3017 lcl_LineTotal(pBorderItem
->GetBottom()) +
3018 pBorderItem
->GetDistance(SvxBoxItemLine::TOP
) +
3019 pBorderItem
->GetDistance(SvxBoxItemLine::BOTTOM
)) );
3021 if (pShadowItem
&& pShadowItem
->GetLocation() != SvxShadowLocation::NONE
)
3023 aDocPageSize
.AdjustWidth( -(pShadowItem
->CalcShadowSpace(SvxShadowItemSide::LEFT
) +
3024 pShadowItem
->CalcShadowSpace(SvxShadowItemSide::RIGHT
)) );
3025 aDocPageSize
.AdjustHeight( -(pShadowItem
->CalcShadowSpace(SvxShadowItemSide::TOP
) +
3026 pShadowItem
->CalcShadowSpace(SvxShadowItemSide::BOTTOM
)) );
3028 return aDocPageSize
;
3031 void ScPrintFunc::ResetBreaks( SCTAB nTab
) // Set Breaks correctly for view
3033 rDoc
.SetPageSize( nTab
, GetDocPageSize() );
3034 rDoc
.UpdatePageBreaks( nTab
);
3037 static void lcl_SetHidden( const ScDocument
& rDoc
, SCTAB nPrintTab
, ScPageRowEntry
& rPageRowEntry
,
3038 SCCOL nStartCol
, const std::vector
< SCCOL
>& rPageEndX
)
3040 size_t nPagesX
= rPageRowEntry
.GetPagesX();
3041 SCROW nStartRow
= rPageRowEntry
.GetStartRow();
3042 SCROW nEndRow
= rPageRowEntry
.GetEndRow();
3044 bool bLeftIsEmpty
= false;
3046 tools::Rectangle aTempRect
= rDoc
.GetMMRect( 0,0, 0,0, 0 );
3048 for (size_t i
=0; i
<nPagesX
; i
++)
3050 OSL_ENSURE(i
< rPageEndX
.size(), "vector access error for aPageEndX");
3051 SCCOL nEndCol
= rPageEndX
[i
];
3052 if ( rDoc
.IsPrintEmpty( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nPrintTab
,
3053 bLeftIsEmpty
, &aTempRange
, &aTempRect
) )
3055 rPageRowEntry
.SetHidden(i
);
3056 bLeftIsEmpty
= true;
3059 bLeftIsEmpty
= false;
3061 nStartCol
= nEndCol
+1;
3065 void ScPrintFunc::CalcPages() // calculates aPageRect and pages from nZoom
3067 assert( bPrintAreaValid
);
3069 sc::PrintPageRangesInput
aInput(aTableParam
.bSkipEmpty
, aAreaParam
.bPrintArea
,
3070 ScRange(nStartCol
, nStartRow
, nPrintTab
, nEndCol
, nEndRow
, nPrintTab
),
3072 m_aRanges
.calculate(rDoc
, aInput
);
3078 PrintPageRanges::PrintPageRanges()
3084 void PrintPageRanges::calculate(ScDocument
& rDoc
, PrintPageRangesInput
const& rInput
)
3086 // Already calculated?
3087 if (m_aInput
== rInput
)
3092 rDoc
.SetPageSize(m_aInput
.getPrintTab(), m_aInput
.m_aDocSize
);
3094 // Clear the map to prevent any outdated values to "survive" when
3095 // we have to recalculate the new values anyway
3096 m_xPageRows
->clear();
3098 // #i123672# use dynamic mem to react on size changes
3099 if (m_xPageEndX
->size() < static_cast<size_t>(rDoc
.MaxCol()) + 1)
3101 m_xPageEndX
->resize(rDoc
.MaxCol()+1, SCCOL());
3104 if (m_aInput
.m_bPrintArea
)
3106 ScRange
aRange(m_aInput
.getStartColumn(), m_aInput
.getStartRow(), m_aInput
.getPrintTab(), m_aInput
.getEndColumn(), m_aInput
.getEndRow(), m_aInput
.getPrintTab());
3107 rDoc
.UpdatePageBreaks(m_aInput
.getPrintTab(), &aRange
);
3111 rDoc
.UpdatePageBreaks(m_aInput
.getPrintTab()); // else, end is marked
3114 const size_t nRealCnt
= m_aInput
.getEndRow() - m_aInput
.getStartRow() + 1;
3116 // #i123672# use dynamic mem to react on size changes
3117 if (m_xPageEndY
->size() < nRealCnt
+1)
3119 m_xPageEndY
->resize(nRealCnt
+ 1, SCROW());
3122 // Page alignment/splitting after breaks in Col/RowFlags
3123 // Of several breaks in a hidden area, only one counts.
3129 bool bVisCol
= false;
3130 for (SCCOL i
= m_aInput
.getStartColumn(); i
<= m_aInput
.getEndColumn(); i
++)
3132 bool bHidden
= rDoc
.ColHidden(i
, m_aInput
.getPrintTab());
3133 bool bPageBreak(rDoc
.HasColBreak(i
, m_aInput
.getPrintTab()) & ScBreakType::Page
);
3134 if (i
> m_aInput
.getStartColumn() && bVisCol
&& bPageBreak
)
3136 OSL_ENSURE(m_nPagesX
< m_xPageEndX
->size(), "vector access error for aPageEndX");
3137 (*m_xPageEndX
)[m_nPagesX
] = i
-1;
3144 if (bVisCol
) // also at the end, no empty pages
3146 OSL_ENSURE(m_nPagesX
< m_xPageEndX
->size(), "vector access error for aPageEndX");
3147 (*m_xPageEndX
)[m_nPagesX
] = m_aInput
.getEndColumn();
3151 bool bVisRow
= false;
3152 SCROW nPageStartRow
= m_aInput
.getStartRow();
3153 SCROW nLastVisibleRow
= -1;
3155 std::unique_ptr
<ScRowBreakIterator
> pRowBreakIter(rDoc
.GetRowBreakIterator(m_aInput
.getPrintTab()));
3156 SCROW nNextPageBreak
= pRowBreakIter
->first();
3157 while (nNextPageBreak
!= ScRowBreakIterator::NOT_FOUND
&& nNextPageBreak
< m_aInput
.getStartRow())
3158 // Skip until the page break position is at the start row or greater.
3159 nNextPageBreak
= pRowBreakIter
->next();
3161 for (SCROW nRow
= m_aInput
.getStartRow(); nRow
<= m_aInput
.getEndRow(); ++nRow
)
3163 bool bPageBreak
= (nNextPageBreak
== nRow
);
3165 nNextPageBreak
= pRowBreakIter
->next();
3167 if (nRow
> m_aInput
.getStartRow() && bVisRow
&& bPageBreak
)
3169 OSL_ENSURE(m_nTotalY
< m_xPageEndY
->size(), "vector access error for rPageEndY");
3170 (*m_xPageEndY
)[m_nTotalY
] = nRow
- 1;
3173 if (!m_aInput
.m_bSkipEmpty
|| !rDoc
.IsPrintEmpty(m_aInput
.getStartColumn(), nPageStartRow
, m_aInput
.getEndColumn(), nRow
-1, m_aInput
.getPrintTab()))
3175 auto& rPageRow
= (*m_xPageRows
)[m_nPagesY
];
3176 rPageRow
.SetStartRow(nPageStartRow
);
3177 rPageRow
.SetEndRow(nRow
- 1);
3178 rPageRow
.SetPagesX(m_nPagesX
);
3179 if (m_aInput
.m_bSkipEmpty
)
3180 lcl_SetHidden(rDoc
, m_aInput
.getPrintTab(), rPageRow
, m_aInput
.getStartColumn(), *m_xPageEndX
);
3184 nPageStartRow
= nRow
;
3188 if (nRow
<= nLastVisibleRow
)
3190 // This row is still visible. Don't bother calling RowHidden() to
3191 // find out, for speed optimization.
3196 SCROW nLastRow
= -1;
3197 if (!rDoc
.RowHidden(nRow
, m_aInput
.getPrintTab(), nullptr, &nLastRow
))
3200 nLastVisibleRow
= nLastRow
;
3204 // Skip all hidden rows until next pagebreak.
3205 nRow
= ((nNextPageBreak
== ScRowBreakIterator::NOT_FOUND
) ? nLastRow
:
3206 std::min(nLastRow
, nNextPageBreak
- 1));
3213 OSL_ENSURE(m_nTotalY
< m_xPageEndY
->size(), "vector access error for maPageEndY");
3214 (*m_xPageEndY
)[m_nTotalY
] = m_aInput
.getEndRow();
3217 if (!m_aInput
.m_bSkipEmpty
|| !rDoc
.IsPrintEmpty(m_aInput
.getStartColumn(), nPageStartRow
, m_aInput
.getEndColumn(), m_aInput
.getEndRow(), m_aInput
.getPrintTab()))
3219 auto& rPageRow
= (*m_xPageRows
)[m_nPagesY
];
3220 rPageRow
.SetStartRow(nPageStartRow
);
3221 rPageRow
.SetEndRow(m_aInput
.getEndRow());
3222 rPageRow
.SetPagesX(m_nPagesX
);
3223 if (m_aInput
.m_bSkipEmpty
)
3224 lcl_SetHidden(rDoc
, m_aInput
.getPrintTab(), rPageRow
, m_aInput
.getStartColumn(), *m_xPageEndX
);
3229 } // end namespace sc
3230 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */