Update ooo320-m1
[ooovba.git] / sc / source / ui / view / printfun.cxx
blob982c02e8ae8b1d6b714ce3bd8ef921cd9083a4d3
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 pDocShell->UpdatePendingRowHeights( nPrintTab );
189 pDoc = pDocShell->GetDocument();
191 SfxPrinter* pDocPrinter = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen
192 if (pDocPrinter)
193 aOldPrinterMode = pDocPrinter->GetMapMode();
195 // einheitlicher MapMode ueber alle Aufrufe (z.B. Repaint !!!),
196 // weil die EditEngine sonst unterschiedliche Texthoehen liefert
197 pDev->SetMapMode(MAP_PIXEL);
199 pPageEndX = NULL;
200 pPageEndY = NULL;
201 pPageRows = NULL;
202 pBorderItem = NULL;
203 pBackgroundItem = NULL;
204 pShadowItem = NULL;
206 pEditEngine = NULL;
207 pEditDefaults = NULL;
209 ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
210 SfxStyleSheetBase* pStyleSheet = pStylePool->Find(
211 pDoc->GetPageStyle( nPrintTab ),
212 SFX_STYLE_FAMILY_PAGE );
213 if (pStyleSheet)
214 pParamSet = &pStyleSheet->GetItemSet();
215 else
217 DBG_ERROR("Seitenvorlage nicht gefunden" );
218 pParamSet = NULL;
221 if (!bState)
222 nZoom = 100;
223 nManualZoom = 100;
224 bClearWin = FALSE;
225 bUseStyleColor = FALSE;
226 bIsRender = FALSE;
228 InitParam(pOptions);
230 pPageData = NULL; // wird nur zur Initialisierung gebraucht
233 ScPrintFunc::ScPrintFunc( ScDocShell* pShell, SfxPrinter* pNewPrinter, SCTAB nTab,
234 long nPage, long nDocP, const ScRange* pArea,
235 const ScPrintOptions* pOptions,
236 ScPageBreakData* pData )
237 : pDocShell ( pShell ),
238 pPrinter ( pNewPrinter ),
239 pDrawView ( NULL ),
240 nPrintTab ( nTab ),
241 nPageStart ( nPage ),
242 nDocPages ( nDocP ),
243 pUserArea ( pArea ),
244 bState ( FALSE ),
245 bSourceRangeValid ( FALSE ),
246 bPrintCurrentTable ( FALSE ),
247 bMultiArea ( FALSE ),
248 nTabPages ( 0 ),
249 nTotalPages ( 0 ),
250 pPageData ( pData )
252 pDev = pPrinter;
253 aSrcOffset = pPrinter->PixelToLogic( pPrinter->GetPageOffsetPixel(), MAP_100TH_MM );
254 Construct( pOptions );
257 ScPrintFunc::ScPrintFunc( OutputDevice* pOutDev, ScDocShell* pShell, SCTAB nTab,
258 long nPage, long nDocP, const ScRange* pArea,
259 const ScPrintOptions* pOptions )
260 : pDocShell ( pShell ),
261 pPrinter ( NULL ),
262 pDrawView ( NULL ),
263 nPrintTab ( nTab ),
264 nPageStart ( nPage ),
265 nDocPages ( nDocP ),
266 pUserArea ( pArea ),
267 bState ( FALSE ),
268 bSourceRangeValid ( FALSE ),
269 bPrintCurrentTable ( FALSE ),
270 bMultiArea ( FALSE ),
271 nTabPages ( 0 ),
272 nTotalPages ( 0 ),
273 pPageData ( NULL )
275 pDev = pOutDev;
276 Construct( pOptions );
279 ScPrintFunc::ScPrintFunc( OutputDevice* pOutDev, ScDocShell* pShell,
280 const ScPrintState& rState, const ScPrintOptions* pOptions )
281 : pDocShell ( pShell ),
282 pPrinter ( NULL ),
283 pDrawView ( NULL ),
284 pUserArea ( NULL ),
285 bSourceRangeValid ( FALSE ),
286 bPrintCurrentTable ( FALSE ),
287 bMultiArea ( FALSE ),
288 pPageData ( NULL )
290 pDev = pOutDev;
292 nPrintTab = rState.nPrintTab;
293 nStartCol = rState.nStartCol;
294 nStartRow = rState.nStartRow;
295 nEndCol = rState.nEndCol;
296 nEndRow = rState.nEndRow;
297 nZoom = rState.nZoom;
298 nPagesX = rState.nPagesX;
299 nPagesY = rState.nPagesY;
300 nTabPages = rState.nTabPages;
301 nTotalPages = rState.nTotalPages;
302 nPageStart = rState.nPageStart;
303 nDocPages = rState.nDocPages;
304 bState = TRUE;
306 Construct( pOptions );
308 ScPrintFunc::ScPrintFunc( ScDocShell* pShell, Window* pWindow, SCTAB nTab,
309 long nPage, long nDocP, const ScRange* pArea,
310 const ScPrintOptions* pOptions )
311 : pDocShell ( pShell ),
312 pPrinter ( NULL ),
313 pDrawView ( NULL ),
314 nPrintTab ( nTab ),
315 nPageStart ( nPage ),
316 nDocPages ( nDocP ),
317 pUserArea ( pArea ),
318 bState ( FALSE ),
319 bPrintCurrentTable ( FALSE ),
320 bMultiArea ( FALSE ),
321 nTabPages ( 0 ),
322 nTotalPages ( 0 ),
323 pPageData ( NULL )
325 pDev = pWindow;
326 Construct( pOptions );
328 ScPrintFunc::ScPrintFunc( ScDocShell* pShell, Window* pWindow,
329 const ScPrintState& rState, const ScPrintOptions* pOptions )
330 : pDocShell ( pShell ),
331 pPrinter ( NULL ),
332 pDrawView ( NULL ),
333 pUserArea ( NULL ),
334 bPrintCurrentTable ( FALSE ),
335 bMultiArea ( FALSE ),
336 pPageData ( NULL )
338 pDev = pWindow;
340 nPrintTab = rState.nPrintTab;
341 nStartCol = rState.nStartCol;
342 nStartRow = rState.nStartRow;
343 nEndCol = rState.nEndCol;
344 nEndRow = rState.nEndRow;
345 nZoom = rState.nZoom;
346 nPagesX = rState.nPagesX;
347 nPagesY = rState.nPagesY;
348 nTabPages = rState.nTabPages;
349 nTotalPages = rState.nTotalPages;
350 nPageStart = rState.nPageStart;
351 nDocPages = rState.nDocPages;
352 bState = TRUE;
354 Construct( pOptions );
357 void ScPrintFunc::GetPrintState( ScPrintState& rState )
359 rState.nPrintTab = nPrintTab;
360 rState.nStartCol = nStartCol;
361 rState.nStartRow = nStartRow;
362 rState.nEndCol = nEndCol;
363 rState.nEndRow = nEndRow;
364 rState.nZoom = nZoom;
365 rState.nPagesX = nPagesX;
366 rState.nPagesY = nPagesY;
367 rState.nTabPages = nTabPages;
368 rState.nTotalPages = nTotalPages;
369 rState.nPageStart = nPageStart;
370 rState.nDocPages = nDocPages;
373 BOOL ScPrintFunc::GetLastSourceRange( ScRange& rRange ) const
375 rRange = aLastSourceRange;
376 return bSourceRangeValid;
379 void ScPrintFunc::FillPageData()
381 if (pPageData)
383 USHORT nCount = sal::static_int_cast<USHORT>( pPageData->GetCount() );
384 ScPrintRangeData& rData = pPageData->GetData(nCount); // hochzaehlen
386 rData.SetPrintRange( ScRange( nStartCol, nStartRow, nPrintTab,
387 nEndCol, nEndRow, nPrintTab ) );
388 rData.SetPagesX( nPagesX, pPageEndX );
389 rData.SetPagesY( nTotalY, pPageEndY );
391 // Einstellungen
392 rData.SetTopDown( aTableParam.bTopDown );
393 rData.SetAutomatic( !aAreaParam.bPrintArea );
397 ScPrintFunc::~ScPrintFunc()
399 ScAddress* pTripel = (ScAddress*) aNotePosList.First();
400 while (pTripel)
402 delete pTripel;
403 pTripel = (ScAddress*) aNotePosList.Next();
405 aNotePosList.Clear();
407 delete[] pPageEndX;
408 delete[] pPageEndY;
409 delete[] pPageRows;
410 delete pEditDefaults;
411 delete pEditEngine;
413 // Druckereinstellungen werden jetzt von aussen wiederhergestellt
415 // #64294# Fuer DrawingLayer/Charts muss der MapMode am Drucker (RefDevice) immer stimmen
416 SfxPrinter* pDocPrinter = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen
417 if (pDocPrinter)
418 pDocPrinter->SetMapMode(aOldPrinterMode);
421 void ScPrintFunc::SetDrawView( FmFormView* pNew )
423 pDrawView = pNew;
426 void lcl_HidePrint( ScTableInfo& rTabInfo, SCCOL nX1, SCCOL nX2 )
428 for (SCSIZE nArrY=1; nArrY+1<rTabInfo.mnArrCount; nArrY++)
430 RowInfo* pThisRowInfo = &rTabInfo.mpRowInfo[nArrY];
431 for (SCCOL nX=nX1; nX<=nX2; nX++)
433 const CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nX+1];
434 if (!rCellInfo.bEmptyCellText)
435 if (((const ScProtectionAttr&)rCellInfo.pPatternAttr->
436 GetItem(ATTR_PROTECTION, rCellInfo.pConditionSet)).GetHidePrint())
438 pThisRowInfo->pCellInfo[nX+1].pCell = NULL;
439 pThisRowInfo->pCellInfo[nX+1].bEmptyCellText = TRUE;
446 // Ausgabe auf Device (static)
448 // wird benutzt fuer:
449 // - Clipboard/Bitmap
450 // - Ole-Object (DocShell::Draw)
451 // - Vorschau bei Vorlagen
453 void ScPrintFunc::DrawToDev( ScDocument* pDoc, OutputDevice* pDev, double /* nPrintFactor */,
454 const Rectangle& rBound, ScViewData* pViewData, BOOL bMetaFile )
456 //! nPrintFactor auswerten !!!
458 SCTAB nTab = 0;
459 if (pViewData)
460 nTab = pViewData->GetTabNo();
462 BOOL bDoGrid, bNullVal, bFormula;
463 ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
464 SfxStyleSheetBase* pStyleSheet = pStylePool->Find( pDoc->GetPageStyle( nTab ), SFX_STYLE_FAMILY_PAGE );
465 if (pStyleSheet)
467 SfxItemSet& rSet = pStyleSheet->GetItemSet();
468 bDoGrid = ((const SfxBoolItem&)rSet.Get(ATTR_PAGE_GRID)).GetValue();
469 bNullVal = ((const SfxBoolItem&)rSet.Get(ATTR_PAGE_NULLVALS)).GetValue();
470 bFormula = ((const SfxBoolItem&)rSet.Get(ATTR_PAGE_FORMULAS)).GetValue();
472 else
474 const ScViewOptions& rOpt = pDoc->GetViewOptions();
475 bDoGrid = rOpt.GetOption(VOPT_GRID);
476 bNullVal = rOpt.GetOption(VOPT_NULLVALS);
477 bFormula = rOpt.GetOption(VOPT_FORMULAS);
480 MapMode aMode = pDev->GetMapMode();
482 Rectangle aRect = rBound;
484 if (aRect.Right() < aRect.Left() || aRect.Bottom() < aRect.Top())
485 aRect = Rectangle( Point(), pDev->GetOutputSize() );
487 SCCOL nX1 = 0;
488 SCROW nY1 = 0;
489 SCCOL nX2 = OLE_STD_CELLS_X - 1;
490 SCROW nY2 = OLE_STD_CELLS_Y - 1;
491 if (bMetaFile)
493 ScRange aRange = pDoc->GetRange( nTab, rBound );
494 nX1 = aRange.aStart.Col();
495 nY1 = aRange.aStart.Row();
496 nX2 = aRange.aEnd.Col();
497 nY2 = aRange.aEnd.Row();
499 else if (pViewData)
501 ScSplitPos eWhich = pViewData->GetActivePart();
502 ScHSplitPos eHWhich = WhichH(eWhich);
503 ScVSplitPos eVWhich = WhichV(eWhich);
504 nX1 = pViewData->GetPosX(eHWhich);
505 nY1 = pViewData->GetPosY(eVWhich);
506 nX2 = nX1 + pViewData->VisibleCellsX(eHWhich);
507 if (nX2>nX1) --nX2;
508 nY2 = nY1 + pViewData->VisibleCellsY(eVWhich);
509 if (nY2>nY1) --nY2;
512 if (nX1 > MAXCOL) nX1 = MAXCOL;
513 if (nX2 > MAXCOL) nX2 = MAXCOL;
514 if (nY1 > MAXROW) nY1 = MAXROW;
515 if (nY2 > MAXROW) nY2 = MAXROW;
517 long nDevSizeX = aRect.Right()-aRect.Left()+1;
518 long nDevSizeY = aRect.Bottom()-aRect.Top()+1;
520 Rectangle aLines;
521 ScRange aRange( nX1,nY1,nTab, nX2,nY2,nTab );
522 // BOOL bAddLines = pDoc->HasLines( aRange, aLines );
524 long nTwipsSizeX = 0;
525 for (SCCOL i=nX1; i<=nX2; i++)
526 nTwipsSizeX += pDoc->GetColWidth( i, nTab );
527 long nTwipsSizeY = (long) pDoc->GetRowHeight( nY1, nY2, nTab );
529 // wenn keine Linien, dann trotzdem Platz fuer den Aussenrahmen (20 Twips = 1pt)
530 // (HasLines initalisiert aLines auf 0,0,0,0)
531 nTwipsSizeX += aLines.Left() + Max( aLines.Right(), 20L );
532 nTwipsSizeY += aLines.Top() + Max( aLines.Bottom(), 20L );
534 double nScaleX = (double) nDevSizeX / nTwipsSizeX;
535 double nScaleY = (double) nDevSizeY / nTwipsSizeY;
537 //! Flag bei FillInfo uebergeben !!!!!
538 ScRange aERange;
539 BOOL bEmbed = pDoc->IsEmbedded();
540 if (bEmbed)
542 pDoc->GetEmbedded(aERange);
543 pDoc->ResetEmbedded();
546 // Daten zusammenstellen
548 ScTableInfo aTabInfo;
549 pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab,
550 nScaleX, nScaleY, FALSE, bFormula );
551 lcl_HidePrint( aTabInfo, nX1, nX2 );
553 if (bEmbed)
554 pDoc->SetEmbedded(aERange);
556 /* if (!bMetaFile)
557 pDev->SetMapMode(MAP_PIXEL);
559 long nScrX = aRect.Left();
560 long nScrY = aRect.Top();
562 // Wenn keine Linien, trotzdem Platz fuer Gitterlinien lassen
563 // (werden sonst abgeschnitten)
564 long nAddX = (long)( aLines.Left() * nScaleX );
565 nScrX += ( nAddX ? nAddX : 1 );
566 long nAddY = (long)( aLines.Top() * nScaleY );
567 nScrY += ( nAddY ? nAddY : 1 );
569 ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pDoc, nTab,
570 nScrX, nScrY, nX1, nY1, nX2, nY2, nScaleX, nScaleY );
571 aOutputData.SetMetaFileMode(bMetaFile);
572 aOutputData.SetShowNullValues(bNullVal);
573 aOutputData.SetShowFormulas(bFormula);
575 // #114135#
576 ScDrawLayer* pModel = pDoc->GetDrawLayer();
577 FmFormView* pDrawView = NULL;
579 if( pModel )
581 pDrawView = new FmFormView( pModel, pDev );
582 pDrawView->ShowSdrPage(pDrawView->GetModel()->GetPage(nTab));
583 pDrawView->SetPrintPreview( TRUE );
584 aOutputData.SetDrawView( pDrawView );
587 //! SetUseStyleColor ??
589 if ( bMetaFile && pDev->GetOutDevType() == OUTDEV_VIRDEV )
590 aOutputData.SetSnapPixel();
592 Point aLogStart = pDev->PixelToLogic( Point(nScrX,nScrY), MAP_100TH_MM );
593 long nLogStX = aLogStart.X();
594 long nLogStY = aLogStart.Y();
596 //! nZoom fuer GetFont in OutputData ???
598 if (!bMetaFile && pViewData)
599 pDev->SetMapMode(pViewData->GetLogicMode(pViewData->GetActivePart()));
601 // #i72502#
602 const Point aMMOffset(aOutputData.PrePrintDrawingLayer(nLogStX, nLogStY));
603 aOutputData.PrintDrawingLayer(SC_LAYER_BACK, aMMOffset);
605 if (!bMetaFile && pViewData)
606 pDev->SetMapMode(aMode);
608 aOutputData.DrawBackground();
610 #ifdef OS2
611 if (bMetaFile && !bDoGrid)
613 // unter OS2 fuer Metafiles gesamte Flaeche benutzen,
614 // weil sonst die Groesse nicht erkannt wird
615 pDev->SetLineColor();
616 pDev->SetFillColor();
617 pDev->DrawRect( Rectangle( nScrX,nScrY,
618 nScrX+aOutputData.GetScrW(), nScrY+aOutputData.GetScrH() ) );
620 #endif
622 aOutputData.DrawShadow();
623 aOutputData.DrawFrame();
624 aOutputData.DrawStrings();
626 if (!bMetaFile && pViewData)
627 pDev->SetMapMode(pViewData->GetLogicMode(pViewData->GetActivePart()));
629 aOutputData.DrawEdit(!bMetaFile);
631 if (bDoGrid)
633 if (!bMetaFile && pViewData)
634 pDev->SetMapMode(aMode);
636 aOutputData.DrawGrid( TRUE, FALSE ); // keine Seitenumbrueche
638 pDev->SetLineColor( COL_BLACK );
640 Size aOne = pDev->PixelToLogic( Size(1,1) );
641 if (bMetaFile)
642 aOne = Size(1,1); // compatible with DrawGrid
643 long nRight = nScrX + aOutputData.GetScrW() - aOne.Width();
644 long nBottom = nScrY + aOutputData.GetScrH() - aOne.Height();
646 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nTab );
648 // extra line at the left edge for left-to-right, right for right-to-left
649 if ( bLayoutRTL )
650 pDev->DrawLine( Point(nRight,nScrY), Point(nRight,nBottom) );
651 else
652 pDev->DrawLine( Point(nScrX,nScrY), Point(nScrX,nBottom) );
653 // extra line at the top in both cases
654 pDev->DrawLine( Point(nScrX,nScrY), Point(nRight,nScrY) );
657 // #i72502#
658 aOutputData.PrintDrawingLayer(SC_LAYER_FRONT, aMMOffset);
659 aOutputData.PrintDrawingLayer(SC_LAYER_INTERN, aMMOffset);
660 aOutputData.PostPrintDrawingLayer(aMMOffset); // #i74768#
662 // #114135#
663 delete pDrawView;
667 // Drucken
670 void lcl_FillHFParam( ScPrintHFParam& rParam, const SfxItemSet* pHFSet )
672 // nDistance muss vorher unterschiedlich initalisiert sein
674 if ( pHFSet == NULL )
676 rParam.bEnable = FALSE;
677 rParam.pBorder = NULL;
678 rParam.pBack = NULL;
679 rParam.pShadow = NULL;
681 else
683 rParam.bEnable = ((const SfxBoolItem&) pHFSet->Get(ATTR_PAGE_ON)).GetValue();
684 rParam.bDynamic = ((const SfxBoolItem&) pHFSet->Get(ATTR_PAGE_DYNAMIC)).GetValue();
685 rParam.bShared = ((const SfxBoolItem&) pHFSet->Get(ATTR_PAGE_SHARED)).GetValue();
686 rParam.nHeight = ((const SvxSizeItem&) pHFSet->Get(ATTR_PAGE_SIZE)).GetSize().Height();
687 const SvxLRSpaceItem* pHFLR = &(const SvxLRSpaceItem&) pHFSet->Get(ATTR_LRSPACE);
688 long nTmp;
689 nTmp = pHFLR->GetLeft();
690 rParam.nLeft = nTmp < 0 ? 0 : USHORT(nTmp);
691 nTmp = pHFLR->GetRight();
692 rParam.nRight = nTmp < 0 ? 0 : USHORT(nTmp);
693 rParam.pBorder = (const SvxBoxItem*) &pHFSet->Get(ATTR_BORDER);
694 rParam.pBack = (const SvxBrushItem*) &pHFSet->Get(ATTR_BACKGROUND);
695 rParam.pShadow = (const SvxShadowItem*)&pHFSet->Get(ATTR_SHADOW);;
697 // jetzt doch wieder schon im Dialog:
698 // rParam.nHeight += rParam.nDistance; // nicht mehr im Dialog ???
700 if (rParam.pBorder)
701 rParam.nHeight += lcl_LineTotal( rParam.pBorder->GetTop() ) +
702 lcl_LineTotal( rParam.pBorder->GetBottom() );
704 rParam.nManHeight = rParam.nHeight;
707 if (!rParam.bEnable)
708 rParam.nHeight = 0;
711 // bNew = TRUE: benutzten Bereich aus dem Dokument suchen
712 // bNew = FALSE: nur ganze Zeilen/Spalten begrenzen
714 BOOL ScPrintFunc::AdjustPrintArea( BOOL bNew )
716 SCCOL nOldEndCol = nEndCol; // nur wichtig bei !bNew
717 SCROW nOldEndRow = nEndRow;
718 BOOL bChangeCol = TRUE; // bei bNew werden beide angepasst
719 BOOL bChangeRow = TRUE;
721 BOOL bNotes = aTableParam.bNotes;
722 if ( bNew )
724 nStartCol = 0;
725 nStartRow = 0;
726 if (!pDoc->GetPrintArea( nPrintTab, nEndCol, nEndRow, bNotes ))
727 return FALSE; // nix
729 else
731 BOOL bFound = TRUE;
732 bChangeCol = ( nStartCol == 0 && nEndCol == MAXCOL );
733 bChangeRow = ( nStartRow == 0 && nEndRow == MAXROW );
734 BOOL bForcedChangeRow = FALSE;
736 // #i53558# Crop entire column of old row limit to real print area with
737 // some fuzzyness.
738 if (!bChangeRow && nStartRow == 0)
740 SCROW nPAEndRow;
741 bFound = pDoc->GetPrintAreaVer( nPrintTab, nStartCol, nEndCol, nPAEndRow, bNotes );
742 // Say we don't want to print more than ~1000 empty rows, which are
743 // about 14 pages intentionally left blank..
744 const SCROW nFuzzy = 23*42;
745 if (nPAEndRow + nFuzzy < nEndRow)
747 bForcedChangeRow = TRUE;
748 nEndRow = nPAEndRow;
750 else
751 bFound = TRUE; // user seems to _want_ to print some empty rows
753 // TODO: in case we extend the number of columns we may have to do the
754 // same for horizontal cropping.
756 if ( bChangeCol && bChangeRow )
757 bFound = pDoc->GetPrintArea( nPrintTab, nEndCol, nEndRow, bNotes );
758 else if ( bChangeCol )
759 bFound = pDoc->GetPrintAreaHor( nPrintTab, nStartRow, nEndRow, nEndCol, bNotes );
760 else if ( bChangeRow )
761 bFound = pDoc->GetPrintAreaVer( nPrintTab, nStartCol, nEndCol, nEndRow, bNotes );
763 if (!bFound)
764 return FALSE; // leer
766 if (bForcedChangeRow)
767 bChangeRow = TRUE;
770 pDoc->ExtendMerge( nStartCol,nStartRow, nEndCol,nEndRow, nPrintTab,
771 FALSE, TRUE ); // kein Refresh, incl. Attrs
773 if ( bChangeCol )
775 OutputDevice* pRefDev = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen
776 pRefDev->SetMapMode( MAP_PIXEL ); // wichtig fuer GetNeededSize
778 pDoc->ExtendPrintArea( pRefDev,
779 nPrintTab, nStartCol, nStartRow, nEndCol, nEndRow );
780 // nEndCol wird veraendert
783 if ( nEndCol < MAXCOL && pDoc->HasAttrib(
784 nEndCol,nStartRow,nPrintTab, nEndCol,nEndRow,nPrintTab, HASATTR_SHADOW_RIGHT ) )
785 ++nEndCol;
786 if ( nEndRow < MAXROW && pDoc->HasAttrib(
787 nStartCol,nEndRow,nPrintTab, nEndCol,nEndRow,nPrintTab, HASATTR_SHADOW_DOWN ) )
788 ++nEndRow;
790 if (!bChangeCol) nEndCol = nOldEndCol;
791 if (!bChangeRow) nEndRow = nOldEndRow;
793 return TRUE;
796 long ScPrintFunc::TextHeight( const EditTextObject* pObject )
798 if (!pObject)
799 return 0;
801 // pEditEngine->SetPageNo( nTotalPages );
802 pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, FALSE );
804 return (long) pEditEngine->GetTextHeight();
807 // nZoom muss gesetzt sein !!!
808 // und der entsprechende Twip-MapMode eingestellt
810 void ScPrintFunc::UpdateHFHeight( ScPrintHFParam& rParam )
812 DBG_ASSERT( aPageSize.Width(), "UpdateHFHeight ohne aPageSize");
814 if (rParam.bEnable && rParam.bDynamic)
816 // nHeight aus Inhalten berechnen
818 MakeEditEngine();
819 long nPaperWidth = ( aPageSize.Width() - nLeftMargin - nRightMargin -
820 rParam.nLeft - rParam.nRight ) * 100 / nZoom;
821 if (rParam.pBorder)
822 nPaperWidth -= ( rParam.pBorder->GetDistance(BOX_LINE_LEFT) +
823 rParam.pBorder->GetDistance(BOX_LINE_RIGHT) +
824 lcl_LineTotal(rParam.pBorder->GetLeft()) +
825 lcl_LineTotal(rParam.pBorder->GetRight()) ) * 100 / nZoom;
827 if (rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE)
828 nPaperWidth -= ( rParam.pShadow->CalcShadowSpace(SHADOW_LEFT) +
829 rParam.pShadow->CalcShadowSpace(SHADOW_RIGHT) ) * 100L / nZoom;
831 pEditEngine->SetPaperSize( Size( nPaperWidth, 10000 ) );
833 long nMaxHeight = 0;
834 if ( rParam.pLeft )
836 nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pLeft->GetLeftArea() ) );
837 nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pLeft->GetCenterArea() ) );
838 nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pLeft->GetRightArea() ) );
840 if ( rParam.pRight )
842 nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pRight->GetLeftArea() ) );
843 nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pRight->GetCenterArea() ) );
844 nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pRight->GetRightArea() ) );
847 rParam.nHeight = nMaxHeight + rParam.nDistance;
848 if (rParam.pBorder)
849 rParam.nHeight += rParam.pBorder->GetDistance(BOX_LINE_TOP) +
850 rParam.pBorder->GetDistance(BOX_LINE_BOTTOM) +
851 lcl_LineTotal( rParam.pBorder->GetTop() ) +
852 lcl_LineTotal( rParam.pBorder->GetBottom() );
853 if (rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE)
854 rParam.nHeight += rParam.pShadow->CalcShadowSpace(SHADOW_TOP) +
855 rParam.pShadow->CalcShadowSpace(SHADOW_BOTTOM);
857 if (rParam.nHeight < rParam.nManHeight)
858 rParam.nHeight = rParam.nManHeight; // eingestelltes Minimum
862 void ScPrintFunc::InitParam( const ScPrintOptions* pOptions )
864 if (!pParamSet)
865 return;
867 // TabPage "Seite"
868 const SvxLRSpaceItem* pLRItem = (const SvxLRSpaceItem*) &pParamSet->Get( ATTR_LRSPACE );
869 long nTmp;
870 nTmp = pLRItem->GetLeft();
871 nLeftMargin = nTmp < 0 ? 0 : USHORT(nTmp);
872 nTmp = pLRItem->GetRight();
873 nRightMargin = nTmp < 0 ? 0 : USHORT(nTmp);
874 const SvxULSpaceItem* pULItem = (const SvxULSpaceItem*) &pParamSet->Get( ATTR_ULSPACE );
875 nTopMargin = pULItem->GetUpper();
876 nBottomMargin = pULItem->GetLower();
878 const SvxPageItem* pPageItem = (const SvxPageItem*) &pParamSet->Get( ATTR_PAGE );
879 nPageUsage = pPageItem->GetPageUsage();
880 bLandscape = pPageItem->IsLandscape();
881 aFieldData.eNumType = pPageItem->GetNumType();
883 bCenterHor = ((const SfxBoolItem&) pParamSet->Get(ATTR_PAGE_HORCENTER)).GetValue();
884 bCenterVer = ((const SfxBoolItem&) pParamSet->Get(ATTR_PAGE_VERCENTER)).GetValue();
886 aPageSize = ((const SvxSizeItem&) pParamSet->Get(ATTR_PAGE_SIZE)).GetSize();
887 if ( !aPageSize.Width() || !aPageSize.Height() )
889 DBG_ERROR("PageSize Null ?!?!?");
890 aPageSize = SvxPaperInfo::GetPaperSize( PAPER_A4 );
893 pBorderItem = (const SvxBoxItem*) &pParamSet->Get(ATTR_BORDER);
894 pBackgroundItem = (const SvxBrushItem*) &pParamSet->Get(ATTR_BACKGROUND);
895 pShadowItem = (const SvxShadowItem*) &pParamSet->Get(ATTR_SHADOW);
897 // TabPage "Kopfzeile"
899 aHdr.pLeft = (const ScPageHFItem*) &pParamSet->Get(ATTR_PAGE_HEADERLEFT); // Inhalt
900 aHdr.pRight = (const ScPageHFItem*) &pParamSet->Get(ATTR_PAGE_HEADERRIGHT);
902 const SvxSetItem* pHeaderSetItem;
903 const SfxItemSet* pHeaderSet = NULL;
904 if ( pParamSet->GetItemState( ATTR_PAGE_HEADERSET, FALSE,
905 (const SfxPoolItem**)&pHeaderSetItem ) == SFX_ITEM_SET )
907 pHeaderSet = &pHeaderSetItem->GetItemSet();
908 // Kopfzeile hat unteren Abstand
909 aHdr.nDistance = ((const SvxULSpaceItem&) pHeaderSet->Get(ATTR_ULSPACE)).GetLower();
911 lcl_FillHFParam( aHdr, pHeaderSet );
913 // TabPage "Fusszeile"
915 aFtr.pLeft = (const ScPageHFItem*) &pParamSet->Get(ATTR_PAGE_FOOTERLEFT); // Inhalt
916 aFtr.pRight = (const ScPageHFItem*) &pParamSet->Get(ATTR_PAGE_FOOTERRIGHT);
918 const SvxSetItem* pFooterSetItem;
919 const SfxItemSet* pFooterSet = NULL;
920 if ( pParamSet->GetItemState( ATTR_PAGE_FOOTERSET, FALSE,
921 (const SfxPoolItem**)&pFooterSetItem ) == SFX_ITEM_SET )
923 pFooterSet = &pFooterSetItem->GetItemSet();
924 // Fusszeile hat oberen Abstand
925 aFtr.nDistance = ((const SvxULSpaceItem&) pFooterSet->Get(ATTR_ULSPACE)).GetUpper();
927 lcl_FillHFParam( aFtr, pFooterSet );
929 //------------------------------------------------------
930 // Table-/Area-Params aus einzelnen Items zusammenbauen:
931 //------------------------------------------------------
932 // TabPage "Tabelle"
934 const SfxUInt16Item* pScaleItem = NULL;
935 const ScPageScaleToItem* pScaleToItem = NULL;
936 const SfxUInt16Item* pScaleToPagesItem = NULL;
937 SfxItemState eState;
939 eState = pParamSet->GetItemState( ATTR_PAGE_SCALE, FALSE,
940 (const SfxPoolItem**)&pScaleItem );
941 if ( SFX_ITEM_DEFAULT == eState )
942 pScaleItem = (const SfxUInt16Item*)
943 &pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALE );
945 eState = pParamSet->GetItemState( ATTR_PAGE_SCALETO, FALSE,
946 (const SfxPoolItem**)&pScaleToItem );
947 if ( SFX_ITEM_DEFAULT == eState )
948 pScaleToItem = (const ScPageScaleToItem*)
949 &pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALETO );
951 eState = pParamSet->GetItemState( ATTR_PAGE_SCALETOPAGES, FALSE,
952 (const SfxPoolItem**)&pScaleToPagesItem );
953 if ( SFX_ITEM_DEFAULT == eState )
954 pScaleToPagesItem = (const SfxUInt16Item*)
955 &pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALETOPAGES );
957 DBG_ASSERT( pScaleItem && pScaleToItem && pScaleToPagesItem, "Missing ScaleItem! :-/" );
959 aTableParam.bCellContent = TRUE;
960 aTableParam.bNotes = GET_BOOL(pParamSet,ATTR_PAGE_NOTES);
961 aTableParam.bGrid = GET_BOOL(pParamSet,ATTR_PAGE_GRID);
962 aTableParam.bHeaders = GET_BOOL(pParamSet,ATTR_PAGE_HEADERS);
963 aTableParam.bFormulas = GET_BOOL(pParamSet,ATTR_PAGE_FORMULAS);
964 aTableParam.bNullVals = GET_BOOL(pParamSet,ATTR_PAGE_NULLVALS);
965 aTableParam.bCharts = GET_SHOW(pParamSet,ATTR_PAGE_CHARTS);
966 aTableParam.bObjects = GET_SHOW(pParamSet,ATTR_PAGE_OBJECTS);
967 aTableParam.bDrawings = GET_SHOW(pParamSet,ATTR_PAGE_DRAWINGS);
968 aTableParam.bTopDown = GET_BOOL(pParamSet,ATTR_PAGE_TOPDOWN);
969 aTableParam.bLeftRight = !aTableParam.bLeftRight;
970 aTableParam.nFirstPageNo = GET_USHORT(pParamSet,ATTR_PAGE_FIRSTPAGENO);
971 if (!aTableParam.nFirstPageNo)
972 aTableParam.nFirstPageNo = (USHORT) nPageStart; // von vorheriger Tabelle
974 if ( pScaleItem && pScaleToItem && pScaleToPagesItem )
976 UINT16 nScaleAll = pScaleItem->GetValue();
977 UINT16 nScaleToPages = pScaleToPagesItem->GetValue();
979 aTableParam.bScaleNone = (nScaleAll == 100);
980 aTableParam.bScaleAll = (nScaleAll > 0 );
981 aTableParam.bScaleTo = pScaleToItem->IsValid();
982 aTableParam.bScalePageNum = (nScaleToPages > 0 );
983 aTableParam.nScaleAll = nScaleAll;
984 aTableParam.nScaleWidth = pScaleToItem->GetWidth();
985 aTableParam.nScaleHeight = pScaleToItem->GetHeight();
986 aTableParam.nScalePageNum = nScaleToPages;
988 else
990 aTableParam.bScaleNone = TRUE;
991 aTableParam.bScaleAll = FALSE;
992 aTableParam.bScaleTo = FALSE;
993 aTableParam.bScalePageNum = FALSE;
994 aTableParam.nScaleAll = 0;
995 aTableParam.nScaleWidth = 0;
996 aTableParam.nScaleHeight = 0;
997 aTableParam.nScalePageNum = 0;
1000 // skip empty pages only if options with that flag are passed
1001 aTableParam.bSkipEmpty = pOptions && pOptions->GetSkipEmpty();
1002 if ( pPageData )
1003 aTableParam.bSkipEmpty = FALSE;
1004 // Wenn pPageData gesetzt ist, interessieren fuer die Umbruch-Vorschau
1005 // nur die Umbrueche, leere Seiten werden nicht speziell behandelt
1007 //------------------------------------------------------
1008 // TabPage "Bereiche":
1009 //------------------------------------------------------
1011 //! alle PrintAreas der Tabelle durchgehen !!!
1012 const ScRange* pPrintArea = pDoc->GetPrintRange( nPrintTab, 0 );
1013 const ScRange* pRepeatCol = pDoc->GetRepeatColRange( nPrintTab );
1014 const ScRange* pRepeatRow = pDoc->GetRepeatRowRange( nPrintTab );
1016 // ATTR_PAGE_PRINTTABLES wird ignoriert
1018 if ( pUserArea ) // UserArea (Selektion) hat Vorrang
1020 bPrintCurrentTable =
1021 aAreaParam.bPrintArea = TRUE; // Selektion
1022 aAreaParam.aPrintArea = *pUserArea;
1024 // Die Tabellen-Abfrage ist schon in DocShell::Print, hier immer
1025 aAreaParam.aPrintArea.aStart.SetTab(nPrintTab);
1026 aAreaParam.aPrintArea.aEnd.SetTab(nPrintTab);
1028 // lcl_LimitRange( aAreaParam.aPrintArea, nPrintTab ); // ganze Zeilen/Spalten...
1030 else if ( pDoc->HasPrintRange() )
1032 if ( pPrintArea ) // mindestens eine gesetzt ?
1034 bPrintCurrentTable =
1035 aAreaParam.bPrintArea = TRUE;
1036 aAreaParam.aPrintArea = *pPrintArea;
1038 bMultiArea = ( pDoc->GetPrintRangeCount(nPrintTab) > 1 );
1040 else
1042 // do not print hidden sheets with "Print entire sheet" flag
1043 bPrintCurrentTable = pDoc->IsPrintEntireSheet( nPrintTab ) && pDoc->IsVisible( nPrintTab );
1044 aAreaParam.bPrintArea = !bPrintCurrentTable; // otherwise the table is always counted
1047 else
1049 // #74834# don't print hidden tables if there's no print range defined there
1050 if ( pDoc->IsVisible( nPrintTab ) )
1052 aAreaParam.bPrintArea = FALSE;
1053 bPrintCurrentTable = TRUE;
1055 else
1057 aAreaParam.bPrintArea = TRUE; // otherwise the table is always counted
1058 bPrintCurrentTable = FALSE;
1062 if ( pRepeatCol )
1064 aAreaParam.bRepeatCol = TRUE;
1065 aAreaParam.aRepeatCol = *pRepeatCol;
1066 nRepeatStartCol = pRepeatCol->aStart.Col();
1067 nRepeatEndCol = pRepeatCol->aEnd .Col();
1069 else
1071 aAreaParam.bRepeatCol = FALSE;
1072 nRepeatStartCol = nRepeatEndCol = SCCOL_REPEAT_NONE;
1075 if ( pRepeatRow )
1077 aAreaParam.bRepeatRow = TRUE;
1078 aAreaParam.aRepeatRow = *pRepeatRow;
1079 nRepeatStartRow = pRepeatRow->aStart.Row();
1080 nRepeatEndRow = pRepeatRow->aEnd .Row();
1082 else
1084 aAreaParam.bRepeatRow = FALSE;
1085 nRepeatStartRow = nRepeatEndRow = SCROW_REPEAT_NONE;
1089 // Seiten aufteilen
1092 if (!bState)
1094 nTabPages = CountPages(); // berechnet auch Zoom
1095 nTotalPages = nTabPages;
1096 nTotalPages += CountNotePages();
1098 else
1100 CalcPages(); // nur Umbrueche suchen
1101 CountNotePages(); // Notizen zaehlen, auch wenn Seitenzahl schon bekannt
1104 if (nDocPages)
1105 aFieldData.nTotalPages = nDocPages;
1106 else
1107 aFieldData.nTotalPages = nTotalPages;
1109 SetDateTime( Date(), Time() );
1111 aFieldData.aTitle = pDocShell->GetTitle();
1112 const INetURLObject& rURLObj = pDocShell->GetMedium()->GetURLObject();
1113 aFieldData.aLongDocName = rURLObj.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS );
1114 if ( aFieldData.aLongDocName.Len() )
1115 aFieldData.aShortDocName = rURLObj.GetName( INetURLObject::DECODE_UNAMBIGUOUS );
1116 else
1117 aFieldData.aShortDocName = aFieldData.aLongDocName = aFieldData.aTitle;
1119 // Druckereinstellungen (Orientation, Paper) jetzt erst bei DoPrint
1122 Size ScPrintFunc::GetDataSize() const
1124 Size aSize = aPageSize;
1125 aSize.Width() -= nLeftMargin + nRightMargin;
1126 aSize.Height() -= nTopMargin + nBottomMargin;
1127 aSize.Height() -= aHdr.nHeight + aFtr.nHeight;
1128 return aSize;
1131 void ScPrintFunc::GetScaleData( Size& rPhysSize, long& rDocHdr, long& rDocFtr )
1133 rPhysSize = aPageSize;
1134 rPhysSize.Width() -= nLeftMargin + nRightMargin;
1135 rPhysSize.Height() -= nTopMargin + nBottomMargin;
1137 rDocHdr = aHdr.nHeight;
1138 rDocFtr = aFtr.nHeight;
1141 void ScPrintFunc::SetDateTime( const Date& rDate, const Time& rTime )
1143 aFieldData.aDate = rDate;
1144 aFieldData.aTime = rTime;
1147 void lcl_DrawGraphic( const Graphic &rGraphic, OutputDevice *pOut,
1148 const Rectangle &rGrf, const Rectangle &rOut )
1150 const FASTBOOL bNotInside = !rOut.IsInside( rGrf );
1151 if ( bNotInside )
1153 pOut->Push();
1154 pOut->IntersectClipRegion( rOut );
1157 ((Graphic&)rGraphic).Draw( pOut, rGrf.TopLeft(), rGrf.GetSize() );
1159 if ( bNotInside )
1160 pOut->Pop();
1163 void lcl_DrawGraphic( const SvxBrushItem &rBrush, OutputDevice *pOut, OutputDevice* pRefDev,
1164 const Rectangle &rOrg, const Rectangle &rOut )
1166 Size aGrfSize(0,0);
1167 const Graphic *pGraphic = rBrush.GetGraphic();
1168 SvxGraphicPosition ePos;
1169 if ( pGraphic && pGraphic->IsSupportedGraphic() )
1171 const MapMode aMapMM( MAP_100TH_MM );
1172 if ( pGraphic->GetPrefMapMode().GetMapUnit() == MAP_PIXEL )
1173 aGrfSize = pRefDev->PixelToLogic( pGraphic->GetPrefSize(), aMapMM );
1174 else
1175 aGrfSize = OutputDevice::LogicToLogic( pGraphic->GetPrefSize(),
1176 pGraphic->GetPrefMapMode(), aMapMM );
1177 ePos = rBrush.GetGraphicPos();
1179 else
1180 ePos = GPOS_NONE;
1182 Point aPos;
1183 Size aDrawSize = aGrfSize;
1185 FASTBOOL bDraw = TRUE;
1186 // FASTBOOL bRetouche = TRUE;
1187 switch ( ePos )
1189 case GPOS_LT: aPos = rOrg.TopLeft();
1190 break;
1191 case GPOS_MT: aPos.Y() = rOrg.Top();
1192 aPos.X() = rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2;
1193 break;
1194 case GPOS_RT: aPos.Y() = rOrg.Top();
1195 aPos.X() = rOrg.Right() - aGrfSize.Width();
1196 break;
1198 case GPOS_LM: aPos.Y() = rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2;
1199 aPos.X() = rOrg.Left();
1200 break;
1201 case GPOS_MM: aPos.Y() = rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2;
1202 aPos.X() = rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2;
1203 break;
1204 case GPOS_RM: aPos.Y() = rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2;
1205 aPos.X() = rOrg.Right() - aGrfSize.Width();
1206 break;
1208 case GPOS_LB: aPos.Y() = rOrg.Bottom() - aGrfSize.Height();
1209 aPos.X() = rOrg.Left();
1210 break;
1211 case GPOS_MB: aPos.Y() = rOrg.Bottom() - aGrfSize.Height();
1212 aPos.X() = rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2;
1213 break;
1214 case GPOS_RB: aPos.Y() = rOrg.Bottom() - aGrfSize.Height();
1215 aPos.X() = rOrg.Right() - aGrfSize.Width();
1216 break;
1218 case GPOS_AREA:
1219 aPos = rOrg.TopLeft();
1220 aDrawSize = rOrg.GetSize();
1221 // bRetouche = FALSE;
1222 break;
1223 case GPOS_TILED:
1225 // #104004# use GraphicObject::DrawTiled instead of an own loop
1226 // (pixel rounding is handled correctly, and a very small bitmap
1227 // is duplicated into a bigger one for better performance)
1229 GraphicObject aObject( *pGraphic );
1231 if( pOut->GetPDFWriter() &&
1232 (aObject.GetType() == GRAPHIC_BITMAP || aObject.GetType() == GRAPHIC_DEFAULT) )
1234 // #104004# For PDF export, every draw
1235 // operation for bitmaps takes a noticeable
1236 // amount of place (~50 characters). Thus,
1237 // optimize between tile bitmap size and
1238 // number of drawing operations here.
1240 // A_out
1241 // n_chars = k1 * ---------- + k2 * A_bitmap
1242 // A_bitmap
1244 // minimum n_chars is obtained for (derive for
1245 // A_bitmap, set to 0, take positive
1246 // solution):
1247 // k1
1248 // A_bitmap = Sqrt( ---- A_out )
1249 // k2
1251 // where k1 is the number of chars per draw
1252 // operation, and k2 is the number of chars
1253 // per bitmap pixel. This is approximately 50
1254 // and 7 for current PDF writer, respectively.
1256 const double k1( 50 );
1257 const double k2( 7 );
1258 const Size aSize( rOrg.GetSize() );
1259 const double Abitmap( k1/k2 * aSize.Width()*aSize.Height() );
1261 aObject.DrawTiled( pOut, rOrg, aGrfSize, Size(0,0),
1262 NULL, GRFMGR_DRAW_STANDARD,
1263 ::std::max( 128, static_cast<int>( sqrt(sqrt( Abitmap)) + .5 ) ) );
1265 else
1267 aObject.DrawTiled( pOut, rOrg, aGrfSize, Size(0,0) );
1270 bDraw = FALSE;
1271 // bRetouche = FALSE;
1273 break;
1275 case GPOS_NONE:
1276 bDraw = FALSE;
1277 break;
1279 default: DBG_ASSERT( !pOut, "new Graphic position?" );
1281 Rectangle aGrf( aPos,aDrawSize );
1282 if ( bDraw && aGrf.IsOver( rOut ) )
1284 lcl_DrawGraphic( *pGraphic, pOut, aGrf, rOut );
1288 // Rahmen wird nach innen gezeichnet
1290 void ScPrintFunc::DrawBorder( long nScrX, long nScrY, long nScrW, long nScrH,
1291 const SvxBoxItem* pBorderData, const SvxBrushItem* pBackground,
1292 const SvxShadowItem* pShadow )
1294 //! direkte Ausgabe aus SvxBoxItem !!!
1296 if (pBorderData)
1297 if ( !pBorderData->GetTop() && !pBorderData->GetBottom() && !pBorderData->GetLeft() &&
1298 !pBorderData->GetRight() )
1299 pBorderData = NULL;
1301 if (!pBorderData && !pBackground && !pShadow)
1302 return; // nichts zu tun
1304 long nLeft = 0;
1305 long nRight = 0;
1306 long nTop = 0;
1307 long nBottom = 0;
1309 // aFrameRect - aussen um die Umrandung, ohne Schatten
1310 if ( pShadow && pShadow->GetLocation() != SVX_SHADOW_NONE )
1312 nLeft += (long) ( pShadow->CalcShadowSpace(SHADOW_LEFT) * nScaleX );
1313 nRight += (long) ( pShadow->CalcShadowSpace(SHADOW_RIGHT) * nScaleX );
1314 nTop += (long) ( pShadow->CalcShadowSpace(SHADOW_TOP) * nScaleY );
1315 nBottom += (long) ( pShadow->CalcShadowSpace(SHADOW_BOTTOM) * nScaleY );
1317 Rectangle aFrameRect( Point(nScrX+nLeft, nScrY+nTop),
1318 Size(nScrW-nLeft-nRight, nScrH-nTop-nBottom) );
1320 // Mitte der Umrandung, um Linien ueber OutputData zu zeichnen:
1321 if (pBorderData)
1323 nLeft += (long) ( lcl_LineTotal(pBorderData->GetLeft()) * nScaleX / 2 );
1324 nRight += (long) ( lcl_LineTotal(pBorderData->GetRight()) * nScaleX / 2 );
1325 nTop += (long) ( lcl_LineTotal(pBorderData->GetTop()) * nScaleY / 2 );
1326 nBottom += (long) ( lcl_LineTotal(pBorderData->GetBottom()) * nScaleY / 2 );
1328 long nEffHeight = nScrH - nTop - nBottom;
1329 long nEffWidth = nScrW - nLeft - nRight;
1330 if (nEffHeight<=0 || nEffWidth<=0)
1331 return; // leer
1333 // #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed TRUE)
1334 BOOL bCellContrast = bUseStyleColor &&
1335 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
1337 if ( pBackground && !bCellContrast )
1339 // Rectangle aBackRect( Point(nScrX+nLeft, nScrY+nTop), Size(nEffWidth,nEffHeight) );
1340 if (pBackground->GetGraphicPos() != GPOS_NONE)
1342 OutputDevice* pRefDev;
1343 if ( bIsRender )
1344 pRefDev = pDev; // don't use printer for PDF
1345 else
1346 pRefDev = pDoc->GetPrinter(); // use printer also for preview
1348 lcl_DrawGraphic( *pBackground, pDev, pRefDev, aFrameRect, aFrameRect );
1350 else
1352 pDev->SetFillColor(pBackground->GetColor());
1353 pDev->SetLineColor();
1354 pDev->DrawRect(aFrameRect);
1358 if ( pShadow && pShadow->GetLocation() != SVX_SHADOW_NONE )
1360 if ( bCellContrast )
1361 pDev->SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
1362 else
1363 pDev->SetFillColor(pShadow->GetColor());
1364 pDev->SetLineColor();
1365 long nShadowX = (long) ( pShadow->GetWidth() * nScaleX );
1366 long nShadowY = (long) ( pShadow->GetWidth() * nScaleY );
1367 switch (pShadow->GetLocation())
1369 case SVX_SHADOW_TOPLEFT:
1370 pDev->DrawRect( Rectangle(
1371 aFrameRect.Left()-nShadowX, aFrameRect.Top()-nShadowY,
1372 aFrameRect.Right()-nShadowX, aFrameRect.Top() ) );
1373 pDev->DrawRect( Rectangle(
1374 aFrameRect.Left()-nShadowX, aFrameRect.Top()-nShadowY,
1375 aFrameRect.Left(), aFrameRect.Bottom()-nShadowY ) );
1376 break;
1377 case SVX_SHADOW_TOPRIGHT:
1378 pDev->DrawRect( Rectangle(
1379 aFrameRect.Left()+nShadowX, aFrameRect.Top()-nShadowY,
1380 aFrameRect.Right()+nShadowX, aFrameRect.Top() ) );
1381 pDev->DrawRect( Rectangle(
1382 aFrameRect.Right(), aFrameRect.Top()-nShadowY,
1383 aFrameRect.Right()+nShadowX, aFrameRect.Bottom()-nShadowY ) );
1384 break;
1385 case SVX_SHADOW_BOTTOMLEFT:
1386 pDev->DrawRect( Rectangle(
1387 aFrameRect.Left()-nShadowX, aFrameRect.Bottom(),
1388 aFrameRect.Right()-nShadowX, aFrameRect.Bottom()+nShadowY ) );
1389 pDev->DrawRect( Rectangle(
1390 aFrameRect.Left()-nShadowX, aFrameRect.Top()+nShadowY,
1391 aFrameRect.Left(), aFrameRect.Bottom()+nShadowY ) );
1392 break;
1393 case SVX_SHADOW_BOTTOMRIGHT:
1394 pDev->DrawRect( Rectangle(
1395 aFrameRect.Left()+nShadowX, aFrameRect.Bottom(),
1396 aFrameRect.Right()+nShadowX, aFrameRect.Bottom()+nShadowY ) );
1397 pDev->DrawRect( Rectangle(
1398 aFrameRect.Right(), aFrameRect.Top()+nShadowY,
1399 aFrameRect.Right()+nShadowX, aFrameRect.Bottom()+nShadowY ) );
1400 break;
1401 default:
1403 // added to avoid warnings
1408 if (pBorderData)
1410 ScDocument* pBorderDoc = new ScDocument( SCDOCMODE_UNDO );
1411 pBorderDoc->InitUndo( pDoc, 0,0, TRUE,TRUE );
1412 if (pBorderData)
1413 pBorderDoc->ApplyAttr( 0,0,0, *pBorderData );
1415 ScTableInfo aTabInfo;
1416 pBorderDoc->FillInfo( aTabInfo, 0,0, 0,0, 0,
1417 nScaleX, nScaleY, FALSE, FALSE );
1418 DBG_ASSERT(aTabInfo.mnArrCount,"nArrCount == 0");
1420 aTabInfo.mpRowInfo[1].nHeight = (USHORT) nEffHeight;
1421 aTabInfo.mpRowInfo[0].pCellInfo[1].nWidth =
1422 aTabInfo.mpRowInfo[1].pCellInfo[1].nWidth = (USHORT) nEffWidth;
1424 ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pBorderDoc, 0,
1425 nScrX+nLeft, nScrY+nTop, 0,0, 0,0, nScaleX, nScaleY );
1426 aOutputData.SetUseStyleColor( bUseStyleColor );
1428 // pDev->SetMapMode(aTwipMode);
1430 if (pBorderData)
1431 aOutputData.DrawFrame();
1433 delete pBorderDoc;
1437 void ScPrintFunc::PrintColHdr( SCCOL nX1, SCCOL nX2, long nScrX, long nScrY )
1439 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab );
1440 long nLayoutSign = bLayoutRTL ? -1 : 1;
1442 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1443 long nOneX = aOnePixel.Width();
1444 long nOneY = aOnePixel.Height();
1445 SCCOL nCol;
1447 long nHeight = (long) (PRINT_HEADER_HEIGHT * nScaleY);
1448 long nEndY = nScrY + nHeight - nOneY;
1450 long nPosX = nScrX;
1451 if ( bLayoutRTL )
1453 for (nCol=nX1; nCol<=nX2; nCol++)
1454 nPosX += (long)( pDoc->GetColWidth( nCol, nPrintTab ) * nScaleX );
1456 else
1457 nPosX -= nOneX;
1458 long nPosY = nScrY - nOneY;
1459 String aText;
1461 for (nCol=nX1; nCol<=nX2; nCol++)
1463 USHORT nDocW = pDoc->GetColWidth( nCol, nPrintTab );
1464 if (nDocW)
1466 long nWidth = (long) (nDocW * nScaleX);
1467 long nEndX = nPosX + nWidth * nLayoutSign;
1469 pDev->DrawRect( Rectangle( nPosX,nPosY,nEndX,nEndY ) );
1471 aText = ::ScColToAlpha( nCol);
1472 long nTextWidth = pDev->GetTextWidth(aText);
1473 long nTextHeight = pDev->GetTextHeight();
1474 long nAddX = ( nWidth - nTextWidth ) / 2;
1475 long nAddY = ( nHeight - nTextHeight ) / 2;
1476 long nTextPosX = nPosX+nAddX;
1477 if ( bLayoutRTL )
1478 nTextPosX -= nWidth;
1479 pDev->DrawText( Point( nTextPosX,nPosY+nAddY ), aText );
1481 nPosX = nEndX;
1486 void ScPrintFunc::PrintRowHdr( SCROW nY1, SCROW nY2, long nScrX, long nScrY )
1488 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1489 long nOneX = aOnePixel.Width();
1490 long nOneY = aOnePixel.Height();
1492 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab );
1494 long nWidth = (long) (PRINT_HEADER_WIDTH * nScaleX);
1495 long nEndX = nScrX + nWidth;
1496 long nPosX = nScrX;
1497 if ( !bLayoutRTL )
1499 nEndX -= nOneX;
1500 nPosX -= nOneX;
1502 long nPosY = nScrY - nOneY;
1503 String aText;
1505 for (SCROW nRow=nY1; nRow<=nY2; nRow++)
1507 USHORT nDocH = pDoc->FastGetRowHeight( nRow, nPrintTab );
1508 if (nDocH)
1510 long nHeight = (long) (nDocH * nScaleY);
1511 long nEndY = nPosY + nHeight;
1513 pDev->DrawRect( Rectangle( nPosX,nPosY,nEndX,nEndY ) );
1515 aText = String::CreateFromInt32( nRow+1 );
1516 long nTextWidth = pDev->GetTextWidth(aText);
1517 long nTextHeight = pDev->GetTextHeight();
1518 long nAddX = ( nWidth - nTextWidth ) / 2;
1519 long nAddY = ( nHeight - nTextHeight ) / 2;
1520 pDev->DrawText( Point( nPosX+nAddX,nPosY+nAddY ), aText );
1522 nPosY = nEndY;
1527 void ScPrintFunc::LocateColHdr( SCCOL nX1, SCCOL nX2, long nScrX, long nScrY,
1528 BOOL bRepCol, ScPreviewLocationData& rLocationData )
1530 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1531 long nOneX = aOnePixel.Width();
1532 long nOneY = aOnePixel.Height();
1534 long nHeight = (long) (PRINT_HEADER_HEIGHT * nScaleY);
1535 long nEndY = nScrY + nHeight - nOneY;
1537 long nPosX = nScrX - nOneX;
1538 for (SCCOL nCol=nX1; nCol<=nX2; nCol++)
1540 USHORT nDocW = pDoc->GetColWidth( nCol, nPrintTab );
1541 if (nDocW)
1542 nPosX += (long) (nDocW * nScaleX);
1544 Rectangle aCellRect( nScrX, nScrY, nPosX, nEndY );
1545 rLocationData.AddColHeaders( aCellRect, nX1, nX2, bRepCol );
1548 void ScPrintFunc::LocateRowHdr( SCROW nY1, SCROW nY2, long nScrX, long nScrY,
1549 BOOL bRepRow, ScPreviewLocationData& rLocationData )
1551 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1552 long nOneX = aOnePixel.Width();
1553 long nOneY = aOnePixel.Height();
1555 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab );
1557 long nWidth = (long) (PRINT_HEADER_WIDTH * nScaleX);
1558 long nEndX = nScrX + nWidth;
1559 if ( !bLayoutRTL )
1560 nEndX -= nOneX;
1562 long nPosY = nScrY - nOneY;
1563 nPosY += pDoc->FastGetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY);
1564 Rectangle aCellRect( nScrX, nScrY, nEndX, nPosY );
1565 rLocationData.AddRowHeaders( aCellRect, nY1, nY2, bRepRow );
1568 void ScPrintFunc::LocateArea( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
1569 long nScrX, long nScrY, BOOL bRepCol, BOOL bRepRow,
1570 ScPreviewLocationData& rLocationData )
1572 // get MapMode for drawing objects (same MapMode as in ScOutputData::PrintDrawingLayer)
1574 Point aLogPos = OutputDevice::LogicToLogic(Point(nScrX,nScrY), aOffsetMode, aLogicMode);
1575 long nLogStX = aLogPos.X();
1576 long nLogStY = aLogPos.Y();
1578 SCCOL nCol;
1579 Point aTwipOffset;
1580 for (nCol=0; nCol<nX1; nCol++)
1581 aTwipOffset.X() -= pDoc->GetColWidth( nCol, nPrintTab );
1582 aTwipOffset.Y() -= pDoc->GetRowHeight( 0, nY1-1, nPrintTab );
1584 Point aMMOffset( aTwipOffset );
1585 aMMOffset.X() = (long)(aMMOffset.X() * HMM_PER_TWIPS);
1586 aMMOffset.Y() = (long)(aMMOffset.Y() * HMM_PER_TWIPS);
1587 aMMOffset += Point( nLogStX, nLogStY );
1588 MapMode aDrawMapMode( MAP_100TH_MM, aMMOffset, aLogicMode.GetScaleX(), aLogicMode.GetScaleY() );
1590 // get pixel rectangle
1592 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
1593 long nOneX = aOnePixel.Width();
1594 long nOneY = aOnePixel.Height();
1596 long nPosX = nScrX - nOneX;
1597 for (nCol=nX1; nCol<=nX2; nCol++)
1599 USHORT nDocW = pDoc->GetColWidth( nCol, nPrintTab );
1600 if (nDocW)
1601 nPosX += (long) (nDocW * nScaleX);
1604 long nPosY = nScrY - nOneY;
1605 nPosY += pDoc->FastGetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY);
1606 Rectangle aCellRect( nScrX, nScrY, nPosX, nPosY );
1607 rLocationData.AddCellRange( aCellRect, ScRange( nX1,nY1,nPrintTab, nX2,nY2,nPrintTab ),
1608 bRepCol, bRepRow, aDrawMapMode );
1611 void ScPrintFunc::PrintArea( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
1612 long nScrX, long nScrY,
1613 BOOL bShLeft, BOOL bShTop, BOOL bShRight, BOOL bShBottom )
1615 // #i47547# nothing to do if the end of the print area is before the end of
1616 // the repeat columns/rows (don't use negative size for ScOutputData)
1617 if ( nX2 < nX1 || nY2 < nY1 )
1618 return;
1620 //! Flag bei FillInfo uebergeben !!!!!
1621 ScRange aERange;
1622 BOOL bEmbed = pDoc->IsEmbedded();
1623 if (bEmbed)
1625 pDoc->GetEmbedded(aERange);
1626 pDoc->ResetEmbedded();
1629 Point aPos = OutputDevice::LogicToLogic(Point(nScrX,nScrY), aOffsetMode, aLogicMode);
1630 long nLogStX = aPos.X();
1631 long nLogStY = aPos.Y();
1633 // Daten zusammenstellen
1635 ScTableInfo aTabInfo;
1636 pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nPrintTab,
1637 nScaleX, nScaleY, TRUE, aTableParam.bFormulas );
1638 lcl_HidePrint( aTabInfo, nX1, nX2 );
1640 if (bEmbed)
1641 pDoc->SetEmbedded(aERange);
1643 ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pDoc, nPrintTab,
1644 nScrX, nScrY, nX1, nY1, nX2, nY2, nScaleX, nScaleY );
1646 // #114135#
1647 aOutputData.SetDrawView( pDrawView );
1649 // test if all paint parts are hidden, then a paint is not necessary at all
1650 const Point aMMOffset(aOutputData.PrePrintDrawingLayer(nLogStX, nLogStY));
1651 const bool bHideAllDrawingLayer(pDrawView && pDrawView->getHideOle() && pDrawView->getHideChart() && pDrawView->getHideDraw());
1653 if(!bHideAllDrawingLayer)
1655 pDev->SetMapMode(aLogicMode);
1656 // hier kein Clipping setzen (Mapmode wird verschoben)
1658 // #i72502#
1659 aOutputData.PrintDrawingLayer(SC_LAYER_BACK, aMMOffset);
1662 pDev->SetMapMode(aOffsetMode);
1664 aOutputData.SetShowFormulas( aTableParam.bFormulas );
1665 aOutputData.SetShowNullValues( aTableParam.bNullVals );
1666 aOutputData.SetUseStyleColor( bUseStyleColor );
1668 Color aGridColor( COL_BLACK );
1669 if ( bUseStyleColor )
1670 aGridColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
1671 aOutputData.SetGridColor( aGridColor );
1673 if ( !pPrinter )
1675 OutputDevice* pRefDev = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen
1676 Fraction aPrintFrac( nZoom, 100 ); // ohne nManualZoom
1677 // MapMode, wie er beim Drucken herauskommen wuerde:
1678 pRefDev->SetMapMode( MapMode( MAP_100TH_MM, Point(), aPrintFrac, aPrintFrac ) );
1680 // when rendering (PDF), don't use printer as ref device, but printer's MapMode
1681 // has to be set anyway, as charts still use it (#106409#)
1682 if ( !bIsRender )
1683 aOutputData.SetRefDevice( pRefDev );
1686 // aOutputData.SetMetaFileMode(TRUE);
1687 if( aTableParam.bCellContent )
1688 aOutputData.DrawBackground();
1690 pDev->SetClipRegion( Rectangle( aPos, Size( aOutputData.GetScrW(), aOutputData.GetScrH() ) ) );
1691 pDev->SetClipRegion();
1693 // aOutputData.SetMetaFileMode(FALSE);
1694 if( aTableParam.bCellContent )
1696 aOutputData.DrawExtraShadow( bShLeft, bShTop, bShRight, bShBottom );
1697 aOutputData.DrawFrame();
1698 aOutputData.DrawStrings();
1700 // pDev->SetMapMode(aLogicMode);
1701 aOutputData.DrawEdit(FALSE);
1704 // pDev->SetMapMode(aOffsetMode);
1705 if (aTableParam.bGrid)
1706 aOutputData.DrawGrid( TRUE, FALSE ); // keine Seitenumbrueche
1708 /*!!!!!!!!!!! Notizen in Tabelle markieren ??????????????????????????
1710 if (aTableParam.bNotes)
1712 pDev->SetMapMode(aOffsetMode);
1713 aOutputData.PrintNoteMarks(aNotePosList);
1714 pDev->SetMapMode(aLogicMode);
1718 aOutputData.AddPDFNotes(); // has no effect if not rendering PDF with notes enabled
1720 // pDev->SetMapMode(aDrawMode);
1722 // test if all paint parts are hidden, then a paint is not necessary at all
1723 if(!bHideAllDrawingLayer)
1725 // #i72502#
1726 aOutputData.PrintDrawingLayer(SC_LAYER_FRONT, aMMOffset);
1729 // #i72502#
1730 aOutputData.PrintDrawingLayer(SC_LAYER_INTERN, aMMOffset);
1731 aOutputData.PostPrintDrawingLayer(aMMOffset); // #i74768#
1734 BOOL ScPrintFunc::IsMirror( long nPageNo ) // Raender spiegeln ?
1736 SvxPageUsage eUsage = (SvxPageUsage) ( nPageUsage & 0x000f );
1737 return ( eUsage == SVX_PAGE_MIRROR && (nPageNo & 1) );
1740 BOOL ScPrintFunc::IsLeft( long nPageNo ) // linke Fussnoten ?
1742 SvxPageUsage eUsage = (SvxPageUsage) ( nPageUsage & 0x000f );
1743 BOOL bLeft;
1744 if (eUsage == SVX_PAGE_LEFT)
1745 bLeft = TRUE;
1746 else if (eUsage == SVX_PAGE_RIGHT)
1747 bLeft = FALSE;
1748 else
1749 bLeft = (nPageNo & 1) != 0;
1750 return bLeft;
1753 void ScPrintFunc::MakeTableString()
1755 pDoc->GetName( nPrintTab, aFieldData.aTabName );
1758 void ScPrintFunc::MakeEditEngine()
1760 if (!pEditEngine)
1762 // can't use document's edit engine pool here,
1763 // because pool must have twips as default metric
1764 pEditEngine = new ScHeaderEditEngine( EditEngine::CreatePool(), TRUE );
1766 pEditEngine->EnableUndo(FALSE);
1767 pEditEngine->SetRefDevice( pDev );
1768 pEditEngine->SetWordDelimiters(
1769 ScEditUtil::ModifyDelimiters( pEditEngine->GetWordDelimiters() ) );
1770 pEditEngine->SetControlWord( pEditEngine->GetControlWord() & ~EE_CNTRL_RTFSTYLESHEETS );
1771 pEditEngine->EnableAutoColor( bUseStyleColor );
1773 // Default-Set fuer Ausrichtung
1774 pEditDefaults = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
1776 const ScPatternAttr& rPattern = (const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN);
1777 rPattern.FillEditItemSet( pEditDefaults );
1778 // FillEditItemSet adjusts font height to 1/100th mm,
1779 // but for header/footer twips is needed, as in the PatternAttr:
1780 pEditDefaults->Put( rPattern.GetItem(ATTR_FONT_HEIGHT), EE_CHAR_FONTHEIGHT );
1781 pEditDefaults->Put( rPattern.GetItem(ATTR_CJK_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CJK );
1782 pEditDefaults->Put( rPattern.GetItem(ATTR_CTL_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CTL );
1783 // #69193# dont use font color, because background color is not used
1784 //! there's no way to set the background for note pages
1785 pEditDefaults->ClearItem( EE_CHAR_COLOR );
1786 if (ScGlobal::IsSystemRTL())
1787 pEditDefaults->Put( SvxFrameDirectionItem( FRMDIR_HORI_RIGHT_TOP, EE_PARA_WRITINGDIR ) );
1790 pEditEngine->SetData( aFieldData ); // Seitennummer etc. setzen
1793 // nStartY = logic
1794 void ScPrintFunc::PrintHF( long nPageNo, BOOL bHeader, long nStartY,
1795 BOOL bDoPrint, ScPreviewLocationData* pLocationData )
1797 const ScPrintHFParam& rParam = bHeader ? aHdr : aFtr;
1799 pDev->SetMapMode( aTwipMode ); // Kopf-/Fusszeilen in Twips
1801 BOOL bLeft = IsLeft(nPageNo) && !rParam.bShared;
1802 const ScPageHFItem* pHFItem = bLeft ? rParam.pLeft : rParam.pRight;
1804 long nLineStartX = aPageRect.Left() + rParam.nLeft;
1805 long nLineEndX = aPageRect.Right() - rParam.nRight;
1806 long nLineWidth = nLineEndX - nLineStartX + 1;
1808 // Edit-Engine
1810 Point aStart( nLineStartX, nStartY );
1811 Size aPaperSize( nLineWidth, rParam.nHeight-rParam.nDistance );
1812 if ( rParam.pBorder )
1814 long nLeft = lcl_LineTotal( rParam.pBorder->GetLeft() ) + rParam.pBorder->GetDistance(BOX_LINE_LEFT);
1815 long nTop = lcl_LineTotal( rParam.pBorder->GetTop() ) + rParam.pBorder->GetDistance(BOX_LINE_TOP);
1816 aStart.X() += nLeft;
1817 aStart.Y() += nTop;
1818 aPaperSize.Width() -= nLeft + lcl_LineTotal( rParam.pBorder->GetRight() ) + rParam.pBorder->GetDistance(BOX_LINE_RIGHT);
1819 aPaperSize.Height() -= nTop + lcl_LineTotal( rParam.pBorder->GetBottom() ) + rParam.pBorder->GetDistance(BOX_LINE_BOTTOM);
1822 if ( rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE )
1824 long nLeft = rParam.pShadow->CalcShadowSpace(SHADOW_LEFT);
1825 long nTop = rParam.pShadow->CalcShadowSpace(SHADOW_TOP);
1826 aStart.X() += nLeft;
1827 aStart.Y() += nTop;
1828 aPaperSize.Width() -= nLeft + rParam.pShadow->CalcShadowSpace(SHADOW_RIGHT);
1829 aPaperSize.Height() -= nTop + rParam.pShadow->CalcShadowSpace(SHADOW_BOTTOM);
1832 aFieldData.nPageNo = nPageNo+aTableParam.nFirstPageNo;
1833 MakeEditEngine();
1835 pEditEngine->SetPaperSize(aPaperSize);
1836 const EditTextObject* pObject;
1838 // Rahmen / Hintergrund
1840 Point aBorderStart( nLineStartX, nStartY );
1841 Size aBorderSize( nLineWidth, rParam.nHeight-rParam.nDistance );
1842 if ( rParam.bDynamic )
1844 // hier nochmal anpassen, wegen geraden/ungeraden Kopf/Fusszeilen
1845 // und evtl. anderen Umbruechen durch Variablen (Seitennummer etc.)
1847 long nMaxHeight = 0;
1848 nMaxHeight = Max( nMaxHeight, TextHeight( pHFItem->GetLeftArea() ) );
1849 nMaxHeight = Max( nMaxHeight, TextHeight( pHFItem->GetCenterArea() ) );
1850 nMaxHeight = Max( nMaxHeight, TextHeight( pHFItem->GetRightArea() ) );
1851 if (rParam.pBorder)
1852 nMaxHeight += lcl_LineTotal( rParam.pBorder->GetTop() ) +
1853 lcl_LineTotal( rParam.pBorder->GetBottom() ) +
1854 rParam.pBorder->GetDistance(BOX_LINE_TOP) +
1855 rParam.pBorder->GetDistance(BOX_LINE_BOTTOM);
1856 if (rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE)
1857 nMaxHeight += rParam.pShadow->CalcShadowSpace(SHADOW_TOP) +
1858 rParam.pShadow->CalcShadowSpace(SHADOW_BOTTOM);
1860 if (nMaxHeight < rParam.nManHeight-rParam.nDistance)
1861 nMaxHeight = rParam.nManHeight-rParam.nDistance; // eingestelltes Minimum
1863 aBorderSize.Height() = nMaxHeight;
1866 if ( bDoPrint )
1868 double nOldScaleX = nScaleX;
1869 double nOldScaleY = nScaleY;
1870 nScaleX = nScaleY = 1.0; // direkt in Twips ausgeben
1871 DrawBorder( aBorderStart.X(), aBorderStart.Y(), aBorderSize.Width(), aBorderSize.Height(),
1872 rParam.pBorder, rParam.pBack, rParam.pShadow );
1873 nScaleX = nOldScaleX;
1874 nScaleY = nOldScaleY;
1876 // Clipping fuer Text
1878 pDev->SetClipRegion( Rectangle( aStart, aPaperSize ) );
1880 // links
1882 pObject = pHFItem->GetLeftArea();
1883 if (pObject)
1885 pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_LEFT, EE_PARA_JUST ) );
1886 pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, FALSE );
1887 Point aDraw = aStart;
1888 long nDif = aPaperSize.Height() - (long) pEditEngine->GetTextHeight();
1889 if (nDif > 0)
1890 aDraw.Y() += nDif / 2;
1891 pEditEngine->Draw( pDev, aDraw, 0 );
1894 // Mitte
1896 pObject = pHFItem->GetCenterArea();
1897 if (pObject)
1899 pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_CENTER, EE_PARA_JUST ) );
1900 pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, FALSE );
1901 Point aDraw = aStart;
1902 long nDif = aPaperSize.Height() - (long) pEditEngine->GetTextHeight();
1903 if (nDif > 0)
1904 aDraw.Y() += nDif / 2;
1905 pEditEngine->Draw( pDev, aDraw, 0 );
1908 // rechts
1910 pObject = pHFItem->GetRightArea();
1911 if (pObject)
1913 pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_RIGHT, EE_PARA_JUST ) );
1914 pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, FALSE );
1915 Point aDraw = aStart;
1916 long nDif = aPaperSize.Height() - (long) pEditEngine->GetTextHeight();
1917 if (nDif > 0)
1918 aDraw.Y() += nDif / 2;
1919 pEditEngine->Draw( pDev, aDraw, 0 );
1922 pDev->SetClipRegion();
1925 if ( pLocationData )
1927 Rectangle aHeaderRect( aBorderStart, aBorderSize );
1928 pLocationData->AddHeaderFooter( aHeaderRect, bHeader, bLeft );
1932 long ScPrintFunc::DoNotes( long nNoteStart, BOOL bDoPrint, ScPreviewLocationData* pLocationData )
1934 if (bDoPrint)
1935 pDev->SetMapMode(aTwipMode);
1937 MakeEditEngine();
1938 pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_LEFT, EE_PARA_JUST ) );
1939 pEditEngine->SetDefaults( *pEditDefaults );
1941 Font aMarkFont;
1942 ScAutoFontColorMode eColorMode = bUseStyleColor ? SC_AUTOCOL_DISPLAY : SC_AUTOCOL_PRINT;
1943 ((const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN)).GetFont( aMarkFont, eColorMode );
1944 //? aMarkFont.SetWeight( WEIGHT_BOLD );
1945 pDev->SetFont( aMarkFont );
1946 long nMarkLen = pDev->GetTextWidth(
1947 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("GW99999:")));
1948 // ohne Space, weil's eh selten so weit kommt
1950 Size aDataSize = aPageRect.GetSize();
1951 if ( nMarkLen > aDataSize.Width() / 2 ) // alles viel zu klein?
1952 nMarkLen = aDataSize.Width() / 2; // Seite bruederlich aufteilen
1953 aDataSize.Width() -= nMarkLen;
1955 pEditEngine->SetPaperSize( aDataSize );
1956 long nPosX = aPageRect.Left() + nMarkLen;
1957 long nPosY = aPageRect.Top();
1959 long nCount = 0;
1960 BOOL bOk;
1963 bOk = FALSE;
1964 ScAddress* pPos = (ScAddress*) aNotePosList.GetObject( nNoteStart+nCount );
1965 if (pPos)
1967 ScBaseCell* pCell = pDoc->GetCell( *pPos);
1968 if( const ScPostIt* pNote = pCell->GetNote() )
1970 if(const EditTextObject *pEditText = pNote->GetEditTextObject())
1971 pEditEngine->SetText(*pEditText);
1972 long nTextHeight = pEditEngine->GetTextHeight();
1973 if ( nPosY + nTextHeight < aPageRect.Bottom() )
1975 if (bDoPrint)
1977 pEditEngine->Draw( pDev, Point( nPosX, nPosY ), 0 );
1979 String aMarkStr;
1980 pPos->Format( aMarkStr, SCA_VALID, pDoc, pDoc->GetAddressConvention() );
1981 aMarkStr += ':';
1983 // Zellposition auch per EditEngine, damit die Position stimmt
1984 pEditEngine->SetText(aMarkStr);
1985 pEditEngine->Draw( pDev, Point( aPageRect.Left(), nPosY ), 0 );
1988 if ( pLocationData )
1990 Rectangle aTextRect( Point( nPosX, nPosY ), Size( aDataSize.Width(), nTextHeight ) );
1991 pLocationData->AddNoteText( aTextRect, *pPos );
1992 Rectangle aMarkRect( Point( aPageRect.Left(), nPosY ), Size( nMarkLen, nTextHeight ) );
1993 pLocationData->AddNoteMark( aMarkRect, *pPos );
1996 nPosY += nTextHeight;
1997 nPosY += 200; // Abstand
1998 ++nCount;
1999 bOk = TRUE;
2004 while (bOk);
2006 return nCount;
2009 long ScPrintFunc::PrintNotes( long nPageNo, long nNoteStart, BOOL bDoPrint, ScPreviewLocationData* pLocationData )
2011 if ( nNoteStart >= (long) aNotePosList.Count() || !aTableParam.bNotes )
2012 return 0;
2014 if ( bDoPrint && bClearWin )
2016 //! mit PrintPage zusammenfassen !!!
2018 Color aBackgroundColor( COL_WHITE );
2019 if ( bUseStyleColor )
2020 aBackgroundColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
2022 pDev->SetMapMode(aOffsetMode);
2023 pDev->SetLineColor();
2024 pDev->SetFillColor(aBackgroundColor);
2025 pDev->DrawRect(Rectangle(Point(),
2026 Size((long)(aPageSize.Width() * nScaleX * 100 / nZoom),
2027 (long)(aPageSize.Height() * nScaleY * 100 / nZoom))));
2031 // aPageRect auf linke / rechte Seiten anpassen
2033 Rectangle aTempRect = Rectangle( Point(), aPageSize );
2034 if (IsMirror(nPageNo))
2036 aPageRect.Left() = ( aTempRect.Left() + nRightMargin ) * 100 / nZoom;
2037 aPageRect.Right() = ( aTempRect.Right() - nLeftMargin ) * 100 / nZoom;
2039 else
2041 aPageRect.Left() = ( aTempRect.Left() + nLeftMargin ) * 100 / nZoom;
2042 aPageRect.Right() = ( aTempRect.Right() - nRightMargin ) * 100 / nZoom;
2045 if ( pPrinter && bDoPrint )
2046 pPrinter->StartPage();
2048 if ( bDoPrint || pLocationData )
2050 // Kopf- und Fusszeilen
2052 if (aHdr.bEnable)
2054 long nHeaderY = aPageRect.Top()-aHdr.nHeight;
2055 PrintHF( nPageNo, TRUE, nHeaderY, bDoPrint, pLocationData );
2057 if (aFtr.bEnable)
2059 long nFooterY = aPageRect.Bottom()+aFtr.nDistance;
2060 PrintHF( nPageNo, FALSE, nFooterY, bDoPrint, pLocationData );
2064 long nCount = DoNotes( nNoteStart, bDoPrint, pLocationData );
2066 if ( pPrinter && bDoPrint )
2067 pPrinter->EndPage();
2069 return nCount;
2072 void ScPrintFunc::PrintPage( long nPageNo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
2073 BOOL bDoPrint, ScPreviewLocationData* pLocationData )
2075 BOOL bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab );
2076 long nLayoutSign = bLayoutRTL ? -1 : 1;
2078 // nPageNo is the page number within all sheets of one "start page" setting
2080 if ( bClearWin && bDoPrint )
2082 // muss genau zum Zeichnen des Rahmens in preview.cxx passen !!!
2084 Color aBackgroundColor( COL_WHITE );
2085 if ( bUseStyleColor )
2086 aBackgroundColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
2088 pDev->SetMapMode(aOffsetMode);
2089 pDev->SetLineColor();
2090 pDev->SetFillColor(aBackgroundColor);
2091 pDev->DrawRect(Rectangle(Point(),
2092 Size((long)(aPageSize.Width() * nScaleX * 100 / nZoom),
2093 (long)(aPageSize.Height() * nScaleY * 100 / nZoom))));
2097 // aPageRect auf linke / rechte Seiten anpassen
2099 Rectangle aTempRect = Rectangle( Point(), aPageSize );
2100 if (IsMirror(nPageNo))
2102 aPageRect.Left() = ( aTempRect.Left() + nRightMargin ) * 100 / nZoom;
2103 aPageRect.Right() = ( aTempRect.Right() - nLeftMargin ) * 100 / nZoom;
2105 else
2107 aPageRect.Left() = ( aTempRect.Left() + nLeftMargin ) * 100 / nZoom;
2108 aPageRect.Right() = ( aTempRect.Right() - nRightMargin ) * 100 / nZoom;
2111 if ( aAreaParam.bRepeatCol )
2112 if ( nX1 > nRepeatStartCol && nX1 <= nRepeatEndCol )
2113 nX1 = nRepeatEndCol + 1;
2114 BOOL bDoRepCol = (aAreaParam.bRepeatCol && nX1 > nRepeatEndCol);
2115 if ( aAreaParam.bRepeatRow )
2116 if ( nY1 > nRepeatStartRow && nY1 <= nRepeatEndRow )
2117 nY1 = nRepeatEndRow + 1;
2118 BOOL bDoRepRow = (aAreaParam.bRepeatRow && nY1 > nRepeatEndRow);
2120 // use new object hide flags in SdrPaintView
2121 if(pDrawView)
2123 pDrawView->setHideOle(!aTableParam.bObjects);
2124 pDrawView->setHideChart(!aTableParam.bCharts);
2125 pDrawView->setHideDraw(!aTableParam.bDrawings);
2128 if ( pPrinter && bDoPrint )
2129 pPrinter->StartPage();
2131 // Kopf- und Fusszeilen (ohne Zentrierung)
2133 if (aHdr.bEnable)
2135 long nHeaderY = aPageRect.Top()-aHdr.nHeight;
2136 PrintHF( nPageNo, TRUE, nHeaderY, bDoPrint, pLocationData );
2138 if (aFtr.bEnable)
2140 long nFooterY = aPageRect.Bottom()+aFtr.nDistance;
2141 PrintHF( nPageNo, FALSE, nFooterY, bDoPrint, pLocationData );
2144 // Position ( Raender / zentrieren )
2146 long nLeftSpace = aPageRect.Left(); // Document-Twips
2147 long nTopSpace = aPageRect.Top();
2148 if ( bCenterHor || bLayoutRTL )
2150 long nDataWidth = 0;
2151 SCCOL i;
2152 for (i=nX1; i<=nX2; i++)
2153 nDataWidth += pDoc->GetColWidth( i,nPrintTab );
2154 if (bDoRepCol)
2155 for (i=nRepeatStartCol; i<=nRepeatEndCol; i++)
2156 nDataWidth += pDoc->GetColWidth( i,nPrintTab );
2157 if (aTableParam.bHeaders)
2158 nDataWidth += (long) PRINT_HEADER_WIDTH;
2159 if (pBorderItem)
2160 nDataWidth += pBorderItem->GetDistance(BOX_LINE_LEFT) +
2161 pBorderItem->GetDistance(BOX_LINE_RIGHT); //! Line width?
2162 if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
2163 nDataWidth += pShadowItem->CalcShadowSpace(SHADOW_LEFT) +
2164 pShadowItem->CalcShadowSpace(SHADOW_RIGHT);
2165 if ( bCenterHor )
2167 nLeftSpace += ( aPageRect.GetWidth() - nDataWidth ) / 2; // LTR or RTL
2168 if (pBorderItem)
2169 nLeftSpace -= lcl_LineTotal(pBorderItem->GetLeft());
2171 else if ( bLayoutRTL )
2172 nLeftSpace += aPageRect.GetWidth() - nDataWidth; // align to the right edge of the page
2174 if ( bCenterVer )
2176 long nDataHeight = pDoc->FastGetRowHeight( nY1, nY2, nPrintTab);
2177 if (bDoRepRow)
2178 nDataHeight += pDoc->FastGetRowHeight( nRepeatStartRow,
2179 nRepeatEndRow, nPrintTab);
2180 if (aTableParam.bHeaders)
2181 nDataHeight += (long) PRINT_HEADER_HEIGHT;
2182 if (pBorderItem)
2183 nDataHeight += pBorderItem->GetDistance(BOX_LINE_TOP) +
2184 pBorderItem->GetDistance(BOX_LINE_BOTTOM); //! Line width?
2185 if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
2186 nDataHeight += pShadowItem->CalcShadowSpace(SHADOW_TOP) +
2187 pShadowItem->CalcShadowSpace(SHADOW_BOTTOM);
2188 nTopSpace += ( aPageRect.GetHeight() - nDataHeight ) / 2;
2189 if (pBorderItem)
2190 nTopSpace -= lcl_LineTotal(pBorderItem->GetTop());
2193 // calculate sizes of the elements for partitioning
2194 // (header, repeat, data)
2196 long nHeaderWidth = 0;
2197 long nHeaderHeight = 0;
2198 long nRepeatWidth = 0;
2199 long nRepeatHeight = 0;
2200 long nContentWidth = 0; // scaled - not the same as nDataWidth above
2201 long nContentHeight = 0;
2202 if (aTableParam.bHeaders)
2204 nHeaderWidth = (long) (PRINT_HEADER_WIDTH * nScaleX);
2205 nHeaderHeight = (long) (PRINT_HEADER_HEIGHT * nScaleY);
2207 if (bDoRepCol)
2208 for (SCCOL i=nRepeatStartCol; i<=nRepeatEndCol; i++)
2209 nRepeatWidth += (long) (pDoc->GetColWidth(i,nPrintTab) * nScaleX);
2210 if (bDoRepRow)
2211 nRepeatHeight += pDoc->FastGetScaledRowHeight( nRepeatStartRow,
2212 nRepeatEndRow, nPrintTab, nScaleY);
2213 for (SCCOL i=nX1; i<=nX2; i++)
2214 nContentWidth += (long) (pDoc->GetColWidth(i,nPrintTab) * nScaleX);
2215 nContentHeight += pDoc->FastGetScaledRowHeight( nY1, nY2, nPrintTab,
2216 nScaleY);
2218 // partition the page
2220 long nStartX = ((long) ( nLeftSpace * nScaleX ));
2221 long nStartY = ((long) ( nTopSpace * nScaleY ));
2222 // nStartX -= aOffset.X(); // schon im MapMode
2223 // nStartY -= aOffset.Y();
2225 long nInnerStartX = nStartX;
2226 long nInnerStartY = nStartY;
2227 if (pBorderItem)
2229 nInnerStartX += (long) ( ( lcl_LineTotal(pBorderItem->GetLeft()) +
2230 pBorderItem->GetDistance(BOX_LINE_LEFT) ) * nScaleX );
2231 nInnerStartY += (long) ( ( lcl_LineTotal(pBorderItem->GetTop()) +
2232 pBorderItem->GetDistance(BOX_LINE_TOP) ) * nScaleY );
2234 if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
2236 nInnerStartX += (long) ( pShadowItem->CalcShadowSpace(SHADOW_LEFT) * nScaleX );
2237 nInnerStartY += (long) ( pShadowItem->CalcShadowSpace(SHADOW_TOP) * nScaleY );
2240 if ( bLayoutRTL )
2242 // arrange elements starting from the right edge
2243 nInnerStartX += nHeaderWidth + nRepeatWidth + nContentWidth;
2245 // make rounding easier so the elements are really next to each other in preview
2246 Size aOffsetOnePixel = pDev->PixelToLogic( Size(1,1), aOffsetMode );
2247 long nOffsetOneX = aOffsetOnePixel.Width();
2248 nInnerStartX += nOffsetOneX / 2;
2251 long nFrameStartX = nInnerStartX;
2252 long nFrameStartY = nInnerStartY;
2254 long nRepStartX = nInnerStartX + nHeaderWidth * nLayoutSign; // widths/heights are 0 if not used
2255 long nRepStartY = nInnerStartY + nHeaderHeight;
2256 long nDataX = nRepStartX + nRepeatWidth * nLayoutSign;
2257 long nDataY = nRepStartY + nRepeatHeight;
2258 long nEndX = nDataX + nContentWidth * nLayoutSign;
2259 long nEndY = nDataY + nContentHeight;
2260 long nFrameEndX = nEndX;
2261 long nFrameEndY = nEndY;
2263 if ( bLayoutRTL )
2265 // each element's start position is its left edge
2266 //! subtract one pixel less?
2267 nInnerStartX -= nHeaderWidth; // used for header
2268 nRepStartX -= nRepeatWidth;
2269 nDataX -= nContentWidth;
2271 // continue right of the main elements again
2272 nEndX += nHeaderWidth + nRepeatWidth + nContentWidth;
2275 // Seiten-Rahmen / Hintergrund
2277 //! nEndX/Y anpassen
2279 long nBorderEndX = nEndX;
2280 long nBorderEndY = nEndY;
2281 if (pBorderItem)
2283 nBorderEndX += (long) ( ( lcl_LineTotal(pBorderItem->GetRight()) +
2284 pBorderItem->GetDistance(BOX_LINE_RIGHT) ) * nScaleX );
2285 nBorderEndY += (long) ( ( lcl_LineTotal(pBorderItem->GetBottom()) +
2286 pBorderItem->GetDistance(BOX_LINE_BOTTOM) ) * nScaleY );
2288 if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
2290 nBorderEndX += (long) ( pShadowItem->CalcShadowSpace(SHADOW_RIGHT) * nScaleX );
2291 nBorderEndY += (long) ( pShadowItem->CalcShadowSpace(SHADOW_BOTTOM) * nScaleY );
2294 if ( bDoPrint )
2296 pDev->SetMapMode( aOffsetMode );
2297 DrawBorder( nStartX, nStartY, nBorderEndX-nStartX, nBorderEndY-nStartY,
2298 pBorderItem, pBackgroundItem, pShadowItem );
2300 pDev->SetMapMode( aTwipMode );
2303 pDev->SetMapMode( aOffsetMode );
2305 // Wiederholungszeilen/Spalten ausgeben
2307 if (bDoRepCol && bDoRepRow)
2309 if ( bDoPrint )
2310 PrintArea( nRepeatStartCol,nRepeatStartRow, nRepeatEndCol,nRepeatEndRow,
2311 nRepStartX,nRepStartY, TRUE,TRUE,FALSE,FALSE );
2312 if ( pLocationData )
2313 LocateArea( nRepeatStartCol,nRepeatStartRow, nRepeatEndCol,nRepeatEndRow,
2314 nRepStartX,nRepStartY, TRUE,TRUE, *pLocationData );
2316 if (bDoRepCol)
2318 if ( bDoPrint )
2319 PrintArea( nRepeatStartCol,nY1, nRepeatEndCol,nY2, nRepStartX,nDataY,
2320 TRUE,!bDoRepRow,FALSE,TRUE );
2321 if ( pLocationData )
2322 LocateArea( nRepeatStartCol,nY1, nRepeatEndCol,nY2, nRepStartX,nDataY, TRUE,FALSE, *pLocationData );
2324 if (bDoRepRow)
2326 if ( bDoPrint )
2327 PrintArea( nX1,nRepeatStartRow, nX2,nRepeatEndRow, nDataX,nRepStartY,
2328 !bDoRepCol,TRUE,TRUE,FALSE );
2329 if ( pLocationData )
2330 LocateArea( nX1,nRepeatStartRow, nX2,nRepeatEndRow, nDataX,nRepStartY, FALSE,TRUE, *pLocationData );
2333 // Daten ausgeben
2335 if ( bDoPrint )
2336 PrintArea( nX1,nY1, nX2,nY2, nDataX,nDataY, !bDoRepCol,!bDoRepRow,TRUE,TRUE );
2337 if ( pLocationData )
2338 LocateArea( nX1,nY1, nX2,nY2, nDataX,nDataY, FALSE,FALSE, *pLocationData );
2340 // Spalten-/Zeilenkoepfe ausgeben
2341 // nach den Daten (ueber evtl. weitergezeichneten Schatten)
2343 Color aGridColor( COL_BLACK );
2344 if ( bUseStyleColor )
2345 aGridColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
2347 if (aTableParam.bHeaders)
2349 if ( bDoPrint )
2351 pDev->SetLineColor( aGridColor );
2352 pDev->SetFillColor();
2353 pDev->SetMapMode(aOffsetMode);
2356 ScPatternAttr aPattern( pDoc->GetPool() );
2357 Font aFont;
2358 ScAutoFontColorMode eColorMode = bUseStyleColor ? SC_AUTOCOL_DISPLAY : SC_AUTOCOL_PRINT;
2359 aPattern.GetFont( aFont, eColorMode, pDev );
2360 pDev->SetFont( aFont );
2362 if (bDoRepCol)
2364 if ( bDoPrint )
2365 PrintColHdr( nRepeatStartCol,nRepeatEndCol, nRepStartX,nInnerStartY );
2366 if ( pLocationData )
2367 LocateColHdr( nRepeatStartCol,nRepeatEndCol, nRepStartX,nInnerStartY, TRUE, *pLocationData );
2369 if ( bDoPrint )
2370 PrintColHdr( nX1,nX2, nDataX,nInnerStartY );
2371 if ( pLocationData )
2372 LocateColHdr( nX1,nX2, nDataX,nInnerStartY, FALSE, *pLocationData );
2373 if (bDoRepRow)
2375 if ( bDoPrint )
2376 PrintRowHdr( nRepeatStartRow,nRepeatEndRow, nInnerStartX,nRepStartY );
2377 if ( pLocationData )
2378 LocateRowHdr( nRepeatStartRow,nRepeatEndRow, nInnerStartX,nRepStartY, TRUE, *pLocationData );
2380 if ( bDoPrint )
2381 PrintRowHdr( nY1,nY2, nInnerStartX,nDataY );
2382 if ( pLocationData )
2383 LocateRowHdr( nY1,nY2, nInnerStartX,nDataY, FALSE, *pLocationData );
2386 // einfacher Rahmen
2388 if ( bDoPrint && ( aTableParam.bGrid || aTableParam.bHeaders ) )
2390 Size aOnePixel = pDev->PixelToLogic(Size(1,1));
2391 long nOneX = aOnePixel.Width();
2392 long nOneY = aOnePixel.Height();
2394 long nLeftX = nFrameStartX;
2395 long nTopY = nFrameStartY - nOneY;
2396 long nRightX = nFrameEndX;
2397 long nBottomY = nFrameEndY - nOneY;
2398 if ( !bLayoutRTL )
2400 nLeftX -= nOneX;
2401 nRightX -= nOneX;
2403 pDev->SetMapMode(aOffsetMode);
2404 pDev->SetLineColor( aGridColor );
2405 pDev->SetFillColor();
2406 pDev->DrawRect( Rectangle( nLeftX, nTopY, nRightX, nBottomY ) );
2407 // nEndX/Y ohne Rahmen-Anpassung
2410 if ( pPrinter && bDoPrint )
2411 pPrinter->EndPage();
2413 aLastSourceRange = ScRange( nX1, nY1, nPrintTab, nX2, nY2, nPrintTab );
2414 bSourceRangeValid = TRUE;
2417 void ScPrintFunc::SetOffset( const Point& rOfs )
2419 aSrcOffset = rOfs;
2422 void ScPrintFunc::SetManualZoom( USHORT nNewZoom )
2424 nManualZoom = nNewZoom;
2427 void ScPrintFunc::SetClearFlag( BOOL bFlag )
2429 bClearWin = bFlag;
2432 void ScPrintFunc::SetUseStyleColor( BOOL bFlag )
2434 bUseStyleColor = bFlag;
2435 if (pEditEngine)
2436 pEditEngine->EnableAutoColor( bUseStyleColor );
2439 void ScPrintFunc::SetRenderFlag( BOOL bFlag )
2441 bIsRender = bFlag; // set when using XRenderable (PDF)
2444 void ScPrintFunc::SetExclusivelyDrawOleAndDrawObjects()
2446 aTableParam.bCellContent = false;
2447 aTableParam.bNotes = false;
2448 aTableParam.bGrid = false;
2449 aTableParam.bHeaders = false;
2450 aTableParam.bFormulas = false;;
2451 aTableParam.bNullVals = false;;
2452 aTableParam.bNullVals = false;;
2456 // UpdatePages wird nur von aussen gerufen, um die Umbrueche fuer die Anzeige
2457 // richtig zu setzen - immer ohne UserArea
2460 BOOL ScPrintFunc::UpdatePages()
2462 if (!pParamSet)
2463 return FALSE;
2465 // Zoom
2467 nZoom = 100;
2468 if (aTableParam.bScalePageNum || aTableParam.bScaleTo)
2469 nZoom = ZOOM_MIN; // stimmt fuer Umbrueche
2470 else if (aTableParam.bScaleAll)
2472 nZoom = aTableParam.nScaleAll;
2473 if ( nZoom <= ZOOM_MIN )
2474 nZoom = ZOOM_MIN;
2477 String aName = pDoc->GetPageStyle( nPrintTab );
2478 SCTAB nTabCount = pDoc->GetTableCount();
2479 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
2480 if ( nTab==nPrintTab || pDoc->GetPageStyle(nTab)==aName )
2482 // Wiederholungszeilen / Spalten
2483 pDoc->SetRepeatArea( nTab, nRepeatStartCol,nRepeatEndCol, nRepeatStartRow,nRepeatEndRow );
2485 // Umbrueche setzen
2486 ResetBreaks(nTab);
2487 pDocShell->PostPaint(0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID);
2490 return TRUE;
2493 long ScPrintFunc::CountPages() // setzt auch nPagesX, nPagesY
2495 BOOL bAreaOk = FALSE;
2497 if (pDoc->HasTable( nPrintTab ))
2499 if (aAreaParam.bPrintArea) // Druckbereich angegeben?
2501 if ( bPrintCurrentTable )
2503 ScRange& rRange = aAreaParam.aPrintArea;
2505 // hier kein Vergleich der Tabellen mehr, die Area gilt immer fuer diese Tabelle
2506 // wenn hier verglichen werden soll, muss die Tabelle der Druckbereiche beim
2507 // Einfuegen von Tabellen etc. angepasst werden !
2509 nStartCol = rRange.aStart.Col();
2510 nStartRow = rRange.aStart.Row();
2511 nEndCol = rRange.aEnd .Col();
2512 nEndRow = rRange.aEnd .Row();
2513 bAreaOk = AdjustPrintArea(FALSE); // begrenzen
2515 else
2516 bAreaOk = FALSE;
2518 else // aus Dokument suchen
2519 bAreaOk = AdjustPrintArea(TRUE);
2522 if (bAreaOk)
2524 long nPages = 0;
2525 size_t nY;
2526 if (bMultiArea)
2528 USHORT nRCount = pDoc->GetPrintRangeCount( nPrintTab );
2529 for (USHORT i=0; i<nRCount; i++)
2531 CalcZoom(i);
2532 if ( aTableParam.bSkipEmpty )
2533 for (nY=0; nY<nPagesY; nY++)
2534 nPages += pPageRows[nY].CountVisible();
2535 else
2536 nPages += ((long) nPagesX) * nPagesY;
2537 if ( pPageData )
2538 FillPageData();
2541 else
2543 CalcZoom(RANGENO_NORANGE); // Zoom berechnen
2544 if ( aTableParam.bSkipEmpty )
2545 for (nY=0; nY<nPagesY; nY++)
2546 nPages += pPageRows[nY].CountVisible();
2547 else
2548 nPages += ((long) nPagesX) * nPagesY;
2549 if ( pPageData )
2550 FillPageData();
2552 return nPages;
2554 else
2556 // nZoom = 100; // nZoom auf letztem Wert stehenlassen !!!
2557 nPagesX = nPagesY = nTotalY = 0;
2558 return 0;
2562 long ScPrintFunc::CountNotePages()
2564 if ( !aTableParam.bNotes || !bPrintCurrentTable )
2565 return 0;
2567 long nCount=0;
2568 SCCOL nCol;
2569 SCROW nRow;
2571 BOOL bError = FALSE;
2572 if (!aAreaParam.bPrintArea)
2573 bError = !AdjustPrintArea(TRUE); // komplett aus Dok suchen
2575 USHORT nRepeats = 1; // wie oft durchgehen ?
2576 if (bMultiArea)
2577 nRepeats = pDoc->GetPrintRangeCount(nPrintTab);
2578 if (bError)
2579 nRepeats = 0;
2581 for (USHORT nStep=0; nStep<nRepeats; nStep++)
2583 BOOL bDoThis = TRUE;
2584 if (bMultiArea) // alle Areas durchgehen
2586 const ScRange* pThisRange = pDoc->GetPrintRange( nPrintTab, nStep );
2587 if ( pThisRange )
2589 nStartCol = pThisRange->aStart.Col();
2590 nStartRow = pThisRange->aStart.Row();
2591 nEndCol = pThisRange->aEnd .Col();
2592 nEndRow = pThisRange->aEnd .Row();
2593 bDoThis = AdjustPrintArea(FALSE);
2597 if (bDoThis)
2599 ScHorizontalCellIterator aIter( pDoc, nPrintTab, nStartCol,nStartRow, nEndCol,nEndRow );
2600 ScBaseCell* pCell = aIter.GetNext( nCol, nRow );
2601 while (pCell)
2603 if (pCell->HasNote())
2605 aNotePosList.Insert( new ScAddress( nCol,nRow,nPrintTab ), LIST_APPEND );
2606 ++nCount;
2609 pCell = aIter.GetNext( nCol, nRow );
2614 long nPages = 0;
2615 long nNoteNr = 0;
2616 long nNoteAdd;
2619 nNoteAdd = PrintNotes( nPages, nNoteNr, FALSE, NULL );
2620 if (nNoteAdd)
2622 nNoteNr += nNoteAdd;
2623 ++nPages;
2626 while (nNoteAdd);
2628 return nPages;
2631 void ScPrintFunc::InitModes() // aus nZoom etc. die MapModes setzen
2633 aOffset = Point( aSrcOffset.X()*100/nZoom, aSrcOffset.Y()*100/nZoom );
2635 long nEffZoom = nZoom * (long) nManualZoom;
2637 // nScaleX = nScaleY = 1.0; // Ausgabe in Twips
2638 nScaleX = nScaleY = HMM_PER_TWIPS; // Ausgabe in 1/100 mm
2640 Fraction aZoomFract( nEffZoom,10000 );
2641 Fraction aHorFract = aZoomFract;
2643 if ( !pPrinter && !bIsRender ) // adjust scale for preview
2645 double nFact = pDocShell->GetOutputFactor();
2646 aHorFract = Fraction( (long)( nEffZoom / nFact ), 10000 );
2649 aLogicMode = MapMode( MAP_100TH_MM, Point(), aHorFract, aZoomFract );
2651 Point aLogicOfs( -aOffset.X(), -aOffset.Y() );
2652 aOffsetMode = MapMode( MAP_100TH_MM, aLogicOfs, aHorFract, aZoomFract );
2654 Point aTwipsOfs( (long) ( -aOffset.X() / nScaleX + 0.5 ), (long) ( -aOffset.Y() / nScaleY + 0.5 ) );
2655 aTwipMode = MapMode( MAP_TWIP, aTwipsOfs, aHorFract, aZoomFract );
2658 //--------------------------------------------------------------------
2660 void ScPrintFunc::ApplyPrintSettings()
2662 if ( pPrinter )
2665 // Printer zum Drucken umstellen
2668 Size aEnumSize = aPageSize;
2671 pPrinter->SetOrientation( bLandscape ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT );
2672 if ( bLandscape )
2674 // landscape is always interpreted as a rotation by 90 degrees !
2675 // this leads to non WYSIWIG but at least it prints!
2676 // #i21775#
2677 long nTemp = aEnumSize.Width();
2678 aEnumSize.Width() = aEnumSize.Height();
2679 aEnumSize.Height() = nTemp;
2681 Paper ePaper = SvxPaperInfo::GetSvxPaper( aEnumSize, MAP_TWIP, TRUE );
2682 USHORT nPaperBin = ((const SvxPaperBinItem&)pParamSet->Get(ATTR_PAGE_PAPERBIN)).GetValue();
2684 pPrinter->SetPaper( ePaper );
2685 if ( PAPER_USER == ePaper )
2687 MapMode aPrinterMode = pPrinter->GetMapMode();
2688 MapMode aLocalMode( MAP_TWIP );
2689 pPrinter->SetMapMode( aLocalMode );
2690 pPrinter->SetPaperSizeUser( aEnumSize );
2691 pPrinter->SetMapMode( aPrinterMode );
2694 pPrinter->SetPaperBin( nPaperBin );
2698 //--------------------------------------------------------------------
2699 // rPageRanges = Range fuer alle Tabellen
2700 // nStartPage = in rPageRanges beginnen bei nStartPage
2701 // nDisplayStart = lfd. Nummer fuer Anzeige der Seitennummer
2703 long ScPrintFunc::DoPrint( const MultiSelection& rPageRanges,
2704 long nStartPage, long nDisplayStart, BOOL bDoPrint,
2705 SfxProgress* pProgress, ScPreviewLocationData* pLocationData )
2707 DBG_ASSERT(pDev,"Device == NULL");
2708 if (!pParamSet)
2709 return 0;
2711 if ( pPrinter && bDoPrint )
2712 ApplyPrintSettings();
2714 //--------------------------------------------------------------------
2716 InitModes();
2717 if ( pLocationData )
2719 pLocationData->SetCellMapMode( aOffsetMode );
2720 pLocationData->SetPrintTab( nPrintTab );
2723 MakeTableString();
2725 if ( pProgress )
2726 pProgress->SetText( String( ScResId( SCSTR_STAT_PRINT ) ) );
2728 //--------------------------------------------------------------------
2730 long nPageNo = 0;
2731 long nPrinted = 0;
2732 long nEndPage = rPageRanges.GetTotalRange().Max();
2734 USHORT nRepeats = 1; // wie oft durchgehen ?
2735 if (bMultiArea)
2736 nRepeats = pDoc->GetPrintRangeCount(nPrintTab);
2737 for (USHORT nStep=0; nStep<nRepeats; nStep++)
2739 if (bMultiArea) // Bereich neu belegen ?
2741 CalcZoom(nStep); // setzt auch nStartCol etc. neu
2742 InitModes();
2745 SCCOL nX1;
2746 SCROW nY1;
2747 SCCOL nX2;
2748 SCROW nY2;
2749 size_t nCountX;
2750 size_t nCountY;
2752 if (aTableParam.bTopDown) // von oben nach unten
2754 nX1 = nStartCol;
2755 for (nCountX=0; nCountX<nPagesX; nCountX++)
2757 nX2 = pPageEndX[nCountX];
2758 for (nCountY=0; nCountY<nPagesY; nCountY++)
2760 nY1 = pPageRows[nCountY].GetStartRow();
2761 nY2 = pPageRows[nCountY].GetEndRow();
2762 if ( !aTableParam.bSkipEmpty || !pPageRows[nCountY].IsHidden(nCountX) )
2764 if ( rPageRanges.IsSelected( nPageNo+nStartPage+1 ) )
2766 PrintPage( nPageNo+nDisplayStart, nX1, nY1, nX2, nY2,
2767 bDoPrint, pLocationData );
2769 if ( pProgress )
2771 pProgress->SetState( nPageNo+nStartPage+1, nEndPage );
2772 pProgress->Reschedule(); //Mag der Anwender noch oder hat er genug?
2774 ++nPrinted;
2776 ++nPageNo;
2779 nX1 = nX2 + 1;
2782 else // von links nach rechts
2784 for (nCountY=0; nCountY<nPagesY; nCountY++)
2786 nY1 = pPageRows[nCountY].GetStartRow();
2787 nY2 = pPageRows[nCountY].GetEndRow();
2788 nX1 = nStartCol;
2789 for (nCountX=0; nCountX<nPagesX; nCountX++)
2791 nX2 = pPageEndX[nCountX];
2792 if ( !aTableParam.bSkipEmpty || !pPageRows[nCountY].IsHidden(nCountX) )
2794 if ( rPageRanges.IsSelected( nPageNo+nStartPage+1 ) )
2796 PrintPage( nPageNo+nDisplayStart, nX1, nY1, nX2, nY2,
2797 bDoPrint, pLocationData );
2799 if ( pProgress )
2801 pProgress->SetState( nPageNo+nStartPage+1, nEndPage );
2802 pProgress->Reschedule(); //Mag der Anwender noch oder hat er genug?
2804 ++nPrinted;
2806 ++nPageNo;
2808 nX1 = nX2 + 1;
2814 aFieldData.aTabName = ScGlobal::GetRscString( STR_NOTES );
2816 long nNoteNr = 0;
2817 long nNoteAdd;
2820 if ( nPageNo+nStartPage <= nEndPage )
2822 BOOL bPageSelected = rPageRanges.IsSelected( nPageNo+nStartPage+1 );
2823 nNoteAdd = PrintNotes( nPageNo+nStartPage, nNoteNr, bDoPrint && bPageSelected,
2824 ( bPageSelected ? pLocationData : NULL ) );
2825 if ( nNoteAdd )
2827 nNoteNr += nNoteAdd;
2828 if ( pProgress && bPageSelected )
2830 pProgress->SetState( nPageNo+nStartPage+1, nEndPage );
2831 pProgress->Reschedule(); //Mag der Anwender noch oder hat er genug?
2833 if (bPageSelected)
2835 ++nPrinted;
2836 bSourceRangeValid = FALSE; // last page was no cell range
2838 ++nPageNo;
2841 else
2842 nNoteAdd = 0;
2844 while (nNoteAdd);
2846 if ( bMultiArea )
2847 ResetBreaks(nPrintTab); // Breaks fuer Anzeige richtig
2849 return nPrinted;
2852 void ScPrintFunc::CalcZoom( USHORT nRangeNo ) // Zoom berechnen
2854 USHORT nRCount = pDoc->GetPrintRangeCount( nPrintTab );
2855 const ScRange* pThisRange = NULL;
2856 if ( nRangeNo != RANGENO_NORANGE || nRangeNo < nRCount )
2857 pThisRange = pDoc->GetPrintRange( nPrintTab, nRangeNo );
2858 if ( pThisRange )
2860 nStartCol = pThisRange->aStart.Col();
2861 nStartRow = pThisRange->aStart.Row();
2862 nEndCol = pThisRange->aEnd .Col();
2863 nEndRow = pThisRange->aEnd .Row();
2866 if (!AdjustPrintArea(FALSE)) // leer
2868 nZoom = 100;
2869 nPagesX = nPagesY = nTotalY = 0;
2870 return;
2873 pDoc->SetRepeatArea( nPrintTab, nRepeatStartCol,nRepeatEndCol, nRepeatStartRow,nRepeatEndRow );
2875 if (aTableParam.bScalePageNum)
2877 nZoom = 100;
2878 USHORT nPagesToFit = aTableParam.nScalePageNum;
2880 sal_uInt16 nLastFitZoom = 0, nLastNonFitZoom = 0;
2881 while (true)
2883 if (nZoom <= ZOOM_MIN)
2884 break;
2886 CalcPages();
2887 bool bFitsPage = (nPagesX * nPagesY <= nPagesToFit);
2889 if (bFitsPage)
2891 if (nZoom == 100)
2892 // If it fits at 100 %, it's good enough for me.
2893 break;
2895 nLastFitZoom = nZoom;
2896 nZoom = (nLastNonFitZoom + nZoom) / 2;
2898 if (nLastFitZoom == nZoom)
2899 // It converged. Use this zoom level.
2900 break;
2902 else
2904 if (nZoom - nLastFitZoom <= 1)
2906 nZoom = nLastFitZoom;
2907 CalcPages();
2908 break;
2911 nLastNonFitZoom = nZoom;
2912 nZoom = (nLastFitZoom + nZoom) / 2;
2916 else if (aTableParam.bScaleTo)
2918 nZoom = 100;
2919 USHORT nW = aTableParam.nScaleWidth;
2920 USHORT nH = aTableParam.nScaleHeight;
2922 sal_uInt16 nLastFitZoom = 0, nLastNonFitZoom = 0;
2923 while (true)
2925 if (nZoom <= ZOOM_MIN)
2926 break;
2928 CalcPages();
2929 bool bFitsPage = ((!nW || (nPagesX <= nW)) && (!nH || (nPagesY <= nH)));
2931 if (bFitsPage)
2933 if (nZoom == 100)
2934 // If it fits at 100 %, it's good enough for me.
2935 break;
2937 nLastFitZoom = nZoom;
2938 nZoom = (nLastNonFitZoom + nZoom) / 2;
2940 if (nLastFitZoom == nZoom)
2941 // It converged. Use this zoom level.
2942 break;
2944 else
2946 if (nZoom - nLastFitZoom <= 1)
2948 nZoom = nLastFitZoom;
2949 CalcPages();
2950 break;
2953 nLastNonFitZoom = nZoom;
2954 nZoom = (nLastFitZoom + nZoom) / 2;
2958 else if (aTableParam.bScaleAll)
2960 nZoom = aTableParam.nScaleAll;
2961 if ( nZoom <= ZOOM_MIN )
2962 nZoom = ZOOM_MIN;
2963 CalcPages();
2965 else
2967 DBG_ASSERT( aTableParam.bScaleNone, "kein Scale-Flag gesetzt" );
2968 nZoom = 100;
2969 CalcPages();
2973 Size ScPrintFunc::GetDocPageSize()
2975 // Hoehe Kopf-/Fusszeile anpassen
2977 InitModes(); // aTwipMode aus nZoom initialisieren
2978 pDev->SetMapMode( aTwipMode ); // Kopf-/Fusszeilen in Twips
2979 UpdateHFHeight( aHdr );
2980 UpdateHFHeight( aFtr );
2982 // Seitengroesse in Document-Twips
2983 // Berechnung Left / Right auch in PrintPage
2985 aPageRect = Rectangle( Point(), aPageSize );
2986 aPageRect.Left() = ( aPageRect.Left() + nLeftMargin ) * 100 / nZoom;
2987 aPageRect.Right() = ( aPageRect.Right() - nRightMargin ) * 100 / nZoom;
2988 aPageRect.Top() = ( aPageRect.Top() + nTopMargin ) * 100 / nZoom + aHdr.nHeight;
2989 aPageRect.Bottom() = ( aPageRect.Bottom() - nBottomMargin ) * 100 / nZoom - aFtr.nHeight;
2991 Size aDocPageSize = aPageRect.GetSize();
2992 if (aTableParam.bHeaders)
2994 aDocPageSize.Width() -= (long) PRINT_HEADER_WIDTH;
2995 aDocPageSize.Height() -= (long) PRINT_HEADER_HEIGHT;
2997 if (pBorderItem)
2999 aDocPageSize.Width() -= lcl_LineTotal(pBorderItem->GetLeft()) +
3000 lcl_LineTotal(pBorderItem->GetRight()) +
3001 pBorderItem->GetDistance(BOX_LINE_LEFT) +
3002 pBorderItem->GetDistance(BOX_LINE_RIGHT);
3003 aDocPageSize.Height() -= lcl_LineTotal(pBorderItem->GetTop()) +
3004 lcl_LineTotal(pBorderItem->GetBottom()) +
3005 pBorderItem->GetDistance(BOX_LINE_TOP) +
3006 pBorderItem->GetDistance(BOX_LINE_BOTTOM);
3008 if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
3010 aDocPageSize.Width() -= pShadowItem->CalcShadowSpace(SHADOW_LEFT) +
3011 pShadowItem->CalcShadowSpace(SHADOW_RIGHT);
3012 aDocPageSize.Height() -= pShadowItem->CalcShadowSpace(SHADOW_TOP) +
3013 pShadowItem->CalcShadowSpace(SHADOW_BOTTOM);
3015 return aDocPageSize;
3018 void ScPrintFunc::ResetBreaks( SCTAB nTab ) // Breaks fuer Anzeige richtig setzen
3020 pDoc->SetPageSize( nTab, GetDocPageSize() );
3021 pDoc->UpdatePageBreaks( nTab, NULL );
3024 void lcl_SetHidden( ScDocument* pDoc, SCTAB nPrintTab, ScPageRowEntry& rPageRowEntry,
3025 SCCOL nStartCol, const SCCOL* pPageEndX )
3027 size_t nPagesX = rPageRowEntry.GetPagesX();
3028 SCROW nStartRow = rPageRowEntry.GetStartRow();
3029 SCROW nEndRow = rPageRowEntry.GetEndRow();
3031 BOOL bLeftIsEmpty = FALSE;
3032 ScRange aTempRange;
3033 Rectangle aTempRect = pDoc->GetMMRect( 0,0, 0,0, 0 );
3035 for (size_t i=0; i<nPagesX; i++)
3037 SCCOL nEndCol = pPageEndX[i];
3038 if ( pDoc->IsPrintEmpty( nPrintTab, nStartCol, nStartRow, nEndCol, nEndRow,
3039 bLeftIsEmpty, &aTempRange, &aTempRect ) )
3041 rPageRowEntry.SetHidden(i);
3042 bLeftIsEmpty = TRUE;
3044 else
3045 bLeftIsEmpty = FALSE;
3047 nStartCol = nEndCol+1;
3051 void ScPrintFunc::CalcPages() // berechnet aPageRect und Seiten aus nZoom
3053 if (!pPageEndX) pPageEndX = new SCCOL[MAXCOL+1];
3054 if (!pPageEndY) pPageEndY = new SCROW[MAXROW+1];
3055 if (!pPageRows) pPageRows = new ScPageRowEntry[MAXROW+1]; //! vorher zaehlen !!!!
3057 pDoc->SetPageSize( nPrintTab, GetDocPageSize() );
3058 if (aAreaParam.bPrintArea)
3060 ScRange aRange( nStartCol, nStartRow, nPrintTab, nEndCol, nEndRow, nPrintTab );
3061 pDoc->UpdatePageBreaks( nPrintTab, &aRange );
3063 else
3064 pDoc->UpdatePageBreaks( nPrintTab, NULL ); // sonst wird das Ende markiert
3067 // Seiteneinteilung nach Umbruechen in Col/RowFlags
3068 // Von mehreren Umbruechen in einem ausgeblendeten Bereich zaehlt nur einer.
3071 nPagesX = 0;
3072 nPagesY = 0;
3073 nTotalY = 0;
3075 BOOL bVisCol = FALSE;
3076 SCCOL nLastCol = -1;
3077 for (SCCOL i=nStartCol; i<=nEndCol; i++)
3079 bool bHidden = pDoc->ColHidden(i, nPrintTab, nLastCol);
3080 bool bPageBreak = (pDoc->HasColBreak(i, nPrintTab) & BREAK_PAGE);
3081 if ( i>nStartCol && bVisCol && bPageBreak )
3083 pPageEndX[nPagesX] = i-1;
3084 ++nPagesX;
3085 bVisCol = FALSE;
3087 if (!bHidden)
3088 bVisCol = TRUE;
3090 if (bVisCol) // auch am Ende keine leeren Seiten
3092 pPageEndX[nPagesX] = nEndCol;
3093 ++nPagesX;
3096 BOOL bVisRow = FALSE;
3097 SCROW nPageStartRow = nStartRow;
3098 for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
3100 bool bPageBreak = (pDoc->HasRowBreak(nRow, nPrintTab) & BREAK_PAGE);
3101 if (nRow > nStartRow && bVisRow && bPageBreak )
3103 pPageEndY[nTotalY] = nRow-1;
3104 ++nTotalY;
3106 if ( !aTableParam.bSkipEmpty ||
3107 !pDoc->IsPrintEmpty( nPrintTab, nStartCol, nPageStartRow, nEndCol, nRow-1 ) )
3109 pPageRows[nPagesY].SetStartRow( nPageStartRow );
3110 pPageRows[nPagesY].SetEndRow( nRow-1 );
3111 pPageRows[nPagesY].SetPagesX( nPagesX );
3112 if (aTableParam.bSkipEmpty)
3113 lcl_SetHidden( pDoc, nPrintTab, pPageRows[nPagesY], nStartCol, pPageEndX );
3114 ++nPagesY;
3117 nPageStartRow = nRow;
3118 bVisRow = FALSE;
3120 SCROW nLastRow = -1;
3121 if (!pDoc->RowHidden(nRow, nPrintTab, nLastRow))
3122 bVisRow = TRUE;
3123 else
3124 // skip all hidden rows.
3125 nRow = nLastRow;
3128 if (bVisRow)
3130 pPageEndY[nTotalY] = nEndRow;
3131 ++nTotalY;
3133 if ( !aTableParam.bSkipEmpty ||
3134 !pDoc->IsPrintEmpty( nPrintTab, nStartCol, nPageStartRow, nEndCol, nEndRow ) )
3136 pPageRows[nPagesY].SetStartRow( nPageStartRow );
3137 pPageRows[nPagesY].SetEndRow( nEndRow );
3138 pPageRows[nPagesY].SetPagesX( nPagesX );
3139 if (aTableParam.bSkipEmpty)
3140 lcl_SetHidden( pDoc, nPrintTab, pPageRows[nPagesY], nStartCol, pPageEndX );
3141 ++nPagesY;
3146 //------------------------------------------------------------------------
3147 // class ScJobSetup
3148 //------------------------------------------------------------------------
3150 ScJobSetup::ScJobSetup( SfxPrinter* pPrinter )
3152 eOrientation = pPrinter->GetOrientation();
3153 nPaperBin = pPrinter->GetPaperBin();
3154 ePaper = pPrinter->GetPaper();
3156 if ( PAPER_USER == ePaper )
3158 aUserSize = pPrinter->GetPaperSize();
3159 aUserMapMode = pPrinter->GetMapMode();