Update TextureRenderContext

This commit is contained in:
Nomango 2020-02-08 00:17:31 +08:00
parent a633669058
commit d938922605
14 changed files with 532 additions and 378 deletions

View File

@ -84,6 +84,7 @@
<ClInclude Include="..\..\src\kiwano\render\TextStyle.hpp" /> <ClInclude Include="..\..\src\kiwano\render\TextStyle.hpp" />
<ClInclude Include="..\..\src\kiwano\render\Texture.h" /> <ClInclude Include="..\..\src\kiwano\render\Texture.h" />
<ClInclude Include="..\..\src\kiwano\render\TextureCache.h" /> <ClInclude Include="..\..\src\kiwano\render\TextureCache.h" />
<ClInclude Include="..\..\src\kiwano\render\TextureRenderContext.h" />
<ClInclude Include="..\..\src\kiwano\utils\LocalStorage.h" /> <ClInclude Include="..\..\src\kiwano\utils\LocalStorage.h" />
<ClInclude Include="..\..\src\kiwano\utils\ResourceCache.h" /> <ClInclude Include="..\..\src\kiwano\utils\ResourceCache.h" />
<ClInclude Include="..\..\src\kiwano\utils\UserData.h" /> <ClInclude Include="..\..\src\kiwano\utils\UserData.h" />
@ -151,6 +152,7 @@
<ClCompile Include="..\..\src\kiwano\render\TextLayout.cpp" /> <ClCompile Include="..\..\src\kiwano\render\TextLayout.cpp" />
<ClCompile Include="..\..\src\kiwano\render\Texture.cpp" /> <ClCompile Include="..\..\src\kiwano\render\Texture.cpp" />
<ClCompile Include="..\..\src\kiwano\render\TextureCache.cpp" /> <ClCompile Include="..\..\src\kiwano\render\TextureCache.cpp" />
<ClCompile Include="..\..\src\kiwano\render\TextureRenderContext.cpp" />
<ClCompile Include="..\..\src\kiwano\utils\LocalStorage.cpp" /> <ClCompile Include="..\..\src\kiwano\utils\LocalStorage.cpp" />
<ClCompile Include="..\..\src\kiwano\utils\ResourceCache.cpp" /> <ClCompile Include="..\..\src\kiwano\utils\ResourceCache.cpp" />
<ClCompile Include="..\..\src\kiwano\utils\UserData.cpp" /> <ClCompile Include="..\..\src\kiwano\utils\UserData.cpp" />

View File

@ -285,6 +285,9 @@
<ClInclude Include="..\..\src\kiwano\math\Scalar.h"> <ClInclude Include="..\..\src\kiwano\math\Scalar.h">
<Filter>math</Filter> <Filter>math</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\kiwano\render\TextureRenderContext.h">
<Filter>render</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp"> <ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp">
@ -482,5 +485,8 @@
<ClCompile Include="..\..\src\kiwano\render\ShapeSink.cpp"> <ClCompile Include="..\..\src\kiwano\render\ShapeSink.cpp">
<Filter>render</Filter> <Filter>render</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\kiwano\render\TextureRenderContext.cpp">
<Filter>render</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -154,7 +154,7 @@ void Actor::RenderBorder(RenderContext& ctx)
ctx.FillRectangle(bounds); ctx.FillRectangle(bounds);
ctx.SetCurrentBrush(GetStage()->GetBorderStrokeBrush()); ctx.SetCurrentBrush(GetStage()->GetBorderStrokeBrush());
ctx.DrawRectangle(bounds, 2.f); ctx.DrawRectangle(bounds, nullptr, 2.f);
} }
for (auto child = children_.first_item(); child; child = child->next_item()) for (auto child = children_.first_item(); child; child = child->next_item())

View File

@ -25,9 +25,22 @@
namespace kiwano namespace kiwano
{ {
CanvasPtr Canvas::Create() CanvasPtr Canvas::Create(Size const& size)
{ {
CanvasPtr ptr = new (std::nothrow) Canvas; CanvasPtr ptr = new (std::nothrow) Canvas;
if (ptr)
{
try
{
ptr->ctx_ = TextureRenderContext::Create();
ptr->stroke_brush_ = Brush::Create(Color::White);
ptr->fill_brush_ = Brush::Create(Color::White);
}
catch (std::exception)
{
return nullptr;
}
}
return ptr; return ptr;
} }
@ -38,17 +51,15 @@ Canvas::Canvas()
{ {
} }
Canvas::~Canvas() {}
void Canvas::BeginDraw() void Canvas::BeginDraw()
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->BeginDraw(); ctx_->BeginDraw();
} }
void Canvas::EndDraw() void Canvas::EndDraw()
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->EndDraw(); ctx_->EndDraw();
cache_expired_ = true; cache_expired_ = true;
} }
@ -68,116 +79,111 @@ void Canvas::OnRender(RenderContext& ctx)
void Canvas::SetBrush(BrushPtr brush) void Canvas::SetBrush(BrushPtr brush)
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(brush); ctx_->SetCurrentBrush(brush);
} }
float Canvas::GetStrokeWidth() const
{
return stroke_width_;
}
void Canvas::SetBrushTransform(Transform const& transform) void Canvas::SetBrushTransform(Transform const& transform)
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->SetTransform(transform.ToMatrix()); ctx_->SetTransform(transform.ToMatrix());
} }
void Canvas::SetBrushTransform(Matrix3x2 const& transform) void Canvas::SetBrushTransform(Matrix3x2 const& transform)
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->SetTransform(transform); ctx_->SetTransform(transform);
} }
void Canvas::PushLayerArea(LayerArea& area) void Canvas::PushLayerArea(LayerArea& area)
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->PushLayer(area); ctx_->PushLayer(area);
} }
void Canvas::PopLayerArea() void Canvas::PopLayerArea()
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->PopLayer(); ctx_->PopLayer();
} }
void Canvas::PushClipRect(Rect const& clip_rect) void Canvas::PushClipRect(Rect const& clip_rect)
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->PushClipRect(clip_rect); ctx_->PushClipRect(clip_rect);
} }
void Canvas::PopClipRect() void Canvas::PopClipRect()
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->PopClipRect(); ctx_->PopClipRect();
} }
void Canvas::DrawShape(ShapePtr shape) void Canvas::DrawShape(ShapePtr shape)
{ {
if (!shape) KGE_ASSERT(ctx_);
return; if (shape)
{
InitRenderTargetAndBrushs(); ctx_->SetCurrentBrush(stroke_brush_);
ctx_->SetCurrentBrush(stroke_brush_); ctx_->DrawShape(*shape, stroke_style_, stroke_width_);
ctx_->DrawShape(*shape, stroke_width_, stroke_style_); cache_expired_ = true;
cache_expired_ = true; }
} }
void Canvas::DrawLine(Point const& begin, Point const& end) void Canvas::DrawLine(Point const& begin, Point const& end)
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(stroke_brush_); ctx_->SetCurrentBrush(stroke_brush_);
ctx_->DrawLine(begin, end, stroke_width_, stroke_style_); ctx_->DrawLine(begin, end, stroke_style_, stroke_width_);
cache_expired_ = true; cache_expired_ = true;
} }
void Canvas::DrawCircle(Point const& center, float radius) void Canvas::DrawCircle(Point const& center, float radius)
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(stroke_brush_); ctx_->SetCurrentBrush(stroke_brush_);
ctx_->DrawEllipse(center, Vec2(radius, radius), stroke_width_, stroke_style_); ctx_->DrawEllipse(center, Vec2(radius, radius), stroke_style_, stroke_width_);
cache_expired_ = true; cache_expired_ = true;
} }
void Canvas::DrawEllipse(Point const& center, Vec2 const& radius) void Canvas::DrawEllipse(Point const& center, Vec2 const& radius)
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(stroke_brush_); ctx_->SetCurrentBrush(stroke_brush_);
ctx_->DrawEllipse(center, radius, stroke_width_, stroke_style_); ctx_->DrawEllipse(center, radius, stroke_style_, stroke_width_);
cache_expired_ = true; cache_expired_ = true;
} }
void Canvas::DrawRect(Rect const& rect) void Canvas::DrawRect(Rect const& rect)
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(stroke_brush_); ctx_->SetCurrentBrush(stroke_brush_);
ctx_->DrawRectangle(rect, stroke_width_, stroke_style_); ctx_->DrawRectangle(rect, stroke_style_, stroke_width_);
cache_expired_ = true; cache_expired_ = true;
} }
void Canvas::DrawRoundedRect(Rect const& rect, Vec2 const& radius) void Canvas::DrawRoundedRect(Rect const& rect, Vec2 const& radius)
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(stroke_brush_); ctx_->SetCurrentBrush(stroke_brush_);
ctx_->DrawRoundedRectangle(rect, radius, stroke_width_, stroke_style_); ctx_->DrawRoundedRectangle(rect, radius, stroke_style_, stroke_width_);
cache_expired_ = true; cache_expired_ = true;
} }
void Canvas::FillShape(ShapePtr shape) void Canvas::FillShape(ShapePtr shape)
{ {
if (!shape) KGE_ASSERT(ctx_);
return; if (shape)
{
InitRenderTargetAndBrushs(); ctx_->SetCurrentBrush(fill_brush_);
ctx_->SetCurrentBrush(fill_brush_); ctx_->FillShape(*shape);
ctx_->FillShape(*shape); cache_expired_ = true;
cache_expired_ = true; }
} }
void Canvas::FillCircle(Point const& center, float radius) void Canvas::FillCircle(Point const& center, float radius)
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(fill_brush_); ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillEllipse(center, Vec2(radius, radius)); ctx_->FillEllipse(center, Vec2(radius, radius));
cache_expired_ = true; cache_expired_ = true;
@ -185,7 +191,7 @@ void Canvas::FillCircle(Point const& center, float radius)
void Canvas::FillEllipse(Point const& center, Vec2 const& radius) void Canvas::FillEllipse(Point const& center, Vec2 const& radius)
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(fill_brush_); ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillEllipse(center, radius); ctx_->FillEllipse(center, radius);
cache_expired_ = true; cache_expired_ = true;
@ -193,7 +199,7 @@ void Canvas::FillEllipse(Point const& center, Vec2 const& radius)
void Canvas::FillRect(Rect const& rect) void Canvas::FillRect(Rect const& rect)
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(fill_brush_); ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillRectangle(rect); ctx_->FillRectangle(rect);
cache_expired_ = true; cache_expired_ = true;
@ -201,7 +207,7 @@ void Canvas::FillRect(Rect const& rect)
void Canvas::FillRoundedRect(Rect const& rect, Vec2 const& radius) void Canvas::FillRoundedRect(Rect const& rect, Vec2 const& radius)
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(fill_brush_); ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillRoundedRectangle(rect, radius); ctx_->FillRoundedRectangle(rect, radius);
cache_expired_ = true; cache_expired_ = true;
@ -209,9 +215,9 @@ void Canvas::FillRoundedRect(Rect const& rect, Vec2 const& radius)
void Canvas::DrawTexture(TexturePtr texture, const Rect* src_rect, const Rect* dest_rect) void Canvas::DrawTexture(TexturePtr texture, const Rect* src_rect, const Rect* dest_rect)
{ {
KGE_ASSERT(ctx_);
if (texture) if (texture)
{ {
InitRenderTargetAndBrushs();
ctx_->DrawTexture(*texture, src_rect, dest_rect); ctx_->DrawTexture(*texture, src_rect, dest_rect);
cache_expired_ = true; cache_expired_ = true;
} }
@ -230,7 +236,7 @@ void Canvas::DrawTextLayout(String const& text, Point const& point)
void Canvas::DrawTextLayout(TextLayout const& layout, Point const& point) void Canvas::DrawTextLayout(TextLayout const& layout, Point const& point)
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->DrawTextLayout(layout, point); ctx_->DrawTextLayout(layout, point);
} }
@ -266,15 +272,15 @@ void Canvas::AddArc(Point const& point, Size const& radius, float rotation, bool
void Canvas::StrokePath() void Canvas::StrokePath()
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(stroke_brush_); ctx_->SetCurrentBrush(stroke_brush_);
ctx_->DrawShape(*shape_sink_.GetShape(), stroke_width_, stroke_style_); ctx_->DrawShape(*shape_sink_.GetShape(), stroke_style_, stroke_width_);
cache_expired_ = true; cache_expired_ = true;
} }
void Canvas::FillPath() void Canvas::FillPath()
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->SetCurrentBrush(fill_brush_); ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillShape(*shape_sink_.GetShape()); ctx_->FillShape(*shape_sink_.GetShape());
cache_expired_ = true; cache_expired_ = true;
@ -282,44 +288,29 @@ void Canvas::FillPath()
void Canvas::Clear() void Canvas::Clear()
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->Clear(); ctx_->Clear();
cache_expired_ = true; cache_expired_ = true;
} }
void Canvas::Clear(Color const& clear_color) void Canvas::Clear(Color const& clear_color)
{ {
InitRenderTargetAndBrushs(); KGE_ASSERT(ctx_);
ctx_->Clear(clear_color); ctx_->Clear(clear_color);
cache_expired_ = true; cache_expired_ = true;
} }
void Canvas::ResizeAndClear(Size size)
{
ctx_ = TextureRenderContext::Create(size);
}
TexturePtr Canvas::ExportToTexture() const TexturePtr Canvas::ExportToTexture() const
{ {
UpdateCache(); UpdateCache();
return texture_cached_; return texture_cached_;
} }
void Canvas::InitRenderTargetAndBrushs()
{
if (!ctx_)
{
Renderer::Instance().CreateTextureRenderTarget(ctx_);
}
if (!stroke_brush_)
{
stroke_brush_ = new Brush;
stroke_brush_->SetColor(Color::White);
}
if (!fill_brush_)
{
fill_brush_ = new Brush;
fill_brush_->SetColor(Color::White);
}
}
void Canvas::UpdateCache() const void Canvas::UpdateCache() const
{ {
if (cache_expired_ && ctx_) if (cache_expired_ && ctx_)

View File

@ -21,7 +21,7 @@
#pragma once #pragma once
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>
#include <kiwano/render/ShapeSink.h> #include <kiwano/render/ShapeSink.h>
#include <kiwano/render/RenderContext.h> #include <kiwano/render/TextureRenderContext.h>
namespace kiwano namespace kiwano
{ {
@ -35,20 +35,16 @@ KGE_DECLARE_SMART_PTR(Canvas);
/** /**
* \~chinese * \~chinese
* @brief * @brief
* @details
*/ */
class KGE_API Canvas : public Actor class KGE_API Canvas : public Actor
{ {
public: public:
/// \~chinese /// \~chinese
/// @brief 创建画布 /// @brief 创建画布
static CanvasPtr Create(); /// @param size 画布大小
static CanvasPtr Create(Size const& size);
/// \~chinese
/// @brief 构建空画布
Canvas();
virtual ~Canvas();
/// \~chinese /// \~chinese
/// @brief 开始绘图 /// @brief 开始绘图
@ -272,6 +268,10 @@ public:
/// @brief 获取轮廓画刷 /// @brief 获取轮廓画刷
BrushPtr GetStrokeBrush() const; BrushPtr GetStrokeBrush() const;
/// \~chinese
/// @brief 清空画布大小并重设画布大小
void ResizeAndClear(Size size);
/// \~chinese /// \~chinese
/// @brief 导出纹理 /// @brief 导出纹理
TexturePtr ExportToTexture() const; TexturePtr ExportToTexture() const;
@ -279,7 +279,7 @@ public:
void OnRender(RenderContext& ctx) override; void OnRender(RenderContext& ctx) override;
private: private:
void InitRenderTargetAndBrushs(); Canvas();
void UpdateCache() const; void UpdateCache() const;
@ -298,6 +298,11 @@ private:
/** @} */ /** @} */
inline float Canvas::GetStrokeWidth() const
{
return stroke_width_;
}
inline void Canvas::SetStrokeWidth(float width) inline void Canvas::SetStrokeWidth(float width)
{ {
stroke_width_ = std::max(width, 0.f); stroke_width_ = std::max(width, 0.f);
@ -315,13 +320,19 @@ inline void Canvas::SetTextStyle(TextStyle const& text_style)
inline void Canvas::SetStrokeColor(Color const& color) inline void Canvas::SetStrokeColor(Color const& color)
{ {
InitRenderTargetAndBrushs(); if (!stroke_brush_)
{
stroke_brush_ = new Brush;
}
stroke_brush_->SetColor(color); stroke_brush_->SetColor(color);
} }
inline void Canvas::SetFillColor(Color const& color) inline void Canvas::SetFillColor(Color const& color)
{ {
InitRenderTargetAndBrushs(); if (!fill_brush_)
{
fill_brush_ = new Brush;
}
fill_brush_->SetColor(color); fill_brush_->SetColor(color);
} }
@ -344,4 +355,5 @@ inline BrushPtr Canvas::GetStrokeBrush() const
{ {
return stroke_brush_; return stroke_brush_;
} }
} // namespace kiwano } // namespace kiwano

View File

@ -87,14 +87,14 @@ bool GifSprite::Load(GifImagePtr gif)
loop_count_ = 0; loop_count_ = 0;
frame_ = GifImage::Frame(); frame_ = GifImage::Frame();
SetSize(float(gif_->GetWidthInPixels()), float(gif_->GetHeightInPixels()));
if (!frame_rt_) if (!frame_rt_)
{ {
Size frame_size = GetSize(); Size frame_size = Size(float(gif_->GetWidthInPixels()), float(gif_->GetHeightInPixels()));
Renderer::Instance().CreateTextureRenderTarget(frame_rt_, &frame_size); frame_rt_ = TextureRenderContext::Create(frame_size);
} }
SetSize(frame_rt_->GetSize());
if (gif_->GetFramesCount() > 0) if (gif_->GetFramesCount() > 0)
{ {
ComposeNextFrame(); ComposeNextFrame();

View File

@ -22,7 +22,7 @@
#include <kiwano/2d/Actor.h> #include <kiwano/2d/Actor.h>
#include <kiwano/core/Resource.h> #include <kiwano/core/Resource.h>
#include <kiwano/render/GifImage.h> #include <kiwano/render/GifImage.h>
#include <kiwano/render/RenderContext.h> #include <kiwano/render/TextureRenderContext.h>
namespace kiwano namespace kiwano
{ {

View File

@ -91,7 +91,7 @@ void ShapeActor::OnRender(RenderContext& ctx)
if (stroke_brush_) if (stroke_brush_)
{ {
ctx.SetCurrentBrush(stroke_brush_); ctx.SetCurrentBrush(stroke_brush_);
ctx.DrawShape(*shape_, stroke_width_ * 2 /* twice width for widening */, stroke_style_); ctx.DrawShape(*shape_, stroke_style_, stroke_width_ * 2 /* twice width for widening */);
} }
if (fill_brush_) if (fill_brush_)

View File

@ -23,9 +23,6 @@
namespace kiwano namespace kiwano
{ {
//
// RenderContext
//
RenderContext::RenderContext() RenderContext::RenderContext()
: collecting_status_(false) : collecting_status_(false)
@ -101,152 +98,6 @@ void RenderContext::EndDraw()
} }
} }
void RenderContext::DrawShape(Shape const& shape, float stroke_width, StrokeStylePtr stroke)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
if (shape.IsValid())
{
if (stroke)
{
render_target_->DrawGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get(), stroke_width,
stroke->GetStrokeStyle().get());
}
else
{
render_target_->DrawGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get(), stroke_width,
nullptr);
}
IncreasePrimitivesCount();
}
}
void RenderContext::FillShape(Shape const& shape)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
if (shape.IsValid())
{
render_target_->FillGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get());
IncreasePrimitivesCount();
}
}
void RenderContext::DrawLine(Point const& point1, Point const& point2, float stroke_width, StrokeStylePtr stroke)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
if (stroke)
{
render_target_->DrawLine(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2),
current_brush_->GetBrush().get(), stroke_width, stroke->GetStrokeStyle().get());
}
else
{
render_target_->DrawLine(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2),
current_brush_->GetBrush().get(), stroke_width, nullptr);
}
IncreasePrimitivesCount();
}
void RenderContext::DrawRectangle(Rect const& rect, float stroke_width, StrokeStylePtr stroke)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
if (stroke)
{
render_target_->DrawRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get(), stroke_width,
stroke->GetStrokeStyle().get());
}
else
{
render_target_->DrawRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get(), stroke_width,
nullptr);
}
IncreasePrimitivesCount();
}
void RenderContext::FillRectangle(Rect const& rect)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
render_target_->FillRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get());
IncreasePrimitivesCount();
}
void RenderContext::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, float stroke_width,
StrokeStylePtr stroke)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
if (stroke)
{
render_target_->DrawRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y),
current_brush_->GetBrush().get(), stroke_width,
stroke->GetStrokeStyle().get());
}
else
{
render_target_->DrawRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y),
current_brush_->GetBrush().get(), stroke_width, nullptr);
}
IncreasePrimitivesCount();
}
void RenderContext::FillRoundedRectangle(Rect const& rect, Vec2 const& radius)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
render_target_->FillRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y),
current_brush_->GetBrush().get());
IncreasePrimitivesCount();
}
void RenderContext::DrawEllipse(Point const& center, Vec2 const& radius, float stroke_width, StrokeStylePtr stroke)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
if (stroke)
{
render_target_->DrawEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y),
current_brush_->GetBrush().get(), stroke_width, stroke->GetStrokeStyle().get());
}
else
{
render_target_->DrawEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y),
current_brush_->GetBrush().get(), stroke_width, nullptr);
}
IncreasePrimitivesCount();
}
void RenderContext::FillEllipse(Point const& center, Vec2 const& radius)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
render_target_->FillEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y),
current_brush_->GetBrush().get());
IncreasePrimitivesCount();
}
void RenderContext::DrawTexture(Texture const& texture, Rect const& src_rect, Rect const& dest_rect) void RenderContext::DrawTexture(Texture const& texture, Rect const& src_rect, Rect const& dest_rect)
{ {
DrawTexture(texture, &src_rect, &dest_rect); DrawTexture(texture, &src_rect, &dest_rect);
@ -316,6 +167,150 @@ void RenderContext::DrawTextLayout(TextLayout const& layout, Point const& offset
} }
} }
void RenderContext::DrawShape(Shape const& shape, StrokeStylePtr stroke, float stroke_width)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
if (shape.IsValid())
{
if (stroke)
{
render_target_->DrawGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get(), stroke_width,
stroke->GetStrokeStyle().get());
}
else
{
render_target_->DrawGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get(), stroke_width,
nullptr);
}
IncreasePrimitivesCount();
}
}
void RenderContext::DrawLine(Point const& point1, Point const& point2, StrokeStylePtr stroke, float stroke_width)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
if (stroke)
{
render_target_->DrawLine(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2),
current_brush_->GetBrush().get(), stroke_width, stroke->GetStrokeStyle().get());
}
else
{
render_target_->DrawLine(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2),
current_brush_->GetBrush().get(), stroke_width, nullptr);
}
IncreasePrimitivesCount();
}
void RenderContext::DrawRectangle(Rect const& rect, StrokeStylePtr stroke, float stroke_width)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
if (stroke)
{
render_target_->DrawRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get(), stroke_width,
stroke->GetStrokeStyle().get());
}
else
{
render_target_->DrawRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get(), stroke_width,
nullptr);
}
IncreasePrimitivesCount();
}
void RenderContext::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, StrokeStylePtr stroke,
float stroke_width)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
if (stroke)
{
render_target_->DrawRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y),
current_brush_->GetBrush().get(), stroke_width,
stroke->GetStrokeStyle().get());
}
else
{
render_target_->DrawRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y),
current_brush_->GetBrush().get(), stroke_width, nullptr);
}
IncreasePrimitivesCount();
}
void RenderContext::DrawEllipse(Point const& center, Vec2 const& radius, StrokeStylePtr stroke, float stroke_width)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
if (stroke)
{
render_target_->DrawEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y),
current_brush_->GetBrush().get(), stroke_width, stroke->GetStrokeStyle().get());
}
else
{
render_target_->DrawEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y),
current_brush_->GetBrush().get(), stroke_width, nullptr);
}
IncreasePrimitivesCount();
}
void RenderContext::FillShape(Shape const& shape)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
if (shape.IsValid())
{
render_target_->FillGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get());
IncreasePrimitivesCount();
}
}
void RenderContext::FillRectangle(Rect const& rect)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
render_target_->FillRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get());
IncreasePrimitivesCount();
}
void RenderContext::FillRoundedRectangle(Rect const& rect, Vec2 const& radius)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
render_target_->FillRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y),
current_brush_->GetBrush().get());
IncreasePrimitivesCount();
}
void RenderContext::FillEllipse(Point const& center, Vec2 const& radius)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
render_target_->FillEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y),
current_brush_->GetBrush().get());
IncreasePrimitivesCount();
}
void RenderContext::CreateTexture(Texture& texture, math::Vec2T<uint32_t> size) void RenderContext::CreateTexture(Texture& texture, math::Vec2T<uint32_t> size)
{ {
KGE_ASSERT(render_target_ && "Render target has not been initialized!"); KGE_ASSERT(render_target_ && "Render target has not been initialized!");
@ -396,6 +391,15 @@ void RenderContext::Clear(Color const& clear_color)
render_target_->Clear(DX::ConvertToColorF(clear_color)); render_target_->Clear(DX::ConvertToColorF(clear_color));
} }
Size RenderContext::GetSize() const
{
if (render_target_)
{
return reinterpret_cast<const Size&>(render_target_->GetSize());
}
return Size();
}
void RenderContext::SetTransform(const Matrix3x2& matrix) void RenderContext::SetTransform(const Matrix3x2& matrix)
{ {
KGE_ASSERT(render_target_ && "Render target has not been initialized!"); KGE_ASSERT(render_target_ && "Render target has not been initialized!");
@ -508,28 +512,4 @@ void RenderContext::RestoreDrawingState()
} }
} }
//
// TextureRenderContext
//
TextureRenderContext::TextureRenderContext() {}
bool TextureRenderContext::GetOutput(Texture& texture)
{
HRESULT hr = E_FAIL;
if (bitmap_rt_)
{
ComPtr<ID2D1Bitmap> bitmap;
hr = bitmap_rt_->GetBitmap(&bitmap);
if (SUCCEEDED(hr))
{
texture.SetBitmap(bitmap);
}
}
return SUCCEEDED(hr);
}
} // namespace kiwano } // namespace kiwano

View File

@ -33,7 +33,6 @@ namespace kiwano
class Renderer; class Renderer;
KGE_DECLARE_SMART_PTR(RenderContext); KGE_DECLARE_SMART_PTR(RenderContext);
KGE_DECLARE_SMART_PTR(TextureRenderContext);
/** /**
* \addtogroup Render * \addtogroup Render
@ -64,120 +63,162 @@ public:
bool IsValid() const; bool IsValid() const;
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 开始渲染
void BeginDraw(); void BeginDraw();
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 结束渲染
void EndDraw(); void EndDraw();
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 绘制纹理
void DrawShape(Shape const& shape, float stroke_width, StrokeStylePtr stroke = nullptr); /// @param texture 纹理
/// @param src_rect 源纹理裁剪矩形
/// \~chinese /// @param dest_rect 绘制的目标区域
/// @brief 是否有效
void FillShape(Shape const& shape);
/// \~chinese
/// @brief 是否有效
void DrawLine(Point const& point1, Point const& point2, float stroke_width, StrokeStylePtr stroke = nullptr);
/// \~chinese
/// @brief 是否有效
void DrawRectangle(Rect const& rect, float stroke_width, StrokeStylePtr stroke = nullptr);
/// \~chinese
/// @brief 是否有效
void FillRectangle(Rect const& rect);
/// \~chinese
/// @brief 是否有效
void DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, float stroke_width,
StrokeStylePtr stroke = nullptr);
/// \~chinese
/// @brief 是否有效
void FillRoundedRectangle(Rect const& rect, Vec2 const& radius);
/// \~chinese
/// @brief 是否有效
void DrawEllipse(Point const& center, Vec2 const& radius, float stroke_width, StrokeStylePtr stroke = nullptr);
/// \~chinese
/// @brief 是否有效
void FillEllipse(Point const& center, Vec2 const& radius);
/// \~chinese
/// @brief 是否有效
void DrawTexture(Texture const& texture, Rect const& src_rect, Rect const& dest_rect); void DrawTexture(Texture const& texture, Rect const& src_rect, Rect const& dest_rect);
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 绘制纹理
/// @param texture 纹理
/// @param src_rect 源纹理裁剪矩形
/// @param dest_rect 绘制的目标区域
void DrawTexture(Texture const& texture, const Rect* src_rect = nullptr, const Rect* dest_rect = nullptr); void DrawTexture(Texture const& texture, const Rect* src_rect = nullptr, const Rect* dest_rect = nullptr);
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 绘制文本布局
void DrawTextLayout(TextLayout const& layout, Point const& offset = Point{}); /// @param layout 文本布局
/// @param offset 偏移量
void DrawTextLayout(TextLayout const& layout, Point const& offset = Point());
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 绘制形状轮廓
/// @param shape 形状
/// @param stroke 线条样式
/// @param stroke_width 线条宽度
void DrawShape(Shape const& shape, StrokeStylePtr stroke = nullptr, float stroke_width = 1.0f);
/// \~chinese
/// @brief 绘制线段
/// @param point1 线段起点
/// @param point2 线段终点
/// @param stroke 线条样式
/// @param stroke_width 线条宽度
void DrawLine(Point const& point1, Point const& point2, StrokeStylePtr stroke = nullptr, float stroke_width = 1.0f);
/// \~chinese
/// @brief 绘制矩形边框
/// @param rect 矩形
/// @param stroke 线条样式
/// @param stroke_width 线条宽度
void DrawRectangle(Rect const& rect, StrokeStylePtr stroke = nullptr, float stroke_width = 1.0f);
/// \~chinese
/// @brief 绘制圆角矩形边框
/// @param rect 矩形
/// @param radius 圆角半径
/// @param stroke 线条样式
/// @param stroke_width 线条宽度
void DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, StrokeStylePtr stroke = nullptr,
float stroke_width = 1.0f);
/// \~chinese
/// @brief 绘制椭圆边框
/// @param center 圆心
/// @param radius 椭圆半径
/// @param stroke 线条样式
/// @param stroke_width 线条宽度
void DrawEllipse(Point const& center, Vec2 const& radius, StrokeStylePtr stroke = nullptr,
float stroke_width = 1.0f);
/// \~chinese
/// @brief 填充形状
/// @param shape 形状
void FillShape(Shape const& shape);
/// \~chinese
/// @brief 填充矩形
/// @param rect 矩形
void FillRectangle(Rect const& rect);
/// \~chinese
/// @brief 填充圆角矩形
/// @param rect 矩形
/// @param radius 圆角半径
void FillRoundedRectangle(Rect const& rect, Vec2 const& radius);
/// \~chinese
/// @brief 填充椭圆
/// @param center 圆心
/// @param radius 椭圆半径
void FillEllipse(Point const& center, Vec2 const& radius);
/// \~chinese
/// @brief 创建纹理
/// @param texture 纹理
/// @param size 纹理像素大小
void CreateTexture(Texture& texture, math::Vec2T<uint32_t> size); void CreateTexture(Texture& texture, math::Vec2T<uint32_t> size);
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 设置绘制的裁剪区域
/// @param clip_rect 裁剪矩形
void PushClipRect(Rect const& clip_rect); void PushClipRect(Rect const& clip_rect);
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 取消上一次设置的绘制裁剪区域
void PopClipRect(); void PopClipRect();
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 设置图层区域
/// @param layer 图层区域
void PushLayer(LayerArea& layer); void PushLayer(LayerArea& layer);
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 取消上一次设置的图层区域
void PopLayer(); void PopLayer();
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 清空渲染内容
void Clear(); void Clear();
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 使用纯色清空渲染内容
/// @param clear_color 清屏颜色
void Clear(Color const& clear_color); void Clear(Color const& clear_color);
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 获取渲染区域大小
Size GetSize() const;
/// \~chinese
/// @brief 获取画刷透明度
float GetBrushOpacity() const; float GetBrushOpacity() const;
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 获取当前画刷
BrushPtr GetCurrentBrush() const; BrushPtr GetCurrentBrush() const;
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 获取全局二维变换
Matrix3x2 GetGlobalTransform() const; Matrix3x2 GetGlobalTransform() const;
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 设置画刷透明度
void SetBrushOpacity(float opacity); void SetBrushOpacity(float opacity);
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 设置当前画刷
void SetCurrentBrush(BrushPtr brush); void SetCurrentBrush(BrushPtr brush);
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 设置上下文的二维变换
void SetTransform(const Matrix3x2& matrix); void SetTransform(const Matrix3x2& matrix);
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 设置全局二维变换
void SetGlobalTransform(const Matrix3x2& matrix); void SetGlobalTransform(const Matrix3x2& matrix);
/// \~chinese /// \~chinese
/// @brief 是否有效 /// @brief 设置全局二维变换
void SetGlobalTransform(const Matrix3x2* matrix); void SetGlobalTransform(const Matrix3x2* matrix);
/// \~chinese /// \~chinese
@ -260,35 +301,6 @@ private:
ComPtr<ID2D1DrawingStateBlock> drawing_state_; ComPtr<ID2D1DrawingStateBlock> drawing_state_;
}; };
/// \~chinese
/// @brief 纹理渲染上下文
/// @details 纹理渲染上下文将渲染输出到一个纹理对象中
class KGE_API TextureRenderContext : public RenderContext
{
friend class Renderer;
public:
/// \~chinese
/// @brief 是否有效
bool IsValid() const;
/// \~chinese
/// @brief 获取渲染输出
/// @param[out] texture 纹理输出
/// @return 操作是否成功
bool GetOutput(Texture& texture);
private:
TextureRenderContext();
ComPtr<ID2D1BitmapRenderTarget> GetBitmapRenderTarget() const;
void SetBitmapRenderTarget(ComPtr<ID2D1BitmapRenderTarget> ctx);
private:
ComPtr<ID2D1BitmapRenderTarget> bitmap_rt_;
};
/** @} */ /** @} */
inline RenderContext::Status::Status() inline RenderContext::Status::Status()
@ -347,18 +359,4 @@ inline void RenderContext::SetCurrentBrush(BrushPtr brush)
} }
} }
inline bool TextureRenderContext::IsValid() const
{
return bitmap_rt_ != nullptr;
}
inline ComPtr<ID2D1BitmapRenderTarget> TextureRenderContext::GetBitmapRenderTarget() const
{
return bitmap_rt_;
}
inline void TextureRenderContext::SetBitmapRenderTarget(ComPtr<ID2D1BitmapRenderTarget> ctx)
{
bitmap_rt_ = ctx;
}
} // namespace kiwano } // namespace kiwano

View File

@ -751,7 +751,7 @@ void Renderer::CreateShapeSink(ShapeSink& sink)
win32::ThrowIfFailed(hr); win32::ThrowIfFailed(hr);
} }
void Renderer::CreateTextureRenderTarget(TextureRenderContextPtr& render_context, const Size* desired_size) void Renderer::CreateTextureRenderContext(TextureRenderContext& render_context, const Size* desired_size)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
if (!d2d_res_) if (!d2d_res_)
@ -759,8 +759,6 @@ void Renderer::CreateTextureRenderTarget(TextureRenderContextPtr& render_context
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
TextureRenderContextPtr output = new TextureRenderContext;
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
ComPtr<ID2D1BitmapRenderTarget> bitmap_rt; ComPtr<ID2D1BitmapRenderTarget> bitmap_rt;
@ -777,20 +775,15 @@ void Renderer::CreateTextureRenderTarget(TextureRenderContextPtr& render_context
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = output->CreateDeviceResources(d2d_res_->GetFactory(), bitmap_rt); hr = render_context.CreateDeviceResources(d2d_res_->GetFactory(), bitmap_rt);
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
output->SetBitmapRenderTarget(bitmap_rt); render_context.SetBitmapRenderTarget(bitmap_rt);
} }
} }
if (SUCCEEDED(hr))
{
render_context = output;
}
win32::ThrowIfFailed(hr); win32::ThrowIfFailed(hr);
} }

View File

@ -23,8 +23,9 @@
#include <kiwano/platform/Window.h> #include <kiwano/platform/Window.h>
#include <kiwano/render/Font.h> #include <kiwano/render/Font.h>
#include <kiwano/render/GifImage.h> #include <kiwano/render/GifImage.h>
#include <kiwano/render/RenderContext.h>
#include <kiwano/render/TextStyle.hpp> #include <kiwano/render/TextStyle.hpp>
#include <kiwano/render/RenderContext.h>
#include <kiwano/render/TextureRenderContext.h>
#include <kiwano/render/DirectX/FontCollectionLoader.h> #include <kiwano/render/DirectX/FontCollectionLoader.h>
#if defined(KGE_USE_DIRECTX10) #if defined(KGE_USE_DIRECTX10)
@ -168,7 +169,7 @@ public:
/// @brief 创建纹理渲染上下文 /// @brief 创建纹理渲染上下文
/// @param[out] render_context 渲染上下文 /// @param[out] render_context 渲染上下文
/// @param[in] desired_size 期望的输出大小 /// @param[in] desired_size 期望的输出大小
void CreateTextureRenderTarget(TextureRenderContextPtr& render_context, const Size* desired_size = nullptr); void CreateTextureRenderContext(TextureRenderContext& render_context, const Size* desired_size = nullptr);
/// \~chinese /// \~chinese
/// @brief 创建纯色画刷 /// @brief 创建纯色画刷

View File

@ -0,0 +1,82 @@
// Copyright (c) 2016-2019 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <kiwano/core/Logger.h>
#include <kiwano/render/TextureRenderContext.h>
#include <kiwano/render/Renderer.h>
namespace kiwano
{
TextureRenderContextPtr TextureRenderContext::Create()
{
TextureRenderContextPtr ptr = new TextureRenderContext;
if (ptr)
{
try
{
Renderer::Instance().CreateTextureRenderContext(*ptr);
}
catch (std::exception)
{
return nullptr;
}
}
return ptr;
}
TextureRenderContextPtr TextureRenderContext::Create(Size const& desired_size)
{
TextureRenderContextPtr ptr = new TextureRenderContext;
if (ptr)
{
try
{
Renderer::Instance().CreateTextureRenderContext(*ptr, &desired_size);
}
catch (std::exception)
{
return nullptr;
}
}
return ptr;
}
TextureRenderContext::TextureRenderContext() {}
bool TextureRenderContext::GetOutput(Texture& texture)
{
HRESULT hr = E_FAIL;
if (bitmap_rt_)
{
ComPtr<ID2D1Bitmap> bitmap;
hr = bitmap_rt_->GetBitmap(&bitmap);
if (SUCCEEDED(hr))
{
texture.SetBitmap(bitmap);
}
}
return SUCCEEDED(hr);
}
} // namespace kiwano

View File

@ -0,0 +1,89 @@
// Copyright (c) 2016-2019 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <kiwano/render/RenderContext.h>
namespace kiwano
{
class Renderer;
KGE_DECLARE_SMART_PTR(TextureRenderContext);
/**
* \addtogroup Render
* @{
*/
/// \~chinese
/// @brief 纹理渲染上下文
/// @details 纹理渲染上下文将渲染输出到一个纹理对象中
class KGE_API TextureRenderContext : public RenderContext
{
friend class Renderer;
public:
/// \~chinese
/// @brief 创建纹理渲染上下文
static TextureRenderContextPtr Create();
/// \~chinese
/// @brief 创建纹理渲染上下文
/// @param size 期望的输出大小
static TextureRenderContextPtr Create(Size const& desired_size);
/// \~chinese
/// @brief 是否有效
bool IsValid() const;
/// \~chinese
/// @brief 获取渲染输出
/// @param[out] texture 纹理输出
/// @return 操作是否成功
bool GetOutput(Texture& texture);
private:
TextureRenderContext();
ComPtr<ID2D1BitmapRenderTarget> GetBitmapRenderTarget() const;
void SetBitmapRenderTarget(ComPtr<ID2D1BitmapRenderTarget> ctx);
private:
ComPtr<ID2D1BitmapRenderTarget> bitmap_rt_;
};
/** @} */
inline bool TextureRenderContext::IsValid() const
{
return bitmap_rt_ != nullptr;
}
inline ComPtr<ID2D1BitmapRenderTarget> TextureRenderContext::GetBitmapRenderTarget() const
{
return bitmap_rt_;
}
inline void TextureRenderContext::SetBitmapRenderTarget(ComPtr<ID2D1BitmapRenderTarget> ctx)
{
bitmap_rt_ = ctx;
}
} // namespace kiwano