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