From cdadb695e43469e90b703807115cc83e94eeb667 Mon Sep 17 00:00:00 2001 From: Nomango Date: Tue, 6 Oct 2020 00:14:27 +0800 Subject: [PATCH] [deploy] add CanvasRenderContext --- src/kiwano-physics/PhysicWorld.cpp | 26 +- src/kiwano/2d/Canvas.cpp | 62 ++-- src/kiwano/2d/Canvas.h | 459 ++++++++++++++++++++++++++++- 3 files changed, 510 insertions(+), 37 deletions(-) diff --git a/src/kiwano-physics/PhysicWorld.cpp b/src/kiwano-physics/PhysicWorld.cpp index acdd9ce4..6b0a3e37 100644 --- a/src/kiwano-physics/PhysicWorld.cpp +++ b/src/kiwano-physics/PhysicWorld.cpp @@ -34,9 +34,6 @@ public: canvas_ = MakePtr(size); ctx_ = canvas_->GetContext2D(); - fill_brush_ = MakePtr(Color::White); - line_brush_ = MakePtr(Color::White); - b2Draw::SetFlags(b2Draw::e_shapeBit | b2Draw::e_jointBit | b2Draw::e_jointBit | b2Draw::e_centerOfMassBit); } @@ -58,14 +55,12 @@ public: void SetFillColor(const b2Color& color) { - fill_brush_->SetColor(reinterpret_cast(color)); - ctx_->SetCurrentBrush(fill_brush_); + ctx_->SetFillColor(reinterpret_cast(color)); } void SetLineColor(const b2Color& color) { - line_brush_->SetColor(reinterpret_cast(color)); - ctx_->SetCurrentBrush(line_brush_); + ctx_->SetStrokeColor(reinterpret_cast(color)); } void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override @@ -83,16 +78,15 @@ public: void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override { - ShapeMaker maker; - maker.BeginPath(global::WorldToLocal(vertices[0])); - for (int32 i = 1; i < vertexCount; ++i) + Vector local_vertices; + for (int32 i = 0; i < vertexCount; ++i) { - maker.AddLine(global::WorldToLocal(vertices[i])); + local_vertices.push_back(global::WorldToLocal(vertices[i])); } - maker.EndPath(true); + ShapePtr polygon = Shape::CreatePolygon(local_vertices); SetFillColor(color); - ctx_->FillShape(*maker.GetShape()); + ctx_->FillShape(polygon); } void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color) override @@ -139,10 +133,8 @@ public: } private: - CanvasPtr canvas_; - RenderContextPtr ctx_; - BrushPtr fill_brush_; - BrushPtr line_brush_; + CanvasPtr canvas_; + CanvasRenderContextPtr ctx_; }; class DestructionListener : public b2DestructionListener diff --git a/src/kiwano/2d/Canvas.cpp b/src/kiwano/2d/Canvas.cpp index b12f8a7d..d857ce3a 100644 --- a/src/kiwano/2d/Canvas.cpp +++ b/src/kiwano/2d/Canvas.cpp @@ -23,36 +23,39 @@ namespace kiwano { +Canvas::Canvas() +{ + RecreateContext(nullptr); +} Canvas::Canvas(const Size& size) { - try - { - ResizeAndClear(size); - } - catch (Exception& e) - { - Fail(String("Canvas::ResizeAndClear failed: ") + e.what()); - } + ResizeAndClear(size); } -RenderContextPtr Canvas::GetContext2D() const +CanvasRenderContextPtr Canvas::GetContext2D() const { - return render_ctx_; -} - -void Canvas::OnRender(RenderContext& ctx) -{ - if (texture_cached_) - { - ctx.DrawTexture(*texture_cached_, nullptr, &GetBounds()); - } + CanvasRenderContextPtr ctx = new CanvasRenderContext(render_ctx_); + return ctx; } void Canvas::ResizeAndClear(Size size) +{ + RecreateContext(&size); +} + +void Canvas::RecreateContext(Size* size) { texture_cached_ = MakePtr(); - render_ctx_ = RenderContext::Create(*texture_cached_, size); + + if (size) + { + render_ctx_ = RenderContext::Create(*texture_cached_, *size); + } + else + { + render_ctx_ = RenderContext::Create(*texture_cached_); + } if (render_ctx_) { @@ -69,4 +72,25 @@ TexturePtr Canvas::ExportToTexture() const return texture_cached_; } +void Canvas::OnRender(RenderContext& ctx) +{ + if (texture_cached_) + { + ctx.DrawTexture(*texture_cached_, nullptr, &GetBounds()); + } +} + +CanvasRenderContext::CanvasRenderContext(RenderContextPtr ctx) + : ctx_(ctx) +{ + if (!ctx_) + { + Fail("CanvasRenderContext constructor failed"); + } +} + +CanvasRenderContext::~CanvasRenderContext() +{ +} + } // namespace kiwano diff --git a/src/kiwano/2d/Canvas.h b/src/kiwano/2d/Canvas.h index e625ec04..bcdda931 100644 --- a/src/kiwano/2d/Canvas.h +++ b/src/kiwano/2d/Canvas.h @@ -28,6 +28,7 @@ namespace kiwano { KGE_DECLARE_SMART_PTR(Canvas); +KGE_DECLARE_SMART_PTR(CanvasRenderContext); /** * \addtogroup Actors @@ -42,6 +43,8 @@ KGE_DECLARE_SMART_PTR(Canvas); class KGE_API Canvas : public Actor { public: + Canvas(); + /// \~chinese /// @brief 创建画布 /// @param size 画布大小 @@ -49,7 +52,7 @@ public: /// \~chinese /// @brief 获取2D绘图上下文 - RenderContextPtr GetContext2D() const; + CanvasRenderContextPtr GetContext2D() const; /// \~chinese /// @brief 清空画布大小并重设画布大小 @@ -62,11 +65,465 @@ public: void OnRender(RenderContext& ctx) override; +private: + void RecreateContext(Size* size); + private: TexturePtr texture_cached_; RenderContextPtr render_ctx_; }; + +/// \~chinese +/// @brief 画布渲染上下文 +class KGE_API CanvasRenderContext : public ObjectBase +{ +public: + /// \~chinese + /// @brief 开始渲染 + void BeginDraw(); + + /// \~chinese + /// @brief 结束渲染 + void EndDraw(); + + /// \~chinese + /// @brief 画形状轮廓 + /// @param shape 形状 + void DrawShape(ShapePtr shape); + + /// \~chinese + /// @brief 画线段 + /// @param begin 线段起点 + /// @param end 线段终点 + void DrawLine(const Point& begin, const Point& end); + + /// \~chinese + /// @brief 画圆形边框 + /// @param center 圆形原点 + /// @param radius 圆形半径 + void DrawCircle(const Point& center, float radius); + + /// \~chinese + /// @brief 画椭圆形边框 + /// @param center 椭圆原点 + /// @param radius 椭圆半径 + void DrawEllipse(const Point& center, const Vec2& radius); + + /// \~chinese + /// @brief 画矩形边框 + /// @param rect 矩形 + void DrawRect(const Rect& rect); + + /// \~chinese + /// @brief 画圆角矩形边框 + /// @param rect 矩形 + /// @param radius 矩形圆角半径 + void DrawRoundedRect(const Rect& rect, const Vec2& radius); + + /// \~chinese + /// @brief 填充形状 + /// @param shape 形状 + void FillShape(ShapePtr shape); + + /// \~chinese + /// @brief 填充圆形 + /// @param center 圆形原点 + /// @param radius 圆形半径 + void FillCircle(const Point& center, float radius); + + /// \~chinese + /// @brief 填充椭圆形 + /// @param center 椭圆原点 + /// @param radius 椭圆半径 + void FillEllipse(const Point& center, const Vec2& radius); + + /// \~chinese + /// @brief 填充矩形 + /// @param rect 矩形 + void FillRect(const Rect& rect); + + /// \~chinese + /// @brief 填充圆角矩形 + /// @param rect 矩形 + /// @param radius 矩形圆角半径 + void FillRoundedRect(const Rect& rect, const Vec2& radius); + + /// \~chinese + /// @brief 绘制图像帧 + /// @param frame 图像帧 + /// @param pos 绘制图像的位置 + void DrawFrame(FramePtr frame, const Point& pos); + + /// \~chinese + /// @brief 绘制图像帧 + /// @param frame 图像帧 + /// @param pos 绘制图像的位置 + /// @param size 渲染的图像大小 + void DrawFrame(FramePtr frame, const Point& pos, const Size& size); + + /// \~chinese + /// @brief 绘制文字布局 + /// @param text 文字 + /// @param style 文字样式 + /// @param point 绘制文字的位置 + void DrawTextLayout(const String& text, const TextStyle& style, const Point& point); + + /// \~chinese + /// @brief 绘制文字布局 + /// @param layout 文字布局 + /// @param point 绘制布局的位置 + void DrawTextLayout(TextLayoutPtr layout, const Point& point); + + /// \~chinese + /// @brief 清空画布 + void Clear(); + + /// \~chinese + /// @brief 清空画布 + /// @param clear_color 清空颜色 + void Clear(const Color& clear_color); + + /// \~chinese + /// @brief 设置填充颜色 + /// @param color 填充颜色 + void SetFillColor(const Color& color); + + /// \~chinese + /// @brief 设置填充画刷 + /// @param[in] brush 填充画刷 + void SetFillBrush(BrushPtr brush); + + /// \~chinese + /// @brief 获取填充画刷 + BrushPtr GetFillBrush() const; + + /// \~chinese + /// @brief 设置轮廓颜色 + /// @param color 轮廓颜色 + void SetStrokeColor(const Color& color); + + /// \~chinese + /// @brief 设置轮廓画刷 + /// @param[in] brush 轮廓画刷 + void SetStrokeBrush(BrushPtr brush); + + /// \~chinese + /// @brief 获取轮廓画刷 + BrushPtr GetStrokeBrush() const; + + /// \~chinese + /// @brief 设置轮廓样式 + /// @param stroke_style 轮廓样式 + void SetStrokeStyle(StrokeStylePtr stroke_style); + + /// \~chinese + /// @brief 获取轮廓样式 + StrokeStylePtr GetStrokeStyle() const; + + /// \~chinese + /// @brief 添加一个裁剪区域 + /// @param clip_rect 裁剪矩形 + void PushClipRect(const Rect& clip_rect); + + /// \~chinese + /// @brief 删除最近添加的裁剪区域 + void PopClipRect(); + + /// \~chinese + /// @brief 添加一个图层 + /// @param layer 图层 + void PushLayer(LayerPtr layer); + + /// \~chinese + /// @brief 删除最近添加的图层 + void PopLayer(); + + /// \~chinese + /// @brief 获取画布大小 + Size GetSize() const; + + /// \~chinese + /// @brief 设置渲染上下文的二维变换矩阵 + void SetTransform(const Matrix3x2& matrix); + + /// \~chinese + /// @brief 设置抗锯齿模式 + void SetAntialiasMode(bool enabled); + + /// \~chinese + /// @brief 设置文字抗锯齿模式 + void SetTextAntialiasMode(TextAntialiasMode mode); + + virtual ~CanvasRenderContext(); + +private: + friend class Canvas; + + CanvasRenderContext(RenderContextPtr ctx); + +private: + RenderContextPtr ctx_; + BrushPtr fill_brush_; + BrushPtr stroke_brush_; + StrokeStylePtr stroke_style_; +}; + /** @} */ +inline void CanvasRenderContext::BeginDraw() +{ + KGE_ASSERT(ctx_); + ctx_->BeginDraw(); +} + +inline void CanvasRenderContext::EndDraw() +{ + KGE_ASSERT(ctx_); + ctx_->EndDraw(); +} + +inline void CanvasRenderContext::DrawShape(ShapePtr shape) +{ + KGE_ASSERT(ctx_); + if (shape) + { + ctx_->SetCurrentBrush(stroke_brush_); + ctx_->SetCurrentStrokeStyle(stroke_style_); + ctx_->DrawShape(*shape); + } +} + +inline void CanvasRenderContext::DrawLine(const Point& begin, const Point& end) +{ + KGE_ASSERT(ctx_); + + ctx_->SetCurrentBrush(stroke_brush_); + ctx_->SetCurrentStrokeStyle(stroke_style_); + ctx_->DrawLine(begin, end); +} + +inline void CanvasRenderContext::DrawCircle(const Point& center, float radius) +{ + KGE_ASSERT(ctx_); + + ctx_->SetCurrentBrush(stroke_brush_); + ctx_->SetCurrentStrokeStyle(stroke_style_); + ctx_->DrawCircle(center, radius); +} + +inline void CanvasRenderContext::DrawEllipse(const Point& center, const Vec2& radius) +{ + KGE_ASSERT(ctx_); + + ctx_->SetCurrentBrush(stroke_brush_); + ctx_->SetCurrentStrokeStyle(stroke_style_); + ctx_->DrawEllipse(center, radius); +} + +inline void CanvasRenderContext::DrawRect(const Rect& rect) +{ + KGE_ASSERT(ctx_); + + ctx_->SetCurrentBrush(stroke_brush_); + ctx_->SetCurrentStrokeStyle(stroke_style_); + ctx_->DrawRectangle(rect); +} + +inline void CanvasRenderContext::DrawRoundedRect(const Rect& rect, const Vec2& radius) +{ + KGE_ASSERT(ctx_); + + ctx_->SetCurrentBrush(stroke_brush_); + ctx_->SetCurrentStrokeStyle(stroke_style_); + ctx_->DrawRoundedRectangle(rect, radius); +} + +inline void CanvasRenderContext::FillShape(ShapePtr shape) +{ + KGE_ASSERT(ctx_); + if (shape) + { + ctx_->SetCurrentBrush(fill_brush_); + ctx_->FillShape(*shape); + } +} + +inline void CanvasRenderContext::FillCircle(const Point& center, float radius) +{ + KGE_ASSERT(ctx_); + + ctx_->SetCurrentBrush(fill_brush_); + ctx_->FillCircle(center, radius); +} + +inline void CanvasRenderContext::FillEllipse(const Point& center, const Vec2& radius) +{ + KGE_ASSERT(ctx_); + + ctx_->SetCurrentBrush(fill_brush_); + ctx_->FillEllipse(center, radius); +} + +inline void CanvasRenderContext::FillRect(const Rect& rect) +{ + KGE_ASSERT(ctx_); + + ctx_->SetCurrentBrush(fill_brush_); + ctx_->FillRectangle(rect); +} + +inline void CanvasRenderContext::FillRoundedRect(const Rect& rect, const Vec2& radius) +{ + KGE_ASSERT(ctx_); + + ctx_->SetCurrentBrush(fill_brush_); + ctx_->FillRoundedRectangle(rect, radius); +} + +inline void CanvasRenderContext::DrawFrame(FramePtr frame, const Point& pos) +{ + if (frame) + { + Size frame_size = frame->GetSize(); + this->DrawFrame(frame, pos, frame_size); + } +} + +inline void CanvasRenderContext::DrawFrame(FramePtr frame, const Point& pos, const Size& size) +{ + KGE_ASSERT(ctx_); + + if (frame) + { + ctx_->DrawFrame(frame, Rect(pos, size)); + } +} + +inline void CanvasRenderContext::DrawTextLayout(const String& text, const TextStyle& style, const Point& point) +{ + TextLayoutPtr layout = MakePtr(text, style); + this->DrawTextLayout(layout, point); +} + +inline void CanvasRenderContext::DrawTextLayout(TextLayoutPtr layout, const Point& point) +{ + KGE_ASSERT(ctx_); + if (layout) + { + ctx_->DrawTextLayout(*layout, point); + } +} + +inline void CanvasRenderContext::Clear() +{ + KGE_ASSERT(ctx_); + ctx_->Clear(); +} + +inline void CanvasRenderContext::Clear(const Color& clear_color) +{ + KGE_ASSERT(ctx_); + ctx_->Clear(clear_color); +} + +inline void CanvasRenderContext::SetFillColor(const Color& color) +{ + if (!fill_brush_) + { + fill_brush_ = MakePtr(); + } + fill_brush_->SetColor(color); +} + +inline void CanvasRenderContext::SetFillBrush(BrushPtr brush) +{ + fill_brush_ = brush; +} + +inline BrushPtr CanvasRenderContext::GetFillBrush() const +{ + return fill_brush_; +} + +inline void CanvasRenderContext::SetStrokeBrush(BrushPtr brush) +{ + stroke_brush_ = brush; +} + +inline void CanvasRenderContext::SetStrokeColor(const Color& color) +{ + if (!stroke_brush_) + { + stroke_brush_ = MakePtr(); + } + stroke_brush_->SetColor(color); +} + +inline BrushPtr CanvasRenderContext::GetStrokeBrush() const +{ + return stroke_brush_; +} + +inline void CanvasRenderContext::SetStrokeStyle(StrokeStylePtr stroke_style) +{ + stroke_style_ = stroke_style; +} + +inline StrokeStylePtr CanvasRenderContext::GetStrokeStyle() const +{ + return stroke_style_; +} + +inline void CanvasRenderContext::PushClipRect(const Rect& clip_rect) +{ + KGE_ASSERT(ctx_); + ctx_->PushClipRect(clip_rect); +} + +inline void CanvasRenderContext::PopClipRect() +{ + KGE_ASSERT(ctx_); + ctx_->PopClipRect(); +} + +inline void CanvasRenderContext::PushLayer(LayerPtr layer) +{ + KGE_ASSERT(ctx_); + if (layer) + { + ctx_->PushLayer(*layer); + } +} + +inline void CanvasRenderContext::PopLayer() +{ + KGE_ASSERT(ctx_); + ctx_->PopLayer(); +} + +inline Size CanvasRenderContext::GetSize() const +{ + KGE_ASSERT(ctx_); + return ctx_->GetSize(); +} + +inline void CanvasRenderContext::SetTransform(const Matrix3x2& matrix) +{ + KGE_ASSERT(ctx_); + ctx_->SetTransform(matrix); +} + +inline void CanvasRenderContext::SetAntialiasMode(bool enabled) +{ + KGE_ASSERT(ctx_); + ctx_->SetAntialiasMode(enabled); +} + +inline void CanvasRenderContext::SetTextAntialiasMode(TextAntialiasMode mode) +{ + KGE_ASSERT(ctx_); + ctx_->SetTextAntialiasMode(mode); +} + } // namespace kiwano