diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/common/logger.cpp | 37 | ||||
-rw-r--r-- | src/platform/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/platform/graph/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/platform/native/CMakeLists.txt | 8 | ||||
-rw-r--r-- | src/platform/native/cursor.cpp | 10 | ||||
-rw-r--r-- | src/win/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/win/debug_logger.hpp | 6 | ||||
-rw-r--r-- | src/win/graph/direct/CMakeLists.txt | 8 | ||||
-rw-r--r-- | src/win/graph/direct/brush.cpp | 7 | ||||
-rw-r--r-- | src/win/graph/direct/factory.cpp (renamed from src/win/graph/direct/graph_factory.cpp) | 56 | ||||
-rw-r--r-- | src/win/graph/direct/font.cpp | 20 | ||||
-rw-r--r-- | src/win/graph/direct/geometry.cpp | 22 | ||||
-rw-r--r-- | src/win/graph/direct/painter.cpp | 80 | ||||
-rw-r--r-- | src/win/graph/direct/resource.cpp | 14 | ||||
-rw-r--r-- | src/win/graph/direct/text_layout.cpp | 47 | ||||
-rw-r--r-- | src/win/native/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/win/native/ui_application.cpp | 8 | ||||
-rw-r--r-- | src/win/string.cpp | 46 | ||||
-rw-r--r-- | src/win/string_util.cpp | 20 |
20 files changed, 201 insertions, 206 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index afbbc139..516d5f1b 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -2,7 +2,7 @@ set(CRU_BASE_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/common) add_library(cru_base STATIC logger.cpp ) -target_sources(cru_base INTERFACE +target_sources(cru_base PUBLIC ${CRU_BASE_INCLUDE_DIR}/base.hpp ${CRU_BASE_INCLUDE_DIR}/event.hpp ${CRU_BASE_INCLUDE_DIR}/format.hpp diff --git a/src/common/logger.cpp b/src/common/logger.cpp index 25223d91..6c1422f9 100644 --- a/src/common/logger.cpp +++ b/src/common/logger.cpp @@ -2,6 +2,7 @@ #include "cru/common/format.hpp" +#include <array> #include <cstdlib> #include <ctime> #include <memory> @@ -11,7 +12,7 @@ namespace cru::log { namespace { Logger *CreateLogger() { const auto logger = new Logger(); - logger->AddSource(new StdioLoggerSource()); + logger->AddSource(std::make_unique<StdioLogSource>()); return logger; } } // namespace @@ -21,45 +22,45 @@ Logger *Logger::GetInstance() { return logger.get(); } -Logger::~Logger() { - for (const auto i : sources_) { - delete i; - } +void Logger::AddSource(std::unique_ptr<ILogSource> source) { + sources_.push_back(std::move(source)); } -void Logger::AddSource(ILoggerSource *source) { sources_.push_back(source); } - -void Logger::RemoveSource(ILoggerSource *source) { sources_.remove(source); } +void Logger::RemoveSource(ILogSource *source) { + sources_.remove_if([source](const std::unique_ptr<ILogSource> &s) { + return s.get() == source; + }); +} namespace { -std::wstring_view LogLevelToString(LogLevel level) { +std::string_view LogLevelToString(LogLevel level) { switch (level) { case LogLevel::Debug: - return L"DEBUG"; + return "DEBUG"; case LogLevel::Info: - return L"INFO"; + return "INFO"; case LogLevel::Warn: - return L"WARN"; + return "WARN"; case LogLevel::Error: - return L"ERROR"; + return "ERROR"; default: std::abort(); } } } // namespace -void Logger::Log(LogLevel level, const std::wstring_view &s) { +void Logger::Log(LogLevel level, const std::string_view &s) { #ifndef CRU_DEBUG if (level == LogLevel::Debug) { return; } #endif - for (const auto source : sources_) { + for (const auto &source : sources_) { auto now = std::time(nullptr); - wchar_t buffer[50]; - std::wcsftime(buffer, 50, L"%c", std::localtime(&now)); + std::array<char, 50> buffer; + std::strftime(buffer.data(), 50, "%c", std::localtime(&now)); - source->Write(level, util::Format(L"[{}] {}: {}\n", buffer, + source->Write(level, util::Format("[{}] {}: {}\n", buffer.data(), LogLevelToString(level), s)); } } diff --git a/src/platform/CMakeLists.txt b/src/platform/CMakeLists.txt index c9eef482..01952106 100644 --- a/src/platform/CMakeLists.txt +++ b/src/platform/CMakeLists.txt @@ -1,12 +1,12 @@ set(CRU_PLATFORM_BASE_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/platform) add_library(cru_platform_base INTERFACE) target_sources(cru_platform_base INTERFACE + ${CRU_PLATFORM_BASE_INCLUDE_DIR}/check.hpp ${CRU_PLATFORM_BASE_INCLUDE_DIR}/exception.hpp - ${CRU_PLATFORM_BASE_INCLUDE_DIR}/graphic_base.hpp + ${CRU_PLATFORM_BASE_INCLUDE_DIR}/graph_base.hpp ${CRU_PLATFORM_BASE_INCLUDE_DIR}/heap_debug.hpp ${CRU_PLATFORM_BASE_INCLUDE_DIR}/matrix.hpp - ${CRU_PLATFORM_BASE_INCLUDE_DIR}/native_resource.hpp - ${CRU_PLATFORM_BASE_INCLUDE_DIR}/string_util.hpp + ${CRU_PLATFORM_BASE_INCLUDE_DIR}/resource.hpp ) target_link_libraries(cru_platform_base INTERFACE cru_base) diff --git a/src/platform/graph/CMakeLists.txt b/src/platform/graph/CMakeLists.txt index da76d296..dac28370 100644 --- a/src/platform/graph/CMakeLists.txt +++ b/src/platform/graph/CMakeLists.txt @@ -1,12 +1,14 @@ set(CRU_PLATFORM_GRAPH_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/platform/graph) add_library(cru_platform_graph INTERFACE) target_sources(cru_platform_graph INTERFACE + ${CRU_PLATFORM_GRAPH_INCLUDE_DIR}/base.hpp ${CRU_PLATFORM_GRAPH_INCLUDE_DIR}/brush.hpp ${CRU_PLATFORM_GRAPH_INCLUDE_DIR}/font.hpp ${CRU_PLATFORM_GRAPH_INCLUDE_DIR}/geometry.hpp - ${CRU_PLATFORM_GRAPH_INCLUDE_DIR}/graph_factory.hpp + ${CRU_PLATFORM_GRAPH_INCLUDE_DIR}/factory.hpp + ${CRU_PLATFORM_GRAPH_INCLUDE_DIR}/resource.hpp ${CRU_PLATFORM_GRAPH_INCLUDE_DIR}/painter.hpp ${CRU_PLATFORM_GRAPH_INCLUDE_DIR}/text_layout.hpp - ${CRU_PLATFORM_GRAPH_INCLUDE_DIR}/util/painter_util.hpp + ${CRU_PLATFORM_GRAPH_INCLUDE_DIR}/util/painter.hpp ) target_link_libraries(cru_platform_graph INTERFACE cru_platform_base) diff --git a/src/platform/native/CMakeLists.txt b/src/platform/native/CMakeLists.txt index 0e44fd55..bc7c4a63 100644 --- a/src/platform/native/CMakeLists.txt +++ b/src/platform/native/CMakeLists.txt @@ -1,12 +1,10 @@ set(CRU_PLATFORM_NATIVE_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/platform/native) -add_library(cru_platform_native STATIC - cursor.cpp -) -target_sources(cru_platform_native PUBLIC +add_library(cru_platform_native INTERFACE) +target_sources(cru_platform_native INTERFACE ${CRU_PLATFORM_NATIVE_INCLUDE_DIR}/basic_types.hpp ${CRU_PLATFORM_NATIVE_INCLUDE_DIR}/cursor.hpp ${CRU_PLATFORM_NATIVE_INCLUDE_DIR}/native_event.hpp ${CRU_PLATFORM_NATIVE_INCLUDE_DIR}/native_window.hpp ${CRU_PLATFORM_NATIVE_INCLUDE_DIR}/ui_application.hpp ) -target_link_libraries(cru_platform_native PUBLIC cru_platform_graph) +target_link_libraries(cru_platform_native INTERFACE cru_platform_graph) diff --git a/src/platform/native/cursor.cpp b/src/platform/native/cursor.cpp deleted file mode 100644 index b12aec40..00000000 --- a/src/platform/native/cursor.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "cru/platform/native/cursor.hpp" - -#include "cru/platform/native/ui_application.hpp" - -namespace cru::platform::native { -std::shared_ptr<Cursor> GetSystemCursor(SystemCursor type) { - return UiApplication::GetInstance()->GetCursorManager()->GetSystemCursor( - type); -} -} // namespace cru::platform::native diff --git a/src/win/CMakeLists.txt b/src/win/CMakeLists.txt index 8c58954d..5727e4c0 100644 --- a/src/win/CMakeLists.txt +++ b/src/win/CMakeLists.txt @@ -5,10 +5,11 @@ add_library(cru_win_base STATIC exception.cpp heap_debug.cpp - string_util.cpp + string.cpp ) target_sources(cru_win_base PUBLIC ${CRU_WIN_BASE_INCLUDE_DIR}/exception.hpp + ${CRU_WIN_BASE_INCLUDE_DIR}/string.hpp ${CRU_WIN_BASE_INCLUDE_DIR}/win_pre_config.hpp ) target_compile_definitions(cru_win_base PUBLIC UNICODE _UNICODE) # use unicode diff --git a/src/win/debug_logger.hpp b/src/win/debug_logger.hpp index ab6a2266..53c4859b 100644 --- a/src/win/debug_logger.hpp +++ b/src/win/debug_logger.hpp @@ -4,7 +4,7 @@ namespace cru::platform::win { -class WinDebugLoggerSource : public ::cru::log::ILoggerSource { +class WinDebugLoggerSource : public ::cru::log::ILogSource { public: WinDebugLoggerSource() = default; @@ -13,8 +13,8 @@ class WinDebugLoggerSource : public ::cru::log::ILoggerSource { ~WinDebugLoggerSource() = default; - void Write(::cru::log::LogLevel level, const std::wstring_view& s) override { - ::OutputDebugStringW(s.data()); + void Write(::cru::log::LogLevel level, const std::string_view& s) override { + ::OutputDebugStringA(s.data()); } }; } // namespace cru::platform::win diff --git a/src/win/graph/direct/CMakeLists.txt b/src/win/graph/direct/CMakeLists.txt index fa5e3a99..b277fa32 100644 --- a/src/win/graph/direct/CMakeLists.txt +++ b/src/win/graph/direct/CMakeLists.txt @@ -4,21 +4,21 @@ add_library(cru_win_graph_direct STATIC brush.cpp font.cpp geometry.cpp - graph_factory.cpp + factory.cpp painter.cpp + resource.cpp text_layout.cpp ) target_sources(cru_win_graph_direct PUBLIC ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/brush.hpp ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/com_resource.hpp ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/convert_util.hpp - ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/direct_factory.hpp ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/exception.hpp ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/font.hpp ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/geometry.hpp - ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/graph_factory.hpp + ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/factory.hpp ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/painter.hpp - ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/platform_id.hpp + ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/resource.hpp ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/text_layout.hpp ) target_link_libraries(cru_win_graph_direct PUBLIC D3D11 D2d1 DWrite cru_win_base cru_platform_graph) diff --git a/src/win/graph/direct/brush.cpp b/src/win/graph/direct/brush.cpp index 1f17cd03..17024a66 100644 --- a/src/win/graph/direct/brush.cpp +++ b/src/win/graph/direct/brush.cpp @@ -2,17 +2,18 @@ #include "cru/win/graph/direct/convert_util.hpp" #include "cru/win/graph/direct/exception.hpp" +#include "cru/win/graph/direct/factory.hpp" #include <cassert> namespace cru::platform::graph::win::direct { -D2DSolidColorBrush::D2DSolidColorBrush(IDirectFactory* factory) { - assert(factory); +D2DSolidColorBrush::D2DSolidColorBrush(DirectGraphFactory* factory) + : DirectGraphResource(factory) { ThrowIfFailed(factory->GetD2D1DeviceContext()->CreateSolidColorBrush( Convert(color_), &brush_)); } -void D2DSolidColorBrush::OnSetColor(const Color& color) { +void D2DSolidColorBrush::SetColor(const Color& color) { brush_->SetColor(Convert(color)); } } // namespace cru::platform::graph::win::direct diff --git a/src/win/graph/direct/graph_factory.cpp b/src/win/graph/direct/factory.cpp index 49752d0b..7882c3ee 100644 --- a/src/win/graph/direct/graph_factory.cpp +++ b/src/win/graph/direct/factory.cpp @@ -1,4 +1,4 @@ -#include "cru/win/graph/direct/graph_factory.hpp" +#include "cru/win/graph/direct/factory.hpp" #include "cru/win/graph/direct/brush.hpp" #include "cru/win/graph/direct/exception.hpp" @@ -11,37 +11,6 @@ #include <utility> namespace cru::platform::graph::win::direct { -namespace { -DirectGraphFactory* instance = nullptr; -} -} // namespace cru::platform::graph::win::direct - -namespace cru::platform::graph { -void GraphFactoryAutoDeleteExitHandler() { - const auto i = - ::cru::platform::graph::win::direct::instance; // avoid long namespace - // prefix - if (i == nullptr) return; - if (i->IsAutoDelete()) delete i; -} - -GraphFactory* GraphFactory::CreateInstance() { - auto& i = ::cru::platform::graph::win::direct::instance; // avoid long - // namespace prefix - assert(i == nullptr); - i = new ::cru::platform::graph::win::direct::DirectGraphFactory(); - std::atexit(&GraphFactoryAutoDeleteExitHandler); - return i; -} - -GraphFactory* GraphFactory::GetInstance() { - return ::cru::platform::graph::win::direct::instance; -} -} // namespace cru::platform::graph - -namespace cru::platform::graph::win::direct { -DirectGraphFactory* DirectGraphFactory::GetInstance() { return instance; } - DirectGraphFactory::DirectGraphFactory() { UINT creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; @@ -89,23 +58,22 @@ DirectGraphFactory::DirectGraphFactory() { &dwrite_system_font_collection_)); } -DirectGraphFactory::~DirectGraphFactory() { instance = nullptr; } - -D2DSolidColorBrush* DirectGraphFactory::CreateSolidColorBrush() { - return new D2DSolidColorBrush(this); +std::unique_ptr<ISolidColorBrush> DirectGraphFactory::CreateSolidColorBrush() { + return std::make_unique<D2DSolidColorBrush>(this); } -D2DGeometryBuilder* DirectGraphFactory::CreateGeometryBuilder() { - return new D2DGeometryBuilder(this); +std::unique_ptr<IGeometryBuilder> DirectGraphFactory::CreateGeometryBuilder() { + return std::make_unique<D2DGeometryBuilder>(this); } -DWriteFont* DirectGraphFactory::CreateFont( - const std::wstring_view& font_family, float font_size) { - return new DWriteFont(this, font_family, font_size); +std::unique_ptr<IFont> DirectGraphFactory::CreateFont( + const std::string_view& font_family, float font_size) { + return std::make_unique<DWriteFont>(this, font_family, font_size); } -DWriteTextLayout* DirectGraphFactory::CreateTextLayout( - std::shared_ptr<Font> font, std::wstring text) { - return new DWriteTextLayout(this, std::move(font), std::move(text)); +std::unique_ptr<ITextLayout> DirectGraphFactory::CreateTextLayout( + std::shared_ptr<IFont> font, std::string text) { + return std::make_unique<DWriteTextLayout>(this, std::move(font), + std::move(text)); } } // namespace cru::platform::graph::win::direct diff --git a/src/win/graph/direct/font.cpp b/src/win/graph/direct/font.cpp index 5d7b4483..8e881f84 100644 --- a/src/win/graph/direct/font.cpp +++ b/src/win/graph/direct/font.cpp @@ -1,25 +1,29 @@ #include "cru/win/graph/direct/font.hpp" -#include "cru/win/exception.hpp" #include "cru/win/graph/direct/exception.hpp" +#include "cru/win/graph/direct/factory.hpp" +#include "cru/win/string.hpp" #include <array> #include <cassert> #include <utility> namespace cru::platform::graph::win::direct { -DWriteFont::DWriteFont(IDirectFactory* factory, - const std::wstring_view& font_family, float font_size) { - assert(factory); +DWriteFont::DWriteFont(DirectGraphFactory* factory, + const std::string_view& font_family, float font_size) + : DirectGraphResource(factory) { + // Get locale std::array<wchar_t, LOCALE_NAME_MAX_LENGTH> buffer; if (!::GetUserDefaultLocaleName(buffer.data(), static_cast<int>(buffer.size()))) - throw platform::win::Win32Error(::GetLastError(), "Failed to get locale."); + throw platform::win::Win32Error( + ::GetLastError(), "Failed to get locale when create dwrite font."); + + const std::wstring&& wff = cru::platform::win::ToUtf16String(font_family); ThrowIfFailed(factory->GetDWriteFactory()->CreateTextFormat( - font_family.data(), nullptr, DWRITE_FONT_WEIGHT_NORMAL, - DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, font_size, - buffer.data(), &text_format_)); + wff.data(), nullptr, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, font_size, buffer.data(), &text_format_)); ThrowIfFailed(text_format_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER)); ThrowIfFailed( diff --git a/src/win/graph/direct/geometry.cpp b/src/win/graph/direct/geometry.cpp index 470addee..5540edab 100644 --- a/src/win/graph/direct/geometry.cpp +++ b/src/win/graph/direct/geometry.cpp @@ -2,16 +2,22 @@ #include "cru/win/graph/direct/convert_util.hpp" #include "cru/win/graph/direct/exception.hpp" +#include "cru/win/graph/direct/factory.hpp" #include <cassert> namespace cru::platform::graph::win::direct { -D2DGeometryBuilder::D2DGeometryBuilder(IDirectFactory* factory) { - assert(factory); +D2DGeometryBuilder::D2DGeometryBuilder(DirectGraphFactory* factory) + : DirectGraphResource(factory) { ThrowIfFailed(factory->GetD2D1Factory()->CreatePathGeometry(&geometry_)); ThrowIfFailed(geometry_->Open(&geometry_sink_)); } +void D2DGeometryBuilder::CheckValidation() { + if (!IsValid()) + throw ReuseException("The geometry builder is already disposed."); +} + void D2DGeometryBuilder::BeginFigure(const Point& point) { CheckValidation(); geometry_sink_->BeginFigure(Convert(point), D2D1_FIGURE_BEGIN_FILLED); @@ -35,19 +41,19 @@ void D2DGeometryBuilder::CloseFigure(bool close) { : D2D1_FIGURE_END_OPEN); } -Geometry* D2DGeometryBuilder::Build() { +std::unique_ptr<IGeometry> D2DGeometryBuilder::Build() { CheckValidation(); ThrowIfFailed(geometry_sink_->Close()); geometry_sink_ = nullptr; - const auto geometry = new D2DGeometry(std::move(geometry_)); + auto geometry = + std::make_unique<D2DGeometry>(GetDirectFactory(), std::move(geometry_)); geometry_ = nullptr; return geometry; } -D2DGeometry::D2DGeometry(Microsoft::WRL::ComPtr<ID2D1PathGeometry> geometry) { - assert(geometry); - geometry_ = std::move(geometry); -} +D2DGeometry::D2DGeometry(DirectGraphFactory* factory, + Microsoft::WRL::ComPtr<ID2D1PathGeometry> geometry) + : DirectGraphResource(factory), geometry_(std::move(geometry)) {} bool D2DGeometry::FillContains(const Point& point) { BOOL result; diff --git a/src/win/graph/direct/painter.cpp b/src/win/graph/direct/painter.cpp index 6fbbf957..fb2a6e7f 100644 --- a/src/win/graph/direct/painter.cpp +++ b/src/win/graph/direct/painter.cpp @@ -1,5 +1,6 @@ #include "cru/win/graph/direct/painter.hpp" +#include "cru/platform/check.hpp" #include "cru/win/graph/direct/brush.hpp" #include "cru/win/graph/direct/convert_util.hpp" #include "cru/win/graph/direct/exception.hpp" @@ -10,89 +11,63 @@ #include <type_traits> namespace cru::platform::graph::win::direct { - -namespace { -template <typename T, typename U, typename = void> -struct is_static_castable : std::false_type {}; - -template <typename T, typename U> -struct is_static_castable< - T, U, std::void_t<decltype(static_cast<U>(std::declval<T>()))>> - : std::true_type {}; - -template <typename TDes, typename TSrc> -TDes* CheckAndCast(TSrc* src) { - assert(src); - assert(IsDirectResource(src)); - if constexpr (is_static_castable<TSrc*, TDes*>::value) - return static_cast<TDes*>(src); - else { - TDes* d = dynamic_cast<TDes*>(src); - assert(d); - return d; - } -} -} // namespace - D2DPainter::D2DPainter(ID2D1RenderTarget* render_target) { assert(render_target); render_target_ = render_target; } platform::Matrix D2DPainter::GetTransform() { - assert(IsValid()); + CheckValidation(); D2D1_MATRIX_3X2_F m; render_target_->GetTransform(&m); return Convert(m); } void D2DPainter::SetTransform(const platform::Matrix& matrix) { - assert(IsValid()); + CheckValidation(); render_target_->SetTransform(Convert(matrix)); } void D2DPainter::Clear(const Color& color) { - assert(IsValid()); + CheckValidation(); render_target_->Clear(Convert(color)); } -void D2DPainter::StrokeRectangle(const Rect& rectangle, Brush* brush, +void D2DPainter::StrokeRectangle(const Rect& rectangle, IBrush* brush, float width) { - assert(IsValid()); - const auto b = CheckAndCast<ID2DBrush>(brush); + CheckValidation(); + const auto b = CheckPlatform<ID2DBrush>(brush, GetPlatformId()); render_target_->DrawRectangle(Convert(rectangle), b->GetD2DBrushInterface(), width); } -void D2DPainter::FillRectangle(const Rect& rectangle, Brush* brush) { - assert(IsValid()); - const auto b = CheckAndCast<ID2DBrush>(brush); +void D2DPainter::FillRectangle(const Rect& rectangle, IBrush* brush) { + CheckValidation(); + const auto b = CheckPlatform<ID2DBrush>(brush, GetPlatformId()); render_target_->FillRectangle(Convert(rectangle), b->GetD2DBrushInterface()); } -void D2DPainter::StrokeGeometry(Geometry* geometry, Brush* brush, float width) { - assert(IsValid()); - const auto g = CheckAndCast<D2DGeometry>(geometry); - const auto b = CheckAndCast<ID2DBrush>(brush); - +void D2DPainter::StrokeGeometry(IGeometry* geometry, IBrush* brush, + float width) { + CheckValidation(); + const auto g = CheckPlatform<D2DGeometry>(geometry, GetPlatformId()); + const auto b = CheckPlatform<ID2DBrush>(brush, GetPlatformId()); render_target_->DrawGeometry(g->GetComInterface(), b->GetD2DBrushInterface(), width); } -void D2DPainter::FillGeometry(Geometry* geometry, Brush* brush) { - assert(IsValid()); - const auto g = CheckAndCast<D2DGeometry>(geometry); - const auto b = CheckAndCast<ID2DBrush>(brush); - +void D2DPainter::FillGeometry(IGeometry* geometry, IBrush* brush) { + CheckValidation(); + const auto g = CheckPlatform<D2DGeometry>(geometry, GetPlatformId()); + const auto b = CheckPlatform<ID2DBrush>(brush, GetPlatformId()); render_target_->FillGeometry(g->GetComInterface(), b->GetD2DBrushInterface()); } -void D2DPainter::DrawText(const Point& offset, TextLayout* text_layout, - Brush* brush) { - assert(IsValid()); - const auto t = CheckAndCast<DWriteTextLayout>(text_layout); - const auto b = CheckAndCast<ID2DBrush>(brush); - +void D2DPainter::DrawText(const Point& offset, ITextLayout* text_layout, + IBrush* brush) { + CheckValidation(); + const auto t = CheckPlatform<DWriteTextLayout>(text_layout, GetPlatformId()); + const auto b = CheckPlatform<ID2DBrush>(brush, GetPlatformId()); render_target_->DrawTextLayout(Convert(offset), t->GetComInterface(), b->GetD2DBrushInterface()); } @@ -103,4 +78,11 @@ void D2DPainter::EndDraw() { DoEndDraw(); } } + +void D2DPainter::CheckValidation() { + if (!is_drawing_) { + throw cru::platform::ReuseException( + "Can't do that on painter after end drawing."); + } +} } // namespace cru::platform::graph::win::direct diff --git a/src/win/graph/direct/resource.cpp b/src/win/graph/direct/resource.cpp new file mode 100644 index 00000000..2acc91e4 --- /dev/null +++ b/src/win/graph/direct/resource.cpp @@ -0,0 +1,14 @@ +#include "cru/win/graph/direct/resource.hpp" + +#include "cru/win/graph/direct/factory.hpp" + +#include <cassert> + +namespace cru::platform::graph::win::direct { +DirectGraphResource::DirectGraphResource(DirectGraphFactory* factory) + : factory_(factory) { + assert(factory); +} + +IGraphFactory* DirectGraphResource::GetGraphFactory() { return factory_; } +} // namespace cru::platform::graph::win::direct diff --git a/src/win/graph/direct/text_layout.cpp b/src/win/graph/direct/text_layout.cpp index 23a14b2a..a1750799 100644 --- a/src/win/graph/direct/text_layout.cpp +++ b/src/win/graph/direct/text_layout.cpp @@ -1,46 +1,49 @@ #include "cru/win/graph/direct/text_layout.hpp" +#include "cru/platform/check.hpp" #include "cru/win/graph/direct/exception.hpp" +#include "cru/win/graph/direct/factory.hpp" +#include "cru/win/graph/direct/font.hpp" +#include "cru/win/string.hpp" #include <cassert> #include <utility> namespace cru::platform::graph::win::direct { -DWriteTextLayout::DWriteTextLayout(IDirectFactory* factory, - std::shared_ptr<Font> font, - std::wstring text) - : text_(std::move(text)) { - assert(factory); +DWriteTextLayout::DWriteTextLayout(DirectGraphFactory* factory, + std::shared_ptr<IFont> font, + std::string text) + : DirectGraphResource(factory), text_(std::move(text)) { assert(font); - assert(IsDirectResource(font.get())); - factory_ = factory; - font_ = std::static_pointer_cast<DWriteFont>(font); + font_ = CheckPlatform<DWriteFont>(font, GetPlatformId()); + + w_text_ = cru::platform::win::ToUtf16String(text_); ThrowIfFailed(factory->GetDWriteFactory()->CreateTextLayout( - text_.c_str(), static_cast<UINT32>(text_.size()), + w_text_.c_str(), static_cast<UINT32>(w_text_.size()), font_->GetComInterface(), max_width_, max_height_, &text_layout_)); } -std::wstring DWriteTextLayout::GetText() { return text_; } +DWriteTextLayout::~DWriteTextLayout() = default; + +std::string DWriteTextLayout::GetText() { return text_; } -void DWriteTextLayout::SetText(std::wstring new_text) { +void DWriteTextLayout::SetText(std::string new_text) { text_.swap(new_text); - ThrowIfFailed(factory_->GetDWriteFactory()->CreateTextLayout( - text_.c_str(), static_cast<UINT32>(text_.size()), + w_text_ = cru::platform::win::ToUtf16String(text_); + ThrowIfFailed(GetDirectFactory()->GetDWriteFactory()->CreateTextLayout( + w_text_.c_str(), static_cast<UINT32>(w_text_.size()), font_->GetComInterface(), max_width_, max_height_, &text_layout_)); } -std::shared_ptr<Font> DWriteTextLayout::GetFont() { - return std::static_pointer_cast<Font>(font_); +std::shared_ptr<IFont> DWriteTextLayout::GetFont() { + return std::dynamic_pointer_cast<IFont>(font_); } -void DWriteTextLayout::SetFont(std::shared_ptr<Font> font) { - assert(IsDirectResource(font.get())); - auto f = std::static_pointer_cast<DWriteFont>(font); - - f.swap(font_); - ThrowIfFailed(factory_->GetDWriteFactory()->CreateTextLayout( - text_.c_str(), static_cast<UINT32>(text_.size()), +void DWriteTextLayout::SetFont(std::shared_ptr<IFont> font) { + font_ = CheckPlatform<DWriteFont>(font, GetPlatformId()); + ThrowIfFailed(GetDirectFactory()->GetDWriteFactory()->CreateTextLayout( + w_text_.c_str(), static_cast<UINT32>(w_text_.size()), font_->GetComInterface(), max_width_, max_height_, &text_layout_)); } diff --git a/src/win/native/CMakeLists.txt b/src/win/native/CMakeLists.txt index 08acc739..0e7e5b4e 100644 --- a/src/win/native/CMakeLists.txt +++ b/src/win/native/CMakeLists.txt @@ -22,7 +22,6 @@ target_sources(cru_win_native PUBLIC ${CRU_WIN_NATIVE_INCLUDE_DIR}/exception.hpp ${CRU_WIN_NATIVE_INCLUDE_DIR}/god_window.hpp ${CRU_WIN_NATIVE_INCLUDE_DIR}/native_window.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/platform_id.hpp ${CRU_WIN_NATIVE_INCLUDE_DIR}/ui_application.hpp ${CRU_WIN_NATIVE_INCLUDE_DIR}/window_class.hpp ${CRU_WIN_NATIVE_INCLUDE_DIR}/window_native_message_event_args.hpp diff --git a/src/win/native/ui_application.cpp b/src/win/native/ui_application.cpp index c2d3ac2c..0bbe9c03 100644 --- a/src/win/native/ui_application.cpp +++ b/src/win/native/ui_application.cpp @@ -107,16 +107,16 @@ void WinUiApplication::CancelTimer(unsigned long id) { timer_manager_->KillTimer(static_cast<UINT_PTR>(id)); } -std::vector<NativeWindow*> WinUiApplication::GetAllWindow() { +std::vector<INativeWindow*> WinUiApplication::GetAllWindow() { const auto&& windows = window_manager_->GetAllWindows(); - std::vector<NativeWindow*> result; + std::vector<INativeWindow*> result; for (const auto w : windows) { - result.push_back(static_cast<NativeWindow*>(w)); + result.push_back(static_cast<INativeWindow*>(w)); } return result; } -NativeWindow* WinUiApplication::CreateWindow(NativeWindow* parent) { +INativeWindow* WinUiApplication::CreateWindow(INativeWindow* parent) { WinNativeWindow* p = nullptr; if (parent != nullptr) { p = dynamic_cast<WinNativeWindow*>(parent); diff --git a/src/win/string.cpp b/src/win/string.cpp new file mode 100644 index 00000000..84906f6b --- /dev/null +++ b/src/win/string.cpp @@ -0,0 +1,46 @@ +#include "cru/win/string.hpp" + +#include "cru/win/exception.hpp" + +namespace cru::platform::win { +std::string ToUtf8String(const std::wstring_view& string) { + if (string.empty()) return std::string{}; + + const auto length = + ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, string.data(), -1, + nullptr, 0, nullptr, nullptr); + if (length == 0) { + throw Win32Error(::GetLastError(), + "Failed to convert wide string to UTF-8."); + } + + std::string result; + result.resize(length); + if (::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, string.data(), -1, + result.data(), static_cast<int>(result.size()), + nullptr, nullptr) == 0) + throw Win32Error(::GetLastError(), + "Failed to convert wide string to UTF-8."); + return result; +} + +std::wstring ToUtf16String(const std::string_view& string) { + if (string.empty()) return std::wstring{}; + + const auto length = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, + string.data(), -1, nullptr, 0); + if (length == 0) { + throw Win32Error(::GetLastError(), + "Failed to convert wide string to UTF-16."); + } + + std::wstring result; + result.resize(length); + if (::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, string.data(), -1, + result.data(), + static_cast<int>(result.size())) == 0) + throw win::Win32Error(::GetLastError(), + "Failed to convert wide string to UTF-16."); + return result; +} +} // namespace cru::platform::win diff --git a/src/win/string_util.cpp b/src/win/string_util.cpp deleted file mode 100644 index dd513b12..00000000 --- a/src/win/string_util.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "cru/platform/string_util.hpp" - -#include "cru/win/exception.hpp" - -namespace cru::platform { -std::string ToUtf8String(const std::wstring_view& string) { - if (string.empty()) return std::string(); - - const auto length = ::WideCharToMultiByte(CP_UTF8, 0, string.data(), -1, - nullptr, 0, nullptr, nullptr); - std::string result; - result.resize(length); - if (::WideCharToMultiByte(CP_UTF8, 0, string.data(), -1, result.data(), - static_cast<int>(result.size()), nullptr, - nullptr) == 0) - throw win::Win32Error(::GetLastError(), - "Failed to convert wide string to UTF-8."); - return result; -} -} // namespace cru::platform |