Update to m13
[ooovba.git] / sc / source / ui / view / printfun.cxx
blob2a76a83b826d6397ba64da1465991eb1ca18ddb8
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: printfun.cxx,v $
10 * $Revision: 1.58.50.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 // INCLUDE ---------------------------------------------------------------
36 #include "scitems.hxx"
37 #include <svx/eeitem.hxx>
39 #include "printfun.hxx"
41 #include <svx/svxids.hrc>
42 #include <svx/adjitem.hxx>
43 #include <svx/boxitem.hxx>
44 #include <svx/brshitem.hxx>
45 #include <svtools/colorcfg.hxx>
46 #include <svx/editstat.hxx> // EE_CNTRL_RTFSTYLESHEETS
47 #include <svx/fmview.hxx>
48 #include <svx/frmdiritem.hxx>
49 #include <svx/lrspitem.hxx>
50 #include <svx/paperinf.hxx>
51 #include <svx/pbinitem.hxx>
52 #include <svx/shaditem.hxx>
53 #include <svx/sizeitem.hxx>
54 #include <svx/svdpagv.hxx>
55 #include <svx/ulspitem.hxx>
56 #include <sfx2/app.hxx>
57 #include <sfx2/printer.hxx>
58 #include <sfx2/progress.hxx>
59 #include <tools/multisel.hxx>
60 #include <sfx2/docfile.hxx>
61 #include <tools/urlobj.hxx>
62 #include <svx/xoutbmp.hxx>
64 #include "editutil.hxx"
65 #include "docsh.hxx"
66 #include "output.hxx"
67 #include "viewdata.hxx"
68 #include "viewopti.hxx"
69 #include "stlpool.hxx"
70 #include "pagepar.hxx"
71 #include "attrib.hxx"
72 #include "patattr.hxx"
73 #include "docpool.hxx"
74 #include "dociter.hxx"
75 #include "cell.hxx"
76 #include "drawutil.hxx"
77 #include "globstr.hrc"
78 #include "scresid.hxx"
79 #include "sc.hrc"
80 #include "pagedata.hxx"
81 #include "printopt.hxx"
82 #include "prevloc.hxx"
83 #include "scmod.hxx"
84 #include "drwlayer.hxx"
85 #include "fillinfo.hxx"
86 #include "postit.hxx"
88 #include <vcl/lineinfo.hxx>
89 #include <tools/pstm.hxx>
91 #define ZOOM_MIN 10
93 #define GET_BOOL(set,which) ((const SfxBoolItem&)(set)->Get((which))).GetValue()
94 #define GET_USHORT(set,which) ((const SfxUInt16Item&)(set)->Get((which))).GetValue()
95 #define GET_SHOW(set,which) ( VOBJ_MODE_SHOW == ScVObjMode( ((const ScViewObjectModeItem&)(set)->Get((which))).GetValue()) )
97 //------------------------------------------------------------------------
99 ScPageRowEntry::ScPageRowEntry(const ScPageRowEntry& r)
101 nStartRow = r.nStartRow;
102 nEndRow = r.nEndRow;
103 nPagesX = r.nPagesX;
104 if (r.pHidden && nPagesX)
106 pHidden = new BOOL[nPagesX];
107 memcpy( pHidden, r.pHidden, nPagesX * sizeof(BOOL) );
109 else
110 pHidden = NULL;
113 const ScPageRowEntry& ScPageRowEntry::operator=(const ScPageRowEntry& r)
115 delete[] pHidden;
117 nStartRow = r.nStartRow;
118 nEndRow = r.nEndRow;
119 nPagesX = r.nPagesX;
120 if (r.pHidden && nPagesX)
122 pHidden = new BOOL[nPagesX];
123 memcpy( pHidden, r.pHidden, nPagesX * sizeof(BOOL) );
125 else
126 pHidden = NULL;
128 return *this;
131 void ScPageRowEntry::SetPagesX(size_t nNew)
133 if (pHidden)
135 DBG_ERROR("SetPagesX nicht nach SetHidden");
136 delete[] pHidden;
137 pHidden = NULL;
139 nPagesX = nNew;
142 void ScPageRowEntry::SetHidden(size_t nX)
144 if ( nX < nPagesX )
146 if ( nX+1 == nPagesX ) // letzte Seite?
147 --nPagesX;
148 else
150 if (!pHidden)
152 pHidden = new BOOL[nPagesX];
153 memset( pHidden, FALSE, nPagesX * sizeof(BOOL) );
155 pHidden[nX] = TRUE;
160 BOOL ScPageRowEntry::IsHidden(size_t nX) const
162 return nX>=nPagesX || ( pHidden && pHidden[nX] ); //! inline?
165 size_t ScPageRowEntry::CountVisible() const
167 if ( pHidden )
169 size_t nVis = 0;
170 for (size_t i=0; i<nPagesX; i++)
171 if (!pHidden[i])
172 ++nVis;
173 return nVis;
175 else
176 return nPagesX;
179 //------------------------------------------------------------------------
181 long lcl_LineTotal(const SvxBorderLine* pLine)
183 return pLine ? ( pLine->GetOutWidth() + pLine->GetInWidth() + pLine->GetDistance() ) : 0;
186 void ScPrintFunc::Construct( const ScPrintOptions* pOptions )
188 pDoc = pDocShell->GetDocument();
190 SfxPrinter* pDocPrinter = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen
191 if (pDocPrinter)
192 aOldPrinterMode = pDocPrinter->GetMapMode();
194 // einheitlicher MapMode ueber alle Aufrufe (z.B. Repaint !!!),
195 // weil die EditEngine sonst unterschiedliche Texthoehen liefert
196 pDev->SetMapMode(MAP_PIXEL);
198 pPageEndX = NULL;
199 pPageEndY = NULL;
200 pPageRows = NULL;
201 pBorderItem = NULL;
202 pBackgroundItem = NULL;
203 pShadowItem = NULL;
205 pEditEngine = NULL;
206 pEditDefaults = NULL;
208 ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
209 SfxStyleSheetBase* pStyleSheet = pStylePool->Find(
210 pDoc->GetPageStyle( nPrintTab ),
211 SFX_STYLE_FAMILY_PAGE );
212 if (pStyleSheet)
213 pParamSet = &pStyleSheet->GetItemSet();
214 else
216 DBG_ERROR("Seitenvorlage nicht gefunden" );
217 pParamSet = NULL;
220 if (!bState)
221 nZoom = 100;
222 nManualZoom = 100;
223 bClearWin = FALSE;
224 bUseStyleColor = FALSE;
225 bIsRender = FALSE;
227 InitParam(pOptions);
229 pPageData = NULL; // wird nur zur Initialisierung gebraucht
232 ScPrintFunc::ScPrintFunc( ScDocShell* pShell, SfxPrinter* pNewPrinter, SCTAB nTab,
233 long nPage, long nDocP, const ScRange* pArea,
234 const ScPrintOptions* pOptions,
235 ScPageBreakData* pData )
236 : pDocShell ( pShell ),
237 pPrinter ( pNewPrinter ),
238 pDrawView ( NULL ),
239 nPrintTab ( nTab ),
240 nPageStart ( nPage ),
241 nDocPages ( nDocP ),
242 pUserArea ( pArea ),
243 bState ( FALSE ),
244 bSourceRangeValid ( FALSE ),
245 bPrintCurrentTable ( FALSE ),
246 bMultiArea ( FALSE ),
247 nTabPages ( 0 ),
248 nTotalPages ( 0 ),
249 pPageData ( pData )
251 pDev = pPrinter;
252 aSrcOffset = pPrinter->PixelToLogic( pPrinter->GetPageOffsetPixel(), MAP_100TH_MM );
253 Construct( pOptions );
256 ScPrintFunc::ScPrintFunc( OutputDevice* pOutDev, ScDocShell* pShell, SCTAB nTab,
257 long nPage, long nDocP, const ScRange* pArea,
258 const ScPrintOptions* pOptions )
259 : pDocShell ( pShell ),
260 pPrinter ( NULL ),
261 pDrawView ( NULL ),
262 nPrintTab ( nTab ),
263 nPageStart ( nPage ),
264 nDocPages ( nDocP ),
265 pUserArea ( pArea ),
266 bState ( FALSE ),
267 bSourceRangeValid ( FALSE ),
268 bPrintCurrentTable ( FALSE ),
269 bMultiArea ( FALSE ),
270 nTabPages ( 0 ),
271 nTotalPages ( 0 ),
272 pPageData ( NULL )
274 pDev = pOutDev;
275 Construct( pOptions );
278 ScPrintFunc::ScPrintFunc( OutputDevice* pOutDev, ScDocShell* pShell,
279 const ScPrintState& rState, const ScPrintOptions* pOptions )
280 : pDocShell ( pShell ),
281 pPrinter ( NULL ),
282 pDrawView ( NULL ),
283 pUserArea ( NULL ),
284 bSourceRangeValid ( FALSE ),
285 bPrintCurrentTable ( FALSE ),
286 bMultiArea ( FALSE ),
287 pPageData ( NULL )
289 pDev = pOutDev;
291 nPrintTab = rState.nPrintTab;
292 nStartCol = rState.nStartCol;
293 nStartRow = rState.nStartRow;
294 nEndCol = rState.nEndCol;
295 nEndRow = rState.nEndRow;
296 nZoom = rState.nZoom;
297 nPagesX = rState.nPagesX;
298 nPagesY = rState.nPagesY;
299 nTabPages = rState.nTabPages;
300 nTotalPages = rState.nTotalPages;
301 nPageStart = rState.nPageStart;
302 nDocPages = rState.nDocPages;
303 bState = TRUE;
305 Construct( pOptions );
307 ScPrintFunc::ScPrintFunc( ScDocShell* pShell, Window* pWindow, SCTAB nTab,
308 long nPage, long nDocP, const ScRange* pArea,
309 const ScPrintOptions* pOptions )
310 : pDocShell ( pShell ),
311 pPrinter ( NULL ),
312 pDrawView ( NULL ),
313 nPrintTab ( nTab ),
314 nPageStart ( nPage ),
315 nDocPages ( nDocP ),
316 pUserArea ( pArea ),
317 bState ( FALSE ),
318 bPrintCurrentTable ( FALSE ),
319 bMultiArea ( FALSE ),
320 nTabPages ( 0 ),
321 nTotalPages ( 0 ),
322 pPageData ( NULL )
324 pDev = pWindow;
325 Construct( pOptions );
327 ScPrintFunc::ScPrintFunc( ScDocShell* pShell, Window* pWindow,
328 const ScPrintState& rState, const ScPrintOptions* pOptions )
329 : pDocShell ( pShell ),
330 pPrinter ( NULL ),
331 pDrawView ( NULL ),
332 pUserArea ( NULL ),
333 bPrintCurrentTable ( FALSE ),
334 bMultiArea ( FALSE ),
335 pPageData ( NULL )
337 pDev = pWindow;
339 nPrintTab = rState.nPrintTab;
340 nStartCol = rState.nStartCol;
341 nStartRow = rState.nStartRow;
342 nEndCol = rState.nEndCol;
343 nEndRow = rState.nEndRow;
344 nZoom = rState.nZoom;
345 nPagesX = rState.nPagesX;
346 nPagesY = rState.nPagesY;
347 nTabPages = rState.nTabPages;
348 nTotalPages = rState.nTotalPages;
349 nPageStart = rState.nPageStart;
350 nDocPages = rState.nDocPages;
351 bState = TRUE;
353 Construct( pOptions );
356 void ScPrintFunc::GetPrintState( ScPrintState& rState )
358 rState.nPrintTab = nPrintTab;
359 rState.nStartCol = nStartCol;
360 rState.nStartRow = nStartRow;
361 rState.nEndCol = nEndCol;
362 rState.nEndRow = nEndRow;
363 rState.nZoom = nZoom;
364 rState.nPagesX = nPagesX;
365 rState.nPagesY = nPagesY;
366 rState.nTabPages = nTabPages;
367 rState.nTotalPages = nTotalPages;
368 rState.nPageStart = nPageStart;
369 rState.nDocPages = nDocPages;
372 BOOL ScPrintFunc::GetLastSourceRange( ScRange& rRange ) const
374 rRange = aLastSourceRange;
375 return bSourceRangeValid;
378 void ScPrintFunc::FillPageData()
380 if (pPageData)
382 USHORT nCount = sal::static_int_cast<USHORT>( pPageData->GetCount() );
383 ScPrintRangeData& rData = pPageData->GetData(nCount); // hochzaehlen
385 rData.SetPrintRange( ScRange( nStartCol, nStartRow, nPrintTab,
386 nEndCol, nEndRow, nPrintTab ) );
387 rData.SetPagesX( nPagesX, pPageEndX );
388 rData.SetPagesY( nTotalY, pPageEndY );
390 // Einstellungen
391 rData.SetTopDown( aTableParam.bTopDown );
392 rData.SetAutomatic( !aAreaParam.bPrintArea );
396 ScPrintFunc::~ScPrintFunc()
398 ScAddress* pTripel = (ScAddress*) aNotePosList.First();
399 while (pTripel)
401 delete pTripel;
402 pTripel = (ScAddress*) aNotePosList.Next();
404 aNotePosList.Clear();
406 delete[] pPageEndX;
407 delete[] pPageEndY;
408 delete[] pPageRows;
409 delete pEditDefaults;
410 delete pEditEngine;
412 // Druckereinstellungen werden jetzt von aussen wiederhergestellt
414 // #64294# Fuer DrawingLayer/Charts muss der MapMode am Drucker (RefDevice) immer stimmen
415 SfxPrinter* pDocPrinter = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen
416 if (pDocPrinter)
417 pDocPrinter->SetMapMode(aOldPrinterMode);
420 void ScPrintFunc::SetDrawView( FmFormView* pNew )
422 pDrawView = pNew;
425 void lcl_HidePrint( ScTableInfo& rTabInfo, SCCOL nX1, SCCOL nX2 )
427 for (SCSIZE nArrY=1; nArrY+1<rTabInfo.mnArrCount; nArrY++)
429 RowInfo* pThisRowInfo = &rTabInfo.mpRowInfo[nArrY];
430 for (SCCOL nX=nX1; nX<=nX2; nX++)
432 const CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nX+1];
433 if (!rCellInfo.bEmptyCellText)
434 if (((const ScProtectionAttr&)rCellInfo.pPatternAttr->
435 GetItem(ATTR_PROTECTION, rCellInfo.pConditionSet)).GetHidePrint())
437 pThisRowInfo->pCellInfo[nX+1].pCell = NULL;
438 pThisRowInfo->pCellInfo[nX+1].bEmptyCellText = TRUE;
445 // Ausgabe auf Device (static)
447 // wird benutzt fuer:
448 // - Clipboard/Bitmap
449 // - Ole-Object (DocShell::Draw)
450 // - Vorschau bei Vorlagen
452 void ScPrintFunc::DrawToDev( ScDocument* pDoc, OutputDevice* pDev, double /* nPrintFactor */,
453 const Rectangle& rBound, ScViewData* pViewData, BOOL bMetaFile )
455 //! nPrintFactor auswerten !!!
457 SCTAB nTab = 0;
458 if (pViewData)
459 nTab = pViewData->GetTabNo();
461 BOOL bDoGrid, bNullVal, bFormula;
462 ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
463 SfxStyleSheetBase* pStyleSheet = pStylePool->Find( pDoc->GetPageStyle( nTab ), SFX_STYLE_FAMILY_PAGE );
464 if (pStyleSheet)
466 SfxItemSet& rSet = pStyleSheet->GetItemSet();
467 bDoGrid = ((const SfxBoolItem&)rSet.Get(ATTR_PAGE_GRID)).GetValue();
468 bNullVal = ((const SfxBoolItem&)rSet.Get(ATTR_PAGE_NULLVALS)).GetValue();
469 bFormula = ((const SfxBoolItem&)rSet.Get(ATTR_PAGE_FORMULAS)).GetValue();
471 else
473 const ScViewOptions& rOpt = pDoc->GetViewOptions();
474 bDoGrid = rOpt.GetOption(VOPT_GRID);
475 bNullVal = rOpt.GetOption(VOPT_NULLVALS);
476 bFormula = rOpt.GetOption(VOPT_FORMULAS);
479 MapMode aMode = pDev->GetMapMode();
481 Rectangle aRect = rBound;
483 if (aRect.Right() < aRect.Left() || aRect.Bottom() < aRect.Top())
484 aRect = Rectangle( Point(), pDev->GetOutputSize() );
486 SCCOL nX1 = 0;
487 SCROW nY1 = 0;
488 SCCOL nX2 = OLE_STD_CELLS_X - 1;
489 SCROW nY2 = OLE_STD_CELLS_Y - 1;
490 if (bMetaFile)
492 ScRange aRange = pDoc->GetRange( nTab, rBound );
493 nX1 = aRange.aStart.Col();
494 nY1 = aRange.aStart.Row();
495 nX2 = aRange.aEnd.Col();
496 nY2 = aRange.aEnd.Row();
498 else if (pViewData)
500 ScSplitPos eWhich = pViewData->GetActivePart();
501 ScHSplitPos eHWhich = WhichH(eWhich);
502 ScVSplitPos eVWhich = WhichV(eWhich);
503 nX1 = pViewData->GetPosX(eHWhich);
504 nY1 = pViewData->GetPosY(eVWhich);
505 nX2 = nX1 + pViewData->VisibleCellsX(eHWhich);
506 if (nX2>nX1) --nX2;
507 nY2 = nY1 + pViewData->VisibleCellsY(eVWhich);
508 if (nY2>nY1) --nY2;
511 if (nX1 > MAXCOL) nX1 = MAXCOL;
512 if (nX2 > MAXCOL) nX2 = MAXCOL;
513 if (nY1 > MAXROW) nY1 = MAXROW;
514 if (nY2 > MAXROW) nY2 = MAXROW;
516 long nDevSizeX = aRect.Right()-aRect.Left()+1;
517 long nDevSizeY = aRect.Bottom()-aRect.Top()+1;
519 Rectangle aLines;
520 ScRange aRange( nX1,nY1,nTab, nX2,nY2,nTab );
521 // BOOL bAddLines = pDoc->HasLines( aRange, aLines );
523 long nTwipsSizeX = 0;
524 for (SCCOL i=nX1; i<=nX2; i++)
525 nTwipsSizeX += pDoc->GetColWidth( i, nTab );
526 long nTwipsSizeY = (long) pDoc->GetRowHeight( nY1, nY2, nTab );
528 // wenn keine Linien, dann trotzdem Platz fuer den Aussenrahmen (20 Twips = 1pt)
529 // (HasLines initalisiert aLines auf 0,0,0,0)
530 nTwipsSizeX += aLines.Left() + Max( aLines.Right(), 20L );
531 nTwipsSizeY += aLines.Top() + Max( aLines.Bottom(), 20L );
533 double nScaleX = (double) nDevSizeX / nTwipsSizeX;
534 double nScaleY = (double) nDevSizeY / nTwipsSizeY;
536 //! Flag bei FillInfo uebergeben !!!!!
537 ScRange aERange;
538 BOOL bEmbed = pDoc->IsEmbedded();
539 if (bEmbed)
541 pDoc->GetEmbedded(aERange);
542 pDoc->ResetEmbedded();
545 // Daten zusammenstellen
547 ScTableInfo aTabInfo;
548 pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab,
549 nScaleX, nScaleY, FALSE, bFormula );
550 lcl_HidePrint( aTabInfo, nX1, nX2 );
552 if (bEmbed)
553 pDoc->SetEmbedded(aERange);
555 /* if (!bMetaFile)
556 pDev->SetMapMode(MAP_PIXEL);
558 long nScrX = aRect.Left();
559 long nScrY = aRect.Top();
561 // Wenn keine Linien, trotzdem Platz fuer Gitterlinien lassen
562 // (werden sonst abgeschnitten)
563 long nAddX = (long)( aLines.Left() * nScaleX );
564 nScrX += ( nAddX ? nAddX : 1 );
565 long nAddY = (long)( aLines.Top() * nScaleY );
566 nScrY += ( nAddY ? nAddY : 1 );
568 ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pDoc, nTab,
569 nScrX, nScrY, nX1, nY1, nX2, nY2, nScaleX, nScaleY );
570 aOutputData.SetMetaFileMode(bMetaFile);
571 aOutputData.SetShowNullValues(bNullVal);
572 aOutputData.SetShowFormulas(bFormula);
574 // #114135#
575 ScDrawLayer* pModel = pDoc->GetDrawLayer();
576 FmFormView* pDrawView = NULL;
578 if( pModel )
580 pDrawView = new FmFormView( pModel, pDev );
581 pDrawView->ShowSdrPage(pDrawView->GetModel()->GetPage(nTab));
582 pDrawView->SetPrintPreview( TRUE );
583 aOutputData.SetDrawView( pDrawView );
586 //! SetUseStyleColor ??
588 if ( bMetaFile && pDev->GetOutDevType() == OUTDEV_VIRDEV )
589 aOutputData.SetSnapPixel();
591 Point aLogStart = pDev->PixelToLogic( Point(nScrX,nScrY), MAP_100TH_MM );
592 long nLogStX = aLogStart.X();
593 long nLogStY = aLogStart.Y();
595 //! nZoom fuer GetFont in OutputData ???
597 if (!bMetaFile && pViewData)
598 pDev->SetMapMode(pViewData->GetLogicMode(pViewData->GetActivePart()));
600 // #i72502#
601 const Point aMMOffset(aOutputData.PrePrintDrawingLayer(nLogStX, nLogStY));
602 aOutputData.PrintDrawingLayer(SC_LAYER_BACK, aMMOffset);
604 if (!bMetaFile && pViewData)
605 pDev->SetMapMode(aMode);
607 aOutputData.DrawBackground();
609 #ifdef OS2
610 if (bMetaFile && !bDoGrid)
612 // unter OS2 fuer Metafiles gesamte Flaeche benutzen,
613 // weil sonst die Groesse nicht erkannt wird
614 pDev->SetLineColor();
615 pDev->SetFillColor();
616 pDev->DrawRect( Rectangle( nScrX,nScrY,
617 nScrX+aOutputData.GetScrW(), nScrY+aOutputData.GetScrH() ) );
619 #endif
621 aOutputData.DrawShadow();
622 aOutputData.DrawFrame();
623 aOutputData.DrawStrings();
625 if (!bMetaFile && pViewData)
626 pDev->SetMapMode(pViewData->GetLogicMode(pViewData->GetActivePart()));
628 aOutputData.DrawEdit(!bMetaFile);
630 if (bDoGrid)
632 if (!bMetaFile && pViewData)
633 pDev->SetMapMode(aMode);
635 aOutputData.DrawGrid( TRUE, FALSE ); // keine Seitenumbrueche
637 pDev->SetLineColor( COL_BLACK );
639 Size aOne = pDev->PixelToLogic( Size(1,1) );
640 if (bMetaFile)
641 aOne = Size(1,1); // compatible with DrawGrid
642 long nRight = nScrX + aOutputData.GetScrW() - aOne.Width();
643 long nBottom = nScrY + aOutputData.GetScrH() - aOne.Height();
645 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
647 // extra line at the left edge for left-to-right, right for right-to-left
648 if ( bLayoutRTL )
649 pDev->DrawLine( Point(nRight,nScrY), Point(nRight,nBottom) );
650 else
651 pDev->DrawLine( Point(nScrX,nScrY), Point(nScrX,nBottom) );
652 // extra line at the top in both cases
653 pDev->DrawLine( Point(nScrX,nScrY), Point(nRight,nScrY) );
656 // #i72502#
657 aOutputData.PrintDrawingLayer(SC_LAYER_FRONT, aMMOffset);
658 aOutputData.PrintDrawingLayer(SC_LAYER_INTERN, aMMOffset);
659 aOutputData.PostPrintDrawingLayer(aMMOffset); // #i74768#
661 // #114135#
662 delete pDrawView;
666 // Drucken
669 void lcl_FillHFParam( ScPrintHFParam& rParam, const SfxItemSet* pHFSet )
671 // nDistance muss vorher unterschiedlich initalisiert sein
673 if ( pHFSet == NULL )
675 rParam.bEnable = FALSE;
676 rParam.pBorder = NULL;
677 rParam.pBack = NULL;
678 rParam.pShadow = NULL;
680 else
682 rParam.bEnable = ((const SfxBoolItem&) pHFSet->Get(ATTR_PAGE_ON)).GetValue();
683 rParam.bDynamic = ((const SfxBoolItem&) pHFSet->Get(ATTR_PAGE_DYNAMIC)).GetValue();
684 rParam.bShared = ((const SfxBoolItem&) pHFSet->Get(ATTR_PAGE_SHARED)).GetValue();
685 rParam.nHeight = ((const SvxSizeItem&) pHFSet->Get(ATTR_PAGE_SIZE)).GetSize().Height();
686 const SvxLRSpaceItem* pHFLR = &(const SvxLRSpaceItem&) pHFSet->Get(ATTR_LRSPACE);
687 long nTmp;
688 nTmp = pHFLR->GetLeft();
689 rParam.nLeft = nTmp < 0 ? 0 : USHORT(nTmp);
690 nTmp = pHFLR->GetRight();
691 rParam.nRight = nTmp < 0 ? 0 : USHORT(nTmp);
692 rParam.pBorder = (const SvxBoxItem*) &pHFSet->Get(ATTR_BORDER);
693 rParam.pBack = (const SvxBrushItem*) &pHFSet->Get(ATTR_BACKGROUND);
694 rParam.pShadow = (const SvxShadowItem*)&pHFSet->Get(ATTR_SHADOW);;
696 // jetzt doch wieder schon im Dialog:
697 // rParam.nHeight += rParam.nDistance; // nicht mehr im Dialog ???
699 if (rParam.pBorder)
700 rParam.nHeight += lcl_LineTotal( rParam.pBorder->GetTop() ) +
701 lcl_LineTotal( rParam.pBorder->GetBottom() );
703 rParam.nManHeight = rParam.nHeight;
706 if (!rParam.bEnable)
707 rParam.nHeight = 0;
710 // bNew = TRUE: benutzten Bereich aus dem Dokument suchen
711 // bNew = FALSE: nur ganze Zeilen/Spalten begrenzen
713 BOOL ScPrintFunc::AdjustPrintArea( BOOL bNew )
715 SCCOL nOldEndCol = nEndCol; // nur wichtig bei !bNew
716 SCROW nOldEndRow = nEndRow;
717 BOOL bChangeCol = TRUE; // bei bNew werden beide angepasst
718 BOOL bChangeRow = TRUE;
720 BOOL bNotes = aTableParam.bNotes;
721 if ( bNew )
723 nStartCol = 0;
724 nStartRow = 0;
725 if (!pDoc->GetPrintArea( nPrintTab, nEndCol, nEndRow, bNotes ))
726 return FALSE; // nix
728 else
730 BOOL bFound = TRUE;
731 bChangeCol = ( nStartCol == 0 && nEndCol == MAXCOL );
732 bChangeRow = ( nStartRow == 0 && nEndRow == MAXROW );
733 BOOL bForcedChangeRow = FALSE;
735 // #i53558# Crop entire column of old row limit to real print area with
736 // some fuzzyness.
737 if (!bChangeRow && nStartRow == 0)
739 SCROW nPAEndRow;
740 bFound = pDoc->GetPrintAreaVer( nPrintTab, nStartCol, nEndCol, nPAEndRow, bNotes );
741 // Say we don't want to print more than ~1000 empty rows, which are
742 // about 14 pages intentionally left blank..
743 const SCROW nFuzzy = 23*42;
744 if (nPAEndRow + nFuzzy < nEndRow)
746 bForcedChangeRow = TRUE;
747 nEndRow = nPAEndRow;
749 else
750 bFound = TRUE; // user seems to _want_ to print some empty rows
752 // TODO: in case we extend the number of columns we may have to do the
753 // same for horizontal cropping.
755 if ( bChangeCol && bChangeRow )
756 bFound = pDoc->GetPrintArea( nPrintTab, nEndCol, nEndRow, bNotes );
757 else if ( bChangeCol )
758 bFound = pDoc->GetPrintAreaHor( nPrintTab, nStartRow, nEndRow, nEndCol, bNotes );
759 else if ( bChangeRow )
760 bFound = pDoc->GetPrintAreaVer( nPrintTab, nStartCol, nEndCol, nEndRow, bNotes );
762 if (!bFound)
763 return FALSE; // leer
765 if (bForcedChangeRow)
766 bChangeRow = TRUE;
769 pDoc->ExtendMerge( nStartCol,nStartRow, nEndCol,nEndRow, nPrintTab,
770 FALSE, TRUE ); // kein Refresh, incl. Attrs
772 if ( bChangeCol )
774 OutputDevice* pRefDev = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen
775 pRefDev->SetMapMode( MAP_PIXEL ); // wichtig fuer GetNeededSize
777 pDoc->ExtendPrintArea( pRefDev,
778 nPrintTab, nStartCol, nStartRow, nEndCol, nEndRow );
779 // nEndCol wird veraendert
782 if ( nEndCol < MAXCOL && pDoc->HasAttrib(
783 nEndCol,nStartRow,nPrintTab, nEndCol,nEndRow,nPrintTab, HASATTR_SHADOW_RIGHT ) )
784 ++nEndCol;
785 if ( nEndRow < MAXROW && pDoc->HasAttrib(
786 nStartCol,nEndRow,nPrintTab, nEndCol,nEndRow,nPrintTab, HASATTR_SHADOW_DOWN ) )
787 ++nEndRow;
789 if (!bChangeCol) nEndCol = nOldEndCol;
790 if (!bChangeRow) nEndRow = nOldEndRow;
792 return TRUE;
795 long ScPrintFunc::TextHeight( const EditTextObject* pObject )
797 if (!pObject)
798 return 0;
800 // pEditEngine->SetPageNo( nTotalPages );
801 pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, FALSE );
803 return (long) pEditEngine->GetTextHeight();
806 // nZoom muss gesetzt sein !!!
807 // und der entsprechende Twip-MapMode eingestellt
809 void ScPrintFunc::UpdateHFHeight( ScPrintHFParam& rParam )
811 DBG_ASSERT( aPageSize.Width(), "UpdateHFHeight ohne aPageSize");
813 if (rParam.bEnable && rParam.bDynamic)
815 // nHeight aus Inhalten berechnen
817 MakeEditEngine();
818 long nPaperWidth = ( aPageSize.Width() - nLeftMargin - nRightMargin -
819 rParam.nLeft - rParam.nRight ) * 100 / nZoom;
820 if (rParam.pBorder)
821 nPaperWidth -= ( rParam.pBorder->GetDistance(BOX_LINE_LEFT) +
822 rParam.pBorder->GetDistance(BOX_LINE_RIGHT) +
823 lcl_LineTotal(rParam.pBorder->GetLeft()) +
824 lcl_LineTotal(rParam.pBorder->GetRight()) ) * 100 / nZoom;
826 if (rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE)
827 nPaperWidth -= ( rParam.pShadow->CalcShadowSpace(SHADOW_LEFT) +
828 rParam.pShadow->CalcShadowSpace(SHADOW_RIGHT) ) * 100L / nZoom;
830 pEditEngine->SetPaperSize( Size( nPaperWidth, 10000 ) );
832 long nMaxHeight = 0;
833 if ( rParam.pLeft )
835 nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pLeft->GetLeftArea() ) );
836 nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pLeft->GetCenterArea() ) );
837 nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pLeft->GetRightArea() ) );
839 if ( rParam.pRight )
841 nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pRight->GetLeftArea() ) );
842 nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pRight->GetCenterArea() ) );
843 nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pRight->GetRightArea() ) );
846 rParam.nHeight = nMaxHeight + rParam.nDistance;
847 if (rParam.pBorder)
848 rParam.nHeight += rParam.pBorder->GetDistance(BOX_LINE_TOP) +
849 rParam.pBorder->GetDistance(BOX_LINE_BOTTOM) +
850 lcl_LineTotal( rParam.pBorder->GetTop() ) +
851 lcl_LineTotal( rParam.pBorder->GetBottom() );
852 if (rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE)
853 rParam.nHeight += rParam.pShadow->CalcShadowSpace(SHADOW_TOP) +
854 rParam.pShadow->CalcShadowSpace(SHADOW_BOTTOM);
856 if (rParam.nHeight < rParam.nManHeight)
857 rParam.nHeight = rParam.nManHeight; // eingestelltes Minimum
861 void ScPrintFunc::InitParam( const ScPrintOptions* pOptions )
863 if (!pParamSet)
864 return;
866 // TabPage "Seite"
867 const SvxLRSpaceItem* pLRItem = (const SvxLRSpaceItem*) &pParamSet->Get( ATTR_LRSPACE );
868 long nTmp;
869 nTmp = pLRItem->GetLeft();
870 nLeftMargin = nTmp < 0 ? 0 : USHORT(nTmp);
871 nTmp = pLRItem->GetRight();
872 nRightMargin = nTmp < 0 ? 0 : USHORT(nTmp);
873 const SvxULSpaceItem* pULItem = (const SvxULSpaceItem*) &pParamSet->Get( ATTR_ULSPACE );
874 nTopMargin = pULItem->GetUpper();
875 nBottomMargin = pULItem->GetLower();
877 const SvxPageItem* pPageItem = (const SvxPageItem*) &pParamSet->Get( ATTR_PAGE );
878 nPageUsage = pPageItem->GetPageUsage();
879 bLandscape = pPageItem->IsLandscape();
880 aFieldData.eNumType = pPageItem->GetNumType();
882 bCenterHor = ((const SfxBoolItem&) pParamSet->Get(ATTR_PAGE_HORCENTER)).GetValue();
883 bCenterVer = ((const SfxBoolItem&) pParamSet->Get(ATTR_PAGE_VERCENTER)).GetValue();
885 aPageSize = ((const SvxSizeItem&) pParamSet->Get(ATTR_PAGE_SIZE)).GetSize();
886 if ( !aPageSize.Width() || !aPageSize.Height() )
888 DBG_ERROR("PageSize Null ?!?!?");
889 aPageSize = SvxPaperInfo::GetPaperSize( SVX_PAPER_A4 );
892 pBorderItem = (const SvxBoxItem*) &pParamSet->Get(ATTR_BORDER);
893 pBackgroundItem = (const SvxBrushItem*) &pParamSet->Get(ATTR_BACKGROUND);
894 pShadowItem = (const SvxShadowItem*) &pParamSet->Get(ATTR_SHADOW);
896 // TabPage "Kopfzeile"
898 aHdr.pLeft = (const ScPageHFItem*) &pParamSet->Get(ATTR_PAGE_HEADERLEFT); // Inhalt
899 aHdr.pRight = (const ScPageHFItem*) &pParamSet->Get(ATTR_PAGE_HEADERRIGHT);
901 const SvxSetItem* pHeaderSetItem;
902 const SfxItemSet* pHeaderSet = NULL;
903 if ( pParamSet->GetItemState( ATTR_PAGE_HEADERSET, FALSE,
904 (const SfxPoolItem**)&pHeaderSetItem ) == SFX_ITEM_SET )
906 pHeaderSet = &pHeaderSetItem->GetItemSet();
907 // Kopfzeile hat unteren Abstand
908 aHdr.nDistance = ((const SvxULSpaceItem&) pHeaderSet->Get(ATTR_ULSPACE)).GetLower();
910 lcl_FillHFParam( aHdr, pHeaderSet );
912 // TabPage "Fusszeile"
914 aFtr.pLeft = (const ScPageHFItem*) &pParamSet->Get(ATTR_PAGE_FOOTERLEFT); // Inhalt
915 aFtr.pRight = (const ScPageHFItem*) &pParamSet->Get(ATTR_PAGE_FOOTERRIGHT);
917 const SvxSetItem* pFooterSetItem;
918 const SfxItemSet* pFooterSet = NULL;
919 if ( pParamSet->GetItemState( ATTR_PAGE_FOOTERSET, FALSE,
920 (const SfxPoolItem**)&pFooterSetItem ) == SFX_ITEM_SET )
922 pFooterSet = &pFooterSetItem->GetItemSet();
923 // Fusszeile hat oberen Abstand
924 aFtr.nDistance = ((const SvxULSpaceItem&) pFooterSet->Get(ATTR_ULSPACE)).GetUpper();
926 lcl_FillHFParam( aFtr, pFooterSet );
928 //------------------------------------------------------
929 // Table-/Area-Params aus einzelnen Items zusammenbauen:
930 //------------------------------------------------------
931 // TabPage "Tabelle"
933 const SfxUInt16Item* pScaleItem = NULL;
934 const ScPageScaleToItem* pScaleToItem = NULL;
935 const SfxUInt16Item* pScaleToPagesItem = NULL;
936 SfxItemState eState;
938 eState = pParamSet->GetItemState( ATTR_PAGE_SCALE, FALSE,
939 (const SfxPoolItem**)&pScaleItem );
940 if ( SFX_ITEM_DEFAULT == eState )
941 pScaleItem = (const SfxUInt16Item*)
942 &pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALE );
944 eState = pParamSet->GetItemState( ATTR_PAGE_SCALETO, FALSE,
945 (const SfxPoolItem**)&pScaleToItem );
946 if ( SFX_ITEM_DEFAULT == eState )
947 pScaleToItem = (const ScPageScaleToItem*)
948 &pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALETO );
950 eState = pParamSet->GetItemState( ATTR_PAGE_SCALETOPAGES, FALSE,
951 (const SfxPoolItem**)&pScaleToPagesItem );
952 if ( SFX_ITEM_DEFAULT == eState )
953 pScaleToPagesItem = (const SfxUInt16Item*)
954 &pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALETOPAGES );
956 DBG_ASSERT( pScaleItem && pScaleToItem && pScaleToPagesItem, "Missing ScaleItem! :-/" );
958 aTableParam.bCellContent = TRUE;
959 aTableParam.bNotes = GET_BOOL(pParamSet,ATTR_PAGE_NOTES);
960 aTableParam.bGrid = GET_BOOL(pParamSet,ATTR_PAGE_GRID);
961 aTableParam.bHeaders = GET_BOOL(pParamSet,ATTR_PAGE_HEADERS);
962 aTableParam.bFormulas = GET_BOOL(pParamSet,ATTR_PAGE_FORMULAS);
963 aTableParam.bNullVals = GET_BOOL(pParamSet,ATTR_PAGE_NULLVALS);
964 aTableParam.bCharts = GET_SHOW(pParamSet,ATTR_PAGE_CHARTS);
965 aTableParam.bObjects = GET_SHOW(pParamSet,ATTR_PAGE_OBJECTS);
966 aTableParam.bDrawings = GET_SHOW(pParamSet,ATTR_PAGE_DRAWINGS);
967 aTableParam.bTopDown = GET_BOOL(pParamSet,ATTR_PAGE_TOPDOWN);
968 aTableParam.bLeftRight = !aTableParam.bLeftRight;
969 aTableParam.nFirstPageNo = GET_USHORT(pParamSet,ATTR_PAGE_FIRSTPAGENO);
970 if (!aTableParam.nFirstPageNo)
971 aTableParam.nFirstPageNo = (USHORT) nPageStart; // von vorheriger Tabelle
973 if ( pScaleItem && pScaleToItem && pScaleToPagesItem )
975 UINT16 nScaleAll = pScaleItem->GetValue();
976 UINT16 nScaleToPages = pScaleToPagesItem->GetValue();
978 aTableParam.bScaleNone = (nScaleAll == 100);
979 aTableParam.bScaleAll = (nScaleAll > 0 );
980 aTableParam.bScaleTo = pScaleToItem->IsValid();
981 aTableParam.bScalePageNum = (nScaleToPages > 0 );
982 aTableParam.nScaleAll = nScaleAll;
983 aTableParam.nScaleWidth = pScaleToItem->GetWidth();
984 aTableParam.nScaleHeight = pScaleToItem->GetHeight();
985 aTableParam.nScalePageNum = nScaleToPages;
987 else
989 aTableParam.bScaleNone = TRUE;
990 aTableParam.bScaleAll = FALSE;
991 aTableParam.bScaleTo = FALSE;
992 aTableParam.bScalePageNum = FALSE;
993 aTableParam.nScaleAll = 0;
994 aTableParam.nScaleWidth = 0;
995 aTableParam.nScaleHeight = 0;
996 aTableParam.nScalePageNum = 0;
999 // skip empty pages only if options with that flag are passed
1000 aTableParam.bSkipEmpty = pOptions && pOptions->GetSkipEmpty();
1001 if ( pPageData )
1002 aTableParam.bSkipEmpty = FALSE;
1003 // Wenn pPageData gesetzt ist, interessieren fuer die Umbruch-Vorschau
1004 // nur die Umbrueche, leere Seiten werden nicht speziell behandelt
1006 //------------------------------------------------------
1007 // TabPage "Bereiche":
1008 //------------------------------------------------------
1010 //! alle PrintAreas der Tabelle durchgehen !!!
1011 const ScRange* pPrintArea = pDoc->GetPrintRange( nPrintTab, 0 );
1012 const ScRange* pRepeatCol = pDoc->GetRepeatColRange( nPrintTab );
1013 const ScRange* pRepeatRow = pDoc->GetRepeatRowRange( nPrintTab );
1015 // ATTR_PAGE_PRINTTABLES wird ignoriert
1017 if ( pUserArea ) // UserArea (Selektion) hat Vorrang
1019 bPrintCurrentTable =
1020 aAreaParam.bPrintArea = TRUE; // Selektion
1021 aAreaParam.aPrintArea = *pUserArea;
1023 // Die Tabellen-Abfrage ist schon in DocShell::Print, hier immer
1024 aAreaParam.aPrintArea.aStart.SetTab(nPrintTab);
1025 aAreaParam.aPrintArea.aEnd.SetTab(nPrintTab);
1027 // lcl_LimitRange( aAreaParam.aPrintArea, nPrintTab ); // ganze Zeilen/Spalten...
1029 else if ( pDoc->HasPrintRange() )
1031 if ( pPrintArea ) // mindestens eine gesetzt ?
1033 bPrintCurrentTable =
1034 aAreaParam.bPrintArea = TRUE;
1035 aAreaParam.aPrintArea = *pPrintArea;
1037 bMultiArea = ( pDoc->GetPrintRangeCount(nPrintTab) > 1 );
1039 else
1041 // do not print hidden sheets with "Print entire sheet" flag
1042 bPrintCurrentTable = pDoc->IsPrintEntireSheet( nPrintTab ) && pDoc->IsVisible( nPrintTab );
1043 aAreaParam.bPrintArea = !bPrintCurrentTable; // otherwise the table is always counted
1046 else
1048 // #74834# don't print hidden tables if there's no print range defined there
1049 if ( pDoc->IsVisible( nPrintTab ) )
1051 aAreaParam.bPrintArea = FALSE;
1052 bPrintCurrentTable = TRUE;
1054 else
1056 aAreaParam.bPrintArea = TRUE; // otherwise the table is always counted
1057 bPrintCurrentTable = FALSE;
1061 if ( pRepeatCol )
1063 aAreaParam.bRepeatCol = TRUE;
1064 aAreaParam.aRepeatCol = *pRepeatCol;
1065 nRepeatStartCol = pRepeatCol->aStart.Col();
1066 nRepeatEndCol = pRepeatCol->aEnd .Col();
1068 else
1070 aAreaParam.bRepeatCol = FALSE;
1071 nRepeatStartCol = nRepeatEndCol = SCCOL_REPEAT_NONE;
1074 if ( pRepeatRow )
1076 aAreaParam.bRepeatRow = TRUE;
1077 aAreaParam.aRepeatRow = *pRepeatRow;
1078 nRepeatStartRow = pRepeatRow->aStart.Row();
1079 nRepeatEndRow = pRepeatRow->aEnd .Row();
1081 else
1083 aAreaParam.bRepeatRow = FALSE;
1084 nRepeatStartRow = nRepeatEndRow = SCROW_REPEAT_NONE;
1088 // Seiten aufteilen
1091 if (!bState)
1093 nTabPages = CountPages(); // berechnet auch Zoom
1094 nTotalPages = nTabPages;
1095 nTotalPages += CountNotePages();
1097 else
1099 CalcPages(); // nur Umbrueche suchen
1100 CountNotePages(); // Notizen zaehlen, auch wenn Seitenzahl schon bekannt
1103 if (nDocPages)
1104 aFieldData.nTotalPages = nDocPages;
1105 else
1106 aFieldData.nTotalPages = nTotalPages;
1108 SetDateTime( Date(), Time() );
1110 aFieldData.aTitle = pDocShell->GetTitle();
1111 const INetURLObject& rURLObj = pDocShell->GetMedium()->GetURLObject();
1112 aFieldData.aLongDocName = rURLObj.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS );
1113 if ( aFieldData.aLongDocName.Len() )
1114 aFieldData.aShortDocName = rURLObj.GetName( INetURLObject::DECODE_UNAMBIGUOUS );
1115 else
1116 aFieldData.aShortDocName = aFieldData.aLongDocName = aFieldData.aTitle;
1118 // Druckereinstellungen (Orientation, Paper) jetzt erst bei DoPrint
1121 Size ScPrintFunc::GetDataSize() const
1123 Size aSize = aPageSize;
1124 aSize.Width() -= nLeftMargin + nRightMargin;
1125 aSize.Height() -= nTopMargin + nBottomMargin;
1126 aSize.Height() -= aHdr.nHeight + aFtr.nHeight;
1127 return aSize;
1130 void ScPrintFunc::GetScaleData( Size& rPhysSize, long& rDocHdr, long& rDocFtr )
1132 rPhysSize = aPageSize;
1133 rPhysSize.Width() -= nLeftMargin + nRightMargin;
1134 rPhysSize.Height() -= nTopMargin + nBottomMargin;
1136 rDocHdr = aHdr.nHeight;
1137 rDocFtr = aFtr.nHeight;
1140 void ScPrintFunc::SetDateTime( const Date& rDate, const Time& rTime )
1142 aFieldData.aDate = rDate;
1143 aFieldData.aTime = rTime;
1146 void lcl_DrawGraphic( const Graphic &rGraphic, OutputDevice *pOut,
1147 const Rectangle &rGrf, const Rectangle &rOut )
1149 const FASTBOOL bNotInside = !rOut.IsInside( rGrf );
1150 if ( bNotInside )
1152 pOut->Push();
1153 pOut->IntersectClipRegion( rOut );
1156 ((Graphic&)rGraphic).Draw( pOut, rGrf.TopLeft(), rGrf.GetSize() );
1158 if ( bNotInside )
1159 pOut->Pop();
1162 void lcl_DrawGraphic( const SvxBrushItem &rBrush, OutputDevice *pOut, OutputDevice* pRefDev,
1163 const Rectangle &rOrg, const Rectangle &rOut )
1165 Size aGrfSize(0,0);
1166 const Graphic *pGraphic = rBrush.GetGraphic();
1167 SvxGraphicPosition ePos;
1168 if ( pGraphic && pGraphic->IsSupportedGraphic() )
1170 const MapMode aMapMM( MAP_100TH_MM );
1171 if ( pGraphic->GetPrefMapMode().GetMapUnit() == MAP_PIXEL )
1172 aGrfSize = pRefDev->PixelToLogic( pGraphic->GetPrefSize(), aMapMM );
1173 else
1174 aGrfSize = OutputDevice::LogicToLogic( pGraphic->GetPrefSize(),
1175 pGraphic->GetPrefMapMode(), aMapMM );
1176 ePos = rBrush.GetGraphicPos();
1178 else
1179 ePos = GPOS_NONE;
1181 Point aPos;
1182 Size aDrawSize = aGrfSize;
1184 FASTBOOL bDraw = TRUE;
1185 // FASTBOOL bRetouche = TRUE;
1186 switch ( ePos )
1188 case GPOS_LT: aPos = rOrg.TopLeft();
1189 break;
1190 case GPOS_MT: aPos.Y() = rOrg.Top();
1191 aPos.X() = rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2;
1192 break;
1193 case GPOS_RT: aPos.Y() = rOrg.Top();
1194 aPos.X() = rOrg.Right() - aGrfSize.Width();
1195 break;
1197 case GPOS_LM: aPos.Y() = rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2;
1198 aPos.X() = rOrg.Left();
1199 break;
1200 case GPOS_MM: aPos.Y() = rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2;
1201 aPos.X() = rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2;
1202 break;
1203 case GPOS_RM: aPos.Y() = rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2;
1204 aPos.X() = rOrg.Right() - aGrfSize.Width();
1205 break;
1207 case GPOS_LB: aPos.Y() = rOrg.Bottom() - aGrfSize.Height();
1208 aPos.X() = rOrg.Left();
1209 break;
1210 case GPOS_MB: aPos.Y() = rOrg.Bottom() - aGrfSize.Height();
1211 aPos.X() = rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2;
1212 break;
1213 case GPOS_RB: aPos.Y() = rOrg.Bottom() - aGrfSize.Height();
1214 aPos.X() = rOrg.Right() - aGrfSize.Width();
1215 break;
1217 case GPOS_AREA:
1218 aPos = rOrg.TopLeft();
1219 aDrawSize = rOrg.GetSize();
1220 // bRetouche = FALSE;
1221 break;
1222 case GPOS_TILED:
1224 // #104004# use GraphicObject::DrawTiled instead of an own loop
1225 // (pixel rounding is handled correctly, and a very small bitmap
1226 // is duplicated into a bigger one for better performance)
1228 GraphicObject aObject( *pGraphic );
1230 if( pOut->GetPDFWriter() &&
1231 (aObject.GetType() == GRAPHIC_BITMAP || aObject.GetType() == GRAPHIC_DEFAULT) )
1233 // #104004# For PDF export, every draw
1234 // operation for bitmaps takes a noticeable
1235 // amount of place (~50 characters). Thus,
1236 // optimize between tile bitmap size and
1237 // number of drawing operations here.
1239 // A_out
1240 // n_chars = k1 * ---------- + k2 * A_bitmap
1241 // A_bitmap
1243 // minimum n_chars is obtained for (derive for
1244 // A_bitmap, set to 0, take positive
1245 // solution):
1246 // k1
1247 // A_bitmap = Sqrt( ---- A_out )
1248 // k2
1250 // where k1 is the number of chars per draw
1251 // operation, and k2 is the number of chars
1252 // per bitmap pixel. This is approximately 50
1253 // and 7 for current PDF writer, respectively.
1255 const double k1( 50 );
1256 const double k2( 7 );
1257 const Size aSize( rOrg.GetSize() );
1258 const double Abitmap( k1/k2 * aSize.Width()*aSize.Height() );
1260 aObject.DrawTiled( pOut, rOrg, aGrfSize, Size(0,0),
1261 NULL, GRFMGR_DRAW_STANDARD,
1262 ::std::max( 128, static_cast<int>( sqrt(sqrt( Abitmap)) + .5 ) ) );
1264 else
1266 aObject.DrawTiled( pOut, rOrg, aGrfSize, Size(0,0) );
1269 bDraw = FALSE;
1270 // bRetouche = FALSE;
1272 break;
1274 case GPOS_NONE:
1275 bDraw = FALSE;
1276 break;
1278 default: DBG_ASSERT( !pOut, "new Graphic position?" );
1280 Rectangle aGrf( aPos,aDrawSize );
1281 if ( bDraw && aGrf.IsOver( rOut ) )
1283 lcl_DrawGraphic( *pGraphic, pOut, aGrf, rOut );
1287 // Rahmen wird nach innen gezeichnet
1289 void ScPrintFunc::DrawBorder( long nScrX, long nScrY, long nScrW, long nScrH,
1290 const SvxBoxItem* pBorderData, const SvxBrushItem* pBackground,
1291 const SvxShadowItem* pShadow )
1293 //! direkte Ausgabe aus SvxBoxItem !!!
1295 if (pBorderData)
1296 if ( !pBorderData->GetTop() && !pBorderData->GetBottom() && !pBorderData->GetLeft() &&
1297 !pBorderData->GetRight() )
1298 pBorderData = NULL;
1300 if (!pBorderData && !pBackground && !pShadow)
1301 return; // nichts zu tun
1303 long nLeft = 0;
1304 long nRight = 0;
1305 long nTop = 0;
1306 long nBottom = 0;
1308 // aFrameRect - aussen um die Umrandung, ohne Schatten
1309 if ( pShadow && pShadow->GetLocation() != SVX_SHADOW_NONE )
1311 nLeft += (long) ( pShadow->CalcShadowSpace(SHADOW_LEFT) * nScaleX );
1312 nRight += (long) ( pShadow->CalcShadowSpace(SHADOW_RIGHT) * nScaleX );
1313 nTop += (long) ( pShadow->CalcShadowSpace(SHADOW_TOP) * nScaleY );
1314 nBottom += (long) ( pShadow->CalcShadowSpace(SHADOW_BOTTOM) * nScaleY );
1316 Rectangle aFrameRect( Point(nScrX+nLeft, nScrY+nTop),
1317 Size(nScrW-nLeft-nRight, nScrH-nTop-nBottom) );
1319 // Mitte der Umrandung, um Linien ueber OutputData zu zeichnen:
1320 if (pBorderData)
1322 nLeft += (long) ( lcl_LineTotal(pBorderData->GetLeft()) * nScaleX / 2 );
1323 nRight += (long) ( lcl_LineTotal(pBorderData->GetRight()) * nScaleX / 2 );
1324 nTop += (long) ( lcl_LineTotal(pBorderData->GetTop()) * nScaleY / 2 );
1325 nBottom += (long) ( lcl_LineTotal(pBorderData->GetBottom()) * nScaleY / 2 );
1327 long nEffHeight = nScrH - nTop - nBottom;
1328 long nEffWidth = nScrW - nLeft - nRight;
1329 if (nEffHeight<=0 || nEffWidth<=0)
1330 return; // leer
1332 // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed TRUE)
1333 BOOL bCellContrast = bUseStyleColor &&
1334 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
1336 if ( pBackground && !bCellContrast )
1338 // Rectangle aBackRect( Point(nScrX+nLeft, nScrY+nTop), Size(nEffWidth,nEffHeight) );
1339 if (pBackground->GetGraphicPos() != GPOS_NONE)
1341 OutputDevice* pRefDev;
1342 if ( bIsRender )
1343 pRefDev = pDev; // don't use printer for PDF
1344 else
1345 pRefDev = pDoc->GetPrinter(); // use printer also for preview
1347 lcl_DrawGraphic( *pBackground, pDev, pRefDev, aFrameRect, aFrameRect );
1349 else
1351 pDev->SetFillColor(pBackground->GetColor());
1352 pDev->SetLineColor();
1353 pDev->DrawRect(aFrameRect);
1357 if ( pShadow && pShadow->GetLocation() != SVX_SHADOW_NONE )
1359 if ( bCellContrast )
1360 pDev->SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
1361 else
1362 pDev->SetFillColor(pShadow->GetColor());
1363 pDev->SetLineColor();
1364 long nShadowX = (long) ( pShadow->GetWidth() * nScaleX );
1365 long nShadowY = (long) ( pShadow->GetWidth() * nScaleY );
1366 switch (pShadow->GetLocation())
1368 case SVX_SHADOW_TOPLEFT:
1369 pDev->DrawRect( Rectangle(
1370 aFrameRect.Left()-nShadowX, aFrameRect.Top()-nShadowY,
1371 aFrameRect.Right()-nShadowX, aFrameRect.Top() ) );
1372 pDev->DrawRect( Rectangle(
1373 aFrameRect.Left()-nShadowX, aFrameRect.Top()-nShadowY,
1374 aFrameRect.Left(), aFrameRect.Bottom()-nShadowY ) );
1375 break;
1376 case SVX_SHADOW_TOPRIGHT:
1377 pDev->DrawRect( Rectangle(
1378 aFrameRect.Left()+nShadowX, aFrameRect.Top()-nShadowY,
1379 aFrameRect.Right()+nShadowX, aFrameRect.Top() ) );
1380 pDev->DrawRect( Rectangle(
1381 aFrameRect.Right(), aFrameRect.Top()-nShadowY,
1382 aFrameRect.Right()+nShadowX, aFrameRect.Bottom()-nShadowY ) );
1383 break;
1384 case SVX_SHADOW_BOTTOMLEFT:
1385 pDev->DrawRect( Rectangle(
1386 aFrameRect.Left()-nShadowX, aFrameRect.Bottom(),
1387 aFrameRect.Right()-nShadowX, aFrameRect.Bottom()+nShadowY ) );
1388 pDev->DrawRect( Rectangle(
1389 aFrameRect.Left()-nShadowX, aFrameRect.Top()+nShadowY,
1390 aFrameRect.Left(), aFrameRect.Bottom()+nShadowY ) );
1391 break;
1392 case SVX_SHADOW_BOTTOMRIGHT:
1393 pDev->DrawRect( Rectangle(
1394 aFrameRect.Left()+nShadowX, aFrameRect.Bottom(),
1395 aFrameRect.Right()+nShadowX, aFrameRect.Bottom()+nShadowY ) );
1396 pDev->DrawRect( Rectangle(
1397 aFrameRect.Right(), aFrameRect.Top()+nShadowY,
1398 aFrameRect.Right()+nShadowX, aFrameRect.Bottom()+nShadowY ) );
1399 break;
1400 default:
1402 // added to avoid warnings
1407 if (pBorderData)
1409 ScDocument* pBorderDoc = new ScDocument( SCDOCMODE_UNDO );
1410 pBorderDoc->InitUndo( pDoc, 0,0, TRUE,TRUE );
1411 if (pBorderData)
1412 pBorderDoc->ApplyAttr( 0,0,0, *pBorderData );
1414 ScTableInfo aTabInfo;
1415 pBorderDoc->FillInfo( aTabInfo, 0,0, 0,0, 0,
1416 nScaleX, nScaleY, FALSE, FALSE );
1417 DBG_ASSERT(aTabInfo.mnArrCount,"nArrCount == 0");
1419 aTabInfo.mpRowInfo[1].nHeight = (USHORT) nEffHeight;
1420 aTabInfo.mpRowInfo[0].pCellInfo[1].nWidth =
1421 aTabInfo.mpRowInfo[1].pCellInfo[1].nWidth = (USHORT) nEffWidth;
1423 ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pBorderDoc, 0,
1424 nScrX+nLeft, nScrY+nTop, 0,0, 0,0, nScaleX, nScaleY );
1425 aOutputData.SetUseStyleColor( bUseStyleColor );
1427 // pDev->SetMapMode(aTwipMode);
1429 if (pBorderData)
1430 aOutputData.DrawFrame();
1432 delete pBorderDoc;
1436 void ScPrintFunc::PrintColHdr( SCCOL nX1, SCCOL nX2, long nScrX, long nScrY )
1438 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab );
1439 long nLayoutSign = bLayoutRTL ? -1 : 1;
1441 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1442 long nOneX = aOnePixel.Width();
1443 long nOneY = aOnePixel.Height();
1444 SCCOL nCol;
1446 long nHeight = (long) (PRINT_HEADER_HEIGHT * nScaleY);
1447 long nEndY = nScrY + nHeight - nOneY;
1449 long nPosX = nScrX;
1450 if ( bLayoutRTL )
1452 for (nCol=nX1; nCol<=nX2; nCol++)
1453 nPosX += (long)( pDoc->GetColWidth( nCol, nPrintTab ) * nScaleX );
1455 else
1456 nPosX -= nOneX;
1457 long nPosY = nScrY - nOneY;
1458 String aText;
1460 for (nCol=nX1; nCol<=nX2; nCol++)
1462 USHORT nDocW = pDoc->GetColWidth( nCol, nPrintTab );
1463 if (nDocW)
1465 long nWidth = (long) (nDocW * nScaleX);
1466 long nEndX = nPosX + nWidth * nLayoutSign;
1468 pDev->DrawRect( Rectangle( nPosX,nPosY,nEndX,nEndY ) );
1470 aText = ::ScColToAlpha( nCol);
1471 long nTextWidth = pDev->GetTextWidth(aText);
1472 long nTextHeight = pDev->GetTextHeight();
1473 long nAddX = ( nWidth - nTextWidth ) / 2;
1474 long nAddY = ( nHeight - nTextHeight ) / 2;
1475 long nTextPosX = nPosX+nAddX;
1476 if ( bLayoutRTL )
1477 nTextPosX -= nWidth;
1478 pDev->DrawText( Point( nTextPosX,nPosY+nAddY ), aText );
1480 nPosX = nEndX;
1485 void ScPrintFunc::PrintRowHdr( SCROW nY1, SCROW nY2, long nScrX, long nScrY )
1487 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1488 long nOneX = aOnePixel.Width();
1489 long nOneY = aOnePixel.Height();
1491 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab );
1493 long nWidth = (long) (PRINT_HEADER_WIDTH * nScaleX);
1494 long nEndX = nScrX + nWidth;
1495 long nPosX = nScrX;
1496 if ( !bLayoutRTL )
1498 nEndX -= nOneX;
1499 nPosX -= nOneX;
1501 long nPosY = nScrY - nOneY;
1502 String aText;
1504 for (SCROW nRow=nY1; nRow<=nY2; nRow++)
1506 USHORT nDocH = pDoc->FastGetRowHeight( nRow, nPrintTab );
1507 if (nDocH)
1509 long nHeight = (long) (nDocH * nScaleY);
1510 long nEndY = nPosY + nHeight;
1512 pDev->DrawRect( Rectangle( nPosX,nPosY,nEndX,nEndY ) );
1514 aText = String::CreateFromInt32( nRow+1 );
1515 long nTextWidth = pDev->GetTextWidth(aText);
1516 long nTextHeight = pDev->GetTextHeight();
1517 long nAddX = ( nWidth - nTextWidth ) / 2;
1518 long nAddY = ( nHeight - nTextHeight ) / 2;
1519 pDev->DrawText( Point( nPosX+nAddX,nPosY+nAddY ), aText );
1521 nPosY = nEndY;
1526 void ScPrintFunc::LocateColHdr( SCCOL nX1, SCCOL nX2, long nScrX, long nScrY,
1527 BOOL bRepCol, ScPreviewLocationData& rLocationData )
1529 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1530 long nOneX = aOnePixel.Width();
1531 long nOneY = aOnePixel.Height();
1533 long nHeight = (long) (PRINT_HEADER_HEIGHT * nScaleY);
1534 long nEndY = nScrY + nHeight - nOneY;
1536 long nPosX = nScrX - nOneX;
1537 for (SCCOL nCol=nX1; nCol<=nX2; nCol++)
1539 USHORT nDocW = pDoc->GetColWidth( nCol, nPrintTab );
1540 if (nDocW)
1541 nPosX += (long) (nDocW * nScaleX);
1543 Rectangle aCellRect( nScrX, nScrY, nPosX, nEndY );
1544 rLocationData.AddColHeaders( aCellRect, nX1, nX2, bRepCol );
1547 void ScPrintFunc::LocateRowHdr( SCROW nY1, SCROW nY2, long nScrX, long nScrY,
1548 BOOL bRepRow, ScPreviewLocationData& rLocationData )
1550 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1551 long nOneX = aOnePixel.Width();
1552 long nOneY = aOnePixel.Height();
1554 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab );
1556 long nWidth = (long) (PRINT_HEADER_WIDTH * nScaleX);
1557 long nEndX = nScrX + nWidth;
1558 if ( !bLayoutRTL )
1559 nEndX -= nOneX;
1561 long nPosY = nScrY - nOneY;
1562 nPosY += pDoc->FastGetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY);
1563 Rectangle aCellRect( nScrX, nScrY, nEndX, nPosY );
1564 rLocationData.AddRowHeaders( aCellRect, nY1, nY2, bRepRow );
1567 void ScPrintFunc::LocateArea( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
1568 long nScrX, long nScrY, BOOL bRepCol, BOOL bRepRow,
1569 ScPreviewLocationData& rLocationData )
1571 // get MapMode for drawing objects (same MapMode as in ScOutputData::PrintDrawingLayer)
1573 Point aLogPos = OutputDevice::LogicToLogic(Point(nScrX,nScrY), aOffsetMode, aLogicMode);
1574 long nLogStX = aLogPos.X();
1575 long nLogStY = aLogPos.Y();
1577 SCCOL nCol;
1578 Point aTwipOffset;
1579 for (nCol=0; nCol<nX1; nCol++)
1580 aTwipOffset.X() -= pDoc->GetColWidth( nCol, nPrintTab );
1581 aTwipOffset.Y() -= pDoc->GetRowHeight( 0, nY1-1, nPrintTab );
1583 Point aMMOffset( aTwipOffset );
1584 aMMOffset.X() = (long)(aMMOffset.X() * HMM_PER_TWIPS);
1585 aMMOffset.Y() = (long)(aMMOffset.Y() * HMM_PER_TWIPS);
1586 aMMOffset += Point( nLogStX, nLogStY );
1587 MapMode aDrawMapMode( MAP_100TH_MM, aMMOffset, aLogicMode.GetScaleX(), aLogicMode.GetScaleY() );
1589 // get pixel rectangle
1591 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1592 long nOneX = aOnePixel.Width();
1593 long nOneY = aOnePixel.Height();
1595 long nPosX = nScrX - nOneX;
1596 for (nCol=nX1; nCol<=nX2; nCol++)
1598 USHORT nDocW = pDoc->GetColWidth( nCol, nPrintTab );
1599 if (nDocW)
1600 nPosX += (long) (nDocW * nScaleX);
1603 long nPosY = nScrY - nOneY;
1604 nPosY += pDoc->FastGetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY);
1605 Rectangle aCellRect( nScrX, nScrY, nPosX, nPosY );
1606 rLocationData.AddCellRange( aCellRect, ScRange( nX1,nY1,nPrintTab, nX2,nY2,nPrintTab ),
1607 bRepCol, bRepRow, aDrawMapMode );
1610 void ScPrintFunc::PrintArea( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
1611 long nScrX, long nScrY,
1612 BOOL bShLeft, BOOL bShTop, BOOL bShRight, BOOL bShBottom )
1614 // #i47547# nothing to do if the end of the print area is before the end of
1615 // the repeat columns/rows (don't use negative size for ScOutputData)
1616 if ( nX2 < nX1 || nY2 < nY1 )
1617 return;
1619 //! Flag bei FillInfo uebergeben !!!!!
1620 ScRange aERange;
1621 BOOL bEmbed = pDoc->IsEmbedded();
1622 if (bEmbed)
1624 pDoc->GetEmbedded(aERange);
1625 pDoc->ResetEmbedded();
1628 Point aPos = OutputDevice::LogicToLogic(Point(nScrX,nScrY), aOffsetMode, aLogicMode);
1629 long nLogStX = aPos.X();
1630 long nLogStY = aPos.Y();
1632 // Daten zusammenstellen
1634 ScTableInfo aTabInfo;
1635 pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nPrintTab,
1636 nScaleX, nScaleY, TRUE, aTableParam.bFormulas );
1637 lcl_HidePrint( aTabInfo, nX1, nX2 );
1639 if (bEmbed)
1640 pDoc->SetEmbedded(aERange);
1642 ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pDoc, nPrintTab,
1643 nScrX, nScrY, nX1, nY1, nX2, nY2, nScaleX, nScaleY );
1645 // #114135#
1646 aOutputData.SetDrawView( pDrawView );
1648 // test if all paint parts are hidden, then a paint is not necessary at all
1649 const Point aMMOffset(aOutputData.PrePrintDrawingLayer(nLogStX, nLogStY));
1650 const bool bHideAllDrawingLayer(pDrawView && pDrawView->getHideOle() && pDrawView->getHideChart() && pDrawView->getHideDraw());
1652 if(!bHideAllDrawingLayer)
1654 pDev->SetMapMode(aLogicMode);
1655 // hier kein Clipping setzen (Mapmode wird verschoben)
1657 // #i72502#
1658 aOutputData.PrintDrawingLayer(SC_LAYER_BACK, aMMOffset);
1661 pDev->SetMapMode(aOffsetMode);
1663 aOutputData.SetShowFormulas( aTableParam.bFormulas );
1664 aOutputData.SetShowNullValues( aTableParam.bNullVals );
1665 aOutputData.SetUseStyleColor( bUseStyleColor );
1667 Color aGridColor( COL_BLACK );
1668 if ( bUseStyleColor )
1669 aGridColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
1670 aOutputData.SetGridColor( aGridColor );
1672 if ( !pPrinter )
1674 OutputDevice* pRefDev = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen
1675 Fraction aPrintFrac( nZoom, 100 ); // ohne nManualZoom
1676 // MapMode, wie er beim Drucken herauskommen wuerde:
1677 pRefDev->SetMapMode( MapMode( MAP_100TH_MM, Point(), aPrintFrac, aPrintFrac ) );
1679 // when rendering (PDF), don't use printer as ref device, but printer's MapMode
1680 // has to be set anyway, as charts still use it (#106409#)
1681 if ( !bIsRender )
1682 aOutputData.SetRefDevice( pRefDev );
1685 // aOutputData.SetMetaFileMode(TRUE);
1686 if( aTableParam.bCellContent )
1687 aOutputData.DrawBackground();
1689 pDev->SetClipRegion( Rectangle( aPos, Size( aOutputData.GetScrW(), aOutputData.GetScrH() ) ) );
1690 pDev->SetClipRegion();
1692 // aOutputData.SetMetaFileMode(FALSE);
1693 if( aTableParam.bCellContent )
1695 aOutputData.DrawExtraShadow( bShLeft, bShTop, bShRight, bShBottom );
1696 aOutputData.DrawFrame();
1697 aOutputData.DrawStrings();
1699 // pDev->SetMapMode(aLogicMode);
1700 aOutputData.DrawEdit(FALSE);
1703 // pDev->SetMapMode(aOffsetMode);
1704 if (aTableParam.bGrid)
1705 aOutputData.DrawGrid( TRUE, FALSE ); // keine Seitenumbrueche
1707 /*!!!!!!!!!!! Notizen in Tabelle markieren ??????????????????????????
1709 if (aTableParam.bNotes)
1711 pDev->SetMapMode(aOffsetMode);
1712 aOutputData.PrintNoteMarks(aNotePosList);
1713 pDev->SetMapMode(aLogicMode);
1717 aOutputData.AddPDFNotes(); // has no effect if not rendering PDF with notes enabled
1719 // pDev->SetMapMode(aDrawMode);
1721 // test if all paint parts are hidden, then a paint is not necessary at all
1722 if(!bHideAllDrawingLayer)
1724 // #i72502#
1725 aOutputData.PrintDrawingLayer(SC_LAYER_FRONT, aMMOffset);
1728 // #i72502#
1729 aOutputData.PrintDrawingLayer(SC_LAYER_INTERN, aMMOffset);
1730 aOutputData.PostPrintDrawingLayer(aMMOffset); // #i74768#
1733 BOOL ScPrintFunc::IsMirror( long nPageNo ) // Raender spiegeln ?
1735 SvxPageUsage eUsage = (SvxPageUsage) ( nPageUsage & 0x000f );
1736 return ( eUsage == SVX_PAGE_MIRROR && (nPageNo & 1) );
1739 BOOL ScPrintFunc::IsLeft( long nPageNo ) // linke Fussnoten ?
1741 SvxPageUsage eUsage = (SvxPageUsage) ( nPageUsage & 0x000f );
1742 BOOL bLeft;
1743 if (eUsage == SVX_PAGE_LEFT)
1744 bLeft = TRUE;
1745 else if (eUsage == SVX_PAGE_RIGHT)
1746 bLeft = FALSE;
1747 else
1748 bLeft = (nPageNo & 1) != 0;
1749 return bLeft;
1752 void ScPrintFunc::MakeTableString()
1754 pDoc->GetName( nPrintTab, aFieldData.aTabName );
1757 void ScPrintFunc::MakeEditEngine()
1759 if (!pEditEngine)
1761 // can't use document's edit engine pool here,
1762 // because pool must have twips as default metric
1763 pEditEngine = new ScHeaderEditEngine( EditEngine::CreatePool(), TRUE );
1765 pEditEngine->EnableUndo(FALSE);
1766 pEditEngine->SetRefDevice( pDev );
1767 pEditEngine->SetWordDelimiters(
1768 ScEditUtil::ModifyDelimiters( pEditEngine->GetWordDelimiters() ) );
1769 pEditEngine->SetControlWord( pEditEngine->GetControlWord() & ~EE_CNTRL_RTFSTYLESHEETS );
1770 pEditEngine->EnableAutoColor( bUseStyleColor );
1772 // Default-Set fuer Ausrichtung
1773 pEditDefaults = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
1775 const ScPatternAttr& rPattern = (const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN);
1776 rPattern.FillEditItemSet( pEditDefaults );
1777 // FillEditItemSet adjusts font height to 1/100th mm,
1778 // but for header/footer twips is needed, as in the PatternAttr:
1779 pEditDefaults->Put( rPattern.GetItem(ATTR_FONT_HEIGHT), EE_CHAR_FONTHEIGHT );
1780 pEditDefaults->Put( rPattern.GetItem(ATTR_CJK_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CJK );
1781 pEditDefaults->Put( rPattern.GetItem(ATTR_CTL_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CTL );
1782 // #69193# dont use font color, because background color is not used
1783 //! there's no way to set the background for note pages
1784 pEditDefaults->ClearItem( EE_CHAR_COLOR );
1785 if (ScGlobal::IsSystemRTL())
1786 pEditDefaults->Put( SvxFrameDirectionItem( FRMDIR_HORI_RIGHT_TOP, EE_PARA_WRITINGDIR ) );
1789 pEditEngine->SetData( aFieldData ); // Seitennummer etc. setzen
1792 // nStartY = logic
1793 void ScPrintFunc::PrintHF( long nPageNo, BOOL bHeader, long nStartY,
1794 BOOL bDoPrint, ScPreviewLocationData* pLocationData )
1796 const ScPrintHFParam& rParam = bHeader ? aHdr : aFtr;
1798 pDev->SetMapMode( aTwipMode ); // Kopf-/Fusszeilen in Twips
1800 BOOL bLeft = IsLeft(nPageNo) && !rParam.bShared;
1801 const ScPageHFItem* pHFItem = bLeft ? rParam.pLeft : rParam.pRight;
1803 long nLineStartX = aPageRect.Left() + rParam.nLeft;
1804 long nLineEndX = aPageRect.Right() - rParam.nRight;
1805 long nLineWidth = nLineEndX - nLineStartX + 1;
1807 // Edit-Engine
1809 Point aStart( nLineStartX, nStartY );
1810 Size aPaperSize( nLineWidth, rParam.nHeight-rParam.nDistance );
1811 if ( rParam.pBorder )
1813 long nLeft = lcl_LineTotal( rParam.pBorder->GetLeft() ) + rParam.pBorder->GetDistance(BOX_LINE_LEFT);
1814 long nTop = lcl_LineTotal( rParam.pBorder->GetTop() ) + rParam.pBorder->GetDistance(BOX_LINE_TOP);
1815 aStart.X() += nLeft;
1816 aStart.Y() += nTop;
1817 aPaperSize.Width() -= nLeft + lcl_LineTotal( rParam.pBorder->GetRight() ) + rParam.pBorder->GetDistance(BOX_LINE_RIGHT);
1818 aPaperSize.Height() -= nTop + lcl_LineTotal( rParam.pBorder->GetBottom() ) + rParam.pBorder->GetDistance(BOX_LINE_BOTTOM);
1821 if ( rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE )
1823 long nLeft = rParam.pShadow->CalcShadowSpace(SHADOW_LEFT);
1824 long nTop = rParam.pShadow->CalcShadowSpace(SHADOW_TOP);
1825 aStart.X() += nLeft;
1826 aStart.Y() += nTop;
1827 aPaperSize.Width() -= nLeft + rParam.pShadow->CalcShadowSpace(SHADOW_RIGHT);
1828 aPaperSize.Height() -= nTop + rParam.pShadow->CalcShadowSpace(SHADOW_BOTTOM);
1831 aFieldData.nPageNo = nPageNo+aTableParam.nFirstPageNo;
1832 MakeEditEngine();
1834 pEditEngine->SetPaperSize(aPaperSize);
1835 const EditTextObject* pObject;
1837 // Rahmen / Hintergrund
1839 Point aBorderStart( nLineStartX, nStartY );
1840 Size aBorderSize( nLineWidth, rParam.nHeight-rParam.nDistance );
1841 if ( rParam.bDynamic )
1843 // hier nochmal anpassen, wegen geraden/ungeraden Kopf/Fusszeilen
1844 // und evtl. anderen Umbruechen durch Variablen (Seitennummer etc.)
1846 long nMaxHeight = 0;
1847 nMaxHeight = Max( nMaxHeight, TextHeight( pHFItem->GetLeftArea() ) );
1848 nMaxHeight = Max( nMaxHeight, TextHeight( pHFItem->GetCenterArea() ) );
1849 nMaxHeight = Max( nMaxHeight, TextHeight( pHFItem->GetRightArea() ) );
1850 if (rParam.pBorder)
1851 nMaxHeight += lcl_LineTotal( rParam.pBorder->GetTop() ) +
1852 lcl_LineTotal( rParam.pBorder->GetBottom() ) +
1853 rParam.pBorder->GetDistance(BOX_LINE_TOP) +
1854 rParam.pBorder->GetDistance(BOX_LINE_BOTTOM);
1855 if (rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE)
1856 nMaxHeight += rParam.pShadow->CalcShadowSpace(SHADOW_TOP) +
1857 rParam.pShadow->CalcShadowSpace(SHADOW_BOTTOM);
1859 if (nMaxHeight < rParam.nManHeight-rParam.nDistance)
1860 nMaxHeight = rParam.nManHeight-rParam.nDistance; // eingestelltes Minimum
1862 aBorderSize.Height() = nMaxHeight;
1865 if ( bDoPrint )
1867 double nOldScaleX = nScaleX;
1868 double nOldScaleY = nScaleY;
1869 nScaleX = nScaleY = 1.0; // direkt in Twips ausgeben
1870 DrawBorder( aBorderStart.X(), aBorderStart.Y(), aBorderSize.Width(), aBorderSize.Height(),
1871 rParam.pBorder, rParam.pBack, rParam.pShadow );
1872 nScaleX = nOldScaleX;
1873 nScaleY = nOldScaleY;
1875 // Clipping fuer Text
1877 pDev->SetClipRegion( Rectangle( aStart, aPaperSize ) );
1879 // links
1881 pObject = pHFItem->GetLeftArea();
1882 if (pObject)
1884 pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_LEFT, EE_PARA_JUST ) );
1885 pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, FALSE );
1886 Point aDraw = aStart;
1887 long nDif = aPaperSize.Height() - (long) pEditEngine->GetTextHeight();
1888 if (nDif > 0)
1889 aDraw.Y() += nDif / 2;
1890 pEditEngine->Draw( pDev, aDraw, 0 );
1893 // Mitte
1895 pObject = pHFItem->GetCenterArea();
1896 if (pObject)
1898 pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_CENTER, EE_PARA_JUST ) );
1899 pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, FALSE );
1900 Point aDraw = aStart;
1901 long nDif = aPaperSize.Height() - (long) pEditEngine->GetTextHeight();
1902 if (nDif > 0)
1903 aDraw.Y() += nDif / 2;
1904 pEditEngine->Draw( pDev, aDraw, 0 );
1907 // rechts
1909 pObject = pHFItem->GetRightArea();
1910 if (pObject)
1912 pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_RIGHT, EE_PARA_JUST ) );
1913 pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, FALSE );
1914 Point aDraw = aStart;
1915 long nDif = aPaperSize.Height() - (long) pEditEngine->GetTextHeight();
1916 if (nDif > 0)
1917 aDraw.Y() += nDif / 2;
1918 pEditEngine->Draw( pDev, aDraw, 0 );
1921 pDev->SetClipRegion();
1924 if ( pLocationData )
1926 Rectangle aHeaderRect( aBorderStart, aBorderSize );
1927 pLocationData->AddHeaderFooter( aHeaderRect, bHeader, bLeft );
1931 long ScPrintFunc::DoNotes( long nNoteStart, BOOL bDoPrint, ScPreviewLocationData* pLocationData )
1933 if (bDoPrint)
1934 pDev->SetMapMode(aTwipMode);
1936 MakeEditEngine();
1937 pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_LEFT, EE_PARA_JUST ) );
1938 pEditEngine->SetDefaults( *pEditDefaults );
1940 Font aMarkFont;
1941 ScAutoFontColorMode eColorMode = bUseStyleColor ? SC_AUTOCOL_DISPLAY : SC_AUTOCOL_PRINT;
1942 ((const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN)).GetFont( aMarkFont, eColorMode );
1943 //? aMarkFont.SetWeight( WEIGHT_BOLD );
1944 pDev->SetFont( aMarkFont );
1945 long nMarkLen = pDev->GetTextWidth(
1946 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("GW99999:")));
1947 // ohne Space, weil's eh selten so weit kommt
1949 Size aDataSize = aPageRect.GetSize();
1950 if ( nMarkLen > aDataSize.Width() / 2 ) // alles viel zu klein?
1951 nMarkLen = aDataSize.Width() / 2; // Seite bruederlich aufteilen
1952 aDataSize.Width() -= nMarkLen;
1954 pEditEngine->SetPaperSize( aDataSize );
1955 long nPosX = aPageRect.Left() + nMarkLen;
1956 long nPosY = aPageRect.Top();
1958 long nCount = 0;
1959 BOOL bOk;
1962 bOk = FALSE;
1963 ScAddress* pPos = (ScAddress*) aNotePosList.GetObject( nNoteStart+nCount );
1964 if (pPos)
1966 ScBaseCell* pCell = pDoc->GetCell( *pPos);
1967 if( const ScPostIt* pNote = pCell->GetNote() )
1969 if(const EditTextObject *pEditText = pNote->GetEditTextObject())
1970 pEditEngine->SetText(*pEditText);
1971 long nTextHeight = pEditEngine->GetTextHeight();
1972 if ( nPosY + nTextHeight < aPageRect.Bottom() )
1974 if (bDoPrint)
1976 pEditEngine->Draw( pDev, Point( nPosX, nPosY ), 0 );
1978 String aMarkStr;
1979 pPos->Format( aMarkStr, SCA_VALID, pDoc, pDoc->GetAddressConvention() );
1980 aMarkStr += ':';
1982 // Zellposition auch per EditEngine, damit die Position stimmt
1983 pEditEngine->SetText(aMarkStr);
1984 pEditEngine->Draw( pDev, Point( aPageRect.Left(), nPosY ), 0 );
1987 if ( pLocationData )
1989 Rectangle aTextRect( Point( nPosX, nPosY ), Size( aDataSize.Width(), nTextHeight ) );
1990 pLocationData->AddNoteText( aTextRect, *pPos );
1991 Rectangle aMarkRect( Point( aPageRect.Left(), nPosY ), Size( nMarkLen, nTextHeight ) );
1992 pLocationData->AddNoteMark( aMarkRect, *pPos );
1995 nPosY += nTextHeight;
1996 nPosY += 200; // Abstand
1997 ++nCount;
1998 bOk = TRUE;
2003 while (bOk);
2005 return nCount;
2008 long ScPrintFunc::PrintNotes( long nPageNo, long nNoteStart, BOOL bDoPrint, ScPreviewLocationData* pLocationData )
2010 if ( nNoteStart >= (long) aNotePosList.Count() || !aTableParam.bNotes )
2011 return 0;
2013 if ( bDoPrint && bClearWin )
2015 //! mit PrintPage zusammenfassen !!!
2017 Color aBackgroundColor( COL_WHITE );
2018 if ( bUseStyleColor )
2019 aBackgroundColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
2021 pDev->SetMapMode(aOffsetMode);
2022 pDev->SetLineColor();
2023 pDev->SetFillColor(aBackgroundColor);
2024 pDev->DrawRect(Rectangle(Point(),
2025 Size((long)(aPageSize.Width() * nScaleX * 100 / nZoom),
2026 (long)(aPageSize.Height() * nScaleY * 100 / nZoom))));
2030 // aPageRect auf linke / rechte Seiten anpassen
2032 Rectangle aTempRect = Rectangle( Point(), aPageSize );
2033 if (IsMirror(nPageNo))
2035 aPageRect.Left() = ( aTempRect.Left() + nRightMargin ) * 100 / nZoom;
2036 aPageRect.Right() = ( aTempRect.Right() - nLeftMargin ) * 100 / nZoom;
2038 else
2040 aPageRect.Left() = ( aTempRect.Left() + nLeftMargin ) * 100 / nZoom;
2041 aPageRect.Right() = ( aTempRect.Right() - nRightMargin ) * 100 / nZoom;
2044 if ( pPrinter && bDoPrint )
2045 pPrinter->StartPage();
2047 if ( bDoPrint || pLocationData )
2049 // Kopf- und Fusszeilen
2051 if (aHdr.bEnable)
2053 long nHeaderY = aPageRect.Top()-aHdr.nHeight;
2054 PrintHF( nPageNo, TRUE, nHeaderY, bDoPrint, pLocationData );
2056 if (aFtr.bEnable)
2058 long nFooterY = aPageRect.Bottom()+aFtr.nDistance;
2059 PrintHF( nPageNo, FALSE, nFooterY, bDoPrint, pLocationData );
2063 long nCount = DoNotes( nNoteStart, bDoPrint, pLocationData );
2065 if ( pPrinter && bDoPrint )
2066 pPrinter->EndPage();
2068 return nCount;
2071 void ScPrintFunc::PrintPage( long nPageNo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
2072 BOOL bDoPrint, ScPreviewLocationData* pLocationData )
2074 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab );
2075 long nLayoutSign = bLayoutRTL ? -1 : 1;
2077 // nPageNo is the page number within all sheets of one "start page" setting
2079 if ( bClearWin && bDoPrint )
2081 // muss genau zum Zeichnen des Rahmens in preview.cxx passen !!!
2083 Color aBackgroundColor( COL_WHITE );
2084 if ( bUseStyleColor )
2085 aBackgroundColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
2087 pDev->SetMapMode(aOffsetMode);
2088 pDev->SetLineColor();
2089 pDev->SetFillColor(aBackgroundColor);
2090 pDev->DrawRect(Rectangle(Point(),
2091 Size((long)(aPageSize.Width() * nScaleX * 100 / nZoom),
2092 (long)(aPageSize.Height() * nScaleY * 100 / nZoom))));
2096 // aPageRect auf linke / rechte Seiten anpassen
2098 Rectangle aTempRect = Rectangle( Point(), aPageSize );
2099 if (IsMirror(nPageNo))
2101 aPageRect.Left() = ( aTempRect.Left() + nRightMargin ) * 100 / nZoom;
2102 aPageRect.Right() = ( aTempRect.Right() - nLeftMargin ) * 100 / nZoom;
2104 else
2106 aPageRect.Left() = ( aTempRect.Left() + nLeftMargin ) * 100 / nZoom;
2107 aPageRect.Right() = ( aTempRect.Right() - nRightMargin ) * 100 / nZoom;
2110 if ( aAreaParam.bRepeatCol )
2111 if ( nX1 > nRepeatStartCol && nX1 <= nRepeatEndCol )
2112 nX1 = nRepeatEndCol + 1;
2113 BOOL bDoRepCol = (aAreaParam.bRepeatCol && nX1 > nRepeatEndCol);
2114 if ( aAreaParam.bRepeatRow )
2115 if ( nY1 > nRepeatStartRow && nY1 <= nRepeatEndRow )
2116 nY1 = nRepeatEndRow + 1;
2117 BOOL bDoRepRow = (aAreaParam.bRepeatRow && nY1 > nRepeatEndRow);
2119 // use new object hide flags in SdrPaintView
2120 if(pDrawView)
2122 pDrawView->setHideOle(!aTableParam.bObjects);
2123 pDrawView->setHideChart(!aTableParam.bCharts);
2124 pDrawView->setHideDraw(!aTableParam.bDrawings);
2127 if ( pPrinter && bDoPrint )
2128 pPrinter->StartPage();
2130 // Kopf- und Fusszeilen (ohne Zentrierung)
2132 if (aHdr.bEnable)
2134 long nHeaderY = aPageRect.Top()-aHdr.nHeight;
2135 PrintHF( nPageNo, TRUE, nHeaderY, bDoPrint, pLocationData );
2137 if (aFtr.bEnable)
2139 long nFooterY = aPageRect.Bottom()+aFtr.nDistance;
2140 PrintHF( nPageNo, FALSE, nFooterY, bDoPrint, pLocationData );
2143 // Position ( Raender / zentrieren )
2145 long nLeftSpace = aPageRect.Left(); // Document-Twips
2146 long nTopSpace = aPageRect.Top();
2147 if ( bCenterHor || bLayoutRTL )
2149 long nDataWidth = 0;
2150 SCCOL i;
2151 for (i=nX1; i<=nX2; i++)
2152 nDataWidth += pDoc->GetColWidth( i,nPrintTab );
2153 if (bDoRepCol)
2154 for (i=nRepeatStartCol; i<=nRepeatEndCol; i++)
2155 nDataWidth += pDoc->GetColWidth( i,nPrintTab );
2156 if (aTableParam.bHeaders)
2157 nDataWidth += (long) PRINT_HEADER_WIDTH;
2158 if (pBorderItem)
2159 nDataWidth += pBorderItem->GetDistance(BOX_LINE_LEFT) +
2160 pBorderItem->GetDistance(BOX_LINE_RIGHT); //! Line width?
2161 if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
2162 nDataWidth += pShadowItem->CalcShadowSpace(SHADOW_LEFT) +
2163 pShadowItem->CalcShadowSpace(SHADOW_RIGHT);
2164 if ( bCenterHor )
2166 nLeftSpace += ( aPageRect.GetWidth() - nDataWidth ) / 2; // LTR or RTL
2167 if (pBorderItem)
2168 nLeftSpace -= lcl_LineTotal(pBorderItem->GetLeft());
2170 else if ( bLayoutRTL )
2171 nLeftSpace += aPageRect.GetWidth() - nDataWidth; // align to the right edge of the page
2173 if ( bCenterVer )
2175 long nDataHeight = pDoc->FastGetRowHeight( nY1, nY2, nPrintTab);
2176 if (bDoRepRow)
2177 nDataHeight += pDoc->FastGetRowHeight( nRepeatStartRow,
2178 nRepeatEndRow, nPrintTab);
2179 if (aTableParam.bHeaders)
2180 nDataHeight += (long) PRINT_HEADER_HEIGHT;
2181 if (pBorderItem)
2182 nDataHeight += pBorderItem->GetDistance(BOX_LINE_TOP) +
2183 pBorderItem->GetDistance(BOX_LINE_BOTTOM); //! Line width?
2184 if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
2185 nDataHeight += pShadowItem->CalcShadowSpace(SHADOW_TOP) +
2186 pShadowItem->CalcShadowSpace(SHADOW_BOTTOM);
2187 nTopSpace += ( aPageRect.GetHeight() - nDataHeight ) / 2;
2188 if (pBorderItem)
2189 nTopSpace -= lcl_LineTotal(pBorderItem->GetTop());
2192 // calculate sizes of the elements for partitioning
2193 // (header, repeat, data)
2195 long nHeaderWidth = 0;
2196 long nHeaderHeight = 0;
2197 long nRepeatWidth = 0;
2198 long nRepeatHeight = 0;
2199 long nContentWidth = 0; // scaled - not the same as nDataWidth above
2200 long nContentHeight = 0;
2201 if (aTableParam.bHeaders)
2203 nHeaderWidth = (long) (PRINT_HEADER_WIDTH * nScaleX);
2204 nHeaderHeight = (long) (PRINT_HEADER_HEIGHT * nScaleY);
2206 if (bDoRepCol)
2207 for (SCCOL i=nRepeatStartCol; i<=nRepeatEndCol; i++)
2208 nRepeatWidth += (long) (pDoc->GetColWidth(i,nPrintTab) * nScaleX);
2209 if (bDoRepRow)
2210 nRepeatHeight += pDoc->FastGetScaledRowHeight( nRepeatStartRow,
2211 nRepeatEndRow, nPrintTab, nScaleY);
2212 for (SCCOL i=nX1; i<=nX2; i++)
2213 nContentWidth += (long) (pDoc->GetColWidth(i,nPrintTab) * nScaleX);
2214 nContentHeight += pDoc->FastGetScaledRowHeight( nY1, nY2, nPrintTab,
2215 nScaleY);
2217 // partition the page
2219 long nStartX = ((long) ( nLeftSpace * nScaleX ));
2220 long nStartY = ((long) ( nTopSpace * nScaleY ));
2221 // nStartX -= aOffset.X(); // schon im MapMode
2222 // nStartY -= aOffset.Y();
2224 long nInnerStartX = nStartX;
2225 long nInnerStartY = nStartY;
2226 if (pBorderItem)
2228 nInnerStartX += (long) ( ( lcl_LineTotal(pBorderItem->GetLeft()) +
2229 pBorderItem->GetDistance(BOX_LINE_LEFT) ) * nScaleX );
2230 nInnerStartY += (long) ( ( lcl_LineTotal(pBorderItem->GetTop()) +
2231 pBorderItem->GetDistance(BOX_LINE_TOP) ) * nScaleY );
2233 if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
2235 nInnerStartX += (long) ( pShadowItem->CalcShadowSpace(SHADOW_LEFT) * nScaleX );
2236 nInnerStartY += (long) ( pShadowItem->CalcShadowSpace(SHADOW_TOP) * nScaleY );
2239 if ( bLayoutRTL )
2241 // arrange elements starting from the right edge
2242 nInnerStartX += nHeaderWidth + nRepeatWidth + nContentWidth;
2244 // make rounding easier so the elements are really next to each other in preview
2245 Size aOffsetOnePixel = pDev->PixelToLogic( Size(1,1), aOffsetMode );
2246 long nOffsetOneX = aOffsetOnePixel.Width();
2247 nInnerStartX += nOffsetOneX / 2;
2250 long nFrameStartX = nInnerStartX;
2251 long nFrameStartY = nInnerStartY;
2253 long nRepStartX = nInnerStartX + nHeaderWidth * nLayoutSign; // widths/heights are 0 if not used
2254 long nRepStartY = nInnerStartY + nHeaderHeight;
2255 long nDataX = nRepStartX + nRepeatWidth * nLayoutSign;
2256 long nDataY = nRepStartY + nRepeatHeight;
2257 long nEndX = nDataX + nContentWidth * nLayoutSign;
2258 long nEndY = nDataY + nContentHeight;
2259 long nFrameEndX = nEndX;
2260 long nFrameEndY = nEndY;
2262 if ( bLayoutRTL )
2264 // each element's start position is its left edge
2265 //! subtract one pixel less?
2266 nInnerStartX -= nHeaderWidth; // used for header
2267 nRepStartX -= nRepeatWidth;
2268 nDataX -= nContentWidth;
2270 // continue right of the main elements again
2271 nEndX += nHeaderWidth + nRepeatWidth + nContentWidth;
2274 // Seiten-Rahmen / Hintergrund
2276 //! nEndX/Y anpassen
2278 long nBorderEndX = nEndX;
2279 long nBorderEndY = nEndY;
2280 if (pBorderItem)
2282 nBorderEndX += (long) ( ( lcl_LineTotal(pBorderItem->GetRight()) +
2283 pBorderItem->GetDistance(BOX_LINE_RIGHT) ) * nScaleX );
2284 nBorderEndY += (long) ( ( lcl_LineTotal(pBorderItem->GetBottom()) +
2285 pBorderItem->GetDistance(BOX_LINE_BOTTOM) ) * nScaleY );
2287 if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
2289 nBorderEndX += (long) ( pShadowItem->CalcShadowSpace(SHADOW_RIGHT) * nScaleX );
2290 nBorderEndY += (long) ( pShadowItem->CalcShadowSpace(SHADOW_BOTTOM) * nScaleY );
2293 if ( bDoPrint )
2295 pDev->SetMapMode( aOffsetMode );
2296 DrawBorder( nStartX, nStartY, nBorderEndX-nStartX, nBorderEndY-nStartY,
2297 pBorderItem, pBackgroundItem, pShadowItem );
2299 pDev->SetMapMode( aTwipMode );
2302 pDev->SetMapMode( aOffsetMode );
2304 // Wiederholungszeilen/Spalten ausgeben
2306 if (bDoRepCol && bDoRepRow)
2308 if ( bDoPrint )
2309 PrintArea( nRepeatStartCol,nRepeatStartRow, nRepeatEndCol,nRepeatEndRow,
2310 nRepStartX,nRepStartY, TRUE,TRUE,FALSE,FALSE );
2311 if ( pLocationData )
2312 LocateArea( nRepeatStartCol,nRepeatStartRow, nRepeatEndCol,nRepeatEndRow,
2313 nRepStartX,nRepStartY, TRUE,TRUE, *pLocationData );
2315 if (bDoRepCol)
2317 if ( bDoPrint )
2318 PrintArea( nRepeatStartCol,nY1, nRepeatEndCol,nY2, nRepStartX,nDataY,
2319 TRUE,!bDoRepRow,FALSE,TRUE );
2320 if ( pLocationData )
2321 LocateArea( nRepeatStartCol,nY1, nRepeatEndCol,nY2, nRepStartX,nDataY, TRUE,FALSE, *pLocationData );
2323 if (bDoRepRow)
2325 if ( bDoPrint )
2326 PrintArea( nX1,nRepeatStartRow, nX2,nRepeatEndRow, nDataX,nRepStartY,
2327 !bDoRepCol,TRUE,TRUE,FALSE );
2328 if ( pLocationData )
2329 LocateArea( nX1,nRepeatStartRow, nX2,nRepeatEndRow, nDataX,nRepStartY, FALSE,TRUE, *pLocationData );
2332 // Daten ausgeben
2334 if ( bDoPrint )
2335 PrintArea( nX1,nY1, nX2,nY2, nDataX,nDataY, !bDoRepCol,!bDoRepRow,TRUE,TRUE );
2336 if ( pLocationData )
2337 LocateArea( nX1,nY1, nX2,nY2, nDataX,nDataY, FALSE,FALSE, *pLocationData );
2339 // Spalten-/Zeilenkoepfe ausgeben
2340 // nach den Daten (ueber evtl. weitergezeichneten Schatten)
2342 Color aGridColor( COL_BLACK );
2343 if ( bUseStyleColor )
2344 aGridColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
2346 if (aTableParam.bHeaders)
2348 if ( bDoPrint )
2350 pDev->SetLineColor( aGridColor );
2351 pDev->SetFillColor();
2352 pDev->SetMapMode(aOffsetMode);
2355 ScPatternAttr aPattern( pDoc->GetPool() );
2356 Font aFont;
2357 ScAutoFontColorMode eColorMode = bUseStyleColor ? SC_AUTOCOL_DISPLAY : SC_AUTOCOL_PRINT;
2358 aPattern.GetFont( aFont, eColorMode, pDev );
2359 pDev->SetFont( aFont );
2361 if (bDoRepCol)
2363 if ( bDoPrint )
2364 PrintColHdr( nRepeatStartCol,nRepeatEndCol, nRepStartX,nInnerStartY );
2365 if ( pLocationData )
2366 LocateColHdr( nRepeatStartCol,nRepeatEndCol, nRepStartX,nInnerStartY, TRUE, *pLocationData );
2368 if ( bDoPrint )
2369 PrintColHdr( nX1,nX2, nDataX,nInnerStartY );
2370 if ( pLocationData )
2371 LocateColHdr( nX1,nX2, nDataX,nInnerStartY, FALSE, *pLocationData );
2372 if (bDoRepRow)
2374 if ( bDoPrint )
2375 PrintRowHdr( nRepeatStartRow,nRepeatEndRow, nInnerStartX,nRepStartY );
2376 if ( pLocationData )
2377 LocateRowHdr( nRepeatStartRow,nRepeatEndRow, nInnerStartX,nRepStartY, TRUE, *pLocationData );
2379 if ( bDoPrint )
2380 PrintRowHdr( nY1,nY2, nInnerStartX,nDataY );
2381 if ( pLocationData )
2382 LocateRowHdr( nY1,nY2, nInnerStartX,nDataY, FALSE, *pLocationData );
2385 // einfacher Rahmen
2387 if ( bDoPrint && ( aTableParam.bGrid || aTableParam.bHeaders ) )
2389 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
2390 long nOneX = aOnePixel.Width();
2391 long nOneY = aOnePixel.Height();
2393 long nLeftX = nFrameStartX;
2394 long nTopY = nFrameStartY - nOneY;
2395 long nRightX = nFrameEndX;
2396 long nBottomY = nFrameEndY - nOneY;
2397 if ( !bLayoutRTL )
2399 nLeftX -= nOneX;
2400 nRightX -= nOneX;
2402 pDev->SetMapMode(aOffsetMode);
2403 pDev->SetLineColor( aGridColor );
2404 pDev->SetFillColor();
2405 pDev->DrawRect( Rectangle( nLeftX, nTopY, nRightX, nBottomY ) );
2406 // nEndX/Y ohne Rahmen-Anpassung
2409 if ( pPrinter && bDoPrint )
2410 pPrinter->EndPage();
2412 aLastSourceRange = ScRange( nX1, nY1, nPrintTab, nX2, nY2, nPrintTab );
2413 bSourceRangeValid = TRUE;
2416 void ScPrintFunc::SetOffset( const Point& rOfs )
2418 aSrcOffset = rOfs;
2421 void ScPrintFunc::SetManualZoom( USHORT nNewZoom )
2423 nManualZoom = nNewZoom;
2426 void ScPrintFunc::SetClearFlag( BOOL bFlag )
2428 bClearWin = bFlag;
2431 void ScPrintFunc::SetUseStyleColor( BOOL bFlag )
2433 bUseStyleColor = bFlag;
2434 if (pEditEngine)
2435 pEditEngine->EnableAutoColor( bUseStyleColor );
2438 void ScPrintFunc::SetRenderFlag( BOOL bFlag )
2440 bIsRender = bFlag; // set when using XRenderable (PDF)
2443 void ScPrintFunc::SetExclusivelyDrawOleAndDrawObjects()
2445 aTableParam.bCellContent = false;
2446 aTableParam.bNotes = false;
2447 aTableParam.bGrid = false;
2448 aTableParam.bHeaders = false;
2449 aTableParam.bFormulas = false;;
2450 aTableParam.bNullVals = false;;
2451 aTableParam.bNullVals = false;;
2455 // UpdatePages wird nur von aussen gerufen, um die Umbrueche fuer die Anzeige
2456 // richtig zu setzen - immer ohne UserArea
2459 BOOL ScPrintFunc::UpdatePages()
2461 if (!pParamSet)
2462 return FALSE;
2464 // Zoom
2466 nZoom = 100;
2467 if (aTableParam.bScalePageNum || aTableParam.bScaleTo)
2468 nZoom = ZOOM_MIN; // stimmt fuer Umbrueche
2469 else if (aTableParam.bScaleAll)
2471 nZoom = aTableParam.nScaleAll;
2472 if ( nZoom <= ZOOM_MIN )
2473 nZoom = ZOOM_MIN;
2476 String aName = pDoc->GetPageStyle( nPrintTab );
2477 SCTAB nTabCount = pDoc->GetTableCount();
2478 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
2479 if ( nTab==nPrintTab || pDoc->GetPageStyle(nTab)==aName )
2481 // Wiederholungszeilen / Spalten
2482 pDoc->SetRepeatArea( nTab, nRepeatStartCol,nRepeatEndCol, nRepeatStartRow,nRepeatEndRow );
2484 // Umbrueche setzen
2485 ResetBreaks(nTab);
2486 pDocShell->PostPaint(0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID);
2489 return TRUE;
2492 long ScPrintFunc::CountPages() // setzt auch nPagesX, nPagesY
2494 BOOL bAreaOk = FALSE;
2496 if (pDoc->HasTable( nPrintTab ))
2498 if (aAreaParam.bPrintArea) // Druckbereich angegeben?
2500 if ( bPrintCurrentTable )
2502 ScRange& rRange = aAreaParam.aPrintArea;
2504 // hier kein Vergleich der Tabellen mehr, die Area gilt immer fuer diese Tabelle
2505 // wenn hier verglichen werden soll, muss die Tabelle der Druckbereiche beim
2506 // Einfuegen von Tabellen etc. angepasst werden !
2508 nStartCol = rRange.aStart.Col();
2509 nStartRow = rRange.aStart.Row();
2510 nEndCol = rRange.aEnd .Col();
2511 nEndRow = rRange.aEnd .Row();
2512 bAreaOk = AdjustPrintArea(FALSE); // begrenzen
2514 else
2515 bAreaOk = FALSE;
2517 else // aus Dokument suchen
2518 bAreaOk = AdjustPrintArea(TRUE);
2521 if (bAreaOk)
2523 long nPages = 0;
2524 size_t nY;
2525 if (bMultiArea)
2527 USHORT nRCount = pDoc->GetPrintRangeCount( nPrintTab );
2528 for (USHORT i=0; i<nRCount; i++)
2530 CalcZoom(i);
2531 if ( aTableParam.bSkipEmpty )
2532 for (nY=0; nY<nPagesY; nY++)
2533 nPages += pPageRows[nY].CountVisible();
2534 else
2535 nPages += ((long) nPagesX) * nPagesY;
2536 if ( pPageData )
2537 FillPageData();
2540 else
2542 CalcZoom(RANGENO_NORANGE); // Zoom berechnen
2543 if ( aTableParam.bSkipEmpty )
2544 for (nY=0; nY<nPagesY; nY++)
2545 nPages += pPageRows[nY].CountVisible();
2546 else
2547 nPages += ((long) nPagesX) * nPagesY;
2548 if ( pPageData )
2549 FillPageData();
2551 return nPages;
2553 else
2555 // nZoom = 100; // nZoom auf letztem Wert stehenlassen !!!
2556 nPagesX = nPagesY = nTotalY = 0;
2557 return 0;
2561 long ScPrintFunc::CountNotePages()
2563 if ( !aTableParam.bNotes || !bPrintCurrentTable )
2564 return 0;
2566 long nCount=0;
2567 SCCOL nCol;
2568 SCROW nRow;
2570 BOOL bError = FALSE;
2571 if (!aAreaParam.bPrintArea)
2572 bError = !AdjustPrintArea(TRUE); // komplett aus Dok suchen
2574 USHORT nRepeats = 1; // wie oft durchgehen ?
2575 if (bMultiArea)
2576 nRepeats = pDoc->GetPrintRangeCount(nPrintTab);
2577 if (bError)
2578 nRepeats = 0;
2580 for (USHORT nStep=0; nStep<nRepeats; nStep++)
2582 BOOL bDoThis = TRUE;
2583 if (bMultiArea) // alle Areas durchgehen
2585 const ScRange* pThisRange = pDoc->GetPrintRange( nPrintTab, nStep );
2586 if ( pThisRange )
2588 nStartCol = pThisRange->aStart.Col();
2589 nStartRow = pThisRange->aStart.Row();
2590 nEndCol = pThisRange->aEnd .Col();
2591 nEndRow = pThisRange->aEnd .Row();
2592 bDoThis = AdjustPrintArea(FALSE);
2596 if (bDoThis)
2598 ScHorizontalCellIterator aIter( pDoc, nPrintTab, nStartCol,nStartRow, nEndCol,nEndRow );
2599 ScBaseCell* pCell = aIter.GetNext( nCol, nRow );
2600 while (pCell)
2602 if (pCell->HasNote())
2604 aNotePosList.Insert( new ScAddress( nCol,nRow,nPrintTab ), LIST_APPEND );
2605 ++nCount;
2608 pCell = aIter.GetNext( nCol, nRow );
2613 long nPages = 0;
2614 long nNoteNr = 0;
2615 long nNoteAdd;
2618 nNoteAdd = PrintNotes( nPages, nNoteNr, FALSE, NULL );
2619 if (nNoteAdd)
2621 nNoteNr += nNoteAdd;
2622 ++nPages;
2625 while (nNoteAdd);
2627 return nPages;
2630 void ScPrintFunc::InitModes() // aus nZoom etc. die MapModes setzen
2632 aOffset = Point( aSrcOffset.X()*100/nZoom, aSrcOffset.Y()*100/nZoom );
2634 long nEffZoom = nZoom * (long) nManualZoom;
2636 // nScaleX = nScaleY = 1.0; // Ausgabe in Twips
2637 nScaleX = nScaleY = HMM_PER_TWIPS; // Ausgabe in 1/100 mm
2639 Fraction aZoomFract( nEffZoom,10000 );
2640 Fraction aHorFract = aZoomFract;
2642 if ( !pPrinter && !bIsRender ) // adjust scale for preview
2644 double nFact = pDocShell->GetOutputFactor();
2645 aHorFract = Fraction( (long)( nEffZoom / nFact ), 10000 );
2648 aLogicMode = MapMode( MAP_100TH_MM, Point(), aHorFract, aZoomFract );
2650 Point aLogicOfs( -aOffset.X(), -aOffset.Y() );
2651 aOffsetMode = MapMode( MAP_100TH_MM, aLogicOfs, aHorFract, aZoomFract );
2653 Point aTwipsOfs( (long) ( -aOffset.X() / nScaleX + 0.5 ), (long) ( -aOffset.Y() / nScaleY + 0.5 ) );
2654 aTwipMode = MapMode( MAP_TWIP, aTwipsOfs, aHorFract, aZoomFract );
2657 //--------------------------------------------------------------------
2659 void ScPrintFunc::ApplyPrintSettings()
2661 if ( pPrinter )
2664 // Printer zum Drucken umstellen
2667 Size aEnumSize = aPageSize;
2670 pPrinter->SetOrientation( bLandscape ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT );
2671 if ( bLandscape )
2673 // landscape is always interpreted as a rotation by 90 degrees !
2674 // this leads to non WYSIWIG but at least it prints!
2675 // #i21775#
2676 long nTemp = aEnumSize.Width();
2677 aEnumSize.Width() = aEnumSize.Height();
2678 aEnumSize.Height() = nTemp;
2680 Paper ePaper = SvxPaperInfo::GetSvPaper( aEnumSize, MAP_TWIP, TRUE );
2681 USHORT nPaperBin = ((const SvxPaperBinItem&)pParamSet->Get(ATTR_PAGE_PAPERBIN)).GetValue();
2683 pPrinter->SetPaper( ePaper );
2684 if ( PAPER_USER == ePaper )
2686 MapMode aPrinterMode = pPrinter->GetMapMode();
2687 MapMode aLocalMode( MAP_TWIP );
2688 pPrinter->SetMapMode( aLocalMode );
2689 pPrinter->SetPaperSizeUser( aEnumSize );
2690 pPrinter->SetMapMode( aPrinterMode );
2693 pPrinter->SetPaperBin( nPaperBin );
2697 //--------------------------------------------------------------------
2698 // rPageRanges = Range fuer alle Tabellen
2699 // nStartPage = in rPageRanges beginnen bei nStartPage
2700 // nDisplayStart = lfd. Nummer fuer Anzeige der Seitennummer
2702 long ScPrintFunc::DoPrint( const MultiSelection& rPageRanges,
2703 long nStartPage, long nDisplayStart, BOOL bDoPrint,
2704 SfxProgress* pProgress, ScPreviewLocationData* pLocationData )
2706 DBG_ASSERT(pDev,"Device == NULL");
2707 if (!pParamSet)
2708 return 0;
2710 if ( pPrinter && bDoPrint )
2711 ApplyPrintSettings();
2713 //--------------------------------------------------------------------
2715 InitModes();
2716 if ( pLocationData )
2718 pLocationData->SetCellMapMode( aOffsetMode );
2719 pLocationData->SetPrintTab( nPrintTab );
2722 MakeTableString();
2724 if ( pProgress )
2725 pProgress->SetText( String( ScResId( SCSTR_STAT_PRINT ) ) );
2727 //--------------------------------------------------------------------
2729 long nPageNo = 0;
2730 long nPrinted = 0;
2731 long nEndPage = rPageRanges.GetTotalRange().Max();
2733 USHORT nRepeats = 1; // wie oft durchgehen ?
2734 if (bMultiArea)
2735 nRepeats = pDoc->GetPrintRangeCount(nPrintTab);
2736 for (USHORT nStep=0; nStep<nRepeats; nStep++)
2738 if (bMultiArea) // Bereich neu belegen ?
2740 CalcZoom(nStep); // setzt auch nStartCol etc. neu
2741 InitModes();
2744 SCCOL nX1;
2745 SCROW nY1;
2746 SCCOL nX2;
2747 SCROW nY2;
2748 size_t nCountX;
2749 size_t nCountY;
2751 if (aTableParam.bTopDown) // von oben nach unten
2753 nX1 = nStartCol;
2754 for (nCountX=0; nCountX<nPagesX; nCountX++)
2756 nX2 = pPageEndX[nCountX];
2757 for (nCountY=0; nCountY<nPagesY; nCountY++)
2759 nY1 = pPageRows[nCountY].GetStartRow();
2760 nY2 = pPageRows[nCountY].GetEndRow();
2761 if ( !aTableParam.bSkipEmpty || !pPageRows[nCountY].IsHidden(nCountX) )
2763 if ( rPageRanges.IsSelected( nPageNo+nStartPage+1 ) )
2765 PrintPage( nPageNo+nDisplayStart, nX1, nY1, nX2, nY2,
2766 bDoPrint, pLocationData );
2768 if ( pProgress )
2770 pProgress->SetState( nPageNo+nStartPage+1, nEndPage );
2771 pProgress->Reschedule(); //Mag der Anwender noch oder hat er genug?
2773 ++nPrinted;
2775 ++nPageNo;
2778 nX1 = nX2 + 1;
2781 else // von links nach rechts
2783 for (nCountY=0; nCountY<nPagesY; nCountY++)
2785 nY1 = pPageRows[nCountY].GetStartRow();
2786 nY2 = pPageRows[nCountY].GetEndRow();
2787 nX1 = nStartCol;
2788 for (nCountX=0; nCountX<nPagesX; nCountX++)
2790 nX2 = pPageEndX[nCountX];
2791 if ( !aTableParam.bSkipEmpty || !pPageRows[nCountY].IsHidden(nCountX) )
2793 if ( rPageRanges.IsSelected( nPageNo+nStartPage+1 ) )
2795 PrintPage( nPageNo+nDisplayStart, nX1, nY1, nX2, nY2,
2796 bDoPrint, pLocationData );
2798 if ( pProgress )
2800 pProgress->SetState( nPageNo+nStartPage+1, nEndPage );
2801 pProgress->Reschedule(); //Mag der Anwender noch oder hat er genug?
2803 ++nPrinted;
2805 ++nPageNo;
2807 nX1 = nX2 + 1;
2813 aFieldData.aTabName = ScGlobal::GetRscString( STR_NOTES );
2815 long nNoteNr = 0;
2816 long nNoteAdd;
2819 if ( nPageNo+nStartPage <= nEndPage )
2821 BOOL bPageSelected = rPageRanges.IsSelected( nPageNo+nStartPage+1 );
2822 nNoteAdd = PrintNotes( nPageNo+nStartPage, nNoteNr, bDoPrint && bPageSelected,
2823 ( bPageSelected ? pLocationData : NULL ) );
2824 if ( nNoteAdd )
2826 nNoteNr += nNoteAdd;
2827 if ( pProgress && bPageSelected )
2829 pProgress->SetState( nPageNo+nStartPage+1, nEndPage );
2830 pProgress->Reschedule(); //Mag der Anwender noch oder hat er genug?
2832 if (bPageSelected)
2834 ++nPrinted;
2835 bSourceRangeValid = FALSE; // last page was no cell range
2837 ++nPageNo;
2840 else
2841 nNoteAdd = 0;
2843 while (nNoteAdd);
2845 if ( bMultiArea )
2846 ResetBreaks(nPrintTab); // Breaks fuer Anzeige richtig
2848 return nPrinted;
2851 void ScPrintFunc::CalcZoom( USHORT nRangeNo ) // Zoom berechnen
2853 USHORT nRCount = pDoc->GetPrintRangeCount( nPrintTab );
2854 const ScRange* pThisRange = NULL;
2855 if ( nRangeNo != RANGENO_NORANGE || nRangeNo < nRCount )
2856 pThisRange = pDoc->GetPrintRange( nPrintTab, nRangeNo );
2857 if ( pThisRange )
2859 nStartCol = pThisRange->aStart.Col();
2860 nStartRow = pThisRange->aStart.Row();
2861 nEndCol = pThisRange->aEnd .Col();
2862 nEndRow = pThisRange->aEnd .Row();
2865 if (!AdjustPrintArea(FALSE)) // leer
2867 nZoom = 100;
2868 nPagesX = nPagesY = nTotalY = 0;
2869 return;
2872 pDoc->SetRepeatArea( nPrintTab, nRepeatStartCol,nRepeatEndCol, nRepeatStartRow,nRepeatEndRow );
2874 if (aTableParam.bScalePageNum)
2876 nZoom = 100;
2877 USHORT nPagesToFit = aTableParam.nScalePageNum;
2879 sal_uInt16 nLastFitZoom = 0, nLastNonFitZoom = 0;
2880 while (true)
2882 if (nZoom <= ZOOM_MIN)
2883 break;
2885 CalcPages();
2886 bool bFitsPage = (nPagesX * nPagesY <= nPagesToFit);
2888 if (bFitsPage)
2890 if (nZoom == 100)
2891 // If it fits at 100 %, it's good enough for me.
2892 break;
2894 nLastFitZoom = nZoom;
2895 nZoom = (nLastNonFitZoom + nZoom) / 2;
2897 if (nLastFitZoom == nZoom)
2898 // It converged. Use this zoom level.
2899 break;
2901 else
2903 if (nZoom - nLastFitZoom <= 1)
2905 nZoom = nLastFitZoom;
2906 CalcPages();
2907 break;
2910 nLastNonFitZoom = nZoom;
2911 nZoom = (nLastFitZoom + nZoom) / 2;
2915 else if (aTableParam.bScaleTo)
2917 nZoom = 100;
2918 USHORT nW = aTableParam.nScaleWidth;
2919 USHORT nH = aTableParam.nScaleHeight;
2921 sal_uInt16 nLastFitZoom = 0, nLastNonFitZoom = 0;
2922 while (true)
2924 if (nZoom <= ZOOM_MIN)
2925 break;
2927 CalcPages();
2928 bool bFitsPage = ((!nW || (nPagesX <= nW)) && (!nH || (nPagesY <= nH)));
2930 if (bFitsPage)
2932 if (nZoom == 100)
2933 // If it fits at 100 %, it's good enough for me.
2934 break;
2936 nLastFitZoom = nZoom;
2937 nZoom = (nLastNonFitZoom + nZoom) / 2;
2939 if (nLastFitZoom == nZoom)
2940 // It converged. Use this zoom level.
2941 break;
2943 else
2945 if (nZoom - nLastFitZoom <= 1)
2947 nZoom = nLastFitZoom;
2948 CalcPages();
2949 break;
2952 nLastNonFitZoom = nZoom;
2953 nZoom = (nLastFitZoom + nZoom) / 2;
2957 else if (aTableParam.bScaleAll)
2959 nZoom = aTableParam.nScaleAll;
2960 if ( nZoom <= ZOOM_MIN )
2961 nZoom = ZOOM_MIN;
2962 CalcPages();
2964 else
2966 DBG_ASSERT( aTableParam.bScaleNone, "kein Scale-Flag gesetzt" );
2967 nZoom = 100;
2968 CalcPages();
2972 Size ScPrintFunc::GetDocPageSize()
2974 // Hoehe Kopf-/Fusszeile anpassen
2976 InitModes(); // aTwipMode aus nZoom initialisieren
2977 pDev->SetMapMode( aTwipMode ); // Kopf-/Fusszeilen in Twips
2978 UpdateHFHeight( aHdr );
2979 UpdateHFHeight( aFtr );
2981 // Seitengroesse in Document-Twips
2982 // Berechnung Left / Right auch in PrintPage
2984 aPageRect = Rectangle( Point(), aPageSize );
2985 aPageRect.Left() = ( aPageRect.Left() + nLeftMargin ) * 100 / nZoom;
2986 aPageRect.Right() = ( aPageRect.Right() - nRightMargin ) * 100 / nZoom;
2987 aPageRect.Top() = ( aPageRect.Top() + nTopMargin ) * 100 / nZoom + aHdr.nHeight;
2988 aPageRect.Bottom() = ( aPageRect.Bottom() - nBottomMargin ) * 100 / nZoom - aFtr.nHeight;
2990 Size aDocPageSize = aPageRect.GetSize();
2991 if (aTableParam.bHeaders)
2993 aDocPageSize.Width() -= (long) PRINT_HEADER_WIDTH;
2994 aDocPageSize.Height() -= (long) PRINT_HEADER_HEIGHT;
2996 if (pBorderItem)
2998 aDocPageSize.Width() -= lcl_LineTotal(pBorderItem->GetLeft()) +
2999 lcl_LineTotal(pBorderItem->GetRight()) +
3000 pBorderItem->GetDistance(BOX_LINE_LEFT) +
3001 pBorderItem->GetDistance(BOX_LINE_RIGHT);
3002 aDocPageSize.Height() -= lcl_LineTotal(pBorderItem->GetTop()) +
3003 lcl_LineTotal(pBorderItem->GetBottom()) +
3004 pBorderItem->GetDistance(BOX_LINE_TOP) +
3005 pBorderItem->GetDistance(BOX_LINE_BOTTOM);
3007 if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
3009 aDocPageSize.Width() -= pShadowItem->CalcShadowSpace(SHADOW_LEFT) +
3010 pShadowItem->CalcShadowSpace(SHADOW_RIGHT);
3011 aDocPageSize.Height() -= pShadowItem->CalcShadowSpace(SHADOW_TOP) +
3012 pShadowItem->CalcShadowSpace(SHADOW_BOTTOM);
3014 return aDocPageSize;
3017 void ScPrintFunc::ResetBreaks( SCTAB nTab ) // Breaks fuer Anzeige richtig setzen
3019 pDoc->SetPageSize( nTab, GetDocPageSize() );
3020 pDoc->UpdatePageBreaks( nTab, NULL );
3023 void lcl_SetHidden( ScDocument* pDoc, SCTAB nPrintTab, ScPageRowEntry& rPageRowEntry,
3024 SCCOL nStartCol, const SCCOL* pPageEndX )
3026 size_t nPagesX = rPageRowEntry.GetPagesX();
3027 SCROW nStartRow = rPageRowEntry.GetStartRow();
3028 SCROW nEndRow = rPageRowEntry.GetEndRow();
3030 BOOL bLeftIsEmpty = FALSE;
3031 ScRange aTempRange;
3032 Rectangle aTempRect = pDoc->GetMMRect( 0,0, 0,0, 0 );
3034 for (size_t i=0; i<nPagesX; i++)
3036 SCCOL nEndCol = pPageEndX[i];
3037 if ( pDoc->IsPrintEmpty( nPrintTab, nStartCol, nStartRow, nEndCol, nEndRow,
3038 bLeftIsEmpty, &aTempRange, &aTempRect ) )
3040 rPageRowEntry.SetHidden(i);
3041 bLeftIsEmpty = TRUE;
3043 else
3044 bLeftIsEmpty = FALSE;
3046 nStartCol = nEndCol+1;
3050 void ScPrintFunc::CalcPages() // berechnet aPageRect und Seiten aus nZoom
3052 if (!pPageEndX) pPageEndX = new SCCOL[MAXCOL+1];
3053 if (!pPageEndY) pPageEndY = new SCROW[MAXROW+1];
3054 if (!pPageRows) pPageRows = new ScPageRowEntry[MAXROW+1]; //! vorher zaehlen !!!!
3056 pDoc->SetPageSize( nPrintTab, GetDocPageSize() );
3057 if (aAreaParam.bPrintArea)
3059 ScRange aRange( nStartCol, nStartRow, nPrintTab, nEndCol, nEndRow, nPrintTab );
3060 pDoc->UpdatePageBreaks( nPrintTab, &aRange );
3062 else
3063 pDoc->UpdatePageBreaks( nPrintTab, NULL ); // sonst wird das Ende markiert
3066 // Seiteneinteilung nach Umbruechen in Col/RowFlags
3067 // Von mehreren Umbruechen in einem ausgeblendeten Bereich zaehlt nur einer.
3070 nPagesX = 0;
3071 nPagesY = 0;
3072 nTotalY = 0;
3074 BOOL bVisCol = FALSE;
3075 SCCOL nLastCol = -1;
3076 for (SCCOL i=nStartCol; i<=nEndCol; i++)
3078 bool bHidden = pDoc->ColHidden(i, nPrintTab, nLastCol);
3079 bool bPageBreak = (pDoc->HasColBreak(i, nPrintTab) & BREAK_PAGE);
3080 if ( i>nStartCol && bVisCol && bPageBreak )
3082 pPageEndX[nPagesX] = i-1;
3083 ++nPagesX;
3084 bVisCol = FALSE;
3086 if (!bHidden)
3087 bVisCol = TRUE;
3089 if (bVisCol) // auch am Ende keine leeren Seiten
3091 pPageEndX[nPagesX] = nEndCol;
3092 ++nPagesX;
3095 BOOL bVisRow = FALSE;
3096 SCROW nPageStartRow = nStartRow;
3097 for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
3099 bool bPageBreak = (pDoc->HasRowBreak(nRow, nPrintTab) & BREAK_PAGE);
3100 if (nRow > nStartRow && bVisRow && bPageBreak )
3102 pPageEndY[nTotalY] = nRow-1;
3103 ++nTotalY;
3105 if ( !aTableParam.bSkipEmpty ||
3106 !pDoc->IsPrintEmpty( nPrintTab, nStartCol, nPageStartRow, nEndCol, nRow-1 ) )
3108 pPageRows[nPagesY].SetStartRow( nPageStartRow );
3109 pPageRows[nPagesY].SetEndRow( nRow-1 );
3110 pPageRows[nPagesY].SetPagesX( nPagesX );
3111 if (aTableParam.bSkipEmpty)
3112 lcl_SetHidden( pDoc, nPrintTab, pPageRows[nPagesY], nStartCol, pPageEndX );
3113 ++nPagesY;
3116 nPageStartRow = nRow;
3117 bVisRow = FALSE;
3119 SCROW nLastRow = -1;
3120 if (!pDoc->RowHidden(nRow, nPrintTab, nLastRow))
3121 bVisRow = TRUE;
3122 else
3123 // skip all hidden rows.
3124 nRow = nLastRow;
3127 if (bVisRow)
3129 pPageEndY[nTotalY] = nEndRow;
3130 ++nTotalY;
3132 if ( !aTableParam.bSkipEmpty ||
3133 !pDoc->IsPrintEmpty( nPrintTab, nStartCol, nPageStartRow, nEndCol, nEndRow ) )
3135 pPageRows[nPagesY].SetStartRow( nPageStartRow );
3136 pPageRows[nPagesY].SetEndRow( nEndRow );
3137 pPageRows[nPagesY].SetPagesX( nPagesX );
3138 if (aTableParam.bSkipEmpty)
3139 lcl_SetHidden( pDoc, nPrintTab, pPageRows[nPagesY], nStartCol, pPageEndX );
3140 ++nPagesY;
3145 //------------------------------------------------------------------------
3146 // class ScJobSetup
3147 //------------------------------------------------------------------------
3149 ScJobSetup::ScJobSetup( SfxPrinter* pPrinter )
3151 eOrientation = pPrinter->GetOrientation();
3152 nPaperBin = pPrinter->GetPaperBin();
3153 ePaper = pPrinter->GetPaper();
3155 if ( PAPER_USER == ePaper )
3157 aUserSize = pPrinter->GetPaperSize();
3158 aUserMapMode = pPrinter->GetMapMode();