sc/source/ui/inc/output.hxx   |   15 
 sc/source/ui/view/output2.cxx | 1168 +++++++++++++++++++++---------------------
 2 files changed, 609 insertions(+), 574 deletions(-)

New commits:
commit 4bf3cda4dabd2fb37e386e21e578e2fdab0f1c61
Author:     Noel Grandin <[email protected]>
AuthorDate: Sat Jul 19 15:34:44 2025 +0200
Commit:     Noel Grandin <[email protected]>
CommitDate: Sat Jul 26 13:45:58 2025 +0200

    extract inner loop of ScOutputData::LayoutStrings into another func
    
    because it is getting rather hard to read
    
    Change-Id: I29535acf66b0a540727a8215e3ea8f2929b1dfb4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188068
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <[email protected]>
    (cherry picked from commit 92b7ef1baa4c8769a6788b3df561a88a89fff0ff)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188358
    Tested-by: Jenkins CollaboraOffice <[email protected]>

diff --git a/sc/source/ui/inc/output.hxx b/sc/source/ui/inc/output.hxx
index 3c6ebf6cf765..b7933cef53f6 100644
--- a/sc/source/ui/inc/output.hxx
+++ b/sc/source/ui/inc/output.hxx
@@ -54,6 +54,7 @@ class ScPageBreakData;
 class FmFormView;
 class ScFieldEditEngine;
 class SdrPaintWindow;
+class ScDrawStringsVars;
 
 #define SC_SCENARIO_HSPACE      60
 #define SC_SCENARIO_VSPACE      50
@@ -313,6 +314,20 @@ private:
     // and the single call to end of constructor to be sure this always happens
     void    SetCellRotations();
 
+    /// inner loop of LayoutStrings
+    void LayoutStringsImpl(bool bPixelToLogic, RowInfo* pThisRowInfo, SCCOL 
nX, SCROW nY, SCSIZE nArrY,
+                           std::optional<SCCOL>& oLastEmptyCellX,
+                           SCCOL nLastContentCol,
+                           std::vector<std::unique_ptr<ScPatternAttr> >& 
aAltPatterns,
+                           const ScPatternAttr*& pOldPattern,
+                           const SfxItemSet*& pOldCondSet,
+                           SvtScriptType& nOldScript,
+                           ScDrawStringsVars& aVars,
+                           bool& bProgress, tools::Long nPosX, tools::Long 
nPosY, bool bTaggedPDF,
+                           vcl::PDFExtOutDevData* pPDF,
+                           tools::Long nLayoutSign,
+                           KernArray& aDX);
+
 public:
 
     /**
diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx
index c241f65ab211..e581e00e9975 100644
--- a/sc/source/ui/view/output2.cxx
+++ b/sc/source/ui/view/output2.cxx
@@ -1544,11 +1544,6 @@ void ScOutputData::LayoutStrings(bool bPixelToLogic)
         --nLoopStartX;          // start before nX1 for rest of long text to 
the left
 
     // variables for GetOutputArea
-    OutputAreaParam aAreaParam;
-    bool bCellIsValue = false;
-    tools::Long nNeededWidth = 0;
-    const ScPatternAttr* pPattern = nullptr;
-    const SfxItemSet* pCondSet = nullptr;
     const ScPatternAttr* pOldPattern = nullptr;
     const SfxItemSet* pOldCondSet = nullptr;
     SvtScriptType nOldScript = SvtScriptType::NONE;
@@ -1590,658 +1585,683 @@ void ScOutputData::LayoutStrings(bool bPixelToLogic)
             {
                 if (bTaggedPDF)
                     
pPDF->WrapBeginStructureElement(vcl::pdf::StructElement::TableData, u"TD"_ustr);
+                LayoutStringsImpl(bPixelToLogic, pThisRowInfo, nX, nY, nArrY, 
oLastEmptyCellX, nLastContentCol,
+                                  aAltPatterns, pOldPattern, pOldCondSet, 
nOldScript, aVars,
+                                  bProgress, nPosX, nPosY, bTaggedPDF, pPDF, 
nLayoutSign, aDX);
+                nPosX += pRowInfo[0].basicCellInfo(nX).nWidth * nLayoutSign;
+                if (bTaggedPDF)
+                    pPDF->EndStructureElement();
+            }
+            if (bTaggedPDF)
+                pPDF->EndStructureElement();
+        }
+        nPosY += pRowInfo[nArrY].nHeight;
+    }
+    if (bTaggedPDF)
+        pPDF->EndStructureElement();
 
-                bool bMergeEmpty = false;
-                const ScCellInfo* pInfo = &pThisRowInfo->cellInfo(nX);
-                bool bEmpty = nX < nX1 || 
pThisRowInfo->basicCellInfo(nX).bEmptyCellText;
-
-                SCCOL nCellX = nX;                  // position where the cell 
really starts
-                SCROW nCellY = nY;
-                bool bDoCell = false;
-                bool bUseEditEngine = false;
-
-                //  Part of a merged cell?
+    if ( bProgress )
+        ScProgress::DeleteInterpretProgress();
+}
 
-                bool bOverlapped = (pInfo->bHOverlapped || 
pInfo->bVOverlapped);
-                if ( bOverlapped )
-                {
-                    bEmpty = true;
+/// inner loop of LayoutStrings
+void ScOutputData::LayoutStringsImpl(bool const bPixelToLogic, RowInfo* const 
pThisRowInfo,
+            SCCOL const nX, SCROW const nY, SCSIZE const nArrY,
+            std::optional<SCCOL>& oLastEmptyCellX,
+            SCCOL const nLastContentCol,
+            std::vector<std::unique_ptr<ScPatternAttr> >& aAltPatterns,
+            const ScPatternAttr*& pOldPattern,
+            const SfxItemSet*& pOldCondSet,
+            SvtScriptType& nOldScript,
+            ScDrawStringsVars& aVars,
+            bool& bProgress, tools::Long const nPosX, tools::Long const nPosY,
+            bool const bTaggedPDF, vcl::PDFExtOutDevData* const pPDF,
+            tools::Long const nLayoutSign, KernArray& aDX)
+{
+    const ScPatternAttr* pPattern = nullptr;
+    const SfxItemSet* pCondSet = nullptr;
+    bool bCellIsValue = false;
+    tools::Long nNeededWidth = 0;
+    OutputAreaParam aAreaParam;
+    bool bMergeEmpty = false;
+    const ScCellInfo* pInfo = &pThisRowInfo->cellInfo(nX);
+    bool bEmpty = nX < nX1 || pThisRowInfo->basicCellInfo(nX).bEmptyCellText;
 
-                    SCCOL nOverX;                   // start of the merged 
cells
-                    SCROW nOverY;
-                    bool bVisChanged = !pRowInfo[nArrY-1].bChanged;
-                    if (GetMergeOrigin( nX,nY, nArrY, nOverX,nOverY, 
bVisChanged ))
-                    {
-                        nCellX = nOverX;
-                        nCellY = nOverY;
-                        bDoCell = true;
-                    }
-                    else
-                        bMergeEmpty = true;
-                }
+    SCCOL nCellX = nX;                  // position where the cell really 
starts
+    SCROW nCellY = nY;
+    bool bDoCell = false;
+    bool bUseEditEngine = false;
 
-                //  Rest of a long text further to the left?
+    //  Part of a merged cell?
 
-                if ( bEmpty && !bMergeEmpty && nX < nX1 && !bOverlapped )
-                {
-                    if (!oLastEmptyCellX)
-                    {
-                        SCCOL nTempX=nX1;
-                        while (nTempX > 0 && IsEmptyCellText( pThisRowInfo, 
nTempX, nY ))
-                            --nTempX;
-                        oLastEmptyCellX = nTempX;
-                    }
+    bool bOverlapped = (pInfo->bHOverlapped || pInfo->bVOverlapped);
+    if ( bOverlapped )
+    {
+        bEmpty = true;
 
-                    if ( *oLastEmptyCellX < nX1 &&
-                         !IsEmptyCellText( pThisRowInfo, *oLastEmptyCellX, nY 
) &&
-                         !mpDoc->HasAttrib( *oLastEmptyCellX,nY,nTab, 
nX1,nY,nTab, HasAttrFlags::Merged | HasAttrFlags::Overlapped ) )
-                    {
-                        nCellX = *oLastEmptyCellX;
-                        bDoCell = true;
-                    }
-                }
+        SCCOL nOverX;                   // start of the merged cells
+        SCROW nOverY;
+        bool bVisChanged = !pRowInfo[nArrY-1].bChanged;
+        if (GetMergeOrigin( nX,nY, nArrY, nOverX,nOverY, bVisChanged ))
+        {
+            nCellX = nOverX;
+            nCellY = nOverY;
+            bDoCell = true;
+        }
+        else
+            bMergeEmpty = true;
+    }
 
-                //  Rest of a long text further to the right?
+    //  Rest of a long text further to the left?
 
-                if ( bEmpty && !bMergeEmpty && nX == nX2 && !bOverlapped )
-                {
-                    //  don't have to look further than nLastContentCol
+    if ( bEmpty && !bMergeEmpty && nX < nX1 && !bOverlapped )
+    {
+        if (!oLastEmptyCellX)
+        {
+            SCCOL nTempX=nX1;
+            while (nTempX > 0 && IsEmptyCellText( pThisRowInfo, nTempX, nY ))
+                --nTempX;
+            oLastEmptyCellX = nTempX;
+        }
 
-                    SCCOL nTempX=nX;
-                    while (nTempX < nLastContentCol && IsEmptyCellText( 
pThisRowInfo, nTempX, nY ))
-                        ++nTempX;
+        if ( *oLastEmptyCellX < nX1 &&
+             !IsEmptyCellText( pThisRowInfo, *oLastEmptyCellX, nY ) &&
+             !mpDoc->HasAttrib( *oLastEmptyCellX,nY,nTab, nX1,nY,nTab, 
HasAttrFlags::Merged | HasAttrFlags::Overlapped ) )
+        {
+            nCellX = *oLastEmptyCellX;
+            bDoCell = true;
+        }
+    }
 
-                    if ( nTempX > nX &&
-                         !IsEmptyCellText( pThisRowInfo, nTempX, nY ) &&
-                         !mpDoc->HasAttrib( nTempX,nY,nTab, nX,nY,nTab, 
HasAttrFlags::Merged | HasAttrFlags::Overlapped ) )
-                    {
-                        nCellX = nTempX;
-                        bDoCell = true;
-                    }
-                }
+    //  Rest of a long text further to the right?
 
-                //  normal visible cell
+    if ( bEmpty && !bMergeEmpty && nX == nX2 && !bOverlapped )
+    {
+        //  don't have to look further than nLastContentCol
 
-                if (!bEmpty)
-                    bDoCell = true;
+        SCCOL nTempX=nX;
+        while (nTempX < nLastContentCol && IsEmptyCellText( pThisRowInfo, 
nTempX, nY ))
+            ++nTempX;
 
-                //  don't output the cell that's being edited
+        if ( nTempX > nX &&
+             !IsEmptyCellText( pThisRowInfo, nTempX, nY ) &&
+             !mpDoc->HasAttrib( nTempX,nY,nTab, nX,nY,nTab, 
HasAttrFlags::Merged | HasAttrFlags::Overlapped ) )
+        {
+            nCellX = nTempX;
+            bDoCell = true;
+        }
+    }
 
-                if ( bDoCell && bEditMode && nCellX == nEditCol && nCellY == 
nEditRow )
-                    bDoCell = false;
+    //  normal visible cell
 
-                // skip text in cell if data bar/icon set is set and only 
value selected
-                if ( bDoCell )
-                {
-                    if(pInfo->pDataBar && !pInfo->pDataBar->mbShowValue)
-                        bDoCell = false;
-                    if(pInfo->pIconSet && !pInfo->pIconSet->mbShowValue)
-                        bDoCell = false;
-                }
+    if (!bEmpty)
+        bDoCell = true;
 
-                //  output the cell text
+    //  don't output the cell that's being edited
 
-                ScRefCellValue aCell;
-                if (bDoCell)
-                {
-                    if ( nCellY == nY && nCellX == nX && nCellX >= nX1 && 
nCellX <= nX2 )
-                        aCell = pThisRowInfo->cellInfo(nCellX).maCell;
-                    else
-                        GetVisibleCell( nCellX, nCellY, nTab, aCell );      // 
get from document
-                    if (aCell.isEmpty())
-                        bDoCell = false;
-                    else if (aCell.getType() == CELLTYPE_EDIT)
-                        bUseEditEngine = true;
-                }
+    if ( bDoCell && bEditMode && nCellX == nEditCol && nCellY == nEditRow )
+        bDoCell = false;
 
-                // Check if this cell is mis-spelled.
-                if (bDoCell && !bUseEditEngine && aCell.getType() == 
CELLTYPE_STRING)
-                {
-                    if (mpSpellCheckCxt && 
mpSpellCheckCxt->isMisspelled(nCellX, nCellY))
-                        bUseEditEngine = true;
-                }
+    // skip text in cell if data bar/icon set is set and only value selected
+    if ( bDoCell )
+    {
+        if(pInfo->pDataBar && !pInfo->pDataBar->mbShowValue)
+            bDoCell = false;
+        if(pInfo->pIconSet && !pInfo->pIconSet->mbShowValue)
+            bDoCell = false;
+    }
 
-                if (bDoCell && !bUseEditEngine)
-                {
-                    if ( nCellY == nY && nCellX >= nX1 && nCellX <= nX2 )
-                    {
-                        ScCellInfo& rCellInfo = pThisRowInfo->cellInfo(nCellX);
-                        pPattern = rCellInfo.pPatternAttr;
-                        pCondSet = rCellInfo.pConditionSet;
+    //  output the cell text
 
-                        if ( !pPattern )
-                        {
-                            // #i68085# pattern from cell info for hidden 
columns is null,
-                            // test for null is quicker than using column flags
-                            pPattern = mpDoc->GetPattern( nCellX, nCellY, nTab 
);
-                            pCondSet = mpDoc->GetCondResult( nCellX, nCellY, 
nTab );
-                        }
-                    }
-                    else        // get from document
-                    {
-                        pPattern = mpDoc->GetPattern( nCellX, nCellY, nTab );
-                        pCondSet = mpDoc->GetCondResult( nCellX, nCellY, nTab 
);
-                    }
-                    if ( mpDoc->GetPreviewFont() || 
mpDoc->GetPreviewCellStyle() )
-                    {
-                        
aAltPatterns.push_back(std::make_unique<ScPatternAttr>(*pPattern));
-                        ScPatternAttr* pAltPattern = aAltPatterns.back().get();
-                        if (  ScStyleSheet* pPreviewStyle = 
mpDoc->GetPreviewCellStyle( nCellX, nCellY, nTab ) )
-                        {
-                            pAltPattern->SetStyleSheet(pPreviewStyle);
-                        }
-                        else if ( SfxItemSet* pFontSet = 
mpDoc->GetPreviewFont( nCellX, nCellY, nTab ) )
-                        {
-                            if ( const SvxFontItem* pItem = 
pFontSet->GetItemIfSet( ATTR_FONT ) )
-                                pAltPattern->GetItemSet().Put( *pItem );
-                            if ( const SvxFontItem* pItem = 
pFontSet->GetItemIfSet( ATTR_CJK_FONT ) )
-                                pAltPattern->GetItemSet().Put( *pItem );
-                            if ( const SvxFontItem* pItem = 
pFontSet->GetItemIfSet( ATTR_CTL_FONT ) )
-                                pAltPattern->GetItemSet().Put( *pItem );
-                        }
-                        pPattern = pAltPattern;
-                    }
+    ScRefCellValue aCell;
+    if (bDoCell)
+    {
+        if ( nCellY == nY && nCellX == nX && nCellX >= nX1 && nCellX <= nX2 )
+            aCell = pThisRowInfo->cellInfo(nCellX).maCell;
+        else
+            GetVisibleCell( nCellX, nCellY, nTab, aCell );      // get from 
document
+        if (aCell.isEmpty())
+            bDoCell = false;
+        else if (aCell.getType() == CELLTYPE_EDIT)
+            bUseEditEngine = true;
+    }
 
-                    if (aCell.hasNumeric() &&
-                            pPattern->GetItem(ATTR_LINEBREAK, 
pCondSet).GetValue())
-                    {
-                        // Disable line break when the cell content is numeric.
-                        
aAltPatterns.push_back(std::make_unique<ScPatternAttr>(*pPattern));
-                        ScPatternAttr* pAltPattern = aAltPatterns.back().get();
-                        ScLineBreakCell aLineBreak(false);
-                        pAltPattern->GetItemSet().Put(aLineBreak);
-                        pPattern = pAltPattern;
-                    }
+    // Check if this cell is mis-spelled.
+    if (bDoCell && !bUseEditEngine && aCell.getType() == CELLTYPE_STRING)
+    {
+        if (mpSpellCheckCxt && mpSpellCheckCxt->isMisspelled(nCellX, nCellY))
+            bUseEditEngine = true;
+    }
 
-                    SvtScriptType nScript = mpDoc->GetCellScriptType(
-                        ScAddress(nCellX, nCellY, nTab),
-                        pPattern->GetNumberFormat(mpDoc->GetFormatTable(), 
pCondSet));
+    if (bDoCell && !bUseEditEngine)
+    {
+        if ( nCellY == nY && nCellX >= nX1 && nCellX <= nX2 )
+        {
+            ScCellInfo& rCellInfo = pThisRowInfo->cellInfo(nCellX);
+            pPattern = rCellInfo.pPatternAttr;
+            pCondSet = rCellInfo.pConditionSet;
 
-                    if (nScript == SvtScriptType::NONE)
-                        nScript = ScGlobal::GetDefaultScriptType();
+            if ( !pPattern )
+            {
+                // #i68085# pattern from cell info for hidden columns is null,
+                // test for null is quicker than using column flags
+                pPattern = mpDoc->GetPattern( nCellX, nCellY, nTab );
+                pCondSet = mpDoc->GetCondResult( nCellX, nCellY, nTab );
+            }
+        }
+        else        // get from document
+        {
+            pPattern = mpDoc->GetPattern( nCellX, nCellY, nTab );
+            pCondSet = mpDoc->GetCondResult( nCellX, nCellY, nTab );
+        }
+        if ( mpDoc->GetPreviewFont() || mpDoc->GetPreviewCellStyle() )
+        {
+            aAltPatterns.push_back(std::make_unique<ScPatternAttr>(*pPattern));
+            ScPatternAttr* pAltPattern = aAltPatterns.back().get();
+            if (  ScStyleSheet* pPreviewStyle = mpDoc->GetPreviewCellStyle( 
nCellX, nCellY, nTab ) )
+            {
+                pAltPattern->SetStyleSheet(pPreviewStyle);
+            }
+            else if ( SfxItemSet* pFontSet = mpDoc->GetPreviewFont( nCellX, 
nCellY, nTab ) )
+            {
+                if ( const SvxFontItem* pItem = pFontSet->GetItemIfSet( 
ATTR_FONT ) )
+                    pAltPattern->GetItemSet().Put( *pItem );
+                if ( const SvxFontItem* pItem = pFontSet->GetItemIfSet( 
ATTR_CJK_FONT ) )
+                    pAltPattern->GetItemSet().Put( *pItem );
+                if ( const SvxFontItem* pItem = pFontSet->GetItemIfSet( 
ATTR_CTL_FONT ) )
+                    pAltPattern->GetItemSet().Put( *pItem );
+            }
+            pPattern = pAltPattern;
+        }
 
-                    if ( !ScPatternAttr::areSame(pPattern, pOldPattern) || 
pCondSet != pOldCondSet ||
-                         nScript != nOldScript || mbSyntaxMode )
-                    {
-                        if ( StringDiffer(pOldPattern,pPattern) ||
-                             pCondSet != pOldCondSet || nScript != nOldScript 
|| mbSyntaxMode )
-                        {
-                            aVars.SetPattern(pPattern, pCondSet, aCell, 
nScript);
-                        }
-                        else
-                            aVars.SetPatternSimple( pPattern, pCondSet );
-                        pOldPattern = pPattern;
-                        pOldCondSet = pCondSet;
-                        nOldScript = nScript;
-                    }
+        if (aCell.hasNumeric() &&
+                pPattern->GetItem(ATTR_LINEBREAK, pCondSet).GetValue())
+        {
+            // Disable line break when the cell content is numeric.
+            aAltPatterns.push_back(std::make_unique<ScPatternAttr>(*pPattern));
+            ScPatternAttr* pAltPattern = aAltPatterns.back().get();
+            ScLineBreakCell aLineBreak(false);
+            pAltPattern->GetItemSet().Put(aLineBreak);
+            pPattern = pAltPattern;
+        }
 
-                    //  use edit engine for rotated, stacked or mixed-script 
text
-                    if ( aVars.GetOrient() == SvxCellOrientation::Stacked ||
-                         aVars.IsRotated() || IsAmbiguousScript(nScript) )
-                        bUseEditEngine = true;
-                }
-                if (bDoCell && !bUseEditEngine)
-                {
-                    bool bFormulaCell = (aCell.getType() == CELLTYPE_FORMULA);
-                    if ( bFormulaCell )
-                        lcl_CreateInterpretProgress(bProgress, mpDoc, 
aCell.getFormula());
-                    if ( aVars.SetText(aCell) )
-                        pOldPattern = nullptr;
-                    bUseEditEngine = aVars.HasEditCharacters() || 
(bFormulaCell && aCell.getFormula()->IsMultilineResult());
-                }
-                tools::Long nTotalMargin = 0;
-                SvxCellHorJustify eOutHorJust = SvxCellHorJustify::Standard;
-                if (bDoCell && !bUseEditEngine)
-                {
-                    CellType eCellType = aCell.getType();
-                    bCellIsValue = ( eCellType == CELLTYPE_VALUE );
-                    if ( eCellType == CELLTYPE_FORMULA )
-                    {
-                        ScFormulaCell* pFCell = aCell.getFormula();
-                        bCellIsValue = pFCell->IsRunning() || 
pFCell->IsValue();
-                    }
+        SvtScriptType nScript = mpDoc->GetCellScriptType(
+            ScAddress(nCellX, nCellY, nTab),
+            pPattern->GetNumberFormat(mpDoc->GetFormatTable(), pCondSet));
 
-                    const bool bNumberFormatIsText = lcl_isNumberFormatText( 
mpDoc, nCellX, nCellY, nTab );
-                    eOutHorJust = getAlignmentFromContext( aVars.GetHorJust(), 
bCellIsValue, aVars.GetString(),
-                            *pPattern, pCondSet, mpDoc, nTab, 
bNumberFormatIsText );
+        if (nScript == SvtScriptType::NONE)
+            nScript = ScGlobal::GetDefaultScriptType();
 
-                    bool bBreak = ( aVars.GetLineBreak() || aVars.GetHorJust() 
== SvxCellHorJustify::Block );
-                    // #i111387# #o11817313# tdf#121040 disable automatic line 
breaks for all number formats
-                    // Must be synchronized with ScColumn::GetNeededSize()
-                    SvNumberFormatter* pFormatter = mpDoc->GetFormatTable();
-                    if (bBreak && bCellIsValue && 
(pFormatter->GetType(aVars.GetResultValueFormat()) == SvNumFormatType::NUMBER))
-                        bBreak = false;
+        if ( !ScPatternAttr::areSame(pPattern, pOldPattern) || pCondSet != 
pOldCondSet ||
+             nScript != nOldScript || mbSyntaxMode )
+        {
+            if ( StringDiffer(pOldPattern,pPattern) ||
+                 pCondSet != pOldCondSet || nScript != nOldScript || 
mbSyntaxMode )
+            {
+                aVars.SetPattern(pPattern, pCondSet, aCell, nScript);
+            }
+            else
+                aVars.SetPatternSimple( pPattern, pCondSet );
+            pOldPattern = pPattern;
+            pOldCondSet = pCondSet;
+            nOldScript = nScript;
+        }
 
-                    bool bRepeat = aVars.IsRepeat() && !bBreak;
-                    bool bShrink = aVars.IsShrink() && !bBreak && !bRepeat;
+        //  use edit engine for rotated, stacked or mixed-script text
+        if ( aVars.GetOrient() == SvxCellOrientation::Stacked ||
+             aVars.IsRotated() || IsAmbiguousScript(nScript) )
+            bUseEditEngine = true;
+    }
+    if (bDoCell && !bUseEditEngine)
+    {
+        bool bFormulaCell = (aCell.getType() == CELLTYPE_FORMULA);
+        if ( bFormulaCell )
+            lcl_CreateInterpretProgress(bProgress, mpDoc, aCell.getFormula());
+        if ( aVars.SetText(aCell) )
+            pOldPattern = nullptr;
+        bUseEditEngine = aVars.HasEditCharacters() || (bFormulaCell && 
aCell.getFormula()->IsMultilineResult());
+    }
+    tools::Long nTotalMargin = 0;
+    SvxCellHorJustify eOutHorJust = SvxCellHorJustify::Standard;
+    if (bDoCell && !bUseEditEngine)
+    {
+        CellType eCellType = aCell.getType();
+        bCellIsValue = ( eCellType == CELLTYPE_VALUE );
+        if ( eCellType == CELLTYPE_FORMULA )
+        {
+            ScFormulaCell* pFCell = aCell.getFormula();
+            bCellIsValue = pFCell->IsRunning() || pFCell->IsValue();
+        }
 
-                    nTotalMargin =
-                        static_cast<tools::Long>(aVars.GetLeftTotal() * 
mnPPTX) +
-                        
static_cast<tools::Long>(aVars.GetMargin()->GetRightMargin() * mnPPTX);
+        const bool bNumberFormatIsText = lcl_isNumberFormatText( mpDoc, 
nCellX, nCellY, nTab );
+        eOutHorJust = getAlignmentFromContext( aVars.GetHorJust(), 
bCellIsValue, aVars.GetString(),
+                *pPattern, pCondSet, mpDoc, nTab, bNumberFormatIsText );
 
-                    nNeededWidth = aVars.GetTextSize().Width() + nTotalMargin;
+        bool bBreak = ( aVars.GetLineBreak() || aVars.GetHorJust() == 
SvxCellHorJustify::Block );
+        // #i111387# #o11817313# tdf#121040 disable automatic line breaks for 
all number formats
+        // Must be synchronized with ScColumn::GetNeededSize()
+        SvNumberFormatter* pFormatter = mpDoc->GetFormatTable();
+        if (bBreak && bCellIsValue && 
(pFormatter->GetType(aVars.GetResultValueFormat()) == SvNumFormatType::NUMBER))
+            bBreak = false;
 
-                    // GetOutputArea gives justified rectangles
-                    GetOutputArea( nX, nArrY, nPosX, nPosY, nCellX, nCellY, 
nNeededWidth,
-                                   *pPattern, 
sal::static_int_cast<sal_uInt16>(eOutHorJust),
-                                   bCellIsValue || bRepeat || bShrink, bBreak, 
false,
-                                   aAreaParam );
+        bool bRepeat = aVars.IsRepeat() && !bBreak;
+        bool bShrink = aVars.IsShrink() && !bBreak && !bRepeat;
 
-                    aVars.RepeatToFill( aAreaParam.mnColWidth - nTotalMargin );
-                    if ( bShrink )
-                    {
-                        if ( aVars.GetOrient() != SvxCellOrientation::Standard 
)
-                        {
-                            // Only horizontal scaling is handled here.
-                            // DrawEdit is used to vertically scale 90 deg 
rotated text.
-                            bUseEditEngine = true;
-                        }
-                        else if ( aAreaParam.mbLeftClip || 
aAreaParam.mbRightClip )     // horizontal
-                        {
-                            tools::Long nAvailable = 
aAreaParam.maAlignRect.GetWidth() - nTotalMargin;
-                            tools::Long nScaleSize = 
aVars.GetTextSize().Width();         // without margin
+        nTotalMargin =
+            static_cast<tools::Long>(aVars.GetLeftTotal() * mnPPTX) +
+            static_cast<tools::Long>(aVars.GetMargin()->GetRightMargin() * 
mnPPTX);
 
-                            if ( nAvailable > 0 && nScaleSize > 0 )       // 0 
if the text is empty (formulas, number formats)
-                            {
-                                tools::Long nScale = ( nAvailable * 100 ) / 
nScaleSize;
+        nNeededWidth = aVars.GetTextSize().Width() + nTotalMargin;
 
-                                aVars.SetShrinkScale( nScale, nOldScript );
-                                tools::Long nNewSize = 
aVars.GetTextSize().Width();
+        // GetOutputArea gives justified rectangles
+        GetOutputArea( nX, nArrY, nPosX, nPosY, nCellX, nCellY, nNeededWidth,
+                       *pPattern, 
sal::static_int_cast<sal_uInt16>(eOutHorJust),
+                       bCellIsValue || bRepeat || bShrink, bBreak, false,
+                       aAreaParam );
 
-                                sal_uInt16 nShrinkAgain = 0;
-                                while ( nNewSize > nAvailable && nShrinkAgain 
< SC_SHRINKAGAIN_MAX )
-                                {
-                                    // If the text is still too large, reduce 
the scale again by 10%, until it fits,
-                                    // at most 7 times (it's less than 50% of 
the calculated scale then).
+        aVars.RepeatToFill( aAreaParam.mnColWidth - nTotalMargin );
+        if ( bShrink )
+        {
+            if ( aVars.GetOrient() != SvxCellOrientation::Standard )
+            {
+                // Only horizontal scaling is handled here.
+                // DrawEdit is used to vertically scale 90 deg rotated text.
+                bUseEditEngine = true;
+            }
+            else if ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip )     // 
horizontal
+            {
+                tools::Long nAvailable = aAreaParam.maAlignRect.GetWidth() - 
nTotalMargin;
+                tools::Long nScaleSize = aVars.GetTextSize().Width();         
// without margin
 
-                                    nScale = ( nScale * 9 ) / 10;
-                                    aVars.SetShrinkScale( nScale, nOldScript );
-                                    nNewSize = aVars.GetTextSize().Width();
-                                    ++nShrinkAgain;
-                                }
-                                // If even at half the size the font still 
isn't rendered smaller,
-                                // fall back to normal clipping (showing ### 
for numbers).
-                                if ( nNewSize <= nAvailable )
-                                {
-                                    // Reset relevant parameters.
-                                    aAreaParam.mbLeftClip = 
aAreaParam.mbRightClip = false;
-                                    aAreaParam.mnLeftClipLength = 
aAreaParam.mnRightClipLength = 0;
-                                }
+                if ( nAvailable > 0 && nScaleSize > 0 )       // 0 if the text 
is empty (formulas, number formats)
+                {
+                    tools::Long nScale = ( nAvailable * 100 ) / nScaleSize;
 
-                                pOldPattern = nullptr;
-                            }
-                        }
-                    }
+                    aVars.SetShrinkScale( nScale, nOldScript );
+                    tools::Long nNewSize = aVars.GetTextSize().Width();
 
-                    if ( bRepeat && !aAreaParam.mbLeftClip && 
!aAreaParam.mbRightClip )
+                    sal_uInt16 nShrinkAgain = 0;
+                    while ( nNewSize > nAvailable && nShrinkAgain < 
SC_SHRINKAGAIN_MAX )
                     {
-                        tools::Long nAvailable = 
aAreaParam.maAlignRect.GetWidth() - nTotalMargin;
-                        tools::Long nRepeatSize = aVars.GetTextSize().Width(); 
        // without margin
-                        // When formatting for the printer, the text sizes 
don't always add up.
-                        // Round down (too few repetitions) rather than 
exceeding the cell size then:
-                        if ( pFmtDevice != mpRefDevice )
-                            ++nRepeatSize;
-                        if ( nRepeatSize > 0 )
-                        {
-                            tools::Long nRepeatCount = nAvailable / 
nRepeatSize;
-                            if ( nRepeatCount > 1 )
-                            {
-                                OUString aCellStr = aVars.GetString();
-                                OUStringBuffer aRepeated(aCellStr);
-                                for ( tools::Long nRepeat = 1; nRepeat < 
nRepeatCount; nRepeat++ )
-                                    aRepeated.append(aCellStr);
-                                aVars.SetAutoText( 
aRepeated.makeStringAndClear() );
-                            }
-                        }
-                    }
+                        // If the text is still too large, reduce the scale 
again by 10%, until it fits,
+                        // at most 7 times (it's less than 50% of the 
calculated scale then).
 
-                    //  use edit engine if automatic line breaks are needed
-                    if ( bBreak )
-                    {
-                        if ( aVars.GetOrient() == SvxCellOrientation::Standard 
)
-                            bUseEditEngine = ( aAreaParam.mbLeftClip || 
aAreaParam.mbRightClip );
-                        else
-                        {
-                            tools::Long nHeight = aVars.GetTextSize().Height() 
+
-                                            
static_cast<tools::Long>(aVars.GetMargin()->GetTopMargin()*mnPPTY) +
-                                            
static_cast<tools::Long>(aVars.GetMargin()->GetBottomMargin()*mnPPTY);
-                            bUseEditEngine = ( nHeight > 
aAreaParam.maClipRect.GetHeight() );
-                        }
+                        nScale = ( nScale * 9 ) / 10;
+                        aVars.SetShrinkScale( nScale, nOldScript );
+                        nNewSize = aVars.GetTextSize().Width();
+                        ++nShrinkAgain;
                     }
-                    if (!bUseEditEngine)
+                    // If even at half the size the font still isn't rendered 
smaller,
+                    // fall back to normal clipping (showing ### for numbers).
+                    if ( nNewSize <= nAvailable )
                     {
-                        bUseEditEngine =
-                            aVars.GetHorJust() == SvxCellHorJustify::Block &&
-                            aVars.GetHorJustMethod() == 
SvxCellJustifyMethod::Distribute;
+                        // Reset relevant parameters.
+                        aAreaParam.mbLeftClip = aAreaParam.mbRightClip = false;
+                        aAreaParam.mnLeftClipLength = 
aAreaParam.mnRightClipLength = 0;
                     }
+
+                    pOldPattern = nullptr;
                 }
-                if (bUseEditEngine)
+            }
+        }
+
+        if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip )
+        {
+            tools::Long nAvailable = aAreaParam.maAlignRect.GetWidth() - 
nTotalMargin;
+            tools::Long nRepeatSize = aVars.GetTextSize().Width();         // 
without margin
+            // When formatting for the printer, the text sizes don't always 
add up.
+            // Round down (too few repetitions) rather than exceeding the cell 
size then:
+            if ( pFmtDevice != mpRefDevice )
+                ++nRepeatSize;
+            if ( nRepeatSize > 0 )
+            {
+                tools::Long nRepeatCount = nAvailable / nRepeatSize;
+                if ( nRepeatCount > 1 )
                 {
-                    //  mark the cell in ScCellInfo to be drawn in DrawEdit:
-                    //  Cells to the left are marked directly, cells to the
-                    //  right are handled by the flag for nX2
-                    SCCOL nMarkX = ( nCellX <= nX2 ) ? nCellX : nX2;
-                    pThisRowInfo->basicCellInfo(nMarkX).bEditEngine = true;
-                    bDoCell = false;    // don't draw here
-
-                    // Mark the tagged "TD" structure element to be drawn in 
DrawEdit
-                    if (bTaggedPDF)
-                    {
-                        sal_Int32 nId = pPDF->GetCurrentStructureElement();
-                        pPDF->GetScPDFState()->m_TableDataMap[{nY, nX}] = nId;
-                    }
+                    OUString aCellStr = aVars.GetString();
+                    OUStringBuffer aRepeated(aCellStr);
+                    for ( tools::Long nRepeat = 1; nRepeat < nRepeatCount; 
nRepeat++ )
+                        aRepeated.append(aCellStr);
+                    aVars.SetAutoText( aRepeated.makeStringAndClear() );
                 }
-                if ( bDoCell )
-                {
-                    if ( bCellIsValue && ( aAreaParam.mbLeftClip || 
aAreaParam.mbRightClip ) )
-                    {
-                        bool bHasHashText = false;
-                        if (mbShowFormulas)
-                        {
-                            aVars.SetHashText();
-                            bHasHashText = true;
-                        }
-                        else
-                            // Adjust the decimals to fit the available column 
width.
-                            bHasHashText = aVars.SetTextToWidthOrHash( aCell, 
aAreaParam.mnColWidth - nTotalMargin );
-
-                        if ( bHasHashText )
-                        {
-                            tools::Long nMarkPixel = SC_CLIPMARK_SIZE * mnPPTX;
-
-                            if ( eOutHorJust == SvxCellHorJustify::Left )
-                            {
-                                if ( nCellY == nY && nCellX >= nX1 && nCellX 
<= nX2 )
-                                    pRowInfo[nArrY].cellInfo(nCellX).nClipMark 
|= ScClipMark::Right;
-                                bAnyClipped = true;
-                                aAreaParam.maClipRect.AdjustRight( 
-(nMarkPixel * nLayoutSign) );
-                            }
-                            else if ( eOutHorJust == SvxCellHorJustify::Right )
-                            {
-                                if ( nCellY == nY && nCellX >= nX1 && nCellX 
<= nX2 )
-                                    pRowInfo[nArrY].cellInfo(nCellX).nClipMark 
|= ScClipMark::Left;
-                                bAnyClipped = true;
-                                aAreaParam.maClipRect.AdjustLeft(nMarkPixel * 
nLayoutSign);
-                            }
-                            else
-                            {
-                                if ( nCellY == nY && nCellX >= nX1 && nCellX 
<= nX2 )
-                                {
-                                    pRowInfo[nArrY].cellInfo(nCellX).nClipMark 
|= ScClipMark::Right;
-                                    pRowInfo[nArrY].cellInfo(nCellX).nClipMark 
|= ScClipMark::Left;
-                                }
-                                bAnyClipped = true;
-                                aAreaParam.maClipRect.AdjustRight( 
-(nMarkPixel * nLayoutSign) );
-                                aAreaParam.maClipRect.AdjustLeft(nMarkPixel * 
nLayoutSign);
-                            }
-                        }
-
-                        nNeededWidth = aVars.GetTextSize().Width() +
-                                    static_cast<tools::Long>( 
aVars.GetLeftTotal() * mnPPTX ) +
-                                    static_cast<tools::Long>( 
aVars.GetMargin()->GetRightMargin() * mnPPTX );
-                        if ( nNeededWidth <= aAreaParam.maClipRect.GetWidth() )
-                        {
-                            // Cell value is no longer clipped.  Reset 
relevant parameters.
-                            aAreaParam.mbLeftClip = aAreaParam.mbRightClip = 
false;
-                            aAreaParam.mnLeftClipLength = 
aAreaParam.mnRightClipLength = 0;
-                        }
-                    }
+            }
+        }
 
-                    tools::Long nJustPosX = aAreaParam.maAlignRect.Left();     
// "justified" - effect of alignment will be added
-                    tools::Long nJustPosY = aAreaParam.maAlignRect.Top();
-                    tools::Long nAvailWidth = 
aAreaParam.maAlignRect.GetWidth();
-                    tools::Long nOutHeight = 
aAreaParam.maAlignRect.GetHeight();
+        //  use edit engine if automatic line breaks are needed
+        if ( bBreak )
+        {
+            if ( aVars.GetOrient() == SvxCellOrientation::Standard )
+                bUseEditEngine = ( aAreaParam.mbLeftClip || 
aAreaParam.mbRightClip );
+            else
+            {
+                tools::Long nHeight = aVars.GetTextSize().Height() +
+                                
static_cast<tools::Long>(aVars.GetMargin()->GetTopMargin()*mnPPTY) +
+                                
static_cast<tools::Long>(aVars.GetMargin()->GetBottomMargin()*mnPPTY);
+                bUseEditEngine = ( nHeight > aAreaParam.maClipRect.GetHeight() 
);
+            }
+        }
+        if (!bUseEditEngine)
+        {
+            bUseEditEngine =
+                aVars.GetHorJust() == SvxCellHorJustify::Block &&
+                aVars.GetHorJustMethod() == SvxCellJustifyMethod::Distribute;
+        }
+    }
+    if (bUseEditEngine)
+    {
+        //  mark the cell in ScCellInfo to be drawn in DrawEdit:
+        //  Cells to the left are marked directly, cells to the
+        //  right are handled by the flag for nX2
+        SCCOL nMarkX = ( nCellX <= nX2 ) ? nCellX : nX2;
+        pThisRowInfo->basicCellInfo(nMarkX).bEditEngine = true;
+        bDoCell = false;    // don't draw here
 
-                    bool bOutside = ( aAreaParam.maClipRect.Right() < nScrX || 
aAreaParam.maClipRect.Left() >= nScrX + nScrW );
-                    // Take adjusted values of aAreaParam.mbLeftClip and 
aAreaParam.mbRightClip
-                    bool bVClip = AdjustAreaParamClipRect(aAreaParam);
-                    bool bHClip = aAreaParam.mbLeftClip || 
aAreaParam.mbRightClip;
+        // Mark the tagged "TD" structure element to be drawn in DrawEdit
+        if (bTaggedPDF)
+        {
+            sal_Int32 nId = pPDF->GetCurrentStructureElement();
+            pPDF->GetScPDFState()->m_TableDataMap[{nY, nX}] = nId;
+        }
+    }
+    if ( bDoCell )
+    {
+        if ( bCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip 
) )
+        {
+            bool bHasHashText = false;
+            if (mbShowFormulas)
+            {
+                aVars.SetHashText();
+                bHasHashText = true;
+            }
+            else
+                // Adjust the decimals to fit the available column width.
+                bHasHashText = aVars.SetTextToWidthOrHash( aCell, 
aAreaParam.mnColWidth - nTotalMargin );
 
-                    // check horizontal space
+            if ( bHasHashText )
+            {
+                tools::Long nMarkPixel = SC_CLIPMARK_SIZE * mnPPTX;
 
-                    if ( !bOutside )
+                if ( eOutHorJust == SvxCellHorJustify::Left )
+                {
+                    if ( nCellY == nY && nCellX >= nX1 && nCellX <= nX2 )
+                        pRowInfo[nArrY].cellInfo(nCellX).nClipMark |= 
ScClipMark::Right;
+                    bAnyClipped = true;
+                    aAreaParam.maClipRect.AdjustRight( -(nMarkPixel * 
nLayoutSign) );
+                }
+                else if ( eOutHorJust == SvxCellHorJustify::Right )
+                {
+                    if ( nCellY == nY && nCellX >= nX1 && nCellX <= nX2 )
+                        pRowInfo[nArrY].cellInfo(nCellX).nClipMark |= 
ScClipMark::Left;
+                    bAnyClipped = true;
+                    aAreaParam.maClipRect.AdjustLeft(nMarkPixel * nLayoutSign);
+                }
+                else
+                {
+                    if ( nCellY == nY && nCellX >= nX1 && nCellX <= nX2 )
                     {
-                        bool bRightAdjusted = false;        // to correct text 
width calculation later
-                        switch (eOutHorJust)
-                        {
-                            case SvxCellHorJustify::Left:
-                                nJustPosX += static_cast<tools::Long>( 
aVars.GetLeftTotal() * mnPPTX );
-                                break;
-                            case SvxCellHorJustify::Right:
-                                nJustPosX += nAvailWidth - 
aVars.GetTextSize().Width() -
-                                            static_cast<tools::Long>( 
aVars.GetRightTotal() * mnPPTX );
-                                bRightAdjusted = true;
-                                break;
-                            case SvxCellHorJustify::Center:
-                                nJustPosX += ( nAvailWidth - 
aVars.GetTextSize().Width() +
-                                            static_cast<tools::Long>( 
aVars.GetLeftTotal() * mnPPTX ) -
-                                            static_cast<tools::Long>( 
aVars.GetMargin()->GetRightMargin() * mnPPTX ) ) / 2;
-                                break;
-                            default:
-                            {
-                                // added to avoid warnings
-                            }
-                        }
+                        pRowInfo[nArrY].cellInfo(nCellX).nClipMark |= 
ScClipMark::Right;
+                        pRowInfo[nArrY].cellInfo(nCellX).nClipMark |= 
ScClipMark::Left;
+                    }
+                    bAnyClipped = true;
+                    aAreaParam.maClipRect.AdjustRight( -(nMarkPixel * 
nLayoutSign) );
+                    aAreaParam.maClipRect.AdjustLeft(nMarkPixel * nLayoutSign);
+                }
+            }
 
-                        tools::Long nTestClipHeight = 
aVars.GetTextSize().Height();
-                        switch (aVars.GetVerJust())
-                        {
-                            case SvxCellVerJustify::Top:
-                            case SvxCellVerJustify::Block:
-                                {
-                                    tools::Long nTop = 
static_cast<tools::Long>( aVars.GetMargin()->GetTopMargin() * mnPPTY );
-                                    nJustPosY += nTop;
-                                    nTestClipHeight += nTop;
-                                }
-                                break;
-                            case SvxCellVerJustify::Bottom:
-                                {
-                                    tools::Long nBot = 
static_cast<tools::Long>( aVars.GetMargin()->GetBottomMargin() * mnPPTY );
-                                    nJustPosY += nOutHeight - 
aVars.GetTextSize().Height() - nBot;
-                                    nTestClipHeight += nBot;
-                                }
-                                break;
-                            case SvxCellVerJustify::Center:
-                                {
-                                    tools::Long nTop = 
static_cast<tools::Long>( aVars.GetMargin()->GetTopMargin() * mnPPTY );
-                                    tools::Long nBot = 
static_cast<tools::Long>( aVars.GetMargin()->GetBottomMargin() * mnPPTY );
-                                    nJustPosY += ( nOutHeight + nTop -
-                                                    
aVars.GetTextSize().Height() - nBot ) / 2;
-                                    nTestClipHeight += std::abs( nTop - nBot );
-                                }
-                                break;
-                            default:
-                            {
-                                // added to avoid warnings
-                            }
-                        }
+            nNeededWidth = aVars.GetTextSize().Width() +
+                        static_cast<tools::Long>( aVars.GetLeftTotal() * 
mnPPTX ) +
+                        static_cast<tools::Long>( 
aVars.GetMargin()->GetRightMargin() * mnPPTX );
+            if ( nNeededWidth <= aAreaParam.maClipRect.GetWidth() )
+            {
+                // Cell value is no longer clipped.  Reset relevant parameters.
+                aAreaParam.mbLeftClip = aAreaParam.mbRightClip = false;
+                aAreaParam.mnLeftClipLength = aAreaParam.mnRightClipLength = 0;
+            }
+        }
 
-                        if ( nTestClipHeight > nOutHeight )
-                        {
-                            // no vertical clipping when printing cells with 
optimal height,
-                            // except when font size is from conditional 
formatting.
-                            if ( eType != OUTTYPE_PRINTER ||
-                                    ( mpDoc->GetRowFlags( nCellY, nTab ) & 
CRFlags::ManualSize ) ||
-                                    ( aVars.HasCondHeight() ) )
-                                bVClip = true;
-                        }
+        tools::Long nJustPosX = aAreaParam.maAlignRect.Left();     // 
"justified" - effect of alignment will be added
+        tools::Long nJustPosY = aAreaParam.maAlignRect.Top();
+        tools::Long nAvailWidth = aAreaParam.maAlignRect.GetWidth();
+        tools::Long nOutHeight = aAreaParam.maAlignRect.GetHeight();
 
-                        if ( bHClip || bVClip )
-                        {
-                            // only clip the affected dimension so that not 
all right-aligned
-                            // columns are cut off when performing a 
non-proportional resize
-                            if (!bHClip)
-                            {
-                                aAreaParam.maClipRect.SetLeft( nScrX );
-                                aAreaParam.maClipRect.SetRight( nScrX+nScrW );
-                            }
-                            if (!bVClip)
-                            {
-                                aAreaParam.maClipRect.SetTop( nScrY );
-                                aAreaParam.maClipRect.SetBottom( nScrY+nScrH );
-                            }
+        bool bOutside = ( aAreaParam.maClipRect.Right() < nScrX || 
aAreaParam.maClipRect.Left() >= nScrX + nScrW );
+        // Take adjusted values of aAreaParam.mbLeftClip and 
aAreaParam.mbRightClip
+        bool bVClip = AdjustAreaParamClipRect(aAreaParam);
+        bool bHClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
 
-                            //  aClipRect is not used after 
SetClipRegion/IntersectClipRegion,
-                            //  so it can be modified here
-                            if (bPixelToLogic)
-                                aAreaParam.maClipRect = 
mpRefDevice->PixelToLogic( aAreaParam.maClipRect );
+        // check horizontal space
 
-                            if (bMetaFile)
-                            {
-                                mpDev->Push();
-                                mpDev->IntersectClipRegion( 
aAreaParam.maClipRect );
-                            }
-                            else
-                                mpDev->SetClipRegion( vcl::Region( 
aAreaParam.maClipRect ) );
-                        }
+        if ( !bOutside )
+        {
+            bool bRightAdjusted = false;        // to correct text width 
calculation later
+            switch (eOutHorJust)
+            {
+                case SvxCellHorJustify::Left:
+                    nJustPosX += static_cast<tools::Long>( 
aVars.GetLeftTotal() * mnPPTX );
+                    break;
+                case SvxCellHorJustify::Right:
+                    nJustPosX += nAvailWidth - aVars.GetTextSize().Width() -
+                                static_cast<tools::Long>( 
aVars.GetRightTotal() * mnPPTX );
+                    bRightAdjusted = true;
+                    break;
+                case SvxCellHorJustify::Center:
+                    nJustPosX += ( nAvailWidth - aVars.GetTextSize().Width() +
+                                static_cast<tools::Long>( aVars.GetLeftTotal() 
* mnPPTX ) -
+                                static_cast<tools::Long>( 
aVars.GetMargin()->GetRightMargin() * mnPPTX ) ) / 2;
+                    break;
+                default:
+                {
+                    // added to avoid warnings
+                }
+            }
 
-                        Point aURLStart( nJustPosX, nJustPosY );    // copy 
before modifying for orientation
+            tools::Long nTestClipHeight = aVars.GetTextSize().Height();
+            switch (aVars.GetVerJust())
+            {
+                case SvxCellVerJustify::Top:
+                case SvxCellVerJustify::Block:
+                    {
+                        tools::Long nTop = static_cast<tools::Long>( 
aVars.GetMargin()->GetTopMargin() * mnPPTY );
+                        nJustPosY += nTop;
+                        nTestClipHeight += nTop;
+                    }
+                    break;
+                case SvxCellVerJustify::Bottom:
+                    {
+                        tools::Long nBot = static_cast<tools::Long>( 
aVars.GetMargin()->GetBottomMargin() * mnPPTY );
+                        nJustPosY += nOutHeight - aVars.GetTextSize().Height() 
- nBot;
+                        nTestClipHeight += nBot;
+                    }
+                    break;
+                case SvxCellVerJustify::Center:
+                    {
+                        tools::Long nTop = static_cast<tools::Long>( 
aVars.GetMargin()->GetTopMargin() * mnPPTY );
+                        tools::Long nBot = static_cast<tools::Long>( 
aVars.GetMargin()->GetBottomMargin() * mnPPTY );
+                        nJustPosY += ( nOutHeight + nTop -
+                                        aVars.GetTextSize().Height() - nBot ) 
/ 2;
+                        nTestClipHeight += std::abs( nTop - nBot );
+                    }
+                    break;
+                default:
+                {
+                    // added to avoid warnings
+                }
+            }
 
-                        switch (aVars.GetOrient())
-                        {
-                            case SvxCellOrientation::Standard:
-                                nJustPosY += aVars.GetAscent();
-                                break;
-                            case SvxCellOrientation::TopBottom:
-                                nJustPosX += aVars.GetTextSize().Width() - 
aVars.GetAscent();
-                                break;
-                            case SvxCellOrientation::BottomUp:
-                                nJustPosY += aVars.GetTextSize().Height();
-                                nJustPosX += aVars.GetAscent();
-                                break;
-                            default:
-                            {
-                                // added to avoid warnings
-                            }
-                        }
+            if ( nTestClipHeight > nOutHeight )
+            {
+                // no vertical clipping when printing cells with optimal 
height,
+                // except when font size is from conditional formatting.
+                if ( eType != OUTTYPE_PRINTER ||
+                        ( mpDoc->GetRowFlags( nCellY, nTab ) & 
CRFlags::ManualSize ) ||
+                        ( aVars.HasCondHeight() ) )
+                    bVClip = true;
+            }
 
-                        // When clipping, the visible part is now completely 
defined by the alignment,
-                        // there's no more special handling to show the right 
part of RTL text.
+            if ( bHClip || bVClip )
+            {
+                // only clip the affected dimension so that not all 
right-aligned
+                // columns are cut off when performing a non-proportional 
resize
+                if (!bHClip)
+                {
+                    aAreaParam.maClipRect.SetLeft( nScrX );
+                    aAreaParam.maClipRect.SetRight( nScrX+nScrW );
+                }
+                if (!bVClip)
+                {
+                    aAreaParam.maClipRect.SetTop( nScrY );
+                    aAreaParam.maClipRect.SetBottom( nScrY+nScrH );
+                }
 
-                        Point aDrawTextPos( nJustPosX, nJustPosY );
-                        if ( bPixelToLogic )
-                        {
-                            //  undo text width adjustment in pixels
-                            if (bRightAdjusted)
-                                
aDrawTextPos.AdjustX(aVars.GetTextSize().Width() );
+                //  aClipRect is not used after 
SetClipRegion/IntersectClipRegion,
+                //  so it can be modified here
+                if (bPixelToLogic)
+                    aAreaParam.maClipRect = mpRefDevice->PixelToLogic( 
aAreaParam.maClipRect );
 
-                            aDrawTextPos = mpRefDevice->PixelToLogic( 
aDrawTextPos );
+                if (bMetaFile)
+                {
+                    mpDev->Push();
+                    mpDev->IntersectClipRegion( aAreaParam.maClipRect );
+                }
+                else
+                    mpDev->SetClipRegion( vcl::Region( aAreaParam.maClipRect ) 
);
+            }
 
-                            //  redo text width adjustment in logic units
-                            if (bRightAdjusted)
-                                aDrawTextPos.AdjustX( 
-(aVars.GetOriginalWidth()) );
-                        }
+            Point aURLStart( nJustPosX, nJustPosY );    // copy before 
modifying for orientation
 
-                        // in Metafiles always use DrawTextArray to ensure 
that positions are
-                        // recorded (for non-proportional resize):
+            switch (aVars.GetOrient())
+            {
+                case SvxCellOrientation::Standard:
+                    nJustPosY += aVars.GetAscent();
+                    break;
+                case SvxCellOrientation::TopBottom:
+                    nJustPosX += aVars.GetTextSize().Width() - 
aVars.GetAscent();
+                    break;
+                case SvxCellOrientation::BottomUp:
+                    nJustPosY += aVars.GetTextSize().Height();
+                    nJustPosX += aVars.GetAscent();
+                    break;
+                default:
+                {
+                    // added to avoid warnings
+                }
+            }
 
-                        const OUString& aString = aVars.GetString();
-                        if (!aString.isEmpty())
-                        {
-                            if (bTaggedPDF)
-                                
pPDF->WrapBeginStructureElement(vcl::pdf::StructElement::Paragraph, u"P"_ustr);
+            // When clipping, the visible part is now completely defined by 
the alignment,
+            // there's no more special handling to show the right part of RTL 
text.
 
-                            // If the string is clipped, make it shorter for
-                            // better performance since drawing by HarfBuzz is
-                            // quite expensive especially for long string.
+            Point aDrawTextPos( nJustPosX, nJustPosY );
+            if ( bPixelToLogic )
+            {
+                //  undo text width adjustment in pixels
+                if (bRightAdjusted)
+                    aDrawTextPos.AdjustX(aVars.GetTextSize().Width() );
 
-                            OUString aShort = aString;
+                aDrawTextPos = mpRefDevice->PixelToLogic( aDrawTextPos );
 
-                            // But never fiddle with numeric values.
-                            // (Which was the cause of tdf#86024).
-                            // The General automatic format output takes
-                            // care of this, or fixed width numbers either fit
-                            // or display as ###.
-                            if (!bCellIsValue)
-                            {
-                                double fVisibleRatio = 1.0;
-                                double fTextWidth = 
aVars.GetTextSize().Width();
-                                sal_Int32 nTextLen = aString.getLength();
-                                if (eOutHorJust == SvxCellHorJustify::Left && 
aAreaParam.mnRightClipLength > 0)
-                                {
-                                    fVisibleRatio = (fTextWidth - 
aAreaParam.mnRightClipLength) / fTextWidth;
-                                    if (0.0 < fVisibleRatio && fVisibleRatio < 
1.0)
-                                    {
-                                        // Only show the left-end segment.
-                                        sal_Int32 nShortLen = 
fVisibleRatio*nTextLen + 1;
-                                        aShort = aShort.copy(0, nShortLen);
-                                    }
-                                }
-                                else if (eOutHorJust == 
SvxCellHorJustify::Right && aAreaParam.mnLeftClipLength > 0)
-                                {
-                                    fVisibleRatio = (fTextWidth - 
aAreaParam.mnLeftClipLength) / fTextWidth;
-                                    if (0.0 < fVisibleRatio && fVisibleRatio < 
1.0)
-                                    {
-                                        // Only show the right-end segment.
-                                        sal_Int32 nShortLen = 
fVisibleRatio*nTextLen + 1;
-                                        aShort = 
aShort.copy(nTextLen-nShortLen);
-
-                                        // Adjust the text position after 
shortening of the string.
-                                        double fShortWidth = 
aVars.GetFmtTextWidth(aShort);
-                                        double fOffset = fTextWidth - 
fShortWidth;
-                                        aDrawTextPos.Move(fOffset, 0);
-                                    }
-                                }
-                            }
+                //  redo text width adjustment in logic units
+                if (bRightAdjusted)
+                    aDrawTextPos.AdjustX( -(aVars.GetOriginalWidth()) );
+            }
 
-                            if (bMetaFile || pFmtDevice != mpDev || aZoomX != 
aZoomY)
-                            {
-                                size_t nLen = aShort.getLength();
-                                if (aDX.size() < nLen)
-                                    aDX.resize(nLen, 0);
+            // in Metafiles always use DrawTextArray to ensure that positions 
are
+            // recorded (for non-proportional resize):
 
-                                pFmtDevice->GetTextArray(aShort, &aDX);
+            const OUString& aString = aVars.GetString();
+            if (!aString.isEmpty())
+            {
+                if (bTaggedPDF)
+                    
pPDF->WrapBeginStructureElement(vcl::pdf::StructElement::Paragraph, u"P"_ustr);
 
-                                if ( !mpRefDevice->GetConnectMetaFile() ||
-                                        mpRefDevice->GetOutDevType() == 
OUTDEV_PRINTER )
-                                {
-                                    double fMul = GetStretch();
-                                    for (size_t i = 0; i < nLen; ++i)
-                                        aDX[i] /= fMul;
-                                }
+                // If the string is clipped, make it shorter for
+                // better performance since drawing by HarfBuzz is
+                // quite expensive especially for long string.
 
-                                mpDev->DrawTextArray(aDrawTextPos, aShort, 
aDX, {}, 0, nLen);
-                            }
-                            else
-                            {
-                                mpDev->DrawText(aDrawTextPos, aShort, 0, -1, 
nullptr, nullptr,
-                                    aVars.GetLayoutGlyphs(aShort));
-                            }
-                            if (bTaggedPDF)
-                                pPDF->EndStructureElement();
-                        }
+                OUString aShort = aString;
 
-                        if ( bHClip || bVClip )
+                // But never fiddle with numeric values.
+                // (Which was the cause of tdf#86024).
+                // The General automatic format output takes
+                // care of this, or fixed width numbers either fit
+                // or display as ###.
+                if (!bCellIsValue)
+                {
+                    double fVisibleRatio = 1.0;
+                    double fTextWidth = aVars.GetTextSize().Width();
+                    sal_Int32 nTextLen = aString.getLength();
+                    if (eOutHorJust == SvxCellHorJustify::Left && 
aAreaParam.mnRightClipLength > 0)
+                    {
+                        fVisibleRatio = (fTextWidth - 
aAreaParam.mnRightClipLength) / fTextWidth;
+                        if (0.0 < fVisibleRatio && fVisibleRatio < 1.0)
                         {
-                            if (bMetaFile)
-                                mpDev->Pop();
-                            else
-                                mpDev->SetClipRegion();
+                            // Only show the left-end segment.
+                            sal_Int32 nShortLen = fVisibleRatio*nTextLen + 1;
+                            aShort = aShort.copy(0, nShortLen);
                         }
-
-                        // PDF: whole-cell hyperlink from formula?
-                        bool bHasURL = pPDF && aCell.getType() == 
CELLTYPE_FORMULA && aCell.getFormula()->IsHyperLinkCell();
-                        if (bHasURL)
+                    }
+                    else if (eOutHorJust == SvxCellHorJustify::Right && 
aAreaParam.mnLeftClipLength > 0)
+                    {
+                        fVisibleRatio = (fTextWidth - 
aAreaParam.mnLeftClipLength) / fTextWidth;
+                        if (0.0 < fVisibleRatio && fVisibleRatio < 1.0)
                         {
-                            tools::Rectangle aURLRect( aURLStart, 
aVars.GetTextSize() );
-                            lcl_DoHyperlinkResult(mpDev, aURLRect, aCell);
+                            // Only show the right-end segment.
+                            sal_Int32 nShortLen = fVisibleRatio*nTextLen + 1;
+                            aShort = aShort.copy(nTextLen-nShortLen);
+
+                            // Adjust the text position after shortening of 
the string.
+                            double fShortWidth = aVars.GetFmtTextWidth(aShort);
+                            double fOffset = fTextWidth - fShortWidth;
+                            aDrawTextPos.Move(fOffset, 0);
                         }
                     }
                 }
-                nPosX += pRowInfo[0].basicCellInfo(nX).nWidth * nLayoutSign;
+
+                if (bMetaFile || pFmtDevice != mpDev || aZoomX != aZoomY)
+                {
+                    size_t nLen = aShort.getLength();
+                    if (aDX.size() < nLen)
+                        aDX.resize(nLen, 0);
+
+                    pFmtDevice->GetTextArray(aShort, &aDX);
+
+                    if ( !mpRefDevice->GetConnectMetaFile() ||
+                            mpRefDevice->GetOutDevType() == OUTDEV_PRINTER )
+                    {
+                        double fMul = GetStretch();
+                        for (size_t i = 0; i < nLen; ++i)
+                            aDX[i] /= fMul;
+                    }
+
+                    mpDev->DrawTextArray(aDrawTextPos, aShort, aDX, {}, 0, 
nLen);
+                }
+                else
+                {
+                    mpDev->DrawText(aDrawTextPos, aShort, 0, -1, nullptr, 
nullptr,
+                        aVars.GetLayoutGlyphs(aShort));
+                }
                 if (bTaggedPDF)
+                {
                     pPDF->EndStructureElement();
+                }
+            }
+
+            if ( bHClip || bVClip )
+            {
+                if (bMetaFile)
+                    mpDev->Pop();
+                else
+                    mpDev->SetClipRegion();
+            }
+
+            // PDF: whole-cell hyperlink from formula?
+            bool bHasURL = pPDF && aCell.getType() == CELLTYPE_FORMULA && 
aCell.getFormula()->IsHyperLinkCell();
+            if (bHasURL)
+            {
+                tools::Rectangle aURLRect( aURLStart, aVars.GetTextSize() );
+                lcl_DoHyperlinkResult(mpDev, aURLRect, aCell);
             }
-            if (bTaggedPDF)
-                pPDF->EndStructureElement();
         }
-        nPosY += pRowInfo[nArrY].nHeight;
     }
-    if (bTaggedPDF)
-        pPDF->EndStructureElement();
-
-    if ( bProgress )
-        ScProgress::DeleteInterpretProgress();
 }
 
 void ScOutputData::SetRefDevice( OutputDevice* pRDev )

Reply via email to