sw/inc/shellio.hxx                             |    6 +++
 sw/qa/extras/tiledrendering/data/numrules.odt  |binary
 sw/qa/extras/tiledrendering/tiledrendering.cxx |   48 +++++++++++++++++++++++++
 sw/source/filter/basflt/shellio.cxx            |    5 ++
 sw/source/uibase/dochdl/swdtflvr.cxx           |   15 +++++++
 5 files changed, 73 insertions(+), 1 deletion(-)

New commits:
commit a90699037b4e2f5f3652c442e68c550236b776d6
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon Jul 15 14:40:24 2024 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Tue Jul 16 13:32:43 2024 +0200

    cool#9504 sw: don't invalidate num rules when pasting into a non-num 
paragraph
    
    The bugdoc has ~300 pages of content, most of that is bullets, but
    otherwise not complex, pasting a trivial string at doc end (which is not
    a bulleted paragraph) takes a noticeable time:
    
    debug:20449:20330: SwLayAction::InternalAction: start
    debug:20449:20330: SwLayAction::InternalAction: end, took 268 ms
    
    Profiling points out that we re-layout the internal document, which is
    not expected: we just pasted on the first page, causing no layout change
    on page 2 and later pages. Watching who turns on m_bInvalidContent on
    the page frames, it can be noticed that SwReader::Read() invalidates all
    numberings after pasting.
    
    Fix the problem by not doing that in case we paste plain text and we
    know the insertion point is not in a numbering: the invalidation is not
    useful in this case and fixes the unexpected delay.
    
    Other related ideas are 1) don't do the layout for all pages in one go
    2) recognize that the bullets need no invalidation, unlike an actual
    numbering with numbers. Neither of these are done in this commit yet.
    
    (cherry picked from commit dc3e022866893d8c0950f2269c0c8d61c24ed9bf)
    
    Conflicts:
            sw/qa/extras/tiledrendering2/tiledrendering2.cxx
    
    Change-Id: Id7b2c022b31acb358f42ddd77195db70ae451109
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170540
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/inc/shellio.hxx b/sw/inc/shellio.hxx
index 5a7c6f2a7635..37db03c6d20c 100644
--- a/sw/inc/shellio.hxx
+++ b/sw/inc/shellio.hxx
@@ -154,6 +154,7 @@ class SW_DLLPUBLIC SwReader: public SwDocFac
     OUString maFileName;
     OUString msBaseURL;
     bool mbSkipImages;
+    bool mbSkipInvalidateNumRules = false;
 
 public:
 
@@ -175,6 +176,11 @@ public:
     bool HasGlossaries( const Reader& );
     bool ReadGlossaries( const Reader&, SwTextBlocks&, bool bSaveRelFiles );
 
+    void SetSkipInvalidateNumRules(bool bSkipInvalidateNumRules)
+    {
+        mbSkipInvalidateNumRules = bSkipInvalidateNumRules;
+    }
+
 protected:
     void                SetBaseURL( const OUString& rURL ) { msBaseURL = rURL; 
}
     void                SetSkipImages( bool bSkipImages ) { mbSkipImages = 
bSkipImages; }
diff --git a/sw/qa/extras/tiledrendering/data/numrules.odt 
b/sw/qa/extras/tiledrendering/data/numrules.odt
new file mode 100644
index 000000000000..8beaba7fd0bd
Binary files /dev/null and b/sw/qa/extras/tiledrendering/data/numrules.odt 
differ
diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx 
b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index b8c46fe404b4..c7d0a61754ec 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -768,6 +768,8 @@ namespace {
         OString m_aViewSelection;
         OString m_aViewRenderState;
         bool m_bTilesInvalidated;
+        tools::Rectangle m_aInvalidations;
+        bool m_bFullInvalidateSeen = false;
         bool m_bViewCursorVisible;
         bool m_bGraphicViewSelection;
         bool m_bGraphicSelection;
@@ -829,6 +831,20 @@ namespace {
                 case LOK_CALLBACK_INVALIDATE_TILES:
                     {
                         m_bTilesInvalidated = true;
+                        if (std::string_view("EMPTY") == pPayload)
+                        {
+                            m_bFullInvalidateSeen = true;
+                            return;
+                        }
+                        uno::Sequence<OUString> aSeq
+                            = 
comphelper::string::convertCommaSeparated(OUString::fromUtf8(pPayload));
+                        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4), 
aSeq.getLength());
+                        tools::Rectangle aInvalidation;
+                        aInvalidation.SetLeft(aSeq[0].toInt32());
+                        aInvalidation.SetTop(aSeq[1].toInt32());
+                        aInvalidation.setWidth(aSeq[2].toInt32());
+                        aInvalidation.setHeight(aSeq[3].toInt32());
+                        m_aInvalidations.Union(aInvalidation);
                     }
                     break;
                 case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR:
@@ -4365,6 +4381,38 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, 
testTdf159626_blackPatternFill)
     CPPUNIT_ASSERT(nPureBlackPixels / 10 > nEdgePlusWhitePlusAntialiasPixels);
 }
 
+CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testPasteInvalidateNumRules)
+{
+    // Given a document with 3 pages: first page is ~empty, then page break, 
then pages 2 & 3 have
+    // bullets:
+    SwXTextDocument* pXTextDocument = createDoc("numrules.odt");
+    CPPUNIT_ASSERT(pXTextDocument);
+    ViewCallback aView;
+    SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell();
+    pWrtShell->SttEndDoc(/*bStt=*/true);
+    pWrtShell->Down(/*bSelect=*/false);
+    pWrtShell->Insert(u"test"_ustr);
+    pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 4, 
/*bBasicCall=*/false);
+    dispatchCommand(mxComponent, u".uno:Cut"_ustr, {});
+    aView.m_aInvalidations = tools::Rectangle();
+    aView.m_bFullInvalidateSeen = false;
+
+    // When pasting at the end of page 1:
+    dispatchCommand(mxComponent, u".uno:PasteUnformatted"_ustr, {});
+
+    // Then make sure we only invalidate page 1, not page 2 or page 3:
+    CPPUNIT_ASSERT(!aView.m_bFullInvalidateSeen);
+    SwRootFrame* pLayout = pWrtShell->GetLayout();
+    SwFrame* pPage1 = pLayout->GetLower();
+    
CPPUNIT_ASSERT(aView.m_aInvalidations.Overlaps(pPage1->getFrameArea().SVRect()));
+    SwFrame* pPage2 = pPage1->GetNext();
+    // Without the accompanying fix in place, this test would have failed, we 
invalidated page 2 and
+    // page 3 as well.
+    
CPPUNIT_ASSERT(!aView.m_aInvalidations.Overlaps(pPage2->getFrameArea().SVRect()));
+    SwFrame* pPage3 = pPage2->GetNext();
+    
CPPUNIT_ASSERT(!aView.m_aInvalidations.Overlaps(pPage3->getFrameArea().SVRect()));
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/basflt/shellio.cxx 
b/sw/source/filter/basflt/shellio.cxx
index 888213aa9d5e..0ead0d6d811a 100644
--- a/sw/source/filter/basflt/shellio.cxx
+++ b/sw/source/filter/basflt/shellio.cxx
@@ -355,7 +355,10 @@ ErrCodeMsg SwReader::Read( const Reader& rOptions )
     mxDoc->SetInXMLImport( false );
     mxDoc->SetInWriterfilterImport(false);
 
-    mxDoc->InvalidateNumRules();
+    if (!mbSkipInvalidateNumRules)
+    {
+        mxDoc->InvalidateNumRules();
+    }
     mxDoc->UpdateNumRule();
     mxDoc->ChkCondColls();
     mxDoc->SetAllUniqueFlyNames();
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx 
b/sw/source/uibase/dochdl/swdtflvr.cxx
index 65f68e27d8c3..f815355987b4 100644
--- a/sw/source/uibase/dochdl/swdtflvr.cxx
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -2157,11 +2157,22 @@ bool SwTransferable::PasteFileContent( const 
TransferableDataHelper& rData,
     SvStream* pStream = nullptr;
     Reader* pRead = nullptr;
     OUString sData;
+    bool bSkipInvalidateNumRules = false;
     switch( nFormat )
     {
     case SotClipboardFormatId::STRING:
         {
             pRead = ReadAscii;
+
+            const SwPosition& rInsertPosition = *rSh.GetCursor()->Start();
+            SwTextNode* pTextNode = rInsertPosition.GetNode().GetTextNode();
+            if (pTextNode && !pTextNode->GetNum())
+            {
+                // Insertion point is not a numbering and we paste plain text: 
then no need to
+                // invalidate all numberings.
+                bSkipInvalidateNumRules = true;
+            }
+
             if( rData.GetString( nFormat, sData ) )
             {
                 pStream = new SvMemoryStream( const_cast<sal_Unicode 
*>(sData.getStr()),
@@ -2221,6 +2232,10 @@ bool SwTransferable::PasteFileContent( const 
TransferableDataHelper& rData,
 
         if (bIgnoreComments)
             pRead->SetIgnoreHTMLComments(true);
+        if (bSkipInvalidateNumRules)
+        {
+            aReader.SetSkipInvalidateNumRules(bSkipInvalidateNumRules);
+        }
 
         if( aReader.Read( *pRead ).IsError() )
             pResId = STR_ERROR_CLPBRD_READ;

Reply via email to