[deploy] add Font::Preload

This commit is contained in:
Nomango 2020-08-04 02:19:23 +08:00
parent 69f298211c
commit 31692c2a70
13 changed files with 528 additions and 378 deletions

View File

@ -89,6 +89,8 @@ public:
void SetTargetBitmap(_In_ ComPtr<ID2D1Bitmap1> target) override;
void ResetTextRenderingParams(_In_ HMONITOR monitor) override;
public:
unsigned long STDMETHODCALLTYPE AddRef();
@ -386,6 +388,18 @@ void D2DDeviceResources::SetTargetBitmap(ComPtr<ID2D1Bitmap1> target)
}
}
void D2DDeviceResources::ResetTextRenderingParams(HMONITOR monitor)
{
if (!dwrite_factory_ || device_context_)
return;
ComPtr<IDWriteRenderingParams> params;
if (SUCCEEDED(dwrite_factory_->CreateMonitorRenderingParams(monitor, &params)))
{
device_context_->SetTextRenderingParams(params.Get());
}
}
HRESULT D2DDeviceResources::CreateBitmapConverter(_Out_ ComPtr<IWICFormatConverter>& converter,
_In_opt_ ComPtr<IWICBitmapSource> source,
_In_ REFWICPixelFormatGUID format, WICBitmapDitherType dither,
@ -488,9 +502,9 @@ HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr<IDWriteTextFormat>& te
return E_UNEXPECTED;
ComPtr<IDWriteTextFormat> 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;

View File

@ -76,6 +76,8 @@ public:
virtual void SetTargetBitmap(_In_ ComPtr<ID2D1Bitmap1> target) = 0;
virtual void ResetTextRenderingParams(_In_ HMONITOR monitor) = 0;
inline ID2D1Factory1* GetFactory()
{
KGE_ASSERT(factory_);

View File

@ -39,16 +39,16 @@ public:
STDMETHOD(AddFilePaths)
(const Vector<String>& 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<String>& 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<String>& 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<String>& 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<String>& 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<Resource>& 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<Resource>&
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<Resource const*>(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<Resource const*>(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<Resource>& 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<Resource>& 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<Resource>& 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

View File

@ -19,6 +19,7 @@
// THE SOFTWARE.
#include <kiwano/utils/Logger.h>
#include <kiwano/event/Events.h>
#include <kiwano/platform/FileSystem.h>
#include <kiwano/platform/Application.h>
#include <kiwano/render/ShapeMaker.h>
@ -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<IDWriteFontCollection> system_collection;
if (SUCCEEDED(dwrite->GetSystemFontCollection(&system_collection, FALSE)))
{
Vector<String> family_names;
if (SUCCEEDED(d2d_res_->GetFontFamilyNames(family_names, system_collection)))
{
// dummy font
FontPtr font = MakePtr<Font>();
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<WindowMovedEvent>())
{
auto evt = ctx.evt->SafeCast<WindowMovedEvent>();
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<GifImage&>(gif), "Load GIF frame failed");
}
void RendererImpl::CreateFontCollection(Font& font, const String& file_path)
void RendererImpl::CreateFontCollection(Font& font, Vector<String>& 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<String> 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<String>& 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<String> 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<IDWriteFontCollection>(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<IDWriteFontCollection>(style.font);
WideString font_family;
if (style.font)

View File

@ -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<String>& family_names, const String& file_path) override;
void CreateFontCollection(Font& font, const Resource& res) override;
void CreateFontCollection(Font& font, Vector<String>& 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<ID2DDeviceResources> d2d_res_;
ComPtr<ID3DDeviceResources> d3d_res_;
HMONITOR monitor_;
};

View File

@ -20,34 +20,65 @@
#include <kiwano/render/Font.h>
#include <kiwano/render/Renderer.h>
#include <functional> // std::hash
namespace kiwano
{
FontPtr Font::Preload(const String& file)
{
FontPtr ptr = MakePtr<Font>();
try
size_t hash_code = std::hash<String>{}(file);
if (FontPtr ptr = FontCache::GetInstance().GetFont(hash_code))
{
Renderer::GetInstance().CreateFontCollection(*ptr, file);
return ptr;
}
catch (Exception&)
FontPtr ptr = MakePtr<Font>();
if (ptr)
{
return nullptr;
Vector<String> 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<Font>();
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<Font>();
if (ptr)
{
return nullptr;
Vector<String> 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

View File

@ -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<FontCache>
{
friend Singleton<FontCache>;
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<size_t, FontPtr>;
FontMap font_cache_;
using FontFamilyMap = UnorderedMap<String, FontPtr>;
FontFamilyMap font_family_cache_;
};
/** @} */
inline String Font::GetFamilyName() const

View File

@ -21,20 +21,40 @@
#include <kiwano/utils/Logger.h>
#include <kiwano/render/GifImage.h>
#include <kiwano/render/Renderer.h>
#include <kiwano/render/TextureCache.h>
#include <functional> // 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<String>{}(file_path);
if (GifImagePtr ptr = TextureCache::GetInstance().GetGifImage(hash_code))
{
return ptr;
}
GifImagePtr ptr = MakePtr<GifImage>();
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<GifImage>();
if (ptr && ptr->Load(res))
{
TextureCache::GetInstance().AddGifImage(hash_code, ptr);
}
return ptr;
}
GifImage::GifImage(const String& file_path)

View File

@ -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);

View File

@ -18,8 +18,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <functional> // std::hash
#include <kiwano/render/Renderer.h>
#include <kiwano/render/TextureCache.h>
#include <kiwano/event/WindowEvent.h>
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<String>{}(file_path);
if (TexturePtr ptr = texture_cache_.GetTexture(hash_code))
{
return ptr;
}
TexturePtr ptr = MakePtr<Texture>();
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<Texture>();
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<String>{}(file_path);
if (GifImagePtr ptr = texture_cache_.GetGifImage(hash_code))
{
return ptr;
}
GifImagePtr ptr = MakePtr<GifImage>();
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<GifImage>();
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

View File

@ -24,7 +24,6 @@
#include <kiwano/render/GifImage.h>
#include <kiwano/render/TextStyle.h>
#include <kiwano/render/RenderContext.h>
#include <kiwano/render/TextureCache.h>
#include <kiwano/platform/Window.h>
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<String>& 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<String>& 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_;
};
/** @} */

View File

@ -20,6 +20,8 @@
#include <kiwano/render/Renderer.h>
#include <kiwano/render/Texture.h>
#include <kiwano/render/TextureCache.h>
#include <functional> // std::hash
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
#include <kiwano/render/DirectX/NativePtr.h>
@ -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<String>{}(file_path);
if (TexturePtr ptr = TextureCache::GetInstance().GetTexture(hash_code))
{
return ptr;
}
TexturePtr ptr = MakePtr<Texture>();
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<Texture>();
if (ptr && ptr->Load(res))
{
TextureCache::GetInstance().AddTexture(hash_code, ptr);
}
return ptr;
}
Texture::Texture(const String& file_path)

View File

@ -21,6 +21,7 @@
#pragma once
#include <kiwano/render/GifImage.h>
#include <kiwano/render/Texture.h>
#include <kiwano/core/Singleton.h>
namespace kiwano
{
@ -33,19 +34,17 @@ namespace kiwano
* \~chinese
* @brief
*/
class KGE_API TextureCache final : Noncopyable
class KGE_API TextureCache final : public Singleton<TextureCache>
{
friend Singleton<TextureCache>;
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<size_t, TexturePtr>;
TextureMap texture_cache_;