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;