vcl/source/gdi/impgraph.cxx | 12 ++++++++++++ vcl/source/graphic/Manager.cxx | 23 ++++++++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-)
New commits: commit eed9c590db8e94ddc5cc20bc25a779284c9b9249 Author: Patrick Luby <guibmac...@gmail.com> AuthorDate: Sun Jul 13 19:48:44 2025 -0400 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Tue Jul 22 15:23:38 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 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 bafa2711cbff..fddfb842a5ca 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(); }