android: Update app-specific/MIME type icons
[LibreOffice.git] / vcl / source / graphic / Manager.cxx
blobf77e3e3c4041f57229a853802a0e9e59a191bd71
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <graphic/Manager.hxx>
21 #include <impgraph.hxx>
22 #include <sal/log.hxx>
24 #include <officecfg/Office/Common.hxx>
25 #include <unotools/configmgr.hxx>
27 using namespace css;
29 namespace vcl::graphic
31 namespace
33 void setupConfigurationValuesIfPossible(sal_Int64& rMemoryLimit,
34 std::chrono::seconds& rAllowedIdleTime, bool& bSwapEnabled)
36 if (utl::ConfigManager::IsFuzzing())
37 return;
39 try
41 using officecfg::Office::Common::Cache;
43 rMemoryLimit = Cache::GraphicManager::GraphicMemoryLimit::get();
44 rAllowedIdleTime
45 = std::chrono::seconds(Cache::GraphicManager::GraphicAllowedIdleTime::get());
46 bSwapEnabled = Cache::GraphicManager::GraphicSwappingEnabled::get();
48 catch (...)
54 Manager& Manager::get()
56 static Manager gStaticManager;
57 return gStaticManager;
60 Manager::Manager()
61 : mnAllowedIdleTime(10)
62 , mbSwapEnabled(true)
63 , mbReducingGraphicMemory(false)
64 , mnMemoryLimit(300000000)
65 , mnUsedSize(0)
66 , maSwapOutTimer("graphic::Manager maSwapOutTimer")
68 setupConfigurationValuesIfPossible(mnMemoryLimit, mnAllowedIdleTime, mbSwapEnabled);
70 if (mbSwapEnabled)
72 maSwapOutTimer.SetInvokeHandler(LINK(this, Manager, SwapOutTimerHandler));
73 maSwapOutTimer.SetTimeout(10000);
74 maSwapOutTimer.Start();
78 void Manager::loopGraphicsAndSwapOut(std::unique_lock<std::mutex>& rGuard, bool bDropAll)
80 // make a copy of m_pImpGraphicList because if we swap out a svg, the svg
81 // filter may create more temp Graphics which are auto-added to
82 // m_pImpGraphicList invalidating a loop over m_pImpGraphicList, e.g.
83 // reexport of tdf118346-1.odg
84 o3tl::sorted_vector<ImpGraphic*> aImpGraphicList = m_pImpGraphicList;
86 for (ImpGraphic* pEachImpGraphic : aImpGraphicList)
88 if (mnUsedSize < sal_Int64(mnMemoryLimit * 0.7) && !bDropAll)
89 return;
91 if (pEachImpGraphic->isSwappedOut())
92 continue;
94 sal_Int64 nCurrentGraphicSize = getGraphicSizeBytes(pEachImpGraphic);
95 if (nCurrentGraphicSize > 100000 || bDropAll)
97 if (!pEachImpGraphic->mpContext)
99 auto aCurrent = std::chrono::high_resolution_clock::now();
100 auto aDeltaTime = aCurrent - pEachImpGraphic->maLastUsed;
101 auto aSeconds = std::chrono::duration_cast<std::chrono::seconds>(aDeltaTime);
103 if (aSeconds > mnAllowedIdleTime)
105 // unlock because svgio can call back into us
106 rGuard.unlock();
107 pEachImpGraphic->swapOut();
108 rGuard.lock();
115 void Manager::reduceGraphicMemory(std::unique_lock<std::mutex>& rGuard, bool bDropAll)
117 // maMutex is locked in callers
119 if (!mbSwapEnabled)
120 return;
122 if (mnUsedSize < mnMemoryLimit && !bDropAll)
123 return;
125 // avoid recursive reduceGraphicMemory on reexport of tdf118346-1.odg to odg
126 if (mbReducingGraphicMemory)
127 return;
129 mbReducingGraphicMemory = true;
131 loopGraphicsAndSwapOut(rGuard, bDropAll);
133 sal_Int64 calculatedSize = 0;
134 for (ImpGraphic* pEachImpGraphic : m_pImpGraphicList)
136 if (!pEachImpGraphic->isSwappedOut())
138 calculatedSize += getGraphicSizeBytes(pEachImpGraphic);
142 if (calculatedSize != mnUsedSize)
144 assert(rGuard.owns_lock() && rGuard.mutex() == &maMutex);
145 // coverity[missing_lock: FALSE] - as above assert
146 mnUsedSize = calculatedSize;
149 mbReducingGraphicMemory = false;
152 void Manager::dropCache()
154 std::unique_lock aGuard(maMutex);
156 reduceGraphicMemory(aGuard, true);
159 void Manager::dumpState(rtl::OStringBuffer& rState)
161 std::unique_lock aGuard(maMutex);
163 rState.append("\nImage Manager items:\t");
164 rState.append(static_cast<sal_Int32>(m_pImpGraphicList.size()));
165 rState.append("\tsize:\t");
166 rState.append(static_cast<sal_Int64>(mnUsedSize / 1024));
167 rState.append("\tkb");
169 for (ImpGraphic* pEachImpGraphic : m_pImpGraphicList)
171 pEachImpGraphic->dumpState(rState);
175 sal_Int64 Manager::getGraphicSizeBytes(const ImpGraphic* pImpGraphic)
177 if (!pImpGraphic->isAvailable())
178 return 0;
179 return pImpGraphic->getSizeBytes();
182 IMPL_LINK(Manager, SwapOutTimerHandler, Timer*, pTimer, void)
184 std::unique_lock aGuard(maMutex);
186 pTimer->Stop();
187 reduceGraphicMemory(aGuard);
188 pTimer->Start();
191 void Manager::registerGraphic(const std::shared_ptr<ImpGraphic>& pImpGraphic)
193 std::unique_lock aGuard(maMutex);
195 // make some space first
196 if (mnUsedSize > mnMemoryLimit)
197 reduceGraphicMemory(aGuard);
199 // Insert and update the used size (bytes)
200 assert(aGuard.owns_lock() && aGuard.mutex() == &maMutex);
201 // coverity[missing_lock: FALSE] - as above assert
202 mnUsedSize += getGraphicSizeBytes(pImpGraphic.get());
203 m_pImpGraphicList.insert(pImpGraphic.get());
205 // calculate size of the graphic set
206 sal_Int64 calculatedSize = 0;
207 for (ImpGraphic* pEachImpGraphic : m_pImpGraphicList)
209 if (!pEachImpGraphic->isSwappedOut())
211 calculatedSize += getGraphicSizeBytes(pEachImpGraphic);
215 if (calculatedSize != mnUsedSize)
217 SAL_INFO_IF(calculatedSize != mnUsedSize, "vcl.gdi",
218 "Calculated size mismatch. Variable size is '"
219 << mnUsedSize << "' but calculated size is '" << calculatedSize << "'");
220 mnUsedSize = calculatedSize;
224 void Manager::unregisterGraphic(ImpGraphic* pImpGraphic)
226 std::scoped_lock aGuard(maMutex);
228 mnUsedSize -= getGraphicSizeBytes(pImpGraphic);
229 m_pImpGraphicList.erase(pImpGraphic);
232 std::shared_ptr<ImpGraphic> Manager::copy(std::shared_ptr<ImpGraphic> const& rImpGraphicPtr)
234 auto pReturn = std::make_shared<ImpGraphic>(*rImpGraphicPtr);
235 registerGraphic(pReturn);
236 return pReturn;
239 std::shared_ptr<ImpGraphic> Manager::newInstance()
241 auto pReturn = std::make_shared<ImpGraphic>();
242 registerGraphic(pReturn);
243 return pReturn;
246 std::shared_ptr<ImpGraphic> Manager::newInstance(std::shared_ptr<GfxLink> const& rGfxLink,
247 sal_Int32 nPageIndex)
249 auto pReturn = std::make_shared<ImpGraphic>(rGfxLink, nPageIndex);
250 registerGraphic(pReturn);
251 return pReturn;
254 std::shared_ptr<ImpGraphic> Manager::newInstance(const BitmapEx& rBitmapEx)
256 auto pReturn = std::make_shared<ImpGraphic>(rBitmapEx);
257 registerGraphic(pReturn);
258 return pReturn;
261 std::shared_ptr<ImpGraphic> Manager::newInstance(const Animation& rAnimation)
263 auto pReturn = std::make_shared<ImpGraphic>(rAnimation);
264 registerGraphic(pReturn);
265 return pReturn;
268 std::shared_ptr<ImpGraphic>
269 Manager::newInstance(const std::shared_ptr<VectorGraphicData>& rVectorGraphicDataPtr)
271 auto pReturn = std::make_shared<ImpGraphic>(rVectorGraphicDataPtr);
272 registerGraphic(pReturn);
273 return pReturn;
276 std::shared_ptr<ImpGraphic> Manager::newInstance(const GDIMetaFile& rMetaFile)
278 auto pReturn = std::make_shared<ImpGraphic>(rMetaFile);
279 registerGraphic(pReturn);
280 return pReturn;
283 std::shared_ptr<ImpGraphic> Manager::newInstance(const GraphicExternalLink& rGraphicLink)
285 auto pReturn = std::make_shared<ImpGraphic>(rGraphicLink);
286 registerGraphic(pReturn);
287 return pReturn;
290 void Manager::swappedIn(const ImpGraphic* pImpGraphic, sal_Int64 nSizeBytes)
292 std::scoped_lock aGuard(maMutex);
293 if (pImpGraphic)
295 mnUsedSize += nSizeBytes;
299 void Manager::swappedOut(const ImpGraphic* pImpGraphic, sal_Int64 nSizeBytes)
301 std::scoped_lock aGuard(maMutex);
302 if (pImpGraphic)
304 mnUsedSize -= nSizeBytes;
308 void Manager::changeExisting(const ImpGraphic* pImpGraphic, sal_Int64 nOldSizeBytes)
310 std::scoped_lock aGuard(maMutex);
312 mnUsedSize -= nOldSizeBytes;
313 mnUsedSize += getGraphicSizeBytes(pImpGraphic);
315 } // end vcl::graphic
317 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */