Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/sc/source/ui/view/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 115 kB image not shown  

Quelle  printfun.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   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 .
 */


#include <scitems.hxx>
#include <editeng/eeitem.hxx>

#include <printfun.hxx>

#include <editeng/adjustitem.hxx>
#include <editeng/borderline.hxx>
#include <editeng/boxitem.hxx>
#include <editeng/brushitem.hxx>
#include <svtools/colorcfg.hxx>
#include <editeng/editstat.hxx>
#include <svx/fmview.hxx>
#include <vcl/pdfextoutdevdata.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 <editeng/fhgtitem.hxx>
#include <editeng/ulspitem.hxx>
#include <sfx2/printer.hxx>
#include <tools/multisel.hxx>
#include <sfx2/docfile.hxx>
#include <tools/urlobj.hxx>
#include <osl/diagnose.h>

#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 <dociter.hxx>
#include <globstr.hrc>
#include <scresid.hxx>
#include <pagedata.hxx>
#include <printopt.hxx>
#include <prevloc.hxx>
#include <scmod.hxx>
#include <drwlayer.hxx>
#include <fillinfo.hxx>
#include <postit.hxx>

#include <memory>
#include <com/sun/star/document/XDocumentProperties.hpp>

#define ZOOM_MIN    10

namespace{

bool lcl_GetBool(const SfxItemSet* pSet, sal_uInt16 nWhich)
{
    return static_cast<const SfxBoolItem&>(pSet->Get(nWhich)).GetValue();
}

sal_uInt16 lcl_GetUShort(const SfxItemSet* pSet, sal_uInt16 nWhich)
{
    return static_cast<const SfxUInt16Item&>(pSet->Get(nWhich)).GetValue();
}

bool lcl_GetShow(const SfxItemSet* pSet, sal_uInt16 nWhich)
{
    return ScVObjMode::VOBJ_MODE_SHOW == static_cast<const ScViewObjectModeItem&>(pSet->Get(nWhich)).GetValue();
}


// namespace

ScPageRowEntry::ScPageRowEntry(const ScPageRowEntry& r)
{
    nStartRow = r.nStartRow;
    nEndRow   = r.nEndRow;
    nPagesX   = r.nPagesX;
    aHidden   = r.aHidden;
    aHidden.resize(nPagesX, false);
}

ScPageRowEntry& ScPageRowEntry::operator=(const ScPageRowEntry& r)
{
    nStartRow = r.nStartRow;
    nEndRow   = r.nEndRow;
    nPagesX   = r.nPagesX;
    aHidden   = r.aHidden;
    aHidden.resize(nPagesX, false);
    return *this;
}

void ScPageRowEntry::SetPagesX(size_t nNew)
{
    nPagesX = nNew;
    aHidden.resize(nPagesX, false);
}

void ScPageRowEntry::SetHidden(size_t nX)
{
    if ( nX < nPagesX )
    {
        if ( nX+1 == nPagesX )  // last page?
            --nPagesX;
        else
        {
            aHidden.resize(nPagesX, false);
            aHidden[nX] = true;
        }
    }
}

bool ScPageRowEntry::IsHidden(size_t nX) const
{
    return nX >= nPagesX || aHidden[nX];       //! inline?
}

size_t ScPageRowEntry::CountVisible() const
{
    if (!aHidden.empty())
    {
        size_t nVis = 0;
        for (size_t i=0; i<nPagesX; i++)
            if (!aHidden[i])
                ++nVis;
        return nVis;
    }
    else
        return nPagesX;
}

static tools::Long lcl_LineTotal(const ::editeng::SvxBorderLine* pLine)
{
    return pLine ? ( pLine->GetScaledWidth() ) : 0;
}

void ScPrintFunc::Construct( const ScPrintOptions* pOptions )
{
    rDocShell.UpdatePendingRowHeights( nPrintTab );

    SfxPrinter* pDocPrinter = rDoc.GetPrinter();   // use the printer, even for preview
    if (pDocPrinter)
        aOldPrinterMode = pDocPrinter->GetMapMode();

    //  unified MapMode for all calls (e.g. Repaint!!!)
    //  else, EditEngine outputs different text heights
    pDev->SetMapMode(MapMode(MapUnit::MapPixel));

    pBorderItem = nullptr;
    pBackgroundItem = nullptr;
    pShadowItem = nullptr;

    pEditEngine = nullptr;
    pEditDefaults = nullptr;

    ScStyleSheetPool* pStylePool    = rDoc.GetStyleSheetPool();
    SfxStyleSheetBase* pStyleSheet  = pStylePool->Find(
                                            rDoc.GetPageStyle( nPrintTab ),
                                            SfxStyleFamily::Page );
    if (pStyleSheet)
        pParamSet = &pStyleSheet->GetItemSet();
    else
    {
        OSL_FAIL("Template not found" );
        pParamSet = nullptr;
    }

    if (!bFromPrintState)
        nZoom = 100;
    nManualZoom = 100;
    bClearWin = false;
    bUseStyleColor = false;
    bIsRender = false;

    InitParam(pOptions);

    pPageData = nullptr;       // is only needed for initialisation
}

ScPrintFunc::ScPrintFunc(ScDocShell& rShell, SfxPrinter* pNewPrinter, SCTAB nTab, tools::Long nPage,
                         tools::Long nDocP, const ScRange* pArea, const ScPrintOptions* pOptions,
                         ScPageBreakData* pData, Size aSize, bool bPrintLandscape, bool bUsed)
    :   rDocShell           ( rShell ),
        rDoc(rDocShell.GetDocument()),
        pPrinter            ( pNewPrinter ),
        pDrawView           ( nullptr ),
        nPrintTab           ( nTab ),
        nPageStart          ( nPage ),
        nDocPages           ( nDocP ),
        pUserArea           ( pArea ),
        bFromPrintState     ( false ),
        bSourceRangeValid   ( false ),
        bPrintCurrentTable  ( false ),
        bMultiArea          ( false ),
        mbHasPrintRange(true),
        nTabPages           ( 0 ),
        nTotalPages         ( 0 ),
        bPrintAreaValid     ( false ),
        pPageData           ( pData ),
        aPrintPageSize      ( aSize ),
        bPrintPageLandscape ( bPrintLandscape ),
        bUsePrintDialogSetting ( bUsed )
{
    pDev = pPrinter.get();
    aSrcOffset = pPrinter->PixelToLogic(pPrinter->GetPageOffsetPixel(), MapMode(MapUnit::Map100thMM));
    m_aRanges.m_xPageEndX = std::make_shared<std::vector<SCCOL>>();
    m_aRanges.m_xPageEndY = std::make_shared<std::vector<SCROW>>();
    m_aRanges.m_xPageRows = std::make_shared<std::map<size_t, ScPageRowEntry>>();
    Construct( pOptions );
}

ScPrintFunc::ScPrintFunc(ScDocShell& rShell, SfxPrinter* pNewPrinter, const ScPrintState& rState,
                         const ScPrintOptions* pOptions, Size aSize, bool bPrintLandscape,
                         bool bUsed)
    :   rDocShell           ( rShell ),
        rDoc(rDocShell.GetDocument()),
        pPrinter            ( pNewPrinter ),
        pDrawView           ( nullptr ),
        pUserArea           ( nullptr ),
        bSourceRangeValid   ( false ),
        bPrintCurrentTable  ( false ),
        bMultiArea          ( false ),
        mbHasPrintRange(true),
        pPageData           ( nullptr ),
        aPrintPageSize      ( aSize ),
        bPrintPageLandscape ( bPrintLandscape ),
        bUsePrintDialogSetting ( bUsed )
{
    pDev = pPrinter.get();

    nPrintTab   = rState.nPrintTab;
    nStartCol   = rState.nStartCol;
    nStartRow   = rState.nStartRow;
    nEndCol     = rState.nEndCol;
    nEndRow     = rState.nEndRow;
    bPrintAreaValid = rState.bPrintAreaValid;
    nZoom       = rState.nZoom;
    m_aRanges = rState.m_aRanges;
    nTabPages   = rState.nTabPages;
    nTotalPages = rState.nTotalPages;
    nPageStart  = rState.nPageStart;
    nDocPages   = rState.nDocPages;
    bFromPrintState = true;

    aSrcOffset = pPrinter->PixelToLogic(pPrinter->GetPageOffsetPixel(), MapMode(MapUnit::Map100thMM));
    Construct( pOptions );
}

ScPrintFunc::ScPrintFunc( OutputDevice* pOutDev, ScDocShell& rShell, SCTAB nTab,
                            tools::Long nPage, tools::Long nDocP, const ScRange* pArea,
                            const ScPrintOptions* pOptions )
    :   rDocShell           ( rShell ),
        rDoc(rDocShell.GetDocument()),
        pPrinter            ( nullptr ),
        pDrawView           ( nullptr ),
        nPrintTab           ( nTab ),
        nPageStart          ( nPage ),
        nDocPages           ( nDocP ),
        pUserArea           ( pArea ),
        bFromPrintState     ( false ),
        bSourceRangeValid   ( false ),
        bPrintCurrentTable  ( false ),
        bMultiArea          ( false ),
        mbHasPrintRange(true),
        nTabPages           ( 0 ),
        nTotalPages         ( 0 ),
        bPrintAreaValid     ( false ),
        pPageData           ( nullptr ),
        aPrintPageSize      ( Size() ),
        bPrintPageLandscape ( false ),
        bUsePrintDialogSetting ( false )
{
    pDev = pOutDev;
    m_aRanges.m_xPageEndX = std::make_shared<std::vector<SCCOL>>();
    m_aRanges.m_xPageEndY = std::make_shared<std::vector<SCROW>>();
    m_aRanges.m_xPageRows = std::make_shared<std::map<size_t, ScPageRowEntry>>();
    Construct( pOptions );
}

ScPrintFunc::ScPrintFunc(OutputDevice* pOutDev, ScDocShell& rShell, const ScPrintState& rState,
                         const ScPrintOptions* pOptions, Size aSize, bool bPrintLandscape,
                         bool bUsed)
    :   rDocShell           ( rShell ),
        rDoc(rDocShell.GetDocument()),
        pPrinter            ( nullptr ),
        pDrawView           ( nullptr ),
        pUserArea           ( nullptr ),
        bSourceRangeValid   ( false ),
        bPrintCurrentTable  ( false ),
        bMultiArea          ( false ),
        mbHasPrintRange(true),
        pPageData           ( nullptr ),
        aPrintPageSize      ( aSize ),
        bPrintPageLandscape ( bPrintLandscape ),
        bUsePrintDialogSetting ( bUsed )
{
    pDev = pOutDev;

    nPrintTab   = rState.nPrintTab;
    nStartCol   = rState.nStartCol;
    nStartRow   = rState.nStartRow;
    nEndCol     = rState.nEndCol;
    nEndRow     = rState.nEndRow;
    bPrintAreaValid = rState.bPrintAreaValid;
    nZoom       = rState.nZoom;
    m_aRanges   = rState.m_aRanges;
    nTabPages   = rState.nTabPages;
    nTotalPages = rState.nTotalPages;
    nPageStart  = rState.nPageStart;
    nDocPages   = rState.nDocPages;
    bFromPrintState = true;

    Construct( pOptions );
}

void ScPrintFunc::GetPrintState(ScPrintState& rState)
{
    rState.nPrintTab    = nPrintTab;
    rState.nStartCol    = nStartCol;
    rState.nStartRow    = nStartRow;
    rState.nEndCol      = nEndCol;
    rState.nEndRow      = nEndRow;
    rState.bPrintAreaValid = bPrintAreaValid;
    rState.nZoom        = nZoom;
    rState.nTabPages    = nTabPages;
    rState.nTotalPages  = nTotalPages;
    rState.nPageStart   = nPageStart;
    rState.nDocPages    = nDocPages;
    rState.m_aRanges = m_aRanges;
}

bool ScPrintFunc::GetLastSourceRange( ScRange& rRange ) const
{
    rRange = aLastSourceRange;
    return bSourceRangeValid;
}

void ScPrintFunc::FillPageData()
{
    if (!pPageData)
        return;

    sal_uInt16 nCount = sal::static_int_cast<sal_uInt16>( pPageData->GetCount() );
    ScPrintRangeData& rData = pPageData->GetData(nCount);       // count up

    assert( bPrintAreaValid );
    rData.SetPrintRange( ScRange( nStartCol, nStartRow, nPrintTab,
                                    nEndCol, nEndRow, nPrintTab ) );
    // #i123672#
    if(m_aRanges.m_xPageEndX->empty())
    {
        OSL_ENSURE(false"vector access error for maPageEndX (!)");
    }
    else
    {
        rData.SetPagesX( m_aRanges.m_nPagesX, m_aRanges.m_xPageEndX->data());
    }

    // #i123672#
    if(m_aRanges.m_xPageEndY->empty())
    {
        OSL_ENSURE(false"vector access error for maPageEndY (!)");
    }
    else
    {
        rData.SetPagesY( m_aRanges.m_nTotalY, m_aRanges.m_xPageEndY->data());
    }

    //  Settings
    rData.SetTopDown( aTableParam.bTopDown );
    rData.SetAutomatic( !aAreaParam.bPrintArea );
}

ScPrintFunc::~ScPrintFunc()
{
    pEditDefaults.reset();
    pEditEngine.reset();

    //  Printer settings are now restored from outside

    //  For DrawingLayer/Charts, the MapMode of the printer (RefDevice) must always be correct
    SfxPrinter* pDocPrinter = rDoc.GetPrinter();   // use Preview also for the printer
    if (pDocPrinter)
        pDocPrinter->SetMapMode(aOldPrinterMode);
}

void ScPrintFunc::SetDrawView( FmFormView* pNew )
{
    pDrawView = pNew;
}

static void lcl_HidePrint( const 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++)
        {
            ScCellInfo& rCellInfo = pThisRowInfo->cellInfo(nX);
            ScBasicCellInfo& rBasicCellInfo = pThisRowInfo->basicCellInfo(nX);
            if (!rBasicCellInfo.bEmptyCellText)
                if (rCellInfo.pPatternAttr->
                            GetItem(ATTR_PROTECTION, rCellInfo.pConditionSet).GetHidePrint())
                {
                    rCellInfo.maCell.clear();
                    rBasicCellInfo.bEmptyCellText = true;
                }
        }
    }
}

//          output to Device (static)
//
//      us used for:
//      -   Clipboard/Bitmap
//      -   Ole-Object (DocShell::Draw)
//      -   Preview of templates

void ScPrintFunc::DrawToDev(ScDocument& rDoc, OutputDevice* pDev, double /* nPrintFactor */,
                            const tools::Rectangle& rBound, ScViewData& rViewData, bool bMetaFile)
{
    //! evaluate nPrintFactor !!!

    SCTAB nTab = rViewData.GetTabNo();

    bool bDoGrid, bNullVal, bFormula;
    ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool();
    SfxStyleSheetBase* pStyleSheet = pStylePool->Find( rDoc.GetPageStyle( nTab ), SfxStyleFamily::Page );
    if (pStyleSheet)
    {
        SfxItemSet& rSet = pStyleSheet->GetItemSet();
        bDoGrid  = rSet.Get(ATTR_PAGE_GRID).GetValue();
        bNullVal = rSet.Get(ATTR_PAGE_NULLVALS).GetValue();
        bFormula = rSet.Get(ATTR_PAGE_FORMULAS).GetValue();
    }
    else
    {
        const ScViewOptions& rOpt = rDoc.GetViewOptions();
        bDoGrid  = rOpt.GetOption(VOPT_GRID);
        bNullVal = rOpt.GetOption(VOPT_NULLVALS);
        bFormula = rOpt.GetOption(VOPT_FORMULAS);
    }

    MapMode aMode = pDev->GetMapMode();

    tools::Rectangle aRect = rBound;

    if (aRect.Right() < aRect.Left() || aRect.Bottom() < aRect.Top())
        aRect = tools::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 = rDoc.GetRange( nTab, rBound );
        nX1 = aRange.aStart.Col();
        nY1 = aRange.aStart.Row();
        nX2 = aRange.aEnd.Col();
        nY2 = aRange.aEnd.Row();
    }
    else
    {
        ScSplitPos eWhich = rViewData.GetActivePart();
        ScHSplitPos eHWhich = WhichH(eWhich);
        ScVSplitPos eVWhich = WhichV(eWhich);
        nX1 = rViewData.GetPosX(eHWhich);
        nY1 = rViewData.GetPosY(eVWhich);
        nX2 = nX1 + rViewData.VisibleCellsX(eHWhich);
        if (nX2>nX1) --nX2;
        nY2 = nY1 + rViewData.VisibleCellsY(eVWhich);
        if (nY2>nY1) --nY2;
    }

    if (nX1 > rDoc.MaxCol()) nX1 = rDoc.MaxCol();
    if (nX2 > rDoc.MaxCol()) nX2 = rDoc.MaxCol();
    if (nY1 > rDoc.MaxRow()) nY1 = rDoc.MaxRow();
    if (nY2 > rDoc.MaxRow()) nY2 = rDoc.MaxRow();

    tools::Long nDevSizeX = aRect.Right()-aRect.Left()+1;
    tools::Long nDevSizeY = aRect.Bottom()-aRect.Top()+1;

    tools::Long nTwipsSizeX = 0;
    for (SCCOL i=nX1; i<=nX2; i++)
        nTwipsSizeX += rDoc.GetColWidth( i, nTab );
    tools::Long nTwipsSizeY = rDoc.GetRowHeight( nY1, nY2, nTab );

    //  if no lines, still space for the outline frame (20 Twips = 1pt)
    //  (HasLines initializes aLines to 0,0,0,0)
    nTwipsSizeX += 20;
    nTwipsSizeY += 20;

    double nScaleX = static_cast<double>(nDevSizeX) / nTwipsSizeX;
    double nScaleY = static_cast<double>(nDevSizeY) / nTwipsSizeY;

                            //!     hand over Flag at FillInfo !!!!!
    ScRange aERange;
    bool bEmbed = rDoc.IsEmbedded();
    if (bEmbed)
    {
        rDoc.GetEmbedded(aERange);
        rDoc.ResetEmbedded();
    }

    //  Assemble data

    ScTableInfo aTabInfo(nY1, nY2, true);
    rDoc.FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nTab,
                   nScaleX, nScaleY, false, bFormula );
    lcl_HidePrint( aTabInfo, nX1, nX2 );

    if (bEmbed)
        rDoc.SetEmbedded(aERange);

    tools::Long nScrX = aRect.Left();
    tools::Long nScrY = aRect.Top();

    //  If no lines, still leave space for grid lines
    //  (would be elseways cut away)
    // tdf#135891 - adjust the x position to ensure the correct starting point
    const Size aOnePixel = pDev->PixelToLogic(Size(1, 1));
    nScrX += aOnePixel.Width();
    nScrY += 1;

    ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, &rDoc, nTab,
                                nScrX, nScrY, nX1, nY1, nX2, nY2, nScaleX, nScaleY );
    aOutputData.SetMetaFileMode(bMetaFile);
    aOutputData.SetShowNullValues(bNullVal);
    aOutputData.SetShowFormulas(bFormula);

    vcl::PDFExtOutDevData* pPDF = dynamic_cast<vcl::PDFExtOutDevData*>(pDev->GetExtOutDevData());
    bool bTaggedPDF = pPDF && pPDF->GetIsExportTaggedPDF();
    if (bTaggedPDF)
    {
        bool bReopen = aOutputData.ReopenPDFStructureElement(vcl::pdf::StructElement::Part);
        if (!bReopen)
        {
            sal_Int32 nId = pPDF->EnsureStructureElement(nullptr);
            pPDF->InitStructureElement(nId, vcl::pdf::StructElement::Part, u"Worksheet"_ustr);
            pPDF->BeginStructureElement(nId);
            pPDF->GetScPDFState()->m_WorksheetId = nId;
        }
    }

    ScDrawLayer* pModel = rDoc.GetDrawLayer();
    std::unique_ptr<FmFormView> pDrawView;

    if( pModel )
    {
        pDrawView.reset(
            new FmFormView(
                *pModel,
                pDev));
        pDrawView->ShowSdrPage(pDrawView->GetModel().GetPage(nTab));
        pDrawView->SetPrintPreview();
        aOutputData.SetDrawView( pDrawView.get() );
    }

    //! SetUseStyleColor ??

    if ( bMetaFile && pDev->IsVirtual() )
        aOutputData.SetSnapPixel();

    Point aLogStart = pDev->PixelToLogic(Point(nScrX, nScrY), MapMode(MapUnit::Map100thMM));
    tools::Long nLogStX = aLogStart.X();
    tools::Long nLogStY = aLogStart.Y();

    //!     nZoom for GetFont in OutputData ???

    if (!bMetaFile)
        pDev->SetMapMode(rViewData.GetLogicMode(rViewData.GetActivePart()));

    // #i72502#
    const Point aMMOffset(aOutputData.PrePrintDrawingLayer(nLogStX, nLogStY));
    aOutputData.PrintDrawingLayer(SC_LAYER_BACK, aMMOffset);

    if (!bMetaFile)
        pDev->SetMapMode(aMode);

    aOutputData.DrawBackground(*pDev);

    aOutputData.DrawShadow();
    aOutputData.DrawFrame(*pDev);
    aOutputData.DrawSparklines(*pDev);
    aOutputData.DrawStrings();

    if (!bMetaFile)
        pDev->SetMapMode(rViewData.GetLogicMode(rViewData.GetActivePart()));

    aOutputData.DrawEdit(!bMetaFile);

    if (bDoGrid)
    {
        if (!bMetaFile)
            pDev->SetMapMode(aMode);

        aOutputData.DrawGrid(*pDev, truefalse);    // no page breaks

        pDev->SetLineColor( COL_BLACK );

        Size aOne = pDev->PixelToLogic( Size(1,1) );
        if (bMetaFile)
            aOne = Size(1,1);   // compatible with DrawGrid
        tools::Long nRight = nScrX + aOutputData.GetScrW() - aOne.Width();
        tools::Long nBottom = nScrY + aOutputData.GetScrH() - aOne.Height();

        bool bLayoutRTL = rDoc.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);

    if (bTaggedPDF)
        pPDF->EndStructureElement();

    aOutputData.PrintDrawingLayer(SC_LAYER_INTERN, aMMOffset);
    aOutputData.PostPrintDrawingLayer(aMMOffset); // #i74768#
}

//          Printing

static void lcl_FillHFParam( ScPrintHFParam& rParam, const SfxItemSet* pHFSet )
{
    //  nDistance must be initialized differently before

    if ( pHFSet == nullptr )
    {
        rParam.bEnable  = false;
        rParam.pBorder  = nullptr;
        rParam.pBack    = nullptr;
        rParam.pShadow  = nullptr;
    }
    else
    {
        rParam.bEnable  = pHFSet->Get(ATTR_PAGE_ON).GetValue();
        rParam.bDynamic = pHFSet->Get(ATTR_PAGE_DYNAMIC).GetValue();
        rParam.bShared  = pHFSet->Get(ATTR_PAGE_SHARED).GetValue();
        rParam.bSharedFirst = pHFSet->Get(ATTR_PAGE_SHARED_FIRST).GetValue();
        rParam.nHeight  = pHFSet->Get(ATTR_PAGE_SIZE).GetSize().Height();
        const SvxLRSpaceItem* pHFLR = &pHFSet->Get(ATTR_LRSPACE);
        tools::Long nTmp;
        nTmp = pHFLR->ResolveLeft({});
        rParam.nLeft = nTmp < 0 ? 0 : sal_uInt16(nTmp);
        nTmp = pHFLR->ResolveRight({});
        rParam.nRight = nTmp < 0 ? 0 : sal_uInt16(nTmp);
        rParam.pBorder  = &pHFSet->Get(ATTR_BORDER);
        rParam.pBack    = &pHFSet->Get(ATTR_BACKGROUND);
        rParam.pShadow  = &pHFSet->Get(ATTR_SHADOW);

//   now back in the dialog:
//      rParam.nHeight += rParam.nDistance;             // not in the dialog any more ???

        rParam.nHeight += lcl_LineTotal( rParam.pBorder->GetTop() ) +
                          lcl_LineTotal( rParam.pBorder->GetBottom() );

        rParam.nManHeight = rParam.nHeight;
    }

    if (!rParam.bEnable)
        rParam.nHeight = 0;
}

//  bNew = TRUE:    search for used part of the document
//  bNew = FALSE:   only limit whole lines/columns

bool ScPrintFunc::AdjustPrintArea( bool bNew )
{
    SCCOL nOldEndCol = nEndCol; // only important for !bNew
    SCROW nOldEndRow = nEndRow;
    bool bChangeCol = true;         // at bNew both are being adjusted
    bool bChangeRow = true;

    bool bNotes = aTableParam.bNotes;
    if ( bNew )
    {
        nStartCol = 0;
        nStartRow = 0;
        if (!rDoc.GetPrintArea( nPrintTab, nEndCol, nEndRow, bNotes ) && aTableParam.bSkipEmpty)
            return false;   // nothing
        bPrintAreaValid = true;
    }
    else
    {
        bool bFound = true;
        bChangeCol = ( nStartCol == 0 && nEndCol == rDoc.MaxCol() );
        bChangeRow = ( nStartRow == 0 && nEndRow == rDoc.MaxRow() );
        bool bForcedChangeRow = false;

        // #i53558# Crop entire column of old row limit to real print area with
        // some fuzzyness.
        if (!bChangeRow && nStartRow == 0)
        {
            SCROW nPAEndRow;
            bFound = rDoc.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 = true;
                nEndRow = nPAEndRow;
            }
            else
                bFound = 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 = rDoc.GetPrintArea( nPrintTab, nEndCol, nEndRow, bNotes );
        else if ( bChangeCol )
            bFound = rDoc.GetPrintAreaHor( nPrintTab, nStartRow, nEndRow, nEndCol );
        else if ( bChangeRow )
            bFound = rDoc.GetPrintAreaVer( nPrintTab, nStartCol, nEndCol, nEndRow, bNotes );

        if (!bFound)
            return false;   // empty

        bPrintAreaValid = true;
        if (bForcedChangeRow)
            bChangeRow = true;
    }

    assert( bPrintAreaValid );
    rDoc.ExtendMerge( nStartCol,nStartRow, nEndCol,nEndRow, nPrintTab );  // no Refresh, incl. Attrs

    if ( bChangeCol )
    {
        OutputDevice* pRefDev = rDoc.GetPrinter();     // use the printer also for Preview
        pRefDev->SetMapMode(MapMode(MapUnit::MapPixel)); // important for GetNeededSize

        rDoc.ExtendPrintArea( pRefDev,
                            nPrintTab, nStartCol, nStartRow, nEndCol, nEndRow );
        //  changing nEndCol
    }

    if ( nEndCol < rDoc.MaxCol() && rDoc.HasAttrib(
                    nEndCol,nStartRow,nPrintTab, nEndCol,nEndRow,nPrintTab, HasAttrFlags::ShadowRight ) )
        ++nEndCol;
    if ( nEndRow < rDoc.MaxRow() && rDoc.HasAttrib(
                    nStartCol,nEndRow,nPrintTab, nEndCol,nEndRow,nPrintTab, HasAttrFlags::ShadowDown ) )
        ++nEndRow;

    if (!bChangeCol) nEndCol = nOldEndCol;
    if (!bChangeRow) nEndRow = nOldEndRow;

    return true;
}

tools::Long ScPrintFunc::TextHeight( const EditTextObject* pObject )
{
    if (!pObject)
        return 0;

    pEditEngine->SetTextTempDefaults(*pObject, *pEditDefaults);

    return static_cast<tools::Long>(pEditEngine->GetTextHeight());
}

//  nZoom must be set !!!
//  and the respective Twip-MapMode configured

void ScPrintFunc::UpdateHFHeight( ScPrintHFParam& rParam )
{
    OSL_ENSURE( aPageSize.Width(), "UpdateHFHeight without aPageSize");

    if (!(rParam.bEnable && rParam.bDynamic))
        return;

    //  calculate nHeight from content

    MakeEditEngine();
    tools::Long nPaperWidth = ( aPageSize.Width() - nLeftMargin - nRightMargin -
                            rParam.nLeft - rParam.nRight ) * 100 / nZoom;
    if (rParam.pBorder)
        nPaperWidth -= ( rParam.pBorder->GetDistance(SvxBoxItemLine::LEFT) +
                         rParam.pBorder->GetDistance(SvxBoxItemLine::RIGHT) +
                         lcl_LineTotal(rParam.pBorder->GetLeft()) +
                         lcl_LineTotal(rParam.pBorder->GetRight()) ) * 100 / nZoom;

    if (rParam.pShadow && rParam.pShadow->GetLocation() != SvxShadowLocation::NONE)
        nPaperWidth -= ( rParam.pShadow->CalcShadowSpace(SvxShadowItemSide::LEFT) +
                         rParam.pShadow->CalcShadowSpace(SvxShadowItemSide::RIGHT) ) * 100 / nZoom;

    if (nPaperWidth <= 0)
    {
        SAL_WARN("sc.ui""Header/Footer unreasonably narrow width of: " << nPaperWidth << ", cannot calculate height");
        return;
    }

    pEditEngine->SetPaperSize( Size( nPaperWidth, 10000 ) );

    tools::Long nMaxHeight = 0;
    if ( rParam.pLeft )
    {
        nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pLeft->GetLeftArea() ) );
        nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pLeft->GetCenterArea() ) );
        nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pLeft->GetRightArea() ) );
    }
    if ( rParam.pRight )
    {
        nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pRight->GetLeftArea() ) );
        nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pRight->GetCenterArea() ) );
        nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pRight->GetRightArea() ) );
    }
    if ( rParam.pFirst )
    {
        nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pFirst->GetLeftArea() ) );
        nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pFirst->GetCenterArea() ) );
        nMaxHeight = std::max( nMaxHeight, TextHeight( rParam.pFirst->GetRightArea() ) );
    }

    rParam.nHeight = nMaxHeight + rParam.nDistance;
    if (rParam.pBorder)
        rParam.nHeight += rParam.pBorder->GetDistance(SvxBoxItemLine::TOP) +
                          rParam.pBorder->GetDistance(SvxBoxItemLine::BOTTOM) +
                          lcl_LineTotal( rParam.pBorder->GetTop() ) +
                          lcl_LineTotal( rParam.pBorder->GetBottom() );
    if (rParam.pShadow && rParam.pShadow->GetLocation() != SvxShadowLocation::NONE)
        rParam.nHeight += rParam.pShadow->CalcShadowSpace(SvxShadowItemSide::TOP) +
                          rParam.pShadow->CalcShadowSpace(SvxShadowItemSide::BOTTOM);

    if (rParam.nHeight < rParam.nManHeight)
        rParam.nHeight = rParam.nManHeight;         // configured minimum
}

void ScPrintFunc::InitParam( const ScPrintOptions* pOptions )
{
    if (!pParamSet)
        return;

                                // TabPage "Page"
    const SvxLRSpaceItem* pLRItem = &pParamSet->Get( ATTR_LRSPACE );
    tools::Long nTmp;
    nTmp = pLRItem->ResolveLeft({});
    nLeftMargin = nTmp < 0 ? 0 : sal_uInt16(nTmp);
    nTmp = pLRItem->ResolveRight({});
    nRightMargin = nTmp < 0 ? 0 : sal_uInt16(nTmp);
    const SvxULSpaceItem* pULItem = &pParamSet->Get( ATTR_ULSPACE );
    nTopMargin    = pULItem->GetUpper();
    nBottomMargin = pULItem->GetLower();

    const SvxPageItem* pPageItem = &pParamSet->Get( ATTR_PAGE );
    nPageUsage          = pPageItem->GetPageUsage();
    bLandscape          = bUsePrintDialogSetting ? bPrintPageLandscape : pPageItem->IsLandscape();
    aFieldData.eNumType = pPageItem->GetNumType();

    bCenterHor = pParamSet->Get(ATTR_PAGE_HORCENTER).GetValue();
    bCenterVer = pParamSet->Get(ATTR_PAGE_VERCENTER).GetValue();

    aPageSize = bUsePrintDialogSetting ? aPrintPageSize : pParamSet->Get(ATTR_PAGE_SIZE).GetSize();
    if ( !aPageSize.Width() || !aPageSize.Height() )
    {
        OSL_FAIL("PageSize Null ?!?!?");
        aPageSize = SvxPaperInfo::GetPaperSize( PAPER_A4 );
    }

    pBorderItem     = &pParamSet->Get(ATTR_BORDER);
    pBackgroundItem = &pParamSet->Get(ATTR_BACKGROUND);
    pShadowItem     = &pParamSet->Get(ATTR_SHADOW);

                                // TabPage "Headline"

    aHdr.pLeft      = &pParamSet->Get(ATTR_PAGE_HEADERLEFT);      // Content
    aHdr.pRight     = &pParamSet->Get(ATTR_PAGE_HEADERRIGHT);
    aHdr.pFirst     = &pParamSet->Get(ATTR_PAGE_HEADERFIRST);

    const SfxItemSet* pHeaderSet = nullptr;
    if ( const SvxSetItem* pHeaderSetItem = pParamSet->GetItemIfSet( ATTR_PAGE_HEADERSET, false ) )
    {
        pHeaderSet = &pHeaderSetItem->GetItemSet();
                                                        // Headline has space below
        aHdr.nDistance  = pHeaderSet->Get(ATTR_ULSPACE).GetLower();
    }
    lcl_FillHFParam( aHdr, pHeaderSet );

                                // TabPage "Footline"

    aFtr.pLeft      = &pParamSet->Get(ATTR_PAGE_FOOTERLEFT);      // Content
    aFtr.pRight     = &pParamSet->Get(ATTR_PAGE_FOOTERRIGHT);
    aFtr.pFirst     = &pParamSet->Get(ATTR_PAGE_FOOTERFIRST);

    const SfxItemSet* pFooterSet = nullptr;
    if ( const SvxSetItem* pFooterSetItem = pParamSet->GetItemIfSet( ATTR_PAGE_FOOTERSET, false ) )
    {
        pFooterSet = &pFooterSetItem->GetItemSet();
                                                        // Footline has space above
        aFtr.nDistance  = pFooterSet->Get(ATTR_ULSPACE).GetUpper();
    }
    lcl_FillHFParam( aFtr, pFooterSet );

    // Compile Table-/Area-Params from single Items

    // TabPage "Table"

    const SfxUInt16Item*     pScaleItem          = nullptr;
    const ScPageScaleToItem* pScaleToItem        = nullptr;
    const SfxUInt16Item*     pScaleToPagesItem   = nullptr;
    SfxItemState             eState;

    eState = pParamSet->GetItemState( ATTR_PAGE_SCALE, false,
                                      reinterpret_cast<const SfxPoolItem**>(&pScaleItem) );
    if ( SfxItemState::DEFAULT == eState )
        pScaleItem = &pParamSet->GetPool()->GetUserOrPoolDefaultItem( ATTR_PAGE_SCALE );

    eState = pParamSet->GetItemState( ATTR_PAGE_SCALETO, false,
                                      reinterpret_cast<const SfxPoolItem**>(&pScaleToItem) );
    if ( SfxItemState::DEFAULT == eState )
        pScaleToItem = &pParamSet->GetPool()->GetUserOrPoolDefaultItem( ATTR_PAGE_SCALETO );

    eState = pParamSet->GetItemState( ATTR_PAGE_SCALETOPAGES, false,
                                      reinterpret_cast<const SfxPoolItem**>(&pScaleToPagesItem) );
    if ( SfxItemState::DEFAULT == eState )
        pScaleToPagesItem = &pParamSet->GetPool()->GetUserOrPoolDefaultItem( ATTR_PAGE_SCALETOPAGES );

    OSL_ENSURE( pScaleItem && pScaleToItem && pScaleToPagesItem, "Missing ScaleItem! :-/" );

    aTableParam.bCellContent    = true;
    aTableParam.bNotes          = lcl_GetBool(pParamSet,ATTR_PAGE_NOTES);
    aTableParam.bGrid           = lcl_GetBool(pParamSet,ATTR_PAGE_GRID);
    aTableParam.bHeaders        = lcl_GetBool(pParamSet,ATTR_PAGE_HEADERS);
    aTableParam.bFormulas       = lcl_GetBool(pParamSet,ATTR_PAGE_FORMULAS);
    aTableParam.bNullVals       = lcl_GetBool(pParamSet,ATTR_PAGE_NULLVALS);
    aTableParam.bCharts         = lcl_GetShow(pParamSet,ATTR_PAGE_CHARTS);
    aTableParam.bObjects        = lcl_GetShow(pParamSet,ATTR_PAGE_OBJECTS);
    aTableParam.bDrawings       = lcl_GetShow(pParamSet,ATTR_PAGE_DRAWINGS);
    aTableParam.bTopDown        = lcl_GetBool(pParamSet,ATTR_PAGE_TOPDOWN);
    aTableParam.bLeftRight      = !aTableParam.bLeftRight;
    aTableParam.nFirstPageNo    = lcl_GetUShort(pParamSet,ATTR_PAGE_FIRSTPAGENO);
    if (!aTableParam.nFirstPageNo)
        aTableParam.nFirstPageNo = static_cast<sal_uInt16>(nPageStart);     // from previous table

    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      = true;
        aTableParam.bScaleAll       = false;
        aTableParam.bScaleTo        = false;
        aTableParam.bScalePageNum   = 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 = false;
    // If pPageData is set, only the breaks are interesting for the
    // pagebreak preview, empty pages are not addressed separately.

    aTableParam.bForceBreaks = pOptions && pOptions->GetForceBreaks();

    // TabPage "Parts":

    //! walk through all PrintAreas of the table !!!
    const ScRange*  pPrintArea = rDoc.GetPrintRange( nPrintTab, 0 );
    std::optional<ScRange> oRepeatCol = rDoc.GetRepeatColRange( nPrintTab );
    std::optional<ScRange> oRepeatRow = rDoc.GetRepeatRowRange( nPrintTab );

    //  ignoring ATTR_PAGE_PRINTTABLES

    bool bHasPrintRange = rDoc.HasPrintRange();
    sal_uInt16 nPrintRangeCount = rDoc.GetPrintRangeCount(nPrintTab);
    bool bPrintEntireSheet = rDoc.IsPrintEntireSheet(nPrintTab);

    if (!bPrintEntireSheet && !nPrintRangeCount)
        mbHasPrintRange = false;

    if ( pUserArea )                // UserArea (selection) has priority
    {
        bPrintCurrentTable    =
        aAreaParam.bPrintArea = true;                   // Selection
        aAreaParam.aPrintArea = *pUserArea;

        //  The table-query is already in DocShell::Print, here always
        aAreaParam.aPrintArea.aStart.SetTab(nPrintTab);
        aAreaParam.aPrintArea.aEnd.SetTab(nPrintTab);
    }
    else if (bHasPrintRange)
    {
        if ( pPrintArea )                               // at least one set?
        {
            bPrintCurrentTable    =
            aAreaParam.bPrintArea = true;
            aAreaParam.aPrintArea = *pPrintArea;

            bMultiArea = nPrintRangeCount > 1;
        }
        else
        {
            // do not print hidden sheets with "Print entire sheet" flag
            bPrintCurrentTable = rDoc.IsPrintEntireSheet( nPrintTab ) && rDoc.IsVisible( nPrintTab );
            aAreaParam.bPrintArea = !bPrintCurrentTable;    // otherwise the table is always counted
        }
    }
    else
    {
        //  don't print hidden tables if there's no print range defined there
        if ( rDoc.IsVisible( nPrintTab ) )
        {
            aAreaParam.bPrintArea = false;
            bPrintCurrentTable = true;
        }
        else
        {
            aAreaParam.bPrintArea = true;   // otherwise the table is always counted
            bPrintCurrentTable = false;
        }
    }

    if ( oRepeatCol )
    {
        aAreaParam.bRepeatCol = true;
        nRepeatStartCol = oRepeatCol->aStart.Col();
        nRepeatEndCol   = oRepeatCol->aEnd  .Col();
    }
    else
    {
        aAreaParam.bRepeatCol = false;
        nRepeatStartCol = nRepeatEndCol = SCCOL_REPEAT_NONE;
    }

    if ( oRepeatRow )
    {
        aAreaParam.bRepeatRow = true;
        nRepeatStartRow = oRepeatRow->aStart.Row();
        nRepeatEndRow   = oRepeatRow->aEnd  .Row();
    }
    else
    {
        aAreaParam.bRepeatRow = false;
        nRepeatStartRow = nRepeatEndRow = SCROW_REPEAT_NONE;
    }

            //  Split pages

    if (!bPrintAreaValid)
    {
        nTabPages = CountPages();                                   // also calculates zoom
        nTotalPages = nTabPages;
        nTotalPages += CountNotePages();
    }
    else
    {
        CalcPages();            // search breaks only
        CountNotePages();       // Count notes, even if number of pages is already known
    }

    if (nDocPages)
        aFieldData.nTotalPages = nDocPages;
    else
        aFieldData.nTotalPages = nTotalPages;

    SetDateTime( DateTime( DateTime::SYSTEM ) );

    if( rDocShell.getDocProperties()->getTitle().getLength() != 0 )
        aFieldData.aTitle = rDocShell.getDocProperties()->getTitle();
    else
        aFieldData.aTitle = rDocShell.GetTitle();

    const INetURLObject& rURLObj = rDocShell.GetMedium()->GetURLObject();
    aFieldData.aLongDocName = rURLObj.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous );
    if ( !aFieldData.aLongDocName.isEmpty() )
        aFieldData.aShortDocName = rURLObj.GetLastName(INetURLObject::DecodeMechanism::Unambiguous);
    else
        aFieldData.aShortDocName = aFieldData.aLongDocName = aFieldData.aTitle;

    //  Printer settings (Orientation, Paper) at DoPrint
}

Size ScPrintFunc::GetDataSize() const
{
    Size aSize = aPageSize;
    aSize.AdjustWidth( -(nLeftMargin + nRightMargin) );
    aSize.AdjustHeight( -(nTopMargin + nBottomMargin) );
    aSize.AdjustHeight( -(aHdr.nHeight + aFtr.nHeight) );
    return aSize;
}

void ScPrintFunc::GetScaleData( Size& rPhysSize, tools::Long& rDocHdr, tools::Long& rDocFtr )
{
    rPhysSize = aPageSize;
    rPhysSize.AdjustWidth( -(nLeftMargin + nRightMargin) );
    rPhysSize.AdjustHeight( -(nTopMargin + nBottomMargin) );

    rDocHdr = aHdr.nHeight;
    rDocFtr = aFtr.nHeight;
}

void ScPrintFunc::SetDateTime( const DateTime& rDateTime )
{
    aFieldData.aDateTime = rDateTime;
}

static void lcl_DrawGraphic( const Graphic &rGraphic, vcl::RenderContext& rOutDev,
                      const tools::Rectangle &rGrf, const tools::Rectangle &rOut )
{
    const bool bNotInside = !rOut.Contains( rGrf );
    if ( bNotInside )
    {
        rOutDev.Push();
        rOutDev.IntersectClipRegion( rOut );
    }

    rGraphic.Draw(rOutDev, rGrf.TopLeft(), rGrf.GetSize());

    if ( bNotInside )
        rOutDev.Pop();
}

static void lcl_DrawGraphic( const SvxBrushItem &rBrush, vcl::RenderContext& rOutDev, const OutputDevice* pRefDev,
                        const tools::Rectangle &rOrg, const tools::Rectangle &rOut,
                        OUString const & referer )
{
    Size aGrfSize(0,0);
    const Graphic *pGraphic = rBrush.GetGraphic(referer);
    SvxGraphicPosition ePos;
    if ( pGraphic && pGraphic->IsSupportedGraphic() )
    {
        const MapMode aMapMM( MapUnit::Map100thMM );
        if ( pGraphic->GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel )
            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;

    bool bDraw = true;
    switch ( ePos )
    {
        case GPOS_LT: aPos = rOrg.TopLeft();
                      break;
        case GPOS_MT: aPos.setY( rOrg.Top() );
                      aPos.setX( rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2 );
                      break;
        case GPOS_RT: aPos.setY( rOrg.Top() );
                      aPos.setX( rOrg.Right() - aGrfSize.Width() );
                      break;

        case GPOS_LM: aPos.setY( rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2 );
                      aPos.setX( rOrg.Left() );
                      break;
        case GPOS_MM: aPos.setY( rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2 );
                      aPos.setX( rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2 );
                      break;
        case GPOS_RM: aPos.setY( rOrg.Top() + rOrg.GetSize().Height()/2 - aGrfSize.Height()/2 );
                      aPos.setX( rOrg.Right() - aGrfSize.Width() );
                      break;

        case GPOS_LB: aPos.setY( rOrg.Bottom() - aGrfSize.Height() );
                      aPos.setX( rOrg.Left() );
                      break;
        case GPOS_MB: aPos.setY( rOrg.Bottom() - aGrfSize.Height() );
                      aPos.setX( rOrg.Left() + rOrg.GetSize().Width()/2 - aGrfSize.Width()/2 );
                      break;
        case GPOS_RB: aPos.setY( rOrg.Bottom() - aGrfSize.Height() );
                      aPos.setX( rOrg.Right() - aGrfSize.Width() );
                      break;

        case GPOS_AREA:
                      aPos = rOrg.TopLeft();
                      aDrawSize = rOrg.GetSize();
                      break;
        case GPOS_TILED:
                    {
                        //  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( rOutDev.GetOutDevType() == OUTDEV_PDF &&
                            (aObject.GetType() == GraphicType::Bitmap || aObject.GetType() == GraphicType::Default) )
                        {
                            // 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( rOutDev, rOrg, aGrfSize, Size(0,0),
                                               ::std::max( 128, static_cast<int>( sqrt(sqrt( Abitmap)) + .5 ) ) );
                        }
                        else
                        {
                            aObject.DrawTiled( rOutDev, rOrg, aGrfSize, Size(0,0) );
                        }

                        bDraw = false;
                    }
                    break;

        case GPOS_NONE:
                      bDraw = false;
                      break;

        default: OSL_ENSURE( false"new Graphic position?" );
    }
    tools::Rectangle aGrf( aPos,aDrawSize );
    if ( bDraw && aGrf.Overlaps( rOut ) )
    {
        lcl_DrawGraphic( *pGraphic, rOutDev, aGrf, rOut );
    }
}

// The frame is drawn inwards

void ScPrintFunc::DrawBorder( tools::Long nScrX, tools::Long nScrY, tools::Long nScrW, tools::Long nScrH,
                                const SvxBoxItem* pBorderData, const SvxBrushItem* pBackground,
                                const SvxShadowItem* pShadow )
{
    //!     direct output from SvxBoxItem !!!

    if (pBorderData)
        if ( !pBorderData->GetTop() && !pBorderData->GetBottom() && !pBorderData->GetLeft() &&
                                        !pBorderData->GetRight() )
            pBorderData = nullptr;

    if (!pBorderData && !pBackground && !pShadow)
        return;                                     // nothing to do

    tools::Long nLeft   = 0;
    tools::Long nRight  = 0;
    tools::Long nTop    = 0;
    tools::Long nBottom = 0;

    //  aFrameRect - outside around frame, without shadow
    if ( pShadow && pShadow->GetLocation() != SvxShadowLocation::NONE )
    {
        nLeft   += static_cast<tools::Long>( pShadow->CalcShadowSpace(SvxShadowItemSide::LEFT)   * nScaleX );
        nRight  += static_cast<tools::Long>( pShadow->CalcShadowSpace(SvxShadowItemSide::RIGHT)  * nScaleX );
        nTop    += static_cast<tools::Long>( pShadow->CalcShadowSpace(SvxShadowItemSide::TOP)    * nScaleY );
        nBottom += static_cast<tools::Long>( pShadow->CalcShadowSpace(SvxShadowItemSide::BOTTOM) * nScaleY );
    }
    tools::Rectangle aFrameRect( Point(nScrX+nLeft, nScrY+nTop),
                          Size(nScrW-nLeft-nRight, nScrH-nTop-nBottom) );

    //  center of frame, to paint lines through OutputData
    if (pBorderData)
    {
        nLeft   += static_cast<tools::Long>( lcl_LineTotal(pBorderData->GetLeft())   * nScaleX / 2 );
        nRight  += static_cast<tools::Long>( lcl_LineTotal(pBorderData->GetRight())  * nScaleX / 2 );
        nTop    += static_cast<tools::Long>( lcl_LineTotal(pBorderData->GetTop())    * nScaleY / 2 );
        nBottom += static_cast<tools::Long>( lcl_LineTotal(pBorderData->GetBottom()) * nScaleY / 2 );
    }
    tools::Long nEffHeight = nScrH - nTop - nBottom;
    tools::Long nEffWidth = nScrW - nLeft - nRight;
    if (nEffHeight<=0 || nEffWidth<=0)
        return;                                         // empty

    if ( pBackground )
    {
        if (pBackground->GetGraphicPos() != GPOS_NONE)
        {
            OutputDevice* pRefDev;
            if ( bIsRender )
                pRefDev = pDev;                 // don't use printer for PDF
            else
                pRefDev = rDoc.GetPrinter();   // use printer also for preview
            OUString referer;
            if (rDocShell.HasName()) {
                referer = rDocShell.GetMedium()->GetName();
            }
            lcl_DrawGraphic(*pBackground, *pDev, pRefDev, aFrameRect, aFrameRect, referer);
        }
        else
        {
            if (pBackground->GetColor() == COL_TRANSPARENT)
                pDev->SetFillColor();
            else
                pDev->SetFillColor(pBackground->GetColor());
            pDev->SetLineColor();
            pDev->DrawRect(aFrameRect);
        }
    }

    if ( pShadow && pShadow->GetLocation() != SvxShadowLocation::NONE )
    {
        pDev->SetFillColor(pShadow->GetColor());
        pDev->SetLineColor();
        tools::Long nShadowX = static_cast<tools::Long>( pShadow->GetWidth() * nScaleX );
        tools::Long nShadowY = static_cast<tools::Long>( pShadow->GetWidth() * nScaleY );
        switch (pShadow->GetLocation())
        {
            case SvxShadowLocation::TopLeft:
                pDev->DrawRect( tools::Rectangle(
                        aFrameRect.Left()-nShadowX, aFrameRect.Top()-nShadowY,
                        aFrameRect.Right()-nShadowX, aFrameRect.Top() ) );
                pDev->DrawRect( tools::Rectangle(
                        aFrameRect.Left()-nShadowX, aFrameRect.Top()-nShadowY,
                        aFrameRect.Left(), aFrameRect.Bottom()-nShadowY ) );
                break;
            case SvxShadowLocation::TopRight:
                pDev->DrawRect( tools::Rectangle(
                        aFrameRect.Left()+nShadowX, aFrameRect.Top()-nShadowY,
                        aFrameRect.Right()+nShadowX, aFrameRect.Top() ) );
                pDev->DrawRect( tools::Rectangle(
                        aFrameRect.Right(), aFrameRect.Top()-nShadowY,
                        aFrameRect.Right()+nShadowX, aFrameRect.Bottom()-nShadowY ) );
                break;
            case SvxShadowLocation::BottomLeft:
                pDev->DrawRect( tools::Rectangle(
                        aFrameRect.Left()-nShadowX, aFrameRect.Bottom(),
                        aFrameRect.Right()-nShadowX, aFrameRect.Bottom()+nShadowY ) );
                pDev->DrawRect( tools::Rectangle(
                        aFrameRect.Left()-nShadowX, aFrameRect.Top()+nShadowY,
                        aFrameRect.Left(), aFrameRect.Bottom()+nShadowY ) );
                break;
            case SvxShadowLocation::BottomRight:
                pDev->DrawRect( tools::Rectangle(
                        aFrameRect.Left()+nShadowX, aFrameRect.Bottom(),
                        aFrameRect.Right()+nShadowX, aFrameRect.Bottom()+nShadowY ) );
                pDev->DrawRect( tools::Rectangle(
                        aFrameRect.Right(), aFrameRect.Top()+nShadowY,
                        aFrameRect.Right()+nShadowX, aFrameRect.Bottom()+nShadowY ) );
                break;
            default:
            {
                // added to avoid warnings
            }
        }
    }

    if (!pBorderData)
        return;

    ScDocumentUniquePtr pBorderDoc(new ScDocument( SCDOCMODE_UNDO ));
    pBorderDoc->InitUndo( rDoc, 0,0, true,true );
    pBorderDoc->ApplyAttr( 0,0,0, *pBorderData );

    ScTableInfo aTabInfo(0, 1, false);
    pBorderDoc->FillInfo( aTabInfo, 0,0, 0,0, 0,
                                        nScaleX, nScaleY, falsefalse );
    OSL_ENSURE(aTabInfo.mnArrCount,"nArrCount == 0");

    aTabInfo.mpRowInfo[1].nHeight = static_cast<sal_uInt16>(nEffHeight);
    aTabInfo.mpRowInfo[0].basicCellInfo(0).nWidth =
        aTabInfo.mpRowInfo[1].basicCellInfo(0).nWidth = static_cast<sal_uInt16>(nEffWidth);

    ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, pBorderDoc.get(), 0,
                                nScrX+nLeft, nScrY+nTop, 0,0, 0,0, nScaleX, nScaleY );
    aOutputData.SetUseStyleColor( bUseStyleColor );

    aOutputData.DrawFrame(*pDev);
}

void ScPrintFunc::PrintColHdr( SCCOL nX1, SCCOL nX2, tools::Long nScrX, tools::Long nScrY )
{
    bool bLayoutRTL = rDoc.IsLayoutRTL( nPrintTab );
    tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;

    Size aOnePixel = pDev->PixelToLogic(Size(1,1));
    tools::Long nOneX = aOnePixel.Width();
    tools::Long nOneY = aOnePixel.Height();
    SCCOL nCol;

    tools::Long nHeight = static_cast<tools::Long>(PRINT_HEADER_HEIGHT * nScaleY);
    tools::Long nEndY = nScrY + nHeight - nOneY;

    tools::Long nPosX = nScrX;
    if ( bLayoutRTL )
    {
        for (nCol=nX1; nCol<=nX2; nCol++)
            nPosX += static_cast<tools::Long>( rDoc.GetColWidth( nCol, nPrintTab ) * nScaleX );
    }
    else
        nPosX -= nOneX;
    tools::Long nPosY = nScrY - nOneY;
    OUString aText;

    for (nCol=nX1; nCol<=nX2; nCol++)
    {
        sal_uInt16 nDocW = rDoc.GetColWidth( nCol, nPrintTab );
        if (nDocW)
        {
            tools::Long nWidth = static_cast<tools::Long>(nDocW * nScaleX);
            tools::Long nEndX = nPosX + nWidth * nLayoutSign;

            pDev->DrawRect( tools::Rectangle( nPosX,nPosY,nEndX,nEndY ) );

            aText = ::ScColToAlpha( nCol);
            tools::Long nTextWidth = pDev->GetTextWidth(aText);
            tools::Long nTextHeight = pDev->GetTextHeight();
            tools::Long nAddX = ( nWidth  - nTextWidth  ) / 2;
            tools::Long nAddY = ( nHeight - nTextHeight ) / 2;
            tools::Long nTextPosX = nPosX+nAddX;
            if ( bLayoutRTL )
                nTextPosX -= nWidth;
            pDev->DrawText( Point( nTextPosX,nPosY+nAddY ), aText );

            nPosX = nEndX;
        }
    }
}

void ScPrintFunc::PrintRowHdr( SCROW nY1, SCROW nY2, tools::Long nScrX, tools::Long nScrY )
{
    Size aOnePixel = pDev->PixelToLogic(Size(1,1));
    tools::Long nOneX = aOnePixel.Width();
    tools::Long nOneY = aOnePixel.Height();

    bool bLayoutRTL = rDoc.IsLayoutRTL( nPrintTab );

    tools::Long nWidth = static_cast<tools::Long>(PRINT_HEADER_WIDTH * nScaleX);
    tools::Long nEndX = nScrX + nWidth;
    tools::Long nPosX = nScrX;
    if ( !bLayoutRTL )
    {
        nEndX -= nOneX;
        nPosX -= nOneX;
    }
    tools::Long nPosY = nScrY - nOneY;
    OUString aText;

    for (SCROW nRow=nY1; nRow<=nY2; nRow++)
    {
        sal_uInt16 nDocH = rDoc.GetRowHeight( nRow, nPrintTab );
        if (nDocH)
        {
            tools::Long nHeight = static_cast<tools::Long>(nDocH * nScaleY);
            tools::Long nEndY = nPosY + nHeight;

            pDev->DrawRect( tools::Rectangle( nPosX,nPosY,nEndX,nEndY ) );

            aText = OUString::number( nRow+1 );
            tools::Long nTextWidth = pDev->GetTextWidth(aText);
            tools::Long nTextHeight = pDev->GetTextHeight();
            tools::Long nAddX = ( nWidth  - nTextWidth  ) / 2;
            tools::Long nAddY = ( nHeight - nTextHeight ) / 2;
            pDev->DrawText( Point( nPosX+nAddX,nPosY+nAddY ), aText );

            nPosY = nEndY;
        }
    }
}

void ScPrintFunc::LocateColHdr( SCCOL nX1, SCCOL nX2, tools::Long nScrX, tools::Long nScrY,
                                bool bRepCol, ScPreviewLocationData& rLocationData )
{
    Size aOnePixel = pDev->PixelToLogic(Size(1,1));
    tools::Long nOneX = aOnePixel.Width();
    tools::Long nOneY = aOnePixel.Height();

    tools::Long nHeight = static_cast<tools::Long>(PRINT_HEADER_HEIGHT * nScaleY);
    tools::Long nEndY = nScrY + nHeight - nOneY;

    tools::Long nPosX = nScrX - nOneX;
    for (SCCOL nCol=nX1; nCol<=nX2; nCol++)
    {
        sal_uInt16 nDocW = rDoc.GetColWidth( nCol, nPrintTab );
        if (nDocW)
            nPosX += static_cast<tools::Long>(nDocW * nScaleX);
    }
    tools::Rectangle aCellRect( nScrX, nScrY, nPosX, nEndY );
    rLocationData.AddColHeaders( aCellRect, nX1, nX2, bRepCol );
}

void ScPrintFunc::LocateRowHdr( SCROW nY1, SCROW nY2, tools::Long nScrX, tools::Long nScrY,
                                bool bRepRow, ScPreviewLocationData& rLocationData )
{
    Size aOnePixel = pDev->PixelToLogic(Size(1,1));
    tools::Long nOneX = aOnePixel.Width();
    tools::Long nOneY = aOnePixel.Height();

    bool bLayoutRTL = rDoc.IsLayoutRTL( nPrintTab );

    tools::Long nWidth = static_cast<tools::Long>(PRINT_HEADER_WIDTH * nScaleX);
    tools::Long nEndX = nScrX + nWidth;
    if ( !bLayoutRTL )
        nEndX -= nOneX;

    tools::Long nPosY = nScrY - nOneY;
    nPosY += rDoc.GetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY);
    tools::Rectangle aCellRect( nScrX, nScrY, nEndX, nPosY );
    rLocationData.AddRowHeaders( aCellRect, nY1, nY2, bRepRow );
}

void ScPrintFunc::LocateArea( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
                                tools::Long nScrX, tools::Long nScrY, bool bRepCol, bool bRepRow,
                                ScPreviewLocationData& rLocationData )
{
    //  get MapMode for drawing objects (same MapMode as in ScOutputData::PrintDrawingLayer)

    Point aLogPos = OutputDevice::LogicToLogic(Point(nScrX,nScrY), aOffsetMode, aLogicMode);
    tools::Long nLogStX = aLogPos.X();
    tools::Long nLogStY = aLogPos.Y();

    SCCOL nCol;
    Point aTwipOffset;
    for (nCol=0; nCol<nX1; nCol++)
        aTwipOffset.AdjustX( -(rDoc.GetColWidth( nCol, nPrintTab )) );
    aTwipOffset.AdjustY( -sal_Int32(rDoc.GetRowHeight( 0, nY1-1, nPrintTab )) );

    Point aMMOffset(o3tl::convert(aTwipOffset, o3tl::Length::twip, o3tl::Length::mm100));
    aMMOffset += Point( nLogStX, nLogStY );
    MapMode aDrawMapMode( MapUnit::Map100thMM, aMMOffset, aLogicMode.GetScaleX(), aLogicMode.GetScaleY() );

    //  get pixel rectangle

    Size aOnePixel = pDev->PixelToLogic(Size(1,1));
    tools::Long nOneX = aOnePixel.Width();
    tools::Long nOneY = aOnePixel.Height();

    tools::Long nPosX = nScrX - nOneX;
    for (nCol=nX1; nCol<=nX2; nCol++)
    {
        sal_uInt16 nDocW = rDoc.GetColWidth( nCol, nPrintTab );
        if (nDocW)
            nPosX += static_cast<tools::Long>(nDocW * nScaleX);
    }

    tools::Long nPosY = nScrY - nOneY;
    nPosY += rDoc.GetScaledRowHeight( nY1, nY2, nPrintTab, nScaleY);
    tools::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,
                                tools::Long nScrX, tools::Long nScrY,
                                bool bShLeft, bool bShTop, bool bShRight, 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;

                            //!     hand over Flag at FillInfo  !!!!!
    ScRange aERange;
    bool bEmbed = rDoc.IsEmbedded();
    if (bEmbed)
    {
        rDoc.GetEmbedded(aERange);
        rDoc.ResetEmbedded();
    }

    Point aPos = OutputDevice::LogicToLogic(Point(nScrX,nScrY), aOffsetMode, aLogicMode);
    tools::Long nLogStX = aPos.X();
    tools::Long nLogStY = aPos.Y();

                    //  Assemble data

    ScTableInfo aTabInfo(nY1, nY2, true);
    rDoc.FillInfo( aTabInfo, nX1, nY1, nX2, nY2, nPrintTab,
                                        nScaleX, nScaleY, true, aTableParam.bFormulas );
    lcl_HidePrint( aTabInfo, nX1, nX2 );

    if (bEmbed)
        rDoc.SetEmbedded(aERange);

    ScOutputData aOutputData( pDev, OUTTYPE_PRINTER, aTabInfo, &rDoc, nPrintTab,
                                nScrX, nScrY, nX1, nY1, nX2, nY2, nScaleX, nScaleY );

    vcl::PDFExtOutDevData* pPDF = dynamic_cast<vcl::PDFExtOutDevData*>(pDev->GetExtOutDevData());
    bool bTaggedPDF = pPDF && pPDF->GetIsExportTaggedPDF();
    if (bTaggedPDF)
    {
        bool bReopen = aOutputData.ReopenPDFStructureElement(vcl::pdf::StructElement::Part);
        if (!bReopen)
        {
            sal_Int32 nId = pPDF->EnsureStructureElement(nullptr);
            pPDF->InitStructureElement(nId, vcl::pdf::StructElement::Part, u"Worksheet"_ustr);
            pPDF->BeginStructureElement(nId);
            pPDF->GetScPDFState()->m_WorksheetId = nId;
        }
    }

    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);
        //  don's set Clipping here (Mapmode is being moved)

        // #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 = ScModule::get()->GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor;
    aOutputData.SetGridColor( aGridColor );

    if ( !pPrinter )
    {
        OutputDevice* pRefDev = rDoc.GetPrinter();     // use the printer also for Preview
        Fraction aPrintFrac( nZoom, 100 );              // without nManualZoom
        //  MapMode, as it would arrive at the printer:
        pRefDev->SetMapMode( MapMode( MapUnit::Map100thMM, 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 );
    }

    if( aTableParam.bCellContent )
        aOutputData.DrawBackground(*pDev);

    pDev->SetClipRegion(vcl::Region(tools::Rectangle(
                aPos, Size(aOutputData.GetScrW(), aOutputData.GetScrH()))));
    pDev->SetClipRegion();

    if( aTableParam.bCellContent )
    {
        aOutputData.DrawExtraShadow( bShLeft, bShTop, bShRight, bShBottom );
        aOutputData.DrawFrame(*pDev);
        aOutputData.DrawSparklines(*pDev);
        aOutputData.DrawStrings();
        aOutputData.DrawEdit(false);
    }

    if (aTableParam.bGrid)
        aOutputData.DrawGrid(*pDev, truefalse);    // no page breaks

    aOutputData.AddPDFNotes();      // has no effect if not rendering PDF with notes enabled

    // test if all paint parts are hidden, then a paint is not necessary at all
    if(!bHideAllDrawingLayer)
    {
        // #i72502#
        aOutputData.PrintDrawingLayer(SC_LAYER_FRONT, aMMOffset);
    }

    if (bTaggedPDF)
    {
        aOutputData.PrintDrawingLayer(SC_LAYER_CONTROLS, aMMOffset);
        pPDF->EndStructureElement();
    }

    // #i72502#
    aOutputData.PrintDrawingLayer(SC_LAYER_INTERN, aMMOffset);

    if (!bTaggedPDF)
        aOutputData.PostPrintDrawingLayer(aMMOffset); // #i74768#
}

bool ScPrintFunc::IsMirror( tools::Long nPageNo )          // Mirror margins?
{
    return nPageUsage == SvxPageUsage::Mirror && (nPageNo & 1);
}

bool ScPrintFunc::IsLeft( tools::Long nPageNo )            // left foot notes?
{
    bool bLeft;
    if (nPageUsage == SvxPageUsage::Left)
        bLeft = true;
    else if (nPageUsage == SvxPageUsage::Right)
        bLeft = false;
    else
        bLeft = (nPageNo & 1) != 0;
    return bLeft;
}

void ScPrintFunc::MakeTableString()
{
    OUString aTmp;
    rDoc.GetName(nPrintTab, aTmp);
    aFieldData.aTabName = aTmp;
}

void ScPrintFunc::MakeEditEngine()
{
    if (!pEditEngine)
    {
        //  can't use document's edit engine pool here,
        //  because pool must have twips as default metric
        pEditEngine.reset( new ScHeaderEditEngine( EditEngine::CreatePool().get() ) );

        pEditEngine->EnableUndo(false);
        //fdo#45869 we want text to be positioned as it would be for the
        //high dpi printed output, not as would be ideal for the 96dpi preview
        //window itself
        pEditEngine->SetRefDevice(pPrinter ? pPrinter : rDoc.GetRefDevice());
        pEditEngine->SetWordDelimiters(
                ScEditUtil::ModifyDelimiters( pEditEngine->GetWordDelimiters() ) );
        pEditEngine->SetControlWord( pEditEngine->GetControlWord() & ~EEControlBits::RTFSTYLESHEETS );
        rDoc.ApplyAsianEditSettings( *pEditEngine );
        pEditEngine->EnableAutoColor( bUseStyleColor );

        //  Default-Set for alignment
        pEditDefaults.reset( new SfxItemSet( pEditEngine->GetEmptyItemSet() ) );

        const ScPatternAttr& rPattern(rDoc.getCellAttributeHelper().getDefaultCellAttribute());

        rPattern.FillEditItemSet( pEditDefaults.get() );
        //  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).CloneSetWhich(EE_CHAR_FONTHEIGHT) );
        pEditDefaults->Put( rPattern.GetItem(ATTR_CJK_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT_CJK) );
        pEditDefaults->Put( rPattern.GetItem(ATTR_CTL_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT_CTL) );
        //  don't 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())
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=93 H=96 G=94

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.