d3d11 support

This commit is contained in:
Nomango 2019-03-10 13:44:02 +08:00 committed by Nomango
parent 1f8b0bb058
commit 074af87127
60 changed files with 1741 additions and 1451 deletions

View File

@ -216,7 +216,7 @@ int main()
}
catch (std::exception& e)
{
::MessageBoxA(nullptr, e.what(), "An exception has occurred!", MB_ICONERROR | MB_TASKMODAL);
::MessageBoxA(nullptr, e.what(), "An exception has occurred!", MB_ICONERROR | MB_OK);
}
return 0;
}

View File

@ -13,12 +13,10 @@
<ClInclude Include="..\..\src\core\closure.hpp" />
<ClInclude Include="..\..\src\core\Color.h" />
<ClInclude Include="..\..\src\core\config.h" />
<ClInclude Include="..\..\src\core\d2dhelper.hpp" />
<ClInclude Include="..\..\src\core\DebugNode.h" />
<ClInclude Include="..\..\src\core\Event.hpp" />
<ClInclude Include="..\..\src\core\EventDispatcher.h" />
<ClInclude Include="..\..\src\core\EventListener.h" />
<ClInclude Include="..\..\src\core\Factory.h" />
<ClInclude Include="..\..\src\core\Font.hpp" />
<ClInclude Include="..\..\src\core\Frames.h" />
<ClInclude Include="..\..\src\core\Application.h" />
@ -47,16 +45,20 @@
<ClInclude Include="..\..\src\core\Task.h" />
<ClInclude Include="..\..\src\core\TaskManager.h" />
<ClInclude Include="..\..\src\core\Text.h" />
<ClInclude Include="..\..\src\core\TextRenderer.h" />
<ClInclude Include="..\..\src\core\TextStyle.hpp" />
<ClInclude Include="..\..\src\core\time.h" />
<ClInclude Include="..\..\src\core\Transform.hpp" />
<ClInclude Include="..\..\src\core\Transition.h" />
<ClInclude Include="..\..\src\core\window.h" />
<ClInclude Include="..\..\src\dx\D2DDeviceResources.h" />
<ClInclude Include="..\..\src\dx\D3D11DeviceResources.h" />
<ClInclude Include="..\..\src\dx\DeviceResources.h" />
<ClInclude Include="..\..\src\dx\helper.hpp" />
<ClInclude Include="..\..\src\dx\TextRenderer.h" />
<ClInclude Include="..\..\src\easy2d.h" />
<ClInclude Include="..\..\src\math\constants.hpp" />
<ClInclude Include="..\..\src\math\ease.hpp" />
<ClInclude Include="..\..\src\math\Matrix.h" />
<ClInclude Include="..\..\src\math\Matrix.hpp" />
<ClInclude Include="..\..\src\math\rand.h" />
<ClInclude Include="..\..\src\math\Rect.hpp" />
<ClInclude Include="..\..\src\math\scalar.hpp" />
@ -83,7 +85,6 @@
<ClCompile Include="..\..\src\core\DebugNode.cpp" />
<ClCompile Include="..\..\src\core\EventDispatcher.cpp" />
<ClCompile Include="..\..\src\core\EventListener.cpp" />
<ClCompile Include="..\..\src\core\Factory.cpp" />
<ClCompile Include="..\..\src\core\Frames.cpp" />
<ClCompile Include="..\..\src\core\Application.cpp" />
<ClCompile Include="..\..\src\core\Geometry.cpp" />
@ -102,11 +103,12 @@
<ClCompile Include="..\..\src\core\Task.cpp" />
<ClCompile Include="..\..\src\core\TaskManager.cpp" />
<ClCompile Include="..\..\src\core\Text.cpp" />
<ClCompile Include="..\..\src\core\TextRenderer.cpp" />
<ClCompile Include="..\..\src\core\time.cpp" />
<ClCompile Include="..\..\src\core\Transition.cpp" />
<ClCompile Include="..\..\src\core\window.cpp" />
<ClCompile Include="..\..\src\math\Matrix.cpp" />
<ClCompile Include="..\..\src\dx\D2DDeviceResources.cpp" />
<ClCompile Include="..\..\src\dx\D3D11DeviceResources.cpp" />
<ClCompile Include="..\..\src\dx\TextRenderer.cpp" />
<ClCompile Include="..\..\src\math\rand.cpp" />
<ClCompile Include="..\..\src\ui\Button.cpp" />
<ClCompile Include="..\..\src\ui\Menu.cpp" />

View File

@ -13,6 +13,9 @@
<Filter Include="ui">
<UniqueIdentifier>{07b6d541-4a1b-472a-aae0-daf9d082fe84}</UniqueIdentifier>
</Filter>
<Filter Include="dx">
<UniqueIdentifier>{a9793a75-3212-4e31-a443-b23f18a1e136}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\easy2d.h" />
@ -64,9 +67,6 @@
<ClInclude Include="..\..\src\core\Text.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\TextRenderer.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\time.h">
<Filter>core</Filter>
</ClInclude>
@ -154,9 +154,6 @@
<ClInclude Include="..\..\src\math\constants.hpp">
<Filter>math</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\Factory.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\EventDispatcher.h">
<Filter>core</Filter>
</ClInclude>
@ -169,9 +166,6 @@
<ClInclude Include="..\..\src\core\helper.hpp">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\d2dhelper.hpp">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\keys.hpp">
<Filter>core</Filter>
</ClInclude>
@ -208,9 +202,6 @@
<ClInclude Include="..\..\src\core\ActionHelper.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\math\Matrix.h">
<Filter>math</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\Array.h">
<Filter>core</Filter>
</ClInclude>
@ -220,6 +211,24 @@
<ClInclude Include="..\..\src\core\Action.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\math\Matrix.hpp">
<Filter>math</Filter>
</ClInclude>
<ClInclude Include="..\..\src\dx\D2DDeviceResources.h">
<Filter>dx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\dx\D3D11DeviceResources.h">
<Filter>dx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\dx\DeviceResources.h">
<Filter>dx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\dx\helper.hpp">
<Filter>dx</Filter>
</ClInclude>
<ClInclude Include="..\..\src\dx\TextRenderer.h">
<Filter>dx</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\core\Animation.cpp">
@ -264,9 +273,6 @@
<ClCompile Include="..\..\src\core\Text.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\TextRenderer.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\time.cpp">
<Filter>core</Filter>
</ClCompile>
@ -327,9 +333,6 @@
<ClCompile Include="..\..\src\core\Frames.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\Factory.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\EventDispatcher.cpp">
<Filter>core</Filter>
</ClCompile>
@ -351,11 +354,17 @@
<ClCompile Include="..\..\src\core\ActionGroup.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\math\Matrix.cpp">
<Filter>math</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\Action.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\dx\D2DDeviceResources.cpp">
<Filter>dx</Filter>
</ClCompile>
<ClCompile Include="..\..\src\dx\D3D11DeviceResources.cpp">
<Filter>dx</Filter>
</ClCompile>
<ClCompile Include="..\..\src\dx\TextRenderer.cpp">
<Filter>dx</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -13,9 +13,11 @@ public:
{
// 创建文字节点
easy2d::TextPtr text = new easy2d::Text(L"Hello Easy2D!");
// 修改节点位置
// 设置节点大小为文字布局大小
text->SetSize(text->GetLayoutSize());
// 修改节点位置, 使节点在屏幕上居中
text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2);
// 修改节点锚点, 使节点在屏幕上居中
// 修改节点锚点, 使文字中心对齐屏幕中心
text->SetAnchor(0.5, 0.5);
// 添加到场景中
this->AddChild(text);
@ -46,7 +48,7 @@ int main()
}
catch (std::exception& e)
{
::MessageBoxA(nullptr, e.what(), "An exception has occurred!", MB_ICONERROR | MB_TASKMODAL);
::MessageBoxA(nullptr, e.what(), "An exception has occurred!", MB_ICONERROR | MB_OK);
}
return 0;
}

View File

@ -16,6 +16,8 @@ public:
{
// 创建文本
TextPtr text = new Text(L"Hello Easy2D!");
// 设置节点大小为文字布局大小
text->SetSize(text->GetLayoutSize());
// 让文本显示在屏幕中央
text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2);
text->SetAnchor(0.5, 0.5);

View File

@ -80,6 +80,8 @@ public:
// 创建说明文字
TextPtr text = new Text(L"按上下左右键移动\n按鼠标左键旋转\n点击鼠标右键隐藏");
// 设置节点大小为文字布局大小
text->SetSize(text->GetLayoutSize());
// 设置文字位置
text->SetAnchor(0.5f, 0.5f);
text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT - 50);

View File

@ -33,18 +33,15 @@ public:
// 创建说明文字
TextPtr intro_text = new Text(L"按上下键调整音量\n按空格键暂停或继续");
intro_text->SetAnchor(0.5f, 0.5f);
intro_text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2 - 50);
intro_text->SetPosition(WINDOW_WIDTH / 2 - 80, WINDOW_HEIGHT / 2 - 50);
// 创建音量文字
volume_text = new Text(L"当前音量:");
volume_text->SetAnchor(0.5f, 0.5f);
volume_text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2 + 30);
volume_text->SetPosition(WINDOW_WIDTH / 2 - 80, WINDOW_HEIGHT / 2 + 30);
// 创建状态文字
state_text = new Text(L"当前状态:");
state_text->SetAnchor(0.5f, 0.5f);
state_text->SetPosition(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2 + 60);
state_text->SetPosition(WINDOW_WIDTH / 2 - 80, WINDOW_HEIGHT / 2 + 60);
// 添加到场景
this->AddChild(intro_text);

View File

@ -76,7 +76,7 @@ int main()
}
catch (std::exception& e)
{
::MessageBoxA(nullptr, e.what(), "An exception has occurred!", MB_ICONERROR | MB_TASKMODAL);
::MessageBoxA(nullptr, e.what(), "An exception has occurred!", MB_ICONERROR | MB_OK);
}
return 0;
}

View File

@ -21,7 +21,7 @@
#include "Application.h"
#include "logs.h"
#include "modules.h"
#include "Factory.h"
#include "render.h"
#include "Event.hpp"
#include "Scene.h"
#include "DebugNode.h"
@ -37,7 +37,6 @@ namespace easy2d
Application::Application(String const& app_name)
: end_(true)
, inited_(false)
, debug_(false)
, curr_scene_(nullptr)
, next_scene_(nullptr)
, transition_(nullptr)
@ -56,44 +55,6 @@ namespace easy2d
void Application::Init(const Options& options)
{
debug_ = options.debug;
// show console if debug mode enabled
if (debug_ && !::GetConsoleWindow())
{
if (!::AllocConsole())
{
E2D_WARNING_LOG(L"AllocConsole failed");
}
else
{
HWND console = ::GetConsoleWindow();
FILE * dummy;
freopen_s(&dummy, "CONOUT$", "w+t", stdout);
freopen_s(&dummy, "CONIN$", "r+t", stdin);
freopen_s(&dummy, "CONOUT$", "w+t", stderr);
(void)dummy;
std::cout.clear();
std::wcout.clear();
std::cin.clear();
std::wcin.clear();
std::cerr.clear();
std::wcerr.clear();
// disable the close button of console
if (console)
{
HMENU hmenu = ::GetSystemMenu(console, FALSE);
::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND);
}
}
}
ThrowIfFailed(
Factory::Instance().Init(debug_)
);
ThrowIfFailed(
Window::Instance().Init(
options.title,
@ -101,30 +62,26 @@ namespace easy2d
options.height,
options.icon,
options.fullscreen,
Application::WndProc,
debug_
Application::WndProc
)
);
HWND hwnd = Window::Instance().GetHandle();
ThrowIfFailed(
RenderSystem::Instance().Init(
hwnd,
options.vsync,
debug_
)
Renderer::Instance().Init(hwnd)
);
Renderer::Instance().SetClearColor(options.clear_color);
ThrowIfFailed(
Input::Instance().Init(
hwnd,
debug_
hwnd
)
);
ThrowIfFailed(
Audio::Instance().Init(debug_)
Audio::Instance().Init()
);
OnStart();
@ -173,9 +130,8 @@ namespace easy2d
curr_scene_.Reset();
Audio::Instance().Destroy();
RenderSystem::Instance().Destroy();
Renderer::Instance().Destroy();
Window::Instance().Destroy();
Factory::Instance().Destroy();
}
}
@ -251,16 +207,14 @@ namespace easy2d
if (next_scene_)
next_scene_->Update(dt);
if (debug_)
if (DebugNode::IsShown())
DebugNode::Instance().Update(dt);
}
void Application::Render(HWND hwnd)
{
auto& rt = RenderSystem::Instance();
ThrowIfFailed(
rt.BeginDraw(hwnd)
Renderer::Instance().BeginDraw()
);
if (transition_)
@ -272,16 +226,50 @@ namespace easy2d
curr_scene_->Render();
}
if (debug_)
if (DebugNode::IsShown())
DebugNode::Instance().Render();
ThrowIfFailed(
rt.EndDraw()
Renderer::Instance().EndDraw()
);
::InvalidateRect(hwnd, NULL, FALSE);
}
void Application::AllocConsole()
{
if (!::GetConsoleWindow())
{
if (!::AllocConsole())
{
E2D_WARNING_LOG(L"AllocConsole failed");
}
else
{
HWND console = ::GetConsoleWindow();
FILE * dummy;
freopen_s(&dummy, "CONOUT$", "w+t", stdout);
freopen_s(&dummy, "CONIN$", "r+t", stdin);
freopen_s(&dummy, "CONOUT$", "w+t", stderr);
(void)dummy;
std::cout.clear();
std::wcout.clear();
std::cin.clear();
std::wcin.clear();
std::cerr.clear();
std::wcerr.clear();
// disable the close button of console
if (console)
{
HMENU hmenu = ::GetSystemMenu(console, FALSE);
::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND);
}
}
}
}
LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
Application * app = reinterpret_cast<Application*>(
@ -363,10 +351,7 @@ namespace easy2d
UINT width = LOWORD(lparam);
UINT height = HIWORD(lparam);
// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
// 目标的大小。它可能会调用失败,但是这里可以忽略有可能的
// 错误,因为这个错误将在下一次调用 EndDraw 时产生
RenderSystem::Instance().Resize(width, height);
Renderer::Instance().GetDeviceResources()->SetLogicalSize(Size{ (float)width, (float)height });
if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam)
{

View File

@ -22,7 +22,6 @@
#include "include-forwards.h"
#include "time.h"
#include "window.h"
#include "render.h"
#include "input.h"
#include "audio.h"
@ -34,18 +33,18 @@ namespace easy2d
int width; // 宽度
int height; // 高度
LPCWSTR icon; // 图标
Color clear_color; // 清屏颜色
bool vsync; // 垂直同步
bool fullscreen; // 全屏模式
bool debug; // µ÷ÊÔģʽ
Options()
: title(L"Easy2D Game")
, width(640)
, height(480)
, icon(nullptr)
, clear_color(Color::Black)
, vsync(true)
, fullscreen(false)
, debug(false)
{}
};
@ -105,6 +104,9 @@ namespace easy2d
float scale_factor
);
// 分配控制台
static void AllocConsole();
private:
void Render(HWND);
@ -115,7 +117,6 @@ namespace easy2d
private:
bool end_;
bool inited_;
bool debug_;
float time_scale_;
String app_name_;
ScenePtr curr_scene_;

View File

@ -23,7 +23,7 @@
#include "logs.h"
#include "Image.h"
#include "Geometry.h"
#include "Factory.h"
#include "render.h"
namespace easy2d
{
@ -31,37 +31,30 @@ namespace easy2d
: cache_expired_(false)
, stroke_width_(1.0f)
{
auto ctx = Renderer::Instance().GetDeviceResources()->GetD2DDeviceContext();
ThrowIfFailed(
RenderSystem::Instance().CreateBitmapRenderTarget(render_target_)
ctx->CreateCompatibleRenderTarget(&render_target_)
);
auto properties = D2D1::BrushProperties();
ThrowIfFailed(
render_target_->CreateSolidColorBrush(
D2D1::ColorF(0, 0, 0, 0),
properties,
D2D1::BrushProperties(),
&fill_brush_)
);
ThrowIfFailed(
render_target_->CreateSolidColorBrush(
D2D1::ColorF(Color::White),
properties,
D2D1::BrushProperties(),
&stroke_brush_)
);
ThrowIfFailed(
render_target_->CreateSolidColorBrush(
D2D1::ColorF(Color::White),
properties,
&text_brush_)
);
ThrowIfFailed(
Factory::Instance().CreateTextRenderer(
text_renderer_,
render_target_,
text_brush_
ITextRenderer::Create(
&text_renderer_,
render_target_.Get()
)
);
@ -105,18 +98,18 @@ namespace easy2d
if (bitmap_cached_)
{
RenderSystem::Instance().DrawBitmap(bitmap_cached_);
Renderer::Instance().DrawBitmap(bitmap_cached_);
}
}
void Canvas::SetStrokeColor(Color const& color)
{
stroke_brush_->SetColor(ToD2dColorF(color));
stroke_brush_->SetColor(DX::ConvertToColorF(color));
}
void Canvas::SetFillColor(Color const& color)
{
fill_brush_->SetColor(ToD2dColorF(color));
fill_brush_->SetColor(DX::ConvertToColorF(color));
}
void Canvas::SetStrokeWidth(float width)
@ -126,7 +119,7 @@ namespace easy2d
void Canvas::SetOutlineJoinStyle(StrokeStyle outline_join)
{
outline_join_style_ = Factory::Instance().GetStrokeStyle(outline_join);
outline_join_style_ = Renderer::Instance().GetDeviceResources()->GetStrokeStyle(outline_join);
}
void Canvas::SetTextStyle(Font const& font, TextStyle const & text_style)
@ -135,12 +128,15 @@ namespace easy2d
text_style_ = text_style;
text_renderer_->SetTextStyle(
ToD2dColorF(text_style_.color),
DX::ConvertToColorF(text_style_.color),
text_style_.outline,
ToD2dColorF(text_style_.outline_color),
DX::ConvertToColorF(text_style_.outline_color),
text_style_.outline_width,
Factory::Instance().GetStrokeStyle(text_style_.outline_stroke).Get()
Renderer::Instance().GetDeviceResources()->GetStrokeStyle(text_style_.outline_stroke)
);
// clear text format
text_format_ = nullptr;
}
Color Canvas::GetStrokeColor() const
@ -162,7 +158,7 @@ namespace easy2d
void Canvas::SetBrushTransform(Matrix const & transform)
{
render_target_->SetTransform(transform);
render_target_->SetTransform(DX::ConvertToMatrix3x2F(transform));
}
void Canvas::DrawLine(const Point & begin, const Point & end)
@ -258,7 +254,7 @@ namespace easy2d
D2D1::RectF(0, 0, image->GetWidth(), image->GetHeight()),
opacity,
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
ToD2dRectF(image->GetCropRect())
DX::ConvertToRectF(image->GetCropRect())
);
cache_expired_ = true;
}
@ -269,23 +265,25 @@ namespace easy2d
if (text.empty())
return;
D2DTextFormatPtr text_format;
if (!text_format_)
{
ThrowIfFailed(
Factory::Instance().CreateTextFormat(
text_format,
Renderer::Instance().GetDeviceResources()->CreateTextFormat(
text_format_,
text_font_,
text_style_
)
);
}
D2DTextLayoutPtr text_layout;
ComPtr<IDWriteTextLayout> text_layout;
Size layout_size;
ThrowIfFailed(
Factory::Instance().CreateTextLayout(
Renderer::Instance().GetDeviceResources()->CreateTextLayout(
text_layout,
layout_size,
text,
text_format,
text_format_,
text_style_
)
);
@ -390,14 +388,14 @@ namespace easy2d
current_geometry_ = nullptr;
ThrowIfFailed(
Factory::Instance().CreatePathGeometry(current_geometry_)
Renderer::Instance().GetDeviceResources()->GetD2DFactory()->CreatePathGeometry(&current_geometry_)
);
ThrowIfFailed(
current_geometry_->Open(&current_sink_)
);
current_sink_->BeginFigure(ToD2dPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
current_sink_->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
}
void Canvas::EndPath(bool closed)
@ -415,7 +413,7 @@ namespace easy2d
void Canvas::AddLine(Point const & point)
{
if (current_sink_)
current_sink_->AddLine(ToD2dPoint2F(point));
current_sink_->AddLine(DX::ConvertToPoint2F(point));
}
void Canvas::AddLines(Array<Point> const& points)
@ -435,9 +433,9 @@ namespace easy2d
{
current_sink_->AddBezier(
D2D1::BezierSegment(
ToD2dPoint2F(point1),
ToD2dPoint2F(point2),
ToD2dPoint2F(point3)
DX::ConvertToPoint2F(point1),
DX::ConvertToPoint2F(point2),
DX::ConvertToPoint2F(point3)
)
);
}
@ -449,8 +447,8 @@ namespace easy2d
{
current_sink_->AddArc(
D2D1::ArcSegment(
ToD2dPoint2F(point),
ToD2dSizeF(radius),
DX::ConvertToPoint2F(point),
DX::ConvertToSizeF(radius),
rotation,
clockwise ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,
is_small ? D2D1_ARC_SIZE_SMALL : D2D1_ARC_SIZE_LARGE
@ -492,7 +490,7 @@ namespace easy2d
return image;
}
D2DBitmapPtr const& easy2d::Canvas::GetBitmap() const
ComPtr<ID2D1Bitmap> const& easy2d::Canvas::GetBitmap() const
{
if (cache_expired_)
{

View File

@ -22,7 +22,7 @@
#include "Node.h"
#include "Font.hpp"
#include "TextStyle.hpp"
#include "TextRenderer.h"
#include "../DX/TextRenderer.h"
#undef DrawText
@ -30,7 +30,7 @@ namespace easy2d
{
// »­²¼
class E2D_API Canvas
: public Node
: public VisualNode
{
public:
Canvas();
@ -221,22 +221,23 @@ namespace easy2d
void OnRender() override;
protected:
D2DBitmapPtr const& GetBitmap() const;
ComPtr<ID2D1Bitmap> const& GetBitmap() const;
protected:
float stroke_width_;
Font text_font_;
TextStyle text_style_;
D2DPathGeometryPtr current_geometry_;
D2DGeometrySinkPtr current_sink_;
D2DStrokeStylePtr outline_join_style_;
D2DSolidColorBrushPtr fill_brush_;
D2DSolidColorBrushPtr stroke_brush_;
D2DSolidColorBrushPtr text_brush_;
D2DTextRendererPtr text_renderer_;
D2DBitmapRenderTargetPtr render_target_;
ComPtr<ID2D1PathGeometry> current_geometry_;
ComPtr<ID2D1GeometrySink> current_sink_;
ComPtr<ID2D1StrokeStyle> outline_join_style_;
ComPtr<ID2D1SolidColorBrush> fill_brush_;
ComPtr<ID2D1SolidColorBrush> stroke_brush_;
ComPtr<IDWriteTextFormat> text_format_;
ComPtr<ITextRenderer> text_renderer_;
ComPtr<ID2D1BitmapRenderTarget> render_target_;
mutable bool cache_expired_;
mutable D2DBitmapPtr bitmap_cached_;
mutable ComPtr<ID2D1Bitmap> bitmap_cached_;
};
}

View File

@ -28,6 +28,11 @@
namespace easy2d
{
namespace
{
bool show = false;
}
DebugNode::DebugNode()
{
debug_text_ = new Text();
@ -67,16 +72,14 @@ namespace easy2d
void DebugNode::OnRender()
{
auto& rt = RenderSystem::Instance();
Renderer::Instance().GetSolidColorBrush()->SetColor(D2D1::ColorF(0.0f, 0.0f, 0.0f, 0.5f));
rt.GetSolidBrush()->SetColor(D2D1::ColorF(0.0f, 0.0f, 0.0f, 0.5f));
rt.GetRenderTarget()->FillRoundedRectangle(
Renderer::Instance().GetDeviceResources()->GetD2DDeviceContext()->FillRoundedRectangle(
D2D1::RoundedRect(
D2D1_RECT_F{ 10, 10, 200, 120 },
6.f,
6.f),
rt.GetSolidBrush().Get()
Renderer::Instance().GetSolidColorBrush()
);
}
@ -105,9 +108,9 @@ namespace easy2d
ss << "Objects: " << Object::__GetTracingObjects().size() << std::endl;
#endif
ss << "Render: " << RenderSystem::Instance().GetStatus().duration.Milliseconds() << "ms" << std::endl;
ss << "Render: " << Renderer::Instance().GetStatus().duration.Milliseconds() << "ms" << std::endl;
ss << "Primitives / sec: " << RenderSystem::Instance().GetStatus().primitives * frame_time_.size() << std::endl;
ss << "Primitives / sec: " << Renderer::Instance().GetStatus().primitives * frame_time_.size() << std::endl;
PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));
@ -119,4 +122,19 @@ namespace easy2d
debug_text_->SetText(ss.str());
}
void DebugNode::Show()
{
show = true;
}
void DebugNode::Hide()
{
show = false;
}
bool DebugNode::IsShown()
{
return show;
}
}

View File

@ -26,7 +26,7 @@
namespace easy2d
{
class E2D_API DebugNode
: public Node
: public VisualNode
, public Singleton<DebugNode>
{
E2D_DECLARE_SINGLETON(DebugNode);
@ -36,6 +36,12 @@ namespace easy2d
virtual ~DebugNode();
// 显示调试信息
void Show();
// 隐藏调试信息
void Hide();
void AddDebugText(String const& text);
void ClearDebugText();
@ -44,6 +50,8 @@ namespace easy2d
void OnUpdate(Duration dt) override;
static bool IsShown();
protected:
TextPtr debug_text_;
Array<TimePoint> frame_time_;

View File

@ -1,125 +0,0 @@
// Copyright (c) 2016-2018 Easy2D - 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 "include-forwards.h"
#include "Singleton.hpp"
#include "Font.hpp"
#include "Resource.h"
#include "TextRenderer.h"
#include "TextStyle.hpp"
namespace easy2d
{
class E2D_API Factory
: public Singleton<Factory>
{
E2D_DECLARE_SINGLETON(Factory);
public:
HRESULT Init(bool debug);
void Destroy();
HRESULT CreateHwndRenderTarget(
_Out_ D2DHwndRenderTargetPtr& hwnd_render_target,
D2D1_RENDER_TARGET_PROPERTIES const& properties,
D2D1_HWND_RENDER_TARGET_PROPERTIES const& hwnd_rt_properties
) const;
HRESULT CreateTextRenderer(
_Out_ D2DTextRendererPtr& text_renderer,
D2DRenderTargetPtr const& render_target,
D2DSolidColorBrushPtr const& brush
);
HRESULT CreateBitmapFromFile(
_Out_ D2DBitmapPtr& bitmap,
D2DRenderTargetPtr const& rt,
String const& file_path
);
HRESULT CreateBitmapFromResource(
_Out_ D2DBitmapPtr& bitmap,
D2DRenderTargetPtr const& rt,
Resource const& res
);
HRESULT CreateRectangleGeometry(
_Out_ D2DRectangleGeometryPtr& geo,
Rect const& rect
) const;
HRESULT CreateRoundedRectangleGeometry(
_Out_ D2DRoundedRectangleGeometryPtr& geo,
Rect const& rect,
float radius_x,
float radius_y
) const;
HRESULT CreateEllipseGeometry(
_Out_ D2DEllipseGeometryPtr& geo,
Point const& center,
float radius_x,
float radius_y
) const;
HRESULT CreateTransformedGeometry(
_Out_ D2DTransformedGeometryPtr& transformed,
Matrix const& matrix,
D2DGeometryPtr const& geo
) const;
HRESULT CreatePathGeometry(
_Out_ D2DPathGeometryPtr& geometry
) const;
HRESULT CreateTextFormat(
_Out_ D2DTextFormatPtr& text_format,
Font const& font,
TextStyle const& text_style
) const;
HRESULT CreateTextLayout(
_Out_ D2DTextLayoutPtr& text_layout,
_Out_ Size& layout_size,
String const& text,
D2DTextFormatPtr const& text_format,
TextStyle const& text_style
) const;
D2DStrokeStylePtr const& GetStrokeStyle(
StrokeStyle stroke
) const;
protected:
Factory();
~Factory();
protected:
D2DFactoryPtr factory_;
D2DImagingFactoryPtr imaging_factory_;
D2DWriteFactoryPtr write_factory_;
D2DStrokeStylePtr miter_stroke_style_;
D2DStrokeStylePtr bevel_stroke_style_;
D2DStrokeStylePtr round_stroke_style_;
};
}

View File

@ -19,7 +19,6 @@
// THE SOFTWARE.
#include "Geometry.h"
#include "Factory.h"
#include "render.h"
#include "logs.h"
@ -99,7 +98,7 @@ namespace easy2d
BOOL ret = 0;
// no matter it failed or not
geo_->FillContainsPoint(
ToD2dPoint2F(point),
DX::ConvertToPoint2F(point),
D2D1::Matrix3x2F::Identity(),
&ret
);
@ -126,10 +125,10 @@ namespace easy2d
void LineGeometry::SetLine(Point const & begin, Point const & end)
{
D2DPathGeometryPtr path_geo;
D2DGeometrySinkPtr path_sink;
ComPtr<ID2D1PathGeometry> path_geo;
ComPtr<ID2D1GeometrySink> path_sink;
HRESULT hr = Factory::Instance().CreatePathGeometry(path_geo);
HRESULT hr = Renderer::Instance().GetDeviceResources()->GetD2DFactory()->CreatePathGeometry(&path_geo);
if (SUCCEEDED(hr))
{
@ -138,8 +137,8 @@ namespace easy2d
if (SUCCEEDED(hr))
{
path_sink->BeginFigure(ToD2dPoint2F(begin), D2D1_FIGURE_BEGIN_FILLED);
path_sink->AddLine(ToD2dPoint2F(end));
path_sink->BeginFigure(DX::ConvertToPoint2F(begin), D2D1_FIGURE_BEGIN_FILLED);
path_sink->AddLine(DX::ConvertToPoint2F(end));
path_sink->EndFigure(D2D1_FIGURE_END_OPEN);
hr = path_sink->Close();
}
@ -185,8 +184,10 @@ namespace easy2d
void RectangleGeometry::SetRect(Rect const & rect)
{
D2DRectangleGeometryPtr geo;
if (SUCCEEDED(Factory::Instance().CreateRectangleGeometry(geo, rect)))
ComPtr<ID2D1RectangleGeometry> geo;
auto factory = Renderer::Instance().GetDeviceResources()->GetD2DFactory();
if (SUCCEEDED(factory->CreateRectangleGeometry(DX::ConvertToRectF(rect), &geo)))
{
geo_ = geo;
rect_ = rect;
@ -224,8 +225,15 @@ namespace easy2d
void CircleGeometry::SetCircle(Point const & center, float radius)
{
D2DEllipseGeometryPtr geo;
if (SUCCEEDED(Factory::Instance().CreateEllipseGeometry(geo, center, radius, radius)))
ComPtr<ID2D1EllipseGeometry> geo;
auto factory = Renderer::Instance().GetDeviceResources()->GetD2DFactory();
if (SUCCEEDED(factory->CreateEllipseGeometry(
D2D1::Ellipse(
DX::ConvertToPoint2F(center),
radius,
radius),
&geo)))
{
geo_ = geo;
center_ = center;
@ -265,8 +273,15 @@ namespace easy2d
void EllipseGeometry::SetEllipse(Point const & center, float radius_x, float radius_y)
{
D2DEllipseGeometryPtr geo;
if (SUCCEEDED(Factory::Instance().CreateEllipseGeometry(geo, center, radius_x, radius_y)))
ComPtr<ID2D1EllipseGeometry> geo;
auto factory = Renderer::Instance().GetDeviceResources()->GetD2DFactory();
if (SUCCEEDED(factory->CreateEllipseGeometry(
D2D1::Ellipse(
DX::ConvertToPoint2F(center),
radius_x,
radius_y),
&geo)))
{
geo_ = geo;
radius_x_ = radius_x;
@ -291,15 +306,17 @@ namespace easy2d
{
current_geometry_ = nullptr;
auto factory = Renderer::Instance().GetDeviceResources()->GetD2DFactory();
ThrowIfFailed(
Factory::Instance().CreatePathGeometry(current_geometry_)
factory->CreatePathGeometry(&current_geometry_)
);
ThrowIfFailed(
current_geometry_->Open(&current_sink_)
);
current_sink_->BeginFigure(ToD2dPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
current_sink_->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
}
void PathGeometry::EndPath(bool closed)
@ -321,7 +338,7 @@ namespace easy2d
void PathGeometry::AddLine(Point const & point)
{
if (current_sink_)
current_sink_->AddLine(ToD2dPoint2F(point));
current_sink_->AddLine(DX::ConvertToPoint2F(point));
}
void PathGeometry::AddLines(Array<Point> const& points)
@ -341,9 +358,9 @@ namespace easy2d
{
current_sink_->AddBezier(
D2D1::BezierSegment(
ToD2dPoint2F(point1),
ToD2dPoint2F(point2),
ToD2dPoint2F(point3)
DX::ConvertToPoint2F(point1),
DX::ConvertToPoint2F(point2),
DX::ConvertToPoint2F(point3)
)
);
}
@ -355,8 +372,8 @@ namespace easy2d
{
current_sink_->AddArc(
D2D1::ArcSegment(
ToD2dPoint2F(point),
ToD2dSizeF(radius),
DX::ConvertToPoint2F(point),
DX::ConvertToSizeF(radius),
rotation,
clockwise ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,
is_small ? D2D1_ARC_SIZE_SMALL : D2D1_ARC_SIZE_LARGE
@ -404,8 +421,16 @@ namespace easy2d
void RoundedRectGeometry::SetRoundedRect(Rect const & rect, float radius_x, float radius_y)
{
D2DRoundedRectangleGeometryPtr geo;
if (SUCCEEDED(Factory::Instance().CreateRoundedRectangleGeometry(geo, rect, radius_x, radius_y)))
ComPtr<ID2D1RoundedRectangleGeometry> geo;
auto factory = Renderer::Instance().GetDeviceResources()->GetD2DFactory();
if (SUCCEEDED(factory->CreateRoundedRectangleGeometry(
D2D1::RoundedRect(
DX::ConvertToRectF(rect),
radius_x,
radius_y
),
&geo)))
{
geo_ = geo;
rect_ = rect;

View File

@ -57,7 +57,7 @@ namespace easy2d
float ComputeArea();
protected:
D2DGeometryPtr geo_;
ComPtr<ID2D1Geometry> geo_;
};
@ -254,8 +254,8 @@ namespace easy2d
void ClearPath();
protected:
D2DPathGeometryPtr current_geometry_;
D2DGeometrySinkPtr current_sink_;
ComPtr<ID2D1PathGeometry> current_geometry_;
ComPtr<ID2D1GeometrySink> current_sink_;
};

View File

@ -70,14 +70,12 @@ namespace easy2d
{
if (geometry_ && geometry_->geo_)
{
auto& rt = RenderSystem::Instance();
rt.FillGeometry(
geometry_->geo_,
Renderer::Instance().FillGeometry(
geometry_->geo_.Get(),
fill_color_
);
rt.DrawGeometry(
Renderer::Instance().DrawGeometry(
geometry_->geo_,
stroke_color_,
stroke_width_,

View File

@ -26,7 +26,7 @@ namespace easy2d
{
// 섯부暠近
class E2D_API GeometryNode
: public Node
: public VisualNode
{
public:
GeometryNode();

View File

@ -19,8 +19,8 @@
// THE SOFTWARE.
#include "Image.h"
#include "render.h"
#include "logs.h"
#include "render.h"
#include "../utils/File.h"
#include "../utils/string.h"
@ -45,7 +45,7 @@ namespace easy2d
this->Crop(crop_rect);
}
Image::Image(D2DBitmapPtr const & bitmap)
Image::Image(ComPtr<ID2D1Bitmap> const & bitmap)
: Image()
{
SetBitmap(bitmap);
@ -58,7 +58,7 @@ namespace easy2d
bool Image::Load(Resource const& res)
{
HRESULT hr = S_OK;
D2DBitmapPtr bitmap;
ComPtr<ID2D1Bitmap> bitmap;
if (res.IsFileType())
{
@ -67,11 +67,11 @@ namespace easy2d
E2D_WARNING_LOG(L"Image file '%s' not found!", res.GetFileName().c_str());
return false;
}
hr = RenderSystem::Instance().CreateBitmapFromFile(bitmap, res.GetFileName());
hr = Renderer::Instance().GetDeviceResources()->CreateBitmapFromFile(bitmap, res.GetFileName());
}
else
{
hr = RenderSystem::Instance().CreateBitmapFromResource(bitmap, res);
hr = Renderer::Instance().GetDeviceResources()->CreateBitmapFromResource(bitmap, res);
}
if (FAILED(hr))
@ -164,12 +164,12 @@ namespace easy2d
return crop_rect_;
}
D2DBitmapPtr const& Image::GetBitmap() const
ComPtr<ID2D1Bitmap> const& Image::GetBitmap() const
{
return bitmap_;
}
void Image::SetBitmap(D2DBitmapPtr const & bitmap)
void Image::SetBitmap(ComPtr<ID2D1Bitmap> const & bitmap)
{
if (bitmap)
{

View File

@ -41,7 +41,7 @@ namespace easy2d
);
explicit Image(
D2DBitmapPtr const& bitmap
ComPtr<ID2D1Bitmap> const& bitmap
);
virtual ~Image();
@ -89,15 +89,15 @@ namespace easy2d
// »ñÈ¡²Ã¼ô¾ØÐÎ
Rect const& GetCropRect() const;
D2DBitmapPtr const& GetBitmap() const;
ComPtr<ID2D1Bitmap> const& GetBitmap() const;
protected:
void SetBitmap(
D2DBitmapPtr const& bitmap
ComPtr<ID2D1Bitmap> const& bitmap
);
protected:
Rect crop_rect_;
D2DBitmapPtr bitmap_;
ComPtr<ID2D1Bitmap> bitmap_;
};
}

View File

@ -37,10 +37,8 @@ namespace easy2d
{
}
HRESULT Input::Init(HWND hwnd, bool debug)
HRESULT Input::Init(HWND hwnd)
{
E2D_NOT_USED(debug);
hwnd_ = hwnd;
return S_OK;

View File

@ -55,7 +55,7 @@ namespace easy2d
// 資誼報炎恫炎
Point GetMousePos();
HRESULT Init(HWND hwnd, bool debug);
HRESULT Init(HWND hwnd);
void Update();

View File

@ -20,7 +20,6 @@
#include "Node.h"
#include "Action.h"
#include "Factory.h"
#include "Scene.h"
#include "Task.h"
#include "render.h"
@ -42,7 +41,7 @@ namespace easy2d
Node::Node()
: visible_(true)
, pause_(false)
, update_pausing_(false)
, hover_(false)
, pressed_(false)
, responsible_(false)
@ -59,7 +58,7 @@ namespace easy2d
void Node::Update(Duration dt)
{
if (pause_)
if (update_pausing_)
return;
UpdateActions(this, dt);
@ -88,13 +87,9 @@ namespace easy2d
UpdateTransform();
auto& rt = RenderSystem::Instance();
if (children_.IsEmpty())
{
rt.SetTransform(transform_matrix_);
rt.SetOpacity(display_opacity_);
PrepareRender();
OnRender();
}
else
@ -110,9 +105,7 @@ namespace easy2d
child = child->NextItem().Get();
}
rt.SetTransform(transform_matrix_);
rt.SetOpacity(display_opacity_);
PrepareRender();
OnRender();
while (child)
@ -184,16 +177,6 @@ namespace easy2d
EventDispatcher::Dispatch(evt);
}
void Node::PauseUpdating()
{
pause_ = true;
}
void Node::ResumeUpdating()
{
pause_ = false;
}
Matrix const & Node::GetTransformMatrix() const
{
UpdateTransform();
@ -607,4 +590,12 @@ namespace easy2d
Point local = GetTransformInverseMatrix().Transform(point);
return GetBounds().ContainsPoint(local);
}
void VisualNode::PrepareRender()
{
Renderer::Instance().SetTransform(transform_matrix_);
Renderer::Instance().SetOpacity(display_opacity_);
}
}

View File

@ -344,13 +344,13 @@ namespace easy2d
void RemoveFromParent();
// 暂停节点更新
void PauseUpdating();
inline void PauseUpdating() { update_pausing_ = true; }
// 继续节点更新
void ResumeUpdating();
inline void ResumeUpdating() { update_pausing_ = false; }
// 节点更新是否暂停
inline bool IsUpdatePausing() const { return pause_; }
inline bool IsUpdatePausing() const { return update_pausing_; }
// 设置更新时的回调函数
inline void SetCallbackOnUpdate(UpdateCallback const& cb) { cb_update_ = cb; }
@ -365,6 +365,8 @@ namespace easy2d
);
protected:
virtual void PrepareRender() {}
void Update(Duration dt);
void Render();
@ -380,7 +382,7 @@ namespace easy2d
bool hover_;
bool pressed_;
bool responsible_;
bool pause_;
bool update_pausing_;
int z_order_;
float opacity_;
float display_opacity_;
@ -398,4 +400,13 @@ namespace easy2d
mutable Matrix transform_matrix_;
mutable Matrix transform_matrix_inverse_;
};
class E2D_API VisualNode
: public Node
{
public:
virtual void PrepareRender() override;
};
}

View File

@ -25,7 +25,7 @@ namespace easy2d
{
// ³¡¾°
class E2D_API Scene
: public Node
: public VisualNode
{
public:
Scene();

View File

@ -99,7 +99,7 @@ namespace easy2d
{
if (image_)
{
RenderSystem::Instance().DrawImage(image_, GetBounds());
Renderer::Instance().DrawImage(image_, GetBounds());
}
}
}

View File

@ -26,7 +26,7 @@ namespace easy2d
{
// ¾«Áé
class E2D_API Sprite
: public Node
: public VisualNode
{
public:
Sprite();

View File

@ -19,9 +19,7 @@
// THE SOFTWARE.
#include "Text.h"
#include "Factory.h"
#include "render.h"
#include "include-forwards.h"
#include "logs.h"
namespace easy2d
@ -45,6 +43,7 @@ namespace easy2d
Text::Text()
: font_(text_default_font)
, style_(text_default_style)
, layout_dirty_(false)
{
}
@ -67,8 +66,8 @@ namespace easy2d
: font_(font)
, style_(style)
, text_(text)
, layout_dirty_(true)
{
UpdateLayout();
}
Text::~Text()
@ -127,6 +126,7 @@ namespace easy2d
int Text::GetLineCount()
{
UpdateLayout();
if (text_layout_)
{
DWRITE_TEXT_METRICS metrics;
@ -138,6 +138,12 @@ namespace easy2d
return 0;
}
Size const& Text::GetLayoutSize() const
{
UpdateLayout();
return layout_size_;
}
bool Text::IsItalic() const
{
return font_.italic;
@ -161,19 +167,19 @@ namespace easy2d
void Text::SetText(String const& text)
{
text_ = text;
UpdateLayout();
layout_dirty_ = true;
}
void Text::SetStyle(const TextStyle& style)
{
style_ = style;
UpdateLayout();
layout_dirty_ = true;
}
void Text::SetFont(const Font & font)
{
font_ = font;
UpdateLayout();
layout_dirty_ = true;
}
void Text::SetFontFamily(String const& family)
@ -181,7 +187,7 @@ namespace easy2d
if (font_.family != family)
{
font_.family = family;
UpdateLayout();
layout_dirty_ = true;
}
}
@ -190,7 +196,7 @@ namespace easy2d
if (font_.size != size)
{
font_.size = size;
UpdateLayout();
layout_dirty_ = true;
}
}
@ -199,7 +205,7 @@ namespace easy2d
if (font_.weight != weight)
{
font_.weight = weight;
UpdateLayout();
layout_dirty_ = true;
}
}
@ -213,7 +219,7 @@ namespace easy2d
if (font_.italic != val)
{
font_.italic = val;
UpdateLayout();
layout_dirty_ = true;
}
}
@ -222,7 +228,7 @@ namespace easy2d
if (style_.wrap != wrap)
{
style_.wrap = wrap;
UpdateLayout();
layout_dirty_ = true;
}
}
@ -231,7 +237,7 @@ namespace easy2d
if (style_.wrap_width != wrap_width)
{
style_.wrap_width = std::max(wrap_width, 0.f);
UpdateLayout();
layout_dirty_ = true;
}
}
@ -240,7 +246,7 @@ namespace easy2d
if (style_.line_spacing != line_spacing)
{
style_.line_spacing = line_spacing;
UpdateLayout();
layout_dirty_ = true;
}
}
@ -249,7 +255,7 @@ namespace easy2d
if (style_.alignment != align)
{
style_.alignment = align;
UpdateLayout();
layout_dirty_ = true;
}
}
@ -258,7 +264,7 @@ namespace easy2d
if (style_.underline != underline)
{
style_.underline = underline;
UpdateLayout();
layout_dirty_ = true;
}
}
@ -267,7 +273,7 @@ namespace easy2d
if (style_.strikethrough != strikethrough)
{
style_.strikethrough = strikethrough;
UpdateLayout();
layout_dirty_ = true;
}
}
@ -293,22 +299,27 @@ namespace easy2d
void Text::OnRender()
{
UpdateLayout();
if (text_layout_)
{
auto& rt = RenderSystem::Instance();
rt.SetTextStyle(
Renderer::Instance().SetTextStyle(
style_.color,
style_.outline,
style_.outline_color,
style_.outline_width,
style_.outline_stroke
);
rt.DrawTextLayout(text_layout_);
Renderer::Instance().DrawTextLayout(text_layout_);
}
}
void Text::UpdateLayout()
void Text::UpdateLayout() const
{
if (!layout_dirty_)
return;
layout_dirty_ = false;
text_format_ = nullptr;
text_layout_ = nullptr;
@ -316,24 +327,21 @@ namespace easy2d
return;
ThrowIfFailed(
Factory::Instance().CreateTextFormat(
Renderer::Instance().GetDeviceResources()->CreateTextFormat(
text_format_,
font_,
style_
)
);
Size layout_size;
ThrowIfFailed(
Factory::Instance().CreateTextLayout(
Renderer::Instance().GetDeviceResources()->CreateTextLayout(
text_layout_,
layout_size,
layout_size_,
text_,
text_format_,
style_
)
);
this->SetSize(layout_size);
}
}

View File

@ -27,7 +27,7 @@ namespace easy2d
{
// 文本
class E2D_API Text
: public Node
: public VisualNode
{
public:
Text();
@ -87,6 +87,9 @@ namespace easy2d
// 获取文本显示行数
int GetLineCount();
// 获取文字布局大小
Size const& GetLayoutSize() const;
// 是否是斜体
bool IsItalic() const;
@ -202,13 +205,16 @@ namespace easy2d
void OnRender() override;
protected:
void UpdateLayout();
void UpdateLayout() const;
protected:
String text_;
Font font_;
TextStyle style_;
D2DTextFormatPtr text_format_;
D2DTextLayoutPtr text_layout_;
mutable bool layout_dirty_;
mutable Size layout_size_;
mutable ComPtr<IDWriteTextFormat> text_format_;
mutable ComPtr<IDWriteTextLayout> text_layout_;
};
}

View File

@ -19,11 +19,11 @@
// THE SOFTWARE.
#pragma once
#include "helper.hpp"
#include "../math/Matrix.hpp"
namespace easy2d
{
class E2D_API Transform
class Transform
{
public:
float rotation; // Ðýת

View File

@ -66,14 +66,14 @@ namespace easy2d
if (in_scene_)
{
ThrowIfFailed(
RenderSystem::Instance().CreateLayer(in_layer_)
Renderer::Instance().CreateLayer(in_layer_)
);
}
if (out_scene_)
{
ThrowIfFailed(
RenderSystem::Instance().CreateLayer(out_layer_)
Renderer::Instance().CreateLayer(out_layer_)
);
}
@ -101,34 +101,34 @@ namespace easy2d
void Transition::Render()
{
auto& rt = RenderSystem::Instance();
auto& renderer = Renderer::Instance();
if (out_scene_)
{
rt.PushClip(
renderer.PushClip(
out_scene_->GetTransformMatrix(),
window_size_
);
rt.PushLayer(out_layer_, out_layer_prop_);
renderer.PushLayer(out_layer_, out_layer_prop_);
out_scene_->Render();
rt.PopLayer();
rt.PopClip();
renderer.PopLayer();
renderer.PopClip();
}
if (in_scene_)
{
rt.PushClip(
renderer.PushClip(
in_scene_->GetTransformMatrix(),
window_size_
);
rt.PushLayer(in_layer_, in_layer_prop_);
renderer.PushLayer(in_layer_, in_layer_prop_);
in_scene_->Render();
rt.PopLayer();
rt.PopClip();
renderer.PopLayer();
renderer.PopClip();
}
}

View File

@ -63,8 +63,8 @@ namespace easy2d
Size window_size_;
ScenePtr out_scene_;
ScenePtr in_scene_;
D2DLayerPtr out_layer_;
D2DLayerPtr in_layer_;
ComPtr<ID2D1Layer> out_layer_;
ComPtr<ID2D1Layer> in_layer_;
LayerProperties out_layer_prop_;
LayerProperties in_layer_prop_;
};

View File

@ -169,10 +169,8 @@ namespace easy2d
{
}
HRESULT Audio::Init(bool debug)
HRESULT Audio::Init()
{
E2D_NOT_USED(debug);
E2D_LOG(L"Initing audio resources");
HRESULT hr = modules::MediaFoundation::Get().MFStartup(MF_VERSION, MFSTARTUP_FULL);
@ -202,7 +200,7 @@ namespace easy2d
mastering_voice_ = nullptr;
}
SafeRelease(x_audio2_);
DX::SafeRelease(x_audio2_);
modules::MediaFoundation::Get().MFShutdown();
}

View File

@ -82,7 +82,7 @@ namespace easy2d
using VoiceMap = UnorderedSet<Voice*>;
public:
HRESULT Init(bool debug);
HRESULT Init();
void Destroy();

View File

@ -1,101 +0,0 @@
// Copyright (c) 2016-2018 Easy2D - 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 "IntrusivePtr.hpp"
#include "../math/vector.hpp"
#include "../math/Rect.hpp"
#include "Color.h"
#include <d2d1.h>
#include <dwrite.h>
#ifndef E2D_DECLARE_D2D_SMART_PTR
#define E2D_DECLARE_D2D_SMART_PTR(class_name, sp_name)\
using sp_name = ::easy2d::IntrusivePtr< class_name >
#endif
namespace easy2d
{
// "D2DPtr" is a shorthand for "COM Pointer"
E2D_DECLARE_D2D_SMART_PTR(ID2D1Factory, D2DFactoryPtr);
E2D_DECLARE_D2D_SMART_PTR(IWICImagingFactory, D2DImagingFactoryPtr);
E2D_DECLARE_D2D_SMART_PTR(IDWriteFactory, D2DWriteFactoryPtr);
E2D_DECLARE_D2D_SMART_PTR(ID2D1SolidColorBrush, D2DSolidColorBrushPtr);
E2D_DECLARE_D2D_SMART_PTR(ID2D1RenderTarget, D2DRenderTargetPtr);
E2D_DECLARE_D2D_SMART_PTR(ID2D1HwndRenderTarget, D2DHwndRenderTargetPtr);
E2D_DECLARE_D2D_SMART_PTR(ID2D1BitmapRenderTarget, D2DBitmapRenderTargetPtr);
E2D_DECLARE_D2D_SMART_PTR(ID2D1StrokeStyle, D2DStrokeStylePtr);
E2D_DECLARE_D2D_SMART_PTR(ID2D1Geometry, D2DGeometryPtr);
E2D_DECLARE_D2D_SMART_PTR(ID2D1RectangleGeometry, D2DRectangleGeometryPtr);
E2D_DECLARE_D2D_SMART_PTR(ID2D1RoundedRectangleGeometry, D2DRoundedRectangleGeometryPtr);
E2D_DECLARE_D2D_SMART_PTR(ID2D1EllipseGeometry, D2DEllipseGeometryPtr);
E2D_DECLARE_D2D_SMART_PTR(ID2D1GeometryGroup, D2DGeometryGroupPtr);
E2D_DECLARE_D2D_SMART_PTR(ID2D1PathGeometry, D2DPathGeometryPtr);
E2D_DECLARE_D2D_SMART_PTR(ID2D1TransformedGeometry, D2DTransformedGeometryPtr);
E2D_DECLARE_D2D_SMART_PTR(ID2D1GeometrySink, D2DGeometrySinkPtr);
E2D_DECLARE_D2D_SMART_PTR(ID2D1Layer, D2DLayerPtr);
E2D_DECLARE_D2D_SMART_PTR(ID2D1Bitmap, D2DBitmapPtr);
E2D_DECLARE_D2D_SMART_PTR(IDWriteTextFormat, D2DTextFormatPtr);
E2D_DECLARE_D2D_SMART_PTR(IDWriteTextLayout, D2DTextLayoutPtr);
inline void IntrusivePtrAddRef(IUnknown* ptr)
{
if (ptr) { ptr->AddRef(); }
}
inline void IntrusivePtrRelease(IUnknown* ptr)
{
if (ptr) { ptr->Release(); }
}
template <typename T>
inline void SafeRelease(T*& ptr)
{
if (ptr != nullptr)
{
ptr->Release();
ptr = nullptr;
}
}
inline D2D1_POINT_2F const& ToD2dPoint2F(math::Vec2 const& point)
{
return reinterpret_cast<D2D1_POINT_2F const&>(point);
}
inline D2D1_SIZE_F const& ToD2dSizeF(math::Vec2 const& size)
{
return reinterpret_cast<D2D1_SIZE_F const&>(size);
}
inline D2D1_RECT_F ToD2dRectF(math::Rect const& rect)
{
return D2D1_RECT_F{ rect.origin.x, rect.origin.y, rect.origin.x + rect.size.x, rect.origin.y + rect.size.y };
}
inline D2D1_COLOR_F const& ToD2dColorF(Color const& color)
{
return reinterpret_cast<D2D1_COLOR_F const&>(color);
}
}

View File

@ -25,7 +25,7 @@
#include "closure.hpp"
#include "../math/vector.hpp"
#include "../math/Rect.hpp"
#include "../math/Matrix.h"
#include "../math/Matrix.hpp"
#include <set>
#include <map>
#include <list>
@ -72,8 +72,6 @@ namespace easy2d
namespace easy2d
{
// "Ptr" is a shorthand for "Smart Pointer"
E2D_DECLARE_SMART_PTR(Object);
E2D_DECLARE_SMART_PTR(Image);
E2D_DECLARE_SMART_PTR(Music);

View File

@ -23,7 +23,7 @@
#include "Color.h"
#include "Object.h"
#include "helper.hpp"
#include "d2dhelper.hpp"
#include "../DX/helper.hpp"
namespace easy2d
{

View File

@ -97,7 +97,10 @@ namespace easy2d
if (FAILED(hr))
{
E2D_ERROR_LOG(L"Fatal error with HRESULT of %08X", hr);
throw std::runtime_error("Fatal error");
static char buffer[1024 + 1];
sprintf_s(buffer, "Fatal error with HRESULT of %08X", hr);
throw std::runtime_error(buffer);
}
}
}

View File

@ -65,6 +65,17 @@ namespace easy2d
{
E2D_LOG(L"load dwrite.dll failed");
}
d3d11 = LoadLibraryW(L"d3d11.dll");
if (d3d11)
{
D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)
GetProcAddress(d3d11, "D3D11CreateDevice");
}
else
{
E2D_LOG(L"load d3d11.dll failed");
}
}
XAudio2::XAudio2()

View File

@ -26,6 +26,7 @@
#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#include <d3d11.h>
namespace easy2d
{
@ -57,6 +58,7 @@ namespace easy2d
{
DirectX();
HMODULE d3d11;
HMODULE d2d;
HMODULE dwrite;
@ -73,6 +75,7 @@ namespace easy2d
PFN_D2D1CreateFactory D2D1CreateFactory;
PFN_DWriteCreateFactory DWriteCreateFactory;
PFN_D3D11_CREATE_DEVICE D3D11CreateDevice;
};

View File

@ -20,220 +20,233 @@
#include "render.h"
#include "logs.h"
#include "Factory.h"
#include "render.h"
#include "Image.h"
#include "Transform.hpp"
namespace easy2d
{
RenderSystem::RenderSystem()
: fps_text_format_(nullptr)
, fps_text_layout_(nullptr)
Renderer::Renderer()
: antialias_(true)
, text_antialias_(TextAntialias::ClearType)
, clear_color_(D2D1::ColorF(D2D1::ColorF::Black))
, opacity_(1.f)
, debug_(false)
, window_occluded_(false)
, vsync_enabled_(true)
, antialias_(true)
, text_antialias_(TextAntialias::ClearType)
{
status_.primitives = 0;
}
Renderer::~Renderer()
{
}
RenderSystem::~RenderSystem()
HRESULT Renderer::Init(HWND hwnd)
{
HRESULT hr = S_OK;
E2D_LOG(L"Creating device resources");
{
device_resources_ = nullptr;
hr = DeviceResources::Create(
&device_resources_,
hwnd
);
}
HRESULT RenderSystem::Init(HWND hwnd, bool vsync, bool debug)
if (SUCCEEDED(hr))
{
E2D_LOG(L"Initing graphics resources");
vsync_enabled_ = vsync;
debug_ = debug;
return CreateResources(hwnd);
factory_ = device_resources_->GetD2DFactory();
device_context_ = device_resources_->GetD2DDeviceContext();
}
void RenderSystem::Destroy()
if (SUCCEEDED(hr))
{
E2D_LOG(L"Destroying graphics resources");
drawing_state_block_ = nullptr;
hr = factory_->CreateDrawingStateBlock(
&drawing_state_block_
);
}
ClearImageCache();
if (SUCCEEDED(hr))
{
hr = CreateDeviceResources();
}
return hr;
}
void Renderer::Destroy()
{
E2D_LOG(L"Destroying device resources");
device_resources_.Reset();
factory_.Reset();
device_context_.Reset();
drawing_state_block_.Reset();
text_renderer_.Reset();
solid_brush_.Reset();
render_target_.Reset();
fps_text_format_.Reset();
fps_text_layout_.Reset();
solid_color_brush_.Reset();
}
HRESULT RenderSystem::BeginDraw(HWND hwnd)
HRESULT Renderer::CreateDeviceResources()
{
HRESULT hr = CreateResources(hwnd);
HRESULT hr = S_OK;
if (debug_)
hr = device_context_->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
&solid_color_brush_
);
if (SUCCEEDED(hr))
{
hr = ITextRenderer::Create(
&text_renderer_,
device_context_.Get()
);
}
if (SUCCEEDED(hr))
{
SetAntialiasMode(antialias_);
SetTextAntialiasMode(text_antialias_);
}
return hr;
}
HRESULT Renderer::HandleDeviceLost()
{
HRESULT hr = device_resources_->HandleDeviceLost();
if (SUCCEEDED(hr))
{
hr = CreateDeviceResources();
}
return hr;
}
HRESULT Renderer::BeginDraw()
{
if (!device_context_)
return E_UNEXPECTED;
// if (debug_)
{
status_.start = time::Now();
status_.primitives = 0;
}
device_context_->SaveDrawingState(drawing_state_block_.Get());
device_context_->BeginDraw();
device_context_->Clear(clear_color_);
return S_OK;
}
HRESULT Renderer::EndDraw()
{
if (!device_context_)
return E_UNEXPECTED;
HRESULT hr = device_context_->EndDraw();
device_context_->RestoreDrawingState(drawing_state_block_.Get());
if (SUCCEEDED(hr))
{
window_occluded_ = !!(render_target_->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED);
if (!window_occluded_)
{
render_target_->BeginDraw();
render_target_->Clear(clear_color_);
}
}
return hr;
// The first argument instructs DXGI to block until VSync.
hr = device_resources_->GetDXGISwapChain()->Present(1, 0);
}
HRESULT RenderSystem::EndDraw()
{
HRESULT hr = S_OK;
if (!window_occluded_)
{
hr = render_target_->EndDraw();
if (hr == D2DERR_RECREATE_TARGET)
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
{
// 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
// 并在下一次调用时重建资源
DiscardResources();
hr = S_OK;
}
hr = HandleDeviceLost();
}
if (debug_)
// if (debug_)
{
status_.duration = time::Now() - status_.start;
}
return hr;
}
void RenderSystem::ClearImageCache()
HRESULT Renderer::CreateLayer(ComPtr<ID2D1Layer>& layer)
{
bitmap_cache_.clear();
}
D2DHwndRenderTargetPtr const & RenderSystem::GetRenderTarget() const
{
return render_target_;
}
D2DSolidColorBrushPtr const & RenderSystem::GetSolidBrush() const
{
return solid_brush_;
}
HRESULT RenderSystem::CreateLayer(D2DLayerPtr& layer)
{
if (!render_target_)
if (!device_context_)
return E_UNEXPECTED;
layer = nullptr;
return render_target_->CreateLayer(&layer);
return device_context_->CreateLayer(&layer);
}
HRESULT RenderSystem::CreateSolidColorBrush(D2DSolidColorBrushPtr & brush) const
{
if (!render_target_)
return E_UNEXPECTED;
brush = nullptr;
return render_target_->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
&brush
);
}
HRESULT RenderSystem::DrawGeometry(
D2DGeometryPtr const& geometry,
HRESULT Renderer::DrawGeometry(
ComPtr<ID2D1Geometry> const& geometry,
Color const& stroke_color,
float stroke_width,
StrokeStyle stroke
)
{
if (!solid_brush_ ||
!render_target_)
if (!solid_color_brush_ || !device_context_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color));
solid_brush_->SetColor(ToD2dColorF(stroke_color));
auto stroke_style = Factory::Instance().GetStrokeStyle(stroke);
render_target_->DrawGeometry(
device_context_->DrawGeometry(
geometry.Get(),
solid_brush_.Get(),
solid_color_brush_.Get(),
stroke_width,
stroke_style.Get()
device_resources_->GetStrokeStyle(stroke)
);
if (debug_)
// if (debug_)
++status_.primitives;
return S_OK;
}
HRESULT RenderSystem::FillGeometry(D2DGeometryPtr const & geometry, const Color & fill_color)
HRESULT Renderer::FillGeometry(ComPtr<ID2D1Geometry> const & geometry, Color const& fill_color)
{
if (!solid_brush_ ||
!render_target_)
if (!solid_color_brush_ || !device_context_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
solid_brush_->SetColor(ToD2dColorF(fill_color));
render_target_->FillGeometry(
solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color));
device_context_->FillGeometry(
geometry.Get(),
solid_brush_.Get()
solid_color_brush_.Get()
);
if (debug_)
++status_.primitives;
return S_OK;
}
HRESULT RenderSystem::DrawImage(ImagePtr const & image, Rect const& dest_rect)
HRESULT Renderer::DrawImage(ImagePtr const & image, Rect const& dest_rect)
{
if (!render_target_)
if (!device_context_)
return E_UNEXPECTED;
if (!image->GetBitmap())
return S_OK;
if (window_occluded_)
return S_OK;
render_target_->DrawBitmap(
device_context_->DrawBitmap(
image->GetBitmap().Get(),
ToD2dRectF(dest_rect),
DX::ConvertToRectF(dest_rect),
opacity_,
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
ToD2dRectF(image->GetCropRect())
DX::ConvertToRectF(image->GetCropRect())
);
if (debug_)
// if (debug_)
++status_.primitives;
return S_OK;
}
HRESULT RenderSystem::DrawBitmap(
D2DBitmapPtr const& bitmap
)
HRESULT Renderer::DrawBitmap(ComPtr<ID2D1Bitmap> const & bitmap)
{
if (!render_target_)
if (!device_context_)
return E_UNEXPECTED;
if (window_occluded_)
if (!bitmap)
return S_OK;
// Do not crop bitmap
auto rect = D2D1::RectF(0.f, 0.f, bitmap->GetSize().width, bitmap->GetSize().height);
render_target_->DrawBitmap(
D2D_RECT_F rect = D2D1::RectF(0.f, 0.f, bitmap->GetSize().width, bitmap->GetSize().height);
device_context_->DrawBitmap(
bitmap.Get(),
rect,
opacity_,
@ -241,69 +254,56 @@ namespace easy2d
rect
);
if (debug_)
// if (debug_)
++status_.primitives;
return S_OK;
}
HRESULT RenderSystem::DrawTextLayout(D2DTextLayoutPtr const& text_layout)
HRESULT Renderer::DrawTextLayout(ComPtr<IDWriteTextLayout> const& text_layout)
{
if (!text_renderer_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
if (debug_)
// if (debug_)
++status_.primitives;
return text_layout->Draw(nullptr, text_renderer_.Get(), 0, 0);
}
HRESULT RenderSystem::PushClip(const Matrix & clip_matrix, const Size & clip_size)
HRESULT Renderer::PushClip(const Matrix & clip_matrix, const Size & clip_size)
{
if (!render_target_)
if (!device_context_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
render_target_->SetTransform(clip_matrix);
render_target_->PushAxisAlignedClip(
device_context_->SetTransform(DX::ConvertToMatrix3x2F(clip_matrix));
device_context_->PushAxisAlignedClip(
D2D1::RectF(0, 0, clip_size.x, clip_size.y),
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
);
return S_OK;
}
HRESULT RenderSystem::PopClip()
HRESULT Renderer::PopClip()
{
if (!render_target_)
if (!device_context_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
render_target_->PopAxisAlignedClip();
device_context_->PopAxisAlignedClip();
return S_OK;
}
HRESULT RenderSystem::PushLayer(D2DLayerPtr const& layer, LayerProperties const& properties)
HRESULT Renderer::PushLayer(ComPtr<ID2D1Layer> const& layer, LayerProperties const& properties)
{
if (!render_target_ ||
!solid_brush_)
if (!device_context_ || !solid_color_brush_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
render_target_->PushLayer(
device_context_->PushLayer(
D2D1::LayerParameters(
ToD2dRectF(properties.area),
DX::ConvertToRectF(properties.area),
nullptr,
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
D2D1::Matrix3x2F::Identity(),
properties.opacity,
solid_brush_.Get(),
solid_color_brush_.Get(),
D2D1_LAYER_OPTIONS_NONE
),
layer.Get()
@ -311,124 +311,39 @@ namespace easy2d
return S_OK;
}
HRESULT RenderSystem::PopLayer()
HRESULT Renderer::PopLayer()
{
if (!render_target_)
if (!device_context_)
return E_UNEXPECTED;
if (window_occluded_)
return S_OK;
render_target_->PopLayer();
device_context_->PopLayer();
return S_OK;
}
HRESULT RenderSystem::GetSize(Size & size)
void Renderer::SetClearColor(const Color & color)
{
if (!render_target_)
clear_color_ = DX::ConvertToColorF(color);
}
HRESULT Renderer::SetTransform(const Matrix & matrix)
{
if (!device_context_)
return E_UNEXPECTED;
auto rtsize = render_target_->GetSize();
size.x = rtsize.width;
size.y = rtsize.height;
device_context_->SetTransform(DX::ConvertToMatrix3x2F(matrix));
return S_OK;
}
HRESULT RenderSystem::CreateBitmapFromFile(D2DBitmapPtr& bitmap, String const& file_path)
void Renderer::SetOpacity(float opacity)
{
if (render_target_ == nullptr)
if (opacity_ != opacity)
{
return E_UNEXPECTED;
}
size_t hash_code = std::hash<String>{}(file_path);
if (bitmap_cache_.find(hash_code) != bitmap_cache_.end())
{
bitmap = bitmap_cache_[hash_code];
return S_OK;
}
D2DBitmapPtr bitmap_tmp;
HRESULT hr = Factory::Instance().CreateBitmapFromFile(
bitmap,
render_target_,
file_path
);
if (SUCCEEDED(hr))
{
bitmap_cache_.insert(std::make_pair(hash_code, bitmap));
}
return hr;
}
HRESULT RenderSystem::CreateBitmapFromResource(D2DBitmapPtr& bitmap, Resource const& res)
{
if (render_target_ == nullptr)
{
return E_UNEXPECTED;
}
size_t hash_code = res.GetHashCode();
if (bitmap_cache_.find(hash_code) != bitmap_cache_.end())
{
bitmap = bitmap_cache_[hash_code];
return S_OK;
}
HRESULT hr = Factory::Instance().CreateBitmapFromResource(
bitmap,
render_target_,
res
);
if (SUCCEEDED(hr))
{
bitmap_cache_.insert(std::make_pair(hash_code, bitmap));
}
return hr;
}
HRESULT RenderSystem::CreateBitmapRenderTarget(D2DBitmapRenderTargetPtr & brt)
{
if (!render_target_)
return E_UNEXPECTED;
brt = nullptr;
return render_target_->CreateCompatibleRenderTarget(&brt);
}
HRESULT RenderSystem::Resize(UINT32 width, UINT32 height)
{
if (!render_target_)
return E_UNEXPECTED;
render_target_->Resize(D2D1::SizeU(width, height));
return S_OK;
}
HRESULT RenderSystem::SetTransform(const Matrix & matrix)
{
if (!render_target_)
return E_UNEXPECTED;
render_target_->SetTransform(matrix);
return S_OK;
}
HRESULT RenderSystem::SetOpacity(float opacity)
{
if (!render_target_)
return E_UNEXPECTED;
opacity_ = opacity;
solid_brush_->SetOpacity(opacity);
return S_OK;
solid_color_brush_->SetOpacity(opacity);
}
}
HRESULT RenderSystem::SetTextStyle(
HRESULT Renderer::SetTextStyle(
Color const& color,
bool has_outline,
Color const& outline_color,
@ -436,40 +351,34 @@ namespace easy2d
StrokeStyle outline_stroke
)
{
if (!text_renderer_)
if (!text_renderer_ || !device_resources_)
return E_UNEXPECTED;
auto stroke_style = Factory::Instance().GetStrokeStyle(outline_stroke);
text_renderer_->SetTextStyle(
ToD2dColorF(color),
DX::ConvertToColorF(color),
has_outline,
ToD2dColorF(outline_color),
DX::ConvertToColorF(outline_color),
outline_width,
stroke_style.Get()
device_resources_->GetStrokeStyle(outline_stroke)
);
return S_OK;
}
void RenderSystem::SetClearColor(const Color& color)
HRESULT Renderer::SetAntialiasMode(bool enabled)
{
clear_color_ = ToD2dColorF(color);
}
HRESULT RenderSystem::SetAntialiasMode(bool enabled)
{
if (!render_target_)
if (!device_context_)
return E_UNEXPECTED;
render_target_->SetAntialiasMode(
device_context_->SetAntialiasMode(
enabled ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED
);
antialias_ = enabled;
return S_OK;
}
HRESULT RenderSystem::SetTextAntialiasMode(TextAntialias mode)
HRESULT Renderer::SetTextAntialiasMode(TextAntialias mode)
{
if (!render_target_)
if (!device_context_)
return E_UNEXPECTED;
text_antialias_ = mode;
@ -491,78 +400,8 @@ namespace easy2d
default:
break;
}
render_target_->SetTextAntialiasMode(antialias_mode);
device_context_->SetTextAntialiasMode(antialias_mode);
return S_OK;
}
RenderSystem::Status const & RenderSystem::GetStatus() const
{
return status_;
}
HRESULT RenderSystem::CreateResources(HWND hwnd)
{
HRESULT hr = S_OK;
if (!render_target_)
{
RECT rc;
::GetClientRect(hwnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(
rc.right - rc.left,
rc.bottom - rc.top
);
hr = Factory::Instance().CreateHwndRenderTarget(
render_target_,
D2D1::RenderTargetProperties(
D2D1_RENDER_TARGET_TYPE_DEFAULT,
D2D1::PixelFormat(),
96.f,
96.f
),
D2D1::HwndRenderTargetProperties(
hwnd,
size,
vsync_enabled_ ? D2D1_PRESENT_OPTIONS_NONE : D2D1_PRESENT_OPTIONS_IMMEDIATELY
)
);
if (SUCCEEDED(hr))
{
SetAntialiasMode(antialias_);
SetTextAntialiasMode(text_antialias_);
}
if (SUCCEEDED(hr))
{
hr = render_target_->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
&solid_brush_
);
}
if (SUCCEEDED(hr))
{
hr = Factory::Instance().CreateTextRenderer(
text_renderer_,
render_target_,
solid_brush_
);
}
}
return hr;
}
void RenderSystem::DiscardResources()
{
// FIXME! 应通知 Application 类销毁所有节点的 device resources
fps_text_format_ = nullptr;
fps_text_layout_ = nullptr;
text_renderer_ = nullptr;
solid_brush_ = nullptr;
render_target_ = nullptr;
}
}

View File

@ -20,45 +20,80 @@
#pragma once
#include "include-forwards.h"
#include "time.h"
#include "Font.hpp"
#include "Resource.h"
#include "TextRenderer.h"
#include "TextStyle.hpp"
#include "Singleton.hpp"
#include "../math/Matrix.h"
#include <unordered_map>
#include "../DX/helper.hpp"
#include "../DX/DeviceResources.h"
#include "../DX/TextRenderer.h"
#include "time.h"
#include <d2d1.h>
#include <d2d1_1.h>
namespace easy2d
{
class E2D_API RenderSystem
: public Singleton<RenderSystem>
{
E2D_DECLARE_SINGLETON(RenderSystem);
struct Status
struct RenderStatus
{
TimePoint start;
Duration duration;
int primitives;
};
using BitmapMap = UnorderedMap<size_t, D2DBitmapPtr>;
class E2D_API Renderer
: public Singleton<Renderer>
{
E2D_DECLARE_SINGLETON(Renderer);
public:
HRESULT Init(HWND hwnd, bool vsync, bool debug);
HRESULT Init(HWND hwnd);
void Destroy();
// 开始渲染
HRESULT BeginDraw(HWND hwnd);
inline RenderStatus const& GetStatus() const { return status_; }
inline DeviceResources* GetDeviceResources() const { return device_resources_.Get(); }
inline ITextRenderer* GetTextRenderer() const { return text_renderer_.Get(); }
inline ID2D1SolidColorBrush* GetSolidColorBrush() const { return solid_color_brush_.Get(); }
HRESULT BeginDraw();
// 结束渲染
HRESULT EndDraw();
// 设置清空屏幕的颜色
HRESULT CreateLayer(
ComPtr<ID2D1Layer>& layer
);
HRESULT DrawGeometry(
ComPtr<ID2D1Geometry> const& geometry,
const Color& stroke_color,
float stroke_width,
StrokeStyle stroke = StrokeStyle::Miter
);
HRESULT FillGeometry(
ComPtr<ID2D1Geometry> const& geometry,
Color const& fill_color
);
HRESULT DrawImage(
ImagePtr const& image,
Rect const& dest_rect
);
HRESULT DrawBitmap(
ComPtr<ID2D1Bitmap> const& bitmap
);
HRESULT DrawTextLayout(
ComPtr<IDWriteTextLayout> const& text_layout
);
// <20>零헌팁奈<ED8C81>
void SetClearColor(
const Color& color
Color const& clear_color
);
// ÉèÖÿ¹¾â³Ýģʽ
@ -71,44 +106,15 @@ namespace easy2d
TextAntialias mode
);
Status const& GetStatus() const;
HRESULT CreateResources(
HWND hwnd
);
void DiscardResources();
HRESULT CreateLayer(
D2DLayerPtr& layer
);
HRESULT CreateSolidColorBrush(
D2DSolidColorBrushPtr& brush
) const;
HRESULT CreateBitmapFromFile(
D2DBitmapPtr& bitmap,
String const& file_path
);
HRESULT CreateBitmapFromResource(
D2DBitmapPtr& bitmap,
Resource const& res
);
HRESULT CreateBitmapRenderTarget(
D2DBitmapRenderTargetPtr& brt
// <20>零뺌궝拷츠똑
void SetOpacity(
float opacity
);
HRESULT SetTransform(
const Matrix& matrix
);
HRESULT SetOpacity(
float opacity
);
HRESULT SetTextStyle(
const Color& color,
bool has_outline,
@ -117,31 +123,6 @@ namespace easy2d
StrokeStyle outline_stroke
);
HRESULT DrawGeometry(
D2DGeometryPtr const& geometry,
const Color& stroke_color,
float stroke_width,
StrokeStyle stroke = StrokeStyle::Miter
);
HRESULT FillGeometry(
D2DGeometryPtr const& geometry,
const Color& fill_color
);
HRESULT DrawImage(
ImagePtr const& image,
Rect const& dest_rect
);
HRESULT DrawBitmap(
D2DBitmapPtr const& bitmap
);
HRESULT DrawTextLayout(
D2DTextLayoutPtr const& text_layout
);
HRESULT PushClip(
const Matrix& clip_matrix,
const Size& clip_size
@ -150,46 +131,35 @@ namespace easy2d
HRESULT PopClip();
HRESULT PushLayer(
D2DLayerPtr const& layer,
ComPtr<ID2D1Layer> const& layer,
LayerProperties const& properties
);
HRESULT PopLayer();
HRESULT GetSize(
Size& size
);
private:
Renderer();
HRESULT Resize(
UINT32 width,
UINT32 height
);
~Renderer();
void ClearImageCache();
HRESULT CreateDeviceResources();
D2DHwndRenderTargetPtr const& GetRenderTarget() const;
HRESULT HandleDeviceLost();
D2DSolidColorBrushPtr const& GetSolidBrush() const;
protected:
RenderSystem();
~RenderSystem();
protected:
bool debug_;
bool window_occluded_;
bool vsync_enabled_;
bool antialias_;
private:
float opacity_;
D2D1_COLOR_F clear_color_;
bool antialias_;
unsigned long ref_count_;
TextAntialias text_antialias_;
Status status_;
D2DTextRendererPtr text_renderer_;
D2DSolidColorBrushPtr solid_brush_;
D2DHwndRenderTargetPtr render_target_;
D2DTextFormatPtr fps_text_format_;
D2DTextLayoutPtr fps_text_layout_;
BitmapMap bitmap_cache_;
D2D1_COLOR_F clear_color_;
RenderStatus status_;
ComPtr<DeviceResources> device_resources_;
ComPtr<ID2D1Factory1> factory_;
ComPtr<ID2D1DeviceContext> device_context_;
ComPtr<ID2D1DrawingStateBlock> drawing_state_block_;
ComPtr<ITextRenderer> text_renderer_;
ComPtr<ID2D1SolidColorBrush> solid_color_brush_;
};
}

View File

@ -53,12 +53,8 @@ namespace easy2d
{
}
HRESULT Window::Init(String title, int width, int height, LPCWSTR icon, bool fullscreen, WNDPROC proc, bool debug)
HRESULT Window::Init(String title, int width, int height, LPCWSTR icon, bool fullscreen, WNDPROC proc)
{
E2D_NOT_USED(debug);
E2D_LOG(L"Creating window");
HINSTANCE hinst = GetModuleHandleW(nullptr);
WNDCLASSEX wcex = { 0 };
wcex.cbSize = sizeof(WNDCLASSEX);
@ -160,8 +156,6 @@ namespace easy2d
void Window::Destroy()
{
E2D_LOG(L"Destroying window");
if (is_fullscreen_)
RestoreResolution(device_name_);

View File

@ -60,8 +60,7 @@ namespace easy2d
int height,
LPCWSTR icon,
bool fullscreen,
WNDPROC proc,
bool debug
WNDPROC proc
);
void Destroy();

View File

@ -18,57 +18,134 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "Factory.h"
#include "logs.h"
#include "modules.h"
#include "Transform.hpp"
#include "DeviceResources.h"
#include "../core/Image.h"
#include "../core/modules.h"
#include "../core/logs.h"
namespace easy2d
{
Factory::Factory()
D2DDeviceResources::D2DDeviceResources()
: ref_count_(0)
, dpi_(96.f)
{
CreateDeviceIndependentResources();
}
Factory::~Factory()
D2DDeviceResources::~D2DDeviceResources()
{
DiscardResources();
}
HRESULT Factory::Init(bool debug)
STDMETHODIMP_(unsigned long) D2DDeviceResources::AddRef()
{
E2D_LOG(L"Creating device-independent resources");
return InterlockedIncrement(&ref_count_);
}
STDMETHODIMP_(unsigned long) D2DDeviceResources::Release()
{
unsigned long newCount = InterlockedDecrement(&ref_count_);
if (newCount == 0)
{
delete this;
return 0;
}
return newCount;
}
STDMETHODIMP D2DDeviceResources::QueryInterface(
IID const& riid,
void** object)
{
if (__uuidof(IUnknown) == riid)
{
*object = this;
}
else
{
*object = nullptr;
return E_FAIL;
}
AddRef();
return S_OK;
}
void D2DDeviceResources::DiscardResources()
{
ClearImageCache();
d2d_factory_.Reset();
d2d_device_.Reset();
d2d_device_context_.Reset();
d2d_target_bitmap_.Reset();
imaging_factory_.Reset();
dwrite_factory_.Reset();
d2d_miter_stroke_style_.Reset();
d2d_bevel_stroke_style_.Reset();
d2d_round_stroke_style_.Reset();
}
HRESULT D2DDeviceResources::CreateDeviceIndependentResources()
{
HRESULT hr = S_OK;
ComPtr<ID2D1Factory1> d2d_factory;
ComPtr<IWICImagingFactory> imaging_factory;
ComPtr<IDWriteFactory> dwrite_factory;
D2D1_FACTORY_OPTIONS options;
options.debugLevel = debug ? D2D1_DEBUG_LEVEL_INFORMATION : D2D1_DEBUG_LEVEL_NONE;
HRESULT hr = modules::DirectX::Get().D2D1CreateFactory(
ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS));
#ifdef E2D_DEBUG
options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
#endif
hr = modules::DirectX::Get().D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
__uuidof(ID2D1Factory),
__uuidof(ID2D1Factory1),
&options,
reinterpret_cast<void**>(&factory_)
reinterpret_cast<void**>(&d2d_factory)
);
if (SUCCEEDED(hr))
{
d2d_factory_ = d2d_factory;
CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
reinterpret_cast<void**>(&imaging_factory_)
reinterpret_cast<void**>(&imaging_factory)
);
}
if (SUCCEEDED(hr))
{
imaging_factory_ = imaging_factory;
modules::DirectX::Get().DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&write_factory_)
reinterpret_cast<IUnknown**>(&dwrite_factory)
);
}
if (SUCCEEDED(hr))
{
auto stroke_style = D2D1::StrokeStyleProperties(
dwrite_factory_ = dwrite_factory;
ComPtr<ID2D1StrokeStyle> d2d_miter_stroke_style;
ComPtr<ID2D1StrokeStyle> d2d_bevel_stroke_style;
ComPtr<ID2D1StrokeStyle> d2d_round_stroke_style;
D2D1_STROKE_STYLE_PROPERTIES stroke_style = D2D1::StrokeStyleProperties(
D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT,
@ -78,101 +155,89 @@ namespace easy2d
0.0f
);
hr = factory_->CreateStrokeStyle(
hr = d2d_factory_->CreateStrokeStyle(
stroke_style,
nullptr,
0,
&miter_stroke_style_
&d2d_miter_stroke_style
);
if (SUCCEEDED(hr))
{
stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL;
hr = factory_->CreateStrokeStyle(
hr = d2d_factory_->CreateStrokeStyle(
stroke_style,
nullptr,
0,
&bevel_stroke_style_
&d2d_bevel_stroke_style
);
}
if (SUCCEEDED(hr))
{
stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND;
hr = factory_->CreateStrokeStyle(
hr = d2d_factory_->CreateStrokeStyle(
stroke_style,
nullptr,
0,
&round_stroke_style_
&d2d_round_stroke_style
);
}
if (SUCCEEDED(hr))
{
d2d_miter_stroke_style_ = d2d_miter_stroke_style;
d2d_bevel_stroke_style_ = d2d_bevel_stroke_style;
d2d_round_stroke_style_ = d2d_round_stroke_style;
}
}
return hr;
}
void Factory::Destroy()
HRESULT D2DDeviceResources::SetD2DDevice(ComPtr<ID2D1Device> const& device)
{
E2D_LOG(L"Destroying device-independent resources");
ComPtr<ID2D1DeviceContext> d2d_device_ctx;
factory_.Reset();
imaging_factory_.Reset();
write_factory_.Reset();
miter_stroke_style_.Reset();
bevel_stroke_style_.Reset();
round_stroke_style_.Reset();
}
HRESULT Factory::CreateHwndRenderTarget(D2DHwndRenderTargetPtr & hwnd_render_target, D2D1_RENDER_TARGET_PROPERTIES const & properties, D2D1_HWND_RENDER_TARGET_PROPERTIES const & hwnd_rt_properties) const
{
if (!factory_)
return E_UNEXPECTED;
D2DHwndRenderTargetPtr hwnd_render_target_tmp;
HRESULT hr = factory_->CreateHwndRenderTarget(
properties,
hwnd_rt_properties,
&hwnd_render_target_tmp
HRESULT hr = device->CreateDeviceContext(
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
&d2d_device_ctx
);
if (SUCCEEDED(hr))
hwnd_render_target = hwnd_render_target_tmp;
{
d2d_device_ = device;
d2d_device_context_ = d2d_device_ctx;
d2d_device_context_->SetDpi(dpi_, dpi_);
}
return hr;
}
HRESULT Factory::CreateTextRenderer(
D2DTextRendererPtr& text_renderer,
D2DRenderTargetPtr const& render_target,
D2DSolidColorBrushPtr const& brush
)
void D2DDeviceResources::SetTargetBitmap(ComPtr<ID2D1Bitmap1> const& target)
{
if (!factory_)
return E_UNEXPECTED;
D2DTextRendererPtr text_renderer_tmp;
HRESULT hr = ITextRenderer::Create(
&text_renderer_tmp,
factory_.Get(),
render_target.Get(),
brush.Get()
);
if (SUCCEEDED(hr))
text_renderer = text_renderer_tmp;
return hr;
d2d_target_bitmap_ = target;
if (d2d_device_context_)
d2d_device_context_->SetTarget(d2d_target_bitmap_.Get());
}
HRESULT Factory::CreateBitmapFromFile(D2DBitmapPtr & bitmap, D2DRenderTargetPtr const & rt, String const & file_path)
{
if (imaging_factory_ == nullptr)
HRESULT D2DDeviceResources::CreateBitmapFromFile(ComPtr<ID2D1Bitmap> & bitmap, String const & file_path)
{
if (!imaging_factory_ || !d2d_device_context_)
return E_UNEXPECTED;
size_t hash_code = std::hash<String>{}(file_path);
if (bitmap_cache_.find(hash_code) != bitmap_cache_.end())
{
bitmap = bitmap_cache_[hash_code];
return S_OK;
}
IntrusivePtr<IWICBitmapDecoder> decoder;
IntrusivePtr<IWICBitmapFrameDecode> source;
IntrusivePtr<IWICStream> stream;
IntrusivePtr<IWICFormatConverter> converter;
IntrusivePtr<ID2D1Bitmap> bitmap_tmp;
ComPtr<IWICBitmapDecoder> decoder;
ComPtr<IWICBitmapFrameDecode> source;
ComPtr<IWICStream> stream;
ComPtr<IWICFormatConverter> converter;
ComPtr<ID2D1Bitmap> bitmap_tmp;
HRESULT hr = imaging_factory_->CreateDecoderFromFilename(
file_path.c_str(),
@ -207,7 +272,7 @@ namespace easy2d
if (SUCCEEDED(hr))
{
hr = rt->CreateBitmapFromWicBitmap(
hr = d2d_device_context_->CreateBitmapFromWicBitmap(
converter.Get(),
nullptr,
&bitmap_tmp
@ -215,23 +280,31 @@ namespace easy2d
}
if (SUCCEEDED(hr))
{
bitmap = bitmap_tmp;
bitmap_cache_.insert(std::make_pair(hash_code, bitmap));
}
return hr;
}
HRESULT Factory::CreateBitmapFromResource(D2DBitmapPtr & bitmap, D2DRenderTargetPtr const & rt, Resource const & res)
{
if (imaging_factory_ == nullptr)
HRESULT D2DDeviceResources::CreateBitmapFromResource(ComPtr<ID2D1Bitmap> & bitmap, Resource const & res)
{
if (!imaging_factory_ || !d2d_device_context_)
return E_UNEXPECTED;
size_t hash_code = res.GetHashCode();
if (bitmap_cache_.find(hash_code) != bitmap_cache_.end())
{
bitmap = bitmap_cache_[hash_code];
return S_OK;
}
IntrusivePtr<IWICBitmapDecoder> decoder;
IntrusivePtr<IWICBitmapFrameDecode> source;
IntrusivePtr<IWICStream> stream;
IntrusivePtr<IWICFormatConverter> converter;
IntrusivePtr<ID2D1Bitmap> bitmap_tmp;
ComPtr<IWICBitmapDecoder> decoder;
ComPtr<IWICBitmapFrameDecode> source;
ComPtr<IWICStream> stream;
ComPtr<IWICFormatConverter> converter;
ComPtr<ID2D1Bitmap> bitmap_tmp;
// ¼ÓÔØ×ÊÔ´
LPVOID buffer;
@ -286,7 +359,7 @@ namespace easy2d
if (SUCCEEDED(hr))
{
hr = rt->CreateBitmapFromWicBitmap(
hr = d2d_device_context_->CreateBitmapFromWicBitmap(
converter.Get(),
nullptr,
&bitmap_tmp
@ -296,105 +369,19 @@ namespace easy2d
if (SUCCEEDED(hr))
{
bitmap = bitmap_tmp;
bitmap_cache_.insert(std::make_pair(hash_code, bitmap));
}
return hr;
}
HRESULT Factory::CreateRectangleGeometry(D2DRectangleGeometryPtr & geo, Rect const& rect) const
HRESULT D2DDeviceResources::CreateTextFormat(ComPtr<IDWriteTextFormat> & text_format, Font const & font, TextStyle const & text_style) const
{
if (!factory_)
if (!dwrite_factory_)
return E_UNEXPECTED;
D2DRectangleGeometryPtr rectangle;
HRESULT hr = factory_->CreateRectangleGeometry(
ToD2dRectF(rect),
&rectangle
);
if (SUCCEEDED(hr))
geo = rectangle;
return hr;
}
HRESULT Factory::CreateRoundedRectangleGeometry(D2DRoundedRectangleGeometryPtr & geo, Rect const & rect, float radius_x, float radius_y) const
{
if (!factory_)
return E_UNEXPECTED;
D2DRoundedRectangleGeometryPtr rounded_rect;
HRESULT hr = factory_->CreateRoundedRectangleGeometry(
D2D1::RoundedRect(
ToD2dRectF(rect),
radius_x,
radius_y
),
&rounded_rect
);
if (SUCCEEDED(hr))
geo = rounded_rect;
return hr;
}
HRESULT Factory::CreateEllipseGeometry(D2DEllipseGeometryPtr & geo, Point const & center, float radius_x, float radius_y) const
{
if (!factory_)
return E_UNEXPECTED;
D2DEllipseGeometryPtr ellipse;
HRESULT hr = factory_->CreateEllipseGeometry(
D2D1::Ellipse(
ToD2dPoint2F(center),
radius_x,
radius_y
),
&ellipse
);
if (SUCCEEDED(hr))
geo = ellipse;
return hr;
}
HRESULT Factory::CreateTransformedGeometry(
D2DTransformedGeometryPtr& transformed,
Matrix const& matrix,
D2DGeometryPtr const& geo
) const
{
if (!factory_)
return E_UNEXPECTED;
D2DTransformedGeometryPtr transformed_tmp;
HRESULT hr = factory_->CreateTransformedGeometry(
geo.Get(),
matrix,
&transformed_tmp
);
if (SUCCEEDED(hr))
{
transformed = transformed_tmp;
}
return hr;
}
HRESULT Factory::CreatePathGeometry(D2DPathGeometryPtr & geometry) const
{
if (!factory_)
return E_UNEXPECTED;
return factory_->CreatePathGeometry(&geometry);
}
HRESULT Factory::CreateTextFormat(D2DTextFormatPtr & text_format, Font const & font, TextStyle const & text_style) const
{
if (!write_factory_)
return E_UNEXPECTED;
D2DTextFormatPtr text_format_tmp;
HRESULT hr = write_factory_->CreateTextFormat(
ComPtr<IDWriteTextFormat> text_format_tmp;
HRESULT hr = dwrite_factory_->CreateTextFormat(
font.family.c_str(),
nullptr,
DWRITE_FONT_WEIGHT(font.weight),
@ -426,20 +413,20 @@ namespace easy2d
return hr;
}
HRESULT Factory::CreateTextLayout(D2DTextLayoutPtr & text_layout, Size& layout_size, String const & text, D2DTextFormatPtr const& text_format, TextStyle const & text_style) const
HRESULT D2DDeviceResources::CreateTextLayout(ComPtr<IDWriteTextLayout> & text_layout, Size& layout_size, String const & text, ComPtr<IDWriteTextFormat> const& text_format, TextStyle const & text_style) const
{
if (!write_factory_)
if (!dwrite_factory_)
return E_UNEXPECTED;
text_layout = nullptr;
HRESULT hr;
D2DTextLayoutPtr text_layout_tmp;
ComPtr<IDWriteTextLayout> text_layout_tmp;
UINT32 length = static_cast<UINT32>(text.length());
if (text_style.wrap)
{
hr = write_factory_->CreateTextLayout(
hr = dwrite_factory_->CreateTextLayout(
text.c_str(),
length,
text_format.Get(),
@ -450,7 +437,7 @@ namespace easy2d
}
else
{
hr = write_factory_->CreateTextLayout(
hr = dwrite_factory_->CreateTextLayout(
text.c_str(),
length,
text_format.Get(),
@ -468,7 +455,7 @@ namespace easy2d
if (SUCCEEDED(hr))
{
text_layout_tmp = nullptr;
hr = write_factory_->CreateTextLayout(
hr = dwrite_factory_->CreateTextLayout(
text.c_str(),
length,
text_format.Get(),
@ -507,21 +494,20 @@ namespace easy2d
return hr;
}
D2DStrokeStylePtr const& Factory::GetStrokeStyle(StrokeStyle stroke) const
void D2DDeviceResources::ClearImageCache()
{
bitmap_cache_.clear();
}
ID2D1StrokeStyle* D2DDeviceResources::GetStrokeStyle(StrokeStyle stroke) const
{
switch (stroke)
{
case StrokeStyle::Miter:
return miter_stroke_style_;
break;
case StrokeStyle::Bevel:
return bevel_stroke_style_;
break;
case StrokeStyle::Round:
return round_stroke_style_;
break;
case StrokeStyle::Miter: return d2d_miter_stroke_style_.Get(); break;
case StrokeStyle::Bevel: return d2d_bevel_stroke_style_.Get(); break;
case StrokeStyle::Round: return d2d_round_stroke_style_.Get(); break;
}
return miter_stroke_style_;
return nullptr;
}
}

117
src/dx/D2DDeviceResources.h Normal file
View File

@ -0,0 +1,117 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include "helper.hpp"
#include "../core/Resource.h"
#include "../core/Font.hpp"
#include "../core/TextStyle.hpp"
#include <d2d1.h>
#include <d2d1_1.h>
namespace easy2d
{
class E2D_API D2DDeviceResources
: public IUnknown
{
public:
HRESULT CreateBitmapFromFile(
_Out_ ComPtr<ID2D1Bitmap>& bitmap,
_In_ String const& file_path
);
HRESULT CreateBitmapFromResource(
_Out_ ComPtr<ID2D1Bitmap>& bitmap,
_In_ Resource const& res
);
HRESULT CreateTextFormat(
_Out_ ComPtr<IDWriteTextFormat>& text_format,
_In_ Font const& font,
_In_ TextStyle const& text_style
) const;
HRESULT CreateTextLayout(
_Out_ ComPtr<IDWriteTextLayout>& text_layout,
_Out_ Size& layout_size,
_In_ String const& text,
_In_ ComPtr<IDWriteTextFormat> const& text_format,
_In_ TextStyle const& text_style
) const;
void ClearImageCache();
void DiscardResources();
HRESULT SetD2DDevice(
_In_ ComPtr<ID2D1Device> const& device
);
void SetTargetBitmap(
_In_ ComPtr<ID2D1Bitmap1> const& target
);
inline ID2D1Factory1* GetD2DFactory() const { return d2d_factory_.Get(); }
inline IWICImagingFactory* GetWICImagingFactory() const { return imaging_factory_.Get(); }
inline IDWriteFactory* GetDWriteFactory() const { return dwrite_factory_.Get(); }
inline ID2D1Device* GetD2DDevice() const { return d2d_device_.Get(); }
inline ID2D1DeviceContext* GetD2DDeviceContext() const { return d2d_device_context_.Get(); }
inline ID2D1Bitmap1* GetD2DTargetBitmap() const { return d2d_target_bitmap_.Get(); }
ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const;
public:
unsigned long STDMETHODCALLTYPE AddRef();
unsigned long STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(
IID const& riid,
void** ppvObject
);
protected:
D2DDeviceResources();
virtual ~D2DDeviceResources();
HRESULT CreateDeviceIndependentResources();
private:
unsigned long ref_count_;
float dpi_;
using BitmapMap = UnorderedMap<size_t, ComPtr<ID2D1Bitmap>>;
BitmapMap bitmap_cache_;
ComPtr<ID2D1Factory1> d2d_factory_;
ComPtr<ID2D1Device> d2d_device_;
ComPtr<ID2D1DeviceContext> d2d_device_context_;
ComPtr<ID2D1Bitmap1> d2d_target_bitmap_;
ComPtr<IWICImagingFactory> imaging_factory_;
ComPtr<IDWriteFactory> dwrite_factory_;
ComPtr<ID2D1StrokeStyle> d2d_miter_stroke_style_;
ComPtr<ID2D1StrokeStyle> d2d_bevel_stroke_style_;
ComPtr<ID2D1StrokeStyle> d2d_round_stroke_style_;
};
}

View File

@ -0,0 +1,387 @@
// Copyright (c) 2016-2018 Easy2D - 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 "DeviceResources.h"
#include "../core/Image.h"
#include "../core/modules.h"
#include "../core/logs.h"
namespace easy2d
{
#if defined(_DEBUG)
namespace DX
{
inline bool SdkLayersAvailable()
{
HRESULT hr = modules::DirectX::Get().D3D11CreateDevice(
nullptr,
D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device.
0,
D3D11_CREATE_DEVICE_DEBUG, // Check for the SDK layers.
nullptr, // Any feature level will do.
0,
D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Runtime apps.
nullptr, // No need to keep the D3D device reference.
nullptr, // No need to know the feature level.
nullptr // No need to keep the D3D device context reference.
);
return SUCCEEDED(hr);
}
}
#endif
D3D11DeviceResources::D3D11DeviceResources()
: hwnd_(nullptr)
, d3d_feature_level_(D3D_FEATURE_LEVEL_9_1)
{
dpi_ = 96.f; // dpi_ = (float)GetDpiForWindow(hwnd);
}
D3D11DeviceResources::~D3D11DeviceResources()
{
DiscardResources();
}
HRESULT D3D11DeviceResources::Create(D3D11DeviceResources** device_resources, HWND hwnd)
{
HRESULT hr = E_FAIL;
if (device_resources)
{
D3D11DeviceResources* res = new (std::nothrow) D3D11DeviceResources;
if (res)
{
hr = res->CreateDeviceIndependentResources();
if (SUCCEEDED(hr))
{
RECT rc;
GetClientRect(hwnd, &rc);
res->hwnd_ = hwnd;
res->logical_size_.x = float(rc.right - rc.left);
res->logical_size_.y = float(rc.bottom - rc.top);
hr = res->CreateDeviceResources();
}
if (SUCCEEDED(hr))
{
hr = res->CreateWindowSizeDependentResources();
}
if (SUCCEEDED(hr))
{
res->AddRef();
DX::SafeRelease(*device_resources);
(*device_resources) = res;
}
else
{
delete res;
res = nullptr;
}
}
}
return hr;
}
void D3D11DeviceResources::DiscardResources()
{
d3d_device_.Reset();
d3d_device_context_.Reset();
dxgi_swap_chain_.Reset();
dxgi_factory_.Reset();
hwnd_ = nullptr;
}
HRESULT D3D11DeviceResources::CreateDeviceResources()
{
HRESULT hr = S_OK;
D3D_FEATURE_LEVEL feature_levels[] =
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1
};
ComPtr<ID3D11Device> device;
ComPtr<ID3D11DeviceContext> context;
// This flag adds support for surfaces with a different color channel ordering
// than the API default. It is required for compatibility with Direct2D.
UINT creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#if defined(E2D_DEBUG)
if (DX::SdkLayersAvailable())
{
creation_flags |= D3D11_CREATE_DEVICE_DEBUG;
}
#endif
hr = modules::DirectX::Get().D3D11CreateDevice(
nullptr, // Specify nullptr to use the default adapter.
D3D_DRIVER_TYPE_HARDWARE,
0, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE.
creation_flags, // Set debug and Direct2D compatibility flags.
feature_levels, // List of feature levels this app can support.
ARRAYSIZE(feature_levels), // Size of the list above.
D3D11_SDK_VERSION,
&device, // Returns the Direct3D device created.
&d3d_feature_level_, // Returns feature level of device created.
&context // Returns the device immediate context.
);
if (FAILED(hr))
{
// If the initialization fails, fall back to the WARP device.
// For more information on WARP, see:
// http://go.microsoft.com/fwlink/?LinkId=286690
hr = modules::DirectX::Get().D3D11CreateDevice(
nullptr,
D3D_DRIVER_TYPE_WARP, // Create a WARP device instead of a hardware device.
0,
creation_flags,
feature_levels,
ARRAYSIZE(feature_levels),
D3D11_SDK_VERSION,
&device,
&d3d_feature_level_,
&context
);
}
if (SUCCEEDED(hr))
{
d3d_device_ = device;
d3d_device_context_ = context;
ComPtr<IDXGIAdapter> dxgi_adapter;
ComPtr<IDXGIDevice> dxgi_device;
ComPtr<IDXGIFactory> dxgi_factory;
ComPtr<ID2D1Device> d2d_device;
if (SUCCEEDED(hr))
{
hr = d3d_device_->QueryInterface(IID_PPV_ARGS(&dxgi_device));
}
if (SUCCEEDED(hr))
{
hr = dxgi_device->GetAdapter(&dxgi_adapter);
}
if (SUCCEEDED(hr))
{
hr = dxgi_adapter->GetParent(IID_PPV_ARGS(&dxgi_factory));
}
if (SUCCEEDED(hr))
{
dxgi_factory_ = dxgi_factory;
}
// Create the Direct2D device object and a corresponding context.
if (SUCCEEDED(hr))
{
hr = GetD2DFactory()->CreateDevice(dxgi_device.Get(), &d2d_device);
}
if (SUCCEEDED(hr))
{
hr = SetD2DDevice(d2d_device);
}
}
return hr;
}
HRESULT D3D11DeviceResources::CreateWindowSizeDependentResources()
{
HRESULT hr = S_OK;
// Clear the previous window size specific context.
ID3D11RenderTargetView* null_views[] = { nullptr };
SetTargetBitmap(nullptr);
d3d_device_context_->OMSetRenderTargets(ARRAYSIZE(null_views), null_views, nullptr);
d3d_device_context_->Flush();
// Calculate the necessary render target size in pixels.
output_size_.x = DX::ConvertDipsToPixels(logical_size_.x, dpi_);
output_size_.y = DX::ConvertDipsToPixels(logical_size_.y, dpi_);
// Prevent zero size DirectX content from being created.
output_size_.x = std::max(output_size_.x, 1.f);
output_size_.y = std::max(output_size_.y, 1.f);
if (dxgi_swap_chain_)
{
// If the swap chain already exists, resize it.
hr = dxgi_swap_chain_->ResizeBuffers(
2, // Double-buffered swap chain.
::lround(output_size_.x),
::lround(output_size_.y),
DXGI_FORMAT_B8G8R8A8_UNORM,
0);
}
else
{
// Setup swap chain
DXGI_SWAP_CHAIN_DESC swap_chain_desc = { 0 };
swap_chain_desc.BufferCount = 2;
swap_chain_desc.BufferDesc.Width = ::lround(output_size_.x);
swap_chain_desc.BufferDesc.Height = ::lround(output_size_.y);
swap_chain_desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
swap_chain_desc.BufferDesc.RefreshRate.Numerator = 60;
swap_chain_desc.BufferDesc.RefreshRate.Denominator = 1;
swap_chain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swap_chain_desc.OutputWindow = hwnd_;
swap_chain_desc.SampleDesc.Count = 1;
swap_chain_desc.SampleDesc.Quality = 0;
swap_chain_desc.Windowed = TRUE;
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
ComPtr<IDXGIDevice> dxgi_device;
if (SUCCEEDED(hr))
{
hr = d3d_device_->QueryInterface(&dxgi_device);
}
ComPtr<IDXGIAdapter> dxgi_adapter;
if (SUCCEEDED(hr))
{
hr = dxgi_device->GetAdapter(&dxgi_adapter);
}
ComPtr<IDXGIFactory> dxgi_factory;
if (SUCCEEDED(hr))
{
hr = dxgi_adapter->GetParent(IID_PPV_ARGS(&dxgi_factory));
}
if (SUCCEEDED(hr))
{
hr = dxgi_factory->CreateSwapChain(
d3d_device_.Get(),
&swap_chain_desc,
&dxgi_swap_chain_);
}
}
if (SUCCEEDED(hr))
{
// Set the 3D rendering viewport to target the entire window.
CD3D11_VIEWPORT screen_viewport(
0.0f,
0.0f,
output_size_.x,
output_size_.y);
d3d_device_context_->RSSetViewports(1, &screen_viewport);
}
// Create a Direct2D target bitmap associated with the
// swap chain back buffer and set it as the current target.
if (SUCCEEDED(hr))
{
D2D1_BITMAP_PROPERTIES1 bitmap_props =
D2D1::BitmapProperties1(
D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
dpi_,
dpi_);
ComPtr<IDXGISurface> dxgi_back_buffer;
hr = dxgi_swap_chain_->GetBuffer(0, IID_PPV_ARGS(&dxgi_back_buffer));
ComPtr<ID2D1Bitmap1> target;
if (SUCCEEDED(hr))
{
hr = GetD2DDeviceContext()->CreateBitmapFromDxgiSurface(
dxgi_back_buffer.Get(),
&bitmap_props,
&target);
}
if (SUCCEEDED(hr))
{
SetTargetBitmap(target);
}
}
return hr;
}
HRESULT D3D11DeviceResources::HandleDeviceLost()
{
dxgi_swap_chain_ = nullptr;
HRESULT hr = CreateDeviceResources();
if (SUCCEEDED(hr))
{
hr = CreateWindowSizeDependentResources();
}
return hr;
}
void D3D11DeviceResources::SetLogicalSize(Size logical_size)
{
if (logical_size_ != logical_size)
{
logical_size_ = logical_size;
ThrowIfFailed(
CreateWindowSizeDependentResources()
);
}
}
void D3D11DeviceResources::SetDpi(float dpi)
{
if (dpi != dpi_)
{
dpi_ = dpi;
RECT rc;
GetClientRect(hwnd_, &rc);
logical_size_.x = float(rc.right - rc.left);
logical_size_.y = float(rc.bottom - rc.top);
GetD2DDeviceContext()->SetDpi(dpi_, dpi_);
ThrowIfFailed(
CreateWindowSizeDependentResources()
);
}
}
}

View File

@ -0,0 +1,82 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include "helper.hpp"
#include "D2DDeviceResources.h"
#include <d3d11.h>
namespace easy2d
{
class E2D_API D3D11DeviceResources
: public D2DDeviceResources
{
public:
static HRESULT Create(
D3D11DeviceResources** device_resources,
HWND hwnd
);
HRESULT HandleDeviceLost();
void SetLogicalSize(
Size logical_size
);
void SetDpi(
float dpi
);
void DiscardResources();
inline ID3D11Device* GetD3DDevice() const { return d3d_device_.Get(); }
inline ID3D11DeviceContext* GetD3DDeviceContext() const { return d3d_device_context_.Get(); }
inline IDXGIFactory* GetDXGIFactory() const { return dxgi_factory_.Get(); }
inline IDXGISwapChain* GetDXGISwapChain() const { return dxgi_swap_chain_.Get(); }
inline D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return d3d_feature_level_; }
inline Size const& GetLogicalSize() const { return logical_size_; }
inline Size const& GetOutputSize() const { return output_size_; }
inline float GetDpi() const { return dpi_; }
protected:
D3D11DeviceResources();
virtual ~D3D11DeviceResources();
protected:
HRESULT CreateDeviceResources();
HRESULT CreateWindowSizeDependentResources();
private:
HWND hwnd_;
float dpi_;
Size logical_size_;
Size output_size_;
D3D_FEATURE_LEVEL d3d_feature_level_;
ComPtr<ID3D11Device> d3d_device_;
ComPtr<ID3D11DeviceContext> d3d_device_context_;
ComPtr<IDXGISwapChain> dxgi_swap_chain_;
ComPtr<IDXGIFactory> dxgi_factory_;
};
}

27
src/dx/DeviceResources.h Normal file
View File

@ -0,0 +1,27 @@
// Copyright (c) 2016-2018 Easy2D - 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 "D3D11DeviceResources.h"
namespace easy2d
{
using DeviceResources = D3D11DeviceResources;
}

View File

@ -24,17 +24,17 @@
namespace easy2d
{
class TextRendererImpl
class TextRenderer
: public ITextRenderer
{
public:
TextRendererImpl(
ID2D1Factory* pD2DFactory,
ID2D1RenderTarget* pRT,
ID2D1SolidColorBrush* pBrush
TextRenderer(
ID2D1RenderTarget* pRT
);
~TextRendererImpl();
~TextRenderer();
STDMETHOD(CreateDeviceResources)();
STDMETHOD_(void, SetTextStyle)(
CONST D2D1_COLOR_F &fillColor,
@ -109,7 +109,7 @@ namespace easy2d
D2D1_COLOR_F sOutlineColor_;
FLOAT fOutlineWidth;
BOOL bShowOutline_;
ID2D1Factory* pD2DFactory_;
ID2D1Factory* pFactory_;
ID2D1RenderTarget* pRT_;
ID2D1SolidColorBrush* pBrush_;
ID2D1StrokeStyle* pCurrStrokeStyle_;
@ -117,43 +117,72 @@ namespace easy2d
HRESULT ITextRenderer::Create(
ITextRenderer** ppTextRenderer,
ID2D1Factory* pD2DFactory,
ID2D1RenderTarget* pRT,
ID2D1SolidColorBrush* pBrush)
ID2D1RenderTarget* pRT)
{
*ppTextRenderer = new (std::nothrow) TextRendererImpl(pD2DFactory, pRT, pBrush);
if (*ppTextRenderer)
HRESULT hr = E_FAIL;
if (ppTextRenderer)
{
(*ppTextRenderer)->AddRef();
TextRenderer* pTextRenderer = new (std::nothrow) TextRenderer(pRT);
if (pTextRenderer)
{
hr = pTextRenderer->CreateDeviceResources();
if (SUCCEEDED(hr))
{
pTextRenderer->AddRef();
DX::SafeRelease(*ppTextRenderer);
(*ppTextRenderer) = pTextRenderer;
return S_OK;
}
return E_FAIL;
else
{
delete pTextRenderer;
pTextRenderer = NULL;
}
}
}
return hr;
}
TextRendererImpl::TextRendererImpl(ID2D1Factory* pD2DFactory, ID2D1RenderTarget* pRT, ID2D1SolidColorBrush* pBrush)
TextRenderer::TextRenderer(ID2D1RenderTarget* pRT)
: cRefCount_(0)
, pD2DFactory_(pD2DFactory)
, pFactory_(NULL)
, pRT_(pRT)
, pBrush_(pBrush)
, pBrush_(NULL)
, sFillColor_()
, sOutlineColor_()
, fOutlineWidth(1)
, bShowOutline_(TRUE)
, pCurrStrokeStyle_(nullptr)
, pCurrStrokeStyle_(NULL)
{
pD2DFactory->AddRef();
pRT->AddRef();
pBrush->AddRef();
pRT_->AddRef();
pRT_->GetFactory(&pFactory_);
}
TextRendererImpl::~TextRendererImpl()
TextRenderer::~TextRenderer()
{
SafeRelease(pD2DFactory_);
SafeRelease(pRT_);
SafeRelease(pBrush_);
DX::SafeRelease(pFactory_);
DX::SafeRelease(pRT_);
DX::SafeRelease(pBrush_);
}
STDMETHODIMP_(void) TextRendererImpl::SetTextStyle(
STDMETHODIMP TextRenderer::CreateDeviceResources()
{
HRESULT hr = S_OK;
DX::SafeRelease(pBrush_);
hr = pRT_->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::White),
&pBrush_
);
return hr;
}
STDMETHODIMP_(void) TextRenderer::SetTextStyle(
CONST D2D1_COLOR_F &fillColor,
BOOL outline,
CONST D2D1_COLOR_F &outlineColor,
@ -167,7 +196,7 @@ namespace easy2d
pCurrStrokeStyle_ = outlineJoin;
}
STDMETHODIMP TextRendererImpl::DrawGlyphRun(
STDMETHODIMP TextRenderer::DrawGlyphRun(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
@ -183,12 +212,12 @@ namespace easy2d
HRESULT hr = S_OK;
ID2D1PathGeometry* pPathGeometry = nullptr;
hr = pD2DFactory_->CreatePathGeometry(
ID2D1PathGeometry* pPathGeometry = NULL;
hr = pFactory_->CreatePathGeometry(
&pPathGeometry
);
ID2D1GeometrySink* pSink = nullptr;
ID2D1GeometrySink* pSink = NULL;
if (SUCCEEDED(hr))
{
hr = pPathGeometry->Open(
@ -221,10 +250,10 @@ namespace easy2d
baselineOriginX, baselineOriginY
);
ID2D1TransformedGeometry* pTransformedGeometry = nullptr;
ID2D1TransformedGeometry* pTransformedGeometry = NULL;
if (SUCCEEDED(hr))
{
hr = pD2DFactory_->CreateTransformedGeometry(
hr = pFactory_->CreateTransformedGeometry(
pPathGeometry,
&matrix,
&pTransformedGeometry
@ -253,14 +282,14 @@ namespace easy2d
);
}
SafeRelease(pPathGeometry);
SafeRelease(pSink);
SafeRelease(pTransformedGeometry);
DX::SafeRelease(pPathGeometry);
DX::SafeRelease(pSink);
DX::SafeRelease(pTransformedGeometry);
return hr;
}
STDMETHODIMP TextRendererImpl::DrawUnderline(
STDMETHODIMP TextRenderer::DrawUnderline(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
@ -279,8 +308,8 @@ namespace easy2d
underline->offset + underline->thickness
);
ID2D1RectangleGeometry* pRectangleGeometry = nullptr;
hr = pD2DFactory_->CreateRectangleGeometry(
ID2D1RectangleGeometry* pRectangleGeometry = NULL;
hr = pFactory_->CreateRectangleGeometry(
&rect,
&pRectangleGeometry
);
@ -291,10 +320,10 @@ namespace easy2d
baselineOriginX, baselineOriginY
);
ID2D1TransformedGeometry* pTransformedGeometry = nullptr;
ID2D1TransformedGeometry* pTransformedGeometry = NULL;
if (SUCCEEDED(hr))
{
hr = pD2DFactory_->CreateTransformedGeometry(
hr = pFactory_->CreateTransformedGeometry(
pRectangleGeometry,
&matrix,
&pTransformedGeometry
@ -323,13 +352,13 @@ namespace easy2d
);
}
SafeRelease(pRectangleGeometry);
SafeRelease(pTransformedGeometry);
DX::SafeRelease(pRectangleGeometry);
DX::SafeRelease(pTransformedGeometry);
return S_OK;
}
STDMETHODIMP TextRendererImpl::DrawStrikethrough(
STDMETHODIMP TextRenderer::DrawStrikethrough(
__maybenull void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
@ -348,8 +377,8 @@ namespace easy2d
strikethrough->offset + strikethrough->thickness
);
ID2D1RectangleGeometry* pRectangleGeometry = nullptr;
hr = pD2DFactory_->CreateRectangleGeometry(
ID2D1RectangleGeometry* pRectangleGeometry = NULL;
hr = pFactory_->CreateRectangleGeometry(
&rect,
&pRectangleGeometry
);
@ -360,10 +389,10 @@ namespace easy2d
baselineOriginX, baselineOriginY
);
ID2D1TransformedGeometry* pTransformedGeometry = nullptr;
ID2D1TransformedGeometry* pTransformedGeometry = NULL;
if (SUCCEEDED(hr))
{
hr = pD2DFactory_->CreateTransformedGeometry(
hr = pFactory_->CreateTransformedGeometry(
pRectangleGeometry,
&matrix,
&pTransformedGeometry
@ -392,13 +421,13 @@ namespace easy2d
);
}
SafeRelease(pRectangleGeometry);
SafeRelease(pTransformedGeometry);
DX::SafeRelease(pRectangleGeometry);
DX::SafeRelease(pTransformedGeometry);
return S_OK;
}
STDMETHODIMP TextRendererImpl::DrawInlineObject(
STDMETHODIMP TextRenderer::DrawInlineObject(
__maybenull void* clientDrawingContext,
FLOAT originX,
FLOAT originY,
@ -417,12 +446,12 @@ namespace easy2d
return E_NOTIMPL;
}
STDMETHODIMP_(unsigned long) TextRendererImpl::AddRef()
STDMETHODIMP_(unsigned long) TextRenderer::AddRef()
{
return InterlockedIncrement(&cRefCount_);
}
STDMETHODIMP_(unsigned long) TextRendererImpl::Release()
STDMETHODIMP_(unsigned long) TextRenderer::Release()
{
unsigned long newCount = InterlockedDecrement(&cRefCount_);
@ -435,7 +464,7 @@ namespace easy2d
return newCount;
}
STDMETHODIMP TextRendererImpl::IsPixelSnappingDisabled(
STDMETHODIMP TextRenderer::IsPixelSnappingDisabled(
__maybenull void* clientDrawingContext,
__out BOOL* isDisabled)
{
@ -445,7 +474,7 @@ namespace easy2d
return S_OK;
}
STDMETHODIMP TextRendererImpl::GetCurrentTransform(
STDMETHODIMP TextRenderer::GetCurrentTransform(
__maybenull void* clientDrawingContext,
__out DWRITE_MATRIX* transform)
{
@ -455,7 +484,7 @@ namespace easy2d
return S_OK;
}
STDMETHODIMP TextRendererImpl::GetPixelsPerDip(
STDMETHODIMP TextRenderer::GetPixelsPerDip(
__maybenull void* clientDrawingContext,
__out FLOAT* pixelsPerDip)
{
@ -469,7 +498,7 @@ namespace easy2d
return S_OK;
}
STDMETHODIMP TextRendererImpl::QueryInterface(
STDMETHODIMP TextRenderer::QueryInterface(
IID const& riid,
void** ppvObject)
{
@ -487,7 +516,7 @@ namespace easy2d
}
else
{
*ppvObject = nullptr;
*ppvObject = NULL;
return E_FAIL;
}

View File

@ -19,7 +19,8 @@
// THE SOFTWARE.
#pragma once
#include "d2dhelper.hpp"
#include "helper.hpp"
#include <dwrite.h>
namespace easy2d
{
@ -29,9 +30,7 @@ namespace easy2d
public:
static E2D_API HRESULT Create(
_Out_ ITextRenderer** ppTextRenderer,
_In_ ID2D1Factory* pD2DFactory,
_In_ ID2D1RenderTarget* pRT,
_In_ ID2D1SolidColorBrush* pBrush
_In_ ID2D1RenderTarget* pRT
);
STDMETHOD_(void, SetTextStyle)(
@ -43,5 +42,3 @@ namespace easy2d
) PURE;
};
}
E2D_DECLARE_D2D_SMART_PTR(easy2d::ITextRenderer, D2DTextRendererPtr);

90
src/dx/helper.hpp Normal file
View File

@ -0,0 +1,90 @@
// Copyright (c) 2016-2018 Easy2D - 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 "../core/IntrusivePtr.hpp"
#include "../core/Color.h"
#include "../math/vector.hpp"
#include "../math/Rect.hpp"
#include "../math/Matrix.hpp"
#include <d2d1.h>
namespace easy2d
{
// ComPtr<> is a smart pointer for COM
template <typename _Ty>
using ComPtr = IntrusivePtr<_Ty>;
inline void IntrusivePtrAddRef(IUnknown* ptr)
{
if (ptr) { ptr->AddRef(); }
}
inline void IntrusivePtrRelease(IUnknown* ptr)
{
if (ptr) { ptr->Release(); }
}
namespace DX
{
template <typename T>
inline void SafeRelease(T*& ptr)
{
if (ptr != nullptr)
{
ptr->Release();
ptr = nullptr;
}
}
inline D2D1_POINT_2F const& ConvertToPoint2F(math::Vec2 const& point)
{
return reinterpret_cast<D2D1_POINT_2F const&>(point);
}
inline D2D1_SIZE_F const& ConvertToSizeF(math::Vec2 const& size)
{
return reinterpret_cast<D2D1_SIZE_F const&>(size);
}
inline D2D1_RECT_F ConvertToRectF(math::Rect const& rect)
{
return D2D1_RECT_F{ rect.origin.x, rect.origin.y, rect.origin.x + rect.size.x, rect.origin.y + rect.size.y };
}
inline D2D1_COLOR_F const& ConvertToColorF(Color const& color)
{
return reinterpret_cast<D2D1_COLOR_F const&>(color);
}
inline D2D1_MATRIX_3X2_F const& ConvertToMatrix3x2F(math::Matrix const& matrix)
{
return reinterpret_cast<D2D1_MATRIX_3X2_F const&>(matrix);
}
// Converts a length in device-independent pixels (DIPs) to a length in physical pixels.
inline float ConvertDipsToPixels(float dips, float dpi)
{
static const float dips_per_inch = 96.0f;
return math::Floor(dips * dpi / dips_per_inch + 0.5f); // Round to nearest integer.
}
}
}

View File

@ -77,7 +77,6 @@
#include "core/GeometryNode.h"
#include "core/DebugNode.h"
#include "core/Factory.h"
#include "core/Application.h"
@ -90,7 +89,7 @@
#include "math/ease.hpp"
#include "math/vector.hpp"
#include "math/rand.h"
#include "math/Matrix.h"
#include "math/Matrix.hpp"
//

View File

@ -1,152 +0,0 @@
// Copyright (c) 2016-2018 Easy2D - 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 "Matrix.h"
namespace easy2d
{
namespace math
{
Matrix::Matrix()
: _11(1.f), _12(0.f)
, _21(0.f), _22(1.f)
, _31(0.f), _32(0.f)
{
}
Matrix::Matrix(float _11, float _12, float _21, float _22, float _31, float _32)
: _11(_11), _12(_12), _21(_21), _22(_22), _31(_31), _32(_32)
{
}
Matrix::Matrix(const float* p)
{
for (int i = 0; i < 6; i++)
m[i] = p[i];
}
Matrix::Matrix(Matrix const& other)
: _11(other._11), _12(other._12)
, _21(other._21), _22(other._22)
, _31(other._31), _32(other._32)
{
}
void Matrix::Identity()
{
_11 = 1.f; _12 = 0.f;
_21 = 0.f; _12 = 1.f;
_31 = 0.f; _32 = 0.f;
}
Rect Matrix::Transform(const Rect & rect) const
{
Vec2 top_left = Transform(rect.GetLeftTop());
Vec2 top_right = Transform(rect.GetRightTop());
Vec2 bottom_left = Transform(rect.GetLeftBottom());
Vec2 bottom_right = Transform(rect.GetRightBottom());
float left = std::min(std::min(top_left.x, top_right.x), std::min(bottom_left.x, bottom_right.x));
float right = std::max(std::max(top_left.x, top_right.x), std::max(bottom_left.x, bottom_right.x));
float top = std::min(std::min(top_left.y, top_right.y), std::min(bottom_left.y, bottom_right.y));
float bottom = std::max(std::max(top_left.y, top_right.y), std::max(bottom_left.y, bottom_right.y));
return Rect{ left, top, (right - left), (bottom - top) };
}
Matrix Matrix::Translation(const Vec2& v)
{
return Matrix(
1.f, 0.f,
0.f, 1.f,
v.x, v.y
);
}
Matrix Matrix::Translation(
float x,
float y)
{
return Translation(Vec2(x, y));
}
Matrix Matrix::Scaling(
const Vec2& v,
const Vec2& center)
{
return Matrix(
v.x, 0.f,
0.f, v.y,
center.x - v.x * center.x,
center.y - v.y * center.y
);
}
Matrix Matrix::Scaling(
float x,
float y,
const Vec2& center)
{
return Scaling(Vec2(x, y), center);
}
Matrix Matrix::Rotation(
float angle,
const Vec2& center)
{
float s = math::Sin(angle);
float c = math::Cos(angle);
return Matrix(
c, s,
-s, c,
center.x * (1 - c) + center.y * s,
center.y * (1 - c) - center.x * s
);
}
Matrix Matrix::Skewing(
float angle_x,
float angle_y,
const Vec2& center)
{
float tx = math::Tan(angle_x);
float ty = math::Tan(angle_y);
return Matrix(
1.f, -ty,
-tx, 1.f,
center.y * tx, center.x * ty
);
}
Matrix Matrix::Invert(Matrix const& matrix)
{
float det = 1.f / matrix.Determinant();
return Matrix(
det * matrix._22,
-det * matrix._12,
-det * matrix._21,
det * matrix._11,
det * (matrix._21 * matrix._32 - matrix._22 * matrix._31),
det * (matrix._12 * matrix._31 - matrix._11 * matrix._32)
);
}
}
}

View File

@ -21,12 +21,13 @@
#pragma once
#include "vector.hpp"
#include "Rect.hpp"
#include <algorithm>
namespace easy2d
{
namespace math
{
struct E2D_API Matrix
struct Matrix
{
union
{
@ -44,13 +45,30 @@ namespace easy2d
};
};
Matrix();
Matrix()
: _11(1.f), _12(0.f)
, _21(0.f), _22(1.f)
, _31(0.f), _32(0.f)
{
}
Matrix(float _11, float _12, float _21, float _22, float _31, float _32);
Matrix(float _11, float _12, float _21, float _22, float _31, float _32)
: _11(_11), _12(_12), _21(_21), _22(_22), _31(_31), _32(_32)
{
}
Matrix(const float* p);
Matrix(const float* p)
{
for (int i = 0; i < 6; i++)
m[i] = p[i];
}
Matrix(Matrix const& other);
Matrix(Matrix const& other)
: _11(other._11), _12(other._12)
, _21(other._21), _22(other._22)
, _31(other._31), _32(other._32)
{
}
template <typename T>
Matrix(T const& other)
@ -59,7 +77,12 @@ namespace easy2d
m[i] = other[i];
}
void Identity();
inline void Identity()
{
_11 = 1.f; _12 = 0.f;
_21 = 0.f; _12 = 1.f;
_31 = 0.f; _32 = 0.f;
}
inline Vec2 Transform(const Vec2& v) const
{
@ -69,7 +92,20 @@ namespace easy2d
);
}
Rect Transform(const Rect& rect) const;
Rect Transform(const Rect & rect) const
{
Vec2 top_left = Transform(rect.GetLeftTop());
Vec2 top_right = Transform(rect.GetRightTop());
Vec2 bottom_left = Transform(rect.GetLeftBottom());
Vec2 bottom_right = Transform(rect.GetRightBottom());
float left = std::min(std::min(top_left.x, top_right.x), std::min(bottom_left.x, bottom_right.x));
float right = std::max(std::max(top_left.x, top_right.x), std::max(bottom_left.x, bottom_right.x));
float top = std::min(std::min(top_left.y, top_right.y), std::min(bottom_left.y, bottom_right.y));
float bottom = std::max(std::max(top_left.y, top_right.y), std::max(bottom_left.y, bottom_right.y));
return Rect{ left, top, (right - left), (bottom - top) };
}
inline void Translate(const Vec2& v)
{
@ -107,46 +143,83 @@ namespace easy2d
return 0 != Determinant();
}
inline operator D2D1_MATRIX_3X2_F const& () const
static inline Matrix Translation(const Vec2& v)
{
return reinterpret_cast<D2D1_MATRIX_3X2_F const&>(*this);
return Matrix(
1.f, 0.f,
0.f, 1.f,
v.x, v.y
);
}
inline operator D2D1_MATRIX_3X2_F& ()
{
return reinterpret_cast<D2D1_MATRIX_3X2_F&>(*this);
}
static Matrix Translation(const Vec2& v);
static Matrix Translation(
static inline Matrix Translation(
float x,
float y
);
float y)
{
return Translation(Vec2(x, y));
}
static Matrix Scaling(
static inline Matrix Scaling(
const Vec2& v,
const Vec2& center = Vec2()
const Vec2& center = Vec2())
{
return Matrix(
v.x, 0.f,
0.f, v.y,
center.x - v.x * center.x,
center.y - v.y * center.y
);
}
static Matrix Scaling(
static inline Matrix Scaling(
float x,
float y,
const Vec2& center = Vec2()
);
const Vec2& center = Vec2())
{
return Scaling(Vec2(x, y), center);
}
static Matrix Rotation(
static inline Matrix Rotation(
float angle,
const Vec2& center = Vec2()
const Vec2& center = Vec2())
{
float s = math::Sin(angle);
float c = math::Cos(angle);
return Matrix(
c, s,
-s, c,
center.x * (1 - c) + center.y * s,
center.y * (1 - c) - center.x * s
);
}
static Matrix Skewing(
static inline Matrix Skewing(
float angle_x,
float angle_y,
const Vec2& center = Vec2()
const Vec2& center = Vec2())
{
float tx = math::Tan(angle_x);
float ty = math::Tan(angle_y);
return Matrix(
1.f, -ty,
-tx, 1.f,
center.y * tx, center.x * ty
);
}
static Matrix Invert(Matrix const& matrix);
static inline Matrix Invert(Matrix const& matrix)
{
float det = 1.f / matrix.Determinant();
return Matrix(
det * matrix._22,
-det * matrix._12,
-det * matrix._21,
det * matrix._11,
det * (matrix._21 * matrix._32 - matrix._22 * matrix._31),
det * (matrix._12 * matrix._31 - matrix._11 * matrix._32)
);
}
};

View File

@ -26,7 +26,7 @@ namespace easy2d
namespace math
{
// 矩形
struct E2D_API Rect
struct Rect
{
Vec2 origin; // 左上角坐标
Vec2 size; // 宽度和高度

View File

@ -19,7 +19,6 @@
// THE SOFTWARE.
#pragma once
#include "../core/macros.h"
#include "constants.hpp"
#include <cmath>

View File

@ -25,7 +25,7 @@ namespace easy2d
{
namespace math
{
struct E2D_API Vec2
struct Vec2
{
float x;
float y;
@ -81,6 +81,11 @@ namespace easy2d
{
return (x == other.x) && (y == other.y);
}
inline bool operator!= (const Vec2& other) const
{
return (x != other.x) || (y != other.y);
}
};
using Point = Vec2;

View File

@ -23,9 +23,9 @@
#endif
#include "Transcoder.h"
#include "../core/d2dhelper.hpp"
#include "../core/modules.h"
#include "../core/logs.h"
#include "../DX/helper.hpp"
#include <shlwapi.h>
namespace easy2d
@ -53,7 +53,7 @@ namespace easy2d
{
HRESULT hr = S_OK;
IntrusivePtr<IMFSourceReader> reader;
ComPtr<IMFSourceReader> reader;
hr = modules::MediaFoundation::Get().MFCreateSourceReaderFromURL(
file_path.c_str(),
@ -73,9 +73,9 @@ namespace easy2d
{
HRESULT hr = S_OK;
IntrusivePtr<IStream> stream;
IntrusivePtr<IMFByteStream> byte_stream;
IntrusivePtr<IMFSourceReader> reader;
ComPtr<IStream> stream;
ComPtr<IMFByteStream> byte_stream;
ComPtr<IMFSourceReader> reader;
LPVOID buffer;
DWORD buffer_size;
@ -119,8 +119,8 @@ namespace easy2d
HRESULT hr = S_OK;
DWORD max_stream_size = 0;
IntrusivePtr<IMFMediaType> partial_type;
IntrusivePtr<IMFMediaType> uncompressed_type;
ComPtr<IMFMediaType> partial_type;
ComPtr<IMFMediaType> uncompressed_type;
hr = modules::MediaFoundation::Get().MFCreateMediaType(&partial_type);
@ -200,8 +200,8 @@ namespace easy2d
DWORD position = 0;
BYTE* data = new (std::nothrow) BYTE[max_stream_size];
IntrusivePtr<IMFSample> sample;
IntrusivePtr<IMFMediaBuffer> buffer;
ComPtr<IMFSample> sample;
ComPtr<IMFMediaBuffer> buffer;
if (data == nullptr)
{