Made Renderer, RenderContext, TextureRenderContext to be interface
This commit is contained in:
parent
4633d7b6b9
commit
d302ec3a20
|
|
@ -62,6 +62,7 @@
|
|||
<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" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\Brush.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\Color.h" />
|
||||
|
|
@ -71,7 +72,10 @@
|
|||
<ClInclude Include="..\..\src\kiwano\render\DirectX\D3DDeviceResourcesBase.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\FontCollectionLoader.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\helper.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\RenderContextImpl.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\RendererImpl.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\TextRenderer.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\TextureRenderContextImpl.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\Font.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\Shape.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\ShapeSink.h" />
|
||||
|
|
@ -140,7 +144,10 @@
|
|||
<ClCompile Include="..\..\src\kiwano\render\DirectX\D3D10DeviceResources.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\DirectX\D3D11DeviceResources.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\DirectX\FontCollectionLoader.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\DirectX\RenderContextImpl.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\DirectX\RendererImpl.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\DirectX\TextRenderer.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\DirectX\TextureRenderContextImpl.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\Font.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\Shape.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\ShapeSink.cpp" />
|
||||
|
|
|
|||
|
|
@ -288,6 +288,18 @@
|
|||
<ClInclude Include="..\..\src\kiwano\render\TextureRenderContext.h">
|
||||
<Filter>render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\RenderContextImpl.h">
|
||||
<Filter>render\DirectX</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\TextureRenderContextImpl.h">
|
||||
<Filter>render\DirectX</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\RendererImpl.h">
|
||||
<Filter>render\DirectX</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\platform\win32\WindowImpl.h">
|
||||
<Filter>platform\win32</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp">
|
||||
|
|
@ -488,5 +500,14 @@
|
|||
<ClCompile Include="..\..\src\kiwano\render\TextureRenderContext.cpp">
|
||||
<Filter>render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\render\DirectX\RenderContextImpl.cpp">
|
||||
<Filter>render\DirectX</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\render\DirectX\TextureRenderContextImpl.cpp">
|
||||
<Filter>render\DirectX</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\render\DirectX\RendererImpl.cpp">
|
||||
<Filter>render\DirectX</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -58,7 +58,7 @@ void ImGuiModule::SetupComponent()
|
|||
io.KeyMap[ImGuiKey_Y] = (int)KeyCode::Y;
|
||||
io.KeyMap[ImGuiKey_Z] = (int)KeyCode::Z;
|
||||
|
||||
ImGui_Impl_Init(Renderer::GetInstance());
|
||||
ImGui_Impl_Init();
|
||||
}
|
||||
|
||||
void ImGuiModule::DestroyComponent()
|
||||
|
|
|
|||
|
|
@ -7,20 +7,25 @@
|
|||
#if !defined(KGE_USE_DIRECTX10)
|
||||
|
||||
#include <kiwano-imgui/imgui_impl_dx11.h>
|
||||
#include <kiwano/render/DirectX/RendererImpl.h>
|
||||
|
||||
inline bool ImGui_Impl_Init(::kiwano::Renderer& renderer)
|
||||
inline bool ImGui_Impl_Init()
|
||||
{
|
||||
::kiwano::RendererImpl& renderer = ::kiwano::RendererImpl::GetInstance();
|
||||
return ImGui_ImplDX11_Init(renderer.GetD3DDeviceResources()->GetDevice(),
|
||||
renderer.GetD3DDeviceResources()->GetDeviceContext());
|
||||
}
|
||||
|
||||
inline void ImGui_Impl_Shutdown()
|
||||
{
|
||||
ImGui_ImplDX11_Shutdown();
|
||||
}
|
||||
|
||||
inline void ImGui_Impl_NewFrame()
|
||||
{
|
||||
ImGui_ImplDX11_NewFrame();
|
||||
}
|
||||
|
||||
inline void ImGui_Impl_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
ImGui_ImplDX11_RenderDrawData(draw_data);
|
||||
|
|
@ -30,6 +35,7 @@ inline void ImGui_Impl_InvalidateDeviceObjects()
|
|||
{
|
||||
ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
}
|
||||
|
||||
inline bool ImGui_Impl_CreateDeviceObjects()
|
||||
{
|
||||
return ImGui_ImplDX11_CreateDeviceObjects();
|
||||
|
|
@ -39,18 +45,22 @@ inline bool ImGui_Impl_CreateDeviceObjects()
|
|||
|
||||
#include <kiwano-imgui/imgui_impl_dx10.h>
|
||||
|
||||
inline bool ImGui_Impl_Init(::kiwano::Renderer& renderer)
|
||||
inline bool ImGui_Impl_Init()
|
||||
{
|
||||
::kiwano::RendererImpl& renderer = ::kiwano::RendererImpl::GetInstance();
|
||||
return ImGui_ImplDX10_Init(renderer.GetD3DDeviceResources()->GetDevice());
|
||||
}
|
||||
|
||||
inline void ImGui_Impl_Shutdown()
|
||||
{
|
||||
ImGui_ImplDX10_Shutdown();
|
||||
}
|
||||
|
||||
inline void ImGui_Impl_NewFrame()
|
||||
{
|
||||
ImGui_ImplDX10_NewFrame();
|
||||
}
|
||||
|
||||
inline void ImGui_Impl_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
ImGui_ImplDX10_RenderDrawData(draw_data);
|
||||
|
|
@ -60,6 +70,7 @@ inline void ImGui_Impl_InvalidateDeviceObjects()
|
|||
{
|
||||
ImGui_ImplDX10_InvalidateDeviceObjects();
|
||||
}
|
||||
|
||||
inline bool ImGui_Impl_CreateDeviceObjects()
|
||||
{
|
||||
return ImGui_ImplDX10_CreateDeviceObjects();
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ CanvasPtr Canvas::Create(Size const& size)
|
|||
ptr->ctx_ = TextureRenderContext::Create();
|
||||
ptr->stroke_brush_ = Brush::Create(Color::White);
|
||||
ptr->fill_brush_ = Brush::Create(Color::White);
|
||||
|
||||
ptr->SetSize(ptr->ctx_->GetSize());
|
||||
}
|
||||
catch (std::exception)
|
||||
{
|
||||
|
|
@ -71,9 +73,7 @@ void Canvas::OnRender(RenderContext& ctx)
|
|||
if (texture_cached_ && texture_cached_->IsValid())
|
||||
{
|
||||
PrepareToRender(ctx);
|
||||
|
||||
Rect bitmap_rect(0.f, 0.f, texture_cached_->GetWidth(), texture_cached_->GetHeight());
|
||||
ctx.DrawTexture(*texture_cached_, bitmap_rect, bitmap_rect);
|
||||
ctx.DrawTexture(*texture_cached_, nullptr, &GetBounds());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano/platform/Window.h>
|
||||
#include <kiwano/platform/win32/WindowImpl.h>
|
||||
|
||||
#if defined(KGE_WIN32)
|
||||
|
||||
|
|
@ -38,8 +38,19 @@
|
|||
|
||||
namespace kiwano
|
||||
{
|
||||
namespace win32
|
||||
|
||||
|
||||
Window& Window::GetInstance()
|
||||
{
|
||||
return WindowImpl::GetInstance();
|
||||
}
|
||||
|
||||
WindowImpl& WindowImpl::GetInstance()
|
||||
{
|
||||
static WindowImpl instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
MONITORINFOEX GetMoniterInfoEx(HWND hwnd)
|
||||
|
|
@ -96,51 +107,6 @@ void RestoreResolution(WCHAR* device_name)
|
|||
}
|
||||
} // namespace
|
||||
|
||||
class KGE_API WindowImpl : public kiwano::Window
|
||||
{
|
||||
public:
|
||||
WindowImpl();
|
||||
|
||||
~WindowImpl();
|
||||
|
||||
void Create(String const& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable,
|
||||
bool fullscreen) override;
|
||||
|
||||
WindowHandle GetHandle() const override;
|
||||
|
||||
void SetTitle(String const& title) override;
|
||||
|
||||
void SetIcon(uint32_t icon_resource) override;
|
||||
|
||||
void Resize(uint32_t width, uint32_t height) override;
|
||||
|
||||
void SetFullscreen(bool fullscreen) override;
|
||||
|
||||
void SetCursor(CursorType cursor) override;
|
||||
|
||||
void Destroy() override;
|
||||
|
||||
private:
|
||||
void PumpEvents() override;
|
||||
|
||||
DWORD GetStyle() const;
|
||||
|
||||
void UpdateCursor();
|
||||
|
||||
void SetActive(bool actived);
|
||||
|
||||
static LRESULT CALLBACK WndProc(HWND, UINT32, WPARAM, LPARAM);
|
||||
|
||||
private:
|
||||
bool resizable_;
|
||||
bool is_fullscreen_;
|
||||
wchar_t* device_name_;
|
||||
WindowHandle handle_;
|
||||
CursorType mouse_cursor_;
|
||||
|
||||
std::array<KeyCode, 256> key_map_;
|
||||
};
|
||||
|
||||
WindowImpl::WindowImpl()
|
||||
: handle_(nullptr)
|
||||
, device_name_(nullptr)
|
||||
|
|
@ -678,18 +644,6 @@ LRESULT CALLBACK WindowImpl::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
|
|||
return ::DefWindowProcW(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
} // namespace win32
|
||||
} // namespace kiwano
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
Window& Window::GetInstance()
|
||||
{
|
||||
static win32::WindowImpl instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright (c) 2016-2020 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/platform/Window.h>
|
||||
#include <kiwano/core/Keys.h>
|
||||
|
||||
#if defined(KGE_WIN32)
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
class KGE_API WindowImpl : public Window
|
||||
{
|
||||
public:
|
||||
static WindowImpl& GetInstance();
|
||||
|
||||
void Create(String const& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable,
|
||||
bool fullscreen) override;
|
||||
|
||||
WindowHandle GetHandle() const override;
|
||||
|
||||
void SetTitle(String const& title) override;
|
||||
|
||||
void SetIcon(uint32_t icon_resource) override;
|
||||
|
||||
void Resize(uint32_t width, uint32_t height) override;
|
||||
|
||||
void SetFullscreen(bool fullscreen) override;
|
||||
|
||||
void SetCursor(CursorType cursor) override;
|
||||
|
||||
void Destroy() override;
|
||||
|
||||
private:
|
||||
WindowImpl();
|
||||
|
||||
~WindowImpl();
|
||||
|
||||
void PumpEvents() override;
|
||||
|
||||
DWORD GetStyle() const;
|
||||
|
||||
void UpdateCursor();
|
||||
|
||||
void SetActive(bool actived);
|
||||
|
||||
static LRESULT CALLBACK WndProc(HWND, UINT32, WPARAM, LPARAM);
|
||||
|
||||
private:
|
||||
bool resizable_;
|
||||
bool is_fullscreen_;
|
||||
wchar_t* device_name_;
|
||||
WindowHandle handle_;
|
||||
CursorType mouse_cursor_;
|
||||
|
||||
std::array<KeyCode, 256> key_map_;
|
||||
};
|
||||
|
||||
} // namespace kiwano
|
||||
|
||||
#endif
|
||||
|
|
@ -86,8 +86,7 @@ BrushPtr Brush::Create(RadialGradientStyle const& style)
|
|||
}
|
||||
|
||||
Brush::Brush()
|
||||
: opacity_(1.f)
|
||||
, type_(Type::Unknown)
|
||||
: type_(Type::Unknown)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -96,20 +95,6 @@ bool Brush::IsValid() const
|
|||
return raw_ != nullptr;
|
||||
}
|
||||
|
||||
float Brush::GetOpacity() const
|
||||
{
|
||||
return opacity_;
|
||||
}
|
||||
|
||||
void Brush::SetOpacity(float opacity)
|
||||
{
|
||||
opacity_ = opacity;
|
||||
if (raw_)
|
||||
{
|
||||
raw_->SetOpacity(opacity);
|
||||
}
|
||||
}
|
||||
|
||||
void Brush::SetColor(Color const& color)
|
||||
{
|
||||
Renderer::GetInstance().CreateBrush(*this, color);
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@
|
|||
|
||||
namespace kiwano
|
||||
{
|
||||
class RenderContext;
|
||||
class Renderer;
|
||||
|
||||
KGE_DECLARE_SMART_PTR(Brush);
|
||||
|
||||
|
|
@ -89,9 +87,6 @@ struct RadialGradientStyle
|
|||
*/
|
||||
class KGE_API Brush : public virtual ObjectBase
|
||||
{
|
||||
friend class RenderContext;
|
||||
friend class Renderer;
|
||||
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief ´´½¨´¿É«»Ë¢
|
||||
|
|
@ -141,24 +136,16 @@ public:
|
|||
/// @brief »ñÈ¡»Ë¢ÀàÐÍ
|
||||
Type GetType() const;
|
||||
|
||||
private:
|
||||
/// \~chinese
|
||||
/// @brief »ñȡ͸Ã÷¶È
|
||||
float GetOpacity() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief ÉèÖÃ͸Ã÷¶È
|
||||
void SetOpacity(float opacity);
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
float opacity_;
|
||||
|
||||
#if defined(KGE_WIN32)
|
||||
public:
|
||||
void SetBrush(ComPtr<ID2D1Brush> brush, Type type);
|
||||
|
||||
ComPtr<ID2D1Brush> GetBrush() const;
|
||||
|
||||
private:
|
||||
ComPtr<ID2D1Brush> raw_;
|
||||
#endif
|
||||
};
|
||||
|
|
@ -175,10 +162,6 @@ inline void Brush::SetBrush(ComPtr<ID2D1Brush> brush, Type type)
|
|||
{
|
||||
type_ = type;
|
||||
raw_ = brush;
|
||||
if (raw_)
|
||||
{
|
||||
raw_->SetOpacity(opacity_);
|
||||
}
|
||||
}
|
||||
|
||||
inline ComPtr<ID2D1Brush> Brush::GetBrush() const
|
||||
|
|
|
|||
|
|
@ -0,0 +1,489 @@
|
|||
// Copyright (c) 2016-2019 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/Logger.h>
|
||||
#include <kiwano/render/DirectX/RenderContextImpl.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
RenderContextImpl::RenderContextImpl()
|
||||
{}
|
||||
|
||||
RenderContextImpl::~RenderContextImpl()
|
||||
{
|
||||
DiscardDeviceResources();
|
||||
}
|
||||
|
||||
HRESULT RenderContextImpl::CreateDeviceResources(ComPtr<ID2D1Factory> factory, ComPtr<ID2D1RenderTarget> ctx)
|
||||
{
|
||||
if (!factory || !ctx)
|
||||
return E_INVALIDARG;
|
||||
|
||||
render_target_ = ctx;
|
||||
text_renderer_.reset();
|
||||
current_brush_.reset();
|
||||
|
||||
HRESULT hr = ITextRenderer::Create(&text_renderer_, render_target_.get());
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
SetAntialiasMode(antialias_);
|
||||
SetTextAntialiasMode(text_antialias_);
|
||||
|
||||
Resize(reinterpret_cast<const Size&>(ctx->GetSize()));
|
||||
}
|
||||
|
||||
// DrawingStateBlock
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = factory->CreateDrawingStateBlock(&drawing_state_);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
void RenderContextImpl::DiscardDeviceResources()
|
||||
{
|
||||
text_renderer_.reset();
|
||||
render_target_.reset();
|
||||
current_brush_.reset();
|
||||
}
|
||||
|
||||
bool RenderContextImpl::IsValid() const
|
||||
{
|
||||
return render_target_ != nullptr;
|
||||
}
|
||||
|
||||
void RenderContextImpl::BeginDraw()
|
||||
{
|
||||
SaveDrawingState();
|
||||
|
||||
RenderContext::BeginDraw();
|
||||
|
||||
if (render_target_)
|
||||
{
|
||||
render_target_->BeginDraw();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContextImpl::EndDraw()
|
||||
{
|
||||
win32::ThrowIfFailed(render_target_->EndDraw());
|
||||
|
||||
RenderContext::EndDraw();
|
||||
|
||||
RestoreDrawingState();
|
||||
}
|
||||
|
||||
void RenderContextImpl::DrawTexture(Texture const& texture, const Rect* src_rect, const Rect* dest_rect)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
|
||||
if (texture.IsValid())
|
||||
{
|
||||
auto mode = (texture.GetBitmapInterpolationMode() == InterpolationMode::Linear)
|
||||
? D2D1_BITMAP_INTERPOLATION_MODE_LINEAR
|
||||
: D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR;
|
||||
|
||||
render_target_->DrawBitmap(texture.GetBitmap().get(), dest_rect ? &DX::ConvertToRectF(*dest_rect) : nullptr,
|
||||
brush_opacity_, mode, src_rect ? &DX::ConvertToRectF(*src_rect) : nullptr);
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContextImpl::DrawTextLayout(TextLayout const& layout, Point const& offset)
|
||||
{
|
||||
KGE_ASSERT(text_renderer_ && "Text renderer has not been initialized!");
|
||||
|
||||
if (layout.IsValid())
|
||||
{
|
||||
ComPtr<ID2D1Brush> fill_brush;
|
||||
ComPtr<ID2D1Brush> outline_brush;
|
||||
const TextStyle& style = layout.GetStyle();
|
||||
|
||||
if (style.fill_brush)
|
||||
{
|
||||
fill_brush = style.fill_brush->GetBrush();
|
||||
fill_brush->SetOpacity(brush_opacity_);
|
||||
}
|
||||
|
||||
if (style.outline_brush)
|
||||
{
|
||||
outline_brush = style.outline_brush->GetBrush();
|
||||
outline_brush->SetOpacity(brush_opacity_);
|
||||
}
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (style.outline_stroke)
|
||||
{
|
||||
hr = text_renderer_->DrawTextLayout(layout.GetTextLayout().get(), offset.x, offset.y, fill_brush.get(),
|
||||
outline_brush.get(), style.outline_width,
|
||||
style.outline_stroke->GetStrokeStyle().get());
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = text_renderer_->DrawTextLayout(layout.GetTextLayout().get(), offset.x, offset.y, fill_brush.get(),
|
||||
outline_brush.get(), style.outline_width, nullptr);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IncreasePrimitivesCount(text_renderer_->GetLastPrimitivesCount());
|
||||
}
|
||||
else
|
||||
{
|
||||
KGE_ERROR(L"Failed to draw text layout with HRESULT of %08X", hr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContextImpl::DrawShape(Shape const& shape, StrokeStylePtr stroke, float stroke_width)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
if (shape.IsValid())
|
||||
{
|
||||
if (stroke)
|
||||
{
|
||||
render_target_->DrawGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get(), stroke_width,
|
||||
stroke->GetStrokeStyle().get());
|
||||
}
|
||||
else
|
||||
{
|
||||
render_target_->DrawGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get(), stroke_width,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContextImpl::DrawLine(Point const& point1, Point const& point2, StrokeStylePtr stroke, float stroke_width)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
if (stroke)
|
||||
{
|
||||
render_target_->DrawLine(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2),
|
||||
current_brush_->GetBrush().get(), stroke_width, stroke->GetStrokeStyle().get());
|
||||
}
|
||||
else
|
||||
{
|
||||
render_target_->DrawLine(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2),
|
||||
current_brush_->GetBrush().get(), stroke_width, nullptr);
|
||||
}
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContextImpl::DrawRectangle(Rect const& rect, StrokeStylePtr stroke, float stroke_width)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
if (stroke)
|
||||
{
|
||||
render_target_->DrawRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get(), stroke_width,
|
||||
stroke->GetStrokeStyle().get());
|
||||
}
|
||||
else
|
||||
{
|
||||
render_target_->DrawRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get(), stroke_width,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContextImpl::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, StrokeStylePtr stroke,
|
||||
float stroke_width)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
if (stroke)
|
||||
{
|
||||
render_target_->DrawRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y),
|
||||
current_brush_->GetBrush().get(), stroke_width,
|
||||
stroke->GetStrokeStyle().get());
|
||||
}
|
||||
else
|
||||
{
|
||||
render_target_->DrawRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y),
|
||||
current_brush_->GetBrush().get(), stroke_width, nullptr);
|
||||
}
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContextImpl::DrawEllipse(Point const& center, Vec2 const& radius, StrokeStylePtr stroke, float stroke_width)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
if (stroke)
|
||||
{
|
||||
render_target_->DrawEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y),
|
||||
current_brush_->GetBrush().get(), stroke_width, stroke->GetStrokeStyle().get());
|
||||
}
|
||||
else
|
||||
{
|
||||
render_target_->DrawEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y),
|
||||
current_brush_->GetBrush().get(), stroke_width, nullptr);
|
||||
}
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContextImpl::FillShape(Shape const& shape)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
if (shape.IsValid())
|
||||
{
|
||||
render_target_->FillGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContextImpl::FillRectangle(Rect const& rect)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
render_target_->FillRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContextImpl::FillRoundedRectangle(Rect const& rect, Vec2 const& radius)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
render_target_->FillRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y),
|
||||
current_brush_->GetBrush().get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContextImpl::FillEllipse(Point const& center, Vec2 const& radius)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
render_target_->FillEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y),
|
||||
current_brush_->GetBrush().get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContextImpl::CreateTexture(Texture& texture, math::Vec2T<uint32_t> size)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
|
||||
ComPtr<ID2D1Bitmap> saved_bitmap;
|
||||
|
||||
HRESULT hr = render_target_->CreateBitmap(D2D1::SizeU(size.x, size.y), D2D1::BitmapProperties(), &saved_bitmap);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
texture.SetBitmap(saved_bitmap);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RenderContextImpl::PushClipRect(Rect const& clip_rect)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
render_target_->PushAxisAlignedClip(DX::ConvertToRectF(clip_rect),
|
||||
antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED);
|
||||
}
|
||||
|
||||
void RenderContextImpl::PopClipRect()
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
render_target_->PopAxisAlignedClip();
|
||||
}
|
||||
|
||||
void RenderContextImpl::PushLayer(LayerArea& layer)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
if (!layer.IsValid())
|
||||
{
|
||||
ComPtr<ID2D1Layer> output;
|
||||
HRESULT hr = render_target_->CreateLayer(&output);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
layer.SetLayer(output);
|
||||
}
|
||||
else
|
||||
{
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
}
|
||||
|
||||
if (layer.IsValid())
|
||||
{
|
||||
ComPtr<ID2D1Geometry> mask;
|
||||
if (layer.GetMaskShape())
|
||||
mask = layer.GetMaskShape()->GetGeometry();
|
||||
|
||||
render_target_->PushLayer(
|
||||
D2D1::LayerParameters(DX::ConvertToRectF(layer.GetAreaRect()), mask.get(),
|
||||
antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED,
|
||||
DX::ConvertToMatrix3x2F(layer.GetMaskTransform()), layer.GetOpacity(), nullptr,
|
||||
D2D1_LAYER_OPTIONS_NONE),
|
||||
layer.GetLayer().get());
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContextImpl::PopLayer()
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
render_target_->PopLayer();
|
||||
}
|
||||
|
||||
void RenderContextImpl::Clear()
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
render_target_->Clear();
|
||||
}
|
||||
|
||||
void RenderContextImpl::Clear(Color const& clear_color)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
render_target_->Clear(DX::ConvertToColorF(clear_color));
|
||||
}
|
||||
|
||||
Size RenderContextImpl::GetSize() const
|
||||
{
|
||||
if (render_target_)
|
||||
{
|
||||
return reinterpret_cast<const Size&>(render_target_->GetSize());
|
||||
}
|
||||
return Size();
|
||||
}
|
||||
|
||||
void RenderContextImpl::SetCurrentBrush(BrushPtr brush)
|
||||
{
|
||||
RenderContext::SetCurrentBrush(brush);
|
||||
|
||||
if (current_brush_ && current_brush_->IsValid())
|
||||
{
|
||||
current_brush_->GetBrush()->SetOpacity(brush_opacity_);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContextImpl::SetTransform(const Matrix3x2& matrix)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
|
||||
if (fast_global_transform_)
|
||||
{
|
||||
render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix));
|
||||
}
|
||||
else
|
||||
{
|
||||
Matrix3x2 result = matrix * global_transform_;
|
||||
render_target_->SetTransform(DX::ConvertToMatrix3x2F(&result));
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContextImpl::SetAntialiasMode(bool enabled)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
|
||||
render_target_->SetAntialiasMode(enabled ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED);
|
||||
antialias_ = enabled;
|
||||
}
|
||||
|
||||
void RenderContextImpl::SetTextAntialiasMode(TextAntialiasMode mode)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
|
||||
D2D1_TEXT_ANTIALIAS_MODE antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
||||
switch (mode)
|
||||
{
|
||||
case TextAntialiasMode::Default:
|
||||
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
|
||||
break;
|
||||
case TextAntialiasMode::ClearType:
|
||||
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
||||
break;
|
||||
case TextAntialiasMode::GrayScale:
|
||||
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
||||
break;
|
||||
case TextAntialiasMode::None:
|
||||
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
text_antialias_ = mode;
|
||||
render_target_->SetTextAntialiasMode(antialias_mode);
|
||||
}
|
||||
|
||||
bool RenderContextImpl::CheckVisibility(Rect const& bounds, Matrix3x2 const& transform)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
|
||||
if (fast_global_transform_)
|
||||
{
|
||||
return visible_size_.Intersects(transform.Transform(bounds));
|
||||
}
|
||||
return visible_size_.Intersects(Matrix3x2(transform * global_transform_).Transform(bounds));
|
||||
}
|
||||
|
||||
void RenderContextImpl::Resize(Size const& size)
|
||||
{
|
||||
visible_size_ = Rect(Point(), size);
|
||||
}
|
||||
|
||||
void RenderContextImpl::SaveDrawingState()
|
||||
{
|
||||
KGE_ASSERT(IsValid());
|
||||
|
||||
if (drawing_state_)
|
||||
{
|
||||
render_target_->SaveDrawingState(drawing_state_.get());
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContextImpl::RestoreDrawingState()
|
||||
{
|
||||
KGE_ASSERT(IsValid());
|
||||
|
||||
if (drawing_state_)
|
||||
{
|
||||
render_target_->RestoreDrawingState(drawing_state_.get());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
// Copyright (c) 2016-2019 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/render/RenderContext.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
class RendererImpl;
|
||||
|
||||
KGE_DECLARE_SMART_PTR(RenderContextImpl);
|
||||
|
||||
class KGE_API RenderContextImpl : public virtual RenderContext
|
||||
{
|
||||
friend class RendererImpl;
|
||||
|
||||
public:
|
||||
bool IsValid() const override;
|
||||
|
||||
void BeginDraw() override;
|
||||
|
||||
void EndDraw() override;
|
||||
|
||||
void DrawTexture(Texture const& texture, const Rect* src_rect = nullptr, const Rect* dest_rect = nullptr) override;
|
||||
|
||||
void DrawTextLayout(TextLayout const& layout, Point const& offset = Point()) override;
|
||||
|
||||
void DrawShape(Shape const& shape, StrokeStylePtr stroke = nullptr, float stroke_width = 1.0f) override;
|
||||
|
||||
void DrawLine(Point const& point1, Point const& point2, StrokeStylePtr stroke = nullptr,
|
||||
float stroke_width = 1.0f) override;
|
||||
|
||||
void DrawRectangle(Rect const& rect, StrokeStylePtr stroke = nullptr, float stroke_width = 1.0f) override;
|
||||
|
||||
void DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, StrokeStylePtr stroke = nullptr,
|
||||
float stroke_width = 1.0f) override;
|
||||
|
||||
void DrawEllipse(Point const& center, Vec2 const& radius, StrokeStylePtr stroke = nullptr,
|
||||
float stroke_width = 1.0f) override;
|
||||
|
||||
void FillShape(Shape const& shape) override;
|
||||
|
||||
void FillRectangle(Rect const& rect) override;
|
||||
|
||||
void FillRoundedRectangle(Rect const& rect, Vec2 const& radius) override;
|
||||
|
||||
void FillEllipse(Point const& center, Vec2 const& radius) override;
|
||||
|
||||
void CreateTexture(Texture& texture, math::Vec2T<uint32_t> size) override;
|
||||
|
||||
void PushClipRect(Rect const& clip_rect) override;
|
||||
|
||||
void PopClipRect() override;
|
||||
|
||||
void PushLayer(LayerArea& layer) override;
|
||||
|
||||
void PopLayer() override;
|
||||
|
||||
void Clear() override;
|
||||
|
||||
void Clear(Color const& clear_color) override;
|
||||
|
||||
Size GetSize() const override;
|
||||
|
||||
void SetCurrentBrush(BrushPtr brush) override;
|
||||
|
||||
void SetTransform(const Matrix3x2& matrix) override;
|
||||
|
||||
void SetAntialiasMode(bool enabled) override;
|
||||
|
||||
void SetTextAntialiasMode(TextAntialiasMode mode) override;
|
||||
|
||||
bool CheckVisibility(Rect const& bounds, Matrix3x2 const& transform) override;
|
||||
|
||||
void Resize(Size const& size) override;
|
||||
|
||||
protected:
|
||||
RenderContextImpl();
|
||||
|
||||
virtual ~RenderContextImpl();
|
||||
|
||||
HRESULT CreateDeviceResources(ComPtr<ID2D1Factory> factory, ComPtr<ID2D1RenderTarget> ctx);
|
||||
|
||||
void DiscardDeviceResources();
|
||||
|
||||
void SaveDrawingState();
|
||||
|
||||
void RestoreDrawingState();
|
||||
|
||||
protected:
|
||||
ComPtr<ITextRenderer> text_renderer_;
|
||||
ComPtr<ID2D1RenderTarget> render_target_;
|
||||
ComPtr<ID2D1DrawingStateBlock> drawing_state_;
|
||||
};
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
@ -0,0 +1,954 @@
|
|||
// 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/Logger.h>
|
||||
#include <kiwano/core/event/WindowEvent.h>
|
||||
#include <kiwano/platform/FileSystem.h>
|
||||
#include <kiwano/render/ShapeSink.h>
|
||||
#include <kiwano/render/DirectX/TextureRenderContextImpl.h>
|
||||
#include <kiwano/render/DirectX/RendererImpl.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
Renderer& Renderer::GetInstance()
|
||||
{
|
||||
return RendererImpl::GetInstance();
|
||||
}
|
||||
|
||||
RendererImpl& RendererImpl::GetInstance()
|
||||
{
|
||||
static RendererImpl instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
RendererImpl::RendererImpl()
|
||||
{
|
||||
render_ctx_ = new RenderContextImpl;
|
||||
}
|
||||
|
||||
void RendererImpl::SetupComponent()
|
||||
{
|
||||
KGE_SYS_LOG(L"Creating device resources");
|
||||
|
||||
win32::ThrowIfFailed(::CoInitialize(nullptr));
|
||||
|
||||
target_window_ = Window::GetInstance().GetHandle();
|
||||
output_size_ = Window::GetInstance().GetSize();
|
||||
|
||||
d2d_res_ = nullptr;
|
||||
d3d_res_ = nullptr;
|
||||
|
||||
HRESULT hr = target_window_ ? S_OK : E_FAIL;
|
||||
|
||||
// Direct3D device resources
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = ID3DDeviceResources::Create(&d3d_res_, target_window_);
|
||||
|
||||
// Direct2D device resources
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = ID2DDeviceResources::Create(&d2d_res_, d3d_res_->GetDXGIDevice(), d3d_res_->GetDXGISwapChain());
|
||||
|
||||
// Other device resources
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = render_ctx_->CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext());
|
||||
}
|
||||
|
||||
// FontFileLoader and FontCollectionLoader
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IFontCollectionLoader::Create(&font_collection_loader_);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(font_collection_loader_.get());
|
||||
}
|
||||
}
|
||||
|
||||
// ResourceFontFileLoader and ResourceFontCollectionLoader
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IResourceFontFileLoader::Create(&res_font_file_loader_);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetDWriteFactory()->RegisterFontFileLoader(res_font_file_loader_.get());
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IResourceFontCollectionLoader::Create(&res_font_collection_loader_,
|
||||
res_font_file_loader_.get());
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(
|
||||
res_font_collection_loader_.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RendererImpl::DestroyComponent()
|
||||
{
|
||||
KGE_SYS_LOG(L"Destroying device resources");
|
||||
|
||||
d2d_res_->GetDWriteFactory()->UnregisterFontFileLoader(res_font_file_loader_.get());
|
||||
res_font_file_loader_.reset();
|
||||
|
||||
d2d_res_->GetDWriteFactory()->UnregisterFontCollectionLoader(res_font_collection_loader_.get());
|
||||
res_font_collection_loader_.reset();
|
||||
|
||||
render_ctx_.reset();
|
||||
d2d_res_.reset();
|
||||
d3d_res_.reset();
|
||||
|
||||
::CoUninitialize();
|
||||
}
|
||||
|
||||
void RendererImpl::BeginDraw()
|
||||
{
|
||||
KGE_ASSERT(render_ctx_);
|
||||
|
||||
render_ctx_->BeginDraw();
|
||||
}
|
||||
|
||||
void RendererImpl::EndDraw()
|
||||
{
|
||||
KGE_ASSERT(render_ctx_);
|
||||
|
||||
render_ctx_->EndDraw();
|
||||
}
|
||||
|
||||
void RendererImpl::Clear()
|
||||
{
|
||||
KGE_ASSERT(d3d_res_);
|
||||
|
||||
HRESULT hr = d3d_res_->ClearRenderTarget(clear_color_);
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RendererImpl::Present()
|
||||
{
|
||||
KGE_ASSERT(d3d_res_);
|
||||
|
||||
HRESULT hr = d3d_res_->Present(vsync_);
|
||||
|
||||
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
|
||||
{
|
||||
// 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
|
||||
hr = HandleDeviceLost();
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RendererImpl::HandleEvent(Event* evt)
|
||||
{
|
||||
if (evt->IsType<WindowResizedEvent>())
|
||||
{
|
||||
auto window_evt = dynamic_cast<WindowResizedEvent*>(evt);
|
||||
Resize(window_evt->width, window_evt->height);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT RendererImpl::HandleDeviceLost()
|
||||
{
|
||||
KGE_ASSERT(d3d_res_ && d2d_res_ && render_ctx_);
|
||||
|
||||
HRESULT hr = d3d_res_->HandleDeviceLost();
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->HandleDeviceLost(d3d_res_->GetDXGIDevice(), d3d_res_->GetDXGISwapChain());
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = render_ctx_->CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext());
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
void RendererImpl::CreateTexture(Texture& texture, String const& file_path)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!FileSystem::GetInstance().IsFileExists(file_path))
|
||||
{
|
||||
KGE_WARN(L"Texture file '%s' not found!", file_path.c_str());
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
String full_path = FileSystem::GetInstance().GetFullPathForFile(file_path);
|
||||
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, full_path);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICBitmapFrameDecode> source;
|
||||
hr = decoder->GetFrame(0, &source);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICFormatConverter> converter;
|
||||
hr = d2d_res_->CreateBitmapConverter(converter, source, GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone, nullptr, 0.f,
|
||||
WICBitmapPaletteTypeMedianCut);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1Bitmap> bitmap;
|
||||
hr = d2d_res_->CreateBitmapFromConverter(bitmap, nullptr, converter);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
texture.SetBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARN(L"Load texture failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
void RendererImpl::CreateTexture(Texture& texture, Resource const& resource)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = d2d_res_->CreateBitmapDecoderFromResource(decoder, resource);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICBitmapFrameDecode> source;
|
||||
hr = decoder->GetFrame(0, &source);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICFormatConverter> converter;
|
||||
hr = d2d_res_->CreateBitmapConverter(converter, source, GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone, nullptr, 0.f,
|
||||
WICBitmapPaletteTypeMedianCut);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1Bitmap> bitmap;
|
||||
hr = d2d_res_->CreateBitmapFromConverter(bitmap, nullptr, converter);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
texture.SetBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARN(L"Load texture failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
void RendererImpl::CreateGifImage(GifImage& gif, String const& file_path)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!FileSystem::GetInstance().IsFileExists(file_path))
|
||||
{
|
||||
KGE_WARN(L"Gif texture file '%s' not found!", file_path.c_str());
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
String full_path = FileSystem::GetInstance().GetFullPathForFile(file_path);
|
||||
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, full_path);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
gif.SetDecoder(decoder);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARN(L"Load GIF texture failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
void RendererImpl::CreateGifImage(GifImage& gif, Resource const& resource)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = d2d_res_->CreateBitmapDecoderFromResource(decoder, resource);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
gif.SetDecoder(decoder);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARN(L"Load GIF texture failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
void RendererImpl::CreateGifImageFrame(GifImage::Frame& frame, GifImage const& gif, size_t frame_index)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (gif.GetDecoder() == nullptr)
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICBitmapFrameDecode> wic_frame;
|
||||
|
||||
HRESULT hr = gif.GetDecoder()->GetFrame(UINT(frame_index), &wic_frame);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICFormatConverter> converter;
|
||||
d2d_res_->CreateBitmapConverter(converter, wic_frame, GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone, nullptr, 0.f, WICBitmapPaletteTypeCustom);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1Bitmap> raw_bitmap;
|
||||
hr = d2d_res_->CreateBitmapFromConverter(raw_bitmap, nullptr, converter);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.texture = new Texture;
|
||||
frame.texture->SetBitmap(raw_bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
PROPVARIANT prop_val;
|
||||
PropVariantInit(&prop_val);
|
||||
|
||||
// Get Metadata Query Reader from the frame
|
||||
ComPtr<IWICMetadataQueryReader> metadata_reader;
|
||||
hr = wic_frame->GetMetadataQueryReader(&metadata_reader);
|
||||
|
||||
// Get the Metadata for the current frame
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = metadata_reader->GetMetadataByName(L"/imgdesc/Left", &prop_val);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.rect.left_top.x = static_cast<float>(prop_val.uiVal);
|
||||
}
|
||||
PropVariantClear(&prop_val);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = metadata_reader->GetMetadataByName(L"/imgdesc/Top", &prop_val);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.rect.left_top.y = static_cast<float>(prop_val.uiVal);
|
||||
}
|
||||
PropVariantClear(&prop_val);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = metadata_reader->GetMetadataByName(L"/imgdesc/Width", &prop_val);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.rect.right_bottom.x = frame.rect.left_top.x + static_cast<float>(prop_val.uiVal);
|
||||
}
|
||||
PropVariantClear(&prop_val);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = metadata_reader->GetMetadataByName(L"/imgdesc/Height", &prop_val);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.rect.right_bottom.y = frame.rect.left_top.y + static_cast<float>(prop_val.uiVal);
|
||||
}
|
||||
PropVariantClear(&prop_val);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = metadata_reader->GetMetadataByName(L"/grctlext/Delay", &prop_val);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
uint32_t udelay = 0;
|
||||
|
||||
hr = UIntMult(prop_val.uiVal, 10, &udelay);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.delay.SetMilliseconds(static_cast<long>(udelay));
|
||||
}
|
||||
}
|
||||
PropVariantClear(&prop_val);
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.delay = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = metadata_reader->GetMetadataByName(L"/grctlext/Disposal", &prop_val);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = (prop_val.vt == VT_UI1) ? S_OK : E_FAIL;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.disposal_type = GifImage::DisposalType(prop_val.bVal);
|
||||
}
|
||||
::PropVariantClear(&prop_val);
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.disposal_type = GifImage::DisposalType::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
::PropVariantClear(&prop_val);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARN(L"Load GIF frame failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
void RendererImpl::CreateFontCollection(Font& font, String const& file_path)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (!FileSystem::GetInstance().IsFileExists(file_path))
|
||||
{
|
||||
KGE_WARN(L"Font file '%s' not found!", file_path.c_str());
|
||||
hr = E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
LPVOID key = nullptr;
|
||||
uint32_t key_size = 0;
|
||||
String full_path = FileSystem::GetInstance().GetFullPathForFile(file_path);
|
||||
|
||||
hr = font_collection_loader_->AddFilePaths({ full_path }, &key, &key_size);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IDWriteFontCollection> font_collection;
|
||||
hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection(font_collection_loader_.get(), key, key_size,
|
||||
&font_collection);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
font.SetCollection(font_collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RendererImpl::CreateFontCollection(Font& font, Resource const& res)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
LPVOID key = nullptr;
|
||||
uint32_t key_size = 0;
|
||||
|
||||
hr = res_font_collection_loader_->AddResources(Vector<Resource>{ res }, &key, &key_size);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IDWriteFontCollection> font_collection;
|
||||
hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection(res_font_collection_loader_.get(), key,
|
||||
key_size, &font_collection);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
font.SetCollection(font_collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RendererImpl::CreateTextFormat(TextLayout& layout)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ComPtr<IDWriteTextFormat> output;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
const TextStyle& style = layout.GetStyle();
|
||||
|
||||
hr = d2d_res_->CreateTextFormat(output, style.font_family, style.font ? style.font->GetCollection() : nullptr,
|
||||
DWRITE_FONT_WEIGHT(style.font_weight),
|
||||
style.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL,
|
||||
DWRITE_FONT_STRETCH_NORMAL, style.font_size);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
layout.SetTextFormat(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RendererImpl::CreateTextLayout(TextLayout& layout)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ComPtr<IDWriteTextLayout> output;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->CreateTextLayout(output, layout.GetText(), layout.GetTextFormat());
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
layout.SetTextLayout(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RendererImpl::CreateLineShape(Shape& shape, Point const& begin_pos, Point const& end_pos)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ComPtr<ID2D1PathGeometry> path_geo;
|
||||
ComPtr<ID2D1GeometrySink> path_sink;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetFactory()->CreatePathGeometry(&path_geo);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = path_geo->Open(&path_sink);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
path_sink->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
|
||||
path_sink->AddLine(DX::ConvertToPoint2F(end_pos));
|
||||
path_sink->EndFigure(D2D1_FIGURE_END_OPEN);
|
||||
hr = path_sink->Close();
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
shape.SetGeometry(path_geo);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RendererImpl::CreateRectShape(Shape& shape, Rect const& rect)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ComPtr<ID2D1RectangleGeometry> output;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetFactory()->CreateRectangleGeometry(DX::ConvertToRectF(rect), &output);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
shape.SetGeometry(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RendererImpl::CreateRoundedRectShape(Shape& shape, Rect const& rect, Vec2 const& radius)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ComPtr<ID2D1RoundedRectangleGeometry> output;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetFactory()->CreateRoundedRectangleGeometry(
|
||||
D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y), &output);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
shape.SetGeometry(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RendererImpl::CreateEllipseShape(Shape& shape, Point const& center, Vec2 const& radius)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ComPtr<ID2D1EllipseGeometry> output;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetFactory()->CreateEllipseGeometry(
|
||||
D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y), &output);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
shape.SetGeometry(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RendererImpl::CreateShapeSink(ShapeSink& sink)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ComPtr<ID2D1PathGeometry> output;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetFactory()->CreatePathGeometry(&output);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
sink.SetPathGeometry(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
TextureRenderContextPtr RendererImpl::CreateTextureRenderContext(const Size* desired_size)
|
||||
{
|
||||
TextureRenderContextImplPtr ptr = new TextureRenderContextImpl;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1BitmapRenderTarget> bitmap_rt;
|
||||
|
||||
if (desired_size)
|
||||
{
|
||||
hr = d2d_res_->GetDeviceContext()->CreateCompatibleRenderTarget(DX::ConvertToSizeF(*desired_size),
|
||||
&bitmap_rt);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = d2d_res_->GetDeviceContext()->CreateCompatibleRenderTarget(&bitmap_rt);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = ptr->CreateDeviceResources(d2d_res_->GetFactory(), bitmap_rt);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ptr->bitmap_rt_ = bitmap_rt;
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
return ptr;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RendererImpl::CreateBrush(Brush& brush, Color const& color)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1SolidColorBrush> solid_brush;
|
||||
|
||||
if (brush.GetType() == Brush::Type::SolidColor && brush.GetBrush())
|
||||
{
|
||||
hr = brush.GetBrush()->QueryInterface(&solid_brush);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
solid_brush->SetColor(DX::ConvertToColorF(color));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = d2d_res_->GetDeviceContext()->CreateSolidColorBrush(DX::ConvertToColorF(color), &solid_brush);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
brush.SetBrush(solid_brush, Brush::Type::SolidColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RendererImpl::CreateBrush(Brush& brush, LinearGradientStyle const& style)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1GradientStopCollection> collection;
|
||||
hr = d2d_res_->GetDeviceContext()->CreateGradientStopCollection(
|
||||
reinterpret_cast<const D2D1_GRADIENT_STOP*>(&style.stops[0]), UINT32(style.stops.size()), D2D1_GAMMA_2_2,
|
||||
D2D1_EXTEND_MODE(style.extend_mode), &collection);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1LinearGradientBrush> output;
|
||||
hr = d2d_res_->GetDeviceContext()->CreateLinearGradientBrush(
|
||||
D2D1::LinearGradientBrushProperties(DX::ConvertToPoint2F(style.begin), DX::ConvertToPoint2F(style.end)),
|
||||
collection.get(), &output);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
brush.SetBrush(output, Brush::Type::LinearGradient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RendererImpl::CreateBrush(Brush& brush, RadialGradientStyle const& style)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1GradientStopCollection> collection;
|
||||
hr = d2d_res_->GetDeviceContext()->CreateGradientStopCollection(
|
||||
reinterpret_cast<const D2D1_GRADIENT_STOP*>(&style.stops[0]), UINT32(style.stops.size()), D2D1_GAMMA_2_2,
|
||||
D2D1_EXTEND_MODE(style.extend_mode), &collection);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1RadialGradientBrush> output;
|
||||
hr = d2d_res_->GetDeviceContext()->CreateRadialGradientBrush(
|
||||
D2D1::RadialGradientBrushProperties(DX::ConvertToPoint2F(style.center),
|
||||
DX::ConvertToPoint2F(style.offset), style.radius.x, style.radius.y),
|
||||
collection.get(), &output);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
brush.SetBrush(output, Brush::Type::RadialGradient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RendererImpl::CreateStrokeStyle(StrokeStyle& stroke_style, CapStyle cap, LineJoinStyle line_join,
|
||||
const float* dash_array, size_t dash_size, float dash_offset)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
D2D1_STROKE_STYLE_PROPERTIES style =
|
||||
D2D1::StrokeStyleProperties(D2D1_CAP_STYLE(cap), D2D1_CAP_STYLE(cap), D2D1_CAP_STYLE(cap),
|
||||
D2D1_LINE_JOIN(line_join), 10.0f, D2D1_DASH_STYLE_CUSTOM, dash_offset);
|
||||
|
||||
ComPtr<ID2D1StrokeStyle> output;
|
||||
hr = d2d_res_->GetFactory()->CreateStrokeStyle(style, dash_array, dash_size, &output);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
stroke_style.SetStrokeStyle(output);
|
||||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RendererImpl::Resize(uint32_t width, uint32_t height)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (!d3d_res_)
|
||||
hr = E_UNEXPECTED;
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
output_size_.x = static_cast<float>(width);
|
||||
output_size_.y = static_cast<float>(height);
|
||||
|
||||
hr = d3d_res_->SetLogicalSize(output_size_);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->SetLogicalSize(output_size_);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
render_ctx_->Resize(output_size_);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
// 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/render/Renderer.h>
|
||||
#include <kiwano/render/DirectX/FontCollectionLoader.h>
|
||||
#include <kiwano/render/DirectX/RenderContextImpl.h>
|
||||
|
||||
#if defined(KGE_USE_DIRECTX10)
|
||||
#include <kiwano/render/DirectX/D3D10DeviceResources.h>
|
||||
#else
|
||||
#include <kiwano/render/DirectX/D3D11DeviceResources.h>
|
||||
#endif
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
#if defined(KGE_USE_DIRECTX10)
|
||||
typedef ID3D10DeviceResources ID3DDeviceResources;
|
||||
#else
|
||||
typedef ID3D11DeviceResources ID3DDeviceResources;
|
||||
#endif
|
||||
|
||||
class KGE_API RendererImpl
|
||||
: public Renderer
|
||||
{
|
||||
public:
|
||||
static RendererImpl& GetInstance();
|
||||
|
||||
void CreateTexture(Texture& texture, String const& file_path);
|
||||
|
||||
void CreateTexture(Texture& texture, Resource const& resource);
|
||||
|
||||
void CreateGifImage(GifImage& gif, String const& file_path);
|
||||
|
||||
void CreateGifImage(GifImage& gif, Resource const& resource);
|
||||
|
||||
void CreateGifImageFrame(GifImage::Frame& frame, GifImage const& gif, size_t frame_index);
|
||||
|
||||
void CreateFontCollection(Font& font, String const& file_path);
|
||||
|
||||
void CreateFontCollection(Font& font, Resource const& res);
|
||||
|
||||
void CreateTextFormat(TextLayout& layout);
|
||||
|
||||
void CreateTextLayout(TextLayout& layout);
|
||||
|
||||
void CreateLineShape(Shape& shape, Point const& begin_pos, Point const& end_pos);
|
||||
|
||||
void CreateRectShape(Shape& shape, Rect const& rect);
|
||||
|
||||
void CreateRoundedRectShape(Shape& shape, Rect const& rect, Vec2 const& radius);
|
||||
|
||||
void CreateEllipseShape(Shape& shape, Point const& center, Vec2 const& radius);
|
||||
|
||||
void CreateShapeSink(ShapeSink& sink);
|
||||
|
||||
void CreateBrush(Brush& brush, Color const& color);
|
||||
|
||||
void CreateBrush(Brush& brush, LinearGradientStyle const& style);
|
||||
|
||||
void CreateBrush(Brush& brush, RadialGradientStyle const& style);
|
||||
|
||||
void CreateStrokeStyle(StrokeStyle& stroke_style, CapStyle cap, LineJoinStyle line_join, const float* dash_array,
|
||||
size_t dash_size, float dash_offset);
|
||||
|
||||
TextureRenderContextPtr CreateTextureRenderContext(const Size* desired_size = nullptr);
|
||||
|
||||
public:
|
||||
void BeginDraw();
|
||||
|
||||
void EndDraw();
|
||||
|
||||
void Clear();
|
||||
|
||||
void Present();
|
||||
|
||||
RenderContext& GetContext();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取Direct2D设备资源
|
||||
ID2DDeviceResources* GetD2DDeviceResources();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取Direct3D设备资源
|
||||
ID3DDeviceResources* GetD3DDeviceResources();
|
||||
|
||||
public:
|
||||
void SetupComponent() override;
|
||||
|
||||
void DestroyComponent() override;
|
||||
|
||||
void HandleEvent(Event* evt) override;
|
||||
|
||||
private:
|
||||
RendererImpl();
|
||||
|
||||
HRESULT HandleDeviceLost();
|
||||
|
||||
void Resize(uint32_t width, uint32_t height);
|
||||
|
||||
private:
|
||||
RenderContextImplPtr render_ctx_;
|
||||
ComPtr<ID2DDeviceResources> d2d_res_;
|
||||
ComPtr<ID3DDeviceResources> d3d_res_;
|
||||
ComPtr<IFontCollectionLoader> font_collection_loader_;
|
||||
ComPtr<IResourceFontFileLoader> res_font_file_loader_;
|
||||
ComPtr<IResourceFontCollectionLoader> res_font_collection_loader_;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
inline RenderContext& RendererImpl::GetContext()
|
||||
{
|
||||
return *render_ctx_;
|
||||
}
|
||||
|
||||
inline ID2DDeviceResources* RendererImpl::GetD2DDeviceResources()
|
||||
{
|
||||
KGE_ASSERT(d2d_res_);
|
||||
return d2d_res_.get();
|
||||
}
|
||||
|
||||
inline ID3DDeviceResources* RendererImpl::GetD3DDeviceResources()
|
||||
{
|
||||
KGE_ASSERT(d3d_res_);
|
||||
return d3d_res_.get();
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) 2016-2019 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/Logger.h>
|
||||
#include <kiwano/render/Renderer.h>
|
||||
#include <kiwano/render/DirectX/TextureRenderContextImpl.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
bool TextureRenderContextImpl::GetOutput(Texture& texture)
|
||||
{
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
if (bitmap_rt_)
|
||||
{
|
||||
ComPtr<ID2D1Bitmap> bitmap;
|
||||
|
||||
hr = bitmap_rt_->GetBitmap(&bitmap);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
texture.SetBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright (c) 2016-2019 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/render/TextureRenderContext.h>
|
||||
#include <kiwano/render/DirectX/RenderContextImpl.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
class RendererImpl;
|
||||
|
||||
KGE_DECLARE_SMART_PTR(TextureRenderContextImpl);
|
||||
|
||||
KGE_SUPPRESS_WARNING_PUSH
|
||||
KGE_SUPPRESS_WARNING(4250) // inherits via domainance
|
||||
|
||||
class KGE_API TextureRenderContextImpl
|
||||
: public RenderContextImpl
|
||||
, public TextureRenderContext
|
||||
{
|
||||
friend class RendererImpl;
|
||||
|
||||
public:
|
||||
bool GetOutput(Texture& texture) override;
|
||||
|
||||
using RenderContextImpl::IsValid;
|
||||
|
||||
using RenderContextImpl::BeginDraw;
|
||||
|
||||
using RenderContextImpl::EndDraw;
|
||||
|
||||
using RenderContextImpl::DrawTexture;
|
||||
|
||||
using RenderContextImpl::DrawTextLayout;
|
||||
|
||||
using RenderContextImpl::DrawShape;
|
||||
|
||||
using RenderContextImpl::DrawLine;
|
||||
|
||||
using RenderContextImpl::DrawRectangle;
|
||||
|
||||
using RenderContextImpl::DrawRoundedRectangle;
|
||||
|
||||
using RenderContextImpl::DrawEllipse;
|
||||
|
||||
using RenderContextImpl::FillShape;
|
||||
|
||||
using RenderContextImpl::FillRectangle;
|
||||
|
||||
using RenderContextImpl::FillRoundedRectangle;
|
||||
|
||||
using RenderContextImpl::FillEllipse;
|
||||
|
||||
using RenderContextImpl::CreateTexture;
|
||||
|
||||
using RenderContextImpl::PushClipRect;
|
||||
|
||||
using RenderContextImpl::PopClipRect;
|
||||
|
||||
using RenderContextImpl::PushLayer;
|
||||
|
||||
using RenderContextImpl::PopLayer;
|
||||
|
||||
using RenderContextImpl::Clear;
|
||||
|
||||
using RenderContextImpl::GetSize;
|
||||
|
||||
using RenderContextImpl::SetCurrentBrush;
|
||||
|
||||
using RenderContextImpl::SetTransform;
|
||||
|
||||
using RenderContextImpl::SetAntialiasMode;
|
||||
|
||||
using RenderContextImpl::SetTextAntialiasMode;
|
||||
|
||||
using RenderContextImpl::CheckVisibility;
|
||||
|
||||
using RenderContextImpl::Resize;
|
||||
|
||||
private:
|
||||
ComPtr<ID2D1BitmapRenderTarget> bitmap_rt_;
|
||||
};
|
||||
|
||||
KGE_SUPPRESS_WARNING_POP
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
@ -63,11 +63,12 @@ public:
|
|||
bool Load(Resource const& resource);
|
||||
|
||||
#if defined(KGE_WIN32)
|
||||
private:
|
||||
public:
|
||||
ComPtr<IDWriteFontCollection> GetCollection() const;
|
||||
|
||||
void SetCollection(ComPtr<IDWriteFontCollection> collection);
|
||||
|
||||
private:
|
||||
ComPtr<IDWriteFontCollection> collection_;
|
||||
#endif
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@
|
|||
|
||||
namespace kiwano
|
||||
{
|
||||
class Renderer;
|
||||
|
||||
KGE_DECLARE_SMART_PTR(GifImage);
|
||||
|
||||
/**
|
||||
|
|
@ -39,8 +37,6 @@ KGE_DECLARE_SMART_PTR(GifImage);
|
|||
*/
|
||||
class KGE_API GifImage : public virtual ObjectBase
|
||||
{
|
||||
friend class Renderer;
|
||||
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief ´´½¨GIFͼƬ
|
||||
|
|
@ -113,10 +109,12 @@ private:
|
|||
uint32_t height_in_pixels_;
|
||||
|
||||
#if defined(KGE_WIN32)
|
||||
public:
|
||||
ComPtr<IWICBitmapDecoder> GetDecoder() const;
|
||||
|
||||
void SetDecoder(ComPtr<IWICBitmapDecoder> decoder);
|
||||
|
||||
private:
|
||||
ComPtr<IWICBitmapDecoder> decoder_;
|
||||
#endif
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
namespace kiwano
|
||||
{
|
||||
class RenderContext;
|
||||
|
||||
/**
|
||||
* \addtogroup Render
|
||||
|
|
@ -36,8 +35,6 @@ class RenderContext;
|
|||
*/
|
||||
class KGE_API LayerArea
|
||||
{
|
||||
friend class RenderContext;
|
||||
|
||||
public:
|
||||
LayerArea();
|
||||
|
||||
|
|
@ -84,10 +81,12 @@ private:
|
|||
Matrix3x2 mask_transform_;
|
||||
|
||||
#if defined(KGE_WIN32)
|
||||
public:
|
||||
ComPtr<ID2D1Layer> GetLayer() const;
|
||||
|
||||
void SetLayer(ComPtr<ID2D1Layer> layer);
|
||||
|
||||
private:
|
||||
ComPtr<ID2D1Layer> layer_;
|
||||
#endif
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano/core/Logger.h>
|
||||
#include <kiwano/render/RenderContext.h>
|
||||
|
||||
namespace kiwano
|
||||
|
|
@ -31,47 +30,6 @@ RenderContext::RenderContext()
|
|||
, antialias_(true)
|
||||
, text_antialias_(TextAntialiasMode::GrayScale)
|
||||
{
|
||||
status_.primitives = 0;
|
||||
}
|
||||
|
||||
HRESULT RenderContext::CreateDeviceResources(ComPtr<ID2D1Factory> factory, ComPtr<ID2D1RenderTarget> ctx)
|
||||
{
|
||||
if (!factory || !ctx)
|
||||
return E_INVALIDARG;
|
||||
|
||||
render_target_ = ctx;
|
||||
text_renderer_.reset();
|
||||
current_brush_.reset();
|
||||
|
||||
HRESULT hr = ITextRenderer::Create(&text_renderer_, render_target_.get());
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
SetAntialiasMode(antialias_);
|
||||
SetTextAntialiasMode(text_antialias_);
|
||||
|
||||
Resize(reinterpret_cast<const Size&>(GetRenderTarget()->GetSize()));
|
||||
}
|
||||
|
||||
// DrawingStateBlock
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = factory->CreateDrawingStateBlock(&drawing_state_);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
void RenderContext::DiscardDeviceResources()
|
||||
{
|
||||
text_renderer_.reset();
|
||||
render_target_.reset();
|
||||
current_brush_.reset();
|
||||
}
|
||||
|
||||
bool RenderContext::IsValid() const
|
||||
{
|
||||
return render_target_ != nullptr;
|
||||
}
|
||||
|
||||
void RenderContext::BeginDraw()
|
||||
|
|
@ -81,340 +39,16 @@ void RenderContext::BeginDraw()
|
|||
status_.start = Time::Now();
|
||||
status_.primitives = 0;
|
||||
}
|
||||
|
||||
if (render_target_)
|
||||
{
|
||||
render_target_->BeginDraw();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContext::EndDraw()
|
||||
{
|
||||
win32::ThrowIfFailed(render_target_->EndDraw());
|
||||
|
||||
if (collecting_status_)
|
||||
{
|
||||
status_.duration = Time::Now() - status_.start;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContext::DrawTexture(Texture const& texture, Rect const& src_rect, Rect const& dest_rect)
|
||||
{
|
||||
DrawTexture(texture, &src_rect, &dest_rect);
|
||||
}
|
||||
|
||||
void RenderContext::DrawTexture(Texture const& texture, const Rect* src_rect, const Rect* dest_rect)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
|
||||
if (texture.IsValid())
|
||||
{
|
||||
auto mode = (texture.GetBitmapInterpolationMode() == InterpolationMode::Linear)
|
||||
? D2D1_BITMAP_INTERPOLATION_MODE_LINEAR
|
||||
: D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR;
|
||||
|
||||
render_target_->DrawBitmap(texture.GetBitmap().get(), dest_rect ? &DX::ConvertToRectF(*dest_rect) : nullptr,
|
||||
brush_opacity_, mode, src_rect ? &DX::ConvertToRectF(*src_rect) : nullptr);
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContext::DrawTextLayout(TextLayout const& layout, Point const& offset)
|
||||
{
|
||||
KGE_ASSERT(text_renderer_ && "Text renderer has not been initialized!");
|
||||
|
||||
if (layout.IsValid())
|
||||
{
|
||||
ComPtr<ID2D1Brush> fill_brush;
|
||||
ComPtr<ID2D1Brush> outline_brush;
|
||||
const TextStyle& style = layout.GetStyle();
|
||||
|
||||
if (style.fill_brush)
|
||||
{
|
||||
fill_brush = style.fill_brush->GetBrush();
|
||||
fill_brush->SetOpacity(brush_opacity_);
|
||||
}
|
||||
|
||||
if (style.outline_brush)
|
||||
{
|
||||
outline_brush = style.outline_brush->GetBrush();
|
||||
outline_brush->SetOpacity(brush_opacity_);
|
||||
}
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (style.outline_stroke)
|
||||
{
|
||||
hr = text_renderer_->DrawTextLayout(layout.GetTextLayout().get(), offset.x, offset.y, fill_brush.get(),
|
||||
outline_brush.get(), style.outline_width,
|
||||
style.outline_stroke->GetStrokeStyle().get());
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = text_renderer_->DrawTextLayout(layout.GetTextLayout().get(), offset.x, offset.y, fill_brush.get(),
|
||||
outline_brush.get(), style.outline_width, nullptr);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IncreasePrimitivesCount(text_renderer_->GetLastPrimitivesCount());
|
||||
}
|
||||
else
|
||||
{
|
||||
KGE_ERROR(L"Failed to draw text layout with HRESULT of %08X", hr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContext::DrawShape(Shape const& shape, StrokeStylePtr stroke, float stroke_width)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
if (shape.IsValid())
|
||||
{
|
||||
if (stroke)
|
||||
{
|
||||
render_target_->DrawGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get(), stroke_width,
|
||||
stroke->GetStrokeStyle().get());
|
||||
}
|
||||
else
|
||||
{
|
||||
render_target_->DrawGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get(), stroke_width,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContext::DrawLine(Point const& point1, Point const& point2, StrokeStylePtr stroke, float stroke_width)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
if (stroke)
|
||||
{
|
||||
render_target_->DrawLine(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2),
|
||||
current_brush_->GetBrush().get(), stroke_width, stroke->GetStrokeStyle().get());
|
||||
}
|
||||
else
|
||||
{
|
||||
render_target_->DrawLine(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2),
|
||||
current_brush_->GetBrush().get(), stroke_width, nullptr);
|
||||
}
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContext::DrawRectangle(Rect const& rect, StrokeStylePtr stroke, float stroke_width)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
if (stroke)
|
||||
{
|
||||
render_target_->DrawRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get(), stroke_width,
|
||||
stroke->GetStrokeStyle().get());
|
||||
}
|
||||
else
|
||||
{
|
||||
render_target_->DrawRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get(), stroke_width,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContext::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, StrokeStylePtr stroke,
|
||||
float stroke_width)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
if (stroke)
|
||||
{
|
||||
render_target_->DrawRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y),
|
||||
current_brush_->GetBrush().get(), stroke_width,
|
||||
stroke->GetStrokeStyle().get());
|
||||
}
|
||||
else
|
||||
{
|
||||
render_target_->DrawRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y),
|
||||
current_brush_->GetBrush().get(), stroke_width, nullptr);
|
||||
}
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContext::DrawEllipse(Point const& center, Vec2 const& radius, StrokeStylePtr stroke, float stroke_width)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
if (stroke)
|
||||
{
|
||||
render_target_->DrawEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y),
|
||||
current_brush_->GetBrush().get(), stroke_width, stroke->GetStrokeStyle().get());
|
||||
}
|
||||
else
|
||||
{
|
||||
render_target_->DrawEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y),
|
||||
current_brush_->GetBrush().get(), stroke_width, nullptr);
|
||||
}
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContext::FillShape(Shape const& shape)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
if (shape.IsValid())
|
||||
{
|
||||
render_target_->FillGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContext::FillRectangle(Rect const& rect)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
render_target_->FillRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContext::FillRoundedRectangle(Rect const& rect, Vec2 const& radius)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
render_target_->FillRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y),
|
||||
current_brush_->GetBrush().get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContext::FillEllipse(Point const& center, Vec2 const& radius)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
render_target_->FillEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y),
|
||||
current_brush_->GetBrush().get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContext::CreateTexture(Texture& texture, math::Vec2T<uint32_t> size)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
|
||||
ComPtr<ID2D1Bitmap> saved_bitmap;
|
||||
|
||||
HRESULT hr = render_target_->CreateBitmap(D2D1::SizeU(size.x, size.y), D2D1::BitmapProperties(), &saved_bitmap);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
texture.SetBitmap(saved_bitmap);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RenderContext::PushClipRect(Rect const& clip_rect)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
render_target_->PushAxisAlignedClip(DX::ConvertToRectF(clip_rect),
|
||||
antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED);
|
||||
}
|
||||
|
||||
void RenderContext::PopClipRect()
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
render_target_->PopAxisAlignedClip();
|
||||
}
|
||||
|
||||
void RenderContext::PushLayer(LayerArea& layer)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
if (!layer.IsValid())
|
||||
{
|
||||
ComPtr<ID2D1Layer> output;
|
||||
HRESULT hr = render_target_->CreateLayer(&output);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
layer.SetLayer(output);
|
||||
}
|
||||
else
|
||||
{
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
}
|
||||
|
||||
if (layer.IsValid())
|
||||
{
|
||||
ComPtr<ID2D1Geometry> mask;
|
||||
if (layer.GetMaskShape())
|
||||
mask = layer.GetMaskShape()->GetGeometry();
|
||||
|
||||
render_target_->PushLayer(
|
||||
D2D1::LayerParameters(DX::ConvertToRectF(layer.GetAreaRect()), mask.get(),
|
||||
antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED,
|
||||
DX::ConvertToMatrix3x2F(layer.GetMaskTransform()), layer.GetOpacity(), nullptr,
|
||||
D2D1_LAYER_OPTIONS_NONE),
|
||||
layer.GetLayer().get());
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContext::PopLayer()
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
render_target_->PopLayer();
|
||||
}
|
||||
|
||||
void RenderContext::Clear()
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
render_target_->Clear();
|
||||
}
|
||||
|
||||
void RenderContext::Clear(Color const& clear_color)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
render_target_->Clear(DX::ConvertToColorF(clear_color));
|
||||
}
|
||||
|
||||
Size RenderContext::GetSize() const
|
||||
{
|
||||
if (render_target_)
|
||||
{
|
||||
return reinterpret_cast<const Size&>(render_target_->GetSize());
|
||||
}
|
||||
return Size();
|
||||
}
|
||||
|
||||
void RenderContext::SetTransform(const Matrix3x2& matrix)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
|
||||
if (fast_global_transform_)
|
||||
{
|
||||
render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix));
|
||||
}
|
||||
else
|
||||
{
|
||||
Matrix3x2 result = matrix * global_transform_;
|
||||
render_target_->SetTransform(DX::ConvertToMatrix3x2F(&result));
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContext::SetGlobalTransform(const Matrix3x2* matrix)
|
||||
{
|
||||
if (matrix)
|
||||
|
|
@ -428,57 +62,6 @@ void RenderContext::SetGlobalTransform(const Matrix3x2* matrix)
|
|||
}
|
||||
}
|
||||
|
||||
void RenderContext::SetAntialiasMode(bool enabled)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
|
||||
render_target_->SetAntialiasMode(enabled ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED);
|
||||
antialias_ = enabled;
|
||||
}
|
||||
|
||||
void RenderContext::SetTextAntialiasMode(TextAntialiasMode mode)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
|
||||
D2D1_TEXT_ANTIALIAS_MODE antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
||||
switch (mode)
|
||||
{
|
||||
case TextAntialiasMode::Default:
|
||||
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
|
||||
break;
|
||||
case TextAntialiasMode::ClearType:
|
||||
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
||||
break;
|
||||
case TextAntialiasMode::GrayScale:
|
||||
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
||||
break;
|
||||
case TextAntialiasMode::None:
|
||||
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
text_antialias_ = mode;
|
||||
render_target_->SetTextAntialiasMode(antialias_mode);
|
||||
}
|
||||
|
||||
bool RenderContext::CheckVisibility(Rect const& bounds, Matrix3x2 const& transform)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
|
||||
if (fast_global_transform_)
|
||||
{
|
||||
return visible_size_.Intersects(transform.Transform(bounds));
|
||||
}
|
||||
return visible_size_.Intersects(Matrix3x2(transform * global_transform_).Transform(bounds));
|
||||
}
|
||||
|
||||
void RenderContext::Resize(Size const& size)
|
||||
{
|
||||
visible_size_ = Rect(Point(), size);
|
||||
}
|
||||
|
||||
void RenderContext::SetCollectingStatus(bool enable)
|
||||
{
|
||||
collecting_status_ = enable;
|
||||
|
|
@ -492,24 +75,34 @@ void RenderContext::IncreasePrimitivesCount(uint32_t increase) const
|
|||
}
|
||||
}
|
||||
|
||||
void RenderContext::SaveDrawingState()
|
||||
float RenderContext::GetBrushOpacity() const
|
||||
{
|
||||
KGE_ASSERT(IsValid());
|
||||
|
||||
if (drawing_state_)
|
||||
{
|
||||
render_target_->SaveDrawingState(drawing_state_.get());
|
||||
}
|
||||
return brush_opacity_;
|
||||
}
|
||||
|
||||
void RenderContext::RestoreDrawingState()
|
||||
BrushPtr RenderContext::GetCurrentBrush() const
|
||||
{
|
||||
KGE_ASSERT(IsValid());
|
||||
|
||||
if (drawing_state_)
|
||||
{
|
||||
render_target_->RestoreDrawingState(drawing_state_.get());
|
||||
return current_brush_;
|
||||
}
|
||||
|
||||
const Matrix3x2& RenderContext::GetGlobalTransform() const
|
||||
{
|
||||
return global_transform_;
|
||||
}
|
||||
|
||||
void RenderContext::SetBrushOpacity(float opacity)
|
||||
{
|
||||
brush_opacity_ = opacity;
|
||||
}
|
||||
|
||||
void RenderContext::SetGlobalTransform(const Matrix3x2& matrix)
|
||||
{
|
||||
SetGlobalTransform(&matrix);
|
||||
}
|
||||
|
||||
void RenderContext::SetCurrentBrush(BrushPtr brush)
|
||||
{
|
||||
current_brush_ = brush;
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -60,42 +60,36 @@ class KGE_API RenderContext : public virtual ObjectBase
|
|||
public:
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
bool IsValid() const;
|
||||
virtual bool IsValid() const = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 开始渲染
|
||||
void BeginDraw();
|
||||
virtual void BeginDraw();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 结束渲染
|
||||
void EndDraw();
|
||||
virtual void EndDraw();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 绘制纹理
|
||||
/// @param texture 纹理
|
||||
/// @param src_rect 源纹理裁剪矩形
|
||||
/// @param dest_rect 绘制的目标区域
|
||||
void DrawTexture(Texture const& texture, Rect const& src_rect, Rect const& dest_rect);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 绘制纹理
|
||||
/// @param texture 纹理
|
||||
/// @param src_rect 源纹理裁剪矩形
|
||||
/// @param dest_rect 绘制的目标区域
|
||||
void DrawTexture(Texture const& texture, const Rect* src_rect = nullptr, const Rect* dest_rect = nullptr);
|
||||
virtual void DrawTexture(Texture const& texture, const Rect* src_rect = nullptr,
|
||||
const Rect* dest_rect = nullptr) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 绘制文本布局
|
||||
/// @param layout 文本布局
|
||||
/// @param offset 偏移量
|
||||
void DrawTextLayout(TextLayout const& layout, Point const& offset = Point());
|
||||
virtual void DrawTextLayout(TextLayout const& layout, Point const& offset = Point()) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 绘制形状轮廓
|
||||
/// @param shape 形状
|
||||
/// @param stroke 线条样式
|
||||
/// @param stroke_width 线条宽度
|
||||
void DrawShape(Shape const& shape, StrokeStylePtr stroke = nullptr, float stroke_width = 1.0f);
|
||||
virtual void DrawShape(Shape const& shape, StrokeStylePtr stroke = nullptr, float stroke_width = 1.0f) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 绘制线段
|
||||
|
|
@ -103,14 +97,15 @@ public:
|
|||
/// @param point2 线段终点
|
||||
/// @param stroke 线条样式
|
||||
/// @param stroke_width 线条宽度
|
||||
void DrawLine(Point const& point1, Point const& point2, StrokeStylePtr stroke = nullptr, float stroke_width = 1.0f);
|
||||
virtual void DrawLine(Point const& point1, Point const& point2, StrokeStylePtr stroke = nullptr,
|
||||
float stroke_width = 1.0f) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 绘制矩形边框
|
||||
/// @param rect 矩形
|
||||
/// @param stroke 线条样式
|
||||
/// @param stroke_width 线条宽度
|
||||
void DrawRectangle(Rect const& rect, StrokeStylePtr stroke = nullptr, float stroke_width = 1.0f);
|
||||
virtual void DrawRectangle(Rect const& rect, StrokeStylePtr stroke = nullptr, float stroke_width = 1.0f) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 绘制圆角矩形边框
|
||||
|
|
@ -118,8 +113,8 @@ public:
|
|||
/// @param radius 圆角半径
|
||||
/// @param stroke 线条样式
|
||||
/// @param stroke_width 线条宽度
|
||||
void DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, StrokeStylePtr stroke = nullptr,
|
||||
float stroke_width = 1.0f);
|
||||
virtual void DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, StrokeStylePtr stroke = nullptr,
|
||||
float stroke_width = 1.0f) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 绘制椭圆边框
|
||||
|
|
@ -127,115 +122,115 @@ public:
|
|||
/// @param radius 椭圆半径
|
||||
/// @param stroke 线条样式
|
||||
/// @param stroke_width 线条宽度
|
||||
void DrawEllipse(Point const& center, Vec2 const& radius, StrokeStylePtr stroke = nullptr,
|
||||
float stroke_width = 1.0f);
|
||||
virtual void DrawEllipse(Point const& center, Vec2 const& radius, StrokeStylePtr stroke = nullptr,
|
||||
float stroke_width = 1.0f) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 填充形状
|
||||
/// @param shape 形状
|
||||
void FillShape(Shape const& shape);
|
||||
virtual void FillShape(Shape const& shape) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 填充矩形
|
||||
/// @param rect 矩形
|
||||
void FillRectangle(Rect const& rect);
|
||||
virtual void FillRectangle(Rect const& rect) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 填充圆角矩形
|
||||
/// @param rect 矩形
|
||||
/// @param radius 圆角半径
|
||||
void FillRoundedRectangle(Rect const& rect, Vec2 const& radius);
|
||||
virtual void FillRoundedRectangle(Rect const& rect, Vec2 const& radius) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 填充椭圆
|
||||
/// @param center 圆心
|
||||
/// @param radius 椭圆半径
|
||||
void FillEllipse(Point const& center, Vec2 const& radius);
|
||||
virtual void FillEllipse(Point const& center, Vec2 const& radius) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建纹理
|
||||
/// @param texture 纹理
|
||||
/// @param size 纹理像素大小
|
||||
void CreateTexture(Texture& texture, math::Vec2T<uint32_t> size);
|
||||
virtual void CreateTexture(Texture& texture, math::Vec2T<uint32_t> size) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置绘制的裁剪区域
|
||||
/// @param clip_rect 裁剪矩形
|
||||
void PushClipRect(Rect const& clip_rect);
|
||||
virtual void PushClipRect(Rect const& clip_rect) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 取消上一次设置的绘制裁剪区域
|
||||
void PopClipRect();
|
||||
virtual void PopClipRect() = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置图层区域
|
||||
/// @param layer 图层区域
|
||||
void PushLayer(LayerArea& layer);
|
||||
virtual void PushLayer(LayerArea& layer) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 取消上一次设置的图层区域
|
||||
void PopLayer();
|
||||
virtual void PopLayer() = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 清空渲染内容
|
||||
void Clear();
|
||||
virtual void Clear() = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 使用纯色清空渲染内容
|
||||
/// @param clear_color 清屏颜色
|
||||
void Clear(Color const& clear_color);
|
||||
virtual void Clear(Color const& clear_color) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取渲染区域大小
|
||||
Size GetSize() const;
|
||||
virtual Size GetSize() const = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取画刷透明度
|
||||
float GetBrushOpacity() const;
|
||||
virtual float GetBrushOpacity() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取当前画刷
|
||||
BrushPtr GetCurrentBrush() const;
|
||||
virtual BrushPtr GetCurrentBrush() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取全局二维变换
|
||||
Matrix3x2 GetGlobalTransform() const;
|
||||
virtual const Matrix3x2& GetGlobalTransform() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置画刷透明度
|
||||
void SetBrushOpacity(float opacity);
|
||||
virtual void SetBrushOpacity(float opacity);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置当前画刷
|
||||
void SetCurrentBrush(BrushPtr brush);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置上下文的二维变换
|
||||
void SetTransform(const Matrix3x2& matrix);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置全局二维变换
|
||||
void SetGlobalTransform(const Matrix3x2& matrix);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置全局二维变换
|
||||
void SetGlobalTransform(const Matrix3x2* matrix);
|
||||
virtual void SetCurrentBrush(BrushPtr brush);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置抗锯齿模式
|
||||
void SetAntialiasMode(bool enabled);
|
||||
virtual void SetAntialiasMode(bool enabled) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置文字抗锯齿模式
|
||||
void SetTextAntialiasMode(TextAntialiasMode mode);
|
||||
virtual void SetTextAntialiasMode(TextAntialiasMode mode) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 检查边界是否在视区内
|
||||
bool CheckVisibility(Rect const& bounds, Matrix3x2 const& transform);
|
||||
virtual bool CheckVisibility(Rect const& bounds, Matrix3x2 const& transform) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 重设渲染上下文大小
|
||||
void Resize(Size const& size);
|
||||
virtual void Resize(Size const& size) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置上下文的二维变换
|
||||
virtual void SetTransform(const Matrix3x2& matrix) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置全局二维变换
|
||||
virtual void SetGlobalTransform(const Matrix3x2& matrix);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置全局二维变换
|
||||
virtual void SetGlobalTransform(const Matrix3x2* matrix);
|
||||
|
||||
public:
|
||||
/// \~chinese
|
||||
|
|
@ -260,32 +255,11 @@ public:
|
|||
protected:
|
||||
RenderContext();
|
||||
|
||||
ComPtr<ID2D1RenderTarget> GetRenderTarget() const;
|
||||
|
||||
ComPtr<ITextRenderer> GetTextRenderer() const;
|
||||
|
||||
private:
|
||||
/// \~chinese
|
||||
/// @brief 创建设备依赖资源
|
||||
HRESULT CreateDeviceResources(ComPtr<ID2D1Factory> factory, ComPtr<ID2D1RenderTarget> ctx);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 销毁设备依赖资源
|
||||
void DiscardDeviceResources();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 增加渲染图元数量
|
||||
void IncreasePrimitivesCount(uint32_t increase = 1) const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 保存绘制状态
|
||||
void SaveDrawingState();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 恢复绘制状态
|
||||
void RestoreDrawingState();
|
||||
|
||||
private:
|
||||
protected:
|
||||
bool antialias_;
|
||||
bool fast_global_transform_;
|
||||
mutable bool collecting_status_;
|
||||
|
|
@ -295,10 +269,6 @@ private:
|
|||
Rect visible_size_;
|
||||
Matrix3x2 global_transform_;
|
||||
mutable Status status_;
|
||||
|
||||
ComPtr<ITextRenderer> text_renderer_;
|
||||
ComPtr<ID2D1RenderTarget> render_target_;
|
||||
ComPtr<ID2D1DrawingStateBlock> drawing_state_;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
|
@ -313,50 +283,4 @@ inline RenderContext::Status const& RenderContext::GetStatus() const
|
|||
return status_;
|
||||
}
|
||||
|
||||
inline ComPtr<ID2D1RenderTarget> RenderContext::GetRenderTarget() const
|
||||
{
|
||||
KGE_ASSERT(render_target_);
|
||||
return render_target_;
|
||||
}
|
||||
|
||||
inline ComPtr<ITextRenderer> RenderContext::GetTextRenderer() const
|
||||
{
|
||||
KGE_ASSERT(text_renderer_);
|
||||
return text_renderer_;
|
||||
}
|
||||
|
||||
inline float RenderContext::GetBrushOpacity() const
|
||||
{
|
||||
return brush_opacity_;
|
||||
}
|
||||
|
||||
inline BrushPtr RenderContext::GetCurrentBrush() const
|
||||
{
|
||||
return current_brush_;
|
||||
}
|
||||
|
||||
inline Matrix3x2 RenderContext::GetGlobalTransform() const
|
||||
{
|
||||
return global_transform_;
|
||||
}
|
||||
|
||||
inline void RenderContext::SetBrushOpacity(float opacity)
|
||||
{
|
||||
brush_opacity_ = opacity;
|
||||
}
|
||||
|
||||
inline void RenderContext::SetGlobalTransform(const Matrix3x2& matrix)
|
||||
{
|
||||
SetGlobalTransform(&matrix);
|
||||
}
|
||||
|
||||
inline void RenderContext::SetCurrentBrush(BrushPtr brush)
|
||||
{
|
||||
current_brush_ = brush;
|
||||
if (current_brush_)
|
||||
{
|
||||
current_brush_->SetOpacity(brush_opacity_);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -18,10 +18,6 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano/core/Logger.h>
|
||||
#include <kiwano/core/event/WindowEvent.h>
|
||||
#include <kiwano/platform/FileSystem.h>
|
||||
#include <kiwano/render/ShapeSink.h>
|
||||
#include <kiwano/render/Renderer.h>
|
||||
|
||||
namespace kiwano
|
||||
|
|
@ -34,934 +30,4 @@ Renderer::Renderer()
|
|||
{
|
||||
}
|
||||
|
||||
Renderer::~Renderer() {}
|
||||
|
||||
void Renderer::SetupComponent()
|
||||
{
|
||||
KGE_SYS_LOG(L"Creating device resources");
|
||||
|
||||
win32::ThrowIfFailed(::CoInitialize(nullptr));
|
||||
|
||||
target_window_ = Window::GetInstance().GetHandle();
|
||||
output_size_ = Window::GetInstance().GetSize();
|
||||
|
||||
d2d_res_ = nullptr;
|
||||
d3d_res_ = nullptr;
|
||||
|
||||
HRESULT hr = target_window_ ? S_OK : E_FAIL;
|
||||
|
||||
// Direct3D device resources
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = ID3DDeviceResources::Create(&d3d_res_, target_window_);
|
||||
|
||||
// Direct2D device resources
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = ID2DDeviceResources::Create(&d2d_res_, d3d_res_->GetDXGIDevice(), d3d_res_->GetDXGISwapChain());
|
||||
|
||||
// Other device resources
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = render_ctx_.CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext());
|
||||
}
|
||||
|
||||
// FontFileLoader and FontCollectionLoader
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IFontCollectionLoader::Create(&font_collection_loader_);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(font_collection_loader_.get());
|
||||
}
|
||||
}
|
||||
|
||||
// ResourceFontFileLoader and ResourceFontCollectionLoader
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IResourceFontFileLoader::Create(&res_font_file_loader_);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetDWriteFactory()->RegisterFontFileLoader(res_font_file_loader_.get());
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IResourceFontCollectionLoader::Create(&res_font_collection_loader_,
|
||||
res_font_file_loader_.get());
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(
|
||||
res_font_collection_loader_.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::DestroyComponent()
|
||||
{
|
||||
KGE_SYS_LOG(L"Destroying device resources");
|
||||
|
||||
render_ctx_.DiscardDeviceResources();
|
||||
|
||||
d2d_res_->GetDWriteFactory()->UnregisterFontFileLoader(res_font_file_loader_.get());
|
||||
res_font_file_loader_.reset();
|
||||
|
||||
d2d_res_->GetDWriteFactory()->UnregisterFontCollectionLoader(res_font_collection_loader_.get());
|
||||
res_font_collection_loader_.reset();
|
||||
|
||||
d2d_res_.reset();
|
||||
d3d_res_.reset();
|
||||
|
||||
::CoUninitialize();
|
||||
}
|
||||
|
||||
void Renderer::BeginDraw()
|
||||
{
|
||||
KGE_ASSERT(render_ctx_.IsValid());
|
||||
|
||||
render_ctx_.SaveDrawingState();
|
||||
render_ctx_.BeginDraw();
|
||||
}
|
||||
|
||||
void Renderer::EndDraw()
|
||||
{
|
||||
KGE_ASSERT(render_ctx_.IsValid());
|
||||
|
||||
render_ctx_.EndDraw();
|
||||
render_ctx_.RestoreDrawingState();
|
||||
}
|
||||
|
||||
void Renderer::Clear()
|
||||
{
|
||||
KGE_ASSERT(d3d_res_);
|
||||
|
||||
HRESULT hr = d3d_res_->ClearRenderTarget(clear_color_);
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::Present()
|
||||
{
|
||||
KGE_ASSERT(d3d_res_);
|
||||
|
||||
HRESULT hr = d3d_res_->Present(vsync_);
|
||||
|
||||
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
|
||||
{
|
||||
// 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
|
||||
hr = HandleDeviceLost();
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::HandleEvent(Event* evt)
|
||||
{
|
||||
if (evt->IsType<WindowResizedEvent>())
|
||||
{
|
||||
auto window_evt = dynamic_cast<WindowResizedEvent*>(evt);
|
||||
ResizeTarget(window_evt->width, window_evt->height);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT Renderer::HandleDeviceLost()
|
||||
{
|
||||
KGE_ASSERT(d3d_res_ && d2d_res_ && render_ctx_.IsValid());
|
||||
|
||||
HRESULT hr = d3d_res_->HandleDeviceLost();
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->HandleDeviceLost(d3d_res_->GetDXGIDevice(), d3d_res_->GetDXGISwapChain());
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = render_ctx_.CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext());
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
void Renderer::CreateTexture(Texture& texture, String const& file_path)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!FileSystem::GetInstance().IsFileExists(file_path))
|
||||
{
|
||||
KGE_WARN(L"Texture file '%s' not found!", file_path.c_str());
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
String full_path = FileSystem::GetInstance().GetFullPathForFile(file_path);
|
||||
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, full_path);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICBitmapFrameDecode> source;
|
||||
hr = decoder->GetFrame(0, &source);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICFormatConverter> converter;
|
||||
hr = d2d_res_->CreateBitmapConverter(converter, source, GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone, nullptr, 0.f,
|
||||
WICBitmapPaletteTypeMedianCut);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1Bitmap> bitmap;
|
||||
hr = d2d_res_->CreateBitmapFromConverter(bitmap, nullptr, converter);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
texture.SetBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARN(L"Load texture failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::CreateTexture(Texture& texture, Resource const& resource)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = d2d_res_->CreateBitmapDecoderFromResource(decoder, resource);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICBitmapFrameDecode> source;
|
||||
hr = decoder->GetFrame(0, &source);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICFormatConverter> converter;
|
||||
hr = d2d_res_->CreateBitmapConverter(converter, source, GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone, nullptr, 0.f,
|
||||
WICBitmapPaletteTypeMedianCut);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1Bitmap> bitmap;
|
||||
hr = d2d_res_->CreateBitmapFromConverter(bitmap, nullptr, converter);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
texture.SetBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARN(L"Load texture failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::CreateGifImage(GifImage& gif, String const& file_path)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!FileSystem::GetInstance().IsFileExists(file_path))
|
||||
{
|
||||
KGE_WARN(L"Gif texture file '%s' not found!", file_path.c_str());
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
String full_path = FileSystem::GetInstance().GetFullPathForFile(file_path);
|
||||
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, full_path);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
gif.SetDecoder(decoder);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARN(L"Load GIF texture failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::CreateGifImage(GifImage& gif, Resource const& resource)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = d2d_res_->CreateBitmapDecoderFromResource(decoder, resource);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
gif.SetDecoder(decoder);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARN(L"Load GIF texture failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::CreateGifImageFrame(GifImage::Frame& frame, GifImage const& gif, size_t frame_index)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (gif.GetDecoder() == nullptr)
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICBitmapFrameDecode> wic_frame;
|
||||
|
||||
HRESULT hr = gif.GetDecoder()->GetFrame(UINT(frame_index), &wic_frame);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICFormatConverter> converter;
|
||||
d2d_res_->CreateBitmapConverter(converter, wic_frame, GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone, nullptr, 0.f, WICBitmapPaletteTypeCustom);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1Bitmap> raw_bitmap;
|
||||
hr = d2d_res_->CreateBitmapFromConverter(raw_bitmap, nullptr, converter);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.texture = new Texture;
|
||||
frame.texture->SetBitmap(raw_bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
PROPVARIANT prop_val;
|
||||
PropVariantInit(&prop_val);
|
||||
|
||||
// Get Metadata Query Reader from the frame
|
||||
ComPtr<IWICMetadataQueryReader> metadata_reader;
|
||||
hr = wic_frame->GetMetadataQueryReader(&metadata_reader);
|
||||
|
||||
// Get the Metadata for the current frame
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = metadata_reader->GetMetadataByName(L"/imgdesc/Left", &prop_val);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.rect.left_top.x = static_cast<float>(prop_val.uiVal);
|
||||
}
|
||||
PropVariantClear(&prop_val);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = metadata_reader->GetMetadataByName(L"/imgdesc/Top", &prop_val);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.rect.left_top.y = static_cast<float>(prop_val.uiVal);
|
||||
}
|
||||
PropVariantClear(&prop_val);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = metadata_reader->GetMetadataByName(L"/imgdesc/Width", &prop_val);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.rect.right_bottom.x = frame.rect.left_top.x + static_cast<float>(prop_val.uiVal);
|
||||
}
|
||||
PropVariantClear(&prop_val);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = metadata_reader->GetMetadataByName(L"/imgdesc/Height", &prop_val);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.rect.right_bottom.y = frame.rect.left_top.y + static_cast<float>(prop_val.uiVal);
|
||||
}
|
||||
PropVariantClear(&prop_val);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = metadata_reader->GetMetadataByName(L"/grctlext/Delay", &prop_val);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
uint32_t udelay = 0;
|
||||
|
||||
hr = UIntMult(prop_val.uiVal, 10, &udelay);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.delay.SetMilliseconds(static_cast<long>(udelay));
|
||||
}
|
||||
}
|
||||
PropVariantClear(&prop_val);
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.delay = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = metadata_reader->GetMetadataByName(L"/grctlext/Disposal", &prop_val);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = (prop_val.vt == VT_UI1) ? S_OK : E_FAIL;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.disposal_type = GifImage::DisposalType(prop_val.bVal);
|
||||
}
|
||||
::PropVariantClear(&prop_val);
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.disposal_type = GifImage::DisposalType::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
::PropVariantClear(&prop_val);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARN(L"Load GIF frame failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::CreateFontCollection(Font& font, String const& file_path)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (!FileSystem::GetInstance().IsFileExists(file_path))
|
||||
{
|
||||
KGE_WARN(L"Font file '%s' not found!", file_path.c_str());
|
||||
hr = E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
LPVOID key = nullptr;
|
||||
uint32_t key_size = 0;
|
||||
String full_path = FileSystem::GetInstance().GetFullPathForFile(file_path);
|
||||
|
||||
hr = font_collection_loader_->AddFilePaths({ full_path }, &key, &key_size);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IDWriteFontCollection> font_collection;
|
||||
hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection(font_collection_loader_.get(), key, key_size,
|
||||
&font_collection);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
font.SetCollection(font_collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::CreateFontCollection(Font& font, Resource const& res)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
LPVOID key = nullptr;
|
||||
uint32_t key_size = 0;
|
||||
|
||||
hr = res_font_collection_loader_->AddResources(Vector<Resource>{ res }, &key, &key_size);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IDWriteFontCollection> font_collection;
|
||||
hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection(res_font_collection_loader_.get(), key,
|
||||
key_size, &font_collection);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
font.SetCollection(font_collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::CreateTextFormat(TextLayout& layout)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ComPtr<IDWriteTextFormat> output;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
const TextStyle& style = layout.GetStyle();
|
||||
|
||||
hr = d2d_res_->CreateTextFormat(output, style.font_family, style.font ? style.font->GetCollection() : nullptr,
|
||||
DWRITE_FONT_WEIGHT(style.font_weight),
|
||||
style.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL,
|
||||
DWRITE_FONT_STRETCH_NORMAL, style.font_size);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
layout.SetTextFormat(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::CreateTextLayout(TextLayout& layout)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ComPtr<IDWriteTextLayout> output;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->CreateTextLayout(output, layout.GetText(), layout.GetTextFormat());
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
layout.SetTextLayout(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::CreateLineShape(Shape& shape, Point const& begin_pos, Point const& end_pos)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ComPtr<ID2D1PathGeometry> path_geo;
|
||||
ComPtr<ID2D1GeometrySink> path_sink;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetFactory()->CreatePathGeometry(&path_geo);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = path_geo->Open(&path_sink);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
path_sink->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
|
||||
path_sink->AddLine(DX::ConvertToPoint2F(end_pos));
|
||||
path_sink->EndFigure(D2D1_FIGURE_END_OPEN);
|
||||
hr = path_sink->Close();
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
shape.SetGeometry(path_geo);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::CreateRectShape(Shape& shape, Rect const& rect)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ComPtr<ID2D1RectangleGeometry> output;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetFactory()->CreateRectangleGeometry(DX::ConvertToRectF(rect), &output);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
shape.SetGeometry(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::CreateRoundedRectShape(Shape& shape, Rect const& rect, Vec2 const& radius)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ComPtr<ID2D1RoundedRectangleGeometry> output;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetFactory()->CreateRoundedRectangleGeometry(
|
||||
D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y), &output);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
shape.SetGeometry(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::CreateEllipseShape(Shape& shape, Point const& center, Vec2 const& radius)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ComPtr<ID2D1EllipseGeometry> output;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetFactory()->CreateEllipseGeometry(
|
||||
D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y), &output);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
shape.SetGeometry(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::CreateShapeSink(ShapeSink& sink)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ComPtr<ID2D1PathGeometry> output;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetFactory()->CreatePathGeometry(&output);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
sink.SetPathGeometry(output);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::CreateTextureRenderContext(TextureRenderContext& render_context, const Size* desired_size)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1BitmapRenderTarget> bitmap_rt;
|
||||
|
||||
if (desired_size)
|
||||
{
|
||||
hr = d2d_res_->GetDeviceContext()->CreateCompatibleRenderTarget(DX::ConvertToSizeF(*desired_size),
|
||||
&bitmap_rt);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = d2d_res_->GetDeviceContext()->CreateCompatibleRenderTarget(&bitmap_rt);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = render_context.CreateDeviceResources(d2d_res_->GetFactory(), bitmap_rt);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
render_context.SetBitmapRenderTarget(bitmap_rt);
|
||||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::CreateBrush(Brush& brush, Color const& color)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1SolidColorBrush> solid_brush;
|
||||
|
||||
if (brush.GetType() == Brush::Type::SolidColor && brush.GetBrush())
|
||||
{
|
||||
hr = brush.GetBrush()->QueryInterface(&solid_brush);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
solid_brush->SetColor(DX::ConvertToColorF(color));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = d2d_res_->GetDeviceContext()->CreateSolidColorBrush(DX::ConvertToColorF(color), &solid_brush);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
brush.SetBrush(solid_brush, Brush::Type::SolidColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::CreateBrush(Brush& brush, LinearGradientStyle const& style)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1GradientStopCollection> collection;
|
||||
hr = d2d_res_->GetDeviceContext()->CreateGradientStopCollection(
|
||||
reinterpret_cast<const D2D1_GRADIENT_STOP*>(&style.stops[0]), UINT32(style.stops.size()), D2D1_GAMMA_2_2,
|
||||
D2D1_EXTEND_MODE(style.extend_mode), &collection);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1LinearGradientBrush> output;
|
||||
hr = d2d_res_->GetDeviceContext()->CreateLinearGradientBrush(
|
||||
D2D1::LinearGradientBrushProperties(DX::ConvertToPoint2F(style.begin), DX::ConvertToPoint2F(style.end)),
|
||||
collection.get(), &output);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
brush.SetBrush(output, Brush::Type::LinearGradient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::CreateBrush(Brush& brush, RadialGradientStyle const& style)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1GradientStopCollection> collection;
|
||||
hr = d2d_res_->GetDeviceContext()->CreateGradientStopCollection(
|
||||
reinterpret_cast<const D2D1_GRADIENT_STOP*>(&style.stops[0]), UINT32(style.stops.size()), D2D1_GAMMA_2_2,
|
||||
D2D1_EXTEND_MODE(style.extend_mode), &collection);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1RadialGradientBrush> output;
|
||||
hr = d2d_res_->GetDeviceContext()->CreateRadialGradientBrush(
|
||||
D2D1::RadialGradientBrushProperties(DX::ConvertToPoint2F(style.center),
|
||||
DX::ConvertToPoint2F(style.offset), style.radius.x, style.radius.y),
|
||||
collection.get(), &output);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
brush.SetBrush(output, Brush::Type::RadialGradient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::CreateStrokeStyle(StrokeStyle& stroke_style, CapStyle cap, LineJoinStyle line_join,
|
||||
const float* dash_array, size_t dash_size, float dash_offset)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
D2D1_STROKE_STYLE_PROPERTIES style =
|
||||
D2D1::StrokeStyleProperties(D2D1_CAP_STYLE(cap), D2D1_CAP_STYLE(cap), D2D1_CAP_STYLE(cap),
|
||||
D2D1_LINE_JOIN(line_join), 10.0f, D2D1_DASH_STYLE_CUSTOM, dash_offset);
|
||||
|
||||
ComPtr<ID2D1StrokeStyle> output;
|
||||
hr = d2d_res_->GetFactory()->CreateStrokeStyle(style, dash_array, dash_size, &output);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
stroke_style.SetStrokeStyle(output);
|
||||
}
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::SetDpi(float dpi)
|
||||
{
|
||||
KGE_ASSERT(d3d_res_ && d2d_res_);
|
||||
|
||||
HRESULT hr = d3d_res_->SetDpi(dpi);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->SetDpi(dpi);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::SetVSyncEnabled(bool enabled)
|
||||
{
|
||||
vsync_ = enabled;
|
||||
}
|
||||
|
||||
void Renderer::SetClearColor(const Color& color)
|
||||
{
|
||||
clear_color_ = color;
|
||||
}
|
||||
|
||||
void Renderer::ResizeTarget(uint32_t width, uint32_t height)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (!d3d_res_)
|
||||
hr = E_UNEXPECTED;
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
output_size_.x = static_cast<float>(width);
|
||||
output_size_.y = static_cast<float>(height);
|
||||
|
||||
hr = d3d_res_->SetLogicalSize(output_size_);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->SetLogicalSize(output_size_);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
render_ctx_.Resize(output_size_);
|
||||
}
|
||||
|
||||
win32::ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -26,23 +26,10 @@
|
|||
#include <kiwano/render/TextStyle.hpp>
|
||||
#include <kiwano/render/RenderContext.h>
|
||||
#include <kiwano/render/TextureRenderContext.h>
|
||||
#include <kiwano/render/DirectX/FontCollectionLoader.h>
|
||||
|
||||
#if defined(KGE_USE_DIRECTX10)
|
||||
#include <kiwano/render/DirectX/D3D10DeviceResources.h>
|
||||
#else
|
||||
#include <kiwano/render/DirectX/D3D11DeviceResources.h>
|
||||
#endif
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
#if defined(KGE_USE_DIRECTX10)
|
||||
typedef ID3D10DeviceResources ID3DDeviceResources;
|
||||
#else
|
||||
typedef ID3D11DeviceResources ID3DDeviceResources;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* \defgroup Render 渲染引擎
|
||||
|
|
@ -57,137 +44,127 @@ typedef ID3D11DeviceResources ID3DDeviceResources;
|
|||
* \~chinese
|
||||
* @brief 渲染器
|
||||
*/
|
||||
class KGE_API Renderer
|
||||
: public Singleton<Renderer>
|
||||
, public EventComponent
|
||||
class KGE_API Renderer : public EventComponent
|
||||
{
|
||||
friend Singleton<Renderer>;
|
||||
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief 获取实例
|
||||
static Renderer& GetInstance();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取清屏颜色
|
||||
Color const& GetClearColor() const;
|
||||
virtual Color GetClearColor() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置清屏颜色
|
||||
void SetClearColor(Color const& clear_color);
|
||||
virtual void SetClearColor(Color const& clear_color);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 开启或关闭垂直同步
|
||||
void SetVSyncEnabled(bool enabled);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置DPI
|
||||
void SetDpi(float dpi);
|
||||
virtual void SetVSyncEnabled(bool enabled);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建纹理
|
||||
/// @param[out] texture 纹理
|
||||
/// @param[in] file_path 图片路径
|
||||
void CreateTexture(Texture& texture, String const& file_path);
|
||||
virtual void CreateTexture(Texture& texture, String const& file_path) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建纹理
|
||||
/// @param[out] texture 纹理
|
||||
/// @param[in] resource 图片资源
|
||||
void CreateTexture(Texture& texture, Resource const& resource);
|
||||
virtual void CreateTexture(Texture& texture, Resource const& resource) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建GIF图像
|
||||
/// @param[out] gif GIF图像
|
||||
/// @param[in] file_path 图片路径
|
||||
void CreateGifImage(GifImage& gif, String const& file_path);
|
||||
virtual void CreateGifImage(GifImage& gif, String const& file_path) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建GIF图像
|
||||
/// @param[out] gif GIF图像
|
||||
/// @param[in] resource 图片资源
|
||||
void CreateGifImage(GifImage& gif, Resource const& resource);
|
||||
virtual void CreateGifImage(GifImage& gif, Resource const& resource) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建GIF图像帧
|
||||
/// @param[out] frame GIF图像帧
|
||||
/// @param[in] gif GIF图像
|
||||
/// @param[in] frame_index 帧下标
|
||||
void CreateGifImageFrame(GifImage::Frame& frame, GifImage const& gif, size_t frame_index);
|
||||
virtual void CreateGifImageFrame(GifImage::Frame& frame, GifImage const& gif, size_t frame_index) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建字体集
|
||||
/// @param[out] font 字体
|
||||
/// @param[in] file_paths 字体文件路径
|
||||
void CreateFontCollection(Font& font, String const& file_path);
|
||||
virtual void CreateFontCollection(Font& font, String const& file_path) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建字体集
|
||||
/// @param[out] font 字体
|
||||
/// @param[in] res_arr 字体资源
|
||||
void CreateFontCollection(Font& font, Resource const& res);
|
||||
virtual void CreateFontCollection(Font& font, Resource const& res) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建文字格式
|
||||
/// @param[out] layout 字体布局
|
||||
void CreateTextFormat(TextLayout& layout);
|
||||
virtual void CreateTextFormat(TextLayout& layout) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建文字布局
|
||||
/// @param[out] layout 字体布局
|
||||
void CreateTextLayout(TextLayout& layout);
|
||||
virtual void CreateTextLayout(TextLayout& layout) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建线段形状
|
||||
/// @param[out] geo 形状
|
||||
/// @param[in] begin_pos 线段起点
|
||||
/// @param[in] end_pos 线段终点
|
||||
void CreateLineShape(Shape& shape, Point const& begin_pos, Point const& end_pos);
|
||||
virtual void CreateLineShape(Shape& shape, Point const& begin_pos, Point const& end_pos) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建矩形形状
|
||||
/// @param[out] geo 形状
|
||||
/// @param[in] rect 矩形大小
|
||||
void CreateRectShape(Shape& shape, Rect const& rect);
|
||||
virtual void CreateRectShape(Shape& shape, Rect const& rect) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建圆角矩形形状
|
||||
/// @param[out] geo 形状
|
||||
/// @param[in] rect 矩形大小
|
||||
/// @param[in] radius 圆角半径
|
||||
void CreateRoundedRectShape(Shape& shape, Rect const& rect, Vec2 const& radius);
|
||||
virtual void CreateRoundedRectShape(Shape& shape, Rect const& rect, Vec2 const& radius) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建椭圆形状
|
||||
/// @param[out] geo 形状
|
||||
/// @param[in] center 椭圆圆心
|
||||
/// @param[in] radius 椭圆半径
|
||||
void CreateEllipseShape(Shape& shape, Point const& center, Vec2 const& radius);
|
||||
virtual void CreateEllipseShape(Shape& shape, Point const& center, Vec2 const& radius) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建几何图形生成器
|
||||
/// @param[out] sink 形状生成器
|
||||
void CreateShapeSink(ShapeSink& sink);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建纹理渲染上下文
|
||||
/// @param[out] render_context 渲染上下文
|
||||
/// @param[in] desired_size 期望的输出大小
|
||||
void CreateTextureRenderContext(TextureRenderContext& render_context, const Size* desired_size = nullptr);
|
||||
virtual void CreateShapeSink(ShapeSink& sink) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建纯色画刷
|
||||
/// @param[out] brush 画刷
|
||||
/// @param[in] color 颜色
|
||||
void CreateBrush(Brush& brush, Color const& color);
|
||||
virtual void CreateBrush(Brush& brush, Color const& color) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建线性渐变画刷
|
||||
/// @param[out] brush 画刷
|
||||
/// @param[in] style 线性渐变样式
|
||||
void CreateBrush(Brush& brush, LinearGradientStyle const& style);
|
||||
virtual void CreateBrush(Brush& brush, LinearGradientStyle const& style) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建径向渐变画刷
|
||||
/// @param[out] brush 画刷
|
||||
/// @param[in] style 径向渐变样式
|
||||
void CreateBrush(Brush& brush, RadialGradientStyle const& style);
|
||||
virtual void CreateBrush(Brush& brush, RadialGradientStyle const& style) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建线条样式
|
||||
|
|
@ -197,74 +174,52 @@ public:
|
|||
/// @param[in] dash_array 虚线长度与间隙数组
|
||||
/// @param[in] dash_size 虚线数组大小
|
||||
/// @param[in] dash_offset 虚线偏移量
|
||||
void CreateStrokeStyle(StrokeStyle& stroke_style, CapStyle cap, LineJoinStyle line_join, const float* dash_array,
|
||||
size_t dash_size, float dash_offset);
|
||||
virtual void CreateStrokeStyle(StrokeStyle& stroke_style, CapStyle cap, LineJoinStyle line_join,
|
||||
const float* dash_array, size_t dash_size, float dash_offset) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建纹理渲染上下文
|
||||
/// @param[in] desired_size 期望的输出大小
|
||||
/// @return 纹理渲染上下文
|
||||
virtual TextureRenderContextPtr CreateTextureRenderContext(const Size* desired_size = nullptr) = 0;
|
||||
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief 开始渲染
|
||||
void BeginDraw();
|
||||
virtual void BeginDraw() = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 结束渲染
|
||||
void EndDraw();
|
||||
virtual void EndDraw() = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 清除绘制内容
|
||||
void Clear();
|
||||
virtual void Clear() = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 将绘制内容呈现至窗口
|
||||
void Present();
|
||||
virtual void Present() = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取渲染上下文
|
||||
RenderContext& GetContext();
|
||||
virtual RenderContext& GetContext() = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取目标窗口
|
||||
WindowHandle GetTargetWindow() const;
|
||||
virtual WindowHandle GetTargetWindow() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取渲染输出大小
|
||||
Size const& GetOutputSize() const;
|
||||
virtual Size GetOutputSize() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取Direct2D设备资源
|
||||
ID2DDeviceResources* GetD2DDeviceResources();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取Direct3D设备资源
|
||||
ID3DDeviceResources* GetD3DDeviceResources();
|
||||
|
||||
public:
|
||||
void SetupComponent() override;
|
||||
|
||||
void DestroyComponent() override;
|
||||
|
||||
void HandleEvent(Event* evt) override;
|
||||
|
||||
private:
|
||||
protected:
|
||||
Renderer();
|
||||
|
||||
~Renderer();
|
||||
|
||||
HRESULT HandleDeviceLost();
|
||||
|
||||
void ResizeTarget(uint32_t width, uint32_t height);
|
||||
|
||||
private:
|
||||
protected:
|
||||
bool vsync_;
|
||||
WindowHandle target_window_;
|
||||
Color clear_color_;
|
||||
Size output_size_;
|
||||
RenderContext render_ctx_;
|
||||
|
||||
ComPtr<ID2DDeviceResources> d2d_res_;
|
||||
ComPtr<ID3DDeviceResources> d3d_res_;
|
||||
ComPtr<IFontCollectionLoader> font_collection_loader_;
|
||||
ComPtr<IResourceFontFileLoader> res_font_file_loader_;
|
||||
ComPtr<IResourceFontCollectionLoader> res_font_collection_loader_;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
|
@ -274,30 +229,24 @@ inline WindowHandle Renderer::GetTargetWindow() const
|
|||
return target_window_;
|
||||
}
|
||||
|
||||
inline Size const& Renderer::GetOutputSize() const
|
||||
inline Size Renderer::GetOutputSize() const
|
||||
{
|
||||
return output_size_;
|
||||
}
|
||||
|
||||
inline Color const& Renderer::GetClearColor() const
|
||||
inline Color Renderer::GetClearColor() const
|
||||
{
|
||||
return clear_color_;
|
||||
}
|
||||
|
||||
inline RenderContext& Renderer::GetContext()
|
||||
inline void Renderer::SetVSyncEnabled(bool enabled)
|
||||
{
|
||||
return render_ctx_;
|
||||
vsync_ = enabled;
|
||||
}
|
||||
|
||||
inline ID2DDeviceResources* Renderer::GetD2DDeviceResources()
|
||||
inline void Renderer::SetClearColor(const Color& color)
|
||||
{
|
||||
KGE_ASSERT(d2d_res_);
|
||||
return d2d_res_.get();
|
||||
clear_color_ = color;
|
||||
}
|
||||
|
||||
inline ID3DDeviceResources* Renderer::GetD3DDeviceResources()
|
||||
{
|
||||
KGE_ASSERT(d3d_res_);
|
||||
return d3d_res_.get();
|
||||
}
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@
|
|||
|
||||
namespace kiwano
|
||||
{
|
||||
class RenderContext;
|
||||
class Renderer;
|
||||
class ShapeSink;
|
||||
|
||||
KGE_DECLARE_SMART_PTR(Shape);
|
||||
|
|
@ -41,8 +39,6 @@ KGE_DECLARE_SMART_PTR(Shape);
|
|||
*/
|
||||
class KGE_API Shape : public virtual ObjectBase
|
||||
{
|
||||
friend class RenderContext;
|
||||
friend class Renderer;
|
||||
friend class ShapeSink;
|
||||
|
||||
public:
|
||||
|
|
@ -116,7 +112,7 @@ public:
|
|||
void Clear();
|
||||
|
||||
#if defined(KGE_WIN32)
|
||||
private:
|
||||
public:
|
||||
ComPtr<ID2D1Geometry> GetGeometry() const;
|
||||
|
||||
void SetGeometry(ComPtr<ID2D1Geometry> shape);
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@
|
|||
|
||||
namespace kiwano
|
||||
{
|
||||
class RenderContext;
|
||||
class Renderer;
|
||||
|
||||
/**
|
||||
* \addtogroup Render
|
||||
|
|
@ -45,8 +43,6 @@ enum class CombineMode
|
|||
/// @brief ÐÎ×´Éú³ÉÆ÷
|
||||
class KGE_API ShapeSink : protected Noncopyable
|
||||
{
|
||||
friend class Renderer;
|
||||
|
||||
public:
|
||||
ShapeSink();
|
||||
|
||||
|
|
@ -137,7 +133,7 @@ private:
|
|||
ShapePtr shape_;
|
||||
|
||||
#if defined(KGE_WIN32)
|
||||
private:
|
||||
public:
|
||||
ComPtr<ID2D1PathGeometry> GetPathGeometry() const;
|
||||
|
||||
void SetPathGeometry(ComPtr<ID2D1PathGeometry> path);
|
||||
|
|
@ -146,6 +142,7 @@ private:
|
|||
|
||||
void SetGeometrySink(ComPtr<ID2D1GeometrySink> sink);
|
||||
|
||||
private:
|
||||
ComPtr<ID2D1GeometrySink> sink_;
|
||||
ComPtr<ID2D1PathGeometry> path_geo_;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@
|
|||
|
||||
namespace kiwano
|
||||
{
|
||||
class RenderContext;
|
||||
class Renderer;
|
||||
|
||||
KGE_DECLARE_SMART_PTR(StrokeStyle);
|
||||
|
||||
|
|
@ -71,9 +69,6 @@ enum class DashStyle
|
|||
/// @brief ĎßĚőŃůĘ˝
|
||||
class StrokeStyle : public virtual ObjectBase
|
||||
{
|
||||
friend class RenderContext;
|
||||
friend class Renderer;
|
||||
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief ´´˝¨ĎßĚőŃůĘ˝
|
||||
|
|
@ -115,7 +110,7 @@ public:
|
|||
bool IsValid() const;
|
||||
|
||||
#if defined(KGE_WIN32)
|
||||
private:
|
||||
public:
|
||||
ComPtr<ID2D1StrokeStyle> GetStrokeStyle() const;
|
||||
|
||||
void SetStrokeStyle(ComPtr<ID2D1StrokeStyle> style);
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@
|
|||
|
||||
namespace kiwano
|
||||
{
|
||||
class RenderContext;
|
||||
class Renderer;
|
||||
|
||||
/**
|
||||
* \addtogroup Render
|
||||
|
|
@ -36,9 +34,6 @@ class Renderer;
|
|||
/// @brief 文本布局
|
||||
class KGE_API TextLayout
|
||||
{
|
||||
friend class RenderContext;
|
||||
friend class Renderer;
|
||||
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief 构造空的文本布局
|
||||
|
|
@ -165,8 +160,13 @@ public:
|
|||
|
||||
void SetDirtyFlag(uint8_t flag);
|
||||
|
||||
#if defined(KGE_WIN32)
|
||||
private:
|
||||
uint8_t dirty_flag_;
|
||||
String text_;
|
||||
TextStyle style_;
|
||||
|
||||
#if defined(KGE_WIN32)
|
||||
public:
|
||||
ComPtr<IDWriteTextFormat> GetTextFormat() const;
|
||||
|
||||
void SetTextFormat(ComPtr<IDWriteTextFormat> format);
|
||||
|
|
@ -175,15 +175,10 @@ private:
|
|||
|
||||
void SetTextLayout(ComPtr<IDWriteTextLayout> layout);
|
||||
|
||||
private:
|
||||
ComPtr<IDWriteTextFormat> text_format_;
|
||||
ComPtr<IDWriteTextLayout> text_layout_;
|
||||
#endif
|
||||
|
||||
private:
|
||||
uint8_t dirty_flag_;
|
||||
|
||||
String text_;
|
||||
TextStyle style_;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
|
|
|||
|
|
@ -181,15 +181,6 @@ InterpolationMode Texture::GetDefaultInterpolationMode()
|
|||
}
|
||||
|
||||
#if defined(KGE_WIN32)
|
||||
D2D1_PIXEL_FORMAT Texture::GetPixelFormat() const
|
||||
{
|
||||
if (bitmap_)
|
||||
{
|
||||
return bitmap_->GetPixelFormat();
|
||||
}
|
||||
return D2D1_PIXEL_FORMAT();
|
||||
}
|
||||
|
||||
ComPtr<ID2D1Bitmap> Texture::GetBitmap() const
|
||||
{
|
||||
return bitmap_;
|
||||
|
|
|
|||
|
|
@ -24,9 +24,6 @@
|
|||
|
||||
namespace kiwano
|
||||
{
|
||||
class RenderContext;
|
||||
class TextureRenderContext;
|
||||
class Renderer;
|
||||
|
||||
KGE_DECLARE_SMART_PTR(Texture);
|
||||
|
||||
|
|
@ -52,10 +49,6 @@ enum class InterpolationMode
|
|||
*/
|
||||
class KGE_API Texture : public virtual ObjectBase
|
||||
{
|
||||
friend class RenderContext;
|
||||
friend class TextureRenderContext;
|
||||
friend class Renderer;
|
||||
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief 从本地文件创建纹理
|
||||
|
|
@ -133,8 +126,13 @@ public:
|
|||
/// @brief 获取默认的像素插值方式
|
||||
static InterpolationMode GetDefaultInterpolationMode();
|
||||
|
||||
#if defined(KGE_WIN32)
|
||||
private:
|
||||
InterpolationMode interpolation_mode_;
|
||||
|
||||
static InterpolationMode default_interpolation_mode_;
|
||||
|
||||
#if defined(KGE_WIN32)
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief 获取源位图
|
||||
ComPtr<ID2D1Bitmap> GetBitmap() const;
|
||||
|
|
@ -143,17 +141,9 @@ private:
|
|||
/// @brief 设置源位图
|
||||
void SetBitmap(ComPtr<ID2D1Bitmap> bitmap);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief »ñÈ¡ÏñËØ¸ñʽ
|
||||
D2D1_PIXEL_FORMAT GetPixelFormat() const;
|
||||
|
||||
private:
|
||||
ComPtr<ID2D1Bitmap> bitmap_;
|
||||
#endif
|
||||
|
||||
private:
|
||||
InterpolationMode interpolation_mode_;
|
||||
|
||||
static InterpolationMode default_interpolation_mode_;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
|
|
|||
|
|
@ -27,56 +27,30 @@ namespace kiwano
|
|||
|
||||
TextureRenderContextPtr TextureRenderContext::Create()
|
||||
{
|
||||
TextureRenderContextPtr ptr = new TextureRenderContext;
|
||||
if (ptr)
|
||||
{
|
||||
TextureRenderContextPtr ptr;
|
||||
try
|
||||
{
|
||||
Renderer::GetInstance().CreateTextureRenderContext(*ptr);
|
||||
ptr = Renderer::GetInstance().CreateTextureRenderContext(nullptr);
|
||||
}
|
||||
catch (std::exception)
|
||||
catch (std::exception&)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
TextureRenderContextPtr TextureRenderContext::Create(Size const& desired_size)
|
||||
{
|
||||
TextureRenderContextPtr ptr = new TextureRenderContext;
|
||||
if (ptr)
|
||||
{
|
||||
TextureRenderContextPtr ptr;
|
||||
try
|
||||
{
|
||||
Renderer::GetInstance().CreateTextureRenderContext(*ptr, &desired_size);
|
||||
ptr = Renderer::GetInstance().CreateTextureRenderContext(&desired_size);
|
||||
}
|
||||
catch (std::exception)
|
||||
catch (std::exception&)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
TextureRenderContext::TextureRenderContext() {}
|
||||
|
||||
bool TextureRenderContext::GetOutput(Texture& texture)
|
||||
{
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
if (bitmap_rt_)
|
||||
{
|
||||
ComPtr<ID2D1Bitmap> bitmap;
|
||||
|
||||
hr = bitmap_rt_->GetBitmap(&bitmap);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
texture.SetBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@
|
|||
|
||||
namespace kiwano
|
||||
{
|
||||
class Renderer;
|
||||
|
||||
KGE_DECLARE_SMART_PTR(TextureRenderContext);
|
||||
|
||||
/**
|
||||
|
|
@ -35,10 +33,8 @@ KGE_DECLARE_SMART_PTR(TextureRenderContext);
|
|||
/// \~chinese
|
||||
/// @brief 纹理渲染上下文
|
||||
/// @details 纹理渲染上下文将渲染输出到一个纹理对象中
|
||||
class KGE_API TextureRenderContext : public RenderContext
|
||||
class KGE_API TextureRenderContext : public virtual RenderContext
|
||||
{
|
||||
friend class Renderer;
|
||||
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief 创建纹理渲染上下文
|
||||
|
|
@ -49,41 +45,13 @@ public:
|
|||
/// @param size 期望的输出大小
|
||||
static TextureRenderContextPtr Create(Size const& desired_size);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief ÊÇ·ñÓÐЧ
|
||||
bool IsValid() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取渲染输出
|
||||
/// @param[out] texture 纹理输出
|
||||
/// @return 操作是否成功
|
||||
bool GetOutput(Texture& texture);
|
||||
|
||||
private:
|
||||
TextureRenderContext();
|
||||
|
||||
ComPtr<ID2D1BitmapRenderTarget> GetBitmapRenderTarget() const;
|
||||
|
||||
void SetBitmapRenderTarget(ComPtr<ID2D1BitmapRenderTarget> ctx);
|
||||
|
||||
private:
|
||||
ComPtr<ID2D1BitmapRenderTarget> bitmap_rt_;
|
||||
virtual bool GetOutput(Texture& texture) = 0;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
inline bool TextureRenderContext::IsValid() const
|
||||
{
|
||||
return bitmap_rt_ != nullptr;
|
||||
}
|
||||
|
||||
inline ComPtr<ID2D1BitmapRenderTarget> TextureRenderContext::GetBitmapRenderTarget() const
|
||||
{
|
||||
return bitmap_rt_;
|
||||
}
|
||||
|
||||
inline void TextureRenderContext::SetBitmapRenderTarget(ComPtr<ID2D1BitmapRenderTarget> ctx)
|
||||
{
|
||||
bitmap_rt_ = ctx;
|
||||
}
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
Loading…
Reference in New Issue