sc/source/ui/inc/output.hxx   |    1 +
 sc/source/ui/view/output2.cxx |   25 +++++++++++++++----------
 2 files changed, 16 insertions(+), 10 deletions(-)

New commits:
commit d814d5610118cd4aed49f486295b449d2a75ae30
Author:     Noel Grandin <noelgran...@gmail.com>
AuthorDate: Sat Jul 26 13:56:41 2025 +0200
Commit:     Noel Grandin <noelgran...@gmail.com>
CommitDate: Sun Jul 27 21:37:28 2025 +0200

    cool#11336 reduce cost of IsEmptyCellText (2)
    
    if we have to produce output data for a large range, we end
    up with an O(n^2) loop because we loop over X, while looping over X
    
    Change-Id: Ia16f635257e2547731e3343026c52cb6e8712d81
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188400
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>
    Tested-by: Jenkins

diff --git a/sc/source/ui/inc/output.hxx b/sc/source/ui/inc/output.hxx
index f120c2d66253..8c805ea09a92 100644
--- a/sc/source/ui/inc/output.hxx
+++ b/sc/source/ui/inc/output.hxx
@@ -316,6 +316,7 @@ private:
     /// inner loop of LayoutStrings
     void LayoutStringsImpl(bool bPixelToLogic, RowInfo* pThisRowInfo, SCCOL 
nX, SCROW nY, SCSIZE nArrY,
                            std::optional<SCCOL>& oFirstNonEmptyCellX,
+                           std::optional<SCCOL>& oLastEmptyCellX,
                            SCCOL nLastContentCol,
                            std::vector<std::unique_ptr<ScPatternAttr> >& 
aAltPatterns,
                            const ScPatternAttr*& pOldPattern,
diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx
index 470d2f4c3de5..64c9e9b5c1d4 100644
--- a/sc/source/ui/view/output2.cxx
+++ b/sc/source/ui/view/output2.cxx
@@ -1559,9 +1559,10 @@ void ScOutputData::LayoutStrings(bool bPixelToLogic)
             if ( nLoopStartX < mnX1 )
                 nPosX -= mpRowInfo[0].basicCellInfo(nLoopStartX).nWidth * 
nLayoutSign;
             std::optional<SCCOL> oFirstNonEmptyCellX;
+            std::optional<SCCOL> oLastEmptyCellX;
             for (SCCOL nX=nLoopStartX; nX<=mnX2; nX++)
             {
-                LayoutStringsImpl(bPixelToLogic, pThisRowInfo, nX, nY, nArrY, 
oFirstNonEmptyCellX, nLastContentCol,
+                LayoutStringsImpl(bPixelToLogic, pThisRowInfo, nX, nY, nArrY, 
oFirstNonEmptyCellX, oLastEmptyCellX, nLastContentCol,
                                   aAltPatterns, pOldPattern, pOldCondSet, 
nOldScript, aVars,
                                   bProgress, nPosX, nPosY, bTaggedPDF, 
bReopenRowTag, pPDF, nLayoutSign, aDX);
                 nPosX += mpRowInfo[0].basicCellInfo(nX).nWidth * nLayoutSign;
@@ -1580,6 +1581,7 @@ void ScOutputData::LayoutStrings(bool bPixelToLogic)
 void ScOutputData::LayoutStringsImpl(bool const bPixelToLogic, RowInfo* const 
pThisRowInfo,
             SCCOL const nX, SCROW const nY, SCSIZE const nArrY,
             std::optional<SCCOL>& oFirstNonEmptyCellX,
+            std::optional<SCCOL>& oLastEmptyCellX,
             SCCOL const nLastContentCol,
             std::vector<std::unique_ptr<ScPatternAttr> >& aAltPatterns,
             const ScPatternAttr*& pOldPattern,
@@ -1649,17 +1651,20 @@ void ScOutputData::LayoutStringsImpl(bool const 
bPixelToLogic, RowInfo* const pT
 
     if ( bEmpty && !bMergeEmpty && nX == mnX2 && !bOverlapped )
     {
-        //  don't have to look further than nLastContentCol
-
-        SCCOL nTempX=nX;
-        while (nTempX < nLastContentCol && IsEmptyCellText( pThisRowInfo, 
nTempX, nY ))
-            ++nTempX;
+        if (!oLastEmptyCellX)
+        {
+            //  don't have to look further than nLastContentCol
+            SCCOL nTempX=nX;
+            while (nTempX < nLastContentCol && IsEmptyCellText( pThisRowInfo, 
nTempX, nY ))
+                ++nTempX;
+            oLastEmptyCellX = nTempX;
+        }
 
-        if ( nTempX > nX &&
-             !IsEmptyCellText( pThisRowInfo, nTempX, nY ) &&
-             !mpDoc->HasAttrib( nTempX,nY,mnTab, nX,nY,mnTab, 
HasAttrFlags::Merged | HasAttrFlags::Overlapped ) )
+        if ( *oLastEmptyCellX > nX &&
+             !IsEmptyCellText( pThisRowInfo, *oLastEmptyCellX, nY ) &&
+             !mpDoc->HasAttrib( *oLastEmptyCellX, nY,mnTab, nX,nY,mnTab, 
HasAttrFlags::Merged | HasAttrFlags::Overlapped ) )
         {
-            nCellX = nTempX;
+            nCellX = *oLastEmptyCellX;
             bDoCell = true;
         }
     }

Reply via email to