From 31692c2a70b0d14520c7d93fc7c539894e5d49fb Mon Sep 17 00:00:00 2001 From: Nomango Date: Tue, 4 Aug 2020 02:19:23 +0800 Subject: [PATCH] [deploy] add Font::Preload --- .../render/DirectX/D2DDeviceResources.cpp | 18 +- .../render/DirectX/D2DDeviceResources.h | 2 + .../render/DirectX/FontCollectionLoader.cpp | 421 +++++++++--------- src/kiwano/render/DirectX/RendererImpl.cpp | 65 ++- src/kiwano/render/DirectX/RendererImpl.h | 8 +- src/kiwano/render/Font.cpp | 125 +++++- src/kiwano/render/Font.h | 64 ++- src/kiwano/render/GifImage.cpp | 28 +- src/kiwano/render/GifImage.h | 4 +- src/kiwano/render/Renderer.cpp | 70 +-- src/kiwano/render/Renderer.h | 55 +-- src/kiwano/render/Texture.cpp | 28 +- src/kiwano/render/TextureCache.h | 18 +- 13 files changed, 528 insertions(+), 378 deletions(-) diff --git a/src/kiwano/render/DirectX/D2DDeviceResources.cpp b/src/kiwano/render/DirectX/D2DDeviceResources.cpp index 1e295907..5633124e 100644 --- a/src/kiwano/render/DirectX/D2DDeviceResources.cpp +++ b/src/kiwano/render/DirectX/D2DDeviceResources.cpp @@ -89,6 +89,8 @@ public: void SetTargetBitmap(_In_ ComPtr target) override; + void ResetTextRenderingParams(_In_ HMONITOR monitor) override; + public: unsigned long STDMETHODCALLTYPE AddRef(); @@ -386,6 +388,18 @@ void D2DDeviceResources::SetTargetBitmap(ComPtr target) } } +void D2DDeviceResources::ResetTextRenderingParams(HMONITOR monitor) +{ + if (!dwrite_factory_ || device_context_) + return; + + ComPtr params; + if (SUCCEEDED(dwrite_factory_->CreateMonitorRenderingParams(monitor, ¶ms))) + { + device_context_->SetTextRenderingParams(params.Get()); + } +} + HRESULT D2DDeviceResources::CreateBitmapConverter(_Out_ ComPtr& converter, _In_opt_ ComPtr source, _In_ REFWICPixelFormatGUID format, WICBitmapDitherType dither, @@ -488,9 +502,9 @@ HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr& te return E_UNEXPECTED; ComPtr output; - HRESULT hr = - dwrite_factory_->CreateTextFormat(family, collection.Get(), weight, style, stretch, font_size, L"", &output); + HRESULT hr = + dwrite_factory_->CreateTextFormat(family, collection.Get(), weight, style, stretch, font_size, L"", &output); if (SUCCEEDED(hr)) { text_format = output; diff --git a/src/kiwano/render/DirectX/D2DDeviceResources.h b/src/kiwano/render/DirectX/D2DDeviceResources.h index 929a3222..b3c80ddb 100644 --- a/src/kiwano/render/DirectX/D2DDeviceResources.h +++ b/src/kiwano/render/DirectX/D2DDeviceResources.h @@ -76,6 +76,8 @@ public: virtual void SetTargetBitmap(_In_ ComPtr target) = 0; + virtual void ResetTextRenderingParams(_In_ HMONITOR monitor) = 0; + inline ID2D1Factory1* GetFactory() { KGE_ASSERT(factory_); diff --git a/src/kiwano/render/DirectX/FontCollectionLoader.cpp b/src/kiwano/render/DirectX/FontCollectionLoader.cpp index 4b4b7727..5cbc8b0b 100644 --- a/src/kiwano/render/DirectX/FontCollectionLoader.cpp +++ b/src/kiwano/render/DirectX/FontCollectionLoader.cpp @@ -39,16 +39,16 @@ public: STDMETHOD(AddFilePaths) (const Vector& filePaths, _Out_ LPVOID* pCollectionKey, _Out_ uint32_t* pCollectionKeySize); - // IUnknown methods - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); - virtual ULONG STDMETHODCALLTYPE AddRef(); - virtual ULONG STDMETHODCALLTYPE Release(); - // IDWriteFontCollectionLoader methods virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(IDWriteFactory* pFactory, void const* collectionKey, uint32_t collectionKeySize, _Out_ IDWriteFontFileEnumerator** fontFileEnumerator); + // IUnknown methods + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); + private: ULONG refCount_; @@ -108,35 +108,6 @@ STDMETHODIMP FontCollectionLoader::AddFilePaths(const Vector& filePaths, return S_OK; } -HRESULT STDMETHODCALLTYPE FontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) -{ - if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) - { - *ppvObject = this; - AddRef(); - return S_OK; - } - else - { - *ppvObject = NULL; - return E_NOINTERFACE; - } -} - -ULONG STDMETHODCALLTYPE FontCollectionLoader::AddRef() -{ - return InterlockedIncrement(&refCount_); -} - -ULONG STDMETHODCALLTYPE FontCollectionLoader::Release() -{ - ULONG newCount = InterlockedDecrement(&refCount_); - if (newCount == 0) - delete this; - - return newCount; -} - HRESULT STDMETHODCALLTYPE FontCollectionLoader::CreateEnumeratorFromKey( IDWriteFactory* pFactory, void const* collectionKey, uint32_t collectionKeySize, _Out_ IDWriteFontFileEnumerator** fontFileEnumerator) @@ -166,6 +137,35 @@ HRESULT STDMETHODCALLTYPE FontCollectionLoader::CreateEnumeratorFromKey( return hr; } +HRESULT STDMETHODCALLTYPE FontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) +{ + if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) + { + *ppvObject = this; + AddRef(); + return S_OK; + } + else + { + *ppvObject = NULL; + return E_NOINTERFACE; + } +} + +ULONG STDMETHODCALLTYPE FontCollectionLoader::AddRef() +{ + return InterlockedIncrement(&refCount_); +} + +ULONG STDMETHODCALLTYPE FontCollectionLoader::Release() +{ + ULONG newCount = InterlockedDecrement(&refCount_); + if (newCount == 0) + delete this; + + return newCount; +} + //////////////////////////////////////////////////////////////////////////////////////// // // FontFileEnumerator @@ -177,25 +177,25 @@ class FontFileEnumerator : public IFontFileEnumerator public: FontFileEnumerator(); - STDMETHOD(Initialize)(IDWriteFactory* pFactory); - - STDMETHOD(SetFilePaths)(const Vector& filePaths); - ~FontFileEnumerator() { DX::SafeRelease(currentFile_); DX::SafeRelease(pFactory_); } - // IUnknown methods - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, _Out_ void** ppvObject); - virtual ULONG STDMETHODCALLTYPE AddRef(); - virtual ULONG STDMETHODCALLTYPE Release(); + STDMETHOD(Initialize)(IDWriteFactory* pFactory); + + STDMETHOD(SetFilePaths)(const Vector& filePaths); // IDWriteFontFileEnumerator methods virtual HRESULT STDMETHODCALLTYPE MoveNext(_Out_ BOOL* hasCurrentFile); virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(_Out_ IDWriteFontFile** fontFile); + // IUnknown methods + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, _Out_ void** ppvObject); + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); + private: ULONG refCount_; @@ -268,35 +268,6 @@ STDMETHODIMP FontFileEnumerator::SetFilePaths(const Vector& filePaths) return S_OK; } -HRESULT STDMETHODCALLTYPE FontFileEnumerator::QueryInterface(REFIID iid, _Out_ void** ppvObject) -{ - if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) - { - *ppvObject = this; - AddRef(); - return S_OK; - } - else - { - *ppvObject = NULL; - return E_NOINTERFACE; - } -} - -ULONG STDMETHODCALLTYPE FontFileEnumerator::AddRef() -{ - return InterlockedIncrement(&refCount_); -} - -ULONG STDMETHODCALLTYPE FontFileEnumerator::Release() -{ - ULONG newCount = InterlockedDecrement(&refCount_); - if (newCount == 0) - delete this; - - return newCount; -} - HRESULT STDMETHODCALLTYPE FontFileEnumerator::MoveNext(_Out_ BOOL* hasCurrentFile) { HRESULT hr = S_OK; @@ -328,6 +299,35 @@ HRESULT STDMETHODCALLTYPE FontFileEnumerator::GetCurrentFontFile(_Out_ IDWriteFo return (currentFile_ != NULL) ? S_OK : E_FAIL; } +HRESULT STDMETHODCALLTYPE FontFileEnumerator::QueryInterface(REFIID iid, _Out_ void** ppvObject) +{ + if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) + { + *ppvObject = this; + AddRef(); + return S_OK; + } + else + { + *ppvObject = NULL; + return E_NOINTERFACE; + } +} + +ULONG STDMETHODCALLTYPE FontFileEnumerator::AddRef() +{ + return InterlockedIncrement(&refCount_); +} + +ULONG STDMETHODCALLTYPE FontFileEnumerator::Release() +{ + ULONG newCount = InterlockedDecrement(&refCount_); + if (newCount == 0) + delete this; + + return newCount; +} + //////////////////////////////////////////////////////////////////////////////////////// // // ResourceFontCollectionLoader @@ -346,16 +346,16 @@ public: STDMETHOD(AddResources) (const Vector& resources, _Out_ LPVOID* pCollectionKey, _Out_ uint32_t* pCollectionKeySize); - // IUnknown methods - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); - virtual ULONG STDMETHODCALLTYPE AddRef(); - virtual ULONG STDMETHODCALLTYPE Release(); - // IDWriteFontCollectionLoader methods virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(IDWriteFactory* pFactory, void const* collectionKey, uint32_t collectionKeySize, _Out_ IDWriteFontFileEnumerator** fontFileEnumerator); + // IUnknown methods + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); + private: ULONG refCount_; IDWriteFontFileLoader* pFileLoader_; @@ -417,35 +417,6 @@ STDMETHODIMP ResourceFontCollectionLoader::AddResources(const Vector& return S_OK; } -HRESULT STDMETHODCALLTYPE ResourceFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) -{ - if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) - { - *ppvObject = this; - AddRef(); - return S_OK; - } - else - { - *ppvObject = NULL; - return E_NOINTERFACE; - } -} - -ULONG STDMETHODCALLTYPE ResourceFontCollectionLoader::AddRef() -{ - return InterlockedIncrement(&refCount_); -} - -ULONG STDMETHODCALLTYPE ResourceFontCollectionLoader::Release() -{ - ULONG newCount = InterlockedDecrement(&refCount_); - if (newCount == 0) - delete this; - - return newCount; -} - HRESULT STDMETHODCALLTYPE ResourceFontCollectionLoader::CreateEnumeratorFromKey( IDWriteFactory* pFactory, void const* collectionKey, uint32_t collectionKeySize, _Out_ IDWriteFontFileEnumerator** fontFileEnumerator) @@ -476,6 +447,35 @@ HRESULT STDMETHODCALLTYPE ResourceFontCollectionLoader::CreateEnumeratorFromKey( return hr; } +HRESULT STDMETHODCALLTYPE ResourceFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) +{ + if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) + { + *ppvObject = this; + AddRef(); + return S_OK; + } + else + { + *ppvObject = NULL; + return E_NOINTERFACE; + } +} + +ULONG STDMETHODCALLTYPE ResourceFontCollectionLoader::AddRef() +{ + return InterlockedIncrement(&refCount_); +} + +ULONG STDMETHODCALLTYPE ResourceFontCollectionLoader::Release() +{ + ULONG newCount = InterlockedDecrement(&refCount_); + if (newCount == 0) + delete this; + + return newCount; +} + //////////////////////////////////////////////////////////////////////////////////////// // // ResourceFontFileLoader @@ -490,16 +490,16 @@ public: { } - // IUnknown methods - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); - virtual ULONG STDMETHODCALLTYPE AddRef(); - virtual ULONG STDMETHODCALLTYPE Release(); - // IDWriteFontFileLoader methods virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(void const* fontFileReferenceKey, uint32_t fontFileReferenceKeySize, _Out_ IDWriteFontFileStream** fontFileStream); + // IUnknown methods + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); + private: ULONG refCount_; }; @@ -526,6 +526,33 @@ HRESULT IResourceFontFileLoader::Create(_Out_ IResourceFontFileLoader** ppFileLo return hr; } +HRESULT STDMETHODCALLTYPE ResourceFontFileLoader::CreateStreamFromKey(void const* fontFileReferenceKey, + uint32_t fontFileReferenceKeySize, + _Out_ IDWriteFontFileStream** fontFileStream) +{ + HRESULT hr = S_OK; + + // Make sure the key is the right size. + if (fontFileReferenceKeySize != sizeof(Resource)) + hr = E_INVALIDARG; + + if (SUCCEEDED(hr)) + { + // Create the pFileStream object. + IResourceFontFileStream* pFileStream = NULL; + Resource resource = *static_cast(fontFileReferenceKey); + + hr = IResourceFontFileStream::Create(&pFileStream, resource); + + if (SUCCEEDED(hr)) + { + DX::SafeRelease(*fontFileStream); + (*fontFileStream) = pFileStream; + } + } + return hr; +} + HRESULT STDMETHODCALLTYPE ResourceFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) { if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) @@ -555,33 +582,6 @@ ULONG STDMETHODCALLTYPE ResourceFontFileLoader::Release() return newCount; } -HRESULT STDMETHODCALLTYPE ResourceFontFileLoader::CreateStreamFromKey(void const* fontFileReferenceKey, - uint32_t fontFileReferenceKeySize, - _Out_ IDWriteFontFileStream** fontFileStream) -{ - HRESULT hr = S_OK; - - // Make sure the key is the right size. - if (fontFileReferenceKeySize != sizeof(Resource)) - hr = E_INVALIDARG; - - if (SUCCEEDED(hr)) - { - // Create the pFileStream object. - IResourceFontFileStream* pFileStream = NULL; - Resource resource = *static_cast(fontFileReferenceKey); - - hr = IResourceFontFileStream::Create(&pFileStream, resource); - - if (SUCCEEDED(hr)) - { - DX::SafeRelease(*fontFileStream); - (*fontFileStream) = pFileStream; - } - } - return hr; -} - //////////////////////////////////////////////////////////////////////////////////////// // // ResourceFontFileEnumerator @@ -593,25 +593,25 @@ class ResourceFontFileEnumerator : public IResourceFontFileEnumerator public: ResourceFontFileEnumerator(); - STDMETHOD(Initialize)(IDWriteFactory* pFactory, IDWriteFontFileLoader* pLoader); - - STDMETHOD(SetResources)(const Vector& resources); - ~ResourceFontFileEnumerator() { DX::SafeRelease(currentFile_); DX::SafeRelease(pFactory_); } - // IUnknown methods - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, _Out_ void** ppvObject); - virtual ULONG STDMETHODCALLTYPE AddRef(); - virtual ULONG STDMETHODCALLTYPE Release(); + STDMETHOD(Initialize)(IDWriteFactory* pFactory, IDWriteFontFileLoader* pLoader); + + STDMETHOD(SetResources)(const Vector& resources); // IDWriteFontFileEnumerator methods virtual HRESULT STDMETHODCALLTYPE MoveNext(_Out_ BOOL* hasCurrentFile); virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(_Out_ IDWriteFontFile** fontFile); + // IUnknown methods + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, _Out_ void** ppvObject); + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); + private: ULONG refCount_; @@ -688,35 +688,6 @@ STDMETHODIMP ResourceFontFileEnumerator::SetResources(const Vector& re return S_OK; } -HRESULT STDMETHODCALLTYPE ResourceFontFileEnumerator::QueryInterface(REFIID iid, _Out_ void** ppvObject) -{ - if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) - { - *ppvObject = this; - AddRef(); - return S_OK; - } - else - { - *ppvObject = NULL; - return E_NOINTERFACE; - } -} - -ULONG STDMETHODCALLTYPE ResourceFontFileEnumerator::AddRef() -{ - return InterlockedIncrement(&refCount_); -} - -ULONG STDMETHODCALLTYPE ResourceFontFileEnumerator::Release() -{ - ULONG newCount = InterlockedDecrement(&refCount_); - if (newCount == 0) - delete this; - - return newCount; -} - HRESULT STDMETHODCALLTYPE ResourceFontFileEnumerator::MoveNext(_Out_ BOOL* hasCurrentFile) { HRESULT hr = S_OK; @@ -747,6 +718,35 @@ HRESULT STDMETHODCALLTYPE ResourceFontFileEnumerator::GetCurrentFontFile(_Out_ I return (currentFile_ != NULL) ? S_OK : E_FAIL; } +HRESULT STDMETHODCALLTYPE ResourceFontFileEnumerator::QueryInterface(REFIID iid, _Out_ void** ppvObject) +{ + if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) + { + *ppvObject = this; + AddRef(); + return S_OK; + } + else + { + *ppvObject = NULL; + return E_NOINTERFACE; + } +} + +ULONG STDMETHODCALLTYPE ResourceFontFileEnumerator::AddRef() +{ + return InterlockedIncrement(&refCount_); +} + +ULONG STDMETHODCALLTYPE ResourceFontFileEnumerator::Release() +{ + ULONG newCount = InterlockedDecrement(&refCount_); + if (newCount == 0) + delete this; + + return newCount; +} + //////////////////////////////////////////////////////////////////////////////////////// // // ResourceFontFileStream @@ -760,11 +760,6 @@ public: STDMETHOD(Initialize)(Resource const resources); - // IUnknown methods - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); - virtual ULONG STDMETHODCALLTYPE AddRef(); - virtual ULONG STDMETHODCALLTYPE Release(); - // IDWriteFontFileStream methods virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(void const** fragmentStart, UINT64 fileOffset, UINT64 fragmentSize, _Out_ void** fragmentContext); @@ -775,10 +770,10 @@ public: virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(_Out_ UINT64* lastWriteTime); - bool IsInitialized() - { - return resourcePtr_ != NULL; - } + // IUnknown methods + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); + virtual ULONG STDMETHODCALLTYPE AddRef(); + virtual ULONG STDMETHODCALLTYPE Release(); private: ULONG refCount_; @@ -834,36 +829,6 @@ STDMETHODIMP ResourceFontFileStream::Initialize(const Resource resource) return hr; } -// IUnknown methods -HRESULT STDMETHODCALLTYPE ResourceFontFileStream::QueryInterface(REFIID iid, void** ppvObject) -{ - if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) - { - *ppvObject = this; - AddRef(); - return S_OK; - } - else - { - *ppvObject = NULL; - return E_NOINTERFACE; - } -} - -ULONG STDMETHODCALLTYPE ResourceFontFileStream::AddRef() -{ - return InterlockedIncrement(&refCount_); -} - -ULONG STDMETHODCALLTYPE ResourceFontFileStream::Release() -{ - ULONG newCount = InterlockedDecrement(&refCount_); - if (newCount == 0) - delete this; - - return newCount; -} - HRESULT STDMETHODCALLTYPE ResourceFontFileStream::ReadFileFragment(void const** fragmentStart, UINT64 fileOffset, UINT64 fragmentSize, _Out_ void** fragmentContext) { @@ -896,4 +861,34 @@ HRESULT STDMETHODCALLTYPE ResourceFontFileStream::GetLastWriteTime(_Out_ UINT64* return E_NOTIMPL; } +// IUnknown methods +HRESULT STDMETHODCALLTYPE ResourceFontFileStream::QueryInterface(REFIID iid, void** ppvObject) +{ + if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) + { + *ppvObject = this; + AddRef(); + return S_OK; + } + else + { + *ppvObject = NULL; + return E_NOINTERFACE; + } +} + +ULONG STDMETHODCALLTYPE ResourceFontFileStream::AddRef() +{ + return InterlockedIncrement(&refCount_); +} + +ULONG STDMETHODCALLTYPE ResourceFontFileStream::Release() +{ + ULONG newCount = InterlockedDecrement(&refCount_); + if (newCount == 0) + delete this; + + return newCount; +} + } // namespace kiwano diff --git a/src/kiwano/render/DirectX/RendererImpl.cpp b/src/kiwano/render/DirectX/RendererImpl.cpp index 8aef4243..fac95e0f 100644 --- a/src/kiwano/render/DirectX/RendererImpl.cpp +++ b/src/kiwano/render/DirectX/RendererImpl.cpp @@ -19,6 +19,7 @@ // THE SOFTWARE. #include +#include #include #include #include @@ -48,6 +49,7 @@ RendererImpl& RendererImpl::GetInstance() } RendererImpl::RendererImpl() + : monitor_(nullptr) { } @@ -62,6 +64,7 @@ void RendererImpl::MakeContextForWindow(WindowPtr window) HRESULT hr = target_window ? S_OK : E_FAIL; output_size_ = Size{ float(resolution.width), float(resolution.height) }; + monitor_ = ::MonitorFromWindow(target_window, MONITOR_DEFAULTTONULL); // Initialize Direct3D resources if (SUCCEEDED(hr)) @@ -107,6 +110,28 @@ void RendererImpl::MakeContextForWindow(WindowPtr window) } } + if (SUCCEEDED(hr)) + { + IDWriteFactory* dwrite = d2d_res_->GetDWriteFactory(); + if (dwrite) + { + ComPtr system_collection; + if (SUCCEEDED(dwrite->GetSystemFontCollection(&system_collection, FALSE))) + { + Vector family_names; + if (SUCCEEDED(d2d_res_->GetFontFamilyNames(family_names, system_collection))) + { + // dummy font + FontPtr font = MakePtr(); + for (const auto& name : family_names) + { + FontCache::GetInstance().AddFontByFamily(name, font); + } + } + } + } + } + KGE_THROW_IF_FAILED(hr, "Create render resources failed"); } @@ -132,6 +157,26 @@ void RendererImpl::Destroy() ::CoUninitialize(); } +void RendererImpl::HandleEvent(EventModuleContext& ctx) +{ + Renderer::HandleEvent(ctx); + + if (ctx.evt->IsType()) + { + auto evt = ctx.evt->SafeCast(); + HMONITOR monitor = ::MonitorFromWindow(evt->window->GetHandle(), MONITOR_DEFAULTTONULL); + if (monitor_ != monitor) + { + monitor_ = monitor; + + if (d2d_res_) + { + d2d_res_->ResetTextRenderingParams(monitor); + } + } + } +} + void RendererImpl::Clear() { KGE_ASSERT(d3d_res_); @@ -479,7 +524,7 @@ void RendererImpl::CreateGifImageFrame(GifImage::Frame& frame, const GifImage& g KGE_SET_STATUS_IF_FAILED(hr, const_cast(gif), "Load GIF frame failed"); } -void RendererImpl::CreateFontCollection(Font& font, const String& file_path) +void RendererImpl::CreateFontCollection(Font& font, Vector& family_names, const String& file_path) { HRESULT hr = S_OK; if (!d2d_res_) @@ -506,12 +551,7 @@ void RendererImpl::CreateFontCollection(Font& font, const String& file_path) if (SUCCEEDED(hr)) { - Vector family_names; d2d_res_->GetFontFamilyNames(family_names, font_collection); // ignore the result - - if (!family_names.empty()) - font.SetFamilyName(family_names[0]); - NativePtr::Set(font, font_collection); } } @@ -519,7 +559,7 @@ void RendererImpl::CreateFontCollection(Font& font, const String& file_path) KGE_SET_STATUS_IF_FAILED(hr, font, "Create font collection failed"); } -void RendererImpl::CreateFontCollection(Font& font, const Resource& res) +void RendererImpl::CreateFontCollection(Font& font, Vector& family_names, const Resource& res) { HRESULT hr = S_OK; if (!d2d_res_) @@ -534,12 +574,7 @@ void RendererImpl::CreateFontCollection(Font& font, const Resource& res) if (SUCCEEDED(hr)) { - Vector family_names; d2d_res_->GetFontFamilyNames(family_names, font_collection); // ignore the result - - if (!family_names.empty()) - font.SetFamilyName(family_names[0]); - NativePtr::Set(font, font_collection); } } @@ -564,9 +599,9 @@ void RendererImpl::CreateTextLayout(TextLayout& layout, const String& content, c if (SUCCEEDED(hr)) { - DWRITE_FONT_WEIGHT font_weight = DWRITE_FONT_WEIGHT(style.font_weight); - DWRITE_FONT_STYLE font_style = style.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; - auto collection = NativePtr::Get(style.font); + auto font_weight = DWRITE_FONT_WEIGHT(style.font_weight); + auto font_style = style.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; + auto collection = NativePtr::Get(style.font); WideString font_family; if (style.font) diff --git a/src/kiwano/render/DirectX/RendererImpl.h b/src/kiwano/render/DirectX/RendererImpl.h index 4a58c3b9..434ef363 100644 --- a/src/kiwano/render/DirectX/RendererImpl.h +++ b/src/kiwano/render/DirectX/RendererImpl.h @@ -42,9 +42,9 @@ public: void CreateGifImageFrame(GifImage::Frame& frame, const GifImage& gif, size_t frame_index) override; - void CreateFontCollection(Font& font, const String& file_path) override; + void CreateFontCollection(Font& font, Vector& family_names, const String& file_path) override; - void CreateFontCollection(Font& font, const Resource& res) override; + void CreateFontCollection(Font& font, Vector& family_names, const Resource& res) override; void CreateTextLayout(TextLayout& layout, const String& content, const TextStyle& style) override; @@ -81,6 +81,8 @@ public: void Destroy() override; + void HandleEvent(EventModuleContext& ctx) override; + protected: RendererImpl(); @@ -90,6 +92,8 @@ private: ComPtr d2d_res_; ComPtr d3d_res_; + + HMONITOR monitor_; }; diff --git a/src/kiwano/render/Font.cpp b/src/kiwano/render/Font.cpp index ccc9bbe8..deb10ad3 100644 --- a/src/kiwano/render/Font.cpp +++ b/src/kiwano/render/Font.cpp @@ -20,34 +20,65 @@ #include #include +#include // std::hash namespace kiwano { FontPtr Font::Preload(const String& file) { - FontPtr ptr = MakePtr(); - try + size_t hash_code = std::hash{}(file); + if (FontPtr ptr = FontCache::GetInstance().GetFont(hash_code)) { - Renderer::GetInstance().CreateFontCollection(*ptr, file); + return ptr; } - catch (Exception&) + + FontPtr ptr = MakePtr(); + if (ptr) { - return nullptr; + Vector family_names; + Renderer::GetInstance().CreateFontCollection(*ptr, family_names, file); + if (ptr->IsValid()) + { + FontCache::GetInstance().AddFont(hash_code, ptr); + if (!family_names.empty()) + { + ptr->SetFamilyName(family_names[0]); + } + for (const auto& name : family_names) + { + FontCache::GetInstance().AddFontByFamily(name, ptr); + } + } } return ptr; } FontPtr Font::Preload(const Resource& resource) { - FontPtr ptr = MakePtr(); - try + size_t hash_code = resource.GetId(); + if (FontPtr ptr = FontCache::GetInstance().GetFont(hash_code)) { - Renderer::GetInstance().CreateFontCollection(*ptr, resource); + return ptr; } - catch (Exception&) + + FontPtr ptr = MakePtr(); + if (ptr) { - return nullptr; + Vector family_names; + Renderer::GetInstance().CreateFontCollection(*ptr, family_names, resource); + if (ptr->IsValid()) + { + FontCache::GetInstance().AddFont(hash_code, ptr); + if (!family_names.empty()) + { + ptr->SetFamilyName(family_names[0]); + } + for (const auto& name : family_names) + { + FontCache::GetInstance().AddFontByFamily(name, ptr); + } + } } return ptr; } @@ -55,8 +86,80 @@ FontPtr Font::Preload(const Resource& resource) Font::Font() {} Font::Font(const String& family_name) - : family_name_(family_name) { + Load(family_name); +} + +bool Font::Load(const String& family_name) +{ + if (family_name.empty()) + return true; + + if (FontPtr font = FontCache::GetInstance().GetFontByFamily(family_name)) + { + ResetNativePointer(font->GetNativePointer()); + SetFamilyName(family_name); + return true; + } + Fail(strings::Format("Font::Load failed: cannot find family name \"%s\"", family_name.c_str())); + return false; +} + +FontCache::FontCache() {} + +FontCache::~FontCache() {} + +void FontCache::AddFont(size_t key, FontPtr font) +{ + font_cache_.insert(std::make_pair(key, font)); +} + +void FontCache::AddFontByFamily(const String& font_family, FontPtr font) +{ + String family = TransformFamily(font_family); + font_family_cache_.insert(std::make_pair(family, font)); +} + +FontPtr FontCache::GetFont(size_t key) const +{ + if (font_cache_.count(key)) + { + return font_cache_.at(key); + } + return FontPtr(); +} + +FontPtr FontCache::GetFontByFamily(const String& font_family) const +{ + String family = TransformFamily(font_family); + if (font_family_cache_.count(family)) + { + return font_family_cache_.at(family); + } + return FontPtr(); +} + +void FontCache::RemoveFont(size_t key) +{ + font_cache_.erase(key); +} + +void FontCache::RemoveFontByFamily(const String& font_family) +{ + String family = TransformFamily(font_family); + font_family_cache_.erase(family); +} + +void FontCache::Clear() +{ + font_cache_.clear(); + font_family_cache_.clear(); +} + +String FontCache::TransformFamily(String family) const +{ + std::transform(family.begin(), family.end(), family.begin(), std::tolower); + return family; } } // namespace kiwano diff --git a/src/kiwano/render/Font.h b/src/kiwano/render/Font.h index dfa59a85..3ff5e421 100644 --- a/src/kiwano/render/Font.h +++ b/src/kiwano/render/Font.h @@ -41,26 +41,32 @@ class Font : public NativeObject { public: /// \~chinese - /// @brief 创建字体 + /// @brief 预加载字体 /// @param file 字体文件 static FontPtr Preload(const String& file); /// \~chinese - /// @brief 创建字体 + /// @brief 预加载字体 /// @param resource 字体资源 static FontPtr Preload(const Resource& resource); Font(); /// \~chinese - /// @brief 创建字体 + /// @brief 通过字体族创建字体 /// @param family_name 字体族 Font(const String& family_name); + /// \~chinese + /// @brief 加载字体族 + /// @param family_name 字体族 + bool Load(const String& family_name); + /// \~chinese /// @brief 获取字体族 String GetFamilyName() const; +protected: /// \~chinese /// @brief 获取字体族 void SetFamilyName(const String& name); @@ -69,6 +75,58 @@ protected: String family_name_; }; +/** + * \~chinese + * @brief 纹理缓存 + */ +class KGE_API FontCache final : public Singleton +{ + friend Singleton; + +public: + /// \~chinese + /// @brief 添加字体缓存 + void AddFont(size_t key, FontPtr font); + + /// \~chinese + /// @brief 添加字体族映射字体缓存 + void AddFontByFamily(const String& font_family, FontPtr font); + + /// \~chinese + /// @brief 获取字体缓存 + FontPtr GetFont(size_t key) const; + + /// \~chinese + /// @brief 获取字体族映射字体缓存 + FontPtr GetFontByFamily(const String& font_family) const; + + /// \~chinese + /// @brief 移除字体缓存 + void RemoveFont(size_t key); + + /// \~chinese + /// @brief 移除字体族映射字体缓存 + void RemoveFontByFamily(const String& font_family); + + /// \~chinese + /// @brief 清空缓存 + void Clear(); + + ~FontCache(); + +private: + FontCache(); + + String TransformFamily(String family) const; + +private: + using FontMap = UnorderedMap; + FontMap font_cache_; + + using FontFamilyMap = UnorderedMap; + FontFamilyMap font_family_cache_; +}; + /** @} */ inline String Font::GetFamilyName() const diff --git a/src/kiwano/render/GifImage.cpp b/src/kiwano/render/GifImage.cpp index a2c102e0..ca2b3aea 100644 --- a/src/kiwano/render/GifImage.cpp +++ b/src/kiwano/render/GifImage.cpp @@ -21,20 +21,40 @@ #include #include #include +#include +#include // std::hash namespace kiwano { GifImagePtr GifImage::Preload(const String& file_path) { - GifImagePtr image = Renderer::GetInstance().CreateGifImage(file_path); - return image; + size_t hash_code = std::hash{}(file_path); + if (GifImagePtr ptr = TextureCache::GetInstance().GetGifImage(hash_code)) + { + return ptr; + } + GifImagePtr ptr = MakePtr(); + if (ptr && ptr->Load(file_path)) + { + TextureCache::GetInstance().AddGifImage(hash_code, ptr); + } + return ptr; } GifImagePtr GifImage::Preload(const Resource& res) { - GifImagePtr image = Renderer::GetInstance().CreateGifImage(res); - return image; + size_t hash_code = res.GetId(); + if (GifImagePtr ptr = TextureCache::GetInstance().GetGifImage(hash_code)) + { + return ptr; + } + GifImagePtr ptr = MakePtr(); + if (ptr && ptr->Load(res)) + { + TextureCache::GetInstance().AddGifImage(hash_code, ptr); + } + return ptr; } GifImage::GifImage(const String& file_path) diff --git a/src/kiwano/render/GifImage.h b/src/kiwano/render/GifImage.h index 64d98811..d8c31916 100644 --- a/src/kiwano/render/GifImage.h +++ b/src/kiwano/render/GifImage.h @@ -46,6 +46,8 @@ public: /// @brief 预加载GIF图片资源 static GifImagePtr Preload(const Resource& res); + GifImage(); + /// \~chinese /// @brief 创建GIF图片 GifImage(const String& file_path); @@ -54,8 +56,6 @@ public: /// @brief 创建GIF图片 GifImage(const Resource& res); - GifImage(); - /// \~chinese /// @brief 加载本地GIF图片 bool Load(const String& file_path); diff --git a/src/kiwano/render/Renderer.cpp b/src/kiwano/render/Renderer.cpp index a4459c0e..d1610a7e 100644 --- a/src/kiwano/render/Renderer.cpp +++ b/src/kiwano/render/Renderer.cpp @@ -18,8 +18,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include // std::hash #include +#include #include namespace kiwano @@ -47,69 +47,10 @@ void Renderer::ResetResolutionWhenWindowResized(bool enabled) auto_reset_resolution_ = enabled; } -TexturePtr Renderer::CreateTexture(const String& file_path) -{ - size_t hash_code = std::hash{}(file_path); - if (TexturePtr ptr = texture_cache_.GetTexture(hash_code)) - { - return ptr; - } - TexturePtr ptr = MakePtr(); - if (ptr && ptr->Load(file_path)) - { - texture_cache_.AddTexture(hash_code, ptr); - } - return ptr; -} - -TexturePtr Renderer::CreateTexture(const Resource& resource) -{ - size_t hash_code = resource.GetId(); - if (TexturePtr ptr = texture_cache_.GetTexture(hash_code)) - { - return ptr; - } - TexturePtr ptr = MakePtr(); - if (ptr && ptr->Load(resource)) - { - texture_cache_.AddTexture(hash_code, ptr); - } - return ptr; -} - -GifImagePtr Renderer::CreateGifImage(const String& file_path) -{ - size_t hash_code = std::hash{}(file_path); - if (GifImagePtr ptr = texture_cache_.GetGifImage(hash_code)) - { - return ptr; - } - GifImagePtr ptr = MakePtr(); - if (ptr && ptr->Load(file_path)) - { - texture_cache_.AddGifImage(hash_code, ptr); - } - return ptr; -} - -GifImagePtr Renderer::CreateGifImage(const Resource& resource) -{ - size_t hash_code = resource.GetId(); - if (GifImagePtr ptr = texture_cache_.GetGifImage(hash_code)) - { - return ptr; - } - GifImagePtr ptr = MakePtr(); - if (ptr && ptr->Load(resource)) - { - texture_cache_.AddGifImage(hash_code, ptr); - } - return ptr; -} - void Renderer::Destroy() { - texture_cache_.Clear(); + TextureCache::GetInstance().Clear(); + FontCache::GetInstance().Clear(); } void Renderer::HandleEvent(EventModuleContext& ctx) @@ -124,9 +65,4 @@ void Renderer::HandleEvent(EventModuleContext& ctx) } } -TextureCache& Renderer::GetTextureCache() -{ - return texture_cache_; -} - } // namespace kiwano diff --git a/src/kiwano/render/Renderer.h b/src/kiwano/render/Renderer.h index 47a6174f..dd1956d4 100644 --- a/src/kiwano/render/Renderer.h +++ b/src/kiwano/render/Renderer.h @@ -24,7 +24,6 @@ #include #include #include -#include #include namespace kiwano @@ -80,52 +79,28 @@ public: /// @brief 窗口大小变化时自动调整分辨率 void ResetResolutionWhenWindowResized(bool enabled); - /// \~chinese - /// @brief 创建纹理 - /// @param[in] file_path 图片路径 - TexturePtr CreateTexture(const String& file_path); - - /// \~chinese - /// @brief 创建纹理 - /// @param[in] resource 图片资源 - TexturePtr CreateTexture(const Resource& resource); - - /// \~chinese - /// @brief 创建GIF图像 - /// @param[in] file_path 图片路径 - GifImagePtr CreateGifImage(const String& file_path); - - /// \~chinese - /// @brief 创建GIF图像 - /// @param[in] resource 图片资源 - GifImagePtr CreateGifImage(const Resource& resource); - /// \~chinese /// @brief 创建纹理内部资源 /// @param[out] texture 纹理 /// @param[in] file_path 图片路径 - /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateTexture(Texture& texture, const String& file_path) = 0; /// \~chinese /// @brief 创建纹理内部资源 /// @param[out] texture 纹理 /// @param[in] resource 图片资源 - /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateTexture(Texture& texture, const Resource& resource) = 0; /// \~chinese /// @brief 创建GIF图像内部资源 /// @param[out] gif GIF图像 /// @param[in] file_path 图片路径 - /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateGifImage(GifImage& gif, const String& file_path) = 0; /// \~chinese /// @brief 创建GIF图像内部资源 /// @param[out] gif GIF图像 /// @param[in] resource 图片资源 - /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateGifImage(GifImage& gif, const Resource& resource) = 0; /// \~chinese @@ -133,29 +108,27 @@ public: /// @param[out] frame GIF图像帧 /// @param[in] gif GIF图像 /// @param[in] frame_index 帧下标 - /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateGifImageFrame(GifImage::Frame& frame, const GifImage& gif, size_t frame_index) = 0; /// \~chinese /// @brief 创建字体集内部资源 /// @param[out] font 字体 + /// @param[out] family_names 字体包含的字体族 /// @param[in] file_paths 字体文件路径 - /// @throw kiwano::SystemError 创建失败时抛出 - virtual void CreateFontCollection(Font& font, const String& file_path) = 0; + virtual void CreateFontCollection(Font& font, Vector& family_names, const String& file_path) = 0; /// \~chinese /// @brief 创建字体集内部资源 /// @param[out] font 字体 + /// @param[out] family_names 字体包含的字体族 /// @param[in] res_arr 字体资源 - /// @throw kiwano::SystemError 创建失败时抛出 - virtual void CreateFontCollection(Font& font, const Resource& res) = 0; + virtual void CreateFontCollection(Font& font, Vector& family_names, const Resource& res) = 0; /// \~chinese /// @brief 创建文字布局内部资源 /// @param[out] layout 字体布局 /// @param text 文字内容 /// @param style 文本样式 - /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateTextLayout(TextLayout& layout, const String& content, const TextStyle& style) = 0; /// \~chinese @@ -163,14 +136,12 @@ public: /// @param[out] shape 形状 /// @param[in] begin_pos 线段起点 /// @param[in] end_pos 线段终点 - /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateLineShape(Shape& shape, const Point& begin_pos, const Point& end_pos) = 0; /// \~chinese /// @brief 创建矩形形状内部资源 /// @param[out] shape 形状 /// @param[in] rect 矩形大小 - /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateRectShape(Shape& shape, const Rect& rect) = 0; /// \~chinese @@ -178,7 +149,6 @@ public: /// @param[out] shape 形状 /// @param[in] rect 矩形大小 /// @param[in] radius 圆角半径 - /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateRoundedRectShape(Shape& shape, const Rect& rect, const Vec2& radius) = 0; /// \~chinese @@ -186,41 +156,35 @@ public: /// @param[out] shape 形状 /// @param[in] center 椭圆圆心 /// @param[in] radius 椭圆半径 - /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateEllipseShape(Shape& shape, const Point& center, const Vec2& radius) = 0; /// \~chinese /// @brief 创建几何图形生成器内部资源 /// @param[out] maker 形状生成器 - /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateShapeSink(ShapeMaker& maker) = 0; /// \~chinese /// @brief 创建纯色画刷内部资源 /// @param[out] brush 画刷 /// @param[in] color 颜色 - /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateBrush(Brush& brush, const Color& color) = 0; /// \~chinese /// @brief 创建线性渐变画刷内部资源 /// @param[out] brush 画刷 /// @param[in] style 线性渐变样式 - /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateBrush(Brush& brush, const LinearGradientStyle& style) = 0; /// \~chinese /// @brief 创建径向渐变画刷内部资源 /// @param[out] brush 画刷 /// @param[in] style 径向渐变样式 - /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateBrush(Brush& brush, const RadialGradientStyle& style) = 0; /// \~chinese /// @brief 创建纹理画刷内部资源 /// @param[out] brush 画刷 /// @param[in] texture 纹理 - /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateBrush(Brush& brush, TexturePtr texture) = 0; /// \~chinese @@ -231,7 +195,6 @@ public: /// @param[in] dash_array 虚线长度与间隙数组 /// @param[in] dash_size 虚线数组大小 /// @param[in] dash_offset 虚线偏移量 - /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateStrokeStyle(StrokeStyle& stroke_style) = 0; /// \~chinese @@ -239,13 +202,8 @@ public: /// @param[in,out] texture 渲染输出的纹理 /// @param[in] desired_size 期望的输出大小 /// @return 纹理渲染上下文 - /// @throw kiwano::SystemError 创建失败时抛出 virtual RenderContextPtr CreateTextureRenderContext(Texture& texture, const Size* desired_size = nullptr) = 0; - /// \~chinese - /// @brief 创建纹理渲染上下文 - TextureCache& GetTextureCache(); - public: /// \~chinese /// @brief 清除绘制内容 @@ -258,12 +216,15 @@ public: /// \~chinese /// @brief 为窗口创建渲染上下文 + /// @throw kiwano::SystemError 创建上下文失败时抛出 virtual void MakeContextForWindow(WindowPtr window) = 0; /// \~chinese /// @brief 销毁渲染器资源 virtual void Destroy(); + /// \~chinese + /// @brief 处理事件 void HandleEvent(EventModuleContext& ctx) override; protected: @@ -275,8 +236,6 @@ protected: Color clear_color_; Size output_size_; RenderContextPtr render_ctx_; - - TextureCache texture_cache_; }; /** @} */ diff --git a/src/kiwano/render/Texture.cpp b/src/kiwano/render/Texture.cpp index 3e2bd993..c77e64b5 100644 --- a/src/kiwano/render/Texture.cpp +++ b/src/kiwano/render/Texture.cpp @@ -20,6 +20,8 @@ #include #include +#include +#include // std::hash #if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX #include @@ -32,14 +34,32 @@ InterpolationMode Texture::default_interpolation_mode_ = InterpolationMode::Line TexturePtr Texture::Preload(const String& file_path) { - TexturePtr image = Renderer::GetInstance().CreateTexture(file_path); - return image; + size_t hash_code = std::hash{}(file_path); + if (TexturePtr ptr = TextureCache::GetInstance().GetTexture(hash_code)) + { + return ptr; + } + TexturePtr ptr = MakePtr(); + if (ptr && ptr->Load(file_path)) + { + TextureCache::GetInstance().AddTexture(hash_code, ptr); + } + return ptr; } TexturePtr Texture::Preload(const Resource& res) { - TexturePtr image = Renderer::GetInstance().CreateTexture(res); - return image; + size_t hash_code = res.GetId(); + if (TexturePtr ptr = TextureCache::GetInstance().GetTexture(hash_code)) + { + return ptr; + } + TexturePtr ptr = MakePtr(); + if (ptr && ptr->Load(res)) + { + TextureCache::GetInstance().AddTexture(hash_code, ptr); + } + return ptr; } Texture::Texture(const String& file_path) diff --git a/src/kiwano/render/TextureCache.h b/src/kiwano/render/TextureCache.h index 687501f5..6bf2bb7f 100644 --- a/src/kiwano/render/TextureCache.h +++ b/src/kiwano/render/TextureCache.h @@ -21,6 +21,7 @@ #pragma once #include #include +#include namespace kiwano { @@ -33,19 +34,17 @@ namespace kiwano * \~chinese * @brief 纹理缓存 */ -class KGE_API TextureCache final : Noncopyable +class KGE_API TextureCache final : public Singleton { + friend Singleton; + public: - TextureCache(); - - ~TextureCache(); - /// \~chinese - /// @brief 添加或获取纹理 + /// @brief 添加纹理缓存 void AddTexture(size_t key, TexturePtr texture); /// \~chinese - /// @brief 添加或获取GIF图像 + /// @brief 添加GIF图像缓存 void AddGifImage(size_t key, GifImagePtr gif); /// \~chinese @@ -68,6 +67,11 @@ public: /// @brief 清空缓存 void Clear(); + ~TextureCache(); + +private: + TextureCache(); + private: using TextureMap = UnorderedMap; TextureMap texture_cache_;