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();
 }

Reply via email to