vcl/source/gdi/impgraph.cxx    |   12 ++++++++++++
 vcl/source/graphic/Manager.cxx |   23 ++++++++++++++++-------
 2 files changed, 28 insertions(+), 7 deletions(-)

New commits:
commit 4bbef581d68b391a4de57cc36c85775635f324d6
Author:     Patrick Luby <guibmac...@gmail.com>
AuthorDate: Sun Jul 13 19:48:44 2025 -0400
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Thu Jul 24 07:39:18 2025 +0200

    tdf#167007 Add animated graphic to cache when prepared
    
    For some reason, after an animation has been swapped out by
    MemoryManager::loopAndReduceMemory(), the animation repeatedly
    creates a new ImpGraphic instance, swaps it in, but it never
    gets registered in the cache. Since it is not in the cache, new
    ImpGraphic instances get deleted almost immediately after they
    are created.
    
    So prevent immediate deletion by ensuring that animated
    ImpGraphic instances are registered when they are prepared.
    
    Change-Id: Ib721e0bc31d3eddc4ed4131d9d8dc8919eed7b44
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187836
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>
    Tested-by: Jenkins
    (cherry picked from commit eed9c590db8e94ddc5cc20bc25a779284c9b9249)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188234
    Reviewed-by: Patrick Luby <guibomac...@gmail.com>

diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index 2f54037e7b09..a6afc521b72a 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -446,6 +446,18 @@ void ImpGraphic::setPrepared(bool bAnimated, const Size* 
pSizeHint)
 
     if (maVectorGraphicData)
         maSwapInfo.mnPageIndex = maVectorGraphicData->getPageIndex();
+
+    // tdf#167007 Add animated graphic to cache when prepared
+    // For some reason, after an animation has been swapped out by
+    // MemoryManager::loopAndReduceMemory(), the animation repeatedly
+    // creates a new ImpGraphic instance, swaps it in, but it never
+    // gets registered in the cache. Since it is not in the cache, new
+    // ImpGraphic instances get deleted almost immediately after they
+    // are created.
+    // So prevent immediate deletion by ensuring that animated
+    // ImpGraphic instances are registered when they are prepared.
+    if (maSwapInfo.mbIsAnimated)
+        registerIntoManager();
 }
 
 void ImpGraphic::clear()
diff --git a/vcl/source/graphic/Manager.cxx b/vcl/source/graphic/Manager.cxx
index 17f25cedec7c..28fd1e00d4c1 100644
--- a/vcl/source/graphic/Manager.cxx
+++ b/vcl/source/graphic/Manager.cxx
@@ -86,25 +86,34 @@ void MemoryManager::registerObject(MemoryManaged* 
pMemoryManaged)
     // Insert and update the used size (bytes)
     assert(aGuard.owns_lock() && aGuard.mutex() == &maMutex);
     // coverity[missing_lock: FALSE] - as above assert
-    mnTotalSize += pMemoryManaged->getCurrentSizeInBytes();
-    maObjectList.insert(pMemoryManaged);
+    // Related: tdf#167007 Only add object bytes if the object is
+    // actually inserted into the cache
+    if (maObjectList.insert(pMemoryManaged).second)
+        mnTotalSize += pMemoryManaged->getCurrentSizeInBytes();
     checkStartReduceTimer();
 }
 
 void MemoryManager::unregisterObject(MemoryManaged* pMemoryManaged)
 {
     std::unique_lock aGuard(maMutex);
-    mnTotalSize -= pMemoryManaged->getCurrentSizeInBytes();
-    maObjectList.erase(pMemoryManaged);
+    // Related: tdf#167007 Only remove object size if the object is
+    // actually removed from the cache
+    if (maObjectList.erase(pMemoryManaged))
+        mnTotalSize -= pMemoryManaged->getCurrentSizeInBytes();
     checkStartReduceTimer();
 }
 
 void MemoryManager::changeExisting(MemoryManaged* pMemoryManaged, sal_Int64 
nNewSize)
 {
     std::scoped_lock aGuard(maMutex);
-    sal_Int64 nOldSize = pMemoryManaged->getCurrentSizeInBytes();
-    mnTotalSize -= nOldSize;
-    mnTotalSize += nNewSize;
+    // Related: tdf#167007 Only change total cache bytes if the object
+    // actually exists in the cache
+    if (maObjectList.find(pMemoryManaged) != maObjectList.end())
+    {
+        sal_Int64 nOldSize = pMemoryManaged->getCurrentSizeInBytes();
+        mnTotalSize -= nOldSize;
+        mnTotalSize += nNewSize;
+    }
     pMemoryManaged->setCurrentSizeInBytes(nNewSize);
     checkStartReduceTimer();
 }

Reply via email to