diff options
author | Noel Grandin <noel@peralex.com> | 2019-11-22 13:32:17 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2019-11-22 20:31:37 +0100 |
commit | 90ea305110e5881256ba272800074a2a9f6b613d (patch) | |
tree | f6377700e996937e919948ccc94032e36e028d50 /vcl/win/gdi | |
parent | 5f520f757774db17ea4e33d34c724cf2af3adcba (diff) |
tdf#121740 cache font data to speed up PPT load
takes the load time from 24s to 21s for me.
The cache was determined experimentally for this document.
Change-Id: I34c78d1ff99cb8e72b274a201ded61d23e66941a
Reviewed-on: https://gerrit.libreoffice.org/83470
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'vcl/win/gdi')
-rw-r--r-- | vcl/win/gdi/winlayout.cxx | 53 |
1 files changed, 48 insertions, 5 deletions
diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx index b67f191c0b47..9f4da1950245 100644 --- a/vcl/win/gdi/winlayout.cxx +++ b/vcl/win/gdi/winlayout.cxx @@ -1,3 +1,4 @@ + /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. @@ -44,6 +45,7 @@ #include <rtl/character.hxx> +#include <boost/functional/hash.hpp> #include <algorithm> #include <shlwapi.h> @@ -327,16 +329,53 @@ float WinFontInstance::getHScale() const return nWidth / nHeight; } +struct BlobReference +{ + hb_blob_t* mpBlob; + BlobReference(hb_blob_t* pBlob) : mpBlob(pBlob) + { + hb_blob_reference(mpBlob); + } + BlobReference(BlobReference const & other) + : mpBlob(other.mpBlob) + { + hb_blob_reference(mpBlob); + } + ~BlobReference() { hb_blob_destroy(mpBlob); } +}; +using BlobCacheKey = std::pair<rtl::Reference<PhysicalFontFace>, hb_tag_t>; +struct BlobCacheKeyHash +{ + std::size_t operator()(BlobCacheKey const& rKey) const + { + std::size_t seed = 0; + boost::hash_combine(seed, rKey.first.get()); + boost::hash_combine(seed, rKey.second); + return seed; + } +}; + static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData) { - sal_uLong nLength = 0; - unsigned char* pBuffer = nullptr; + static o3tl::lru_map<BlobCacheKey, BlobReference, BlobCacheKeyHash> gCache(50); + WinFontInstance* pFont = static_cast<WinFontInstance*>(pUserData); HDC hDC = pFont->GetGraphics()->getHDC(); HFONT hFont = pFont->GetHFONT(); assert(hDC); assert(hFont); + BlobCacheKey cacheKey { rtl::Reference<PhysicalFontFace>(pFont->GetFontFace()), nTableTag }; + auto it = gCache.find(cacheKey); + if (it != gCache.end()) + { + hb_blob_reference(it->second.mpBlob); + return it->second.mpBlob; + } + + sal_uLong nLength = 0; + unsigned char* pBuffer = nullptr; + HGDIOBJ hOrigFont = SelectObject(hDC, hFont); nLength = ::GetFontData(hDC, OSL_NETDWORD(nTableTag), 0, nullptr, 0); if (nLength > 0 && nLength != GDI_ERROR) @@ -346,10 +385,14 @@ static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pU } SelectObject(hDC, hOrigFont); - hb_blob_t* pBlob = nullptr; - if (pBuffer != nullptr) - pBlob = hb_blob_create(reinterpret_cast<const char*>(pBuffer), nLength, HB_MEMORY_MODE_READONLY, + if (!pBuffer) + return nullptr; + + hb_blob_t* pBlob = hb_blob_create(reinterpret_cast<const char*>(pBuffer), nLength, HB_MEMORY_MODE_READONLY, pBuffer, [](void* data){ delete[] static_cast<unsigned char*>(data); }); + if (!pBlob) + return pBlob; + gCache.insert({cacheKey, BlobReference(pBlob)}); return pBlob; } |