/* -*- 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 #include #include #include 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 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(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& 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 Manager::copy(std::shared_ptr const& rImpGraphicPtr) { auto pReturn = std::make_shared(*rImpGraphicPtr.get()); registerGraphic(pReturn, "Copy"); return pReturn; } std::shared_ptr Manager::newInstance() { auto pReturn = std::make_shared(); registerGraphic(pReturn, "Empty"); return pReturn; } std::shared_ptr Manager::newInstance(const Bitmap& rBitmap) { auto pReturn = std::make_shared(rBitmap); registerGraphic(pReturn, "Bitmap"); return pReturn; } std::shared_ptr Manager::newInstance(const BitmapEx& rBitmapEx) { auto pReturn = std::make_shared(rBitmapEx); registerGraphic(pReturn, "BitmapEx"); return pReturn; } std::shared_ptr Manager::newInstance(const Animation& rAnimation) { auto pReturn = std::make_shared(rAnimation); registerGraphic(pReturn, "Animation"); return pReturn; } std::shared_ptr Manager::newInstance(const VectorGraphicDataPtr& rVectorGraphicDataPtr) { auto pReturn = std::make_shared(rVectorGraphicDataPtr); registerGraphic(pReturn, "VectorGraphic"); return pReturn; } std::shared_ptr Manager::newInstance(const GDIMetaFile& rMetaFile) { auto pReturn = std::make_shared(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: */