Update exceptions
This commit is contained in:
parent
6a25403841
commit
a34184dd18
|
|
@ -61,7 +61,6 @@
|
|||
<ClInclude Include="..\..\src\kiwano\platform\FileSystem.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\platform\Input.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\platform\win32\ComPtr.hpp" />
|
||||
<ClInclude Include="..\..\src\kiwano\platform\win32\helper.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\platform\win32\libraries.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\platform\win32\WindowImpl.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\platform\Window.h" />
|
||||
|
|
@ -137,7 +136,6 @@
|
|||
<ClCompile Include="..\..\src\kiwano\platform\FileSystem.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\platform\Input.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\platform\win32\libraries.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\platform\win32\StackWalker.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\platform\win32\WindowImpl.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\platform\Window.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\Brush.cpp" />
|
||||
|
|
|
|||
|
|
@ -165,9 +165,6 @@
|
|||
<ClInclude Include="..\..\src\kiwano\platform\win32\libraries.h">
|
||||
<Filter>platform\win32</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\platform\win32\helper.h">
|
||||
<Filter>platform\win32</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\core\event\Event.h">
|
||||
<Filter>core\event</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -416,9 +413,6 @@
|
|||
<ClCompile Include="..\..\src\kiwano\platform\win32\libraries.cpp">
|
||||
<Filter>platform\win32</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\platform\win32\StackWalker.cpp">
|
||||
<Filter>platform\win32</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\core\event\Event.cpp">
|
||||
<Filter>core\event</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include <kiwano-audio/AudioEngine.h>
|
||||
#include <kiwano-audio/libraries.h>
|
||||
#include <kiwano/core/Logger.h>
|
||||
#include <kiwano/platform/win32/helper.h> // win32::ThrowIfFailed
|
||||
#include <kiwano/core/Exception.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -51,7 +51,7 @@ void AudioEngine::SetupComponent()
|
|||
hr = x_audio2_->CreateMasteringVoice(&mastering_voice_);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Create audio resources failed");
|
||||
ThrowIfFailed(hr, "Create audio resources failed");
|
||||
}
|
||||
|
||||
void AudioEngine::DestroyComponent()
|
||||
|
|
@ -85,7 +85,8 @@ bool AudioEngine::CreateSound(Sound& sound, const Transcoder::Buffer& buffer)
|
|||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IXAudio2SourceVoice* voice = nullptr;
|
||||
hr = x_audio2_->CreateSourceVoice(&voice, buffer.format, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
|
||||
|
||||
hr = x_audio2_->CreateSourceVoice(&voice, buffer.format, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
|
|
@ -100,8 +101,12 @@ bool AudioEngine::CreateSound(Sound& sound, const Transcoder::Buffer& buffer)
|
|||
}
|
||||
}
|
||||
|
||||
win32::WarnIfFailed(hr, "Create sound failed");
|
||||
return SUCCEEDED(hr);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_ERROR("Create IXAudio2SourceVoice failed with HRESULT of %08X", hr);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AudioEngine::Open()
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include <kiwano-audio/libraries.h>
|
||||
#include <kiwano/core/Logger.h>
|
||||
#include <kiwano/core/Exception.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -51,8 +52,7 @@ XAudio2::XAudio2()
|
|||
}
|
||||
else
|
||||
{
|
||||
KGE_ERROR("Load xaudio2.dll failed");
|
||||
throw std::runtime_error("Load xaudio2.dll failed");
|
||||
KGE_THROW_SYSTEM_ERROR(HRESULT_FROM_WIN32(GetLastError()), "Load xaudio2.dll failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -79,8 +79,7 @@ MediaFoundation::MediaFoundation()
|
|||
}
|
||||
else
|
||||
{
|
||||
KGE_ERROR("Load Mfplat.dll failed");
|
||||
throw std::runtime_error("Load Mfplat.dll failed");
|
||||
KGE_THROW_SYSTEM_ERROR(HRESULT_FROM_WIN32(GetLastError()), "Load Mfplat.dll failed");
|
||||
}
|
||||
|
||||
if (mfreadwrite.Load("Mfreadwrite.dll"))
|
||||
|
|
@ -92,8 +91,7 @@ MediaFoundation::MediaFoundation()
|
|||
}
|
||||
else
|
||||
{
|
||||
KGE_ERROR("Load Mfreadwrite.dll failed");
|
||||
throw std::runtime_error("Load Mfreadwrite.dll failed");
|
||||
KGE_THROW_SYSTEM_ERROR(HRESULT_FROM_WIN32(GetLastError()), "Load Mfreadwrite.dll failed");
|
||||
}
|
||||
}
|
||||
} // namespace dlls
|
||||
|
|
|
|||
|
|
@ -19,42 +19,275 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano/core/Exception.h>
|
||||
#include <kiwano/core/Library.h>
|
||||
#include <kiwano/core/Logger.h>
|
||||
|
||||
#if defined(KGE_WIN32)
|
||||
#include <comdef.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
Exception::Exception()
|
||||
class com_error_category : public std::error_category
|
||||
{
|
||||
}
|
||||
public:
|
||||
using error_category::error_category;
|
||||
|
||||
Exception::Exception(String const& message)
|
||||
: message_(message)
|
||||
{
|
||||
}
|
||||
const char* name() const noexcept override
|
||||
{
|
||||
return "com";
|
||||
}
|
||||
|
||||
Exception::~Exception()
|
||||
{
|
||||
}
|
||||
// @note If _UNICODE is defined the error description gets
|
||||
// converted to an ANSI string using the CP_ACP codepage.
|
||||
std::string message(int hr) const override
|
||||
{
|
||||
#ifdef _UNICODE
|
||||
auto message = WideToMultiByte(_com_error{ hr }.ErrorMessage());
|
||||
return message.c_str();
|
||||
#else
|
||||
return _com_error{ hr }.ErrorMessage();
|
||||
#endif
|
||||
}
|
||||
|
||||
const String& Exception::ToString() const
|
||||
{
|
||||
return message_;
|
||||
}
|
||||
// Make error_condition for error code (generic if possible)
|
||||
// @return system's default error condition if error value can be mapped to a Windows error, error condition with
|
||||
// com category otherwise
|
||||
std::error_condition default_error_condition(int hr) const noexcept override
|
||||
{
|
||||
if (HRESULT_CODE(hr) || hr == 0)
|
||||
// system error condition
|
||||
return std::system_category().default_error_condition(HRESULT_CODE(hr));
|
||||
else
|
||||
// special error condition
|
||||
return { hr, com_category() };
|
||||
}
|
||||
};
|
||||
|
||||
const char* Exception::what() const
|
||||
{
|
||||
return message_.c_str();
|
||||
}
|
||||
static kiwano::com_error_category com_ecat;
|
||||
|
||||
SystemException::SystemException()
|
||||
: code_(0)
|
||||
{
|
||||
}
|
||||
|
||||
SystemException::SystemException(ErrorCodeType code, String const& message)
|
||||
: Exception(message)
|
||||
, code_(code)
|
||||
const std::error_category& com_category() noexcept
|
||||
{
|
||||
return com_ecat;
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
||||
|
||||
KGE_SUPPRESS_WARNING_PUSH
|
||||
KGE_SUPPRESS_WARNING(4091)
|
||||
#include <dbghelp.h> // ignored on left of 'type' when no variable is declared
|
||||
KGE_SUPPRESS_WARNING_POP
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// SymInitialize()
|
||||
typedef BOOL(__stdcall* PFN_SymInitialize)(IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess);
|
||||
|
||||
// SymCleanup()
|
||||
typedef BOOL(__stdcall* PFN_SymCleanup)(IN HANDLE hProcess);
|
||||
|
||||
// SymGetLineFromAddr64()
|
||||
typedef BOOL(__stdcall* PFN_SymGetLineFromAddr64)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PDWORD pdwDisplacement,
|
||||
OUT PIMAGEHLP_LINE64 Line);
|
||||
|
||||
// SymGetSymFromAddr64()
|
||||
typedef BOOL(__stdcall* PFN_SymGetSymFromAddr64)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PDWORD64 pdwDisplacement,
|
||||
OUT PIMAGEHLP_SYMBOL64 Symbol);
|
||||
|
||||
// StackWalk64()
|
||||
typedef BOOL(__stdcall* PFN_StackWalk64)(DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame,
|
||||
PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
|
||||
PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
|
||||
PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
|
||||
PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
|
||||
|
||||
// SymFunctionTableAccess64()
|
||||
typedef PVOID(__stdcall* PFN_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase);
|
||||
|
||||
// SymGetModuleBase64()
|
||||
typedef DWORD64(__stdcall* PFN_SymGetModuleBase64)(IN HANDLE hProcess, IN DWORD64 dwAddr);
|
||||
|
||||
struct DbgHelp
|
||||
{
|
||||
Library dbgLib;
|
||||
PFN_SymInitialize SymInitialize;
|
||||
PFN_SymCleanup SymCleanup;
|
||||
PFN_SymGetLineFromAddr64 SymGetLineFromAddr64;
|
||||
PFN_SymGetSymFromAddr64 SymGetSymFromAddr64;
|
||||
PFN_StackWalk64 StackWalk64;
|
||||
PFN_SymFunctionTableAccess64 SymFunctionTableAccess64;
|
||||
PFN_SymGetModuleBase64 SymGetModuleBase64;
|
||||
|
||||
DbgHelp()
|
||||
: SymInitialize(nullptr)
|
||||
, SymCleanup(nullptr)
|
||||
, SymGetLineFromAddr64(nullptr)
|
||||
, SymGetSymFromAddr64(nullptr)
|
||||
, StackWalk64(nullptr)
|
||||
, SymFunctionTableAccess64(nullptr)
|
||||
, SymGetModuleBase64(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool Load()
|
||||
{
|
||||
if (IsValid())
|
||||
return true;
|
||||
|
||||
if (!dbgLib.Load("dbghelp.dll"))
|
||||
return false;
|
||||
|
||||
SymInitialize = dbgLib.GetProcess<PFN_SymInitialize>("SymInitialize");
|
||||
SymCleanup = dbgLib.GetProcess<PFN_SymCleanup>("SymCleanup");
|
||||
SymGetLineFromAddr64 = dbgLib.GetProcess<PFN_SymGetLineFromAddr64>("SymGetLineFromAddr64");
|
||||
SymGetSymFromAddr64 = dbgLib.GetProcess<PFN_SymGetSymFromAddr64>("SymGetSymFromAddr64");
|
||||
StackWalk64 = dbgLib.GetProcess<PFN_StackWalk64>("StackWalk64");
|
||||
SymFunctionTableAccess64 = dbgLib.GetProcess<PFN_SymFunctionTableAccess64>("SymFunctionTableAccess64");
|
||||
SymGetModuleBase64 = dbgLib.GetProcess<PFN_SymGetModuleBase64>("SymGetModuleBase64");
|
||||
|
||||
if (!IsValid())
|
||||
{
|
||||
dbgLib.Free();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return SymInitialize && SymCleanup && SymGetLineFromAddr64 && SymGetSymFromAddr64 && StackWalk64
|
||||
&& SymFunctionTableAccess64 && SymGetModuleBase64;
|
||||
}
|
||||
};
|
||||
|
||||
DbgHelp g_DbgHelp;
|
||||
|
||||
} // namespace
|
||||
|
||||
void PrintErrorCode(LPCSTR lpszFunction)
|
||||
{
|
||||
KGE_ERROR("%s failed with HRESULT of %08X", lpszFunction, HRESULT_FROM_WIN32(GetLastError()));
|
||||
}
|
||||
|
||||
void PrintCallStackOnContext(PCONTEXT pContext)
|
||||
{
|
||||
if (!g_DbgHelp.Load())
|
||||
return;
|
||||
|
||||
if (pContext == nullptr)
|
||||
return;
|
||||
|
||||
DWORD dwMachineType;
|
||||
STACKFRAME64 sf;
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
HANDLE hThread = GetCurrentThread();
|
||||
|
||||
ZeroMemory(&sf, sizeof(sf));
|
||||
|
||||
sf.AddrPC.Mode = AddrModeFlat;
|
||||
sf.AddrFrame.Mode = AddrModeFlat;
|
||||
sf.AddrStack.Mode = AddrModeFlat;
|
||||
sf.AddrBStore.Mode = AddrModeFlat;
|
||||
|
||||
#ifdef _M_IX86
|
||||
dwMachineType = IMAGE_FILE_MACHINE_I386;
|
||||
sf.AddrPC.Offset = pContext->Eip;
|
||||
sf.AddrFrame.Offset = pContext->Ebp;
|
||||
sf.AddrStack.Offset = pContext->Esp;
|
||||
#elif _M_X64
|
||||
dwMachineType = IMAGE_FILE_MACHINE_AMD64;
|
||||
sf.AddrPC.Offset = pContext->Rip;
|
||||
sf.AddrFrame.Offset = pContext->Rsp;
|
||||
sf.AddrStack.Offset = pContext->Rsp;
|
||||
#elif _M_IA64
|
||||
dwMachineType = IMAGE_FILE_MACHINE_IA64;
|
||||
sf.AddrPC.Offset = pContext->StIIP;
|
||||
sf.AddrFrame.Offset = pContext->IntSp;
|
||||
sf.AddrBStore.Offset = pContext->RsBSP;
|
||||
sf.AddrStack.Offset = pContext->IntSp;
|
||||
#else
|
||||
#error "Platform not supported!"
|
||||
#endif
|
||||
|
||||
constexpr int STACKWALK_MAX_NAMELEN = 1024;
|
||||
BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN];
|
||||
|
||||
KGE_ERROR("========== Stack trace ==========");
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (!g_DbgHelp.StackWalk64(dwMachineType, hProcess, hThread, &sf, pContext, NULL,
|
||||
g_DbgHelp.SymFunctionTableAccess64, g_DbgHelp.SymGetModuleBase64, NULL))
|
||||
{
|
||||
PrintErrorCode("StackWalk64");
|
||||
break;
|
||||
}
|
||||
|
||||
if (sf.AddrFrame.Offset == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ZeroMemory(symbolBuffer, sizeof(symbolBuffer));
|
||||
|
||||
IMAGEHLP_SYMBOL64* pSymbol = reinterpret_cast<IMAGEHLP_SYMBOL64*>(symbolBuffer);
|
||||
pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
||||
pSymbol->MaxNameLength = STACKWALK_MAX_NAMELEN;
|
||||
|
||||
DWORD64 dwDisplacement;
|
||||
if (!g_DbgHelp.SymGetSymFromAddr64(hProcess, sf.AddrPC.Offset, &dwDisplacement, pSymbol))
|
||||
{
|
||||
PrintErrorCode("SymGetSymFromAddr64");
|
||||
break;
|
||||
}
|
||||
|
||||
IMAGEHLP_LINE64 lineInfo;
|
||||
ZeroMemory(&lineInfo, sizeof(IMAGEHLP_LINE64));
|
||||
lineInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||
|
||||
DWORD dwLineDisplacement;
|
||||
if (g_DbgHelp.SymGetLineFromAddr64(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo))
|
||||
{
|
||||
KGE_ERROR("%s (%d): %s", lineInfo.FileName, lineInfo.LineNumber, pSymbol->Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
KGE_ERROR("(filename not available): %s", pSymbol->Name);
|
||||
}
|
||||
|
||||
if (sf.AddrReturn.Offset == 0)
|
||||
{
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StackTracer::StackTracer() {}
|
||||
|
||||
void StackTracer::Print() const
|
||||
{
|
||||
CONTEXT ctx;
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
|
||||
if (!g_DbgHelp.Load())
|
||||
return;
|
||||
|
||||
if (!g_DbgHelp.SymInitialize(hProcess, NULL, TRUE))
|
||||
return;
|
||||
|
||||
RtlCaptureContext(&ctx);
|
||||
|
||||
PrintCallStackOnContext(&ctx);
|
||||
|
||||
g_DbgHelp.SymCleanup(hProcess);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -20,72 +20,83 @@
|
|||
|
||||
#pragma once
|
||||
#include <kiwano/core/Common.h>
|
||||
#include <kiwano/macros.h>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
|
||||
#define KGE_THROW(MESSAGE) \
|
||||
do \
|
||||
{ \
|
||||
kiwano::StackTracer().Print(); \
|
||||
throw std::runtime_error(MESSAGE); \
|
||||
} while (0)
|
||||
|
||||
#define KGE_THROW_SYSTEM_ERROR(ERRCODE, MESSAGE) \
|
||||
do \
|
||||
{ \
|
||||
kiwano::StackTracer().Print(); \
|
||||
throw std::system_error(std::error_code(kiwano::error_enum(ERRCODE)), MESSAGE); \
|
||||
} while (0)
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 异常
|
||||
*/
|
||||
class KGE_API Exception : public std::exception
|
||||
class StackTracer
|
||||
{
|
||||
public:
|
||||
Exception();
|
||||
StackTracer();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 构造异常
|
||||
/// @param message 描述异常的信息
|
||||
explicit Exception(String const& message);
|
||||
|
||||
virtual ~Exception();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 转为解释性字符串
|
||||
const String& ToString() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 转为解释性字符串
|
||||
virtual const char* what() const override;
|
||||
|
||||
protected:
|
||||
String message_;
|
||||
void Print() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 系统异常
|
||||
*/
|
||||
class SystemException : public Exception
|
||||
#ifdef KGE_WIN32
|
||||
|
||||
// Enables classifying error codes
|
||||
// @note We don't bother listing all possible values
|
||||
enum class error_enum
|
||||
{
|
||||
public:
|
||||
#if defined(KGE_WIN32)
|
||||
/// \~chinese
|
||||
/// @brief 错误代码类型
|
||||
typedef HRESULT ErrorCodeType;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
typedef std::errc error_enum;
|
||||
|
||||
#endif
|
||||
|
||||
SystemException();
|
||||
} // namespace kiwano
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 构造系统异常
|
||||
/// @param code 错误代码
|
||||
/// @param message 描述异常的信息
|
||||
SystemException(ErrorCodeType code, String const& message);
|
||||
#ifdef KGE_WIN32
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取错误代码
|
||||
ErrorCodeType GetErrorCode() const;
|
||||
|
||||
private:
|
||||
ErrorCodeType code_;
|
||||
};
|
||||
|
||||
inline SystemException::ErrorCodeType SystemException::GetErrorCode() const
|
||||
namespace std
|
||||
{
|
||||
return code_;
|
||||
template <>
|
||||
struct is_error_code_enum<kiwano::error_enum> : true_type
|
||||
{
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
const std::error_category& com_category() noexcept;
|
||||
|
||||
inline std::error_code make_error_code(kiwano::error_enum errc) noexcept
|
||||
{
|
||||
return std::error_code(static_cast<int>(errc), kiwano::com_category());
|
||||
}
|
||||
|
||||
inline std::error_condition make_error_condition(kiwano::error_enum errc) noexcept
|
||||
{
|
||||
return std::error_condition(static_cast<int>(errc), kiwano::com_category());
|
||||
}
|
||||
|
||||
inline void ThrowIfFailed(HRESULT hr, const String& message)
|
||||
{
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_THROW_SYSTEM_ERROR(hr, message.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
||||
#endif // KGE_WIN32
|
||||
|
|
|
|||
|
|
@ -358,7 +358,7 @@ Duration Duration::Parse(const String& format)
|
|||
|
||||
if (!std::regex_match(format.c_str(), duration_regex))
|
||||
{
|
||||
throw Exception("Duration::Parse failed, invalid duration");
|
||||
KGE_THROW("Duration::Parse failed, invalid duration");
|
||||
}
|
||||
|
||||
if (format.empty() || format == "0")
|
||||
|
|
@ -391,7 +391,7 @@ Duration Duration::Parse(const String& format)
|
|||
pos = i;
|
||||
|
||||
if (num_str.empty() || num_str == ".")
|
||||
throw Exception("Duration::Parse failed, invalid duration");
|
||||
KGE_THROW("Duration::Parse failed, invalid duration");
|
||||
|
||||
// 单位
|
||||
for (; i < len; ++i)
|
||||
|
|
@ -408,7 +408,7 @@ Duration Duration::Parse(const String& format)
|
|||
pos = i;
|
||||
|
||||
if (unit_map.find(unit_str) == unit_map.end())
|
||||
throw Exception("Duration::Parse failed, invalid duration");
|
||||
KGE_THROW("Duration::Parse failed, invalid duration");
|
||||
|
||||
double num = std::stod(num_str.c_str());
|
||||
Duration unit = unit_map.at(unit_str);
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ struct KGE_API Duration
|
|||
/// 例如: "300ms", "-1.5h", "2h45m"
|
||||
/// 允许的时间单位有 "ms", "s", "m", "h"
|
||||
/// @return 解析出的时间段
|
||||
/// @throw kiwano::Exception 传入一个不合法的格式时抛出
|
||||
/// @throw std::runtime_error 传入一个不合法的格式时抛出
|
||||
static Duration Parse(const String& str);
|
||||
|
||||
static const Duration Ms; ///< 毫秒
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ public:
|
|||
* @param icon 图标资源ID
|
||||
* @param resizable 窗口大小可拉伸
|
||||
* @param fullscreen 全屏模式
|
||||
* @throw kiwano::SystemException 窗口创建失败时抛出
|
||||
* @throw std::system_error 窗口创建失败时抛出
|
||||
*/
|
||||
virtual void Create(String const& title, uint32_t width, uint32_t height, uint32_t icon = 0, bool resizable = false,
|
||||
bool fullscreen = false) = 0;
|
||||
|
|
|
|||
|
|
@ -1,238 +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.
|
||||
|
||||
#include <kiwano/core/Library.h>
|
||||
#include <kiwano/core/Logger.h>
|
||||
#include <kiwano/macros.h>
|
||||
|
||||
KGE_SUPPRESS_WARNING_PUSH
|
||||
KGE_SUPPRESS_WARNING(4091)
|
||||
#include <dbghelp.h> // ignored on left of 'type' when no variable is declared
|
||||
KGE_SUPPRESS_WARNING_POP
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
namespace
|
||||
{
|
||||
|
||||
// SymInitialize()
|
||||
typedef BOOL(__stdcall* PFN_SymInitialize)(IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess);
|
||||
|
||||
// SymCleanup()
|
||||
typedef BOOL(__stdcall* PFN_SymCleanup)(IN HANDLE hProcess);
|
||||
|
||||
// SymGetLineFromAddr64()
|
||||
typedef BOOL(__stdcall* PFN_SymGetLineFromAddr64)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PDWORD pdwDisplacement,
|
||||
OUT PIMAGEHLP_LINE64 Line);
|
||||
|
||||
// SymGetSymFromAddr64()
|
||||
typedef BOOL(__stdcall* PFN_SymGetSymFromAddr64)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PDWORD64 pdwDisplacement,
|
||||
OUT PIMAGEHLP_SYMBOL64 Symbol);
|
||||
|
||||
// StackWalk64()
|
||||
typedef BOOL(__stdcall* PFN_StackWalk64)(DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame,
|
||||
PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
|
||||
PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
|
||||
PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
|
||||
PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
|
||||
|
||||
// SymFunctionTableAccess64()
|
||||
typedef PVOID(__stdcall* PFN_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase);
|
||||
|
||||
// SymGetModuleBase64()
|
||||
typedef DWORD64(__stdcall* PFN_SymGetModuleBase64)(IN HANDLE hProcess, IN DWORD64 dwAddr);
|
||||
|
||||
struct DbgHelp
|
||||
{
|
||||
Library dbgLib;
|
||||
PFN_SymInitialize SymInitialize;
|
||||
PFN_SymCleanup SymCleanup;
|
||||
PFN_SymGetLineFromAddr64 SymGetLineFromAddr64;
|
||||
PFN_SymGetSymFromAddr64 SymGetSymFromAddr64;
|
||||
PFN_StackWalk64 StackWalk64;
|
||||
PFN_SymFunctionTableAccess64 SymFunctionTableAccess64;
|
||||
PFN_SymGetModuleBase64 SymGetModuleBase64;
|
||||
|
||||
DbgHelp()
|
||||
: SymInitialize(nullptr)
|
||||
, SymCleanup(nullptr)
|
||||
, SymGetLineFromAddr64(nullptr)
|
||||
, SymGetSymFromAddr64(nullptr)
|
||||
, StackWalk64(nullptr)
|
||||
, SymFunctionTableAccess64(nullptr)
|
||||
, SymGetModuleBase64(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool Load()
|
||||
{
|
||||
if (IsValid())
|
||||
return true;
|
||||
|
||||
if (!dbgLib.Load("dbghelp.dll"))
|
||||
return false;
|
||||
|
||||
SymInitialize = dbgLib.GetProcess<PFN_SymInitialize>("SymInitialize");
|
||||
SymCleanup = dbgLib.GetProcess<PFN_SymCleanup>("SymCleanup");
|
||||
SymGetLineFromAddr64 = dbgLib.GetProcess<PFN_SymGetLineFromAddr64>("SymGetLineFromAddr64");
|
||||
SymGetSymFromAddr64 = dbgLib.GetProcess<PFN_SymGetSymFromAddr64>("SymGetSymFromAddr64");
|
||||
StackWalk64 = dbgLib.GetProcess<PFN_StackWalk64>("StackWalk64");
|
||||
SymFunctionTableAccess64 = dbgLib.GetProcess<PFN_SymFunctionTableAccess64>("SymFunctionTableAccess64");
|
||||
SymGetModuleBase64 = dbgLib.GetProcess<PFN_SymGetModuleBase64>("SymGetModuleBase64");
|
||||
|
||||
if (!IsValid())
|
||||
{
|
||||
dbgLib.Free();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return SymInitialize && SymCleanup && SymGetLineFromAddr64 && SymGetSymFromAddr64 && StackWalk64
|
||||
&& SymFunctionTableAccess64 && SymGetModuleBase64;
|
||||
}
|
||||
};
|
||||
|
||||
DbgHelp g_DbgHelp;
|
||||
} // namespace
|
||||
|
||||
void PrintErrorCode(LPCSTR lpszFunction)
|
||||
{
|
||||
KGE_ERROR("%s failed with HRESULT of %08X", lpszFunction, HRESULT_FROM_WIN32(GetLastError()));
|
||||
}
|
||||
|
||||
void PrintCallStackOnContext(PCONTEXT pContext)
|
||||
{
|
||||
if (!g_DbgHelp.Load())
|
||||
return;
|
||||
|
||||
if (pContext == nullptr)
|
||||
return;
|
||||
|
||||
DWORD dwMachineType;
|
||||
STACKFRAME64 sf;
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
HANDLE hThread = GetCurrentThread();
|
||||
|
||||
ZeroMemory(&sf, sizeof(sf));
|
||||
|
||||
sf.AddrPC.Mode = AddrModeFlat;
|
||||
sf.AddrFrame.Mode = AddrModeFlat;
|
||||
sf.AddrStack.Mode = AddrModeFlat;
|
||||
sf.AddrBStore.Mode = AddrModeFlat;
|
||||
|
||||
#ifdef _M_IX86
|
||||
dwMachineType = IMAGE_FILE_MACHINE_I386;
|
||||
sf.AddrPC.Offset = pContext->Eip;
|
||||
sf.AddrFrame.Offset = pContext->Ebp;
|
||||
sf.AddrStack.Offset = pContext->Esp;
|
||||
#elif _M_X64
|
||||
dwMachineType = IMAGE_FILE_MACHINE_AMD64;
|
||||
sf.AddrPC.Offset = pContext->Rip;
|
||||
sf.AddrFrame.Offset = pContext->Rsp;
|
||||
sf.AddrStack.Offset = pContext->Rsp;
|
||||
#elif _M_IA64
|
||||
dwMachineType = IMAGE_FILE_MACHINE_IA64;
|
||||
sf.AddrPC.Offset = pContext->StIIP;
|
||||
sf.AddrFrame.Offset = pContext->IntSp;
|
||||
sf.AddrBStore.Offset = pContext->RsBSP;
|
||||
sf.AddrStack.Offset = pContext->IntSp;
|
||||
#else
|
||||
#error "Platform not supported!"
|
||||
#endif
|
||||
|
||||
constexpr int STACKWALK_MAX_NAMELEN = 1024;
|
||||
BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN];
|
||||
|
||||
KGE_ERROR("========== Stack trace ==========");
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (!g_DbgHelp.StackWalk64(dwMachineType, hProcess, hThread, &sf, pContext, NULL,
|
||||
g_DbgHelp.SymFunctionTableAccess64, g_DbgHelp.SymGetModuleBase64, NULL))
|
||||
{
|
||||
PrintErrorCode("StackWalk64");
|
||||
break;
|
||||
}
|
||||
|
||||
if (sf.AddrFrame.Offset == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ZeroMemory(symbolBuffer, sizeof(symbolBuffer));
|
||||
|
||||
IMAGEHLP_SYMBOL64* pSymbol = reinterpret_cast<IMAGEHLP_SYMBOL64*>(symbolBuffer);
|
||||
pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
||||
pSymbol->MaxNameLength = STACKWALK_MAX_NAMELEN;
|
||||
|
||||
DWORD64 dwDisplacement;
|
||||
if (!g_DbgHelp.SymGetSymFromAddr64(hProcess, sf.AddrPC.Offset, &dwDisplacement, pSymbol))
|
||||
{
|
||||
PrintErrorCode("SymGetSymFromAddr64");
|
||||
break;
|
||||
}
|
||||
|
||||
IMAGEHLP_LINE64 lineInfo;
|
||||
ZeroMemory(&lineInfo, sizeof(IMAGEHLP_LINE64));
|
||||
lineInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||
|
||||
DWORD dwLineDisplacement;
|
||||
if (g_DbgHelp.SymGetLineFromAddr64(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo))
|
||||
{
|
||||
KGE_ERROR("%s (%d): %s", lineInfo.FileName, lineInfo.LineNumber, pSymbol->Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
KGE_ERROR("(filename not available): %s", pSymbol->Name);
|
||||
}
|
||||
|
||||
if (sf.AddrReturn.Offset == 0)
|
||||
{
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintCallStack()
|
||||
{
|
||||
CONTEXT ctx;
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
|
||||
if (!g_DbgHelp.Load())
|
||||
return;
|
||||
|
||||
if (!g_DbgHelp.SymInitialize(hProcess, NULL, TRUE))
|
||||
return;
|
||||
|
||||
RtlCaptureContext(&ctx);
|
||||
|
||||
PrintCallStackOnContext(&ctx);
|
||||
|
||||
g_DbgHelp.SymCleanup(hProcess);
|
||||
}
|
||||
|
||||
} // namespace win32
|
||||
} // namespace kiwano
|
||||
|
|
@ -236,9 +236,7 @@ void WindowImpl::Create(String const& title, uint32_t width, uint32_t height, ui
|
|||
if (handle_ == nullptr)
|
||||
{
|
||||
::UnregisterClassW(L"KiwanoAppWnd", hinst);
|
||||
|
||||
KGE_ERROR("Failed with HRESULT of %08X", HRESULT_FROM_WIN32(GetLastError()));
|
||||
throw SystemException(HRESULT_FROM_WIN32(GetLastError()), "Create window failed");
|
||||
KGE_THROW_SYSTEM_ERROR(HRESULT_FROM_WIN32(GetLastError()), "Create window failed");
|
||||
}
|
||||
|
||||
width_ = width;
|
||||
|
|
|
|||
|
|
@ -1,54 +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 <kiwano/core/Exception.h>
|
||||
#include <kiwano/core/Logger.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
void PrintCallStack();
|
||||
|
||||
void PrintCallStackOnContext(PCONTEXT pContext);
|
||||
|
||||
inline void ThrowIfFailed(HRESULT hr, const String& message)
|
||||
{
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PrintCallStack();
|
||||
|
||||
throw SystemException(hr, message);
|
||||
}
|
||||
}
|
||||
|
||||
inline void WarnIfFailed(HRESULT hr, const String& message)
|
||||
{
|
||||
if (FAILED(hr))
|
||||
{
|
||||
PrintCallStack();
|
||||
|
||||
KGE_WARN("Failed with HRESULT of %08X: ", hr, message.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace win32
|
||||
} // namespace kiwano
|
||||
|
|
@ -41,8 +41,7 @@ Shlwapi::Shlwapi()
|
|||
}
|
||||
else
|
||||
{
|
||||
KGE_ERROR("Load shlapi.dll failed");
|
||||
throw SystemException(HRESULT_FROM_WIN32(GetLastError()), "Load shlapi.dll failed");
|
||||
KGE_THROW_SYSTEM_ERROR(HRESULT_FROM_WIN32(GetLastError()), "Load shlapi.dll failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ void RenderContextImpl::BeginDraw()
|
|||
|
||||
void RenderContextImpl::EndDraw()
|
||||
{
|
||||
win32::ThrowIfFailed(render_target_->EndDraw(), "ID2D1RenderTarget EndDraw failed");
|
||||
ThrowIfFailed(render_target_->EndDraw(), "ID2D1RenderTarget EndDraw failed");
|
||||
|
||||
RenderContext::EndDraw();
|
||||
|
||||
|
|
@ -271,7 +271,7 @@ void RenderContextImpl::CreateTexture(Texture& texture, math::Vec2T<uint32_t> si
|
|||
texture.SetBitmap(saved_bitmap);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Create texture failed");
|
||||
ThrowIfFailed(hr, "Create texture failed");
|
||||
}
|
||||
|
||||
void RenderContextImpl::PushClipRect(Rect const& clip_rect)
|
||||
|
|
@ -302,7 +302,7 @@ void RenderContextImpl::PushLayer(Layer& layer)
|
|||
}
|
||||
else
|
||||
{
|
||||
win32::ThrowIfFailed(hr, "Create ID2D1Layer failed");
|
||||
ThrowIfFailed(hr, "Create ID2D1Layer failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ void RendererImpl::SetupComponent()
|
|||
{
|
||||
KGE_SYS_LOG("Creating device resources");
|
||||
|
||||
win32::ThrowIfFailed(::CoInitialize(nullptr), "CoInitialize failed");
|
||||
ThrowIfFailed(::CoInitialize(nullptr), "CoInitialize failed");
|
||||
|
||||
HWND target_window = WindowImpl::GetInstance().GetHandle();
|
||||
output_size_ = Window::GetInstance().GetSize();
|
||||
|
|
@ -112,7 +112,7 @@ void RendererImpl::SetupComponent()
|
|||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Create render resources failed");
|
||||
ThrowIfFailed(hr, "Create render resources failed");
|
||||
}
|
||||
|
||||
void RendererImpl::DestroyComponent()
|
||||
|
|
@ -165,7 +165,7 @@ void RendererImpl::Present()
|
|||
hr = HandleDeviceLost();
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Unexpected DXGI exception");
|
||||
ThrowIfFailed(hr, "Unexpected DXGI exception");
|
||||
}
|
||||
|
||||
void RendererImpl::HandleEvent(Event* evt)
|
||||
|
|
@ -206,7 +206,7 @@ void RendererImpl::CreateTexture(Texture& texture, String const& file_path)
|
|||
if (!FileSystem::GetInstance().IsFileExists(file_path))
|
||||
{
|
||||
KGE_WARN("Texture file '%s' not found!", file_path.c_str());
|
||||
hr = E_FAIL;
|
||||
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
|
|
@ -244,7 +244,7 @@ void RendererImpl::CreateTexture(Texture& texture, String const& file_path)
|
|||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
win32::ThrowIfFailed(hr, "Load texture failed");
|
||||
ThrowIfFailed(hr, "Load texture failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -311,7 +311,7 @@ void RendererImpl::CreateGifImage(GifImage& gif, String const& file_path)
|
|||
if (!FileSystem::GetInstance().IsFileExists(file_path))
|
||||
{
|
||||
KGE_WARN("Gif texture file '%s' not found!", file_path.c_str());
|
||||
hr = E_FAIL;
|
||||
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
|
|
@ -537,7 +537,7 @@ void RendererImpl::CreateFontCollection(Font& font, String const& file_path)
|
|||
if (!FileSystem::GetInstance().IsFileExists(file_path))
|
||||
{
|
||||
KGE_WARN("Font file '%s' not found!", file_path.c_str());
|
||||
hr = E_FAIL;
|
||||
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -562,7 +562,7 @@ void RendererImpl::CreateFontCollection(Font& font, String const& file_path)
|
|||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Create font collection failed");
|
||||
ThrowIfFailed(hr, "Create font collection failed");
|
||||
}
|
||||
|
||||
void RendererImpl::CreateFontCollection(Font& font, Resource const& res)
|
||||
|
|
@ -593,7 +593,7 @@ void RendererImpl::CreateFontCollection(Font& font, Resource const& res)
|
|||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Create font collection failed");
|
||||
ThrowIfFailed(hr, "Create font collection failed");
|
||||
}
|
||||
|
||||
void RendererImpl::CreateTextFormat(TextLayout& layout)
|
||||
|
|
@ -620,7 +620,7 @@ void RendererImpl::CreateTextFormat(TextLayout& layout)
|
|||
layout.SetTextFormat(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Create text format failed");
|
||||
ThrowIfFailed(hr, "Create text format failed");
|
||||
}
|
||||
|
||||
void RendererImpl::CreateTextLayout(TextLayout& layout)
|
||||
|
|
@ -644,7 +644,7 @@ void RendererImpl::CreateTextLayout(TextLayout& layout)
|
|||
layout.SetTextLayout(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Create text layout failed");
|
||||
ThrowIfFailed(hr, "Create text layout failed");
|
||||
}
|
||||
|
||||
void RendererImpl::CreateLineShape(Shape& shape, Point const& begin_pos, Point const& end_pos)
|
||||
|
|
@ -680,7 +680,7 @@ void RendererImpl::CreateLineShape(Shape& shape, Point const& begin_pos, Point c
|
|||
shape.SetGeometry(path_geo);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Create ID2D1PathGeometry failed");
|
||||
ThrowIfFailed(hr, "Create ID2D1PathGeometry failed");
|
||||
}
|
||||
|
||||
void RendererImpl::CreateRectShape(Shape& shape, Rect const& rect)
|
||||
|
|
@ -702,7 +702,7 @@ void RendererImpl::CreateRectShape(Shape& shape, Rect const& rect)
|
|||
shape.SetGeometry(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Create ID2D1RectangleGeometry failed");
|
||||
ThrowIfFailed(hr, "Create ID2D1RectangleGeometry failed");
|
||||
}
|
||||
|
||||
void RendererImpl::CreateRoundedRectShape(Shape& shape, Rect const& rect, Vec2 const& radius)
|
||||
|
|
@ -725,7 +725,7 @@ void RendererImpl::CreateRoundedRectShape(Shape& shape, Rect const& rect, Vec2 c
|
|||
shape.SetGeometry(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Create ID2D1RoundedRectangleGeometry failed");
|
||||
ThrowIfFailed(hr, "Create ID2D1RoundedRectangleGeometry failed");
|
||||
}
|
||||
|
||||
void RendererImpl::CreateEllipseShape(Shape& shape, Point const& center, Vec2 const& radius)
|
||||
|
|
@ -748,7 +748,7 @@ void RendererImpl::CreateEllipseShape(Shape& shape, Point const& center, Vec2 co
|
|||
shape.SetGeometry(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Create ID2D1EllipseGeometry failed");
|
||||
ThrowIfFailed(hr, "Create ID2D1EllipseGeometry failed");
|
||||
}
|
||||
|
||||
void RendererImpl::CreateShapeSink(ShapeSink& sink)
|
||||
|
|
@ -770,7 +770,7 @@ void RendererImpl::CreateShapeSink(ShapeSink& sink)
|
|||
sink.SetPathGeometry(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Create ID2D1PathGeometry failed");
|
||||
ThrowIfFailed(hr, "Create ID2D1PathGeometry failed");
|
||||
}
|
||||
|
||||
void RendererImpl::CreateBrush(Brush& brush, Color const& color)
|
||||
|
|
@ -804,7 +804,7 @@ void RendererImpl::CreateBrush(Brush& brush, Color const& color)
|
|||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Create ID2D1SolidBrush failed");
|
||||
ThrowIfFailed(hr, "Create ID2D1SolidBrush failed");
|
||||
}
|
||||
|
||||
void RendererImpl::CreateBrush(Brush& brush, LinearGradientStyle const& style)
|
||||
|
|
@ -836,7 +836,7 @@ void RendererImpl::CreateBrush(Brush& brush, LinearGradientStyle const& style)
|
|||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Create ID2D1LinearGradientBrush failed");
|
||||
ThrowIfFailed(hr, "Create ID2D1LinearGradientBrush failed");
|
||||
}
|
||||
|
||||
void RendererImpl::CreateBrush(Brush& brush, RadialGradientStyle const& style)
|
||||
|
|
@ -869,7 +869,7 @@ void RendererImpl::CreateBrush(Brush& brush, RadialGradientStyle const& style)
|
|||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Create ID2D1RadialGradientBrush failed");
|
||||
ThrowIfFailed(hr, "Create ID2D1RadialGradientBrush failed");
|
||||
}
|
||||
|
||||
void RendererImpl::CreateStrokeStyle(StrokeStyle& stroke_style, CapStyle cap, LineJoinStyle line_join,
|
||||
|
|
@ -896,7 +896,7 @@ void RendererImpl::CreateStrokeStyle(StrokeStyle& stroke_style, CapStyle cap, Li
|
|||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Create ID2D1StrokeStyle failed");
|
||||
ThrowIfFailed(hr, "Create ID2D1StrokeStyle failed");
|
||||
}
|
||||
|
||||
TextureRenderContextPtr RendererImpl::CreateTextureRenderContext(const Size* desired_size)
|
||||
|
|
@ -965,7 +965,7 @@ void RendererImpl::Resize(uint32_t width, uint32_t height)
|
|||
render_ctx_->Resize(output_size_);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr, "Resize render target failed");
|
||||
ThrowIfFailed(hr, "Resize render target failed");
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@
|
|||
|
||||
#pragma once
|
||||
#include <kiwano/math/Math.h>
|
||||
#include <kiwano/core/Exception.h>
|
||||
#include <kiwano/render/Color.h>
|
||||
#include <kiwano/platform/win32/ComPtr.hpp>
|
||||
#include <kiwano/platform/win32/helper.h>
|
||||
#include <d2d1.h>
|
||||
|
||||
namespace kiwano
|
||||
|
|
|
|||
|
|
@ -66,28 +66,28 @@ public:
|
|||
/// @brief 创建纹理内部资源
|
||||
/// @param[out] texture 纹理
|
||||
/// @param[in] file_path 图片路径
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateTexture(Texture& texture, String const& file_path) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建纹理内部资源
|
||||
/// @param[out] texture 纹理
|
||||
/// @param[in] resource 图片资源
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateTexture(Texture& texture, Resource const& resource) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建GIF图像内部资源
|
||||
/// @param[out] gif GIF图像
|
||||
/// @param[in] file_path 图片路径
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateGifImage(GifImage& gif, String const& file_path) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建GIF图像内部资源
|
||||
/// @param[out] gif GIF图像
|
||||
/// @param[in] resource 图片资源
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateGifImage(GifImage& gif, Resource const& resource) = 0;
|
||||
|
||||
/// \~chinese
|
||||
|
|
@ -95,33 +95,33 @@ public:
|
|||
/// @param[out] frame GIF图像帧
|
||||
/// @param[in] gif GIF图像
|
||||
/// @param[in] frame_index 帧下标
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateGifImageFrame(GifImage::Frame& frame, GifImage const& gif, size_t frame_index) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建字体集内部资源
|
||||
/// @param[out] font 字体
|
||||
/// @param[in] file_paths 字体文件路径
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateFontCollection(Font& font, String const& file_path) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建字体集内部资源
|
||||
/// @param[out] font 字体
|
||||
/// @param[in] res_arr 字体资源
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateFontCollection(Font& font, Resource const& res) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建文字格式内部资源
|
||||
/// @param[out] layout 字体布局
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateTextFormat(TextLayout& layout) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建文字布局内部资源
|
||||
/// @param[out] layout 字体布局
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateTextLayout(TextLayout& layout) = 0;
|
||||
|
||||
/// \~chinese
|
||||
|
|
@ -129,14 +129,14 @@ public:
|
|||
/// @param[out] shape 形状
|
||||
/// @param[in] begin_pos 线段起点
|
||||
/// @param[in] end_pos 线段终点
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateLineShape(Shape& shape, Point const& begin_pos, Point const& end_pos) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建矩形形状内部资源
|
||||
/// @param[out] shape 形状
|
||||
/// @param[in] rect 矩形大小
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateRectShape(Shape& shape, Rect const& rect) = 0;
|
||||
|
||||
/// \~chinese
|
||||
|
|
@ -144,7 +144,7 @@ public:
|
|||
/// @param[out] shape 形状
|
||||
/// @param[in] rect 矩形大小
|
||||
/// @param[in] radius 圆角半径
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateRoundedRectShape(Shape& shape, Rect const& rect, Vec2 const& radius) = 0;
|
||||
|
||||
/// \~chinese
|
||||
|
|
@ -152,34 +152,34 @@ public:
|
|||
/// @param[out] shape 形状
|
||||
/// @param[in] center 椭圆圆心
|
||||
/// @param[in] radius 椭圆半径
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateEllipseShape(Shape& shape, Point const& center, Vec2 const& radius) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建几何图形生成器内部资源
|
||||
/// @param[out] sink 形状生成器
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateShapeSink(ShapeSink& sink) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建纯色画刷内部资源
|
||||
/// @param[out] brush 画刷
|
||||
/// @param[in] color 颜色
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateBrush(Brush& brush, Color const& color) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建线性渐变画刷内部资源
|
||||
/// @param[out] brush 画刷
|
||||
/// @param[in] style 线性渐变样式
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateBrush(Brush& brush, LinearGradientStyle const& style) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建径向渐变画刷内部资源
|
||||
/// @param[out] brush 画刷
|
||||
/// @param[in] style 径向渐变样式
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateBrush(Brush& brush, RadialGradientStyle const& style) = 0;
|
||||
|
||||
/// \~chinese
|
||||
|
|
@ -190,7 +190,7 @@ public:
|
|||
/// @param[in] dash_array 虚线长度与间隙数组
|
||||
/// @param[in] dash_size 虚线数组大小
|
||||
/// @param[in] dash_offset 虚线偏移量
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual void CreateStrokeStyle(StrokeStyle& stroke_style, CapStyle cap, LineJoinStyle line_join,
|
||||
const float* dash_array, size_t dash_size, float dash_offset) = 0;
|
||||
|
||||
|
|
@ -198,7 +198,7 @@ public:
|
|||
/// @brief 创建纹理渲染上下文
|
||||
/// @param[in] desired_size 期望的输出大小
|
||||
/// @return 纹理渲染上下文
|
||||
/// @throw kiwano::SystemException 创建失败时抛出
|
||||
/// @throw std::system_error 创建失败时抛出
|
||||
virtual TextureRenderContextPtr CreateTextureRenderContext(const Size* desired_size = nullptr) = 0;
|
||||
|
||||
public:
|
||||
|
|
@ -216,7 +216,7 @@ public:
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 将绘制内容呈现至窗口
|
||||
/// @throw kiwano::SystemException 呈现失败时抛出
|
||||
/// @throw std::system_error 呈现失败时抛出
|
||||
virtual void Present() = 0;
|
||||
|
||||
/// \~chinese
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ void ShapeSink::Open()
|
|||
path_geo_.reset();
|
||||
Renderer::GetInstance().CreateShapeSink(*this);
|
||||
|
||||
win32::ThrowIfFailed(path_geo_->Open(&sink_), "Open ID2D1GeometrySink failed");
|
||||
ThrowIfFailed(path_geo_->Open(&sink_), "Open ID2D1GeometrySink failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ void ShapeSink::Close()
|
|||
{
|
||||
if (IsOpened())
|
||||
{
|
||||
win32::ThrowIfFailed(sink_->Close(), "Close ID2D1GeometrySink failed");
|
||||
ThrowIfFailed(sink_->Close(), "Close ID2D1GeometrySink failed");
|
||||
sink_.reset();
|
||||
}
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ ShapeSink& ShapeSink::AddShape(ShapePtr input, const Matrix3x2* input_matrix)
|
|||
|
||||
HRESULT hr =
|
||||
geo->Outline(DX::ConvertToMatrix3x2F(input_matrix), D2D1_DEFAULT_FLATTENING_TOLERANCE, sink_.get());
|
||||
win32::ThrowIfFailed(hr, "Get outline of ID2D1Geometry failed");
|
||||
ThrowIfFailed(hr, "Get outline of ID2D1Geometry failed");
|
||||
}
|
||||
return (*this);
|
||||
}
|
||||
|
|
@ -153,7 +153,7 @@ ShapeSink& ShapeSink::Combine(ShapePtr shape_a, ShapePtr shape_b, CombineMode mo
|
|||
|
||||
HRESULT hr = geo_a_raw->CombineWithGeometry(geo_b_raw.get(), D2D1_COMBINE_MODE(mode),
|
||||
DX::ConvertToMatrix3x2F(matrix), sink_.get());
|
||||
win32::ThrowIfFailed(hr, "Combine ID2D1Geometry failed");
|
||||
ThrowIfFailed(hr, "Combine ID2D1Geometry failed");
|
||||
}
|
||||
return (*this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ void TextLayout::SetWrapWidth(float wrap_width)
|
|||
}
|
||||
}
|
||||
}
|
||||
win32::ThrowIfFailed(hr, "Apply word wrapping to text layout failed");
|
||||
ThrowIfFailed(hr, "Apply word wrapping to text layout failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -202,7 +202,7 @@ void TextLayout::SetLineSpacing(float line_spacing)
|
|||
{
|
||||
hr = text_layout_->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_UNIFORM, line_spacing, line_spacing * 0.8f);
|
||||
}
|
||||
win32::ThrowIfFailed(hr, "Apply line spacing to text layout failed");
|
||||
ThrowIfFailed(hr, "Apply line spacing to text layout failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -213,7 +213,7 @@ void TextLayout::SetAlignment(TextAlign align)
|
|||
if (text_layout_)
|
||||
{
|
||||
HRESULT hr = text_layout_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(align));
|
||||
win32::ThrowIfFailed(hr, "Apply alignment style to text layout failed");
|
||||
ThrowIfFailed(hr, "Apply alignment style to text layout failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -228,7 +228,7 @@ void TextLayout::SetUnderline(bool enable, uint32_t start, uint32_t length)
|
|||
{
|
||||
hr = text_layout_->SetUnderline(enable, { start, length });
|
||||
}
|
||||
win32::ThrowIfFailed(hr, "Apply underline style to text layout failed");
|
||||
ThrowIfFailed(hr, "Apply underline style to text layout failed");
|
||||
}
|
||||
|
||||
void TextLayout::SetStrikethrough(bool enable, uint32_t start, uint32_t length)
|
||||
|
|
@ -242,7 +242,7 @@ void TextLayout::SetStrikethrough(bool enable, uint32_t start, uint32_t length)
|
|||
{
|
||||
hr = text_layout_->SetStrikethrough(enable, { start, length });
|
||||
}
|
||||
win32::ThrowIfFailed(hr, "Apply strikethrough style to text layout failed");
|
||||
ThrowIfFailed(hr, "Apply strikethrough style to text layout failed");
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ void Texture::CopyFrom(TexturePtr copy_from)
|
|||
{
|
||||
HRESULT hr = bitmap_->CopyFromBitmap(nullptr, copy_from->GetBitmap().get(), nullptr);
|
||||
|
||||
win32::ThrowIfFailed(hr, "Copy texture data failed");
|
||||
ThrowIfFailed(hr, "Copy texture data failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -152,7 +152,7 @@ void Texture::CopyFrom(TexturePtr copy_from, Rect const& src_rect, Point const&
|
|||
&D2D1::RectU(uint32_t(src_rect.GetLeft()), uint32_t(src_rect.GetTop()), uint32_t(src_rect.GetRight()),
|
||||
uint32_t(src_rect.GetBottom())));
|
||||
|
||||
win32::ThrowIfFailed(hr, "Copy texture data failed");
|
||||
ThrowIfFailed(hr, "Copy texture data failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue