From 088cfda0c574f01e9a5c1cee49651b8e3f7b6759 Mon Sep 17 00:00:00 2001 From: Nomango Date: Sun, 26 Jul 2020 00:22:32 +0800 Subject: [PATCH] add ObjectPolicy --- src/kiwano/2d/Actor.cpp | 12 +- src/kiwano/2d/Canvas.cpp | 18 ++- src/kiwano/2d/GifSprite.cpp | 20 ++- src/kiwano/2d/Sprite.cpp | 4 +- src/kiwano/2d/TextActor.cpp | 10 +- src/kiwano/base/ObjectBase.cpp | 101 +++++++++++++- src/kiwano/base/ObjectBase.h | 122 ++++++++++++++++- src/kiwano/base/RefPtr.h | 4 +- src/kiwano/core/Exception.h | 23 ---- src/kiwano/core/Time.cpp | 5 +- src/kiwano/platform/Runner.cpp | 2 +- src/kiwano/platform/Runner.h | 12 +- src/kiwano/platform/win32/ComPtr.hpp | 4 +- src/kiwano/platform/win32/WindowImpl.cpp | 1 - src/kiwano/platform/win32/libraries.cpp | 1 - .../render/DirectX/D2DDeviceResources.cpp | 110 ++++++++++++++- .../render/DirectX/D2DDeviceResources.h | 10 +- .../render/DirectX/FontCollectionLoader.h | 3 +- src/kiwano/render/DirectX/RendererImpl.cpp | 129 +++++------------- src/kiwano/render/DirectX/RendererImpl.h | 5 - src/kiwano/render/DirectX/helper.h | 3 +- src/kiwano/render/FrameSequence.cpp | 6 +- src/kiwano/render/GifImage.cpp | 2 + src/kiwano/utils/ConfigIni.cpp | 20 ++- src/kiwano/utils/Logger.h | 47 +++++-- src/kiwano/utils/ResourceCache.cpp | 9 +- 26 files changed, 484 insertions(+), 199 deletions(-) diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp index 70e31ca4..ecca2e7e 100644 --- a/src/kiwano/2d/Actor.cpp +++ b/src/kiwano/2d/Actor.cpp @@ -517,8 +517,6 @@ void Actor::SetRotation(float angle) void Actor::AddChild(ActorPtr child, int zorder) { - KGE_ASSERT(child && "Actor::AddChild failed, NULL pointer exception"); - if (child) { KGE_ASSERT(!child->parent_ && "Actor::AddChild failed, the actor to be added already has a parent"); @@ -545,6 +543,10 @@ void Actor::AddChild(ActorPtr child, int zorder) child->Reorder(); child->UpdateOpacity(); } + else + { + Fail("Actor::AddChild failed, NULL pointer exception"); + } } void Actor::AddChildren(const Vector& children) @@ -614,8 +616,6 @@ void Actor::RemoveFromParent() void Actor::RemoveChild(ActorPtr child) { - KGE_ASSERT(child && "Actor::RemoveChild failed, NULL pointer exception"); - if (children_.IsEmpty()) return; @@ -626,6 +626,10 @@ void Actor::RemoveChild(ActorPtr child) child->SetStage(nullptr); children_.Remove(child); } + else + { + Fail("Actor::RemoveChild failed, NULL pointer exception"); + } } void Actor::RemoveChildren(const String& child_name) diff --git a/src/kiwano/2d/Canvas.cpp b/src/kiwano/2d/Canvas.cpp index eb2179cc..b12f8a7d 100644 --- a/src/kiwano/2d/Canvas.cpp +++ b/src/kiwano/2d/Canvas.cpp @@ -26,7 +26,14 @@ namespace kiwano Canvas::Canvas(const Size& size) { - ResizeAndClear(size); + try + { + ResizeAndClear(size); + } + catch (Exception& e) + { + Fail(String("Canvas::ResizeAndClear failed: ") + e.what()); + } } RenderContextPtr Canvas::GetContext2D() const @@ -47,7 +54,14 @@ void Canvas::ResizeAndClear(Size size) texture_cached_ = MakePtr(); render_ctx_ = RenderContext::Create(*texture_cached_, size); - SetSize(render_ctx_->GetSize()); + if (render_ctx_) + { + SetSize(render_ctx_->GetSize()); + } + else + { + Fail("Canvas::ResizeAndClear failed"); + } } TexturePtr Canvas::ExportToTexture() const diff --git a/src/kiwano/2d/GifSprite.cpp b/src/kiwano/2d/GifSprite.cpp index 800d17a1..50eeb989 100644 --- a/src/kiwano/2d/GifSprite.cpp +++ b/src/kiwano/2d/GifSprite.cpp @@ -81,14 +81,24 @@ bool GifSprite::Load(GifImagePtr gif) frame_to_render_ = MakePtr(); frame_rt_ = RenderContext::Create(*frame_to_render_, frame_size); - SetSize(frame_rt_->GetSize()); - - if (gif_->GetFramesCount() > 0) + if (frame_rt_) { - ComposeNextFrame(); + SetSize(frame_rt_->GetSize()); + + if (gif_->GetFramesCount() > 0) + { + ComposeNextFrame(); + } + return true; + } + else + { + Fail("GifSprite::Load failed: RenderContext::Create returns null"); + return false; } - return true; } + + Fail("GifSprite::Load failed: GifImage is invalid"); return false; } diff --git a/src/kiwano/2d/Sprite.cpp b/src/kiwano/2d/Sprite.cpp index 3518bee6..3298be2f 100644 --- a/src/kiwano/2d/Sprite.cpp +++ b/src/kiwano/2d/Sprite.cpp @@ -58,11 +58,12 @@ Sprite::~Sprite() {} bool Sprite::Load(const String& file_path, bool autoresize) { FramePtr frame = MakePtr(file_path); - if (frame) + if (frame && frame->IsValid()) { SetFrame(frame, autoresize); return true; } + Fail("Sprite::Load failed"); return false; } @@ -74,6 +75,7 @@ bool Sprite::Load(const Resource& res, bool autoresize) SetFrame(frame, autoresize); return true; } + Fail("Sprite::Load failed"); return false; } diff --git a/src/kiwano/2d/TextActor.cpp b/src/kiwano/2d/TextActor.cpp index 1f7ad180..9e4e8305 100644 --- a/src/kiwano/2d/TextActor.cpp +++ b/src/kiwano/2d/TextActor.cpp @@ -60,7 +60,15 @@ void TextActor::SetText(const String& text) { layout_ = MakePtr(); } - layout_->Reset(text, style_); + + try + { + layout_->Reset(text, style_); + } + catch (SystemError& e) + { + Fail(String("TextActor::SetText failed: ") + e.what()); + } } void TextActor::SetStyle(const TextStyle& style) diff --git a/src/kiwano/base/ObjectBase.cpp b/src/kiwano/base/ObjectBase.cpp index 99c05f9e..b83c23d1 100644 --- a/src/kiwano/base/ObjectBase.cpp +++ b/src/kiwano/base/ObjectBase.cpp @@ -18,26 +18,74 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#include +#include #include #include #include -#include namespace kiwano { namespace { -bool tracing_leaks = false; -Vector tracing_objects; -uint32_t last_object_id = 0; +bool tracing_leaks = false; +Vector tracing_objects; +std::atomic last_object_id = 0; +ObjectPolicyFunc object_policy_ = ObjectPolicy::ErrorLog(); } // namespace + + +ObjectFailException::ObjectFailException(ObjectBase* obj, const ObjectStatus& status) + : obj_(obj) + , status_(status) +{ +} + +char const* ObjectFailException::what() const +{ + return status_.msg.empty() ? "Object operation failed" : status_.msg.c_str(); +} + +ObjectPolicyFunc ObjectPolicy::WarnLog() +{ + return [](ObjectBase* obj, const ObjectStatus& status) + { + if (!obj->IsValid()) + { + KGE_WARNF("Object operation failed: obj(%p), code(%d), msg(%s)", obj, status.code, status.msg.c_str()); + } + }; +} + +ObjectPolicyFunc ObjectPolicy::ErrorLog() +{ + return [](ObjectBase* obj, const ObjectStatus& status) + { + if (!obj->IsValid()) + { + KGE_ERRORF("Object operation failed: obj(%p), code(%d), msg(%s)", obj, status.code, status.msg.c_str()); + } + }; +} + +ObjectPolicyFunc ObjectPolicy::Exception() +{ + return [](ObjectBase* obj, const ObjectStatus& status) + { + if (!obj->IsValid()) + { + throw ObjectFailException(obj, status); + } + }; +} + ObjectBase::ObjectBase() : tracing_leak_(false) , name_(nullptr) - , user_data_() + , user_data_(nullptr) , id_(++last_object_id) { #ifdef KGE_DEBUG @@ -58,12 +106,12 @@ ObjectBase::~ObjectBase() #endif } -const Any& ObjectBase::GetUserData() const +void* ObjectBase::GetUserData() const { return user_data_; } -void ObjectBase::SetUserData(const Any& data) +void ObjectBase::SetUserData(void* data) { user_data_ = data; } @@ -101,6 +149,45 @@ void ObjectBase::DoDeserialize(Deserializer* deserializer) SetName(name); } +bool ObjectBase::IsValid() const +{ + return status_.Success(); +} + +ObjectStatus ObjectBase::GetStatus() const +{ + return status_; +} + +void ObjectBase::SetStatus(const ObjectStatus& status) +{ + status_.msg = status.msg; + if (status_.code != status.code) + { + status_.code = status.code; + + if (object_policy_) + { + object_policy_(this, status_); + } + } +} + +void ObjectBase::Fail(const String& msg, int code) +{ + SetStatus(ObjectStatus{ code, msg }); +} + +void ObjectBase::ClearStatus() +{ + status_ = ObjectStatus{}; +} + +void ObjectBase::SetObjectPolicy(const ObjectPolicyFunc& policy) +{ + object_policy_ = policy; +} + bool ObjectBase::IsTracingLeaks() { return tracing_leaks; diff --git a/src/kiwano/base/ObjectBase.h b/src/kiwano/base/ObjectBase.h index 2ccb785a..dc3361d7 100644 --- a/src/kiwano/base/ObjectBase.h +++ b/src/kiwano/base/ObjectBase.h @@ -21,6 +21,7 @@ #pragma once #include #include +#include #include #include #include @@ -29,6 +30,89 @@ namespace kiwano { KGE_DECLARE_SMART_PTR(ObjectBase); +/** + * \~chinese + * @brief 对象状态 + */ +struct ObjectStatus +{ + int code = 0; ///< 状态码,等于 0 时为成功状态,否则为失败状态 + String msg; ///< 状态信息 + + /// \~chinese + /// @brief 对象状态是否成功 + inline bool Success() const + { + return this->code == 0; + } + + /// \~chinese + /// @brief 对象失败状态 + static const int fail = -1; +}; + +/** + * \~chinese + * @brief 对象失败状态异常 + */ +class ObjectFailException : public Exception +{ +public: + ObjectFailException(ObjectBase* obj, const ObjectStatus& status); + + /// \~chinese + /// @brief 获取失败的对象指针 + inline ObjectBase* GetObj() const + { + return obj_; + } + + /// \~chinese + /// @brief 获取对象状态 + inline ObjectStatus GetStatus() const + { + return status_; + } + + virtual char const* what() const override; + +private: + ObjectBase* obj_; + ObjectStatus status_; +}; + +/** + * \~chinese + * @brief 对象处理策略方法 + */ +typedef Function ObjectPolicyFunc; + +/** + * \~chinese + * @brief 对象处理策略 + */ +struct ObjectPolicy +{ + /// \~chinese + /// @brief 忽略对象失败状态 + static inline ObjectPolicyFunc Ignore() + { + return nullptr; + } + + /// \~chinese + /// @brief 在对象状态变为失败时打印警告日志 + static ObjectPolicyFunc WarnLog(); + + /// \~chinese + /// @brief 在对象状态变为失败时打印错误日志(默认策略) + static ObjectPolicyFunc ErrorLog(); + + /// \~chinese + /// @brief 在对象状态变为失败时抛出 ObjectFailException + static ObjectPolicyFunc Exception(); +}; + /** * \~chinese * @brief 基础对象 @@ -59,15 +143,15 @@ public: /// \~chinese /// @brief 获取用户数据 - const Any& GetUserData() const; + void* GetUserData() const; /// \~chinese /// @brief 设置用户数据 - void SetUserData(const Any& data); + void SetUserData(void* data); /// \~chinese /// @brief 获取对象ID - uint32_t GetObjectID() const; + uint64_t GetObjectID() const; /// \~chinese /// @brief 序列化 @@ -77,6 +161,30 @@ public: /// @brief 反序列化 void DoDeserialize(Deserializer* deserializer) override; + /// \~chinese + /// @brief 判断对象是否有效 + virtual bool IsValid() const; + + /// \~chinese + /// @brief 获取对象状态 + ObjectStatus GetStatus() const; + + /// \~chinese + /// @brief 设置对象状态 + void SetStatus(const ObjectStatus& status); + + /// \~chinese + /// @brief 将对象标记为失败状态 + void Fail(const String& msg, int code = ObjectStatus::fail); + + /// \~chinese + /// @brief 清除对象状态 + void ClearStatus(); + + /// \~chinese + /// @brief 设置对象处理策略 + static void SetObjectPolicy(const ObjectPolicyFunc& policy); + public: /// \~chinese /// @brief 是否启用了内存泄漏追踪 @@ -104,11 +212,13 @@ private: static void RemoveObjectFromTracingList(ObjectBase*); private: - const uint32_t id_; + const uint64_t id_; bool tracing_leak_; String* name_; - Any user_data_; + void* user_data_; + + ObjectStatus status_; }; inline String ObjectBase::GetName() const @@ -123,7 +233,7 @@ inline bool ObjectBase::IsName(const String& name) const return name_ ? (*name_ == name) : name.empty(); } -inline uint32_t ObjectBase::GetObjectID() const +inline uint64_t ObjectBase::GetObjectID() const { return id_; } diff --git a/src/kiwano/base/RefPtr.h b/src/kiwano/base/RefPtr.h index 93a184f5..b78c9bc9 100644 --- a/src/kiwano/base/RefPtr.h +++ b/src/kiwano/base/RefPtr.h @@ -29,13 +29,13 @@ namespace kiwano /// @brief 默认的智能指针引用计数策略 struct DefaultRefPtrPolicy { - static inline void Retain(RefObject* ptr) + inline void Retain(RefObject* ptr) { if (ptr) ptr->Retain(); } - static inline void Release(RefObject* ptr) + inline void Release(RefObject* ptr) { if (ptr) ptr->Release(); diff --git a/src/kiwano/core/Exception.h b/src/kiwano/core/Exception.h index 45c3fe69..c12b1f13 100644 --- a/src/kiwano/core/Exception.h +++ b/src/kiwano/core/Exception.h @@ -20,26 +20,9 @@ #pragma once #include -#include #include #include -#define KGE_THROW(MESSAGE) \ - do \ - { \ - KGE_ERRORF("An exception occurred: %s", MESSAGE); \ - kiwano::StackTracer().Print(); \ - throw kiwano::RuntimeError(MESSAGE); \ - } while (0) - -#define KGE_THROW_SYSTEM_ERROR(ERRCODE, MESSAGE) \ - do \ - { \ - KGE_ERRORF("An exception occurred (%#x): %s", ERRCODE, MESSAGE); \ - kiwano::StackTracer().Print(); \ - throw kiwano::SystemError(std::error_code(kiwano::error_enum(ERRCODE)), MESSAGE); \ - } while (0) - namespace kiwano { @@ -104,12 +87,6 @@ inline std::error_condition make_error_condition(kiwano::error_enum errc) noexce return std::error_condition(static_cast(errc), kiwano::com_category()); } -#define KGE_THROW_IF_FAILED(HR, MESSAGE) \ - if (FAILED(HR)) \ - { \ - KGE_THROW_SYSTEM_ERROR(HR, MESSAGE); \ - } - } // namespace kiwano #endif // KGE_PLATFORM_WINDOWS diff --git a/src/kiwano/core/Time.cpp b/src/kiwano/core/Time.cpp index eafaccf0..57c12ac0 100644 --- a/src/kiwano/core/Time.cpp +++ b/src/kiwano/core/Time.cpp @@ -18,13 +18,12 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include -#include -#include #include #include #include #include +#include +#include namespace kiwano { diff --git a/src/kiwano/platform/Runner.cpp b/src/kiwano/platform/Runner.cpp index 869da1ac..35779f8f 100644 --- a/src/kiwano/platform/Runner.cpp +++ b/src/kiwano/platform/Runner.cpp @@ -28,7 +28,7 @@ namespace kiwano { -Runner::Runner(Settings settings) +Runner::Runner(const Settings& settings) : settings_(settings) { } diff --git a/src/kiwano/platform/Runner.h b/src/kiwano/platform/Runner.h index f48ce828..e63a6338 100644 --- a/src/kiwano/platform/Runner.h +++ b/src/kiwano/platform/Runner.h @@ -67,7 +67,7 @@ public: /// \~chinese /// @brief 创建程序运行器 /// @param main_window 主窗口 - Runner(Settings settings); + Runner(const Settings& settings); virtual ~Runner(); @@ -92,16 +92,12 @@ public: /// @param dt 时间间隔 /// @details 重载该函数以控制程序主循环 /// @return 返回false退出主循环,否则继续运行主循环 - virtual bool MainLoop(Duration dt); + bool MainLoop(Duration dt); /// \~chinese /// @brief 获取窗口 WindowPtr GetWindow() const; - /// \~chinese - /// @brief 设置窗口 - void SetWindow(WindowPtr window); - /// \~chinese /// @brief 获取设置 Settings GetSettings() const; @@ -119,6 +115,10 @@ protected: /// @brief 修改设置 void SetSettings(Settings settings); + /// \~chinese + /// @brief 设置窗口 + void SetWindow(WindowPtr window); + private: friend class Application; diff --git a/src/kiwano/platform/win32/ComPtr.hpp b/src/kiwano/platform/win32/ComPtr.hpp index 72879900..9fe892ee 100644 --- a/src/kiwano/platform/win32/ComPtr.hpp +++ b/src/kiwano/platform/win32/ComPtr.hpp @@ -28,13 +28,13 @@ namespace kiwano { struct ComPtrPolicy { - static inline void Retain(IUnknown* ptr) + inline void Retain(IUnknown* ptr) { if (ptr) ptr->AddRef(); } - static inline void Release(IUnknown* ptr) + inline void Release(IUnknown* ptr) { if (ptr) ptr->Release(); diff --git a/src/kiwano/platform/win32/WindowImpl.cpp b/src/kiwano/platform/win32/WindowImpl.cpp index e069005f..2dac03be 100644 --- a/src/kiwano/platform/win32/WindowImpl.cpp +++ b/src/kiwano/platform/win32/WindowImpl.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/src/kiwano/platform/win32/libraries.cpp b/src/kiwano/platform/win32/libraries.cpp index 4505ee66..c8da8c3d 100644 --- a/src/kiwano/platform/win32/libraries.cpp +++ b/src/kiwano/platform/win32/libraries.cpp @@ -18,7 +18,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include #include #include diff --git a/src/kiwano/render/DirectX/D2DDeviceResources.cpp b/src/kiwano/render/DirectX/D2DDeviceResources.cpp index 2062ac2d..1fb786b9 100644 --- a/src/kiwano/render/DirectX/D2DDeviceResources.cpp +++ b/src/kiwano/render/DirectX/D2DDeviceResources.cpp @@ -70,6 +70,12 @@ public: HRESULT CreateTextLayout(_Out_ ComPtr& text_layout, _In_ LPCWSTR text, UINT32 length, _In_ ComPtr text_format) override; + HRESULT CreateFontCollectionFromFiles(_Out_ ComPtr& font_collection, + const Vector& file_paths) override; + + HRESULT CreateFontCollectionFromResources(_Out_ ComPtr& font_collection, + const Vector& resources) override; + HRESULT SetDpi(float dpi) override; HRESULT SetLogicalSize(float width, float height) override; @@ -93,6 +99,10 @@ private: float dpi_; ComPtr dxgi_swap_chain_; + + ComPtr font_collection_loader_; + ComPtr res_font_file_loader_; + ComPtr res_font_collection_loader_; }; @@ -173,13 +183,34 @@ STDMETHODIMP D2DDeviceResources::QueryInterface(const IID& riid, void** object) void D2DDeviceResources::DiscardResources() { - factory_.Reset(); - device_.Reset(); - device_context_.Reset(); - target_bitmap_.Reset(); + if (dwrite_factory_) + { + if (font_collection_loader_) + { + dwrite_factory_->UnregisterFontCollectionLoader(font_collection_loader_.Get()); + font_collection_loader_.Reset(); + } + + if (res_font_file_loader_) + { + dwrite_factory_->UnregisterFontFileLoader(res_font_file_loader_.Get()); + res_font_file_loader_.Reset(); + } + + if (res_font_collection_loader_) + { + dwrite_factory_->UnregisterFontCollectionLoader(res_font_collection_loader_.Get()); + res_font_collection_loader_.Reset(); + } + } + + target_bitmap_.Reset(); + device_context_.Reset(); + device_.Reset(); - imaging_factory_.Reset(); dwrite_factory_.Reset(); + imaging_factory_.Reset(); + factory_.Reset(); } HRESULT D2DDeviceResources::CreateDeviceIndependentResources() @@ -225,6 +256,38 @@ HRESULT D2DDeviceResources::CreateDeviceIndependentResources() dwrite_factory_ = dwrite_factory; } } + + // FontFileLoader and FontCollectionLoader + if (SUCCEEDED(hr)) + { + hr = IFontCollectionLoader::Create(&font_collection_loader_); + + if (SUCCEEDED(hr)) + { + hr = dwrite_factory->RegisterFontCollectionLoader(font_collection_loader_.Get()); + } + } + + // ResourceFontFileLoader and ResourceFontCollectionLoader + if (SUCCEEDED(hr)) + { + hr = IResourceFontFileLoader::Create(&res_font_file_loader_); + + if (SUCCEEDED(hr)) + { + hr = dwrite_factory->RegisterFontFileLoader(res_font_file_loader_.Get()); + } + + if (SUCCEEDED(hr)) + { + hr = IResourceFontCollectionLoader::Create(&res_font_collection_loader_, res_font_file_loader_.Get()); + + if (SUCCEEDED(hr)) + { + hr = dwrite_factory->RegisterFontCollectionLoader(res_font_collection_loader_.Get()); + } + } + } return hr; } @@ -450,6 +513,43 @@ HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr& te return hr; } +HRESULT D2DDeviceResources::CreateFontCollectionFromFiles(ComPtr& font_collection, + const Vector& file_paths) +{ + if (!dwrite_factory_ || !font_collection_loader_) + return E_UNEXPECTED; + + LPVOID key = nullptr; + uint32_t key_size = 0; + + HRESULT hr = font_collection_loader_->AddFilePaths(file_paths, &key, &key_size); + + if (SUCCEEDED(hr)) + { + hr = + dwrite_factory_->CreateCustomFontCollection(font_collection_loader_.Get(), key, key_size, &font_collection); + } + return hr; +} + +HRESULT D2DDeviceResources::CreateFontCollectionFromResources(ComPtr& font_collection, + const Vector& resources) +{ + if (!dwrite_factory_ || !res_font_collection_loader_) + return E_UNEXPECTED; + + LPVOID key = nullptr; + uint32_t key_size = 0; + + HRESULT hr = res_font_collection_loader_->AddResources(resources, &key, &key_size); + + if (SUCCEEDED(hr)) + { + hr = dwrite_factory_->CreateCustomFontCollection(res_font_collection_loader_.Get(), key, key_size, &font_collection); + } + return hr; +} + } // namespace directx } // namespace graphics } // namespace kiwano diff --git a/src/kiwano/render/DirectX/D2DDeviceResources.h b/src/kiwano/render/DirectX/D2DDeviceResources.h index 4c57f263..ef6adf0b 100644 --- a/src/kiwano/render/DirectX/D2DDeviceResources.h +++ b/src/kiwano/render/DirectX/D2DDeviceResources.h @@ -20,9 +20,7 @@ #pragma once #include -#include -#include -#include +#include namespace kiwano { @@ -58,6 +56,12 @@ public: virtual HRESULT CreateTextLayout(_Out_ ComPtr & text_layout, _In_ LPCWSTR text, UINT32 length, _In_ ComPtr text_format) = 0; + virtual HRESULT CreateFontCollectionFromFiles(_Out_ ComPtr & font_collection, + const Vector& file_paths) = 0; + + virtual HRESULT CreateFontCollectionFromResources(_Out_ ComPtr & font_collection, + const Vector& resources) = 0; + virtual HRESULT SetDpi(float dpi) = 0; virtual HRESULT SetLogicalSize(float width, float height) = 0; diff --git a/src/kiwano/render/DirectX/FontCollectionLoader.h b/src/kiwano/render/DirectX/FontCollectionLoader.h index b48e1330..518fd426 100644 --- a/src/kiwano/render/DirectX/FontCollectionLoader.h +++ b/src/kiwano/render/DirectX/FontCollectionLoader.h @@ -20,7 +20,8 @@ #pragma once #include -#include +#include +#include namespace kiwano { diff --git a/src/kiwano/render/DirectX/RendererImpl.cpp b/src/kiwano/render/DirectX/RendererImpl.cpp index 8666e5f8..7a9eb429 100644 --- a/src/kiwano/render/DirectX/RendererImpl.cpp +++ b/src/kiwano/render/DirectX/RendererImpl.cpp @@ -18,7 +18,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include #include #include #include @@ -27,7 +26,11 @@ #include #include -#include +#define KGE_SET_STATUS_IF_FAILED(ERRCODE, OBJ, MESSAGE) \ + if (FAILED(ERRCODE)) \ + { \ + OBJ.Fail(strings::Format("An exception occurred (%#x): %s", ERRCODE, MESSAGE)); \ + } namespace kiwano { @@ -93,7 +96,6 @@ void RendererImpl::MakeContextForWindow(WindowPtr window) } } - // Initialize other device resources if (SUCCEEDED(hr)) { @@ -106,38 +108,6 @@ void RendererImpl::MakeContextForWindow(WindowPtr window) } } - // FontFileLoader and FontCollectionLoader - if (SUCCEEDED(hr)) - { - hr = IFontCollectionLoader::Create(&font_collection_loader_); - - if (SUCCEEDED(hr)) - { - hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(font_collection_loader_.Get()); - } - } - - // ResourceFontFileLoader and ResourceFontCollectionLoader - if (SUCCEEDED(hr)) - { - hr = IResourceFontFileLoader::Create(&res_font_file_loader_); - - if (SUCCEEDED(hr)) - { - hr = d2d_res_->GetDWriteFactory()->RegisterFontFileLoader(res_font_file_loader_.Get()); - } - - if (SUCCEEDED(hr)) - { - hr = IResourceFontCollectionLoader::Create(&res_font_collection_loader_, res_font_file_loader_.Get()); - - if (SUCCEEDED(hr)) - { - hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(res_font_collection_loader_.Get()); - } - } - } - KGE_THROW_IF_FAILED(hr, "Create render resources failed"); } @@ -147,14 +117,9 @@ void RendererImpl::Destroy() if (d2d_res_) { - d2d_res_->GetDWriteFactory()->UnregisterFontFileLoader(res_font_file_loader_.Get()); - res_font_file_loader_.Reset(); - - d2d_res_->GetDWriteFactory()->UnregisterFontCollectionLoader(res_font_collection_loader_.Get()); - res_font_collection_loader_.Reset(); - render_ctx_.Reset(); d2d_res_->DiscardResources(); + d2d_res_.Reset(); } if (d3d_res_) @@ -243,10 +208,7 @@ void RendererImpl::CreateTexture(Texture& texture, const String& file_path) } } - if (FAILED(hr)) - { - KGE_THROW_IF_FAILED(hr, "Load texture failed"); - } + KGE_SET_STATUS_IF_FAILED(hr, texture, "Load texture failed"); } void RendererImpl::CreateTexture(Texture& texture, const Resource& resource) @@ -298,10 +260,7 @@ void RendererImpl::CreateTexture(Texture& texture, const Resource& resource) } } - if (FAILED(hr)) - { - KGE_WARNF("Load texture failed with HRESULT of %08X!", hr); - } + KGE_SET_STATUS_IF_FAILED(hr, texture, "Load texture failed"); } void RendererImpl::CreateGifImage(GifImage& gif, const String& file_path) @@ -331,10 +290,7 @@ void RendererImpl::CreateGifImage(GifImage& gif, const String& file_path) } } - if (FAILED(hr)) - { - KGE_WARNF("Load GIF texture failed with HRESULT of %08X!", hr); - } + KGE_SET_STATUS_IF_FAILED(hr, gif, "Load GIF texture failed"); } void RendererImpl::CreateGifImage(GifImage& gif, const Resource& resource) @@ -363,10 +319,7 @@ void RendererImpl::CreateGifImage(GifImage& gif, const Resource& resource) } } - if (FAILED(hr)) - { - KGE_WARNF("Load GIF texture failed with HRESULT of %08X!", hr); - } + KGE_SET_STATUS_IF_FAILED(hr, gif, "Load GIF texture failed"); } void RendererImpl::CreateGifImageFrame(GifImage::Frame& frame, const GifImage& gif, size_t frame_index) @@ -527,10 +480,7 @@ void RendererImpl::CreateGifImageFrame(GifImage::Frame& frame, const GifImage& g } } - if (FAILED(hr)) - { - KGE_WARNF("Load GIF frame failed with HRESULT of %08X!", hr); - } + KGE_SET_STATUS_IF_FAILED(hr, const_cast(gif), "Load GIF frame failed"); } void RendererImpl::CreateFontCollection(Font& font, const String& file_path) @@ -552,26 +502,18 @@ void RendererImpl::CreateFontCollection(Font& font, const String& file_path) if (SUCCEEDED(hr)) { - LPVOID key = nullptr; - uint32_t key_size = 0; - String full_path = FileSystem::GetInstance().GetFullPathForFile(file_path); + String full_path = FileSystem::GetInstance().GetFullPathForFile(file_path); - hr = font_collection_loader_->AddFilePaths({ full_path }, &key, &key_size); + ComPtr font_collection; + hr = d2d_res_->CreateFontCollectionFromFiles(font_collection, { full_path }); if (SUCCEEDED(hr)) { - ComPtr font_collection; - hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection(font_collection_loader_.Get(), key, key_size, - &font_collection); - - if (SUCCEEDED(hr)) - { - NativePtr::Set(font, font_collection); - } + NativePtr::Set(font, font_collection); } } - KGE_THROW_IF_FAILED(hr, "Create font collection failed"); + KGE_SET_STATUS_IF_FAILED(hr, font, "Create font collection failed"); } void RendererImpl::CreateFontCollection(Font& font, const Resource& res) @@ -584,25 +526,16 @@ void RendererImpl::CreateFontCollection(Font& font, const Resource& res) if (SUCCEEDED(hr)) { - LPVOID key = nullptr; - uint32_t key_size = 0; - - hr = res_font_collection_loader_->AddResources(Vector{ res }, &key, &key_size); + ComPtr font_collection; + hr = d2d_res_->CreateFontCollectionFromResources(font_collection, Vector{ res }); if (SUCCEEDED(hr)) { - ComPtr font_collection; - hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection(res_font_collection_loader_.Get(), key, - key_size, &font_collection); - - if (SUCCEEDED(hr)) - { - NativePtr::Set(font, font_collection); - } + NativePtr::Set(font, font_collection); } } - KGE_THROW_IF_FAILED(hr, "Create font collection failed"); + KGE_SET_STATUS_IF_FAILED(hr, font, "Create font collection failed"); } void RendererImpl::CreateTextLayout(TextLayout& layout, const String& content, const TextStyle& style) @@ -646,7 +579,7 @@ void RendererImpl::CreateTextLayout(TextLayout& layout, const String& content, c } } - KGE_THROW_IF_FAILED(hr, "Create text layout failed"); + KGE_SET_STATUS_IF_FAILED(hr, layout, "Create text layout failed"); } void RendererImpl::CreateLineShape(Shape& shape, const Point& begin_pos, const Point& end_pos) @@ -682,7 +615,7 @@ void RendererImpl::CreateLineShape(Shape& shape, const Point& begin_pos, const P } } - KGE_THROW_IF_FAILED(hr, "Create ID2D1PathGeometry failed"); + KGE_SET_STATUS_IF_FAILED(hr, shape, "Create ID2D1PathGeometry failed"); } void RendererImpl::CreateRectShape(Shape& shape, const Rect& rect) @@ -704,7 +637,7 @@ void RendererImpl::CreateRectShape(Shape& shape, const Rect& rect) NativePtr::Set(shape, output); } - KGE_THROW_IF_FAILED(hr, "Create ID2D1RectangleGeometry failed"); + KGE_SET_STATUS_IF_FAILED(hr, shape, "Create ID2D1RectangleGeometry failed"); } void RendererImpl::CreateRoundedRectShape(Shape& shape, const Rect& rect, const Vec2& radius) @@ -727,7 +660,7 @@ void RendererImpl::CreateRoundedRectShape(Shape& shape, const Rect& rect, const NativePtr::Set(shape, output); } - KGE_THROW_IF_FAILED(hr, "Create ID2D1RoundedRectangleGeometry failed"); + KGE_SET_STATUS_IF_FAILED(hr, shape, "Create ID2D1RoundedRectangleGeometry failed"); } void RendererImpl::CreateEllipseShape(Shape& shape, const Point& center, const Vec2& radius) @@ -750,7 +683,7 @@ void RendererImpl::CreateEllipseShape(Shape& shape, const Point& center, const V NativePtr::Set(shape, output); } - KGE_THROW_IF_FAILED(hr, "Create ID2D1EllipseGeometry failed"); + KGE_SET_STATUS_IF_FAILED(hr, shape, "Create ID2D1EllipseGeometry failed"); } void RendererImpl::CreateShapeSink(ShapeMaker& maker) @@ -775,7 +708,7 @@ void RendererImpl::CreateShapeSink(ShapeMaker& maker) maker.SetShape(shape); } } - KGE_THROW_IF_FAILED(hr, "Create ID2D1PathGeometry failed"); + KGE_SET_STATUS_IF_FAILED(hr, maker, "Create ID2D1PathGeometry failed"); } void RendererImpl::CreateBrush(Brush& brush, const Color& color) @@ -809,7 +742,7 @@ void RendererImpl::CreateBrush(Brush& brush, const Color& color) } } - KGE_THROW_IF_FAILED(hr, "Create ID2D1SolidBrush failed"); + KGE_SET_STATUS_IF_FAILED(hr, brush, "Create ID2D1SolidBrush failed"); } void RendererImpl::CreateBrush(Brush& brush, const LinearGradientStyle& style) @@ -841,7 +774,7 @@ void RendererImpl::CreateBrush(Brush& brush, const LinearGradientStyle& style) } } - KGE_THROW_IF_FAILED(hr, "Create ID2D1LinearGradientBrush failed"); + KGE_SET_STATUS_IF_FAILED(hr, brush, "Create ID2D1LinearGradientBrush failed"); } void RendererImpl::CreateBrush(Brush& brush, const RadialGradientStyle& style) @@ -874,7 +807,7 @@ void RendererImpl::CreateBrush(Brush& brush, const RadialGradientStyle& style) } } - KGE_THROW_IF_FAILED(hr, "Create ID2D1RadialGradientBrush failed"); + KGE_SET_STATUS_IF_FAILED(hr, brush, "Create ID2D1RadialGradientBrush failed"); } void RendererImpl::CreateBrush(Brush& brush, TexturePtr texture) @@ -901,7 +834,7 @@ void RendererImpl::CreateBrush(Brush& brush, TexturePtr texture) } } - KGE_THROW_IF_FAILED(hr, "Create ID2D1RadialGradientBrush failed"); + KGE_SET_STATUS_IF_FAILED(hr, brush, "Create ID2D1RadialGradientBrush failed"); } void RendererImpl::CreateStrokeStyle(StrokeStyle& stroke_style) @@ -940,7 +873,7 @@ void RendererImpl::CreateStrokeStyle(StrokeStyle& stroke_style) } } - KGE_THROW_IF_FAILED(hr, "Create ID2D1StrokeStyle failed"); + KGE_SET_STATUS_IF_FAILED(hr, stroke_style, "Create ID2D1StrokeStyle failed"); } RenderContextPtr RendererImpl::CreateTextureRenderContext(Texture& texture, const Size* desired_size) diff --git a/src/kiwano/render/DirectX/RendererImpl.h b/src/kiwano/render/DirectX/RendererImpl.h index dfce0ea0..23a9cd65 100644 --- a/src/kiwano/render/DirectX/RendererImpl.h +++ b/src/kiwano/render/DirectX/RendererImpl.h @@ -21,10 +21,8 @@ #pragma once #include #include -#include #include - namespace kiwano { @@ -94,9 +92,6 @@ private: ComPtr d2d_res_; ComPtr d3d_res_; - ComPtr font_collection_loader_; - ComPtr res_font_file_loader_; - ComPtr res_font_collection_loader_; }; diff --git a/src/kiwano/render/DirectX/helper.h b/src/kiwano/render/DirectX/helper.h index 5461cac8..51ef440e 100644 --- a/src/kiwano/render/DirectX/helper.h +++ b/src/kiwano/render/DirectX/helper.h @@ -20,10 +20,11 @@ #pragma once #include -#include +#include #include #include #include +#include namespace kiwano { diff --git a/src/kiwano/render/FrameSequence.cpp b/src/kiwano/render/FrameSequence.cpp index ec895f02..8a8add29 100644 --- a/src/kiwano/render/FrameSequence.cpp +++ b/src/kiwano/render/FrameSequence.cpp @@ -41,12 +41,14 @@ FrameSequence::~FrameSequence() {} void FrameSequence::AddFrame(FramePtr frame) { - KGE_ASSERT(frame && "FrameSequence::Add failed, NULL pointer exception"); - if (frame) { frames_.push_back(frame); } + else + { + Fail("FrameSequence::Add failed, NULL pointer exception"); + } } void FrameSequence::AddFrames(const Vector& frames) diff --git a/src/kiwano/render/GifImage.cpp b/src/kiwano/render/GifImage.cpp index 53eebf62..0ac90987 100644 --- a/src/kiwano/render/GifImage.cpp +++ b/src/kiwano/render/GifImage.cpp @@ -53,6 +53,7 @@ bool GifImage::Load(const String& file_path) // Clear data ResetNativePointer(); + Fail("GifImage::Load failed"); } return false; } @@ -68,6 +69,7 @@ bool GifImage::Load(const Resource& res) // Clear data ResetNativePointer(); + Fail("GifImage::Load failed"); } return false; } diff --git a/src/kiwano/utils/ConfigIni.cpp b/src/kiwano/utils/ConfigIni.cpp index 12503650..da728718 100644 --- a/src/kiwano/utils/ConfigIni.cpp +++ b/src/kiwano/utils/ConfigIni.cpp @@ -109,6 +109,8 @@ bool ConfigIni::Load(const String& file_path) { return Load(ifs); } + + Fail("ConfigIni::Load failed"); return false; } @@ -121,13 +123,13 @@ bool ConfigIni::Load(std::istream& istream) { ParseLine(line, §ion); } - return true; } - catch (Exception) + catch (RuntimeError& e) { + Fail(String("ConfigIni::Load failed: ") + e.what()); return false; } - return false; + return true; } bool ConfigIni::Save(const String& file_path) @@ -138,6 +140,7 @@ bool ConfigIni::Save(const String& file_path) { return Save(ofs); } + Fail("ConfigIni::Save failed"); return false; } @@ -165,7 +168,12 @@ bool ConfigIni::Save(std::ostream& os) os << std::endl; } } - return !os.fail(); + if (os.fail()) + { + Fail("ConfigIni::Save failed"); + return false; + } + return true; } ConfigIni::SectionMap ConfigIni::GetSectionMap() const @@ -367,7 +375,7 @@ void ConfigIni::ParseLine(StringView line, String* section) { auto name = parser.GetSectionName(); if (name.IsEmpty()) - throw Exception("Empty section name"); + throw RuntimeError("Empty section name"); *section = name; return; } @@ -375,7 +383,7 @@ void ConfigIni::ParseLine(StringView line, String* section) StringView key, value; if (!parser.GetKeyValue(&key, &value)) { - throw Exception("Parse key-value failed"); + throw RuntimeError("Parse key-value failed"); } SetString(*section, key, value); } diff --git a/src/kiwano/utils/Logger.h b/src/kiwano/utils/Logger.h index 443ea54a..81bf0a7e 100644 --- a/src/kiwano/utils/Logger.h +++ b/src/kiwano/utils/Logger.h @@ -19,12 +19,13 @@ // THE SOFTWARE. #pragma once -#include -#include #include #include #include #include +#include +#include +#include #ifndef KGE_DEBUG_LOG #ifdef KGE_DEBUG @@ -74,12 +75,42 @@ #define KGE_ERRORF(FORMAT, ...) ::kiwano::Logger::GetInstance().Logf(::kiwano::LogLevel::Error, FORMAT, __VA_ARGS__) #endif +#ifndef KGE_THROW +#define KGE_THROW(MESSAGE) \ + do \ + { \ + KGE_ERRORF("An exception occurred: %s", MESSAGE); \ + kiwano::StackTracer().Print(); \ + throw kiwano::RuntimeError(MESSAGE); \ + } while (0) +#endif + +#ifndef KGE_THROW_SYSTEM_ERROR +#define KGE_THROW_SYSTEM_ERROR(ERRCODE, MESSAGE) \ + do \ + { \ + KGE_ERRORF("An exception occurred (%#x): %s", ERRCODE, MESSAGE); \ + kiwano::StackTracer().Print(); \ + throw kiwano::SystemError(std::error_code(kiwano::error_enum(ERRCODE)), MESSAGE); \ + } while (0) +#endif + +#ifdef KGE_PLATFORM_WINDOWS +#ifndef KGE_THROW_IF_FAILED +#define KGE_THROW_IF_FAILED(HR, MESSAGE) \ + if (FAILED(HR)) \ + { \ + KGE_THROW_SYSTEM_ERROR(HR, MESSAGE); \ + } +#endif +#endif // KGE_PLATFORM_WINDOWS + + namespace kiwano { KGE_DECLARE_SMART_PTR(LogFormater); KGE_DECLARE_SMART_PTR(LogProvider); -KGE_DECLARE_SMART_PTR(Logger); /** * \~chinese @@ -144,7 +175,7 @@ private: /** * \~chinese - * @brief 日志提供者 + * @brief 日志生产者 */ class KGE_API LogProvider : public ObjectBase { @@ -170,7 +201,7 @@ protected: /** * \~chinese - * @brief 控制台日志提供者 + * @brief 控制台日志生产者 */ class KGE_API ConsoleLogProvider : public LogProvider { @@ -194,7 +225,7 @@ private: /** * \~chinese - * @brief 文件日志提供者 + * @brief 文件日志生产者 */ class KGE_API FileLogProvider : public LogProvider { @@ -253,8 +284,8 @@ public: void SetLevel(LogLevel level); /// \~chinese - /// @brief 添加日志提供者 - /// @param provider 日志提供者 + /// @brief 添加日志生产者 + /// @param provider 日志生产者 void AddProvider(LogProviderPtr provider); /// \~chinese diff --git a/src/kiwano/utils/ResourceCache.cpp b/src/kiwano/utils/ResourceCache.cpp index 9dc5da6a..30728cdb 100644 --- a/src/kiwano/utils/ResourceCache.cpp +++ b/src/kiwano/utils/ResourceCache.cpp @@ -19,9 +19,8 @@ // THE SOFTWARE. #include -#include -#include #include +#include #include namespace kiwano @@ -76,14 +75,14 @@ bool ResourceCache::LoadFromJsonFile(const String& file_path) ifs >> json_data; ifs.close(); } - catch (std::wifstream::failure& e) + catch (std::ios_base::failure& e) { - KGE_ERRORF("%s failed: Cannot open file. (%s)", __FUNCTION__, e.what()); + KGE_ERRORF("%s failed: cannot open file. (%s)", __FUNCTION__, e.what()); return false; } catch (Json::exception& e) { - KGE_ERRORF("%s failed: Cannot parse to JSON. (%s)", __FUNCTION__, e.what()); + KGE_ERRORF("%s failed: cannot parse JSON. (%s)", __FUNCTION__, e.what()); return false; } return LoadFromJson(json_data);