diff --git a/appveyor.yml b/appveyor.yml index 9f7cf1bd..49c87f43 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -54,7 +54,8 @@ for: - master only_commits: message: /\[build\]/ - matrix: + environment: + matrix: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 VS_PLATFORM_TOOLSET: v142 diff --git a/projects/kiwano.vcxproj b/projects/kiwano.vcxproj index a1b790a9..070d909b 100644 --- a/projects/kiwano.vcxproj +++ b/projects/kiwano.vcxproj @@ -11,7 +11,6 @@ - @@ -48,7 +47,7 @@ - + @@ -58,7 +57,7 @@ - + @@ -67,21 +66,22 @@ - - - - - - + + + + + + + @@ -116,7 +116,7 @@ - + @@ -126,9 +126,6 @@ - - - @@ -138,7 +135,11 @@ - + + + + + @@ -201,7 +202,7 @@ Level3 Disabled true - None + EditAndContinue true false @@ -218,7 +219,7 @@ true false true - None + EditAndContinue true false diff --git a/projects/kiwano.vcxproj.filters b/projects/kiwano.vcxproj.filters index 586733bf..e3db99d4 100644 --- a/projects/kiwano.vcxproj.filters +++ b/projects/kiwano.vcxproj.filters @@ -37,6 +37,9 @@ {86e2d0f2-a9d0-4456-b6a5-d480228bbf82} + + {30333461-e9bc-4709-84bd-ce6e0e1a3079} + @@ -96,21 +99,6 @@ base - - renderer - - - renderer - - - renderer - - - renderer - - - renderer - math @@ -140,9 +128,6 @@ - - math - math @@ -152,9 +137,6 @@ base - - base - utils @@ -174,9 +156,6 @@ utils - - renderer - base @@ -198,12 +177,6 @@ 2d - - renderer - - - renderer - 2d\action @@ -222,9 +195,6 @@ 2d\action - - renderer - utils @@ -255,9 +225,6 @@ core - - base - core @@ -267,9 +234,6 @@ 2d - - renderer - 2d\action @@ -282,14 +246,11 @@ base - - renderer + + math - - renderer - - - renderer + + base renderer @@ -297,9 +258,51 @@ renderer + + renderer + + + renderer + + + renderer + + + renderer + renderer + + renderer + + + renderer + + + renderer\win32 + + + renderer\win32 + + + renderer\win32 + + + renderer\win32 + + + renderer\win32 + + + renderer\win32 + + + renderer\win32 + + + renderer + @@ -335,18 +338,6 @@ base - - renderer - - - renderer - - - renderer - - - renderer - platform @@ -359,9 +350,6 @@ base - - base - utils @@ -398,12 +386,6 @@ 2d - - renderer - - - renderer - 2d\action @@ -419,9 +401,6 @@ 2d\action - - renderer - utils @@ -434,9 +413,6 @@ 2d - - renderer - 2d\action @@ -449,14 +425,8 @@ base - - renderer - - - renderer - - - renderer + + base renderer @@ -464,8 +434,44 @@ renderer + + renderer + + + renderer + + + renderer + + + renderer + renderer + + renderer + + + renderer + + + renderer\win32 + + + renderer\win32 + + + renderer\win32 + + + renderer\win32 + + + renderer\win32 + + + renderer + \ No newline at end of file diff --git a/src/kiwano-audio/src/Player.h b/src/kiwano-audio/src/Player.h index 290c7de7..cb9da0a0 100644 --- a/src/kiwano-audio/src/Player.h +++ b/src/kiwano-audio/src/Player.h @@ -20,7 +20,7 @@ #pragma once #include -#include +#include #include "Sound.h" namespace kiwano @@ -31,7 +31,7 @@ namespace kiwano // 音乐播放器 class KGE_API Player - : protected Object + : protected ObjectBase { using MusicMap = Map; diff --git a/src/kiwano-audio/src/Sound.h b/src/kiwano-audio/src/Sound.h index fa505676..9cf9e71f 100644 --- a/src/kiwano-audio/src/Sound.h +++ b/src/kiwano-audio/src/Sound.h @@ -20,7 +20,7 @@ #pragma once #include -#include +#include #include #include @@ -32,7 +32,7 @@ namespace kiwano // 音乐对象 class KGE_API Sound - : public Object + : public ObjectBase { public: Sound(); diff --git a/src/kiwano-audio/src/Transcoder.cpp b/src/kiwano-audio/src/Transcoder.cpp index 4d2d7baf..7189690c 100644 --- a/src/kiwano-audio/src/Transcoder.cpp +++ b/src/kiwano-audio/src/Transcoder.cpp @@ -24,9 +24,9 @@ #include #include -#include #include #include +#include #include #include "audio-modules.h" #include "Transcoder.h" diff --git a/src/kiwano-network/src/HttpRequest.hpp b/src/kiwano-network/src/HttpRequest.hpp index 79335b4f..5f147e57 100644 --- a/src/kiwano-network/src/HttpRequest.hpp +++ b/src/kiwano-network/src/HttpRequest.hpp @@ -21,7 +21,7 @@ #pragma once #include #include -#include +#include namespace kiwano { @@ -30,7 +30,7 @@ namespace kiwano typedef Function ResponseCallback; class KGE_API HttpRequest - : public Object + : public ObjectBase { public: enum class Type diff --git a/src/kiwano-network/src/HttpResponse.hpp b/src/kiwano-network/src/HttpResponse.hpp index 094361b4..c5d35ffe 100644 --- a/src/kiwano-network/src/HttpResponse.hpp +++ b/src/kiwano-network/src/HttpResponse.hpp @@ -21,14 +21,14 @@ #pragma once #include #include -#include +#include namespace kiwano { namespace network { class KGE_API HttpResponse - : public Object + : public ObjectBase { public: inline HttpResponse(HttpRequestPtr request) diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp index 0d2b740d..8ef488f5 100644 --- a/src/kiwano/2d/Actor.cpp +++ b/src/kiwano/2d/Actor.cpp @@ -71,7 +71,7 @@ namespace kiwano OnUpdate(dt); } - if (!children_.is_empty()) + if (!children_.item_empty()) { ActorPtr next; for (auto child = children_.first_item(); child; child = next) @@ -89,7 +89,7 @@ namespace kiwano UpdateTransform(); - if (children_.is_empty()) + if (children_.item_empty()) { OnRender(renderer); } @@ -407,7 +407,7 @@ namespace kiwano { if (!IsName(name)) { - Object::SetName(name); + ObjectBase::SetName(name); hash_name_ = std::hash{}(name); } } @@ -609,7 +609,7 @@ namespace kiwano { KGE_ASSERT(child && "Actor::RemoveChild failed, NULL pointer exception"); - if (children_.is_empty()) + if (children_.item_empty()) return; if (child) @@ -622,7 +622,7 @@ namespace kiwano void Actor::RemoveChildren(String const& child_name) { - if (children_.is_empty()) + if (children_.item_empty()) { return; } diff --git a/src/kiwano/2d/Actor.h b/src/kiwano/2d/Actor.h index 55f8f105..e8764689 100644 --- a/src/kiwano/2d/Actor.h +++ b/src/kiwano/2d/Actor.h @@ -32,7 +32,7 @@ namespace kiwano // 角色 class KGE_API Actor - : public Object + : public ObjectBase , public TimerManager , public ActionManager , public EventDispatcher diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp index 0dbe72d3..a2242f93 100644 --- a/src/kiwano/2d/DebugActor.cpp +++ b/src/kiwano/2d/DebugActor.cpp @@ -82,9 +82,9 @@ namespace kiwano ss << "Fps: " << frame_time_.size() << std::endl; #if defined(KGE_DEBUG) - if (Object::IsTracingLeaks()) + if (ObjectBase::IsTracingLeaks()) { - ss << "Objects: " << Object::__GetTracingObjects().size() << std::endl; + ss << "Objects: " << ObjectBase::__GetTracingObjects().size() << std::endl; } #endif diff --git a/src/kiwano/2d/Frame.h b/src/kiwano/2d/Frame.h index 93569ee9..3ee92fb3 100644 --- a/src/kiwano/2d/Frame.h +++ b/src/kiwano/2d/Frame.h @@ -25,7 +25,7 @@ namespace kiwano { // 帧图像 class KGE_API Frame - : public Object + : public ObjectBase { public: Frame(); diff --git a/src/kiwano/2d/FrameSequence.h b/src/kiwano/2d/FrameSequence.h index 863fa38e..09c0ccde 100644 --- a/src/kiwano/2d/FrameSequence.h +++ b/src/kiwano/2d/FrameSequence.h @@ -25,7 +25,7 @@ namespace kiwano { // 序列帧 class KGE_API FrameSequence - : public Object + : public ObjectBase { public: FrameSequence(); diff --git a/src/kiwano/2d/Transition.h b/src/kiwano/2d/Transition.h index 67dc8900..a70b89cd 100644 --- a/src/kiwano/2d/Transition.h +++ b/src/kiwano/2d/Transition.h @@ -29,7 +29,7 @@ namespace kiwano // 舞台过渡 class KGE_API Transition - : public Object + : public ObjectBase { friend class Director; diff --git a/src/kiwano/2d/action/Action.h b/src/kiwano/2d/action/Action.h index 427bb215..ce7eb0c2 100644 --- a/src/kiwano/2d/action/Action.h +++ b/src/kiwano/2d/action/Action.h @@ -28,7 +28,7 @@ namespace kiwano class ActionManager; class KGE_API Action - : public Object + : public ObjectBase , protected intrusive_list_item { friend class ActionManager; diff --git a/src/kiwano/2d/action/ActionGroup.cpp b/src/kiwano/2d/action/ActionGroup.cpp index fd1a646a..0cd36d40 100644 --- a/src/kiwano/2d/action/ActionGroup.cpp +++ b/src/kiwano/2d/action/ActionGroup.cpp @@ -45,7 +45,7 @@ namespace kiwano void ActionGroup::Init(ActorPtr target) { - if (actions_.is_empty()) + if (actions_.item_empty()) { Done(); return; @@ -135,7 +135,7 @@ namespace kiwano ActionPtr ActionGroup::Reverse() const { auto group = new (std::nothrow) ActionGroup(); - if (group && !actions_.is_empty()) + if (group && !actions_.item_empty()) { for (auto action = actions_.last_item(); action; action = action->prev_item()) { diff --git a/src/kiwano/2d/action/ActionManager.cpp b/src/kiwano/2d/action/ActionManager.cpp index 3428bd8a..2a0c5ac5 100644 --- a/src/kiwano/2d/action/ActionManager.cpp +++ b/src/kiwano/2d/action/ActionManager.cpp @@ -26,7 +26,7 @@ namespace kiwano { void ActionManager::UpdateActions(ActorPtr target, Duration dt) { - if (actions_.is_empty() || !target) + if (actions_.item_empty() || !target) return; ActionPtr next; @@ -55,7 +55,7 @@ namespace kiwano ActionPtr ActionManager::GetAction(String const & name) { - if (actions_.is_empty()) + if (actions_.item_empty()) return nullptr; for (auto action = actions_.first_item().get(); action; action = action->next_item().get()) @@ -66,7 +66,7 @@ namespace kiwano void ActionManager::ResumeAllActions() { - if (actions_.is_empty()) + if (actions_.item_empty()) return; for (auto action = actions_.first_item().get(); action; action = action->next_item().get()) @@ -77,7 +77,7 @@ namespace kiwano void ActionManager::PauseAllActions() { - if (actions_.is_empty()) + if (actions_.item_empty()) return; for (auto action = actions_.first_item().get(); action; action = action->next_item().get()) @@ -88,7 +88,7 @@ namespace kiwano void ActionManager::StopAllActions() { - if (actions_.is_empty()) + if (actions_.item_empty()) return; for (auto action = actions_.first_item().get(); action; action = action->next_item().get()) diff --git a/src/kiwano/2d/include-forwards.h b/src/kiwano/2d/include-forwards.h index 97473233..edbbf0ae 100644 --- a/src/kiwano/2d/include-forwards.h +++ b/src/kiwano/2d/include-forwards.h @@ -23,10 +23,9 @@ #include "../base/time.h" #include "../base/RefCounter.hpp" #include "../base/SmartPtr.hpp" -#include "../base/ComPtr.hpp" -#include "../base/Object.h" +#include "../base/ObjectBase.h" #include "../base/types.h" -#include "../math/helper.h" +#include "../math/math.h" #include "../renderer/Color.h" namespace kiwano diff --git a/src/kiwano/base/AsyncTask.h b/src/kiwano/base/AsyncTask.h index f1d31efa..15551475 100644 --- a/src/kiwano/base/AsyncTask.h +++ b/src/kiwano/base/AsyncTask.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "Object.h" +#include "ObjectBase.h" #include #include @@ -31,7 +31,7 @@ namespace kiwano typedef Function AsyncTaskCallback; class AsyncTask - : public Object + : public ObjectBase { public: AsyncTask(); diff --git a/src/kiwano/base/EventDispatcher.cpp b/src/kiwano/base/EventDispatcher.cpp index 8dc93e26..d46fbb3b 100644 --- a/src/kiwano/base/EventDispatcher.cpp +++ b/src/kiwano/base/EventDispatcher.cpp @@ -25,7 +25,7 @@ namespace kiwano { void EventDispatcher::Dispatch(Event& evt) { - if (listeners_.is_empty()) + if (listeners_.item_empty()) return; EventListenerPtr next; diff --git a/src/kiwano/base/EventListener.h b/src/kiwano/base/EventListener.h index 40ed7aa0..f07e83f3 100644 --- a/src/kiwano/base/EventListener.h +++ b/src/kiwano/base/EventListener.h @@ -21,7 +21,7 @@ #pragma once #include "../core/core.h" #include "../base/SmartPtr.hpp" -#include "Object.h" +#include "ObjectBase.h" #include "Event.hpp" namespace kiwano @@ -34,7 +34,7 @@ namespace kiwano // 事件监听器 class KGE_API EventListener - : public Object + : public ObjectBase , protected intrusive_list_item { friend class EventDispatcher; diff --git a/src/kiwano/base/Input.h b/src/kiwano/base/Input.h index e23b3796..2cbc24bc 100644 --- a/src/kiwano/base/Input.h +++ b/src/kiwano/base/Input.h @@ -21,7 +21,7 @@ #pragma once #include "../macros.h" #include "../core/core.h" -#include "../math/helper.h" +#include "../math/math.h" #include "keys.hpp" #include "Component.h" diff --git a/src/kiwano/base/Object.cpp b/src/kiwano/base/ObjectBase.cpp similarity index 78% rename from src/kiwano/base/Object.cpp rename to src/kiwano/base/ObjectBase.cpp index 888e9108..b3020125 100644 --- a/src/kiwano/base/Object.cpp +++ b/src/kiwano/base/ObjectBase.cpp @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include "Object.h" +#include "ObjectBase.h" #include "Logger.h" #include @@ -27,12 +27,12 @@ namespace kiwano namespace { bool tracing_leaks = false; - Vector tracing_objects; + Vector tracing_objects; } - unsigned int Object::last_object_id = 0; + unsigned int ObjectBase::last_object_id = 0; - Object::Object() + ObjectBase::ObjectBase() : tracing_leak_(false) , user_data_(nullptr) , name_(nullptr) @@ -40,34 +40,34 @@ namespace kiwano { #ifdef KGE_DEBUG - Object::__AddObjectToTracingList(this); + ObjectBase::__AddObjectToTracingList(this); #endif } - Object::~Object() + ObjectBase::~ObjectBase() { if (name_) delete name_; #ifdef KGE_DEBUG - Object::__RemoveObjectFromTracingList(this); + ObjectBase::__RemoveObjectFromTracingList(this); #endif } - void * Object::GetUserData() const + void * ObjectBase::GetUserData() const { return user_data_; } - void Object::SetUserData(void * data) + void ObjectBase::SetUserData(void * data) { user_data_ = data; } - void Object::SetName(String const & name) + void ObjectBase::SetName(String const & name) { if (IsName(name)) return; @@ -88,29 +88,29 @@ namespace kiwano *name_ = name; } - String Object::DumpObject() + String ObjectBase::DumpObject() { String name = kiwano::string_to_wide(typeid(*this).name()); return String::format(L"{ class=\"%s\" id=%d refcount=%d name=\"%s\" }", name.c_str(), GetObjectID(), GetRefCount(), GetName().c_str()); } - bool Object::IsTracingLeaks() + bool ObjectBase::IsTracingLeaks() { return tracing_leaks; } - void Object::StartTracingLeaks() + void ObjectBase::StartTracingLeaks() { tracing_leaks = true; } - void Object::StopTracingLeaks() + void ObjectBase::StopTracingLeaks() { tracing_leaks = false; } - void Object::DumpTracingObjects() + void ObjectBase::DumpTracingObjects() { KGE_LOG(L"-------------------------- All Objects --------------------------"); for (const auto object : tracing_objects) @@ -120,12 +120,12 @@ namespace kiwano KGE_LOG(L"------------------------- Total size: %d -------------------------", tracing_objects.size()); } - Vector& kiwano::Object::__GetTracingObjects() + Vector& kiwano::ObjectBase::__GetTracingObjects() { return tracing_objects; } - void Object::__AddObjectToTracingList(Object * obj) + void ObjectBase::__AddObjectToTracingList(ObjectBase * obj) { #ifdef KGE_DEBUG @@ -138,7 +138,7 @@ namespace kiwano #endif } - void Object::__RemoveObjectFromTracingList(Object * obj) + void ObjectBase::__RemoveObjectFromTracingList(ObjectBase * obj) { #ifdef KGE_DEBUG diff --git a/src/kiwano/base/Object.h b/src/kiwano/base/ObjectBase.h similarity index 88% rename from src/kiwano/base/Object.h rename to src/kiwano/base/ObjectBase.h index 435d0cf0..e527fbf3 100644 --- a/src/kiwano/base/Object.h +++ b/src/kiwano/base/ObjectBase.h @@ -26,15 +26,15 @@ namespace kiwano { - KGE_DECLARE_SMART_PTR(Object); + KGE_DECLARE_SMART_PTR(ObjectBase); - class KGE_API Object + class KGE_API ObjectBase : public RefCounter { public: - Object(); + ObjectBase(); - virtual ~Object(); + virtual ~ObjectBase(); void* GetUserData() const; @@ -60,11 +60,11 @@ namespace kiwano static void DumpTracingObjects(); public: - static Vector& __GetTracingObjects(); + static Vector& __GetTracingObjects(); - static void __AddObjectToTracingList(Object*); + static void __AddObjectToTracingList(ObjectBase*); - static void __RemoveObjectFromTracingList(Object*); + static void __RemoveObjectFromTracingList(ObjectBase*); private: bool tracing_leak_; diff --git a/src/kiwano/base/Resource.cpp b/src/kiwano/base/Resource.cpp index ee6c84e7..b20d87f3 100644 --- a/src/kiwano/base/Resource.cpp +++ b/src/kiwano/base/Resource.cpp @@ -25,7 +25,7 @@ namespace kiwano { Resource::Resource(LPCWSTR file_name) : type_(Type::File) - , bin_name_(nullptr) + , bin_id_(0) , bin_type_(nullptr) { if (file_name) @@ -34,16 +34,16 @@ namespace kiwano Resource::Resource(String const& file_name) : type_(Type::File) - , bin_name_(nullptr) + , bin_id_(0) , bin_type_(nullptr) { if (!file_name.empty()) file_name_ = new (std::nothrow) String(file_name); } - Resource::Resource(LPCWSTR name, LPCWSTR type) + Resource::Resource(UINT id, LPCWSTR type) : type_(Type::Binary) - , bin_name_(name) + , bin_id_(id) , bin_type_(type) { } @@ -61,9 +61,7 @@ namespace kiwano size_t Resource::GetHashCode() const { - if (type_ == Type::File) - return GetFileName().hash(); - return std::hash{}(bin_name_); + return (type_ == Type::File) ? GetFileName().hash() : static_cast(bin_id_); } Resource & Resource::operator=(Resource const & rhs) @@ -86,7 +84,7 @@ namespace kiwano } else { - bin_name_ = rhs.bin_name_; + bin_id_ = rhs.bin_id_; bin_type_ = rhs.bin_type_; } } @@ -104,7 +102,7 @@ namespace kiwano HGLOBAL res_data; HRSRC res_info; - res_info = FindResourceW(nullptr, bin_name_, bin_type_); + res_info = FindResourceW(nullptr, MAKEINTRESOURCE(bin_id_), bin_type_); if (res_info == nullptr) { KGE_ERROR_LOG(L"FindResource failed"); diff --git a/src/kiwano/base/Resource.h b/src/kiwano/base/Resource.h index 4c99c34a..80a1129a 100644 --- a/src/kiwano/base/Resource.h +++ b/src/kiwano/base/Resource.h @@ -28,7 +28,7 @@ namespace kiwano // // 资源可以是文件类型,也可以是保存在 exe 中的二进制资源 // 例如, 一份音频资源的类型为 L"WAVE", 名称标识符为 IDR_WAVE_1, - // 那么可以这样指定该资源: Resource res(MAKEINTRESOURCE(IDR_WAVE_1), L"WAVE"); + // 那么可以这样指定该资源: Resource res(IDR_WAVE_1, L"WAVE"); // // 了解资源的更多信息: https://docs.microsoft.com/en-us/windows/desktop/menurc/resources // @@ -46,7 +46,7 @@ namespace kiwano ); Resource( - LPCWSTR name, /* 资源名称 */ + UINT id, /* 资源名称 */ LPCWSTR type /* 资源类型 */ ); @@ -56,19 +56,20 @@ namespace kiwano virtual ~Resource(); - inline bool IsFileType() const { return type_ == Type::File; } - - inline String GetFileName() const { if (file_name_) return *file_name_; return String(); } - - bool Load( - LPVOID& buffer, - DWORD& buffer_size - ) const; + bool Load(LPVOID& buffer, DWORD& buffer_size) const; size_t GetHashCode() const; Resource& operator= (Resource const& rhs); + inline bool IsFileType() const { return type_ == Type::File; } + + inline String GetFileName() const { return file_name_ ? (*file_name_) : L""; } + + inline UINT GetResourceId() const { return bin_id_; } + + inline LPCWSTR GetResourceType() const { return bin_type_; } + private: Type type_; union @@ -80,7 +81,7 @@ namespace kiwano struct { - LPCWSTR bin_name_; + UINT bin_id_; LPCWSTR bin_type_; }; }; diff --git a/src/kiwano/base/Timer.h b/src/kiwano/base/Timer.h index a3ba1a2f..e82211dd 100644 --- a/src/kiwano/base/Timer.h +++ b/src/kiwano/base/Timer.h @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "Object.h" +#include "ObjectBase.h" #include "time.h" #include @@ -31,7 +31,7 @@ namespace kiwano // 定时任务 class KGE_API Timer - : public Object + : public ObjectBase , protected intrusive_list_item { friend class TimerManager; diff --git a/src/kiwano/base/TimerManager.cpp b/src/kiwano/base/TimerManager.cpp index 1476e157..0380baf8 100644 --- a/src/kiwano/base/TimerManager.cpp +++ b/src/kiwano/base/TimerManager.cpp @@ -25,7 +25,7 @@ namespace kiwano { void TimerManager::UpdateTimers(Duration dt) { - if (timers_.is_empty()) + if (timers_.item_empty()) return; TimerPtr next; @@ -54,7 +54,7 @@ namespace kiwano void TimerManager::StopTimers(String const& name) { - if (timers_.is_empty()) + if (timers_.item_empty()) return; for (auto timer = timers_.first_item().get(); timer; timer = timer->next_item().get()) @@ -68,7 +68,7 @@ namespace kiwano void TimerManager::StartTimers(String const& name) { - if (timers_.is_empty()) + if (timers_.item_empty()) return; for (auto timer = timers_.first_item().get(); timer; timer = timer->next_item().get()) @@ -82,7 +82,7 @@ namespace kiwano void TimerManager::RemoveTimers(String const& name) { - if (timers_.is_empty()) + if (timers_.item_empty()) return; TimerPtr next; @@ -98,7 +98,7 @@ namespace kiwano void TimerManager::StopAllTimers() { - if (timers_.is_empty()) + if (timers_.item_empty()) return; for (auto timer = timers_.first_item().get(); timer; timer = timer->next_item().get()) @@ -109,7 +109,7 @@ namespace kiwano void TimerManager::StartAllTimers() { - if (timers_.is_empty()) + if (timers_.item_empty()) return; for (auto timer = timers_.first_item().get(); timer; timer = timer->next_item().get()) diff --git a/src/kiwano/base/Window.h b/src/kiwano/base/Window.h index bd1dc631..3513ba20 100644 --- a/src/kiwano/base/Window.h +++ b/src/kiwano/base/Window.h @@ -21,7 +21,7 @@ #pragma once #include "../macros.h" #include "../core/core.h" -#include "../math/helper.h" +#include "../math/math.h" #include "types.h" namespace kiwano diff --git a/src/kiwano/base/window.h b/src/kiwano/base/window.h index bd1dc631..3513ba20 100644 --- a/src/kiwano/base/window.h +++ b/src/kiwano/base/window.h @@ -21,7 +21,7 @@ #pragma once #include "../macros.h" #include "../core/core.h" -#include "../math/helper.h" +#include "../math/math.h" #include "types.h" namespace kiwano diff --git a/src/kiwano/core/intrusive_list.hpp b/src/kiwano/core/intrusive_list.hpp index e8f56a28..76e0053d 100644 --- a/src/kiwano/core/intrusive_list.hpp +++ b/src/kiwano/core/intrusive_list.hpp @@ -82,7 +82,7 @@ public: T& last_item() { return last_; } - bool is_empty() const { return !first_; } + bool item_empty() const { return !first_; } void push_back_item(T const& child) { diff --git a/src/kiwano/kiwano.h b/src/kiwano/kiwano.h index 34ab234e..5ddf7f3d 100644 --- a/src/kiwano/kiwano.h +++ b/src/kiwano/kiwano.h @@ -64,11 +64,9 @@ #include "renderer/Image.h" #include "renderer/GifImage.h" #include "renderer/TextLayout.h" -#include "renderer/TextRenderer.h" #include "renderer/Geometry.h" #include "renderer/LayerArea.h" #include "renderer/ImageCache.h" -#include "renderer/RenderTarget.h" #include "renderer/Renderer.h" @@ -81,11 +79,8 @@ #include "base/input.h" #include "base/Director.h" #include "base/Logger.h" - #include "base/SmartPtr.hpp" -#include "base/ComPtr.hpp" - -#include "base/Object.h" +#include "base/ObjectBase.h" #include "base/Event.hpp" #include "base/EventListener.h" #include "base/EventDispatcher.h" diff --git a/src/kiwano/math/Rect.hpp b/src/kiwano/math/Rect.hpp index 7c53ef82..c45480ae 100644 --- a/src/kiwano/math/Rect.hpp +++ b/src/kiwano/math/Rect.hpp @@ -99,7 +99,7 @@ namespace kiwano inline value_type GetBottom() const { return origin.y + size.y; } - inline bool is_empty() const { return origin.IsOrigin() && size.IsOrigin(); } + inline bool IsEmpty() const { return origin.IsOrigin() && size.IsOrigin(); } inline bool ContainsPoint(const Vec2T& point) const { diff --git a/src/kiwano/math/helper.h b/src/kiwano/math/math.h similarity index 100% rename from src/kiwano/math/helper.h rename to src/kiwano/math/math.h diff --git a/src/kiwano/platform/Application.cpp b/src/kiwano/platform/Application.cpp index c47fa142..157f1a29 100644 --- a/src/kiwano/platform/Application.cpp +++ b/src/kiwano/platform/Application.cpp @@ -24,6 +24,7 @@ #include "../base/Logger.h" #include "../base/input.h" #include "../base/Director.h" +#include "../renderer/ImageCache.h" #include "../renderer/Renderer.h" #include "../utils/ResourceCache.h" #include // GET_X_LPARAM, GET_Y_LPARAM @@ -147,8 +148,10 @@ namespace kiwano void Application::Destroy() { - // Clear all stages + // Clear all resources Director::GetInstance()->ClearStages(); + ResourceCache::GetInstance()->Clear(); + ImageCache::GetInstance()->Clear(); if (inited_) { @@ -164,6 +167,7 @@ namespace kiwano // Destroy all instances Director::DestroyInstance(); ResourceCache::DestroyInstance(); + ImageCache::DestroyInstance(); Input::DestroyInstance(); Renderer::DestroyInstance(); Window::DestroyInstance(); diff --git a/src/kiwano/renderer/D2DDeviceResources.h b/src/kiwano/renderer/D2DDeviceResources.h deleted file mode 100644 index cd304459..00000000 --- a/src/kiwano/renderer/D2DDeviceResources.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2016-2018 Kiwano - Nomango -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#pragma once -#include "helper.hpp" -#include "Font.h" -#include "../base/Resource.h" -#include "../2d/TextStyle.hpp" -#include -#include -#include - -namespace kiwano -{ - MIDL_INTERFACE("5706684a-bf6d-4b03-b627-094758a33032") - KGE_API ID2DDeviceResources - : public IUnknown - { - public: - static HRESULT Create(ID2DDeviceResources** device_resources); - - virtual HRESULT CreateBitmapFromFile( - _Out_ ComPtr& bitmap, - _In_ String const& file_path - ) = 0; - - virtual HRESULT CreateBitmapFromResource( - _Out_ ComPtr& bitmap, - _In_ Resource const& res - ) = 0; - - virtual HRESULT CreateTextFormat( - _Out_ ComPtr& text_format, - _In_ Font const& font - ) const = 0; - - virtual HRESULT CreateTextLayout( - _Out_ ComPtr& text_layout, - _In_ String const& text, - _In_ TextStyle const& text_style, - _In_ ComPtr const& text_format - ) const = 0; - - virtual ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const = 0; - - virtual HRESULT SetD2DDevice( - _In_ ComPtr const& device - ) = 0; - - virtual void SetTargetBitmap( - _In_ ComPtr const& target - ) = 0; - - virtual void DiscardResources() = 0; - - inline ID2D1Factory1* GetFactory() const { KGE_ASSERT(factory_); return factory_.get(); } - inline IWICImagingFactory* GetWICImagingFactory() const { KGE_ASSERT(imaging_factory_); return imaging_factory_.get(); } - inline IDWriteFactory* GetDWriteFactory() const { KGE_ASSERT(dwrite_factory_); return dwrite_factory_.get(); } - inline ID2D1Device* GetDevice() const { KGE_ASSERT(device_); return device_.get(); } - inline ID2D1DeviceContext* GetDeviceContext() const { KGE_ASSERT(device_context_); return device_context_.get(); } - inline ID2D1Bitmap1* GetTargetBitmap() const { KGE_ASSERT(target_bitmap_); return target_bitmap_.get(); } - - protected: - ComPtr factory_; - ComPtr device_; - ComPtr device_context_; - ComPtr target_bitmap_; - - ComPtr imaging_factory_; - ComPtr dwrite_factory_; - }; - -} diff --git a/src/kiwano/renderer/Font.cpp b/src/kiwano/renderer/Font.cpp index 20ce297b..8ab74f91 100644 --- a/src/kiwano/renderer/Font.cpp +++ b/src/kiwano/renderer/Font.cpp @@ -19,14 +19,41 @@ // THE SOFTWARE. #include "Font.h" +#include "Renderer.h" namespace kiwano { - Font::Font(const String& family, float size, unsigned int weight, bool italic) + // + // FontCollection + // + + FontCollection::FontCollection() + { + } + + FontCollection::FontCollection(Resource const& res) + { + Load(res); + } + + bool FontCollection::Load(Resource const& res) + { + Renderer::GetInstance()->CreateFontFromResource(*this, res); + return false; + } + + + // + // Font + // + + Font::Font(const String& family, float size, unsigned int weight, bool italic, FontCollection collection) : family(family) , size(size) , weight(weight) , italic(italic) + , collection(collection) { } + } diff --git a/src/kiwano/renderer/Font.h b/src/kiwano/renderer/Font.h index fc402f2b..43aa6441 100644 --- a/src/kiwano/renderer/Font.h +++ b/src/kiwano/renderer/Font.h @@ -20,6 +20,9 @@ #pragma once #include "../core/core.h" +#include "../base/Resource.h" +#include "win32/ComPtr.hpp" +#include namespace kiwano { @@ -37,6 +40,28 @@ namespace kiwano ExtraBlack = 950 }; + + // 字体集 + class FontCollection + { + public: + FontCollection(); + + FontCollection(Resource const& res); + + // 从资源加载字体集 + bool Load(Resource const& res); + + public: + inline ComPtr GetFontCollection() const { return collection_; } + + inline void SetFontCollection(ComPtr collection) { collection_ = collection; } + + protected: + ComPtr collection_; + }; + + // 字体 class Font { @@ -45,13 +70,15 @@ namespace kiwano float size; // 字号 unsigned int weight; // 粗细值 bool italic; // 是否斜体 + FontCollection collection; // 字体集 public: Font( - const String& family = L"", - float size = 18, - unsigned int weight = FontWeight::Normal, - bool italic = false + const String& family = L"", + float size = 18, + unsigned int weight = FontWeight::Normal, + bool italic = false, + FontCollection collection = FontCollection() ); }; } diff --git a/src/kiwano/renderer/Geometry.h b/src/kiwano/renderer/Geometry.h index 8a4f5417..be611d73 100644 --- a/src/kiwano/renderer/Geometry.h +++ b/src/kiwano/renderer/Geometry.h @@ -19,8 +19,7 @@ // THE SOFTWARE. #pragma once -#include "../base/SmartPtr.hpp" -#include "D2DDeviceResources.h" +#include "win32/D2DDeviceResources.h" namespace kiwano { diff --git a/src/kiwano/renderer/GifImage.h b/src/kiwano/renderer/GifImage.h index b30fd113..bcd6efff 100644 --- a/src/kiwano/renderer/GifImage.h +++ b/src/kiwano/renderer/GifImage.h @@ -26,7 +26,7 @@ namespace kiwano // GIF 图像 KGE_DECLARE_SMART_PTR(GifImage); class KGE_API GifImage - : public Object + : public ObjectBase { public: GifImage(); diff --git a/src/kiwano/renderer/Image.h b/src/kiwano/renderer/Image.h index 86d4a71c..2444aaae 100644 --- a/src/kiwano/renderer/Image.h +++ b/src/kiwano/renderer/Image.h @@ -19,8 +19,7 @@ // THE SOFTWARE. #pragma once -#include "../base/Resource.h" -#include "D2DDeviceResources.h" // ID2D1Bitmap +#include "win32/D2DDeviceResources.h" namespace kiwano { diff --git a/src/kiwano/renderer/ImageCache.h b/src/kiwano/renderer/ImageCache.h index 0534704e..f6b62162 100644 --- a/src/kiwano/renderer/ImageCache.h +++ b/src/kiwano/renderer/ImageCache.h @@ -19,7 +19,6 @@ // THE SOFTWARE. #pragma once -#include "../core/singleton.hpp" #include "Image.h" #include "GifImage.h" diff --git a/src/kiwano/renderer/LayerArea.h b/src/kiwano/renderer/LayerArea.h index 92e2848e..59122a2c 100644 --- a/src/kiwano/renderer/LayerArea.h +++ b/src/kiwano/renderer/LayerArea.h @@ -19,7 +19,6 @@ // THE SOFTWARE. #pragma once -#include "D2DDeviceResources.h" #include "Geometry.h" namespace kiwano diff --git a/src/kiwano/renderer/RenderTarget.h b/src/kiwano/renderer/RenderTarget.h index 74ec7b51..308f8778 100644 --- a/src/kiwano/renderer/RenderTarget.h +++ b/src/kiwano/renderer/RenderTarget.h @@ -19,12 +19,12 @@ // THE SOFTWARE. #pragma once -#include "D2DDeviceResources.h" +#include "../base/time.h" #include "Image.h" #include "Geometry.h" #include "TextLayout.h" -#include "TextRenderer.h" #include "LayerArea.h" +#include "win32/TextRenderer.h" namespace kiwano { @@ -168,9 +168,9 @@ namespace kiwano void IncreasePrimitivesCount() const; - inline Status const& GetStatus() const { return status_; } + inline Status const& GetStatus() const { return status_; } - inline ComPtr GetRenderTarget() const { return render_target_; } + inline ComPtr GetRenderTarget() const { return render_target_; } public: RenderTarget(); diff --git a/src/kiwano/renderer/Renderer.cpp b/src/kiwano/renderer/Renderer.cpp index 1688c879..fcba68cc 100644 --- a/src/kiwano/renderer/Renderer.cpp +++ b/src/kiwano/renderer/Renderer.cpp @@ -41,52 +41,97 @@ namespace kiwano KGE_LOG(L"Creating device resources"); hwnd_ = Window::GetInstance()->GetHandle(); + output_size_ = Window::GetInstance()->GetSize(); - ThrowIfFailed(hwnd_ ? S_OK : E_FAIL); - d2d_res_ = nullptr; d3d_res_ = nullptr; drawing_state_block_ = nullptr; - ThrowIfFailed( - ID2DDeviceResources::Create( - &d2d_res_ - ) - ); + HRESULT hr = hwnd_ ? S_OK : E_FAIL; - ThrowIfFailed( + // Direct2D device resources + if (SUCCEEDED(hr)) + { + hr = ID2DDeviceResources::Create(&d2d_res_); + } + + // Direct3D device resources + if (SUCCEEDED(hr)) + { #if defined(KGE_USE_DIRECTX10) - ID3D10DeviceResources::Create( + hr = ID3D10DeviceResources::Create( &d3d_res_, d2d_res_.get(), hwnd_ - ) + ); #else - ID3D11DeviceResources::Create( + hr = ID3D11DeviceResources::Create( &d3d_res_, d2d_res_.get(), hwnd_ - ) + ); #endif - ); + } - ThrowIfFailed( - d2d_res_->GetFactory()->CreateDrawingStateBlock( + // DrawingStateBlock + if (SUCCEEDED(hr)) + { + hr = d2d_res_->GetFactory()->CreateDrawingStateBlock( &drawing_state_block_ - ) - ); + ); + } - ThrowIfFailed( - CreateDeviceResources() - ); + // Other device resources + if (SUCCEEDED(hr)) + { + hr = CreateDeviceResources(); + } - output_size_ = Window::GetInstance()->GetSize(); + // 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()); + } + + ThrowIfFailed(hr); } void Renderer::DestroyComponent() { KGE_LOG(L"Destroying device resources"); + 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(); + drawing_state_block_.reset(); solid_color_brush_.reset(); d2d_res_.reset(); @@ -287,6 +332,53 @@ namespace kiwano } } + void Renderer::CreateFontFromResource(FontCollection& collection, Resource const& res) + { + HRESULT hr = S_OK; + if (!d2d_res_) + { + hr = E_UNEXPECTED; + } + + ComPtr font_collection; + if (res.IsFileType()) + { + String file_path = res.GetFileName(); + if (!FileUtil::ExistsFile(file_path.c_str())) + { + KGE_WARNING_LOG(L"Font file '%s' not found!", file_path.c_str()); + hr = E_FAIL; + } + + hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection( + font_collection_loader_.get(), + reinterpret_cast(&file_path), + sizeof(file_path), + &font_collection + ); + } + else + { + UINT id = res.GetResourceId(); + hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection( + res_font_collection_loader_.get(), + reinterpret_cast(&id), + sizeof(id), + &font_collection + ); + } + + if (SUCCEEDED(hr)) + { + collection.SetFontCollection(font_collection); + } + + if (FAILED(hr)) + { + KGE_WARNING_LOG(L"Load font failed with HRESULT of %08X!", hr); + } + } + void Renderer::CreateTextFormat(TextFormat& format, Font const& font) { HRESULT hr = S_OK; diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h index 16d8081e..1a77f295 100644 --- a/src/kiwano/renderer/Renderer.h +++ b/src/kiwano/renderer/Renderer.h @@ -19,18 +19,15 @@ // THE SOFTWARE. #pragma once -#include "../base/time.h" #include "../base/Component.h" -#include "../base/Resource.h" -#include "../2d/include-forwards.h" -#include "helper.hpp" +#include "win32/FontCollectionLoader.h" #include "RenderTarget.h" #include "GifImage.h" #if defined(KGE_USE_DIRECTX10) # include "D3D10DeviceResources.h" #else -# include "D3D11DeviceResources.h" +# include "win32/D3D11DeviceResources.h" #endif namespace kiwano @@ -71,6 +68,11 @@ namespace kiwano Resource const& res ); + void CreateFontFromResource( + FontCollection& collection, + Resource const& res + ); + void CreateTextFormat( TextFormat& format, Font const& font @@ -166,5 +168,9 @@ namespace kiwano ComPtr d2d_res_; ComPtr d3d_res_; ComPtr drawing_state_block_; + + ComPtr font_collection_loader_; + ComPtr res_font_file_loader_; + ComPtr res_font_collection_loader_; }; } diff --git a/src/kiwano/renderer/TextLayout.h b/src/kiwano/renderer/TextLayout.h index 3fc3add2..d6b23a92 100644 --- a/src/kiwano/renderer/TextLayout.h +++ b/src/kiwano/renderer/TextLayout.h @@ -19,7 +19,6 @@ // THE SOFTWARE. #pragma once -#include "D2DDeviceResources.h" #include "Font.h" #include "../2d/TextStyle.hpp" diff --git a/src/kiwano/base/ComPtr.hpp b/src/kiwano/renderer/win32/ComPtr.hpp similarity index 97% rename from src/kiwano/base/ComPtr.hpp rename to src/kiwano/renderer/win32/ComPtr.hpp index cf525bf3..10812639 100644 --- a/src/kiwano/base/ComPtr.hpp +++ b/src/kiwano/renderer/win32/ComPtr.hpp @@ -19,7 +19,7 @@ // THE SOFTWARE. #pragma once -#include "../core/intrusive_ptr.hpp" +#include "../../core/intrusive_ptr.hpp" #include #include diff --git a/src/kiwano/renderer/D2DDeviceResources.cpp b/src/kiwano/renderer/win32/D2DDeviceResources.cpp similarity index 96% rename from src/kiwano/renderer/D2DDeviceResources.cpp rename to src/kiwano/renderer/win32/D2DDeviceResources.cpp index b94334c2..2ebc880e 100644 --- a/src/kiwano/renderer/D2DDeviceResources.cpp +++ b/src/kiwano/renderer/win32/D2DDeviceResources.cpp @@ -19,9 +19,8 @@ // THE SOFTWARE. #include "D2DDeviceResources.h" -#include "ImageCache.h" -#include "../base/Logger.h" -#include "../utils/FileUtil.h" +#include "../../base/Logger.h" +#include "../../utils/FileUtil.h" #pragma comment(lib, "d2d1.lib") #pragma comment(lib, "dwrite.lib") @@ -108,7 +107,10 @@ namespace kiwano { res->AddRef(); - DX::SafeRelease(*device_resources); + if (*device_resources) + { + (*device_resources)->Release(); + } (*device_resources) = res; } else @@ -172,8 +174,6 @@ namespace kiwano void D2DDeviceResources::DiscardResources() { - ImageCache::GetInstance()->Clear(); - factory_.reset(); device_.reset(); device_context_.reset(); @@ -191,9 +191,9 @@ namespace kiwano { HRESULT hr = S_OK; - ComPtr d2d_factory; - ComPtr imaging_factory; - ComPtr dwrite_factory; + ComPtr d2d_factory; + ComPtr imaging_factory; + ComPtr dwrite_factory; D2D1_FACTORY_OPTIONS options; ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS)); @@ -236,9 +236,9 @@ namespace kiwano { dwrite_factory_ = dwrite_factory; - ComPtr d2d_miter_stroke_style; - ComPtr d2d_bevel_stroke_style; - ComPtr d2d_round_stroke_style; + ComPtr d2d_miter_stroke_style; + ComPtr d2d_bevel_stroke_style; + ComPtr d2d_round_stroke_style; D2D1_STROKE_STYLE_PROPERTIES stroke_style = D2D1::StrokeStyleProperties( D2D1_CAP_STYLE_FLAT, @@ -466,12 +466,12 @@ namespace kiwano ComPtr output; HRESULT hr = dwrite_factory_->CreateTextFormat( font.family.c_str(), - nullptr, + font.collection.GetFontCollection().get(), DWRITE_FONT_WEIGHT(font.weight), font.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, font.size, - L"", + L"en-us", &output ); diff --git a/src/kiwano/renderer/helper.hpp b/src/kiwano/renderer/win32/D2DDeviceResources.h similarity index 62% rename from src/kiwano/renderer/helper.hpp rename to src/kiwano/renderer/win32/D2DDeviceResources.h index ace4bd9f..c87bbfb6 100644 --- a/src/kiwano/renderer/helper.hpp +++ b/src/kiwano/renderer/win32/D2DDeviceResources.h @@ -19,10 +19,14 @@ // THE SOFTWARE. #pragma once -#include "../base/ComPtr.hpp" -#include "../math/helper.h" -#include "Color.h" +#include "../Font.h" +#include "../Color.h" +#include "../../math/math.h" +#include "../../base/Resource.h" +#include "../../2d/TextStyle.hpp" +#include #include +#include namespace kiwano { @@ -38,6 +42,16 @@ namespace kiwano } } + template + inline T* SafeAcquire(T* ptr) + { + if (ptr != nullptr) + { + ptr->AddRef(); + } + return ptr; + } + // // Point2F // @@ -150,3 +164,65 @@ namespace kiwano } } } + +namespace kiwano +{ + MIDL_INTERFACE("5706684a-bf6d-4b03-b627-094758a33032") + KGE_API ID2DDeviceResources + : public IUnknown + { + public: + static HRESULT Create(ID2DDeviceResources** device_resources); + + virtual HRESULT CreateBitmapFromFile( + _Out_ ComPtr& bitmap, + _In_ String const& file_path + ) = 0; + + virtual HRESULT CreateBitmapFromResource( + _Out_ ComPtr& bitmap, + _In_ Resource const& res + ) = 0; + + virtual HRESULT CreateTextFormat( + _Out_ ComPtr& text_format, + _In_ Font const& font + ) const = 0; + + virtual HRESULT CreateTextLayout( + _Out_ ComPtr& text_layout, + _In_ String const& text, + _In_ TextStyle const& text_style, + _In_ ComPtr const& text_format + ) const = 0; + + virtual ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const = 0; + + virtual HRESULT SetD2DDevice( + _In_ ComPtr const& device + ) = 0; + + virtual void SetTargetBitmap( + _In_ ComPtr const& target + ) = 0; + + virtual void DiscardResources() = 0; + + inline ID2D1Factory1* GetFactory() const { KGE_ASSERT(factory_); return factory_.get(); } + inline IWICImagingFactory* GetWICImagingFactory() const { KGE_ASSERT(imaging_factory_); return imaging_factory_.get(); } + inline IDWriteFactory* GetDWriteFactory() const { KGE_ASSERT(dwrite_factory_); return dwrite_factory_.get(); } + inline ID2D1Device* GetDevice() const { KGE_ASSERT(device_); return device_.get(); } + inline ID2D1DeviceContext* GetDeviceContext() const { KGE_ASSERT(device_context_); return device_context_.get(); } + inline ID2D1Bitmap1* GetTargetBitmap() const { KGE_ASSERT(target_bitmap_); return target_bitmap_.get(); } + + protected: + ComPtr factory_; + ComPtr device_; + ComPtr device_context_; + ComPtr target_bitmap_; + + ComPtr imaging_factory_; + ComPtr dwrite_factory_; + }; + +} diff --git a/src/kiwano/renderer/D3D10DeviceResources.cpp b/src/kiwano/renderer/win32/D3D10DeviceResources.cpp similarity index 99% rename from src/kiwano/renderer/D3D10DeviceResources.cpp rename to src/kiwano/renderer/win32/D3D10DeviceResources.cpp index db3b3839..ef5374d6 100644 --- a/src/kiwano/renderer/D3D10DeviceResources.cpp +++ b/src/kiwano/renderer/win32/D3D10DeviceResources.cpp @@ -20,7 +20,7 @@ #include "D3D10DeviceResources.h" -#include "../base/Logger.h" +#include "../../base/Logger.h" #pragma comment(lib, "d3d10_1.lib") @@ -163,7 +163,10 @@ namespace kiwano { res->AddRef(); - DX::SafeRelease(*device_resources); + if (*device_resources) + { + (*device_resources)->Release(); + } (*device_resources) = res; } else diff --git a/src/kiwano/renderer/D3D10DeviceResources.h b/src/kiwano/renderer/win32/D3D10DeviceResources.h similarity index 98% rename from src/kiwano/renderer/D3D10DeviceResources.h rename to src/kiwano/renderer/win32/D3D10DeviceResources.h index 2e01c72f..ad926305 100644 --- a/src/kiwano/renderer/D3D10DeviceResources.h +++ b/src/kiwano/renderer/win32/D3D10DeviceResources.h @@ -20,7 +20,7 @@ #pragma once -#include "../macros.h" +#include "../../macros.h" #include "D2DDeviceResources.h" #include "D3DDeviceResourcesBase.h" diff --git a/src/kiwano/renderer/D3D11DeviceResources.cpp b/src/kiwano/renderer/win32/D3D11DeviceResources.cpp similarity index 99% rename from src/kiwano/renderer/D3D11DeviceResources.cpp rename to src/kiwano/renderer/win32/D3D11DeviceResources.cpp index 07f052dc..3eeadb82 100644 --- a/src/kiwano/renderer/D3D11DeviceResources.cpp +++ b/src/kiwano/renderer/win32/D3D11DeviceResources.cpp @@ -20,7 +20,7 @@ #include "D3D11DeviceResources.h" -#include "../base/Logger.h" +#include "../../base/Logger.h" #include // IsWindows10OrGreater #pragma comment(lib, "d3d11.lib") @@ -140,7 +140,10 @@ namespace kiwano { res->AddRef(); - DX::SafeRelease(*device_resources); + if (*device_resources) + { + (*device_resources)->Release(); + } (*device_resources) = res; } else diff --git a/src/kiwano/renderer/D3D11DeviceResources.h b/src/kiwano/renderer/win32/D3D11DeviceResources.h similarity index 98% rename from src/kiwano/renderer/D3D11DeviceResources.h rename to src/kiwano/renderer/win32/D3D11DeviceResources.h index acf41a8d..dc26fd30 100644 --- a/src/kiwano/renderer/D3D11DeviceResources.h +++ b/src/kiwano/renderer/win32/D3D11DeviceResources.h @@ -20,7 +20,7 @@ #pragma once -#include "../macros.h" +#include "../../macros.h" #include "D2DDeviceResources.h" #include "D3DDeviceResourcesBase.h" diff --git a/src/kiwano/renderer/D3DDeviceResourcesBase.h b/src/kiwano/renderer/win32/D3DDeviceResourcesBase.h similarity index 92% rename from src/kiwano/renderer/D3DDeviceResourcesBase.h rename to src/kiwano/renderer/win32/D3DDeviceResourcesBase.h index e378649c..ca4631ff 100644 --- a/src/kiwano/renderer/D3DDeviceResourcesBase.h +++ b/src/kiwano/renderer/win32/D3DDeviceResourcesBase.h @@ -19,16 +19,12 @@ // THE SOFTWARE. #pragma once -#include "../macros.h" -#include "../math/helper.h" -#include "Color.h" #include namespace kiwano { - MIDL_INTERFACE("fb99fa64-d9cf-4e0e-9c75-90514797b01d") - KGE_API ID3DDeviceResourcesBase : public IUnknown + ID3DDeviceResourcesBase : public IUnknown { public: virtual HRESULT Present(bool vsync) = 0; diff --git a/src/kiwano/renderer/win32/FontCollectionLoader.cpp b/src/kiwano/renderer/win32/FontCollectionLoader.cpp new file mode 100644 index 00000000..ad97e532 --- /dev/null +++ b/src/kiwano/renderer/win32/FontCollectionLoader.cpp @@ -0,0 +1,908 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// _Out_ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "FontCollectionLoader.h" + +namespace kiwano +{ + //////////////////////////////////////////////////////////////////////////////////////// + // + // FontCollectionLoader + // + //////////////////////////////////////////////////////////////////////////////////////// + + class FontCollectionLoader + : public IFontCollectionLoader + { + public: + FontCollectionLoader() + : refCount_(0) + { + } + + // 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 collectionKeySize, + _Out_ IDWriteFontFileEnumerator** fontFileEnumerator + ); + + private: + ULONG refCount_; + }; + + HRESULT IFontCollectionLoader::Create(_Out_ IFontCollectionLoader** ppCollectionLoader) + { + HRESULT hr = S_OK; + + if (!ppCollectionLoader) + { + hr = E_POINTER; + } + + if (SUCCEEDED(hr)) + { + FontCollectionLoader* pCollectionLoader = new (std::nothrow) FontCollectionLoader; + hr = pCollectionLoader ? S_OK : E_OUTOFMEMORY; + + if (SUCCEEDED(hr)) + { + DX::SafeRelease(*ppCollectionLoader); + (*ppCollectionLoader) = DX::SafeAcquire(pCollectionLoader); + } + } + 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; + } + + HRESULT STDMETHODCALLTYPE FontCollectionLoader::CreateEnumeratorFromKey( + IDWriteFactory* pFactory, + void const* collectionKey, + UINT32 collectionKeySize, + _Out_ IDWriteFontFileEnumerator** fontFileEnumerator + ) + { + HRESULT hr = S_OK; + + if (collectionKey == NULL || collectionKeySize != sizeof(String)) + hr = E_INVALIDARG; + + if (SUCCEEDED(hr)) + { + IFontFileEnumerator* pEnumerator = NULL; + hr = IFontFileEnumerator::Create(&pEnumerator, pFactory); + + if (SUCCEEDED(hr)) + { + String const* filePath = static_cast(collectionKey); + UINT32 const fileCount = collectionKeySize / sizeof(String); + + hr = pEnumerator->SetFilePaths(filePath, fileCount); + } + + if (SUCCEEDED(hr)) + { + *fontFileEnumerator = DX::SafeAcquire(pEnumerator); + } + } + return hr; + } + + + //////////////////////////////////////////////////////////////////////////////////////// + // + // FontFileEnumerator + // + //////////////////////////////////////////////////////////////////////////////////////// + + class FontFileEnumerator + : public IFontFileEnumerator + { + public: + FontFileEnumerator(); + + STDMETHOD(Initialize)( + IDWriteFactory* pFactory + ); + + STDMETHOD(SetFilePaths)( + String const* filePath, + UINT32 const fileCount + ); + + ~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(); + + // IDWriteFontFileEnumerator methods + virtual HRESULT STDMETHODCALLTYPE MoveNext(_Out_ BOOL* hasCurrentFile); + virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(_Out_ IDWriteFontFile** fontFile); + + private: + ULONG refCount_; + + IDWriteFactory* pFactory_; + IDWriteFontFile* currentFile_; + Vector filePaths_; + size_t nextIndex_; + }; + + HRESULT IFontFileEnumerator::Create(_Out_ IFontFileEnumerator** ppEnumerator, IDWriteFactory* pFactory) + { + HRESULT hr = S_OK; + + if (!ppEnumerator) + { + hr = E_POINTER; + } + + if (SUCCEEDED(hr)) + { + FontFileEnumerator* pEnumerator = new (std::nothrow) FontFileEnumerator; + hr = pEnumerator ? S_OK : E_OUTOFMEMORY; + + if (SUCCEEDED(hr)) + { + hr = pEnumerator->Initialize(pFactory); + } + + if (SUCCEEDED(hr)) + { + DX::SafeRelease(*ppEnumerator); + (*ppEnumerator) = DX::SafeAcquire(pEnumerator); + } + } + return hr; + } + + FontFileEnumerator::FontFileEnumerator() + : refCount_(0) + , pFactory_(NULL) + , currentFile_(NULL) + , nextIndex_(0) + { + } + + STDMETHODIMP FontFileEnumerator::Initialize( + IDWriteFactory* pFactory + ) + { + if (pFactory) + { + pFactory_ = DX::SafeAcquire(pFactory); + return S_OK; + } + return E_INVALIDARG; + } + + STDMETHODIMP FontFileEnumerator::SetFilePaths( + String const* filePath, + UINT32 const fileCount + ) + { + try + { + filePaths_.assign(filePath, filePath + fileCount); + } + catch (std::bad_alloc&) + { + return E_OUTOFMEMORY; + } + catch (...) + { + return E_FAIL; + } + 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; + + *hasCurrentFile = FALSE; + DX::SafeRelease(currentFile_); + + if (nextIndex_ < filePaths_.size()) + { + hr = pFactory_->CreateFontFileReference( + filePaths_[nextIndex_].c_str(), + NULL, + ¤tFile_ + ); + + if (SUCCEEDED(hr)) + { + *hasCurrentFile = TRUE; + + ++nextIndex_; + } + } + + return hr; + } + + HRESULT STDMETHODCALLTYPE FontFileEnumerator::GetCurrentFontFile(_Out_ IDWriteFontFile** fontFile) + { + *fontFile = DX::SafeAcquire(currentFile_); + + return (currentFile_ != NULL) ? S_OK : E_FAIL; + } + + + //////////////////////////////////////////////////////////////////////////////////////// + // + // ResourceFontCollectionLoader + // + //////////////////////////////////////////////////////////////////////////////////////// + + class ResourceFontCollectionLoader + : public IResourceFontCollectionLoader + { + public: + ResourceFontCollectionLoader(IDWriteFontFileLoader* pFileLoader) + : refCount_(0) + , pFileLoader_(pFileLoader) + { + } + + // 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 collectionKeySize, + _Out_ IDWriteFontFileEnumerator** fontFileEnumerator + ); + + private: + ULONG refCount_; + IDWriteFontFileLoader* pFileLoader_; + }; + + HRESULT IResourceFontCollectionLoader::Create(_Out_ IResourceFontCollectionLoader** ppCollectionLoader, IDWriteFontFileLoader* pFileLoader) + { + HRESULT hr = S_OK; + + if (!ppCollectionLoader) + { + hr = E_POINTER; + } + + if (SUCCEEDED(hr)) + { + ResourceFontCollectionLoader* pCollectionLoader = new (std::nothrow) ResourceFontCollectionLoader(pFileLoader); + hr = pCollectionLoader ? S_OK : E_OUTOFMEMORY; + + if (SUCCEEDED(hr)) + { + DX::SafeRelease(*ppCollectionLoader); + (*ppCollectionLoader) = DX::SafeAcquire(pCollectionLoader); + } + } + 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; + } + + HRESULT STDMETHODCALLTYPE ResourceFontCollectionLoader::CreateEnumeratorFromKey( + IDWriteFactory* pFactory, + void const* collectionKey, + UINT32 collectionKeySize, + _Out_ IDWriteFontFileEnumerator** fontFileEnumerator + ) + { + HRESULT hr = S_OK; + + if (collectionKey == NULL || collectionKeySize % sizeof(UINT) != 0) + hr = E_INVALIDARG; + + if (SUCCEEDED(hr)) + { + IResourceFontFileEnumerator* pEnumerator = NULL; + hr = IResourceFontFileEnumerator::Create(&pEnumerator, pFactory, pFileLoader_); + + if (SUCCEEDED(hr)) + { + UINT const* resourceID = static_cast(collectionKey); + UINT32 const resourceCount = collectionKeySize / sizeof(UINT); + + hr = pEnumerator->SetResources(resourceID, resourceCount); + } + + if (SUCCEEDED(hr)) + { + *fontFileEnumerator = DX::SafeAcquire(pEnumerator); + } + } + return hr; + } + + + //////////////////////////////////////////////////////////////////////////////////////// + // + // ResourceFontFileLoader + // + //////////////////////////////////////////////////////////////////////////////////////// + + class ResourceFontFileLoader + : public IResourceFontFileLoader + { + public: + ResourceFontFileLoader() + : refCount_(0) + { + } + + // 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 fontFileReferenceKeySize, + _Out_ IDWriteFontFileStream** fontFileStream + ); + + private: + ULONG refCount_; + }; + + HRESULT IResourceFontFileLoader::Create(_Out_ IResourceFontFileLoader** ppFileLoader) + { + HRESULT hr = S_OK; + + if (!ppFileLoader) + { + hr = E_POINTER; + } + + if (SUCCEEDED(hr)) + { + ResourceFontFileLoader* pFileLoader = new (std::nothrow) ResourceFontFileLoader; + hr = pFileLoader ? S_OK : E_OUTOFMEMORY; + + if (SUCCEEDED(hr)) + { + (*ppFileLoader) = DX::SafeAcquire(pFileLoader); + } + } + return hr; + } + + HRESULT STDMETHODCALLTYPE ResourceFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) + { + if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) + { + *ppvObject = this; + AddRef(); + return S_OK; + } + else + { + *ppvObject = NULL; + return E_NOINTERFACE; + } + } + + ULONG STDMETHODCALLTYPE ResourceFontFileLoader::AddRef() + { + return InterlockedIncrement(&refCount_); + } + + ULONG STDMETHODCALLTYPE ResourceFontFileLoader::Release() + { + ULONG newCount = InterlockedDecrement(&refCount_); + if (newCount == 0) + delete this; + + return newCount; + } + + HRESULT STDMETHODCALLTYPE ResourceFontFileLoader::CreateStreamFromKey( + void const* fontFileReferenceKey, + UINT32 fontFileReferenceKeySize, + _Out_ IDWriteFontFileStream** fontFileStream + ) + { + HRESULT hr = S_OK; + + // Make sure the key is the right size. + if (fontFileReferenceKeySize != sizeof(UINT)) + hr = E_INVALIDARG; + + if (SUCCEEDED(hr)) + { + // Create the pFileStream object. + IResourceFontFileStream* pFileStream = NULL; + UINT resourceID = *static_cast(fontFileReferenceKey); + + hr = IResourceFontFileStream::Create(&pFileStream, resourceID); + + if (SUCCEEDED(hr)) + { + DX::SafeRelease(*fontFileStream); + *fontFileStream = DX::SafeAcquire(pFileStream); + } + } + return hr; + } + + + //////////////////////////////////////////////////////////////////////////////////////// + // + // ResourceFontFileEnumerator + // + //////////////////////////////////////////////////////////////////////////////////////// + + class ResourceFontFileEnumerator + : public IResourceFontFileEnumerator + { + public: + ResourceFontFileEnumerator(); + + STDMETHOD(Initialize)( + IDWriteFactory* pFactory, + IDWriteFontFileLoader* pLoader + ); + + STDMETHOD(SetResources)( + UINT const* resourceID, + UINT32 const resourceCount + ); + + ~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(); + + // IDWriteFontFileEnumerator methods + virtual HRESULT STDMETHODCALLTYPE MoveNext(_Out_ BOOL* hasCurrentFile); + virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(_Out_ IDWriteFontFile** fontFile); + + private: + ULONG refCount_; + + IDWriteFactory* pFactory_; + IDWriteFontFile* currentFile_; + IDWriteFontFileLoader* pLoader_; + Vector resourceIDs_; + size_t nextIndex_; + }; + + HRESULT IResourceFontFileEnumerator::Create(_Out_ IResourceFontFileEnumerator** ppEnumerator, IDWriteFactory* pFactory, IDWriteFontFileLoader* pFileLoader) + { + HRESULT hr = S_OK; + + if (!ppEnumerator) + { + hr = E_POINTER; + } + + if (SUCCEEDED(hr)) + { + ResourceFontFileEnumerator* pEnumerator = new (std::nothrow) ResourceFontFileEnumerator; + hr = pEnumerator ? S_OK : E_OUTOFMEMORY; + + if (SUCCEEDED(hr)) + { + hr = pEnumerator->Initialize(pFactory, pFileLoader); + } + + if (SUCCEEDED(hr)) + { + DX::SafeRelease(*ppEnumerator); + (*ppEnumerator) = DX::SafeAcquire(pEnumerator); + } + } + return hr; + } + + ResourceFontFileEnumerator::ResourceFontFileEnumerator() + : refCount_(0) + , pFactory_(NULL) + , currentFile_(NULL) + , nextIndex_(0) + , pLoader_(NULL) + { + } + + STDMETHODIMP ResourceFontFileEnumerator::Initialize( + IDWriteFactory* pFactory, + IDWriteFontFileLoader* pLoader + ) + { + if (pFactory && pLoader) + { + pFactory_ = DX::SafeAcquire(pFactory); + pLoader_ = DX::SafeAcquire(pLoader); + return S_OK; + } + return E_INVALIDARG; + } + + STDMETHODIMP ResourceFontFileEnumerator::SetResources( + UINT const* resourceID, + UINT32 const resourceCount + ) + { + try + { + resourceIDs_.assign(resourceID, resourceID + resourceCount); + } + catch (std::bad_alloc&) + { + return E_OUTOFMEMORY; + } + catch (...) + { + return E_FAIL; + } + 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; + + *hasCurrentFile = FALSE; + DX::SafeRelease(currentFile_); + + if (nextIndex_ < resourceIDs_.size()) + { + hr = pFactory_->CreateCustomFontFileReference( + &resourceIDs_[nextIndex_], + sizeof(UINT), + pLoader_, + ¤tFile_ + ); + + if (SUCCEEDED(hr)) + { + *hasCurrentFile = TRUE; + + ++nextIndex_; + } + } + + return hr; + } + + HRESULT STDMETHODCALLTYPE ResourceFontFileEnumerator::GetCurrentFontFile(_Out_ IDWriteFontFile** fontFile) + { + *fontFile = DX::SafeAcquire(currentFile_); + + return (currentFile_ != NULL) ? S_OK : E_FAIL; + } + + + //////////////////////////////////////////////////////////////////////////////////////// + // + // ResourceFontFileStream + // + //////////////////////////////////////////////////////////////////////////////////////// + + class ResourceFontFileStream + : public IResourceFontFileStream + { + public: + ResourceFontFileStream(); + + STDMETHOD(Initialize)( + const UINT resourceID + ); + + // 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 + ); + + virtual void STDMETHODCALLTYPE ReleaseFileFragment( + void* fragmentContext + ); + + virtual HRESULT STDMETHODCALLTYPE GetFileSize( + _Out_ UINT64* fileSize + ); + + virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime( + _Out_ UINT64* lastWriteTime + ); + + bool IsInitialized() + { + return resourcePtr_ != NULL; + } + + private: + ULONG refCount_; + LPVOID resourcePtr_; + DWORD resourceSize_; + }; + + HRESULT IResourceFontFileStream::Create(_Out_ IResourceFontFileStream** ppStream, const UINT resourceID) + { + HRESULT hr = S_OK; + + if (!ppStream) + { + hr = E_POINTER; + } + + if (SUCCEEDED(hr)) + { + ResourceFontFileStream* pFileStream = new (std::nothrow) ResourceFontFileStream; + hr = pFileStream ? S_OK : E_OUTOFMEMORY; + + if (SUCCEEDED(hr)) + { + hr = pFileStream->Initialize(resourceID); + } + + if (SUCCEEDED(hr)) + { + DX::SafeRelease(*ppStream); + (*ppStream) = DX::SafeAcquire(pFileStream); + } + } + return hr; + } + + ResourceFontFileStream::ResourceFontFileStream() + : refCount_(0) + , resourcePtr_(NULL) + , resourceSize_(0) + { + } + + STDMETHODIMP ResourceFontFileStream::Initialize( + const UINT resourceID + ) + { + HRESULT hr = S_OK; + + if (!Resource{ resourceID, RT_FONT }.Load(resourcePtr_, resourceSize_)) + { + hr = E_FAIL; + } + 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 + ) + { + // The pLoader is responsible for doing a bounds check. + if (fileOffset <= resourceSize_ && + fragmentSize <= resourceSize_ - fileOffset) + { + *fragmentStart = static_cast(resourcePtr_) + static_cast(fileOffset); + *fragmentContext = NULL; + return S_OK; + } + else + { + *fragmentStart = NULL; + *fragmentContext = NULL; + return E_FAIL; + } + } + + void STDMETHODCALLTYPE ResourceFontFileStream::ReleaseFileFragment( + void* fragmentContext + ) + { + } + + HRESULT STDMETHODCALLTYPE ResourceFontFileStream::GetFileSize( + _Out_ UINT64* fileSize + ) + { + *fileSize = resourceSize_; + return S_OK; + } + + HRESULT STDMETHODCALLTYPE ResourceFontFileStream::GetLastWriteTime( + _Out_ UINT64* lastWriteTime + ) + { + *lastWriteTime = 0; + return E_NOTIMPL; + } + +} diff --git a/src/kiwano/renderer/win32/FontCollectionLoader.h b/src/kiwano/renderer/win32/FontCollectionLoader.h new file mode 100644 index 00000000..49479d48 --- /dev/null +++ b/src/kiwano/renderer/win32/FontCollectionLoader.h @@ -0,0 +1,99 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITH_Out_ WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// _Out_ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include "D2DDeviceResources.h" + +namespace kiwano +{ + interface DWRITE_DECLARE_INTERFACE("7EC7A55A-1964-4098-83E0-EFA7C12C6EF7") + IFontCollectionLoader : public IDWriteFontCollectionLoader + { + public: + static HRESULT Create( + _Out_ IFontCollectionLoader** ppCollectionLoader + ); + }; + + + interface DWRITE_DECLARE_INTERFACE("0A1A3F2A-85F2-41BB-80FD-EC01271740C4") + IFontFileEnumerator : public IDWriteFontFileEnumerator + { + public: + static HRESULT Create( + _Out_ IFontFileEnumerator** ppEnumerator, + IDWriteFactory* pFactory + ); + + STDMETHOD(SetFilePaths)( + String const* filePath, + UINT32 const fileCount + ) PURE; + }; + + + interface DWRITE_DECLARE_INTERFACE("F2C411F0-2FB0-4D0E-8C73-D2B8F30137A4") + IResourceFontCollectionLoader : public IDWriteFontCollectionLoader + { + public: + static HRESULT Create( + _Out_ IResourceFontCollectionLoader** ppCollectionLoader, + IDWriteFontFileLoader * pFileLoader + ); + }; + + + interface DWRITE_DECLARE_INTERFACE("08D21408-6FC1-4E36-A4EB-4DA16BE3399E") + IResourceFontFileLoader : public IDWriteFontFileLoader + { + public: + static HRESULT Create( + _Out_ IResourceFontFileLoader** ppFileLoader + ); + }; + + + interface DWRITE_DECLARE_INTERFACE("0AD0EC74-7503-46E8-8899-520175ECCB4A") + IResourceFontFileEnumerator : public IDWriteFontFileEnumerator + { + public: + static HRESULT Create( + _Out_ IResourceFontFileEnumerator** ppEnumerator, + IDWriteFactory* pFactory, + IDWriteFontFileLoader* pFileLoader + ); + + STDMETHOD(SetResources)( + UINT const* resourceID, + UINT32 const resourceCount + ) PURE; + }; + + + interface DWRITE_DECLARE_INTERFACE("A6267450-27F3-4948-995F-FF8345A72F88") + IResourceFontFileStream : public IDWriteFontFileStream + { + public: + static HRESULT Create( + _Out_ IResourceFontFileStream** ppStream, + const UINT resourceID + ); + }; +} diff --git a/src/kiwano/renderer/TextRenderer.cpp b/src/kiwano/renderer/win32/TextRenderer.cpp similarity index 99% rename from src/kiwano/renderer/TextRenderer.cpp rename to src/kiwano/renderer/win32/TextRenderer.cpp index a0694a21..9c4e8aca 100644 --- a/src/kiwano/renderer/TextRenderer.cpp +++ b/src/kiwano/renderer/win32/TextRenderer.cpp @@ -98,7 +98,7 @@ namespace kiwano unsigned long STDMETHODCALLTYPE AddRef(); unsigned long STDMETHODCALLTYPE Release(); HRESULT STDMETHODCALLTYPE QueryInterface( - IID const& riid, + REFIID riid, void** ppvObject ); @@ -454,24 +454,6 @@ namespace kiwano return E_NOTIMPL; } - STDMETHODIMP_(unsigned long) TextRenderer::AddRef() - { - return InterlockedIncrement(&cRefCount_); - } - - STDMETHODIMP_(unsigned long) TextRenderer::Release() - { - unsigned long newCount = InterlockedDecrement(&cRefCount_); - - if (newCount == 0) - { - delete this; - return 0; - } - - return newCount; - } - STDMETHODIMP TextRenderer::IsPixelSnappingDisabled( __maybenull void* clientDrawingContext, __out BOOL* isDisabled) @@ -506,8 +488,26 @@ namespace kiwano return S_OK; } + STDMETHODIMP_(unsigned long) TextRenderer::AddRef() + { + return InterlockedIncrement(&cRefCount_); + } + + STDMETHODIMP_(unsigned long) TextRenderer::Release() + { + unsigned long newCount = InterlockedDecrement(&cRefCount_); + + if (newCount == 0) + { + delete this; + return 0; + } + + return newCount; + } + STDMETHODIMP TextRenderer::QueryInterface( - IID const& riid, + REFIID riid, void** ppvObject) { if (__uuidof(ITextRenderer) == riid) diff --git a/src/kiwano/renderer/TextRenderer.h b/src/kiwano/renderer/win32/TextRenderer.h similarity index 94% rename from src/kiwano/renderer/TextRenderer.h rename to src/kiwano/renderer/win32/TextRenderer.h index ea5e47de..604a232e 100644 --- a/src/kiwano/renderer/TextRenderer.h +++ b/src/kiwano/renderer/win32/TextRenderer.h @@ -19,13 +19,12 @@ // THE SOFTWARE. #pragma once -#include "helper.hpp" -#include +#include "D2DDeviceResources.h" namespace kiwano { - interface DWRITE_DECLARE_INTERFACE("b293e798-9916-4096-a3c1-e5d4039dfa64") ITextRenderer - : public IDWriteTextRenderer + interface DWRITE_DECLARE_INTERFACE("b293e798-9916-4096-a3c1-e5d4039dfa64") + ITextRenderer : public IDWriteTextRenderer { public: static KGE_API HRESULT Create( diff --git a/src/kiwano/utils/FileUtil.cpp b/src/kiwano/utils/FileUtil.cpp index 25d3974c..942a7dc7 100644 --- a/src/kiwano/utils/FileUtil.cpp +++ b/src/kiwano/utils/FileUtil.cpp @@ -79,4 +79,4 @@ namespace kiwano return (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); } -} \ No newline at end of file +} diff --git a/src/kiwano/utils/ResourceCache.cpp b/src/kiwano/utils/ResourceCache.cpp index 7d86fac6..1e821f7c 100644 --- a/src/kiwano/utils/ResourceCache.cpp +++ b/src/kiwano/utils/ResourceCache.cpp @@ -323,7 +323,7 @@ namespace kiwano return 0; } - bool ResourceCache::AddObj(String const& id, ObjectPtr obj) + bool ResourceCache::AddObjectBase(String const& id, ObjectBasePtr obj) { if (obj) { diff --git a/src/kiwano/utils/ResourceCache.h b/src/kiwano/utils/ResourceCache.h index 8a7da7b8..06f2b6c7 100644 --- a/src/kiwano/utils/ResourceCache.h +++ b/src/kiwano/utils/ResourceCache.h @@ -76,7 +76,7 @@ namespace kiwano size_t AddFrameSequence(String const& id, FrameSequencePtr frames); // 添加对象 - bool AddObj(String const& id, ObjectPtr obj); + bool AddObjectBase(String const& id, ObjectBasePtr obj); // 获取图片资源 FramePtr GetFrame(String const& id) const; @@ -108,6 +108,6 @@ namespace kiwano virtual ~ResourceCache(); protected: - UnorderedMap cache_; + UnorderedMap cache_; }; }