blob: 94bacc7f03fbfee3969220e35db7804bfe2ef612 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
// INCLUDE ---------------------------------------------------------------
#include "scitems.hxx"
#include <editeng/eeitem.hxx>
#include "printfun.hxx"
#include <svx/svxids.hrc>
#include <editeng/adjitem.hxx>
#include <editeng/boxitem.hxx>
#include <editeng/brshitem.hxx>
#include <svtools/colorcfg.hxx>
#include <editeng/editstat.hxx> // EE_CNTRL_RTFSTYLESHEETS
#include <svx/fmview.hxx>
#include <editeng/frmdiritem.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/paperinf.hxx>
#include <editeng/pbinitem.hxx>
#include <editeng/shaditem.hxx>
#include <editeng/sizeitem.hxx>
#include <svx/svdpagv.hxx>
#include <editeng/ulspitem.hxx>
#include <sfx2/app.hxx>
#include <sfx2/printer.hxx>
#include <tools/multisel.hxx>
#include <sfx2/docfile.hxx>
#include <tools/urlobj.hxx>
#include <svx/xoutbmp.hxx>
#include "editutil.hxx"
#include "docsh.hxx"
#include "output.hxx"
#include "viewdata.hxx"
#include "viewopti.hxx"
#include "stlpool.hxx"
#include "pagepar.hxx"
#include "attrib.hxx"
#include "patattr.hxx"
#include "docpool.hxx"
#include "dociter.hxx"
#include "cell.hxx"
#include "drawutil.hxx"
#include "globstr.hrc"
#include "scresid.hxx"
#include "sc.hrc"
#include "pagedata.hxx"
#include "printopt.hxx"
#include "prevloc.hxx"
#include "scmod.hxx"
#include "drwlayer.hxx"
#include "fillinfo.hxx"
#include "postit.hxx"
#include <vcl/lineinfo.hxx>
#include <tools/pstm.hxx>
#include <boost/scoped_ptr.hpp>
#define ZOOM_MIN 10
#define GET_BOOL(set,which) ((const SfxBoolItem&)(set)->Get((which))).GetValue()
#define GET_USHORT(set,which) ((const SfxUInt16Item&)(set)->Get((which))).GetValue()
#define GET_SHOW(set,which) ( VOBJ_MODE_SHOW == ScVObjMode( ((const ScViewObjectModeItem&)(set)->Get((which))).GetValue()) )
//------------------------------------------------------------------------
ScPageRowEntry::ScPageRowEntry(const ScPageRowEntry& r)
{
nStartRow = r.nStartRow;
nEndRow = r.nEndRow;
nPagesX = r.nPagesX;
if (r.pHidden && nPagesX)
{
pHidden = new sal_Bool[nPagesX];
memcpy( pHidden, r.pHidden, nPagesX * sizeof(sal_Bool) );
}
else
pHidden = NULL;
}
const ScPageRowEntry& ScPageRowEntry::operator=(const ScPageRowEntry& r)
{
delete[] pHidden;
nStartRow = r.nStartRow;
nEndRow = r.nEndRow;
nPagesX = r.nPagesX;
if (r.pHidden && nPagesX)
{
pHidden = new sal_Bool[nPagesX];
memcpy( pHidden, r.pHidden, nPagesX * sizeof(sal_Bool) );
}
else
pHidden = NULL;
return *this;
}
void ScPageRowEntry::SetPagesX(size_t nNew)
{
if (pHidden)
{
DBG_ERROR("SetPagesX nicht nach SetHidden");
delete[] pHidden;
pHidden = NULL;
}
nPagesX = nNew;
}
void ScPageRowEntry::SetHidden(size_t nX)
{
if ( nX < nPagesX )
{
if ( nX+1 == nPagesX ) // letzte Seite?
--nPagesX;
else
{
if (!pHidden)
{
pHidden = new sal_Bool[nPagesX];
memset( pHidden, sal_False, nPagesX * sizeof(sal_Bool) );
}
pHidden[nX] = sal_True;
}
}
}
sal_Bool ScPageRowEntry::IsHidden(size_t nX) const
{
return nX>=nPagesX || ( pHidden && pHidden[nX] ); //! inline?
}
size_t ScPageRowEntry::CountVisible() const
{
if ( pHidden )
{
size_t nVis = 0;
for (size_t i=0; i<nPagesX; i++)
if (!pHidden[i])
++nVis;
return nVis;
}
else
return nPagesX;
}
//------------------------------------------------------------------------
long lcl_LineTotal(const SvxBorderLine* pLine)
{
return pLine ? ( pLine->GetOutWidth() + pLine->GetInWidth() + pLine->GetDistance() ) : 0;
}
void ScPrintFunc::Construct( const ScPrintOptions* pOptions )
{
pDocShell->UpdatePendingRowHeights( nPrintTab );
pDoc = pDocShell->GetDocument();
SfxPrinter* pDocPrinter = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen
if (pDocPrinter)
aOldPrinterMode = pDocPrinter->GetMapMode();
// einheitlicher MapMode ueber alle Aufrufe (z.B. Repaint !!!),
// weil die EditEngine sonst unterschiedliche Texthoehen liefert
pDev->SetMapMode(MAP_PIXEL);
pBorderItem = NULL;
pBackgroundItem = NULL;
pShadowItem = NULL;
pEditEngine = NULL;
pEditDefaults = NULL;
ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
SfxStyleSheetBase* pStyleSheet = pStylePool->Find(
pDoc->GetPageStyle( nPrintTab ),
SFX_STYLE_FAMILY_PAGE );
if (pStyleSheet)
pParamSet = &pStyleSheet->GetItemSet();
else
{
DBG_ERROR("Seitenvorlage nicht gefunden" );
pParamSet = NULL;
}
if (!bState)
nZoom = 100;
nManualZoom = 100;
bClearWin = sal_False;
bUseStyleColor = sal_False;
bIsRender = sal_False;
InitParam(pOptions);
pPageData = NULL; // wird nur zur Initialisierung gebraucht
}
ScPrintFunc::ScPrintFunc( ScDocShell* pShell, SfxPrinter* pNewPrinter, SCTAB nTab,
long nPage, long nDocP, const ScRange* pArea,
const ScPrintOptions* pOptions,
ScPageBreakData* pData )
: pDocShell ( pShell ),
pPrinter ( pNewPrinter ),
pDrawView ( NULL ),
nPrintTab ( nTab ),
nPageStart ( nPage ),
nDocPages ( nDocP ),
pUserArea ( pArea ),
bState ( sal_False ),
bSourceRangeValid ( sal_False ),
bPrintCurrentTable ( sal_False ),
bMultiArea ( sal_False ),
nTabPages ( 0 ),
nTotalPages ( 0 ),
pPageData ( pData )
{
pDev = pPrinter;
aSrcOffset = pPrinter->PixelToLogic( pPrinter->GetPageOffsetPixel(), MAP_100TH_MM );
Construct( pOptions );
}
ScPrintFunc::ScPrintFunc( OutputDevice* pOutDev, ScDocShell* pShell, SCTAB nTab,
long nPage, long nDocP, const ScRange* pArea,
const ScPrintOptions* pOptions )
: pDocShell ( pShell ),
pPrinter ( NULL ),
pDrawView ( NULL ),
nPrintTab ( nTab ),
nPageStart ( nPage ),
nDocPages ( nDocP ),
pUserArea ( pArea ),
bState ( sal_False ),
bSourceRangeValid ( sal_False ),
bPrintCurrentTable ( sal_False ),
bMultiArea ( sal_False ),
nTabPages ( 0 ),
nTotalPages ( 0 ),
pPageData ( NULL )
{
pDev = pOutDev;
Construct( pOptions );
}
ScPrintFunc::ScPrintFunc( OutputDevice* pOutDev, ScDocShell* pShell,
const ScPrintState& rState, const ScPrintOptions* pOptions )
: pDocShell ( pShell ),
pPrinter ( NULL ),
pDrawView ( NULL ),
pUserArea ( NULL ),
bSourceRangeValid ( sal_False ),
bPrintCurrentTable ( sal_False ),
bMultiArea ( sal_False ),
pPageData ( NULL )
{
pDev = pOutDev;
nPrintTab = rState.nPrintTab;
nStartCol = rState.nStartCol;
nStartRow = rState.nStartRow;
nEndCol = rState.nEndCol;
nEndRow = rState.nEndRow;
nZoom = rState.nZoom;
nPagesX = rState.nPagesX;
nPagesY = rState.nPagesY;
nTabPages = rState.nTabPages;
nTotalPages = rState.nTotalPages;
nPageStart = rState.nPageStart;
nDocPages = rState.nDocPages;
bState = sal_True;
Construct( pOptions );
}
void ScPrintFunc::GetPrintState( ScPrintState& rState )
{
rState.nPrintTab = nPrintTab;
rState.nStartCol = nStartCol;
rState.nStartRow = nStartRow;
rState.nEndCol = nEndCol;
rState.nEndRow = nEndRow;
rState.nZoom = nZoom;
rState.nPagesX = nPagesX;
rState.nPagesY = nPagesY;
rState.nTabPages = nTabPages;
rState.nTotalPages = nTotalPages;
rState.nPageStart = nPageStart;
rState.nDocPages = nDocPages;
}
sal_Bool ScPrintFunc::GetLastSourceRange( ScRange& rRange ) const
{
rRange = aLastSourceRange;
return bSourceRangeValid;
}
void ScPrintFunc::FillPageData()
{
if (pPageData)
{
sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( pPageData->GetCount() );
ScPrintRangeData& rData = pPageData->GetData(nCount); // hochzaehlen
rData.SetPrintRange( ScRange( nStartCol, nStartRow, nPrintTab,
nEndCol, nEndRow, nPrintTab ) );
// #123672#
if(maPageEndX.empty())
{
OSL_ENSURE(false, "vector access error for maPageEndX (!)");
}
else
{
rData.SetPagesX( nPagesX, &maPageEndX[0]);
}
// #123672#
if(maPageEndY.empty())
{
OSL_ENSURE(false, "vector access error for maPageEndY (!)");
}
else
{
rData.SetPagesY( nTotalY, &maPageEndY[0]);
}
// Einstellungen
rData.SetTopDown( aTableParam.bTopDown );
rData.SetAutomatic( !aAreaParam.bPrintArea );
}
}
ScPrintFunc::~ScPrintFunc()
{
ScAddress* pTripel = (ScAddress*) aNotePosList.First();
while (pTripel)
{
delete pTripel;
pTripel = (ScAddress*) aNotePosList.Next();
}
aNotePosList.Clear();
delete pEditDefaults;
delete pEditEngine;
// Druckereinstellungen werden jetzt von aussen wiederhergestellt
// #64294# Fuer DrawingLayer/Charts muss der MapMode am Drucker (RefDevice) immer stimmen
SfxPrinter* pDocPrinter = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen
if (pDocPrinter)
pDocPrinter->SetMapMode(aOldPrinterMode);
}
void ScPrintFunc::SetDrawView( FmFormView* pNew )
{
pDrawView = pNew;
}
void lcl_HidePrint( ScTableInfo& rTabInfo, SCCOL nX1, SCCOL nX2 )
{
for (SCSIZE nArrY=1; nArrY+1<rTabInfo.mnArrCount; nArrY++)
{
RowInfo* pThisRowInfo = &rTabInfo.mpRowInfo[nArrY];
for (SCCOL nX=nX1; nX<=nX2; nX++)
{
const CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nX+1];
if (!rCellInfo.bEmptyCellText)
if (((const ScProtectionAttr&)rCellInfo.pPatternAttr->
GetItem(ATTR_PROTECTION, rCellInfo.pConditionSet)).GetHidePrint())
{
pThisRowInfo->pCellInfo[nX+1].pCell = NULL;
pThisRowInfo->pCellInfo[nX+1].bEmptyCellText = sal_True;
}
}
}
}
//
// Ausgabe auf Device (static)
//
// wird benutzt fuer:
// - Clipboard/Bitmap
// - Ole-Object (DocShell::Draw)
// - Vorschau bei Vorlagen
void ScPrintFunc::DrawToDev( ScDocument* pDoc, OutputDevice* pDev, double /* nPrintFactor */,
const Rectangle& rBound, ScViewData* pViewData, sal_Bool bMetaFile )
{
//! nPrintFactor auswerten !!!
SCTAB nTab = 0;
if (pViewData)
nTab = pViewData->GetTabNo();
sal_Bool bDoGrid, bNullVal, bFormula;
ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
SfxStyleSheetBase* pStyleSheet = pStylePool->Find( pDoc->GetPageStyle( nTab ), SFX_STYLE_FAMILY_PAGE );
if (pStyleSheet)
{
SfxItemSet& rSet = pStyleSheet->GetItemSet();
bDoGrid = ((const SfxBoolItem&)rSet.Get(ATTR_PAGE_GRID)).GetValue();
bNullVal = ((const SfxBoolItem&)rSet.Get(ATTR_PAGE_NULLVALS)).GetValue();
bFormula = ((const SfxBoolItem&)rSet.Get(ATTR_PAGE_FORMULAS)).GetValue();
}
else
{
const ScViewOptions& rOpt = pDoc->GetViewOptions();
bDoGrid = rOpt.GetOption(VOPT_GRID);
bNullVal = rOpt.GetOption(VOPT_NULLVALS);
bFormula = rOpt.GetOption(VOPT_FORMULAS);
}
MapMode aMode = pDev->GetMapMode();
Rectangle aRect = rBound;
if (aRect.Right() < aRect.Left() || aRect.Bottom() < aRect.Top())
aRect = Rectangle( Point(), pDev->GetOutputSize() );
SCCOL nX1 = 0;
SCROW nY1 = 0;
SCCOL nX2 = OLE_STD_CELLS_X - 1;
SCROW nY2 = OLE_STD_CELLS_Y - 1;
if (bMetaFile)
{
ScRange aRange = pDoc->GetRange( nTab, rBound );
nX1 = aRange.aStart.Col();
nY1 = aRange.aStart.Row();
nX2 = aRange.aEnd.Col();
nY2 = aRange.aEnd.Row();
}
else if (pViewData)
{
ScSplitPos eWhich = pViewData->GetActivePart();
ScHSplitPos eHWhich = WhichH(eWhich);
ScVSplitPos eVWhich = WhichV(eWhich);
nX1 = pViewData->GetPosX(eHWhich);
nY1 = pViewData->GetPosY(eVWhich);
nX2 = nX1 + pViewData->VisibleCellsX(eHWhich);
if (nX2>nX1) --nX2;
nY2 = nY1 + pViewData->VisibleCellsY(eVWhich);
if (nY2>nY1) --nY2;
}
if (nX1 > MAXCOL) nX1 = MAXCOL;
if (nX2 > MAXCOL) nX2 = MAXCOL;
if (nY1 > MAXROW) nY1 = MAXROW;
if (nY2 > MAXROW) nY2 = MAXROW;
long nDevSizeX = aRect.Right()-aRect.Left()+1;
long nDevSizeY = aRect.Bottom()-aRect.Top()+1;
Rectangle aLines;
ScRange aRange( nX1,nY1,nTab, nX2,nY2,nTab );
// sal_Bool bAddLines = pDoc->HasLines( aRange, aLines );
long nTwipsSizeX = 0;
for (SCCOL i=nX1; i<=nX2; i++)
nTwipsSizeX += pDoc->GetColWidth( i, nTab );
long nTwipsSizeY = (long) pDoc->GetRowHeight( nY1, nY2, nTab );
// wenn keine Linien, dann trotzdem Platz fuer den Aussenrahmen (20 Twips = 1pt)
// (HasLines initalisiert aLines auf 0,0,0,0)
nTwipsSizeX += aLines.Left() + Max( aLines.Right(), 20L );
nTwipsSizeY += aLines.Top() + Max( aLines.Bottom(), 20L );
double nScaleX = (double) nDevSizeX / nTwipsSizeX;
double nScaleY = (double) nDevSizeY / nTwipsSizeY;
//! Flag bei FillInfo uebergeben !!!!!
ScRange aERange;
sal_Bool bEmbed = pDoc->IsEmbedded();
if (bEmbed)
{
pDoc->GetEmbedded(aERange);
pDoc->ResetEmbedded();
}
// Daten zusammenstellen
ScTableInfo aTabInfo;
pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab,
nScaleX, nScaleY, sal_False, bFormula );
lcl_HidePrint( aTabInfo, nX1, nX2 );
if (bEmbed)
pDoc->SetEmbedded(aERange);
/* if (!bMetaFile)
pDev->SetMapMode(MAP_PIXEL);
*/
long nScrX = aRect.Left();
long nScrY = aRect.Top();
// Wenn keine Linien, trotzdem Platz fuer Gitterlinien lassen
// (werden sonst abgeschnitten)
long nAddX = (long)( aLines.Left() * nScaleX );
nScrX += ( nAddX ? nAddX : 1 );
long nAddY = (long)( aLines.Top() * nScaleY );
nScrY += ( nAddY ? nAddY : 1 );
ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pDoc, nTab,
nScrX, nScrY, nX1, nY1, nX2, nY2, nScaleX, nScaleY );
aOutputData.SetMetaFileMode(bMetaFile);
aOutputData.SetShowNullValues(bNullVal);
aOutputData.SetShowFormulas(bFormula);
// #114135#
ScDrawLayer* pModel = pDoc->GetDrawLayer();
FmFormView* pDrawView = NULL;
if( pModel )
{
pDrawView = new FmFormView( pModel, pDev );
pDrawView->ShowSdrPage(pDrawView->GetModel()->GetPage(nTab));
pDrawView->SetPrintPreview( sal_True );
aOutputData.SetDrawView( pDrawView );
}
//! SetUseStyleColor ??
if ( bMetaFile && pDev->GetOutDevType() == OUTDEV_VIRDEV )
aOutputData.SetSnapPixel();
Point aLogStart = pDev->PixelToLogic( Point(nScrX,nScrY), MAP_100TH_MM );
long nLogStX = aLogStart.X();
long nLogStY = aLogStart.Y();
//! nZoom fuer GetFont in OutputData ???
if (!bMetaFile && pViewData)
pDev->SetMapMode(pViewData->GetLogicMode(pViewData->GetActivePart()));
// #i72502#
const Point aMMOffset(aOutputData.PrePrintDrawingLayer(nLogStX, nLogStY));
aOutputData.PrintDrawingLayer(SC_LAYER_BACK, aMMOffset);
if (!bMetaFile && pViewData)
pDev->SetMapMode(aMode);
aOutputData.DrawBackground();
#ifdef OS2
if (bMetaFile && !bDoGrid)
{
// unter OS2 fuer Metafiles gesamte Flaeche benutzen,
// weil sonst die Groesse nicht erkannt wird
pDev->SetLineColor();
pDev->SetFillColor();
pDev->DrawRect( Rectangle( nScrX,nScrY,
nScrX+aOutputData.GetScrW(), nScrY+aOutputData.GetScrH() ) );
}
#endif
aOutputData.DrawShadow();
aOutputData.DrawFrame();
aOutputData.DrawStrings();
if (!bMetaFile && pViewData)
pDev->SetMapMode(pViewData->GetLogicMode(pViewData->GetActivePart()));
aOutputData.DrawEdit(!bMetaFile);
if (bDoGrid)
{
if (!bMetaFile && pViewData)
pDev->SetMapMode(aMode);
aOutputData.DrawGrid( sal_True, sal_False ); // keine Seitenumbrueche
pDev->SetLineColor( COL_BLACK );
Size aOne = pDev->PixelToLogic( Size(1,1) );
if (bMetaFile)
aOne = Size(1,1); // compatible with DrawGrid
long nRight = nScrX + aOutputData.GetScrW() - aOne.Width();
long nBottom = nScrY + aOutputData.GetScrH() - aOne.Height();
sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nTab );
// extra line at the left edge for left-to-right, right for right-to-left
if ( bLayoutRTL )
pDev->DrawLine( Point(nRight,nScrY), Point(nRight,nBottom) );
else
pDev->DrawLine( Point(nScrX,nScrY), Point(nScrX,nBottom) );
// extra line at the top in both cases
pDev->DrawLine( Point(nScrX,nScrY), Point(nRight,nScrY) );
}
// #i72502#
aOutputData.PrintDrawingLayer(SC_LAYER_FRONT, aMMOffset);
aOutputData.PrintDrawingLayer(SC_LAYER_INTERN, aMMOffset);
aOutputData.PostPrintDrawingLayer(aMMOffset); // #i74768#
// #114135#
delete pDrawView;
}
//
// Drucken
//
void lcl_FillHFParam( ScPrintHFParam& rParam, const SfxItemSet* pHFSet )
{
// nDistance muss vorher unterschiedlich initalisiert sein
if ( pHFSet == NULL )
{
rParam.bEnable = sal_False;
rParam.pBorder = NULL;
rParam.pBack = NULL;
rParam.pShadow = NULL;
}
else
{
rParam.bEnable = ((const SfxBoolItem&) pHFSet->Get(ATTR_PAGE_ON)).GetValue();
rParam.bDynamic = ((const SfxBoolItem&) pHFSet->Get(ATTR_PAGE_DYNAMIC)).GetValue();
rParam.bShared = ((const SfxBoolItem&) pHFSet->Get(ATTR_PAGE_SHARED)).GetValue();
rParam.nHeight = ((const SvxSizeItem&) pHFSet->Get(ATTR_PAGE_SIZE)).GetSize().Height();
const SvxLRSpaceItem* pHFLR = &(const SvxLRSpaceItem&) pHFSet->Get(ATTR_LRSPACE);
long nTmp;
nTmp = pHFLR->GetLeft();
rParam.nLeft = nTmp < 0 ? 0 : sal_uInt16(nTmp);
nTmp = pHFLR->GetRight();
rParam.nRight = nTmp < 0 ? 0 : sal_uInt16(nTmp);
rParam.pBorder = (const SvxBoxItem*) &pHFSet->Get(ATTR_BORDER);
rParam.pBack = (const SvxBrushItem*) &pHFSet->Get(ATTR_BACKGROUND);
rParam.pShadow = (const SvxShadowItem*)&pHFSet->Get(ATTR_SHADOW);;
// jetzt doch wieder schon im Dialog:
// rParam.nHeight += rParam.nDistance; // nicht mehr im Dialog ???
if (rParam.pBorder)
rParam.nHeight += lcl_LineTotal( rParam.pBorder->GetTop() ) +
lcl_LineTotal( rParam.pBorder->GetBottom() );
rParam.nManHeight = rParam.nHeight;
}
if (!rParam.bEnable)
rParam.nHeight = 0;
}
// bNew = TRUE: benutzten Bereich aus dem Dokument suchen
// bNew = FALSE: nur ganze Zeilen/Spalten begrenzen
sal_Bool ScPrintFunc::AdjustPrintArea( sal_Bool bNew )
{
SCCOL nOldEndCol = nEndCol; // nur wichtig bei !bNew
SCROW nOldEndRow = nEndRow;
sal_Bool bChangeCol = sal_True; // bei bNew werden beide angepasst
sal_Bool bChangeRow = sal_True;
sal_Bool bNotes = aTableParam.bNotes;
if ( bNew )
{
nStartCol = 0;
nStartRow = 0;
if (!pDoc->GetPrintArea( nPrintTab, nEndCol, nEndRow, bNotes ))
return sal_False; // nix
}
else
{
sal_Bool bFound = sal_True;
bChangeCol = ( nStartCol == 0 && nEndCol == MAXCOL );
bChangeRow = ( nStartRow == 0 && nEndRow == MAXROW );
sal_Bool bForcedChangeRow = sal_False;
// #i53558# Crop entire column of old row limit to real print area with
// some fuzzyness.
if (!bChangeRow && nStartRow == 0)
{
SCROW nPAEndRow;
bFound = pDoc->GetPrintAreaVer( nPrintTab, nStartCol, nEndCol, nPAEndRow, bNotes );
// Say we don't want to print more than ~1000 empty rows, which are
// about 14 pages intentionally left blank..
const SCROW nFuzzy = 23*42;
if (nPAEndRow + nFuzzy < nEndRow)
{
bForcedChangeRow = sal_True;
nEndRow = nPAEndRow;
}
else
bFound = sal_True; // user seems to _want_ to print some empty rows
}
// TODO: in case we extend the number of columns we may have to do the
// same for horizontal cropping.
if ( bChangeCol && bChangeRow )
bFound = pDoc->GetPrintArea( nPrintTab, nEndCol, nEndRow, bNotes );
else if ( bChangeCol )
bFound = pDoc->GetPrintAreaHor( nPrintTab, nStartRow, nEndRow, nEndCol, bNotes );
else if ( bChangeRow )
bFound = pDoc->GetPrintAreaVer( nPrintTab, nStartCol, nEndCol, nEndRow, bNotes );
if (!bFound)
return sal_False; // leer
if (bForcedChangeRow)
bChangeRow = sal_True;
}
pDoc->ExtendMerge( nStartCol,nStartRow, nEndCol,nEndRow, nPrintTab,
sal_False, sal_True ); // kein Refresh, incl. Attrs
if ( bChangeCol )
{
OutputDevice* pRefDev = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen
pRefDev->SetMapMode( MAP_PIXEL ); // wichtig fuer GetNeededSize
pDoc->ExtendPrintArea( pRefDev,
nPrintTab, nStartCol, nStartRow, nEndCol, nEndRow );
// nEndCol wird veraendert
}
if ( nEndCol < MAXCOL && pDoc->HasAttrib(
nEndCol,nStartRow,nPrintTab, nEndCol,nEndRow,nPrintTab, HASATTR_SHADOW_RIGHT ) )
++nEndCol;
if ( nEndRow < MAXROW && pDoc->HasAttrib(
nStartCol,nEndRow,nPrintTab, nEndCol,nEndRow,nPrintTab, HASATTR_SHADOW_DOWN ) )
++nEndRow;
if (!bChangeCol) nEndCol = nOldEndCol;
if (!bChangeRow) nEndRow = nOldEndRow;
return sal_True;
}
long ScPrintFunc::TextHeight( const EditTextObject* pObject )
{
if (!pObject)
return 0;
// pEditEngine->SetPageNo( nTotalPages );
pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, sal_False );
return (long) pEditEngine->GetTextHeight();
}
// nZoom muss gesetzt sein !!!
// und der entsprechende Twip-MapMode eingestellt
void ScPrintFunc::UpdateHFHeight( ScPrintHFParam& rParam )
{
DBG_ASSERT( aPageSize.Width(), "UpdateHFHeight ohne aPageSize");
if (rParam.bEnable && rParam.bDynamic)
{
// nHeight aus Inhalten berechnen
MakeEditEngine();
long nPaperWidth = ( aPageSize.Width() - nLeftMargin - nRightMargin -
rParam.nLeft - rParam.nRight ) * 100 / nZoom;
if (rParam.pBorder)
nPaperWidth -= ( rParam.pBorder->GetDistance(BOX_LINE_LEFT) +
rParam.pBorder->GetDistance(BOX_LINE_RIGHT) +
lcl_LineTotal(rParam.pBorder->GetLeft()) +
lcl_LineTotal(rParam.pBorder->GetRight()) ) * 100 / nZoom;
if (rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE)
nPaperWidth -= ( rParam.pShadow->CalcShadowSpace(SHADOW_LEFT) +
rParam.pShadow->CalcShadowSpace(SHADOW_RIGHT) ) * 100L / nZoom;
pEditEngine->SetPaperSize( Size( nPaperWidth, 10000 ) );
long nMaxHeight = 0;
if ( rParam.pLeft )
{
nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pLeft->GetLeftArea() ) );
nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pLeft->GetCenterArea() ) );
nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pLeft->GetRightArea() ) );
}
if ( rParam.pRight )
{
nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pRight->GetLeftArea() ) );
nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pRight->GetCenterArea() ) );
nMaxHeight = Max( nMaxHeight, TextHeight( rParam.pRight->GetRightArea() ) );
}
rParam.nHeight = nMaxHeight + rParam.nDistance;
if (rParam.pBorder)
rParam.nHeight += rParam.pBorder->GetDistance(BOX_LINE_TOP) +
rParam.pBorder->GetDistance(BOX_LINE_BOTTOM) +
lcl_LineTotal( rParam.pBorder->GetTop() ) +
lcl_LineTotal( rParam.pBorder->GetBottom() );
if (rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE)
rParam.nHeight += rParam.pShadow->CalcShadowSpace(SHADOW_TOP) +
rParam.pShadow->CalcShadowSpace(SHADOW_BOTTOM);
if (rParam.nHeight < rParam.nManHeight)
rParam.nHeight = rParam.nManHeight; // eingestelltes Minimum
}
}
void ScPrintFunc::InitParam( const ScPrintOptions* pOptions )
{
if (!pParamSet)
return;
// TabPage "Seite"
const SvxLRSpaceItem* pLRItem = (const SvxLRSpaceItem*) &pParamSet->Get( ATTR_LRSPACE );
long nTmp;
nTmp = pLRItem->GetLeft();
nLeftMargin = nTmp < 0 ? 0 : sal_uInt16(nTmp);
nTmp = pLRItem->GetRight();
nRightMargin = nTmp < 0 ? 0 : sal_uInt16(nTmp);
const SvxULSpaceItem* pULItem = (const SvxULSpaceItem*) &pParamSet->Get( ATTR_ULSPACE );
nTopMargin = pULItem->GetUpper();
nBottomMargin = pULItem->GetLower();
const SvxPageItem* pPageItem = (const SvxPageItem*) &pParamSet->Get( ATTR_PAGE );
nPageUsage = pPageItem->GetPageUsage();
bLandscape = pPageItem->IsLandscape();
aFieldData.eNumType = pPageItem->GetNumType();
bCenterHor = ((const SfxBoolItem&) pParamSet->Get(ATTR_PAGE_HORCENTER)).GetValue();
bCenterVer = ((const SfxBoolItem&) pParamSet->Get(ATTR_PAGE_VERCENTER)).GetValue();
aPageSize = ((const SvxSizeItem&) pParamSet->Get(ATTR_PAGE_SIZE)).GetSize();
if ( !aPageSize.Width() || !aPageSize.Height() )
{
DBG_ERROR("PageSize Null ?!?!?");
aPageSize = SvxPaperInfo::GetPaperSize( PAPER_A4 );
}
pBorderItem = (const SvxBoxItem*) &pParamSet->Get(ATTR_BORDER);
pBackgroundItem = (const SvxBrushItem*) &pParamSet->Get(ATTR_BACKGROUND);
pShadowItem = (const SvxShadowItem*) &pParamSet->Get(ATTR_SHADOW);
// TabPage "Kopfzeile"
aHdr.pLeft = (const ScPageHFItem*) &pParamSet->Get(ATTR_PAGE_HEADERLEFT); // Inhalt
aHdr.pRight = (const ScPageHFItem*) &pParamSet->Get(ATTR_PAGE_HEADERRIGHT);
const SvxSetItem* pHeaderSetItem;
const SfxItemSet* pHeaderSet = NULL;
if ( pParamSet->GetItemState( ATTR_PAGE_HEADERSET, sal_False,
(const SfxPoolItem**)&pHeaderSetItem ) == SFX_ITEM_SET )
{
pHeaderSet = &pHeaderSetItem->GetItemSet();
// Kopfzeile hat unteren Abstand
aHdr.nDistance = ((const SvxULSpaceItem&) pHeaderSet->Get(ATTR_ULSPACE)).GetLower();
}
lcl_FillHFParam( aHdr, pHeaderSet );
// TabPage "Fusszeile"
aFtr.pLeft = (const ScPageHFItem*) &pParamSet->Get(ATTR_PAGE_FOOTERLEFT); // Inhalt
aFtr.pRight = (const ScPageHFItem*) &pParamSet->Get(ATTR_PAGE_FOOTERRIGHT);
const SvxSetItem* pFooterSetItem;
const SfxItemSet* pFooterSet = NULL;
if ( pParamSet->GetItemState( ATTR_PAGE_FOOTERSET, sal_False,
(const SfxPoolItem**)&pFooterSetItem ) == SFX_ITEM_SET )
{
pFooterSet = &pFooterSetItem->GetItemSet();
// Fusszeile hat oberen Abstand
aFtr.nDistance = ((const SvxULSpaceItem&) pFooterSet->Get(ATTR_ULSPACE)).GetUpper();
}
lcl_FillHFParam( aFtr, pFooterSet );
//------------------------------------------------------
// Table-/Area-Params aus einzelnen Items zusammenbauen:
//------------------------------------------------------
// TabPage "Tabelle"
const SfxUInt16Item* pScaleItem = NULL;
const ScPageScaleToItem* pScaleToItem = NULL;
const SfxUInt16Item* pScaleToPagesItem = NULL;
SfxItemState eState;
eState = pParamSet->GetItemState( ATTR_PAGE_SCALE, sal_False,
(const SfxPoolItem**)&pScaleItem );
if ( SFX_ITEM_DEFAULT == eState )
pScaleItem = (const SfxUInt16Item*)
&pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALE );
eState = pParamSet->GetItemState( ATTR_PAGE_SCALETO, sal_False,
(const SfxPoolItem**)&pScaleToItem );
if ( SFX_ITEM_DEFAULT == eState )
pScaleToItem = (const ScPageScaleToItem*)
&pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALETO );
eState = pParamSet->GetItemState( ATTR_PAGE_SCALETOPAGES, sal_False,
(const SfxPoolItem**)&pScaleToPagesItem );
if ( SFX_ITEM_DEFAULT == eState )
pScaleToPagesItem = (const SfxUInt16Item*)
&pParamSet->GetPool()->GetDefaultItem( ATTR_PAGE_SCALETOPAGES );
DBG_ASSERT( pScaleItem && pScaleToItem && pScaleToPagesItem, "Missing ScaleItem! :-/" );
aTableParam.bCellContent = sal_True;
aTableParam.bNotes = GET_BOOL(pParamSet,ATTR_PAGE_NOTES);
aTableParam.bGrid = GET_BOOL(pParamSet,ATTR_PAGE_GRID);
aTableParam.bHeaders = GET_BOOL(pParamSet,ATTR_PAGE_HEADERS);
aTableParam.bFormulas = GET_BOOL(pParamSet,ATTR_PAGE_FORMULAS);
aTableParam.bNullVals = GET_BOOL(pParamSet,ATTR_PAGE_NULLVALS);
aTableParam.bCharts = GET_SHOW(pParamSet,ATTR_PAGE_CHARTS);
aTableParam.bObjects = GET_SHOW(pParamSet,ATTR_PAGE_OBJECTS);
aTableParam.bDrawings = GET_SHOW(pParamSet,ATTR_PAGE_DRAWINGS);
aTableParam.bTopDown = GET_BOOL(pParamSet,ATTR_PAGE_TOPDOWN);
aTableParam.bLeftRight = !aTableParam.bLeftRight;
aTableParam.nFirstPageNo = GET_USHORT(pParamSet,ATTR_PAGE_FIRSTPAGENO);
if (!aTableParam.nFirstPageNo)
aTableParam.nFirstPageNo = (sal_uInt16) nPageStart; // von vorheriger Tabelle
if ( pScaleItem && pScaleToItem && pScaleToPagesItem )
{
sal_uInt16 nScaleAll = pScaleItem->GetValue();
sal_uInt16 nScaleToPages = pScaleToPagesItem->GetValue();
aTableParam.bScaleNone = (nScaleAll == 100);
aTableParam.bScaleAll = (nScaleAll > 0 );
aTableParam.bScaleTo = pScaleToItem->IsValid();
aTableParam.bScalePageNum = (nScaleToPages > 0 );
aTableParam.nScaleAll = nScaleAll;
aTableParam.nScaleWidth = pScaleToItem->GetWidth();
aTableParam.nScaleHeight = pScaleToItem->GetHeight();
aTableParam.nScalePageNum = nScaleToPages;
}
else
{
aTableParam.bScaleNone = sal_True;
aTableParam.bScaleAll = sal_False;
aTableParam.bScaleTo = sal_False;
aTableParam.bScalePageNum = sal_False;
aTableParam.nScaleAll = 0;
aTableParam.nScaleWidth = 0;
aTableParam.nScaleHeight = 0;
aTableParam.nScalePageNum = 0;
}
// skip empty pages only if options with that flag are passed
aTableParam.bSkipEmpty = pOptions && pOptions->GetSkipEmpty();
if ( pPageData )
aTableParam.bSkipEmpty = sal_False;
// Wenn pPageData gesetzt ist, interessieren fuer die Umbruch-Vorschau
// nur die Umbrueche, leere Seiten werden nicht speziell behandelt
//------------------------------------------------------
// TabPage "Bereiche":
//------------------------------------------------------
//! alle PrintAreas der Tabelle durchgehen !!!
const ScRange* pPrintArea = pDoc->GetPrintRange( nPrintTab, 0 );
const ScRange* pRepeatCol = pDoc->GetRepeatColRange( nPrintTab );
const ScRange* pRepeatRow = pDoc->GetRepeatRowRange( nPrintTab );
// ATTR_PAGE_PRINTTABLES wird ignoriert
if ( pUserArea ) // UserArea (Selektion) hat Vorrang
{
bPrintCurrentTable =
aAreaParam.bPrintArea = sal_True; // Selektion
aAreaParam.aPrintArea = *pUserArea;
// Die Tabellen-Abfrage ist schon in DocShell::Print, hier immer
aAreaParam.aPrintArea.aStart.SetTab(nPrintTab);
aAreaParam.aPrintArea.aEnd.SetTab(nPrintTab);
// lcl_LimitRange( aAreaParam.aPrintArea, nPrintTab ); // ganze Zeilen/Spalten...
}
else if ( pDoc->HasPrintRange() )
{
if ( pPrintArea ) // mindestens eine gesetzt ?
{
bPrintCurrentTable =
aAreaParam.bPrintArea = sal_True;
aAreaParam.aPrintArea = *pPrintArea;
bMultiArea = ( pDoc->GetPrintRangeCount(nPrintTab) > 1 );
}
else
{
// do not print hidden sheets with "Print entire sheet" flag
bPrintCurrentTable = pDoc->IsPrintEntireSheet( nPrintTab ) && pDoc->IsVisible( nPrintTab );
aAreaParam.bPrintArea = !bPrintCurrentTable; // otherwise the table is always counted
}
}
else
{
// #74834# don't print hidden tables if there's no print range defined there
if ( pDoc->IsVisible( nPrintTab ) )
{
aAreaParam.bPrintArea = sal_False;
bPrintCurrentTable = sal_True;
}
else
{
aAreaParam.bPrintArea = sal_True; // otherwise the table is always counted
bPrintCurrentTable = sal_False;
}
}
if ( pRepeatCol )
{
aAreaParam.bRepeatCol = sal_True;
aAreaParam.aRepeatCol = *pRepeatCol;
nRepeatStartCol = pRepeatCol->aStart.Col();
nRepeatEndCol = pRepeatCol->aEnd .Col();
}
else
{
aAreaParam.bRepeatCol = sal_False;
nRepeatStartCol = nRepeatEndCol = SCCOL_REPEAT_NONE;
}
if ( pRepeatRow )
{
aAreaParam.bRepeatRow = sal_True;
aAreaParam.aRepeatRow = *pRepeatRow;
nRepeatStartRow = pRepeatRow->aStart.Row();
nRepeatEndRow = pRepeatRow->aEnd .Row();
}
else
{
aAreaParam.bRepeatRow = sal_False;
nRepeatStartRow = nRepeatEndRow = SCROW_REPEAT_NONE;
}
//
// Seiten aufteilen
//
if (!bState)
{
nTabPages = CountPages(); // berechnet auch Zoom
nTotalPages = nTabPages;
nTotalPages += CountNotePages();
}
else
{
CalcPages(); // nur Umbrueche suchen
CountNotePages(); // Notizen zaehlen, auch wenn Seitenzahl schon bekannt
}
if (nDocPages)
aFieldData.nTotalPages = nDocPages;
else
aFieldData.nTotalPages = nTotalPages;
SetDateTime( Date(), Time() );
aFieldData.aTitle = pDocShell->GetTitle();
const INetURLObject& rURLObj = pDocShell->GetMedium()->GetURLObject();
aFieldData.aLongDocName = rURLObj.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS );
if ( aFieldData.aLongDocName.Len() )
aFieldData.aShortDocName = rURLObj.GetName( INetURLObject::DECODE_UNAMBIGUOUS );
else
aFieldData.aShortDocName = aFieldData.aLongDocName = aFieldData.aTitle;
// Druckereinstellungen (Orientation, Paper) jetzt erst bei DoPrint
}
Size ScPrintFunc::GetDataSize() const
{
Size aSize = aPageSize;
aSize.Width() -= nLeftMargin + nRightMargin;
aSize.Height() -= nTopMargin + nBottomMargin;
aSize.Height() -= aHdr.nHeight + aFtr.nHeight;
return aSize;
}
void ScPrintFunc::GetScaleData( Size& rPhysSize, long& rDocHdr, long& rDocFtr )
{
rPhysSize = aPageSize;
rPhysSize.Width() -= nLeftMargin + nRightMargin;
rPhysSize.Height() -= nTopMargin + nBottomMargin;
rDocHdr = aHdr.nHeight;
rDocFtr = aFtr.nHeight;
}
void ScPrintFunc::SetDateTime( const Date& rDate, const Time& rTime )
{
aFieldData.aDate = rDate;
aFieldData.aTime = rTime;
}
void lcl_DrawGraphic( const Graphic &rGraphic, OutputDevice *pOut,
const Rectangle &rGrf, const Rectangle &rOut )
{
const FASTBOOL bNotInside = !rOut.IsInside( rGrf );
if ( bNotInside )
{
pOut->Push();
pOut->IntersectClipRegion( rOut );
}
((Graphic&)rGraphic).Draw( pOut, rGrf.TopLeft(), rGrf.GetSize() );
if ( bNotInside )
pOut->Pop();
}
void lcl_DrawGraphic( const SvxBrushItem &rBrush, OutputDevice *pOut, OutputDevice* pRefDev,
const Rectangle &rOrg, const Rectangle &rOut )
{
Size aGrfSize(0,0);
const Graphic *pGraphic = rBrush.GetGraphic();
SvxGraphicPosition ePos;
if ( pGraphic && pGraphic->IsSupportedGraphic() )
{
const MapMode aMapMM( MAP_100TH_MM );
if ( pGraphic->GetPrefMapMode().GetMapUnit() == MAP_PIXEL )
aGrfSize = pRefDev->PixelToLogic( pGraphic->GetPrefSize(), aMapMM );
else
aGrfSize = OutputDevice::LogicToLogic( pGraphic->GetPrefSize(),
pGraphic->GetPrefMapMode(), aMapMM );
ePos = rBrush.GetGraphicPos();
}
else
ePos = GPOS_NONE;
Point aPos;
Size aDrawSize = aGrfSize;
FASTBOOL bDraw = sal_True;
// FASTBOOL bRetouche = sal_True;
switch ( ePos )
{
case GPOS_LT: aPos = rOrg.TopLeft();
break;
case GPOS_MT: aPos.Y() = rOrg.Top();
aPos.X() = rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2;
break;
case GPOS_RT: aPos.Y() = rOrg.Top();
aPos.X() = rOrg.Right() - aGrfSize.Width();
break;
case GPOS_LM: aPos.Y() = rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2;
aPos.X() = rOrg.Left();
break;
case GPOS_MM: aPos.Y() = rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2;
aPos.X() = rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2;
break;
case GPOS_RM: aPos.Y() = rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2;
aPos.X() = rOrg.Right() - aGrfSize.Width();
break;
case GPOS_LB: aPos.Y() = rOrg.Bottom() - aGrfSize.Height();
aPos.X() = rOrg.Left();
break;
case GPOS_MB: aPos.Y() = rOrg.Bottom() - aGrfSize.Height();
aPos.X() = rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2;
break;
case GPOS_RB: aPos.Y() = rOrg.Bottom() - aGrfSize.Height();
aPos.X() = rOrg.Right() - aGrfSize.Width();
break;
case GPOS_AREA:
aPos = rOrg.TopLeft();
aDrawSize = rOrg.GetSize();
// bRetouche = sal_False;
break;
case GPOS_TILED:
{
// #104004# use GraphicObject::DrawTiled instead of an own loop
// (pixel rounding is handled correctly, and a very small bitmap
// is duplicated into a bigger one for better performance)
GraphicObject aObject( *pGraphic );
if( pOut->GetPDFWriter() &&
(aObject.GetType() == GRAPHIC_BITMAP || aObject.GetType() == GRAPHIC_DEFAULT) )
{
// #104004# For PDF export, every draw
// operation for bitmaps takes a noticeable
// amount of place (~50 characters). Thus,
// optimize between tile bitmap size and
// number of drawing operations here.
//
// A_out
// n_chars = k1 * ---------- + k2 * A_bitmap
// A_bitmap
//
// minimum n_chars is obtained for (derive for
// A_bitmap, set to 0, take positive
// solution):
// k1
// A_bitmap = Sqrt( ---- A_out )
// k2
//
// where k1 is the number of chars per draw
// operation, and k2 is the number of chars
// per bitmap pixel. This is approximately 50
// and 7 for current PDF writer, respectively.
//
const double k1( 50 );
const double k2( 7 );
const Size aSize( rOrg.GetSize() );
const double Abitmap( k1/k2 * aSize.Width()*aSize.Height() );
aObject.DrawTiled( pOut, rOrg, aGrfSize, Size(0,0),
NULL, GRFMGR_DRAW_STANDARD,
::std::max( 128, static_cast<int>( sqrt(sqrt( Abitmap)) + .5 ) ) );
}
else
{
aObject.DrawTiled( pOut, rOrg, aGrfSize, Size(0,0) );
}
bDraw = sal_False;
// bRetouche = sal_False;
}
break;
case GPOS_NONE:
bDraw = sal_False;
break;
default: DBG_ASSERT( !pOut, "new Graphic position?" );
}
Rectangle aGrf( aPos,aDrawSize );
if ( bDraw && aGrf.IsOver( rOut ) )
{
lcl_DrawGraphic( *pGraphic, pOut, aGrf, rOut );
}
}
// Rahmen wird nach innen gezeichnet
void ScPrintFunc::DrawBorder( long nScrX, long nScrY, long nScrW, long nScrH,
const SvxBoxItem* pBorderData, const SvxBrushItem* pBackground,
const SvxShadowItem* pShadow )
{
//! direkte Ausgabe aus SvxBoxItem !!!
if (pBorderData)
if ( !pBorderData->GetTop() && !pBorderData->GetBottom() && !pBorderData->GetLeft() &&
!pBorderData->GetRight() )
pBorderData = NULL;
if (!pBorderData && !pBackground && !pShadow)
return; // nichts zu tun
long nLeft = 0;
long nRight = 0;
long nTop = 0;
long nBottom = 0;
// aFrameRect - aussen um die Umrandung, ohne Schatten
if ( pShadow && pShadow->GetLocation() != SVX_SHADOW_NONE )
{
nLeft += (long) ( pShadow->CalcShadowSpace(SHADOW_LEFT) * nScaleX );
nRight += (long) ( pShadow->CalcShadowSpace(SHADOW_RIGHT) * nScaleX );
nTop += (long) ( pShadow->CalcShadowSpace(SHADOW_TOP) * nScaleY );
nBottom += (long) ( pShadow->CalcShadowSpace(SHADOW_BOTTOM) * nScaleY );
}
Rectangle aFrameRect( Point(nScrX+nLeft, nScrY+nTop),
Size(nScrW-nLeft-nRight, nScrH-nTop-nBottom) );
// Mitte der Umrandung, um Linien ueber OutputData zu zeichnen:
if (pBorderData)
{
nLeft += (long) ( lcl_LineTotal(pBorderData->GetLeft()) * nScaleX / 2 );
nRight += (long) ( lcl_LineTotal(pBorderData->GetRight()) * nScaleX / 2 );
nTop += (long) ( lcl_LineTotal(pBorderData->GetTop()) * nScaleY / 2 );
nBottom += (long) ( lcl_LineTotal(pBorderData->GetBottom()) * nScaleY / 2 );
}
long nEffHeight = nScrH - nTop - nBottom;
long nEffWidth = nScrW - nLeft - nRight;
if (nEffHeight<=0 || nEffWidth<=0)
return; // leer
// #105733# SvtAccessibilityOptions::GetIsForBorders is no longer used (always assumed sal_True)
sal_Bool bCellContrast = bUseStyleColor &&
Application::GetSettings().GetStyleSettings().GetHighContrastMode();
if ( pBackground && !bCellContrast )
{
// Rectangle aBackRect( Point(nScrX+nLeft, nScrY+nTop), Size(nEffWidth,nEffHeight) );
if (pBackground->GetGraphicPos() != GPOS_NONE)
{
OutputDevice* pRefDev;
if ( bIsRender )
pRefDev = pDev; // don't use printer for PDF
else
pRefDev = pDoc->GetPrinter(); // use printer also for preview
lcl_DrawGraphic( *pBackground, pDev, pRefDev, aFrameRect, aFrameRect );
}
else
{
pDev->SetFillColor(pBackground->GetColor());
pDev->SetLineColor();
pDev->DrawRect(aFrameRect);
}
}
if ( pShadow && pShadow->GetLocation() != SVX_SHADOW_NONE )
{
if ( bCellContrast )
pDev->SetFillColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
else
pDev->SetFillColor(pShadow->GetColor());
pDev->SetLineColor();
long nShadowX = (long) ( pShadow->GetWidth() * nScaleX );
long nShadowY = (long) ( pShadow->GetWidth() * nScaleY );
switch (pShadow->GetLocation())
{
case SVX_SHADOW_TOPLEFT:
pDev->DrawRect( Rectangle(
aFrameRect.Left()-nShadowX, aFrameRect.Top()-nShadowY,
aFrameRect.Right()-nShadowX, aFrameRect.Top() ) );
pDev->DrawRect( Rectangle(
aFrameRect.Left()-nShadowX, aFrameRect.Top()-nShadowY,
aFrameRect.Left(), aFrameRect.Bottom()-nShadowY ) );
break;
case SVX_SHADOW_TOPRIGHT:
pDev->DrawRect( Rectangle(
aFrameRect.Left()+nShadowX, aFrameRect.Top()-nShadowY,
aFrameRect.Right()+nShadowX, aFrameRect.Top() ) );
pDev->DrawRect( Rectangle(
aFrameRect.Right(), aFrameRect.Top()-nShadowY,
aFrameRect.Right()+nShadowX, aFrameRect.Bottom()-nShadowY ) );
break;
case SVX_SHADOW_BOTTOMLEFT:
pDev->DrawRect( Rectangle(
aFrameRect.Left()-nShadowX, aFrameRect.Bottom(),
aFrameRect.Right()-nShadowX, aFrameRect.Bottom()+nShadowY ) );
pDev->DrawRect( Rectangle(
aFrameRect.Left()-nShadowX, aFrameRect.Top()+nShadowY,
aFrameRect.Left(), aFrameRect.Bottom()+nShadowY ) );
break;
case SVX_SHADOW_BOTTOMRIGHT:
pDev->DrawRect( Rectangle(
aFrameRect.Left()+nShadowX, aFrameRect.Bottom(),
aFrameRect.Right()+nShadowX, aFrameRect.Bottom()+nShadowY ) );
pDev->DrawRect( Rectangle(
aFrameRect.Right(), aFrameRect.Top()+nShadowY,
aFrameRect.Right()+nShadowX, aFrameRect.Bottom()+nShadowY ) );
break;
default:
{
// added to avoid warnings
}
}
}
if (pBorderData)
{
ScDocument* pBorderDoc = new ScDocument( SCDOCMODE_UNDO );
pBorderDoc->InitUndo( pDoc, 0,0, sal_True,sal_True );
if (pBorderData)
pBorderDoc->ApplyAttr( 0,0,0, *pBorderData );
ScTableInfo aTabInfo;
pBorderDoc->FillInfo( aTabInfo, 0,0, 0,0, 0,
nScaleX, nScaleY, sal_False, sal_False );
DBG_ASSERT(aTabInfo.mnArrCount,"nArrCount == 0");
aTabInfo.mpRowInfo[1].nHeight = (sal_uInt16) nEffHeight;
aTabInfo.mpRowInfo[0].pCellInfo[1].nWidth =
aTabInfo.mpRowInfo[1].pCellInfo[1].nWidth = (sal_uInt16) nEffWidth;
ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pBorderDoc, 0,
nScrX+nLeft, nScrY+nTop, 0,0, 0,0, nScaleX, nScaleY );
aOutputData.SetUseStyleColor( bUseStyleColor );
// pDev->SetMapMode(aTwipMode);
if (pBorderData)
aOutputData.DrawFrame();
delete pBorderDoc;
}
}
void ScPrintFunc::PrintColHdr( SCCOL nX1, SCCOL nX2, long nScrX, long nScrY )
{
sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab );
long nLayoutSign = bLayoutRTL ? -1 : 1;
Size aOnePixel = pDev->PixelToLogic(Size(1,1));
long nOneX = aOnePixel.Width();
long nOneY = aOnePixel.Height();
SCCOL nCol;
long nHeight = (long) (PRINT_HEADER_HEIGHT * nScaleY);
long nEndY = nScrY + nHeight - nOneY;
long nPosX = nScrX;
if ( bLayoutRTL )
{
for (nCol=nX1; nCol<=nX2; nCol++)
nPosX += (long)( pDoc->GetColWidth( nCol, nPrintTab ) * nScaleX );
}
else
nPosX -= nOneX;
long nPosY = nScrY - nOneY;
String aText;
for (nCol=nX1; nCol<=nX2; nCol++)
{
sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nPrintTab );
if (nDocW)
{
long nWidth = (long) (nDocW * nScaleX);
long nEndX = nPosX + nWidth * nLayoutSign;
pDev->DrawRect( Rectangle( nPosX,nPosY,nEndX,nEndY ) );
aText = ::ScColToAlpha( nCol);
long nTextWidth = pDev->GetTextWidth(aText);
long nTextHeight = pDev->GetTextHeight();
long nAddX = ( nWidth - nTextWidth ) / 2;
long nAddY = ( nHeight - nTextHeight ) / 2;
long nTextPosX = nPosX+nAddX;
if ( bLayoutRTL )
nTextPosX -= nWidth;
pDev->DrawText( Point( nTextPosX,nPosY+nAddY ), aText );
nPosX = nEndX;
}
}
}
void ScPrintFunc::PrintRowHdr( SCROW nY1, SCROW nY2, long nScrX, long nScrY )
{
Size aOnePixel = pDev->PixelToLogic(Size(1,1));
long nOneX = aOnePixel.Width();
long nOneY = aOnePixel.Height();
sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab );
long nWidth = (long) (PRINT_HEADER_WIDTH * nScaleX);
long nEndX = nScrX + nWidth;
long nPosX = nScrX;
if ( !bLayoutRTL )
{
nEndX -= nOneX;
nPosX -= nOneX;
}
long nPosY = nScrY - nOneY;
String aText;
for (SCROW nRow=nY1; nRow<=nY2; nRow++)
{
sal_uInt16 nDocH = pDoc->GetRowHeight( nRow, nPrintTab );
if (nDocH)
{
long nHeight = (long) (nDocH * nScaleY);
long nEndY = nPosY + nHeight;
pDev->DrawRect( Rectangle( nPosX,nPosY,nEndX,nEndY ) );
aText = String::CreateFromInt32( nRow+1 );
long nTextWidth = pDev->GetTextWidth(aText);
long nTextHeight = pDev->GetTextHeight();
long nAddX = ( nWidth - nTextWidth ) / 2;
long nAddY = ( nHeight - nTextHeight ) / 2;
pDev->DrawText( Point( nPosX+nAddX,nPosY+nAddY ), aText );
nPosY = nEndY;
}
}
}
void ScPrintFunc::LocateColHdr( SCCOL nX1, SCCOL nX2, long nScrX, long nScrY,
sal_Bool bRepCol, ScPreviewLocationData& rLocationData )
{
Size aOnePixel = pDev->PixelToLogic(Size(1,1));
long nOneX = aOnePixel.Width();
long nOneY = aOnePixel.Height();
long nHeight = (long) (PRINT_HEADER_HEIGHT * nScaleY);
long nEndY = nScrY + nHeight - nOneY;
long nPosX = nScrX - nOneX;
for (SCCOL nCol=nX1; nCol<=nX2; nCol++)
{
sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nPrintTab );
if (nDocW)
nPosX += (long) (nDocW * nScaleX);
}
Rectangle aCellRect( nScrX, nScrY, nPosX, nEndY );
rLocationData.AddColHeaders( aCellRect, nX1, nX2, bRepCol );
}
void ScPrintFunc::LocateRowHdr( SCROW nY1, SCROW nY2, long nScrX, long nScrY,
sal_Bool bRepRow, ScPreviewLocationData& rLocationData )
{
Size aOnePixel = pDev->PixelToLogic(Size(1,1));
long nOneX = aOnePixel.Width();
long nOneY = aOnePixel.Height();
sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab );
long nWidth = (long) (PRINT_HEADER_WIDTH * nScaleX);
long nEndX = nScrX + nWidth;
if ( !bLayoutRTL )
nEndX -= nOneX;
long nPosY = nScrY - nOneY;
nPosY += pDoc->GetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY);
Rectangle aCellRect( nScrX, nScrY, nEndX, nPosY );
rLocationData.AddRowHeaders( aCellRect, nY1, nY2, bRepRow );
}
void ScPrintFunc::LocateArea( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
long nScrX, long nScrY, sal_Bool bRepCol, sal_Bool bRepRow,
ScPreviewLocationData& rLocationData )
{
// get MapMode for drawing objects (same MapMode as in ScOutputData::PrintDrawingLayer)
Point aLogPos = OutputDevice::LogicToLogic(Point(nScrX,nScrY), aOffsetMode, aLogicMode);
long nLogStX = aLogPos.X();
long nLogStY = aLogPos.Y();
SCCOL nCol;
Point aTwipOffset;
for (nCol=0; nCol<nX1; nCol++)
aTwipOffset.X() -= pDoc->GetColWidth( nCol, nPrintTab );
aTwipOffset.Y() -= pDoc->GetRowHeight( 0, nY1-1, nPrintTab );
Point aMMOffset( aTwipOffset );
aMMOffset.X() = (long)(aMMOffset.X() * HMM_PER_TWIPS);
aMMOffset.Y() = (long)(aMMOffset.Y() * HMM_PER_TWIPS);
aMMOffset += Point( nLogStX, nLogStY );
MapMode aDrawMapMode( MAP_100TH_MM, aMMOffset, aLogicMode.GetScaleX(), aLogicMode.GetScaleY() );
// get pixel rectangle
Size aOnePixel = pDev->PixelToLogic(Size(1,1));
long nOneX = aOnePixel.Width();
long nOneY = aOnePixel.Height();
long nPosX = nScrX - nOneX;
for (nCol=nX1; nCol<=nX2; nCol++)
{
sal_uInt16 nDocW = pDoc->GetColWidth( nCol, nPrintTab );
if (nDocW)
nPosX += (long) (nDocW * nScaleX);
}
long nPosY = nScrY - nOneY;
nPosY += pDoc->GetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY);
Rectangle aCellRect( nScrX, nScrY, nPosX, nPosY );
rLocationData.AddCellRange( aCellRect, ScRange( nX1,nY1,nPrintTab, nX2,nY2,nPrintTab ),
bRepCol, bRepRow, aDrawMapMode );
}
void ScPrintFunc::PrintArea( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
long nScrX, long nScrY,
sal_Bool bShLeft, sal_Bool bShTop, sal_Bool bShRight, sal_Bool bShBottom )
{
// #i47547# nothing to do if the end of the print area is before the end of
// the repeat columns/rows (don't use negative size for ScOutputData)
if ( nX2 < nX1 || nY2 < nY1 )
return;
//! Flag bei FillInfo uebergeben !!!!!
ScRange aERange;
sal_Bool bEmbed = pDoc->IsEmbedded();
if (bEmbed)
{
pDoc->GetEmbedded(aERange);
pDoc->ResetEmbedded();
}
Point aPos = OutputDevice::LogicToLogic(Point(nScrX,nScrY), aOffsetMode, aLogicMode);
long nLogStX = aPos.X();
long nLogStY = aPos.Y();
// Daten zusammenstellen
ScTableInfo aTabInfo;
pDoc->FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nPrintTab,
nScaleX, nScaleY, sal_True, aTableParam.bFormulas );
lcl_HidePrint( aTabInfo, nX1, nX2 );
if (bEmbed)
pDoc->SetEmbedded(aERange);
ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pDoc, nPrintTab,
nScrX, nScrY, nX1, nY1, nX2, nY2, nScaleX, nScaleY );
// #114135#
aOutputData.SetDrawView( pDrawView );
// test if all paint parts are hidden, then a paint is not necessary at all
const Point aMMOffset(aOutputData.PrePrintDrawingLayer(nLogStX, nLogStY));
const bool bHideAllDrawingLayer( pDrawView && pDrawView->getHideOle() && pDrawView->getHideChart()
&& pDrawView->getHideDraw() && pDrawView->getHideFormControl() );
if(!bHideAllDrawingLayer)
{
pDev->SetMapMode(aLogicMode);
// hier kein Clipping setzen (Mapmode wird verschoben)
// #i72502#
aOutputData.PrintDrawingLayer(SC_LAYER_BACK, aMMOffset);
}
pDev->SetMapMode(aOffsetMode);
aOutputData.SetShowFormulas( aTableParam.bFormulas );
aOutputData.SetShowNullValues( aTableParam.bNullVals );
aOutputData.SetUseStyleColor( bUseStyleColor );
Color aGridColor( COL_BLACK );
if ( bUseStyleColor )
aGridColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
aOutputData.SetGridColor( aGridColor );
if ( !pPrinter )
{
OutputDevice* pRefDev = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen
Fraction aPrintFrac( nZoom, 100 ); // ohne nManualZoom
// MapMode, wie er beim Drucken herauskommen wuerde:
pRefDev->SetMapMode( MapMode( MAP_100TH_MM, Point(), aPrintFrac, aPrintFrac ) );
// when rendering (PDF), don't use printer as ref device, but printer's MapMode
// has to be set anyway, as charts still use it (#106409#)
if ( !bIsRender )
aOutputData.SetRefDevice( pRefDev );
}
// aOutputData.SetMetaFileMode(sal_True);
if( aTableParam.bCellContent )
aOutputData.DrawBackground();
pDev->SetClipRegion( Rectangle( aPos, Size( aOutputData.GetScrW(), aOutputData.GetScrH() ) ) );
pDev->SetClipRegion();
// aOutputData.SetMetaFileMode(sal_False);
if( aTableParam.bCellContent )
{
aOutputData.DrawExtraShadow( bShLeft, bShTop, bShRight, bShBottom );
aOutputData.DrawFrame();
aOutputData.DrawStrings();
// pDev->SetMapMode(aLogicMode);
aOutputData.DrawEdit(sal_False);
}
// pDev->SetMapMode(aOffsetMode);
if (aTableParam.bGrid)
aOutputData.DrawGrid( sal_True, sal_False ); // keine Seitenumbrueche
/*!!!!!!!!!!! Notizen in Tabelle markieren ??????????????????????????
if (aTableParam.bNotes)
{
pDev->SetMapMode(aOffsetMode);
aOutputData.PrintNoteMarks(aNotePosList);
pDev->SetMapMode(aLogicMode);
}
*/
aOutputData.AddPDFNotes(); // has no effect if not rendering PDF with notes enabled
// pDev->SetMapMode(aDrawMode);
// test if all paint parts are hidden, then a paint is not necessary at all
if(!bHideAllDrawingLayer)
{
// #i72502#
aOutputData.PrintDrawingLayer(SC_LAYER_FRONT, aMMOffset);
}
// #i72502#
aOutputData.PrintDrawingLayer(SC_LAYER_INTERN, aMMOffset);
aOutputData.PostPrintDrawingLayer(aMMOffset); // #i74768#
}
sal_Bool ScPrintFunc::IsMirror( long nPageNo ) // Raender spiegeln ?
{
SvxPageUsage eUsage = (SvxPageUsage) ( nPageUsage & 0x000f );
return ( eUsage == SVX_PAGE_MIRROR && (nPageNo & 1) );
}
sal_Bool ScPrintFunc::IsLeft( long nPageNo ) // linke Fussnoten ?
{
SvxPageUsage eUsage = (SvxPageUsage) ( nPageUsage & 0x000f );
sal_Bool bLeft;
if (eUsage == SVX_PAGE_LEFT)
bLeft = sal_True;
else if (eUsage == SVX_PAGE_RIGHT)
bLeft = sal_False;
else
bLeft = (nPageNo & 1) != 0;
return bLeft;
}
void ScPrintFunc::MakeTableString()
{
pDoc->GetName( nPrintTab, aFieldData.aTabName );
}
void ScPrintFunc::MakeEditEngine()
{
if (!pEditEngine)
{
// can't use document's edit engine pool here,
// because pool must have twips as default metric
pEditEngine = new ScHeaderEditEngine( EditEngine::CreatePool(), sal_True );
pEditEngine->EnableUndo(sal_False);
pEditEngine->SetRefDevice( pDev );
pEditEngine->SetWordDelimiters(
ScEditUtil::ModifyDelimiters( pEditEngine->GetWordDelimiters() ) );
pEditEngine->SetControlWord( pEditEngine->GetControlWord() & ~EE_CNTRL_RTFSTYLESHEETS );
pDoc->ApplyAsianEditSettings( *pEditEngine );
pEditEngine->EnableAutoColor( bUseStyleColor );
// Default-Set fuer Ausrichtung
pEditDefaults = new SfxItemSet( pEditEngine->GetEmptyItemSet() );
const ScPatternAttr& rPattern = (const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN);
rPattern.FillEditItemSet( pEditDefaults );
// FillEditItemSet adjusts font height to 1/100th mm,
// but for header/footer twips is needed, as in the PatternAttr:
pEditDefaults->Put( rPattern.GetItem(ATTR_FONT_HEIGHT), EE_CHAR_FONTHEIGHT );
pEditDefaults->Put( rPattern.GetItem(ATTR_CJK_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CJK );
pEditDefaults->Put( rPattern.GetItem(ATTR_CTL_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CTL );
// #69193# dont use font color, because background color is not used
//! there's no way to set the background for note pages
pEditDefaults->ClearItem( EE_CHAR_COLOR );
if (ScGlobal::IsSystemRTL())
pEditDefaults->Put( SvxFrameDirectionItem( FRMDIR_HORI_RIGHT_TOP, EE_PARA_WRITINGDIR ) );
}
pEditEngine->SetData( aFieldData ); // Seitennummer etc. setzen
}
// nStartY = logic
void ScPrintFunc::PrintHF( long nPageNo, sal_Bool bHeader, long nStartY,
sal_Bool bDoPrint, ScPreviewLocationData* pLocationData )
{
const ScPrintHFParam& rParam = bHeader ? aHdr : aFtr;
pDev->SetMapMode( aTwipMode ); // Kopf-/Fusszeilen in Twips
sal_Bool bLeft = IsLeft(nPageNo) && !rParam.bShared;
const ScPageHFItem* pHFItem = bLeft ? rParam.pLeft : rParam.pRight;
long nLineStartX = aPageRect.Left() + rParam.nLeft;
long nLineEndX = aPageRect.Right() - rParam.nRight;
long nLineWidth = nLineEndX - nLineStartX + 1;
// Edit-Engine
Point aStart( nLineStartX, nStartY );
Size aPaperSize( nLineWidth, rParam.nHeight-rParam.nDistance );
if ( rParam.pBorder )
{
long nLeft = lcl_LineTotal( rParam.pBorder->GetLeft() ) + rParam.pBorder->GetDistance(BOX_LINE_LEFT);
long nTop = lcl_LineTotal( rParam.pBorder->GetTop() ) + rParam.pBorder->GetDistance(BOX_LINE_TOP);
aStart.X() += nLeft;
aStart.Y() += nTop;
aPaperSize.Width() -= nLeft + lcl_LineTotal( rParam.pBorder->GetRight() ) + rParam.pBorder->GetDistance(BOX_LINE_RIGHT);
aPaperSize.Height() -= nTop + lcl_LineTotal( rParam.pBorder->GetBottom() ) + rParam.pBorder->GetDistance(BOX_LINE_BOTTOM);
}
if ( rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE )
{
long nLeft = rParam.pShadow->CalcShadowSpace(SHADOW_LEFT);
long nTop = rParam.pShadow->CalcShadowSpace(SHADOW_TOP);
aStart.X() += nLeft;
aStart.Y() += nTop;
aPaperSize.Width() -= nLeft + rParam.pShadow->CalcShadowSpace(SHADOW_RIGHT);
aPaperSize.Height() -= nTop + rParam.pShadow->CalcShadowSpace(SHADOW_BOTTOM);
}
aFieldData.nPageNo = nPageNo+aTableParam.nFirstPageNo;
MakeEditEngine();
pEditEngine->SetPaperSize(aPaperSize);
const EditTextObject* pObject;
// Rahmen / Hintergrund
Point aBorderStart( nLineStartX, nStartY );
Size aBorderSize( nLineWidth, rParam.nHeight-rParam.nDistance );
if ( rParam.bDynamic )
{
// hier nochmal anpassen, wegen geraden/ungeraden Kopf/Fusszeilen
// und evtl. anderen Umbruechen durch Variablen (Seitennummer etc.)
long nMaxHeight = 0;
nMaxHeight = Max( nMaxHeight, TextHeight( pHFItem->GetLeftArea() ) );
nMaxHeight = Max( nMaxHeight, TextHeight( pHFItem->GetCenterArea() ) );
nMaxHeight = Max( nMaxHeight, TextHeight( pHFItem->GetRightArea() ) );
if (rParam.pBorder)
nMaxHeight += lcl_LineTotal( rParam.pBorder->GetTop() ) +
lcl_LineTotal( rParam.pBorder->GetBottom() ) +
rParam.pBorder->GetDistance(BOX_LINE_TOP) +
rParam.pBorder->GetDistance(BOX_LINE_BOTTOM);
if (rParam.pShadow && rParam.pShadow->GetLocation() != SVX_SHADOW_NONE)
nMaxHeight += rParam.pShadow->CalcShadowSpace(SHADOW_TOP) +
rParam.pShadow->CalcShadowSpace(SHADOW_BOTTOM);
if (nMaxHeight < rParam.nManHeight-rParam.nDistance)
nMaxHeight = rParam.nManHeight-rParam.nDistance; // eingestelltes Minimum
aBorderSize.Height() = nMaxHeight;
}
if ( bDoPrint )
{
double nOldScaleX = nScaleX;
double nOldScaleY = nScaleY;
nScaleX = nScaleY = 1.0; // direkt in Twips ausgeben
DrawBorder( aBorderStart.X(), aBorderStart.Y(), aBorderSize.Width(), aBorderSize.Height(),
rParam.pBorder, rParam.pBack, rParam.pShadow );
nScaleX = nOldScaleX;
nScaleY = nOldScaleY;
// Clipping fuer Text
pDev->SetClipRegion( Rectangle( aStart, aPaperSize ) );
// links
pObject = pHFItem->GetLeftArea();
if (pObject)
{
pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_LEFT, EE_PARA_JUST ) );
pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, sal_False );
Point aDraw = aStart;
long nDif = aPaperSize.Height() - (long) pEditEngine->GetTextHeight();
if (nDif > 0)
aDraw.Y() += nDif / 2;
pEditEngine->Draw( pDev, aDraw, 0 );
}
// Mitte
pObject = pHFItem->GetCenterArea();
if (pObject)
{
pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_CENTER, EE_PARA_JUST ) );
pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, sal_False );
Point aDraw = aStart;
long nDif = aPaperSize.Height() - (long) pEditEngine->GetTextHeight();
if (nDif > 0)
aDraw.Y() += nDif / 2;
pEditEngine->Draw( pDev, aDraw, 0 );
}
// rechts
pObject = pHFItem->GetRightArea();
if (pObject)
{
pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_RIGHT, EE_PARA_JUST ) );
pEditEngine->SetTextNewDefaults( *pObject, *pEditDefaults, sal_False );
Point aDraw = aStart;
long nDif = aPaperSize.Height() - (long) pEditEngine->GetTextHeight();
if (nDif > 0)
aDraw.Y() += nDif / 2;
pEditEngine->Draw( pDev, aDraw, 0 );
}
pDev->SetClipRegion();
}
if ( pLocationData )
{
Rectangle aHeaderRect( aBorderStart, aBorderSize );
pLocationData->AddHeaderFooter( aHeaderRect, bHeader, bLeft );
}
}
long ScPrintFunc::DoNotes( long nNoteStart, sal_Bool bDoPrint, ScPreviewLocationData* pLocationData )
{
if (bDoPrint)
pDev->SetMapMode(aTwipMode);
MakeEditEngine();
pEditDefaults->Put( SvxAdjustItem( SVX_ADJUST_LEFT, EE_PARA_JUST ) );
pEditEngine->SetDefaults( *pEditDefaults );
Font aMarkFont;
ScAutoFontColorMode eColorMode = bUseStyleColor ? SC_AUTOCOL_DISPLAY : SC_AUTOCOL_PRINT;
((const ScPatternAttr&)pDoc->GetPool()->GetDefaultItem(ATTR_PATTERN)).GetFont( aMarkFont, eColorMode );
//? aMarkFont.SetWeight( WEIGHT_BOLD );
pDev->SetFont( aMarkFont );
long nMarkLen = pDev->GetTextWidth(
String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("GW99999:")));
// ohne Space, weil's eh selten so weit kommt
Size aDataSize = aPageRect.GetSize();
if ( nMarkLen > aDataSize.Width() / 2 ) // alles viel zu klein?
nMarkLen = aDataSize.Width() / 2; // Seite bruederlich aufteilen
aDataSize.Width() -= nMarkLen;
pEditEngine->SetPaperSize( aDataSize );
long nPosX = aPageRect.Left() + nMarkLen;
long nPosY = aPageRect.Top();
long nCount = 0;
sal_Bool bOk;
do
{
bOk = sal_False;
ScAddress* pPos = (ScAddress*) aNotePosList.GetObject( nNoteStart+nCount );
if (pPos)
{
ScBaseCell* pCell = pDoc->GetCell( *pPos);
if( const ScPostIt* pNote = pCell->GetNote() )
{
if(const EditTextObject *pEditText = pNote->GetEditTextObject())
pEditEngine->SetText(*pEditText);
long nTextHeight = pEditEngine->GetTextHeight();
if ( nPosY + nTextHeight < aPageRect.Bottom() )
{
if (bDoPrint)
{
pEditEngine->Draw( pDev, Point( nPosX, nPosY ), 0 );
String aMarkStr;
pPos->Format( aMarkStr, SCA_VALID, pDoc, pDoc->GetAddressConvention() );
aMarkStr += ':';
// Zellposition auch per EditEngine, damit die Position stimmt
pEditEngine->SetText(aMarkStr);
pEditEngine->Draw( pDev, Point( aPageRect.Left(), nPosY ), 0 );
}
if ( pLocationData )
{
Rectangle aTextRect( Point( nPosX, nPosY ), Size( aDataSize.Width(), nTextHeight ) );
pLocationData->AddNoteText( aTextRect, *pPos );
Rectangle aMarkRect( Point( aPageRect.Left(), nPosY ), Size( nMarkLen, nTextHeight ) );
pLocationData->AddNoteMark( aMarkRect, *pPos );
}
nPosY += nTextHeight;
nPosY += 200; // Abstand
++nCount;
bOk = sal_True;
}
}
}
}
while (bOk);
return nCount;
}
long ScPrintFunc::PrintNotes( long nPageNo, long nNoteStart, sal_Bool bDoPrint, ScPreviewLocationData* pLocationData )
{
if ( nNoteStart >= (long) aNotePosList.Count() || !aTableParam.bNotes )
return 0;
if ( bDoPrint && bClearWin )
{
//! mit PrintPage zusammenfassen !!!
Color aBackgroundColor( COL_WHITE );
if ( bUseStyleColor )
aBackgroundColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
pDev->SetMapMode(aOffsetMode);
pDev->SetLineColor();
pDev->SetFillColor(aBackgroundColor);
pDev->DrawRect(Rectangle(Point(),
Size((long)(aPageSize.Width() * nScaleX * 100 / nZoom),
(long)(aPageSize.Height() * nScaleY * 100 / nZoom))));
}
// aPageRect auf linke / rechte Seiten anpassen
Rectangle aTempRect = Rectangle( Point(), aPageSize );
if (IsMirror(nPageNo))
{
aPageRect.Left() = ( aTempRect.Left() + nRightMargin ) * 100 / nZoom;
aPageRect.Right() = ( aTempRect.Right() - nLeftMargin ) * 100 / nZoom;
}
else
{
aPageRect.Left() = ( aTempRect.Left() + nLeftMargin ) * 100 / nZoom;
aPageRect.Right() = ( aTempRect.Right() - nRightMargin ) * 100 / nZoom;
}
if ( pPrinter && bDoPrint )
{
DBG_ERROR( "StartPage does not exist anymore" );
// pPrinter->StartPage();
}
if ( bDoPrint || pLocationData )
{
// Kopf- und Fusszeilen
if (aHdr.bEnable)
{
long nHeaderY = aPageRect.Top()-aHdr.nHeight;
PrintHF( nPageNo, sal_True, nHeaderY, bDoPrint, pLocationData );
}
if (aFtr.bEnable)
{
long nFooterY = aPageRect.Bottom()+aFtr.nDistance;
PrintHF( nPageNo, sal_False, nFooterY, bDoPrint, pLocationData );
}
}
long nCount = DoNotes( nNoteStart, bDoPrint, pLocationData );
if ( pPrinter && bDoPrint )
{
DBG_ERROR( "EndPage does not exist anymore" );
// pPrinter->EndPage();
}
return nCount;
}
void ScPrintFunc::PrintPage( long nPageNo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
sal_Bool bDoPrint, ScPreviewLocationData* pLocationData )
{
sal_Bool bLayoutRTL = pDoc->IsLayoutRTL( nPrintTab );
long nLayoutSign = bLayoutRTL ? -1 : 1;
// nPageNo is the page number within all sheets of one "start page" setting
if ( bClearWin && bDoPrint )
{
// muss genau zum Zeichnen des Rahmens in preview.cxx passen !!!
Color aBackgroundColor( COL_WHITE );
if ( bUseStyleColor )
aBackgroundColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
pDev->SetMapMode(aOffsetMode);
pDev->SetLineColor();
pDev->SetFillColor(aBackgroundColor);
pDev->DrawRect(Rectangle(Point(),
Size((long)(aPageSize.Width() * nScaleX * 100 / nZoom),
(long)(aPageSize.Height() * nScaleY * 100 / nZoom))));
}
// aPageRect auf linke / rechte Seiten anpassen
Rectangle aTempRect = Rectangle( Point(), aPageSize );
if (IsMirror(nPageNo))
{
aPageRect.Left() = ( aTempRect.Left() + nRightMargin ) * 100 / nZoom;
aPageRect.Right() = ( aTempRect.Right() - nLeftMargin ) * 100 / nZoom;
}
else
{
aPageRect.Left() = ( aTempRect.Left() + nLeftMargin ) * 100 / nZoom;
aPageRect.Right() = ( aTempRect.Right() - nRightMargin ) * 100 / nZoom;
}
if ( aAreaParam.bRepeatCol )
if ( nX1 > nRepeatStartCol && nX1 <= nRepeatEndCol )
nX1 = nRepeatEndCol + 1;
sal_Bool bDoRepCol = (aAreaParam.bRepeatCol && nX1 > nRepeatEndCol);
if ( aAreaParam.bRepeatRow )
if ( nY1 > nRepeatStartRow && nY1 <= nRepeatEndRow )
nY1 = nRepeatEndRow + 1;
sal_Bool bDoRepRow = (aAreaParam.bRepeatRow && nY1 > nRepeatEndRow);
// use new object hide flags in SdrPaintView
if(pDrawView)
{
pDrawView->setHideOle(!aTableParam.bObjects);
pDrawView->setHideChart(!aTableParam.bCharts);
pDrawView->setHideDraw(!aTableParam.bDrawings);
pDrawView->setHideFormControl(!aTableParam.bDrawings);
}
if ( pPrinter && bDoPrint )
{
DBG_ERROR( "StartPage does not exist anymore" );
// pPrinter->StartPage();
}
// Kopf- und Fusszeilen (ohne Zentrierung)
if (aHdr.bEnable)
{
long nHeaderY = aPageRect.Top()-aHdr.nHeight;
PrintHF( nPageNo, sal_True, nHeaderY, bDoPrint, pLocationData );
}
if (aFtr.bEnable)
{
long nFooterY = aPageRect.Bottom()+aFtr.nDistance;
PrintHF( nPageNo, sal_False, nFooterY, bDoPrint, pLocationData );
}
// Position ( Raender / zentrieren )
long nLeftSpace = aPageRect.Left(); // Document-Twips
long nTopSpace = aPageRect.Top();
if ( bCenterHor || bLayoutRTL )
{
long nDataWidth = 0;
SCCOL i;
for (i=nX1; i<=nX2; i++)
nDataWidth += pDoc->GetColWidth( i,nPrintTab );
if (bDoRepCol)
for (i=nRepeatStartCol; i<=nRepeatEndCol; i++)
nDataWidth += pDoc->GetColWidth( i,nPrintTab );
if (aTableParam.bHeaders)
nDataWidth += (long) PRINT_HEADER_WIDTH;
if (pBorderItem)
nDataWidth += pBorderItem->GetDistance(BOX_LINE_LEFT) +
pBorderItem->GetDistance(BOX_LINE_RIGHT); //! Line width?
if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
nDataWidth += pShadowItem->CalcShadowSpace(SHADOW_LEFT) +
pShadowItem->CalcShadowSpace(SHADOW_RIGHT);
if ( bCenterHor )
{
nLeftSpace += ( aPageRect.GetWidth() - nDataWidth ) / 2; // LTR or RTL
if (pBorderItem)
nLeftSpace -= lcl_LineTotal(pBorderItem->GetLeft());
}
else if ( bLayoutRTL )
nLeftSpace += aPageRect.GetWidth() - nDataWidth; // align to the right edge of the page
}
if ( bCenterVer )
{
long nDataHeight = pDoc->GetRowHeight( nY1, nY2, nPrintTab);
if (bDoRepRow)
nDataHeight += pDoc->GetRowHeight( nRepeatStartRow,
nRepeatEndRow, nPrintTab);
if (aTableParam.bHeaders)
nDataHeight += (long) PRINT_HEADER_HEIGHT;
if (pBorderItem)
nDataHeight += pBorderItem->GetDistance(BOX_LINE_TOP) +
pBorderItem->GetDistance(BOX_LINE_BOTTOM); //! Line width?
if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
nDataHeight += pShadowItem->CalcShadowSpace(SHADOW_TOP) +
pShadowItem->CalcShadowSpace(SHADOW_BOTTOM);
nTopSpace += ( aPageRect.GetHeight() - nDataHeight ) / 2;
if (pBorderItem)
nTopSpace -= lcl_LineTotal(pBorderItem->GetTop());
}
// calculate sizes of the elements for partitioning
// (header, repeat, data)
long nHeaderWidth = 0;
long nHeaderHeight = 0;
long nRepeatWidth = 0;
long nRepeatHeight = 0;
long nContentWidth = 0; // scaled - not the same as nDataWidth above
long nContentHeight = 0;
if (aTableParam.bHeaders)
{
nHeaderWidth = (long) (PRINT_HEADER_WIDTH * nScaleX);
nHeaderHeight = (long) (PRINT_HEADER_HEIGHT * nScaleY);
}
if (bDoRepCol)
for (SCCOL i=nRepeatStartCol; i<=nRepeatEndCol; i++)
nRepeatWidth += (long) (pDoc->GetColWidth(i,nPrintTab) * nScaleX);
if (bDoRepRow)
nRepeatHeight += pDoc->GetScaledRowHeight( nRepeatStartRow,
nRepeatEndRow, nPrintTab, nScaleY);
for (SCCOL i=nX1; i<=nX2; i++)
nContentWidth += (long) (pDoc->GetColWidth(i,nPrintTab) * nScaleX);
nContentHeight += pDoc->GetScaledRowHeight( nY1, nY2, nPrintTab,
nScaleY);
// partition the page
long nStartX = ((long) ( nLeftSpace * nScaleX ));
long nStartY = ((long) ( nTopSpace * nScaleY ));
// nStartX -= aOffset.X(); // schon im MapMode
// nStartY -= aOffset.Y();
long nInnerStartX = nStartX;
long nInnerStartY = nStartY;
if (pBorderItem)
{
nInnerStartX += (long) ( ( lcl_LineTotal(pBorderItem->GetLeft()) +
pBorderItem->GetDistance(BOX_LINE_LEFT) ) * nScaleX );
nInnerStartY += (long) ( ( lcl_LineTotal(pBorderItem->GetTop()) +
pBorderItem->GetDistance(BOX_LINE_TOP) ) * nScaleY );
}
if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
{
nInnerStartX += (long) ( pShadowItem->CalcShadowSpace(SHADOW_LEFT) * nScaleX );
nInnerStartY += (long) ( pShadowItem->CalcShadowSpace(SHADOW_TOP) * nScaleY );
}
if ( bLayoutRTL )
{
// arrange elements starting from the right edge
nInnerStartX += nHeaderWidth + nRepeatWidth + nContentWidth;
// make rounding easier so the elements are really next to each other in preview
Size aOffsetOnePixel = pDev->PixelToLogic( Size(1,1), aOffsetMode );
long nOffsetOneX = aOffsetOnePixel.Width();
nInnerStartX += nOffsetOneX / 2;
}
long nFrameStartX = nInnerStartX;
long nFrameStartY = nInnerStartY;
long nRepStartX = nInnerStartX + nHeaderWidth * nLayoutSign; // widths/heights are 0 if not used
long nRepStartY = nInnerStartY + nHeaderHeight;
long nDataX = nRepStartX + nRepeatWidth * nLayoutSign;
long nDataY = nRepStartY + nRepeatHeight;
long nEndX = nDataX + nContentWidth * nLayoutSign;
long nEndY = nDataY + nContentHeight;
long nFrameEndX = nEndX;
long nFrameEndY = nEndY;
if ( bLayoutRTL )
{
// each element's start position is its left edge
//! subtract one pixel less?
nInnerStartX -= nHeaderWidth; // used for header
nRepStartX -= nRepeatWidth;
nDataX -= nContentWidth;
// continue right of the main elements again
nEndX += nHeaderWidth + nRepeatWidth + nContentWidth;
}
// Seiten-Rahmen / Hintergrund
//! nEndX/Y anpassen
long nBorderEndX = nEndX;
long nBorderEndY = nEndY;
if (pBorderItem)
{
nBorderEndX += (long) ( ( lcl_LineTotal(pBorderItem->GetRight()) +
pBorderItem->GetDistance(BOX_LINE_RIGHT) ) * nScaleX );
nBorderEndY += (long) ( ( lcl_LineTotal(pBorderItem->GetBottom()) +
pBorderItem->GetDistance(BOX_LINE_BOTTOM) ) * nScaleY );
}
if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
{
nBorderEndX += (long) ( pShadowItem->CalcShadowSpace(SHADOW_RIGHT) * nScaleX );
nBorderEndY += (long) ( pShadowItem->CalcShadowSpace(SHADOW_BOTTOM) * nScaleY );
}
if ( bDoPrint )
{
pDev->SetMapMode( aOffsetMode );
DrawBorder( nStartX, nStartY, nBorderEndX-nStartX, nBorderEndY-nStartY,
pBorderItem, pBackgroundItem, pShadowItem );
pDev->SetMapMode( aTwipMode );
}
pDev->SetMapMode( aOffsetMode );
// Wiederholungszeilen/Spalten ausgeben
if (bDoRepCol && bDoRepRow)
{
if ( bDoPrint )
PrintArea( nRepeatStartCol,nRepeatStartRow, nRepeatEndCol,nRepeatEndRow,
nRepStartX,nRepStartY, sal_True,sal_True,sal_False,sal_False );
if ( pLocationData )
LocateArea( nRepeatStartCol,nRepeatStartRow, nRepeatEndCol,nRepeatEndRow,
nRepStartX,nRepStartY, sal_True,sal_True, *pLocationData );
}
if (bDoRepCol)
{
if ( bDoPrint )
PrintArea( nRepeatStartCol,nY1, nRepeatEndCol,nY2, nRepStartX,nDataY,
sal_True,!bDoRepRow,sal_False,sal_True );
if ( pLocationData )
LocateArea( nRepeatStartCol,nY1, nRepeatEndCol,nY2, nRepStartX,nDataY, sal_True,sal_False, *pLocationData );
}
if (bDoRepRow)
{
if ( bDoPrint )
PrintArea( nX1,nRepeatStartRow, nX2,nRepeatEndRow, nDataX,nRepStartY,
!bDoRepCol,sal_True,sal_True,sal_False );
if ( pLocationData )
LocateArea( nX1,nRepeatStartRow, nX2,nRepeatEndRow, nDataX,nRepStartY, sal_False,sal_True, *pLocationData );
}
// Daten ausgeben
if ( bDoPrint )
PrintArea( nX1,nY1, nX2,nY2, nDataX,nDataY, !bDoRepCol,!bDoRepRow,sal_True,sal_True );
if ( pLocationData )
LocateArea( nX1,nY1, nX2,nY2, nDataX,nDataY, sal_False,sal_False, *pLocationData );
// Spalten-/Zeilenkoepfe ausgeben
// nach den Daten (ueber evtl. weitergezeichneten Schatten)
Color aGridColor( COL_BLACK );
if ( bUseStyleColor )
aGridColor.SetColor( SC_MOD()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
if (aTableParam.bHeaders)
{
if ( bDoPrint )
{
pDev->SetLineColor( aGridColor );
pDev->SetFillColor();
pDev->SetMapMode(aOffsetMode);
}
ScPatternAttr aPattern( pDoc->GetPool() );
Font aFont;
ScAutoFontColorMode eColorMode = bUseStyleColor ? SC_AUTOCOL_DISPLAY : SC_AUTOCOL_PRINT;
aPattern.GetFont( aFont, eColorMode, pDev );
pDev->SetFont( aFont );
if (bDoRepCol)
{
if ( bDoPrint )
PrintColHdr( nRepeatStartCol,nRepeatEndCol, nRepStartX,nInnerStartY );
if ( pLocationData )
LocateColHdr( nRepeatStartCol,nRepeatEndCol, nRepStartX,nInnerStartY, sal_True, *pLocationData );
}
if ( bDoPrint )
PrintColHdr( nX1,nX2, nDataX,nInnerStartY );
if ( pLocationData )
LocateColHdr( nX1,nX2, nDataX,nInnerStartY, sal_False, *pLocationData );
if (bDoRepRow)
{
if ( bDoPrint )
PrintRowHdr( nRepeatStartRow,nRepeatEndRow, nInnerStartX,nRepStartY );
if ( pLocationData )
LocateRowHdr( nRepeatStartRow,nRepeatEndRow, nInnerStartX,nRepStartY, sal_True, *pLocationData );
}
if ( bDoPrint )
PrintRowHdr( nY1,nY2, nInnerStartX,nDataY );
if ( pLocationData )
LocateRowHdr( nY1,nY2, nInnerStartX,nDataY, sal_False, *pLocationData );
}
// einfacher Rahmen
if ( bDoPrint && ( aTableParam.bGrid || aTableParam.bHeaders ) )
{
Size aOnePixel = pDev->PixelToLogic(Size(1,1));
long nOneX = aOnePixel.Width();
long nOneY = aOnePixel.Height();
long nLeftX = nFrameStartX;
long nTopY = nFrameStartY - nOneY;
long nRightX = nFrameEndX;
long nBottomY = nFrameEndY - nOneY;
if ( !bLayoutRTL )
{
nLeftX -= nOneX;
nRightX -= nOneX;
}
pDev->SetMapMode(aOffsetMode);
pDev->SetLineColor( aGridColor );
pDev->SetFillColor();
pDev->DrawRect( Rectangle( nLeftX, nTopY, nRightX, nBottomY ) );
// nEndX/Y ohne Rahmen-Anpassung
}
if ( pPrinter && bDoPrint )
{
DBG_ERROR( "EndPage does not exist anymore" );
// pPrinter->EndPage();
}
aLastSourceRange = ScRange( nX1, nY1, nPrintTab, nX2, nY2, nPrintTab );
bSourceRangeValid = sal_True;
}
void ScPrintFunc::SetOffset( const Point& rOfs )
{
aSrcOffset = rOfs;
}
void ScPrintFunc::SetManualZoom( sal_uInt16 nNewZoom )
{
nManualZoom = nNewZoom;
}
void ScPrintFunc::SetClearFlag( sal_Bool bFlag )
{
bClearWin = bFlag;
}
void ScPrintFunc::SetUseStyleColor( sal_Bool bFlag )
{
bUseStyleColor = bFlag;
if (pEditEngine)
pEditEngine->EnableAutoColor( bUseStyleColor );
}
void ScPrintFunc::SetRenderFlag( sal_Bool bFlag )
{
bIsRender = bFlag; // set when using XRenderable (PDF)
}
void ScPrintFunc::SetExclusivelyDrawOleAndDrawObjects()
{
aTableParam.bCellContent = false;
aTableParam.bNotes = false;
aTableParam.bGrid = false;
aTableParam.bHeaders = false;
aTableParam.bFormulas = false;
aTableParam.bNullVals = false;
}
//
// UpdatePages wird nur von aussen gerufen, um die Umbrueche fuer die Anzeige
// richtig zu setzen - immer ohne UserArea
//
sal_Bool ScPrintFunc::UpdatePages()
{
if (!pParamSet)
return sal_False;
// Zoom
nZoom = 100;
if (aTableParam.bScalePageNum || aTableParam.bScaleTo)
nZoom = ZOOM_MIN; // stimmt fuer Umbrueche
else if (aTableParam.bScaleAll)
{
nZoom = aTableParam.nScaleAll;
if ( nZoom <= ZOOM_MIN )
nZoom = ZOOM_MIN;
}
String aName = pDoc->GetPageStyle( nPrintTab );
SCTAB nTabCount = pDoc->GetTableCount();
for (SCTAB nTab=0; nTab<nTabCount; nTab++)
if ( nTab==nPrintTab || pDoc->GetPageStyle(nTab)==aName )
{
// Wiederholungszeilen / Spalten
pDoc->SetRepeatArea( nTab, nRepeatStartCol,nRepeatEndCol, nRepeatStartRow,nRepeatEndRow );
// Umbrueche setzen
ResetBreaks(nTab);
pDocShell->PostPaint(0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID);
}
return sal_True;
}
long ScPrintFunc::CountPages() // setzt auch nPagesX, nPagesY
{
sal_Bool bAreaOk = sal_False;
if (pDoc->HasTable( nPrintTab ))
{
if (aAreaParam.bPrintArea) // Druckbereich angegeben?
{
if ( bPrintCurrentTable )
{
ScRange& rRange = aAreaParam.aPrintArea;
// hier kein Vergleich der Tabellen mehr, die Area gilt immer fuer diese Tabelle
// wenn hier verglichen werden soll, muss die Tabelle der Druckbereiche beim
// Einfuegen von Tabellen etc. angepasst werden !
nStartCol = rRange.aStart.Col();
nStartRow = rRange.aStart.Row();
nEndCol = rRange.aEnd .Col();
nEndRow = rRange.aEnd .Row();
bAreaOk = AdjustPrintArea(sal_False); // begrenzen
}
else
bAreaOk = sal_False;
}
else // aus Dokument suchen
bAreaOk = AdjustPrintArea(sal_True);
}
if (bAreaOk)
{
long nPages = 0;
size_t nY;
if (bMultiArea)
{
sal_uInt16 nRCount = pDoc->GetPrintRangeCount( nPrintTab );
for (sal_uInt16 i=0; i<nRCount; i++)
{
CalcZoom(i);
if ( aTableParam.bSkipEmpty )
for (nY=0; nY<nPagesY; nY++)
{
OSL_ENSURE(nY < maPageRows.size(), "vector access error for maPageRows (!)");
nPages += maPageRows[nY].CountVisible();
}
else
nPages += ((long) nPagesX) * nPagesY;
if ( pPageData )
FillPageData();
}
}
else
{
CalcZoom(RANGENO_NORANGE); // Zoom berechnen
if ( aTableParam.bSkipEmpty )
for (nY=0; nY<nPagesY; nY++)
{
OSL_ENSURE(nY < maPageRows.size(), "vector access error for maPageRows (!)");
nPages += maPageRows[nY].CountVisible();
}
else
nPages += ((long) nPagesX) * nPagesY;
if ( pPageData )
FillPageData();
}
return nPages;
}
else
{
// nZoom = 100; // nZoom auf letztem Wert stehenlassen !!!
nPagesX = nPagesY = nTotalY = 0;
return 0;
}
}
long ScPrintFunc::CountNotePages()
{
if ( !aTableParam.bNotes || !bPrintCurrentTable )
return 0;
long nCount=0;
SCCOL nCol;
SCROW nRow;
sal_Bool bError = sal_False;
if (!aAreaParam.bPrintArea)
bError = !AdjustPrintArea(sal_True); // komplett aus Dok suchen
sal_uInt16 nRepeats = 1; // wie oft durchgehen ?
if (bMultiArea)
nRepeats = pDoc->GetPrintRangeCount(nPrintTab);
if (bError)
nRepeats = 0;
for (sal_uInt16 nStep=0; nStep<nRepeats; nStep++)
{
sal_Bool bDoThis = sal_True;
if (bMultiArea) // alle Areas durchgehen
{
const ScRange* pThisRange = pDoc->GetPrintRange( nPrintTab, nStep );
if ( pThisRange )
{
nStartCol = pThisRange->aStart.Col();
nStartRow = pThisRange->aStart.Row();
nEndCol = pThisRange->aEnd .Col();
nEndRow = pThisRange->aEnd .Row();
bDoThis = AdjustPrintArea(sal_False);
}
}
if (bDoThis)
{
ScHorizontalCellIterator aIter( pDoc, nPrintTab, nStartCol,nStartRow, nEndCol,nEndRow );
ScBaseCell* pCell = aIter.GetNext( nCol, nRow );
while (pCell)
{
if (pCell->HasNote())
{
aNotePosList.Insert( new ScAddress( nCol,nRow,nPrintTab ), LIST_APPEND );
++nCount;
}
pCell = aIter.GetNext( nCol, nRow );
}
}
}
long nPages = 0;
long nNoteNr = 0;
long nNoteAdd;
do
{
nNoteAdd = PrintNotes( nPages, nNoteNr, sal_False, NULL );
if (nNoteAdd)
{
nNoteNr += nNoteAdd;
++nPages;
}
}
while (nNoteAdd);
return nPages;
}
void ScPrintFunc::InitModes() // aus nZoom etc. die MapModes setzen
{
aOffset = Point( aSrcOffset.X()*100/nZoom, aSrcOffset.Y()*100/nZoom );
long nEffZoom = nZoom * (long) nManualZoom;
// nScaleX = nScaleY = 1.0; // Ausgabe in Twips
nScaleX = nScaleY = HMM_PER_TWIPS; // Ausgabe in 1/100 mm
Fraction aZoomFract( nEffZoom,10000 );
Fraction aHorFract = aZoomFract;
if ( !pPrinter && !bIsRender ) // adjust scale for preview
{
double nFact = pDocShell->GetOutputFactor();
aHorFract = Fraction( (long)( nEffZoom / nFact ), 10000 );
}
aLogicMode = MapMode( MAP_100TH_MM, Point(), aHorFract, aZoomFract );
Point aLogicOfs( -aOffset.X(), -aOffset.Y() );
aOffsetMode = MapMode( MAP_100TH_MM, aLogicOfs, aHorFract, aZoomFract );
Point aTwipsOfs( (long) ( -aOffset.X() / nScaleX + 0.5 ), (long) ( -aOffset.Y() / nScaleY + 0.5 ) );
aTwipMode = MapMode( MAP_TWIP, aTwipsOfs, aHorFract, aZoomFract );
}
//--------------------------------------------------------------------
void ScPrintFunc::ApplyPrintSettings()
{
if ( pPrinter )
{
//
// Printer zum Drucken umstellen
//
Size aEnumSize = aPageSize;
pPrinter->SetOrientation( bLandscape ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT );
if ( bLandscape )
{
// landscape is always interpreted as a rotation by 90 degrees !
// this leads to non WYSIWIG but at least it prints!
// #i21775#
long nTemp = aEnumSize.Width();
aEnumSize.Width() = aEnumSize.Height();
aEnumSize.Height() = nTemp;
}
Paper ePaper = SvxPaperInfo::GetSvxPaper( aEnumSize, MAP_TWIP, sal_True );
sal_uInt16 nPaperBin = ((const SvxPaperBinItem&)pParamSet->Get(ATTR_PAGE_PAPERBIN)).GetValue();
pPrinter->SetPaper( ePaper );
if ( PAPER_USER == ePaper )
{
MapMode aPrinterMode = pPrinter->GetMapMode();
MapMode aLocalMode( MAP_TWIP );
pPrinter->SetMapMode( aLocalMode );
pPrinter->SetPaperSizeUser( aEnumSize );
pPrinter->SetMapMode( aPrinterMode );
}
pPrinter->SetPaperBin( nPaperBin );
}
}
//--------------------------------------------------------------------
// rPageRanges = Range fuer alle Tabellen
// nStartPage = in rPageRanges beginnen bei nStartPage
// nDisplayStart = lfd. Nummer fuer Anzeige der Seitennummer
long ScPrintFunc::DoPrint( const MultiSelection& rPageRanges,
long nStartPage, long nDisplayStart, sal_Bool bDoPrint,
ScPreviewLocationData* pLocationData )
{
DBG_ASSERT(pDev,"Device == NULL");
if (!pParamSet)
return 0;
if ( pPrinter && bDoPrint )
ApplyPrintSettings();
//--------------------------------------------------------------------
InitModes();
if ( pLocationData )
{
pLocationData->SetCellMapMode( aOffsetMode );
pLocationData->SetPrintTab( nPrintTab );
}
MakeTableString();
//--------------------------------------------------------------------
long nPageNo = 0;
long nPrinted = 0;
long nEndPage = rPageRanges.GetTotalRange().Max();
sal_uInt16 nRepeats = 1; // wie oft durchgehen ?
if (bMultiArea)
nRepeats = pDoc->GetPrintRangeCount(nPrintTab);
for (sal_uInt16 nStep=0; nStep<nRepeats; nStep++)
{
if (bMultiArea) // Bereich neu belegen ?
{
CalcZoom(nStep); // setzt auch nStartCol etc. neu
InitModes();
}
SCCOL nX1;
SCROW nY1;
SCCOL nX2;
SCROW nY2;
size_t nCountX;
size_t nCountY;
if (aTableParam.bTopDown) // von oben nach unten
{
nX1 = nStartCol;
for (nCountX=0; nCountX<nPagesX; nCountX++)
{
OSL_ENSURE(nCountX < maPageEndX.size(), "vector access error for maPageEndX (!)");
nX2 = maPageEndX[nCountX];
for (nCountY=0; nCountY<nPagesY; nCountY++)
{
OSL_ENSURE(nCountY < maPageRows.size(), "vector access error for maPageRows (!)");
nY1 = maPageRows[nCountY].GetStartRow();
nY2 = maPageRows[nCountY].GetEndRow();
if ( !aTableParam.bSkipEmpty || !maPageRows[nCountY].IsHidden(nCountX) )
{
if ( rPageRanges.IsSelected( nPageNo+nStartPage+1 ) )
{
PrintPage( nPageNo+nDisplayStart, nX1, nY1, nX2, nY2,
bDoPrint, pLocationData );
++nPrinted;
}
++nPageNo;
}
}
nX1 = nX2 + 1;
}
}
else // von links nach rechts
{
for (nCountY=0; nCountY<nPagesY; nCountY++)
{
OSL_ENSURE(nCountY < maPageRows.size(), "vector access error for maPageRows (!)");
nY1 = maPageRows[nCountY].GetStartRow();
nY2 = maPageRows[nCountY].GetEndRow();
nX1 = nStartCol;
for (nCountX=0; nCountX<nPagesX; nCountX++)
{
OSL_ENSURE(nCountX < maPageEndX.size(), "vector access error for maPageEndX (!)");
nX2 = maPageEndX[nCountX];
if ( !aTableParam.bSkipEmpty || !maPageRows[nCountY].IsHidden(nCountX) )
{
if ( rPageRanges.IsSelected( nPageNo+nStartPage+1 ) )
{
PrintPage( nPageNo+nDisplayStart, nX1, nY1, nX2, nY2,
bDoPrint, pLocationData );
++nPrinted;
}
++nPageNo;
}
nX1 = nX2 + 1;
}
}
}
}
aFieldData.aTabName = ScGlobal::GetRscString( STR_NOTES );
long nNoteNr = 0;
long nNoteAdd;
do
{
if ( nPageNo+nStartPage <= nEndPage )
{
sal_Bool bPageSelected = rPageRanges.IsSelected( nPageNo+nStartPage+1 );
nNoteAdd = PrintNotes( nPageNo+nStartPage, nNoteNr, bDoPrint && bPageSelected,
( bPageSelected ? pLocationData : NULL ) );
if ( nNoteAdd )
{
nNoteNr += nNoteAdd;
if (bPageSelected)
{
++nPrinted;
bSourceRangeValid = sal_False; // last page was no cell range
}
++nPageNo;
}
}
else
nNoteAdd = 0;
}
while (nNoteAdd);
if ( bMultiArea )
ResetBreaks(nPrintTab); // Breaks fuer Anzeige richtig
return nPrinted;
}
void ScPrintFunc::CalcZoom( sal_uInt16 nRangeNo ) // Zoom berechnen
{
sal_uInt16 nRCount = pDoc->GetPrintRangeCount( nPrintTab );
const ScRange* pThisRange = NULL;
if ( nRangeNo != RANGENO_NORANGE || nRangeNo < nRCount )
pThisRange = pDoc->GetPrintRange( nPrintTab, nRangeNo );
if ( pThisRange )
{
nStartCol = pThisRange->aStart.Col();
nStartRow = pThisRange->aStart.Row();
nEndCol = pThisRange->aEnd .Col();
nEndRow = pThisRange->aEnd .Row();
}
if (!AdjustPrintArea(sal_False)) // leer
{
nZoom = 100;
nPagesX = nPagesY = nTotalY = 0;
return;
}
pDoc->SetRepeatArea( nPrintTab, nRepeatStartCol,nRepeatEndCol, nRepeatStartRow,nRepeatEndRow );
if (aTableParam.bScalePageNum)
{
nZoom = 100;
sal_uInt16 nPagesToFit = aTableParam.nScalePageNum;
sal_uInt16 nLastFitZoom = 0, nLastNonFitZoom = 0;
while (true)
{
if (nZoom <= ZOOM_MIN)
break;
CalcPages();
bool bFitsPage = (nPagesX * nPagesY <= nPagesToFit);
if (bFitsPage)
{
if (nZoom == 100)
// If it fits at 100 %, it's good enough for me.
break;
nLastFitZoom = nZoom;
nZoom = (nLastNonFitZoom + nZoom) / 2;
if (nLastFitZoom == nZoom)
// It converged. Use this zoom level.
break;
}
else
{
if (nZoom - nLastFitZoom <= 1)
{
nZoom = nLastFitZoom;
CalcPages();
break;
}
nLastNonFitZoom = nZoom;
nZoom = (nLastFitZoom + nZoom) / 2;
}
}
}
else if (aTableParam.bScaleTo)
{
nZoom = 100;
sal_uInt16 nW = aTableParam.nScaleWidth;
sal_uInt16 nH = aTableParam.nScaleHeight;
sal_uInt16 nLastFitZoom = 0, nLastNonFitZoom = 0;
while (true)
{
if (nZoom <= ZOOM_MIN)
break;
CalcPages();
bool bFitsPage = ((!nW || (nPagesX <= nW)) && (!nH || (nPagesY <= nH)));
if (bFitsPage)
{
if (nZoom == 100)
// If it fits at 100 %, it's good enough for me.
break;
nLastFitZoom = nZoom;
nZoom = (nLastNonFitZoom + nZoom) / 2;
if (nLastFitZoom == nZoom)
// It converged. Use this zoom level.
break;
}
else
{
if (nZoom - nLastFitZoom <= 1)
{
nZoom = nLastFitZoom;
CalcPages();
break;
}
nLastNonFitZoom = nZoom;
nZoom = (nLastFitZoom + nZoom) / 2;
}
}
}
else if (aTableParam.bScaleAll)
{
nZoom = aTableParam.nScaleAll;
if ( nZoom <= ZOOM_MIN )
nZoom = ZOOM_MIN;
CalcPages();
}
else
{
DBG_ASSERT( aTableParam.bScaleNone, "kein Scale-Flag gesetzt" );
nZoom = 100;
CalcPages();
}
}
Size ScPrintFunc::GetDocPageSize()
{
// Hoehe Kopf-/Fusszeile anpassen
InitModes(); // aTwipMode aus nZoom initialisieren
pDev->SetMapMode( aTwipMode ); // Kopf-/Fusszeilen in Twips
UpdateHFHeight( aHdr );
UpdateHFHeight( aFtr );
// Seitengroesse in Document-Twips
// Berechnung Left / Right auch in PrintPage
aPageRect = Rectangle( Point(), aPageSize );
aPageRect.Left() = ( aPageRect.Left() + nLeftMargin ) * 100 / nZoom;
aPageRect.Right() = ( aPageRect.Right() - nRightMargin ) * 100 / nZoom;
aPageRect.Top() = ( aPageRect.Top() + nTopMargin ) * 100 / nZoom + aHdr.nHeight;
aPageRect.Bottom() = ( aPageRect.Bottom() - nBottomMargin ) * 100 / nZoom - aFtr.nHeight;
Size aDocPageSize = aPageRect.GetSize();
if (aTableParam.bHeaders)
{
aDocPageSize.Width() -= (long) PRINT_HEADER_WIDTH;
aDocPageSize.Height() -= (long) PRINT_HEADER_HEIGHT;
}
if (pBorderItem)
{
aDocPageSize.Width() -= lcl_LineTotal(pBorderItem->GetLeft()) +
lcl_LineTotal(pBorderItem->GetRight()) +
pBorderItem->GetDistance(BOX_LINE_LEFT) +
pBorderItem->GetDistance(BOX_LINE_RIGHT);
aDocPageSize.Height() -= lcl_LineTotal(pBorderItem->GetTop()) +
lcl_LineTotal(pBorderItem->GetBottom()) +
pBorderItem->GetDistance(BOX_LINE_TOP) +
pBorderItem->GetDistance(BOX_LINE_BOTTOM);
}
if (pShadowItem && pShadowItem->GetLocation() != SVX_SHADOW_NONE)
{
aDocPageSize.Width() -= pShadowItem->CalcShadowSpace(SHADOW_LEFT) +
pShadowItem->CalcShadowSpace(SHADOW_RIGHT);
aDocPageSize.Height() -= pShadowItem->CalcShadowSpace(SHADOW_TOP) +
pShadowItem->CalcShadowSpace(SHADOW_BOTTOM);
}
return aDocPageSize;
}
void ScPrintFunc::ResetBreaks( SCTAB nTab ) // Breaks fuer Anzeige richtig setzen
{
pDoc->SetPageSize( nTab, GetDocPageSize() );
pDoc->UpdatePageBreaks( nTab, NULL );
}
void lcl_SetHidden( ScDocument* pDoc, SCTAB nPrintTab, ScPageRowEntry& rPageRowEntry, SCCOL nStartCol, const std::vector< SCCOL >& aPageEndX)
{
size_t nPagesX = rPageRowEntry.GetPagesX();
SCROW nStartRow = rPageRowEntry.GetStartRow();
SCROW nEndRow = rPageRowEntry.GetEndRow();
sal_Bool bLeftIsEmpty = sal_False;
ScRange aTempRange;
Rectangle aTempRect = pDoc->GetMMRect( 0,0, 0,0, 0 );
for (size_t i=0; i<nPagesX; i++)
{
OSL_ENSURE(i < aPageEndX.size(), "vector access error for maPageEndX (!)");
SCCOL nEndCol = aPageEndX[i];
if ( pDoc->IsPrintEmpty( nPrintTab, nStartCol, nStartRow, nEndCol, nEndRow,
bLeftIsEmpty, &aTempRange, &aTempRect ) )
{
rPageRowEntry.SetHidden(i);
bLeftIsEmpty = sal_True;
}
else
bLeftIsEmpty = sal_False;
nStartCol = nEndCol+1;
}
}
void ScPrintFunc::CalcPages() // berechnet aPageRect und Seiten aus nZoom
{
// #123672# use dynamic mem to react on size changes
if(maPageEndX.size() < MAXCOL+1)
{
maPageEndX.resize(MAXCOL+1, SCCOL());
}
pDoc->SetPageSize( nPrintTab, GetDocPageSize() );
if (aAreaParam.bPrintArea)
{
ScRange aRange( nStartCol, nStartRow, nPrintTab, nEndCol, nEndRow, nPrintTab );
pDoc->UpdatePageBreaks( nPrintTab, &aRange );
}
else
{
pDoc->UpdatePageBreaks( nPrintTab, NULL ); // sonst wird das Ende markiert
}
const SCROW nRealCnt = nEndRow-nStartRow+1;
// #123672# use dynamic mem to react on size changes
if(maPageEndY.size() < nRealCnt+1)
{
maPageEndY.resize(nRealCnt+1, SCROW());
}
// #123672# use dynamic mem to react on size changes
if(maPageRows.size() < nRealCnt+1)
{
maPageRows.resize(nRealCnt+1, ScPageRowEntry());
}
//
// Seiteneinteilung nach Umbruechen in Col/RowFlags
// Von mehreren Umbruechen in einem ausgeblendeten Bereich zaehlt nur einer.
//
nPagesX = 0;
nPagesY = 0;
nTotalY = 0;
bool bVisCol = false;
SCCOL nLastCol = -1;
for (SCCOL i=nStartCol; i<=nEndCol; i++)
{
bool bHidden = pDoc->ColHidden(i, nPrintTab, nLastCol);
bool bPageBreak = (pDoc->HasColBreak(i, nPrintTab) & BREAK_PAGE);
if ( i>nStartCol && bVisCol && bPageBreak )
{
OSL_ENSURE(nPagesX < maPageEndX.size(), "vector access error for maPageEndX (!)");
maPageEndX[nPagesX] = i-1;
++nPagesX;
bVisCol = false;
}
if (!bHidden)
bVisCol = true;
}
if (bVisCol) // auch am Ende keine leeren Seiten
{
OSL_ENSURE(nPagesX < maPageEndX.size(), "vector access error for maPageEndX (!)");
maPageEndX[nPagesX] = nEndCol;
++nPagesX;
}
bool bVisRow = false;
SCROW nPageStartRow = nStartRow;
SCROW nLastVisibleRow = -1;
::boost::scoped_ptr<ScRowBreakIterator> pRowBreakIter(pDoc->GetRowBreakIterator(nPrintTab));
SCROW nNextPageBreak = pRowBreakIter->first();
while (nNextPageBreak != ScRowBreakIterator::NOT_FOUND && nNextPageBreak < nStartRow)
// Skip until the page break position is at the start row or greater.
nNextPageBreak = pRowBreakIter->next();
for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
{
bool bPageBreak = (nNextPageBreak == nRow);
if (bPageBreak)
nNextPageBreak = pRowBreakIter->next();
if (nRow > nStartRow && bVisRow && bPageBreak )
{
OSL_ENSURE(nTotalY < maPageEndY.size(), "vector access error for maPageEndY (!)");
maPageEndY[nTotalY] = nRow-1;
++nTotalY;
if ( !aTableParam.bSkipEmpty ||
!pDoc->IsPrintEmpty( nPrintTab, nStartCol, nPageStartRow, nEndCol, nRow-1 ) )
{
OSL_ENSURE(nPagesY < maPageRows.size(), "vector access error for maPageRows (!)");
maPageRows[nPagesY].SetStartRow( nPageStartRow );
maPageRows[nPagesY].SetEndRow( nRow-1 );
maPageRows[nPagesY].SetPagesX( nPagesX );
if (aTableParam.bSkipEmpty)
lcl_SetHidden( pDoc, nPrintTab, maPageRows[nPagesY], nStartCol, maPageEndX );
++nPagesY;
}
nPageStartRow = nRow;
bVisRow = false;
}
if (nRow <= nLastVisibleRow)
{
// This row is still visible. Don't bother calling RowHidden() to
// find out, for speed optimization.
bVisRow = true;
continue;
}
SCROW nLastRow = -1;
if (!pDoc->RowHidden(nRow, nPrintTab, NULL, &nLastRow))
{
bVisRow = true;
nLastVisibleRow = nLastRow;
}
else
// skip all hidden rows.
nRow = nLastRow;
}
if (bVisRow)
{
OSL_ENSURE(nTotalY < maPageEndY.size(), "vector access error for maPageEndY (!)");
maPageEndY[nTotalY] = nEndRow;
++nTotalY;
if ( !aTableParam.bSkipEmpty ||
!pDoc->IsPrintEmpty( nPrintTab, nStartCol, nPageStartRow, nEndCol, nEndRow ) )
{
OSL_ENSURE(nPagesY < maPageRows.size(), "vector access error for maPageRows (!)");
maPageRows[nPagesY].SetStartRow( nPageStartRow );
maPageRows[nPagesY].SetEndRow( nEndRow );
maPageRows[nPagesY].SetPagesX( nPagesX );
if (aTableParam.bSkipEmpty)
lcl_SetHidden( pDoc, nPrintTab, maPageRows[nPagesY], nStartCol, maPageEndX );
++nPagesY;
}
}
}
//------------------------------------------------------------------------
// class ScJobSetup
//------------------------------------------------------------------------
ScJobSetup::ScJobSetup( SfxPrinter* pPrinter )
{
eOrientation = pPrinter->GetOrientation();
nPaperBin = pPrinter->GetPaperBin();
ePaper = pPrinter->GetPaper();
if ( PAPER_USER == ePaper )
{
aUserSize = pPrinter->GetPaperSize();
aUserMapMode = pPrinter->GetMapMode();
}
};