comphelper/source/misc/lok.cxx | 15 +++++++++++++ desktop/source/lib/init.cxx | 15 +++++++++++++ include/comphelper/lok.hxx | 8 +++++++ sw/qa/extras/tiledrendering/data/3pages.odt |binary sw/qa/extras/tiledrendering/tiledrendering2.cxx | 26 ++++++++++++++++++++++++ sw/source/core/view/vnew.cxx | 9 ++++++++ 6 files changed, 73 insertions(+)
New commits: commit 5300efbbb13c73d7d5d17cd9834f9cb118657915 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Feb 7 14:09:22 2025 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue Feb 11 16:48:27 2025 +0100 cool#11064 sw lok: allow specifying the visible area during doc load Large enough documents significantly faster on the desktop than in LOK mode for some reason. Investigating the reason, it turns out that the layout mechanism to layout the visible area (first page, typically) of the document as part of doc load goes wrong in the LOK case, where nominally the entire document is visible. Fix the problem by adding new "ClientVisibleArea" option to lo_documentLoadWithOptions(), so the LOK client can inform us about what is the visible area before SwXTextDocument::setClientVisibleArea() can be called. lok::Office::documentLoad() cost for the bugdoc: - before: 540 ms - after: 112 ms Change-Id: Ib1df71e768fc42cf92b858a717d7a0e5d51678b6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181426 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/comphelper/source/misc/lok.cxx b/comphelper/source/misc/lok.cxx index b3ac3ce79420..7d4ca7536b4b 100644 --- a/comphelper/source/misc/lok.cxx +++ b/comphelper/source/misc/lok.cxx @@ -8,12 +8,17 @@ */ #include <comphelper/lok.hxx> + +#include <com/sun/star/awt/Rectangle.hpp> + #include <osl/process.h> #include <i18nlangtag/languagetag.hxx> #include <sal/log.hxx> #include <iostream> +using namespace com::sun::star; + namespace comphelper::LibreOfficeKit { @@ -43,6 +48,9 @@ static void* g_pAnyInputCallbackData; static std::function<void(int)> g_pViewSetter; static std::function<int()> g_pViewGetter; +/// Visible area of the first view during document load. +static awt::Rectangle g_aInitialClientVisibleArea; + namespace { @@ -370,6 +378,13 @@ int getView() return g_pViewGetter(); } +void setInitialClientVisibleArea(const awt::Rectangle& rClientVisibleArea) +{ + g_aInitialClientVisibleArea = rClientVisibleArea; +} + +awt::Rectangle getInitialClientVisibleArea() { return g_aInitialClientVisibleArea; } + } // namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index ea70d1f186b2..4e9977d27418 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -2880,6 +2880,21 @@ static LibreOfficeKitDocument* lo_documentLoadWithOptions(LibreOfficeKit* pThis, } SvtSecurityOptions::SetMacroSecurityLevel(nMacroSecurityLevel); + OUString aClientVisibleArea = extractParameter(aOptions, u"ClientVisibleArea"); + if (!aClientVisibleArea.isEmpty()) + { + std::vector<OUString> aTokens = comphelper::string::split(aClientVisibleArea, ';'); + if (aTokens.size() >= 4) + { + awt::Rectangle aRectangle; + aRectangle.X = aTokens[0].toInt32(); + aRectangle.Y = aTokens[1].toInt32(); + aRectangle.Width = aTokens[2].toInt32(); + aRectangle.Height = aTokens[3].toInt32(); + comphelper::LibreOfficeKit::setInitialClientVisibleArea(aRectangle); + } + } + #if defined(ANDROID) && HAVE_FEATURE_ANDROID_LOK sal_Int16 nMacroExecMode = document::MacroExecMode::USE_CONFIG; #else diff --git a/include/comphelper/lok.hxx b/include/comphelper/lok.hxx index 0dd5fbdb2f23..e222690c7e30 100644 --- a/include/comphelper/lok.hxx +++ b/include/comphelper/lok.hxx @@ -16,6 +16,10 @@ #include <rtl/ustring.hxx> class LanguageTag; +namespace com::sun::star::awt +{ +struct Rectangle; +} // Interface between the LibreOfficeKit implementation called by LibreOfficeKit clients and other // LibreOffice code. @@ -144,6 +148,10 @@ COMPHELPER_DLLPUBLIC void setViewSetter(const std::function<void(int)>& pViewSet COMPHELPER_DLLPUBLIC void setView(int nView); COMPHELPER_DLLPUBLIC void setViewGetter(const std::function<int()>& pViewGetter); COMPHELPER_DLLPUBLIC int getView(); + +COMPHELPER_DLLPUBLIC void +setInitialClientVisibleArea(const css::awt::Rectangle& rClientVisibleArea); +COMPHELPER_DLLPUBLIC css::awt::Rectangle getInitialClientVisibleArea(); } #endif // INCLUDED_COMPHELPER_LOK_HXX diff --git a/sw/qa/extras/tiledrendering/data/3pages.odt b/sw/qa/extras/tiledrendering/data/3pages.odt new file mode 100644 index 000000000000..565cdeae77a5 Binary files /dev/null and b/sw/qa/extras/tiledrendering/data/3pages.odt differ diff --git a/sw/qa/extras/tiledrendering/tiledrendering2.cxx b/sw/qa/extras/tiledrendering/tiledrendering2.cxx index 5464257a388c..93b08546a731 100644 --- a/sw/qa/extras/tiledrendering/tiledrendering2.cxx +++ b/sw/qa/extras/tiledrendering/tiledrendering2.cxx @@ -22,6 +22,7 @@ #include <comphelper/dispatchcommand.hxx> #include <sfx2/lokhelper.hxx> #include <comphelper/lok.hxx> +#include <comphelper/scopeguard.hxx> #include <unotxdoc.hxx> #include <view.hxx> @@ -324,6 +325,31 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testPDFExportViewSwitch) CPPUNIT_ASSERT(aView1.m_aExportFile.isEmpty()); CPPUNIT_ASSERT(!aView2.m_aExportFile.isEmpty()); } + +CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testLoadVisibleArea) +{ + // Given a document with 3 pages, the LOK visible area at load time is set to the first page: + awt::Rectangle aVisibleArea{ 0, 0, 12240, 15840 }; + comphelper::LibreOfficeKit::setInitialClientVisibleArea(aVisibleArea); + comphelper::ScopeGuard g([] { comphelper::LibreOfficeKit::setInitialClientVisibleArea({}); }); + + // When loading that document: + OUString aURL = createFileURL(u"3pages.odt"); + UnoApiXmlTest::loadFromURL(aURL); + + // Then make sure only the first page is laid out: + SwDocShell* pDocShell = getSwDocShell(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + SwRootFrame* pLayout = pWrtShell->GetLayout(); + SwPageFrame* pPage1 = pLayout->GetLower()->DynCastPageFrame(); + CPPUNIT_ASSERT(!pPage1->IsInvalidContent()); + SwPageFrame* pPage2 = pPage1->GetNext()->DynCastPageFrame(); + // Without the accompanying fix in place, this test failed, as the entire document was laid out + // before the loading finished. + CPPUNIT_ASSERT(pPage2->IsInvalidContent()); + SwPageFrame* pPage3 = pPage2->GetNext()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage3->IsInvalidContent()); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/core/view/vnew.cxx b/sw/source/core/view/vnew.cxx index 2a40c099a393..d3e2c2a4d626 100644 --- a/sw/source/core/view/vnew.cxx +++ b/sw/source/core/view/vnew.cxx @@ -20,6 +20,7 @@ #include <sfx2/printer.hxx> #include <sal/log.hxx> #include <osl/diagnose.h> +#include <comphelper/lok.hxx> #include <doc.hxx> #include <IDocumentDrawModelAccess.hxx> #include <IDocumentUndoRedo.hxx> @@ -137,6 +138,14 @@ void SwViewShell::Init( const SwViewOption *pNewOpt ) MakeDrawView(); mpOpt->SetFormView( ! GetDrawView()->IsDesignMode() ); } + + awt::Rectangle aClientVisibleArea = comphelper::LibreOfficeKit::getInitialClientVisibleArea(); + if (aClientVisibleArea.Width && aClientVisibleArea.Height) + { + maLOKVisibleArea + = tools::Rectangle(Point(aClientVisibleArea.X, aClientVisibleArea.Y), + Size(aClientVisibleArea.Width, aClientVisibleArea.Height)); + } } /// CTor for the first Shell.