diff options
-rw-r--r-- | compilerplugins/clang/badstatics.cxx | 1 | ||||
-rw-r--r-- | vcl/Library_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/inc/graphic/Manager.hxx | 71 | ||||
-rw-r--r-- | vcl/inc/impgraph.hxx | 27 | ||||
-rw-r--r-- | vcl/source/gdi/graph.cxx | 26 | ||||
-rw-r--r-- | vcl/source/gdi/impgraph.cxx | 76 | ||||
-rw-r--r-- | vcl/source/graphic/Manager.cxx | 200 |
7 files changed, 371 insertions, 31 deletions
diff --git a/compilerplugins/clang/badstatics.cxx b/compilerplugins/clang/badstatics.cxx index 697a50c8f9b0..d91f3b430a30 100644 --- a/compilerplugins/clang/badstatics.cxx +++ b/compilerplugins/clang/badstatics.cxx @@ -199,6 +199,7 @@ public: || (loplugin::DeclCheck(pVarDecl).Var("aAllListeners") .Class("ScAddInListener").GlobalNamespace()) // not owning || name == "s_pLOKWindowsMap" // LOK only, guarded by assert, and LOK never tries to perform a VCL cleanup + || name == "gStaticManager" // vcl/source/graphic/Manager.cxx - stores non-owning pointers ) // these variables appear unproblematic { return true; diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index b6212ba959a4..c854e94bad45 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -305,6 +305,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/source/graphic/GraphicObject \ vcl/source/graphic/GraphicObject2 \ vcl/source/graphic/grfattr \ + vcl/source/graphic/Manager \ vcl/source/graphic/UnoGraphic \ vcl/source/graphic/UnoGraphicDescriptor \ vcl/source/graphic/UnoGraphicObject \ diff --git a/vcl/inc/graphic/Manager.hxx b/vcl/inc/graphic/Manager.hxx new file mode 100644 index 000000000000..ec3761534493 --- /dev/null +++ b/vcl/inc/graphic/Manager.hxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_VCL_INC_GRAPHIC_MANAGER_HXX +#define INCLUDED_VCL_INC_GRAPHIC_MANAGER_HXX + +#include <sal/types.h> +#include <rtl/ustring.hxx> +#include <vcl/bitmapex.hxx> +#include <vcl/animate.hxx> +#include <vcl/vectorgraphicdata.hxx> +#include <vcl/metaact.hxx> +#include <vcl/timer.hxx> + +#include <officecfg/Office/Common.hxx> +#include <unotools/configmgr.hxx> + +#include <memory> +#include <chrono> +#include <unordered_set> + +class ImpGraphic; + +namespace vcl +{ +namespace graphic +{ +class Manager final +{ +private: + std::unordered_set<ImpGraphic*> m_pImpGraphicList; + sal_Int64 mnTotalCacheSize; + sal_Int64 mnUsedSize; + Timer maSwapOutTimer; + + Manager(); + + void registerGraphic(std::shared_ptr<ImpGraphic>& rImpGraphic, OUString const& rsContext); + + DECL_LINK(SwapOutTimerHandler, Timer*, void); + +public: + static Manager& get(); + + void swappedIn(const ImpGraphic* pImpGraphic); + void swappedOut(const ImpGraphic* pImpGraphic); + + void reduceGraphicMemory(); + void changeExisting(const ImpGraphic* pImpGraphic, sal_Int64 nOldSize); + void unregisterGraphic(ImpGraphic* pImpGraphic); + + std::shared_ptr<ImpGraphic> copy(std::shared_ptr<ImpGraphic> const& pImpGraphic); + std::shared_ptr<ImpGraphic> newInstance(); + std::shared_ptr<ImpGraphic> newInstance(const Bitmap& rBitmap); + std::shared_ptr<ImpGraphic> newInstance(const BitmapEx& rBitmapEx); + std::shared_ptr<ImpGraphic> newInstance(const VectorGraphicDataPtr& rVectorGraphicDataPtr); + std::shared_ptr<ImpGraphic> newInstance(const Animation& rAnimation); + std::shared_ptr<ImpGraphic> newInstance(const GDIMetaFile& rMtf); +}; +} +} // end namespace vcl::graphic + +#endif // INCLUDED_VCL_INC_GRAPHIC_MANAGER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/impgraph.hxx b/vcl/inc/impgraph.hxx index a60296fde556..a24f786a5b86 100644 --- a/vcl/inc/impgraph.hxx +++ b/vcl/inc/impgraph.hxx @@ -21,6 +21,7 @@ #define INCLUDED_VCL_INC_IMPGRAPH_HXX #include <vcl/GraphicExternalLink.hxx> +#include "graphic/Manager.hxx" struct ImpSwapInfo { @@ -32,6 +33,7 @@ class OutputDevice; class GfxLink; struct ImpSwapFile; class GraphicConversionParameters; +class ImpGraphic; class GraphicID { @@ -62,6 +64,7 @@ class ImpGraphic final { friend class Graphic; friend class GraphicID; + friend class vcl::graphic::Manager; private: @@ -81,18 +84,20 @@ private: std::unique_ptr<GraphicID> mpGraphicID; GraphicExternalLink maGraphicExternalLink; -private: + std::chrono::high_resolution_clock::time_point maLastUsed; - ImpGraphic(); - ImpGraphic( const ImpGraphic& rImpGraphic ); - ImpGraphic( ImpGraphic&& rImpGraphic ); - ImpGraphic( const Bitmap& rBmp ); - ImpGraphic( const BitmapEx& rBmpEx ); - ImpGraphic(const VectorGraphicDataPtr& rVectorGraphicDataPtr); - ImpGraphic( const Animation& rAnimation ); - ImpGraphic( const GDIMetaFile& rMtf ); public: - ~ImpGraphic(); + ImpGraphic(); + ImpGraphic( const ImpGraphic& rImpGraphic ); + ImpGraphic( ImpGraphic&& rImpGraphic ); + ImpGraphic( const GraphicExternalLink& rExternalLink); + ImpGraphic( const Bitmap& rBmp ); + ImpGraphic( const BitmapEx& rBmpEx ); + ImpGraphic(const VectorGraphicDataPtr& rVectorGraphicDataPtr); + ImpGraphic( const Animation& rAnimation ); + ImpGraphic( const GDIMetaFile& rMtf ); + ~ImpGraphic(); + private: ImpGraphic& operator=( const ImpGraphic& rImpGraphic ); @@ -196,6 +201,8 @@ private: const css::uno::Sequence<sal_Int8>& getPdfData() const; void setPdfData(const css::uno::Sequence<sal_Int8>& rPdfData); + + bool ensureAvailable () const; }; #endif // INCLUDED_VCL_INC_IMPGRAPH_HXX diff --git a/vcl/source/gdi/graph.cxx b/vcl/source/gdi/graph.cxx index fdaaabf38612..cdc747eae019 100644 --- a/vcl/source/gdi/graph.cxx +++ b/vcl/source/gdi/graph.cxx @@ -182,14 +182,14 @@ void ImplDrawDefault( OutputDevice* pOutDev, const OUString* pText, } // end anonymous namespace Graphic::Graphic() - : mxImpGraphic(new ImpGraphic) + : mxImpGraphic(vcl::graphic::Manager::get().newInstance()) { } Graphic::Graphic(const Graphic& rGraphic) { if( rGraphic.IsAnimated() ) - mxImpGraphic.reset(new ImpGraphic(*rGraphic.mxImpGraphic)); + mxImpGraphic = vcl::graphic::Manager::get().copy(rGraphic.mxImpGraphic); else mxImpGraphic = rGraphic.mxImpGraphic; } @@ -200,27 +200,27 @@ Graphic::Graphic(Graphic&& rGraphic) } Graphic::Graphic(const Bitmap& rBmp) - : mxImpGraphic(new ImpGraphic(rBmp)) + : mxImpGraphic(vcl::graphic::Manager::get().newInstance(rBmp)) { } Graphic::Graphic(const BitmapEx& rBmpEx) - : mxImpGraphic(new ImpGraphic(rBmpEx)) + : mxImpGraphic(vcl::graphic::Manager::get().newInstance(rBmpEx)) { } Graphic::Graphic(const VectorGraphicDataPtr& rVectorGraphicDataPtr) - : mxImpGraphic(new ImpGraphic(rVectorGraphicDataPtr)) + : mxImpGraphic(vcl::graphic::Manager::get().newInstance(rVectorGraphicDataPtr)) { } Graphic::Graphic(const Animation& rAnimation) - : mxImpGraphic(new ImpGraphic(rAnimation)) + : mxImpGraphic(vcl::graphic::Manager::get().newInstance(rAnimation)) { } Graphic::Graphic(const GDIMetaFile& rMtf) - : mxImpGraphic(new ImpGraphic(rMtf)) + : mxImpGraphic(vcl::graphic::Manager::get().newInstance(rMtf)) { } @@ -234,19 +234,19 @@ Graphic::Graphic( const css::uno::Reference< css::graphic::XGraphic >& rxGraphic if( pGraphic ) { if (pGraphic->IsAnimated()) - mxImpGraphic.reset(new ImpGraphic(*pGraphic->mxImpGraphic)); + mxImpGraphic = vcl::graphic::Manager::get().copy(pGraphic->mxImpGraphic); else mxImpGraphic = pGraphic->mxImpGraphic; } else - mxImpGraphic.reset(new ImpGraphic); + mxImpGraphic = vcl::graphic::Manager::get().newInstance(); } void Graphic::ImplTestRefCount() { if (mxImpGraphic.use_count() > 1) { - mxImpGraphic.reset(new ImpGraphic(*mxImpGraphic)); + mxImpGraphic = vcl::graphic::Manager::get().copy(mxImpGraphic); } } @@ -255,13 +255,9 @@ Graphic& Graphic::operator=( const Graphic& rGraphic ) if( &rGraphic != this ) { if( rGraphic.IsAnimated() ) - { - mxImpGraphic.reset(new ImpGraphic(*rGraphic.mxImpGraphic)); - } + mxImpGraphic = vcl::graphic::Manager::get().copy(rGraphic.mxImpGraphic); else - { mxImpGraphic = rGraphic.mxImpGraphic; - } } return *this; diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx index d32f93eab3b4..13f09ee2bb9c 100644 --- a/vcl/source/gdi/impgraph.cxx +++ b/vcl/source/gdi/impgraph.cxx @@ -175,7 +175,8 @@ ImpGraphic::ImpGraphic() : meType ( GraphicType::NONE ), mnSizeBytes ( 0 ), mbSwapOut ( false ), - mbDummyContext ( false ) + mbDummyContext ( false ), + maLastUsed (std::chrono::high_resolution_clock::now()) { } @@ -192,6 +193,7 @@ ImpGraphic::ImpGraphic(const ImpGraphic& rImpGraphic) , maVectorGraphicData(rImpGraphic.maVectorGraphicData) , maPdfData(rImpGraphic.maPdfData) , maGraphicExternalLink(rImpGraphic.maGraphicExternalLink) + , maLastUsed (std::chrono::high_resolution_clock::now()) { if( rImpGraphic.mpGfxLink ) mpGfxLink = o3tl::make_unique<GfxLink>( *rImpGraphic.mpGfxLink ); @@ -218,6 +220,7 @@ ImpGraphic::ImpGraphic(ImpGraphic&& rImpGraphic) , maVectorGraphicData(std::move(rImpGraphic.maVectorGraphicData)) , maPdfData(std::move(rImpGraphic.maPdfData)) , maGraphicExternalLink(rImpGraphic.maGraphicExternalLink) + , maLastUsed (std::chrono::high_resolution_clock::now()) { rImpGraphic.ImplClear(); rImpGraphic.mbDummyContext = false; @@ -228,7 +231,8 @@ ImpGraphic::ImpGraphic( const Bitmap& rBitmap ) : meType ( !rBitmap.IsEmpty() ? GraphicType::Bitmap : GraphicType::NONE ), mnSizeBytes ( 0 ), mbSwapOut ( false ), - mbDummyContext ( false ) + mbDummyContext ( false ), + maLastUsed (std::chrono::high_resolution_clock::now()) { } @@ -237,7 +241,8 @@ ImpGraphic::ImpGraphic( const BitmapEx& rBitmapEx ) : meType ( !rBitmapEx.IsEmpty() ? GraphicType::Bitmap : GraphicType::NONE ), mnSizeBytes ( 0 ), mbSwapOut ( false ), - mbDummyContext ( false ) + mbDummyContext ( false ), + maLastUsed (std::chrono::high_resolution_clock::now()) { } @@ -246,7 +251,8 @@ ImpGraphic::ImpGraphic(const VectorGraphicDataPtr& rVectorGraphicDataPtr) mnSizeBytes( 0 ), mbSwapOut( false ), mbDummyContext ( false ), - maVectorGraphicData(rVectorGraphicDataPtr) + maVectorGraphicData(rVectorGraphicDataPtr), + maLastUsed (std::chrono::high_resolution_clock::now()) { } @@ -256,7 +262,8 @@ ImpGraphic::ImpGraphic( const Animation& rAnimation ) : meType ( GraphicType::Bitmap ), mnSizeBytes ( 0 ), mbSwapOut ( false ), - mbDummyContext ( false ) + mbDummyContext ( false ), + maLastUsed (std::chrono::high_resolution_clock::now()) { } @@ -265,18 +272,22 @@ ImpGraphic::ImpGraphic( const GDIMetaFile& rMtf ) : meType ( GraphicType::GdiMetafile ), mnSizeBytes ( 0 ), mbSwapOut ( false ), - mbDummyContext ( false ) + mbDummyContext ( false ), + maLastUsed (std::chrono::high_resolution_clock::now()) { } ImpGraphic::~ImpGraphic() { + vcl::graphic::Manager::get().unregisterGraphic(this); } ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic ) { if( &rImpGraphic != this ) { + sal_Int64 aOldSizeBytes = mnSizeBytes; + maMetaFile = rImpGraphic.maMetaFile; meType = rImpGraphic.meType; mnSizeBytes = rImpGraphic.mnSizeBytes; @@ -308,6 +319,9 @@ ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic ) maVectorGraphicData = rImpGraphic.maVectorGraphicData; maPdfData = rImpGraphic.maPdfData; + maLastUsed = std::chrono::high_resolution_clock::now(); + + vcl::graphic::Manager::get().changeExisting(this, aOldSizeBytes); } return *this; @@ -315,6 +329,8 @@ ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic ) ImpGraphic& ImpGraphic::operator=(ImpGraphic&& rImpGraphic) { + sal_Int64 aOldSizeBytes = mnSizeBytes; + maMetaFile = std::move(rImpGraphic.maMetaFile); meType = rImpGraphic.meType; mnSizeBytes = rImpGraphic.mnSizeBytes; @@ -332,6 +348,9 @@ ImpGraphic& ImpGraphic::operator=(ImpGraphic&& rImpGraphic) rImpGraphic.ImplClear(); rImpGraphic.mbDummyContext = false; + maLastUsed = std::chrono::high_resolution_clock::now(); + + vcl::graphic::Manager::get().changeExisting(this, aOldSizeBytes); return *this; } @@ -462,7 +481,9 @@ void ImpGraphic::ImplClear() // cleanup ImplClearGraphics(); meType = GraphicType::NONE; + sal_Int64 nOldSize = mnSizeBytes; mnSizeBytes = 0; + vcl::graphic::Manager::get().changeExisting(this, nOldSize); maGraphicExternalLink.msURL.clear(); } @@ -481,6 +502,8 @@ bool ImpGraphic::ImplIsTransparent() const { bool bRet(true); + ensureAvailable(); + if( meType == GraphicType::Bitmap && !maVectorGraphicData.get()) { bRet = ( mpAnimation ? mpAnimation->IsTransparent() : maEx.IsTransparent() ); @@ -493,6 +516,8 @@ bool ImpGraphic::ImplIsAlpha() const { bool bRet(false); + ensureAvailable(); + if(maVectorGraphicData.get()) { bRet = true; @@ -507,11 +532,14 @@ bool ImpGraphic::ImplIsAlpha() const bool ImpGraphic::ImplIsAnimated() const { + ensureAvailable(); return( mpAnimation != nullptr ); } bool ImpGraphic::ImplIsEPS() const { + ensureAvailable(); + return( ( meType == GraphicType::GdiMetafile ) && ( maMetaFile.GetActionSize() > 0 ) && ( maMetaFile.GetAction( 0 )->GetType() == MetaActionType::EPS ) ); @@ -521,6 +549,8 @@ Bitmap ImpGraphic::ImplGetBitmap(const GraphicConversionParameters& rParameters) { Bitmap aRetBmp; + ensureAvailable(); + if( meType == GraphicType::Bitmap ) { if(maVectorGraphicData.get() && maEx.IsEmpty()) @@ -629,6 +659,8 @@ BitmapEx ImpGraphic::ImplGetBitmapEx(const GraphicConversionParameters& rParamet { BitmapEx aRetBmpEx; + ensureAvailable(); + if( meType == GraphicType::Bitmap ) { if(maVectorGraphicData.get() && maEx.IsEmpty()) @@ -666,6 +698,7 @@ Animation ImpGraphic::ImplGetAnimation() const { Animation aAnimation; + ensureAvailable(); if( mpAnimation ) aAnimation = *mpAnimation; @@ -674,11 +707,13 @@ Animation ImpGraphic::ImplGetAnimation() const const BitmapEx& ImpGraphic::ImplGetBitmapExRef() const { + ensureAvailable(); return maEx; } const GDIMetaFile& ImpGraphic::ImplGetGDIMetaFile() const { + ensureAvailable(); if (!maMetaFile.GetActionSize() && maVectorGraphicData.get() && (VectorGraphicDataType::Emf == maVectorGraphicData->getVectorGraphicDataType() @@ -938,6 +973,7 @@ sal_uLong ImpGraphic::ImplGetSizeBytes() const void ImpGraphic::ImplDraw( OutputDevice* pOutDev, const Point& rDestPt ) const { + ensureAvailable(); if( ImplIsSupportedGraphic() && !ImplIsSwapOut() ) { switch( meType ) @@ -974,6 +1010,7 @@ void ImpGraphic::ImplDraw( OutputDevice* pOutDev, const Point& rDestPt ) const void ImpGraphic::ImplDraw( OutputDevice* pOutDev, const Point& rDestPt, const Size& rDestSize ) const { + ensureAvailable(); if( ImplIsSupportedGraphic() && !ImplIsSwapOut() ) { switch( meType ) @@ -1015,6 +1052,8 @@ void ImpGraphic::ImplStartAnimation( OutputDevice* pOutDev, const Point& rDestPt const Size& rDestSize, long nExtraData, OutputDevice* pFirstFrameOutDev ) { + ensureAvailable(); + if( ImplIsSupportedGraphic() && !ImplIsSwapOut() && mpAnimation ) mpAnimation->Start( pOutDev, rDestPt, rDestSize, nExtraData, pFirstFrameOutDev ); } @@ -1043,6 +1082,7 @@ Link<Animation*,void> ImpGraphic::ImplGetAnimationNotifyHdl() const sal_uInt32 ImpGraphic::ImplGetAnimationLoopCount() const { + ensureAvailable(); return( mpAnimation ? mpAnimation->GetLoopCount() : 0 ); } @@ -1187,6 +1227,8 @@ bool ImpGraphic::ImplWriteEmbedded( SvStream& rOStm ) { bool bRet = false; + ensureAvailable(); + if( ( meType != GraphicType::NONE ) && ( meType != GraphicType::Default ) && !ImplIsSwapOut() ) { const MapMode aMapMode( ImplGetPrefMapMode() ); @@ -1317,6 +1359,8 @@ bool ImpGraphic::ImplSwapOut() } } + if (bRet) + vcl::graphic::Manager::get().swappedOut(this); return bRet; } @@ -1348,6 +1392,15 @@ bool ImpGraphic::ImplSwapOut( SvStream* xOStm ) return bRet; } +bool ImpGraphic::ensureAvailable() const +{ + auto pThis = const_cast<ImpGraphic*>(this); + pThis->maLastUsed = std::chrono::high_resolution_clock::now(); + if (ImplIsSwapOut()) + return pThis->ImplSwapIn(); + return true; +} + bool ImpGraphic::ImplSwapIn() { bool bRet = false; @@ -1383,6 +1436,9 @@ bool ImpGraphic::ImplSwapIn() } } + if (bRet) + vcl::graphic::Manager::get().swappedIn(this); + return bRet; } @@ -1429,6 +1485,8 @@ bool ImpGraphic::ImplSwapIn( SvStream* xIStm ) void ImpGraphic::ImplSetLink( const GfxLink& rGfxLink ) { + ensureAvailable(); + mpGfxLink = o3tl::make_unique<GfxLink>( rGfxLink ); if( mpGfxLink->IsNative() ) @@ -1437,6 +1495,8 @@ void ImpGraphic::ImplSetLink( const GfxLink& rGfxLink ) GfxLink ImpGraphic::ImplGetLink() { + ensureAvailable(); + return( mpGfxLink ? *mpGfxLink : GfxLink() ); } @@ -1449,6 +1509,8 @@ BitmapChecksum ImpGraphic::ImplGetChecksum() const { BitmapChecksum nRet = 0; + ensureAvailable(); + if( ImplIsSupportedGraphic() && !ImplIsSwapOut() ) { switch( meType ) @@ -1493,6 +1555,8 @@ bool ImpGraphic::ImplExportNative( SvStream& rOStm ) const { bool bResult = false; + ensureAvailable(); + if( !rOStm.GetError() ) { if( !ImplIsSwapOut() ) diff --git a/vcl/source/graphic/Manager.cxx b/vcl/source/graphic/Manager.cxx new file mode 100644 index 000000000000..ee161c23d878 --- /dev/null +++ b/vcl/source/graphic/Manager.cxx @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <graphic/Manager.hxx> +#include <impgraph.hxx> +#include <vcl/lazydelete.hxx> +#include <o3tl/make_unique.hxx> + +using namespace css; + +namespace vcl +{ +namespace graphic +{ +namespace +{ +void setTotalCacheSizeFromConfigIfPossible(sal_Int64& nTotalCacheSize) +{ + if (utl::ConfigManager::IsFuzzing()) + return; + + try + { + nTotalCacheSize = officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::get(); + } + catch (...) + { + } +} +} + +Manager& Manager::get() +{ + static std::unique_ptr<Manager> gStaticManager(new Manager); + return *gStaticManager; +} + +Manager::Manager() + : mnTotalCacheSize(50000000) + , mnUsedSize(0) + , maSwapOutTimer("graphic::Manager maSwapOutTimer") +{ + setTotalCacheSizeFromConfigIfPossible(mnTotalCacheSize); + + maSwapOutTimer.SetInvokeHandler(LINK(this, Manager, SwapOutTimerHandler)); + maSwapOutTimer.SetTimeout(10000); + maSwapOutTimer.SetDebugName("graphic::Manager maSwapOutTimer"); + maSwapOutTimer.Start(); +} + +void Manager::reduceGraphicMemory() +{ + for (ImpGraphic* pEachImpGraphic : m_pImpGraphicList) + { + if (mnUsedSize < mnTotalCacheSize * 0.7) + return; + + sal_Int64 nCurrentGraphicSize = pEachImpGraphic->ImplGetSizeBytes(); + if (!pEachImpGraphic->ImplIsSwapOut() && nCurrentGraphicSize > 1000000) + { + if (!pEachImpGraphic->mpContext) + { + auto aCurrent = std::chrono::high_resolution_clock::now(); + auto aDeltaTime = aCurrent - pEachImpGraphic->maLastUsed; + auto aSeconds = std::chrono::duration_cast<std::chrono::seconds>(aDeltaTime); + double nSeconds = aSeconds.count(); + if (nSeconds > 10) + pEachImpGraphic->ImplSwapOut(); + } + } + } +} + +IMPL_LINK(Manager, SwapOutTimerHandler, Timer*, pTimer, void) +{ + pTimer->Stop(); + reduceGraphicMemory(); + pTimer->Start(); +} + +void Manager::registerGraphic(std::shared_ptr<ImpGraphic>& pImpGraphic, + OUString const& /*rsContext*/) +{ + // make some space first + if (mnUsedSize > mnTotalCacheSize) + reduceGraphicMemory(); + + // Insert and update the used size (bytes) + mnUsedSize += pImpGraphic->ImplGetSizeBytes(); + m_pImpGraphicList.insert(pImpGraphic.get()); + + // calculate size of the graphic set + sal_Int64 calculatedSize = 0; + for (ImpGraphic* pEachImpGraphic : m_pImpGraphicList) + { + if (!pEachImpGraphic->ImplIsSwapOut()) + { + calculatedSize += pEachImpGraphic->ImplGetSizeBytes(); + } + } + + if (calculatedSize != mnUsedSize) + { + SAL_WARN_IF(calculatedSize != mnUsedSize, "vcl.gdi", + "Calculated size mismatch. Variable size is '" + << mnUsedSize << "' but calculated size is '" << calculatedSize << "'"); + mnUsedSize = calculatedSize; + } +} + +void Manager::unregisterGraphic(ImpGraphic* pImpGraphic) +{ + mnUsedSize -= pImpGraphic->ImplGetSizeBytes(); + m_pImpGraphicList.erase(pImpGraphic); +} + +std::shared_ptr<ImpGraphic> Manager::copy(std::shared_ptr<ImpGraphic> const& rImpGraphicPtr) +{ + auto pReturn = std::make_shared<ImpGraphic>(*rImpGraphicPtr.get()); + registerGraphic(pReturn, "Copy"); + return pReturn; +} + +std::shared_ptr<ImpGraphic> Manager::newInstance() +{ + auto pReturn = std::make_shared<ImpGraphic>(); + registerGraphic(pReturn, "Empty"); + return pReturn; +} + +std::shared_ptr<ImpGraphic> Manager::newInstance(const Bitmap& rBitmap) +{ + auto pReturn = std::make_shared<ImpGraphic>(rBitmap); + registerGraphic(pReturn, "Bitmap"); + return pReturn; +} + +std::shared_ptr<ImpGraphic> Manager::newInstance(const BitmapEx& rBitmapEx) +{ + auto pReturn = std::make_shared<ImpGraphic>(rBitmapEx); + registerGraphic(pReturn, "BitmapEx"); + return pReturn; +} + +std::shared_ptr<ImpGraphic> Manager::newInstance(const Animation& rAnimation) +{ + auto pReturn = std::make_shared<ImpGraphic>(rAnimation); + registerGraphic(pReturn, "Animation"); + return pReturn; +} + +std::shared_ptr<ImpGraphic> Manager::newInstance(const VectorGraphicDataPtr& rVectorGraphicDataPtr) +{ + auto pReturn = std::make_shared<ImpGraphic>(rVectorGraphicDataPtr); + registerGraphic(pReturn, "VectorGraphic"); + return pReturn; +} + +std::shared_ptr<ImpGraphic> Manager::newInstance(const GDIMetaFile& rMetaFile) +{ + auto pReturn = std::make_shared<ImpGraphic>(rMetaFile); + registerGraphic(pReturn, "Metafile"); + return pReturn; +} + +void Manager::swappedIn(const ImpGraphic* pImpGraphic) +{ + mnUsedSize += pImpGraphic->ImplGetSizeBytes(); +} + +void Manager::swappedOut(const ImpGraphic* pImpGraphic) +{ + mnUsedSize -= pImpGraphic->ImplGetSizeBytes(); +} + +void Manager::changeExisting(const ImpGraphic* pImpGraphic, sal_Int64 nOldSizeBytes) +{ + mnUsedSize -= nOldSizeBytes; + mnUsedSize += pImpGraphic->ImplGetSizeBytes(); +} +} +} // end vcl::graphic + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |