include/svx/svdmodel.hxx             |    8 +++---
 sd/source/filter/pdf/sdpdffilter.cxx |    4 ++-
 svx/source/svdraw/svdmodel.cxx       |   46 ++++++++++++++++++-----------------
 3 files changed, 31 insertions(+), 27 deletions(-)

New commits:
commit ad3fa69eeb89573c77feba64dab3380154a90953
Author:     Noel Grandin <noel.gran...@collabora.co.uk>
AuthorDate: Fri Sep 6 12:55:26 2024 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Fri Sep 6 14:48:17 2024 +0200

    reduce time spent in RecalcPageNums when importing PDF
    
    when we have lots of pages, we trigger a O(n^2) loop.
    
    Do two things to reduce this
    (a) be smarter about recalculating page numbers, so we only recalculate
    the set of page numbers that need recalculating
    (b) duplicate the last page repeatedly, instead of the first page, so we
    don't recalculate all the page numbers for each page we duplicate
    
    Change-Id: I40aca812b47a9551039c5855b1c8d26f5f171f41
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172942
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>
    Tested-by: Jenkins

diff --git a/include/svx/svdmodel.hxx b/include/svx/svdmodel.hxx
index 3da5a865fe13..b0d8bd7b36a5 100644
--- a/include/svx/svdmodel.hxx
+++ b/include/svx/svdmodel.hxx
@@ -199,12 +199,12 @@ protected:
     std::deque<std::unique_ptr<SfxUndoAction>> m_aRedoStack;
     std::unique_ptr<SdrUndoGroup> m_pCurrentUndoGroup;  // For multi-level
     sal_uInt16          m_nUndoLevel;                   // undo nesting
+    sal_uInt16          m_nPageNumsDirtyFrom = SAL_MAX_UINT16;
+    sal_uInt16          m_nMasterPageNumsDirtyFrom = SAL_MAX_UINT16;
     bool                m_bIsWriter:1;        // to clean up pMyPool from 303a
     bool                m_bThemedControls:1;  // If false UnoControls should 
not use theme colors
     bool                mbUndoEnabled:1;  // If false no undo is recorded or 
we are during the execution of an undo action
     bool                mbChanged:1;
-    bool                m_bPagNumsDirty:1;
-    bool                m_bMPgNumsDirty:1;
     bool                m_bTransportContainer:1;  // doc is temporary object 
container, no display (e.g. clipboard)
     bool                m_bReadOnly:1;
     bool                m_bTransparentTextFrames:1;
@@ -397,8 +397,8 @@ public:
     static OUString  GetPercentString(const Fraction& rVal);
 
     // RecalcPageNums is ordinarily only called by the Page.
-    bool             IsPagNumsDirty() const                     { return 
m_bPagNumsDirty; };
-    bool             IsMPgNumsDirty() const                     { return 
m_bMPgNumsDirty; };
+    bool             IsPagNumsDirty() const                     { return 
m_nPageNumsDirtyFrom != SAL_MAX_UINT16; }
+    bool             IsMPgNumsDirty() const                     { return 
m_nMasterPageNumsDirtyFrom != SAL_MAX_UINT16; }
     void             RecalcPageNums(bool bMaster);
     // After the Insert the Page belongs to the SdrModel.
     virtual void     InsertPage(SdrPage* pPage, sal_uInt16 nPos=0xFFFF);
diff --git a/sd/source/filter/pdf/sdpdffilter.cxx 
b/sd/source/filter/pdf/sdpdffilter.cxx
index 22229e6597ce..068aca1fcce9 100644
--- a/sd/source/filter/pdf/sdpdffilter.cxx
+++ b/sd/source/filter/pdf/sdpdffilter.cxx
@@ -65,9 +65,11 @@ bool SdPdfFilter::Import()
 
     // Add as many pages as we need up-front.
     mrDocument.CreateFirstPages();
+    sal_uInt16 nPageToDuplicate = 0;
     for (size_t i = 0; i < aGraphics.size() - 1; ++i)
     {
-        mrDocument.DuplicatePage(0);
+        // duplicating the last page is cheaper than repeatedly duplicating 
the first one
+        nPageToDuplicate = mrDocument.DuplicatePage(nPageToDuplicate);
     }
 
     for (vcl::PDFGraphicResult const& rPDFGraphicResult : aGraphics)
diff --git a/svx/source/svdraw/svdmodel.cxx b/svx/source/svdraw/svdmodel.cxx
index e13f1025430a..45bb96a2177b 100644
--- a/svx/source/svdraw/svdmodel.cxx
+++ b/svx/source/svdraw/svdmodel.cxx
@@ -132,8 +132,6 @@ SdrModel::SdrModel(SfxItemPool* pPool, 
comphelper::IEmbeddedHelper* pEmbeddedHel
     , m_bThemedControls(true)
     , mbUndoEnabled(true)
     , mbChanged(false)
-    , m_bPagNumsDirty(false)
-    , m_bMPgNumsDirty(false)
     , m_bTransportContainer(false)
     , m_bReadOnly(false)
     , m_bTransparentTextFrames(false)
@@ -1175,23 +1173,27 @@ void SdrModel::RecalcPageNums(bool bMaster)
 {
     if(bMaster)
     {
-        sal_uInt16 nCount=sal_uInt16(maMasterPages.size());
-        sal_uInt16 i;
-        for (i=0; i<nCount; i++) {
-            SdrPage* pPg = maMasterPages[i].get();
-            pPg->SetPageNum(i);
+        if (m_nMasterPageNumsDirtyFrom != SAL_MAX_UINT16)
+        {
+            sal_uInt16 nCount=sal_uInt16(maMasterPages.size());
+            for (sal_uInt16 i=m_nMasterPageNumsDirtyFrom; i<nCount; i++) {
+                SdrPage* pPg = maMasterPages[i].get();
+                pPg->SetPageNum(i);
+            }
+            m_nMasterPageNumsDirtyFrom = SAL_MAX_UINT16;
         }
-        m_bMPgNumsDirty=false;
     }
     else
     {
-        sal_uInt16 nCount=sal_uInt16(maPages.size());
-        sal_uInt16 i;
-        for (i=0; i<nCount; i++) {
-            SdrPage* pPg = maPages[i].get();
-            pPg->SetPageNum(i);
+        if (m_nPageNumsDirtyFrom != SAL_MAX_UINT16)
+        {
+            sal_uInt16 nCount=sal_uInt16(maPages.size());
+            for (sal_uInt16 i = m_nPageNumsDirtyFrom; i<nCount; i++) {
+                SdrPage* pPg = maPages[i].get();
+                pPg->SetPageNum(i);
+            }
+            m_nPageNumsDirtyFrom = SAL_MAX_UINT16;
         }
-        m_bPagNumsDirty=false;
     }
 }
 
@@ -1209,7 +1211,7 @@ void SdrModel::InsertPage(SdrPage* pPage, sal_uInt16 nPos)
     if (mbMakePageObjectsNamesUnique)
         pPage->MakePageObjectsNamesUnique();
 
-    if (nPos<nCount) m_bPagNumsDirty=true;
+    if (nPos<nCount) m_nPageNumsDirtyFrom = std::min(m_nPageNumsDirtyFrom, 
static_cast<sal_uInt16>(nPos + 1));
     SetChanged();
     SdrHint aHint(SdrHintKind::PageOrderChange, pPage);
     Broadcast(aHint);
@@ -1228,7 +1230,7 @@ rtl::Reference<SdrPage> SdrModel::RemovePage(sal_uInt16 
nPgNum)
     if (pPg) {
         pPg->SetInserted(false);
     }
-    m_bPagNumsDirty=true;
+    m_nPageNumsDirtyFrom = std::min(m_nPageNumsDirtyFrom, nPgNum);
     SetChanged();
     SdrHint aHint(SdrHintKind::PageOrderChange, pPg.get());
     Broadcast(aHint);
@@ -1258,7 +1260,7 @@ void SdrModel::InsertMasterPage(SdrPage* pPage, 
sal_uInt16 nPos)
     pPage->SetPageNum(nPos);
 
     if (nPos<nCount) {
-        m_bMPgNumsDirty=true;
+        m_nMasterPageNumsDirtyFrom = std::min(m_nMasterPageNumsDirtyFrom, 
static_cast<sal_uInt16>(nPos + 1));
     }
 
     SetChanged();
@@ -1290,7 +1292,7 @@ rtl::Reference<SdrPage> 
SdrModel::RemoveMasterPage(sal_uInt16 nPgNum)
         pRetPg->SetInserted(false);
     }
 
-    m_bMPgNumsDirty=true;
+    m_nMasterPageNumsDirtyFrom = std::min(m_nMasterPageNumsDirtyFrom, nPgNum);
     SetChanged();
     SdrHint aHint(SdrHintKind::PageOrderChange, pRetPg.get());
     Broadcast(aHint);
@@ -1307,7 +1309,7 @@ void SdrModel::MoveMasterPage(sal_uInt16 nPgNum, 
sal_uInt16 nNewPos)
         maMasterPages.insert(maMasterPages.begin()+nNewPos,pPg);
         MasterPageListChanged();
     }
-    m_bMPgNumsDirty=true;
+    m_nMasterPageNumsDirtyFrom = std::min(m_nMasterPageNumsDirtyFrom, 
std::min(nPgNum, nNewPos));
     SetChanged();
     SdrHint aHint(SdrHintKind::PageOrderChange, pPg.get());
     Broadcast(aHint);
@@ -1483,7 +1485,7 @@ void SdrModel::Merge(SdrModel& rSourceModel,
                     
maMasterPages.insert(maMasterPages.begin()+nDstMasterPageCnt, pPg);
                     MasterPageListChanged();
                     pPg->SetInserted();
-                    m_bMPgNumsDirty=true;
+                    m_nMasterPageNumsDirtyFrom = 
std::min(m_nMasterPageNumsDirtyFrom, nDstMasterPageCnt);
                     if (bUndo) 
AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg));
                 } else {
                     OSL_FAIL("SdrModel::Merge(): MasterPage not found in 
SourceModel.");
@@ -1566,8 +1568,8 @@ void SdrModel::Merge(SdrModel& rSourceModel,
     pMasterMap.reset();
     pMasterNeed.reset();
 
-    m_bMPgNumsDirty=true;
-    m_bPagNumsDirty=true;
+    m_nMasterPageNumsDirtyFrom = 0;
+    m_nPageNumsDirtyFrom = 0;
 
     SetChanged();
     // TODO: Missing: merging and mapping of layers

Reply via email to