diff options
Diffstat (limited to 'src/win/graph')
-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 |
8 files changed, 116 insertions, 138 deletions
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_)); } |