svx/source/inc/StylesPreviewWindow.hxx | 7 ++-- svx/source/tbxctrls/StylesPreviewWindow.cxx | 43 ++++++++++++++++++---------- 2 files changed, 32 insertions(+), 18 deletions(-)
New commits: commit 7359e9c742d35c999eb9add524052887805e7b26 Author: Noel Grandin <noelgran...@gmail.com> AuthorDate: Wed Jun 11 12:35:14 2025 +0200 Commit: Noel Grandin <noelgran...@gmail.com> CommitDate: Wed Jun 11 16:03:34 2025 +0200 tdf#166932 avoid O(n^2) loop in UpdateStylesList Change-Id: I930ec5ae4229509a98d28bd7afe7124d29c827b4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186366 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/svx/source/inc/StylesPreviewWindow.hxx b/svx/source/inc/StylesPreviewWindow.hxx index 0cbee0c31747..ced475e323af 100644 --- a/svx/source/inc/StylesPreviewWindow.hxx +++ b/svx/source/inc/StylesPreviewWindow.hxx @@ -64,10 +64,10 @@ class StyleItemController public: StyleItemController(std::pair<OUString, OUString> aStyleName); - void Paint(vcl::RenderContext& rRenderContext); + void Paint(vcl::RenderContext& rRenderContext, SfxStyleSheetBase* pStyleHint = nullptr); private: - void DrawEntry(vcl::RenderContext& rRenderContext); + void DrawEntry(vcl::RenderContext& rRenderContext, SfxStyleSheetBase* pStyleHint); void DrawText(vcl::RenderContext& rRenderContext); void DrawHighlight(vcl::RenderContext& rRenderContext, Color aFontBack); static void DrawContentBackground(vcl::RenderContext& rRenderContext, @@ -123,7 +123,8 @@ public: void Select(const OUString& rStyleName); void RequestStylesListUpdate(); - static BitmapEx GetCachedPreview(const std::pair<OUString, OUString>& rStyle); + static BitmapEx GetCachedPreview(const std::pair<OUString, OUString>& rStyle, + SfxStyleSheetBase* pStyleHint = nullptr); static OString GetCachedPreviewJson(const std::pair<OUString, OUString>& rStyle); private: diff --git a/svx/source/tbxctrls/StylesPreviewWindow.cxx b/svx/source/tbxctrls/StylesPreviewWindow.cxx index f3684c13c743..c89ef040ee07 100644 --- a/svx/source/tbxctrls/StylesPreviewWindow.cxx +++ b/svx/source/tbxctrls/StylesPreviewWindow.cxx @@ -180,12 +180,12 @@ StyleItemController::StyleItemController(std::pair<OUString, OUString> aStyleNam { } -void StyleItemController::Paint(vcl::RenderContext& rRenderContext) +void StyleItemController::Paint(vcl::RenderContext& rRenderContext, SfxStyleSheetBase* pStyleHint) { rRenderContext.Push(vcl::PushFlags::FILLCOLOR | vcl::PushFlags::FONT | vcl::PushFlags::TEXTCOLOR); - DrawEntry(rRenderContext); + DrawEntry(rRenderContext, pStyleHint); rRenderContext.Pop(); } @@ -304,25 +304,28 @@ static SvxFont GetFontFromItems(const SvxFontItem* pFontItem, Size aPixelFontSiz return aFont; } -void StyleItemController::DrawEntry(vcl::RenderContext& rRenderContext) +void StyleItemController::DrawEntry(vcl::RenderContext& rRenderContext, + SfxStyleSheetBase* pStyleHint) { SfxObjectShell* pShell = SfxObjectShell::Current(); if (!pShell) return; SfxStyleSheetBasePool* pPool = pShell->GetStyleSheetPool(); - SfxStyleSheetBase* pStyle = nullptr; - if (!pPool) return; - pStyle = pPool->First(m_eStyleFamily); - while (pStyle && pStyle->GetName() != m_aStyleName.first - && pStyle->GetName() != m_aStyleName.second) - pStyle = pPool->Next(); - - if (!pStyle) - return; + SfxStyleSheetBase* pStyle = nullptr; + if (pStyleHint) + pStyle = pStyleHint; + { + pStyle = pPool->First(m_eStyleFamily); + while (pStyle && pStyle->GetName() != m_aStyleName.first + && pStyle->GetName() != m_aStyleName.second) + pStyle = pPool->Next(); + if (!pStyle) + return; + } Size aSize(rRenderContext.GetOutputSizePixel()); tools::Rectangle aFullRect(Point(0, 0), aSize); @@ -577,7 +580,8 @@ IMPL_LINK(StylesPreviewWindow_Base, GetPreviewImage, const weld::encoded_image_q return true; } -BitmapEx StylesPreviewWindow_Base::GetCachedPreview(const std::pair<OUString, OUString>& rStyle) +BitmapEx StylesPreviewWindow_Base::GetCachedPreview(const std::pair<OUString, OUString>& rStyle, + SfxStyleSheetBase* pStyleHint) { auto aFound = StylePreviewCache::Get().find(rStyle.second); if (aFound != StylePreviewCache::Get().end()) @@ -589,7 +593,7 @@ BitmapEx StylesPreviewWindow_Base::GetCachedPreview(const std::pair<OUString, OU pImg->SetOutputSizePixel(aSize); StyleItemController aStyleController(rStyle); - aStyleController.Paint(*pImg); + aStyleController.Paint(*pImg, pStyleHint); BitmapEx aBitmap = pImg->GetBitmapEx(Point(0, 0), aSize); StylePreviewCache::Get()[rStyle.second] = aBitmap; @@ -615,6 +619,8 @@ void StylesPreviewWindow_Base::UpdateStylesList() SfxObjectShell* pDocShell = SfxObjectShell::Current(); SfxStyleSheetBasePool* pStyleSheetPool = nullptr; + // avoid O(n^2) loop when filling a very large style list + std::map<sal_Int32, SfxStyleSheetBase*> aStylesHint; if (pDocShell) pStyleSheetPool = pDocShell->GetStyleSheetPool(); @@ -629,6 +635,7 @@ void StylesPreviewWindow_Base::UpdateStylesList() while (pStyle) { OUString sName(pStyle->GetName()); + aStylesHint[m_aAllStyles.size()] = pStyle; m_aAllStyles.push_back(std::pair<OUString, OUString>(sName, sName)); pStyle = xIter->Next(); } @@ -639,15 +646,21 @@ void StylesPreviewWindow_Base::UpdateStylesList() // for online we can skip inserting the preview into the IconView and rely // on DoJsonProperty to provide the image to clients const bool bNeedInsertPreview = !comphelper::LibreOfficeKit::isActive(); + sal_Int32 nIndex = 0; for (const auto& rStyle : m_aAllStyles) { if (bNeedInsertPreview) { - BitmapEx aPreview = GetCachedPreview(rStyle); + SfxStyleSheetBase* pStyleHint = nullptr; + auto it = aStylesHint.find(nIndex); + if (it != aStylesHint.end()) + pStyleHint = it->second; + BitmapEx aPreview = GetCachedPreview(rStyle, pStyleHint); m_xStylesView->append(rStyle.first, rStyle.second, &aPreview); } else m_xStylesView->append(rStyle.first, rStyle.second, nullptr); + ++nIndex; } m_xStylesView->thaw(); }