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\Texture.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\ResourceCache.h" />
<ClInclude Include="..\..\src\kiwano\utils\UserData.h" />
@ -151,6 +152,7 @@
<ClCompile Include="..\..\src\kiwano\render\TextLayout.cpp" />
<ClCompile Include="..\..\src\kiwano\render\Texture.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\ResourceCache.cpp" />
<ClCompile Include="..\..\src\kiwano\utils\UserData.cpp" />

View File

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

View File

@ -154,7 +154,7 @@ void Actor::RenderBorder(RenderContext& ctx)
ctx.FillRectangle(bounds);
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())

View File

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

View File

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

View File

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

View File

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

View File

@ -91,7 +91,7 @@ void ShapeActor::OnRender(RenderContext& ctx)
if (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_)

View File

@ -23,9 +23,6 @@
namespace kiwano
{
//
// RenderContext
//
RenderContext::RenderContext()
: 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)
{
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)
{
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));
}
Size RenderContext::GetSize() const
{
if (render_target_)
{
return reinterpret_cast<const Size&>(render_target_->GetSize());
}
return Size();
}
void RenderContext::SetTransform(const Matrix3x2& matrix)
{
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
@ -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

View File

@ -33,7 +33,6 @@ namespace kiwano
class Renderer;
KGE_DECLARE_SMART_PTR(RenderContext);
KGE_DECLARE_SMART_PTR(TextureRenderContext);
/**
* \addtogroup Render
@ -64,120 +63,162 @@ public:
bool IsValid() const;
/// \~chinese
/// @brief 是否有效
/// @brief 开始渲染
void BeginDraw();
/// \~chinese
/// @brief 是否有效
/// @brief 结束渲染
void EndDraw();
/// \~chinese
/// @brief 是否有效
void DrawShape(Shape const& shape, float stroke_width, StrokeStylePtr stroke = nullptr);
/// \~chinese
/// @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 是否有效
/// @brief 绘制纹理
/// @param texture 纹理
/// @param src_rect 源纹理裁剪矩形
/// @param dest_rect 绘制的目标区域
void DrawTexture(Texture const& texture, Rect const& src_rect, Rect const& dest_rect);
/// \~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);
/// \~chinese
/// @brief 是否有效
void DrawTextLayout(TextLayout const& layout, Point const& offset = Point{});
/// @brief 绘制文本布局
/// @param layout 文本布局
/// @param offset 偏移量
void DrawTextLayout(TextLayout const& layout, Point const& offset = Point());
/// \~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);
/// \~chinese
/// @brief 是否有效
/// @brief 设置绘制的裁剪区域
/// @param clip_rect 裁剪矩形
void PushClipRect(Rect const& clip_rect);
/// \~chinese
/// @brief 是否有效
/// @brief 取消上一次设置的绘制裁剪区域
void PopClipRect();
/// \~chinese
/// @brief 是否有效
/// @brief 设置图层区域
/// @param layer 图层区域
void PushLayer(LayerArea& layer);
/// \~chinese
/// @brief 是否有效
/// @brief 取消上一次设置的图层区域
void PopLayer();
/// \~chinese
/// @brief 是否有效
/// @brief 清空渲染内容
void Clear();
/// \~chinese
/// @brief 是否有效
/// @brief 使用纯色清空渲染内容
/// @param clear_color 清屏颜色
void Clear(Color const& clear_color);
/// \~chinese
/// @brief 是否有效
/// @brief 获取渲染区域大小
Size GetSize() const;
/// \~chinese
/// @brief 获取画刷透明度
float GetBrushOpacity() const;
/// \~chinese
/// @brief 是否有效
/// @brief 获取当前画刷
BrushPtr GetCurrentBrush() const;
/// \~chinese
/// @brief 是否有效
/// @brief 获取全局二维变换
Matrix3x2 GetGlobalTransform() const;
/// \~chinese
/// @brief 是否有效
/// @brief 设置画刷透明度
void SetBrushOpacity(float opacity);
/// \~chinese
/// @brief 是否有效
/// @brief 设置当前画刷
void SetCurrentBrush(BrushPtr brush);
/// \~chinese
/// @brief 是否有效
/// @brief 设置上下文的二维变换
void SetTransform(const Matrix3x2& matrix);
/// \~chinese
/// @brief 是否有效
/// @brief 设置全局二维变换
void SetGlobalTransform(const Matrix3x2& matrix);
/// \~chinese
/// @brief 是否有效
/// @brief 设置全局二维变换
void SetGlobalTransform(const Matrix3x2* matrix);
/// \~chinese
@ -260,35 +301,6 @@ private:
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()
@ -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

View File

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

View File

@ -23,8 +23,9 @@
#include <kiwano/platform/Window.h>
#include <kiwano/render/Font.h>
#include <kiwano/render/GifImage.h>
#include <kiwano/render/RenderContext.h>
#include <kiwano/render/TextStyle.hpp>
#include <kiwano/render/RenderContext.h>
#include <kiwano/render/TextureRenderContext.h>
#include <kiwano/render/DirectX/FontCollectionLoader.h>
#if defined(KGE_USE_DIRECTX10)
@ -168,7 +169,7 @@ public:
/// @brief 创建纹理渲染上下文
/// @param[out] render_context 渲染上下文
/// @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
/// @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