diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj
index 86570ca7..f544ab77 100644
--- a/projects/kiwano/kiwano.vcxproj
+++ b/projects/kiwano/kiwano.vcxproj
@@ -84,6 +84,7 @@
+
@@ -151,6 +152,7 @@
+
diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters
index 4500b9b2..007fb85b 100644
--- a/projects/kiwano/kiwano.vcxproj.filters
+++ b/projects/kiwano/kiwano.vcxproj.filters
@@ -285,6 +285,9 @@
math
+
+ render
+
@@ -482,5 +485,8 @@
render
+
+ render
+
\ No newline at end of file
diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp
index 141d2fa6..faafeb80 100644
--- a/src/kiwano/2d/Actor.cpp
+++ b/src/kiwano/2d/Actor.cpp
@@ -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())
diff --git a/src/kiwano/2d/Canvas.cpp b/src/kiwano/2d/Canvas.cpp
index 1905fece..eb7715a6 100644
--- a/src/kiwano/2d/Canvas.cpp
+++ b/src/kiwano/2d/Canvas.cpp
@@ -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();
- ctx_->SetCurrentBrush(stroke_brush_);
- ctx_->DrawShape(*shape, stroke_width_, stroke_style_);
- cache_expired_ = true;
+ KGE_ASSERT(ctx_);
+ if (shape)
+ {
+ ctx_->SetCurrentBrush(stroke_brush_);
+ 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();
- ctx_->SetCurrentBrush(fill_brush_);
- ctx_->FillShape(*shape);
- cache_expired_ = true;
+ 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_)
diff --git a/src/kiwano/2d/Canvas.h b/src/kiwano/2d/Canvas.h
index 900aa6d3..fcc34ade 100644
--- a/src/kiwano/2d/Canvas.h
+++ b/src/kiwano/2d/Canvas.h
@@ -21,7 +21,7 @@
#pragma once
#include
#include
-#include
+#include
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
diff --git a/src/kiwano/2d/GifSprite.cpp b/src/kiwano/2d/GifSprite.cpp
index b8296d2d..a3575f7a 100644
--- a/src/kiwano/2d/GifSprite.cpp
+++ b/src/kiwano/2d/GifSprite.cpp
@@ -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();
diff --git a/src/kiwano/2d/GifSprite.h b/src/kiwano/2d/GifSprite.h
index 7b6de011..145f7af4 100644
--- a/src/kiwano/2d/GifSprite.h
+++ b/src/kiwano/2d/GifSprite.h
@@ -22,7 +22,7 @@
#include
#include
#include
-#include
+#include
namespace kiwano
{
diff --git a/src/kiwano/2d/ShapeActor.cpp b/src/kiwano/2d/ShapeActor.cpp
index 34f0074d..ceebe316 100644
--- a/src/kiwano/2d/ShapeActor.cpp
+++ b/src/kiwano/2d/ShapeActor.cpp
@@ -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_)
diff --git a/src/kiwano/render/RenderContext.cpp b/src/kiwano/render/RenderContext.cpp
index e8db988b..e2376083 100644
--- a/src/kiwano/render/RenderContext.cpp
+++ b/src/kiwano/render/RenderContext.cpp
@@ -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 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(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 bitmap;
-
- hr = bitmap_rt_->GetBitmap(&bitmap);
-
- if (SUCCEEDED(hr))
- {
- texture.SetBitmap(bitmap);
- }
- }
- return SUCCEEDED(hr);
-}
-
} // namespace kiwano
diff --git a/src/kiwano/render/RenderContext.h b/src/kiwano/render/RenderContext.h
index ae908a68..6f45f207 100644
--- a/src/kiwano/render/RenderContext.h
+++ b/src/kiwano/render/RenderContext.h
@@ -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 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 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 GetBitmapRenderTarget() const;
-
- void SetBitmapRenderTarget(ComPtr ctx);
-
-private:
- ComPtr 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 TextureRenderContext::GetBitmapRenderTarget() const
-{
- return bitmap_rt_;
-}
-
-inline void TextureRenderContext::SetBitmapRenderTarget(ComPtr ctx)
-{
- bitmap_rt_ = ctx;
-}
} // namespace kiwano
diff --git a/src/kiwano/render/Renderer.cpp b/src/kiwano/render/Renderer.cpp
index 4d1652e8..9f01f0c0 100644
--- a/src/kiwano/render/Renderer.cpp
+++ b/src/kiwano/render/Renderer.cpp
@@ -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 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);
}
diff --git a/src/kiwano/render/Renderer.h b/src/kiwano/render/Renderer.h
index d3d78a82..f5e9e756 100644
--- a/src/kiwano/render/Renderer.h
+++ b/src/kiwano/render/Renderer.h
@@ -23,8 +23,9 @@
#include
#include
#include
-#include
#include
+#include
+#include
#include
#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 创建纯色画刷
diff --git a/src/kiwano/render/TextureRenderContext.cpp b/src/kiwano/render/TextureRenderContext.cpp
new file mode 100644
index 00000000..e0c4e71c
--- /dev/null
+++ b/src/kiwano/render/TextureRenderContext.cpp
@@ -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
+#include
+#include
+
+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 bitmap;
+
+ hr = bitmap_rt_->GetBitmap(&bitmap);
+
+ if (SUCCEEDED(hr))
+ {
+ texture.SetBitmap(bitmap);
+ }
+ }
+ return SUCCEEDED(hr);
+}
+
+} // namespace kiwano
diff --git a/src/kiwano/render/TextureRenderContext.h b/src/kiwano/render/TextureRenderContext.h
new file mode 100644
index 00000000..ed412152
--- /dev/null
+++ b/src/kiwano/render/TextureRenderContext.h
@@ -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
+
+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 GetBitmapRenderTarget() const;
+
+ void SetBitmapRenderTarget(ComPtr ctx);
+
+private:
+ ComPtr bitmap_rt_;
+};
+
+/** @} */
+
+inline bool TextureRenderContext::IsValid() const
+{
+ return bitmap_rt_ != nullptr;
+}
+
+inline ComPtr TextureRenderContext::GetBitmapRenderTarget() const
+{
+ return bitmap_rt_;
+}
+
+inline void TextureRenderContext::SetBitmapRenderTarget(ComPtr ctx)
+{
+ bitmap_rt_ = ctx;
+}
+} // namespace kiwano