Magic_Game/src/kiwano/2d/Canvas.cpp

331 lines
7.4 KiB
C++
Raw Normal View History

2019-04-11 14:40:54 +08:00
// Copyright (c) 2016-2018 Kiwano - Nomango
2020-01-21 10:09:55 +08:00
//
// 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:
2020-01-21 10:09:55 +08:00
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
2020-01-21 10:09:55 +08:00
//
// 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.
2019-10-11 21:55:29 +08:00
#include <kiwano/2d/Canvas.h>
2019-11-13 14:33:15 +08:00
#include <kiwano/core/Logger.h>
2020-01-17 16:55:47 +08:00
#include <kiwano/render/Renderer.h>
2019-04-11 14:40:54 +08:00
namespace kiwano
{
2020-02-06 16:54:47 +08:00
2020-02-08 00:17:31 +08:00
CanvasPtr Canvas::Create(Size const& size)
2020-02-06 16:54:47 +08:00
{
CanvasPtr ptr = new (std::nothrow) Canvas;
2020-02-08 00:17:31 +08:00
if (ptr)
{
try
{
ptr->ctx_ = TextureRenderContext::Create();
ptr->stroke_brush_ = Brush::Create(Color::White);
ptr->fill_brush_ = Brush::Create(Color::White);
ptr->SetSize(ptr->ctx_->GetSize());
2020-02-08 00:17:31 +08:00
}
catch (std::exception)
{
return nullptr;
}
}
2020-02-06 16:54:47 +08:00
return ptr;
}
2020-01-21 10:09:55 +08:00
Canvas::Canvas()
: cache_expired_(false)
, stroke_width_(1.0f)
, stroke_style_()
{
}
void Canvas::BeginDraw()
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->BeginDraw();
}
void Canvas::EndDraw()
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->EndDraw();
cache_expired_ = true;
}
void Canvas::OnRender(RenderContext& ctx)
{
UpdateCache();
if (texture_cached_ && texture_cached_->IsValid())
{
PrepareToRender(ctx);
ctx.DrawTexture(*texture_cached_, nullptr, &GetBounds());
2020-01-21 10:09:55 +08:00
}
}
void Canvas::SetBrush(BrushPtr brush)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->SetCurrentBrush(brush);
}
void Canvas::SetBrushTransform(Transform const& transform)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->SetTransform(transform.ToMatrix());
}
void Canvas::SetBrushTransform(Matrix3x2 const& transform)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->SetTransform(transform);
}
void Canvas::PushLayerArea(LayerArea& area)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->PushLayer(area);
}
2020-01-21 10:09:55 +08:00
void Canvas::PopLayerArea()
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->PopLayer();
}
void Canvas::PushClipRect(Rect const& clip_rect)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->PushClipRect(clip_rect);
}
void Canvas::PopClipRect()
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->PopClipRect();
}
2020-02-05 19:56:22 +08:00
void Canvas::DrawShape(ShapePtr shape)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
if (shape)
{
ctx_->SetCurrentBrush(stroke_brush_);
ctx_->DrawShape(*shape, stroke_style_, stroke_width_);
cache_expired_ = true;
}
2020-02-05 19:56:22 +08:00
}
2020-01-21 10:09:55 +08:00
void Canvas::DrawLine(Point const& begin, Point const& end)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->SetCurrentBrush(stroke_brush_);
2020-02-08 00:17:31 +08:00
ctx_->DrawLine(begin, end, stroke_style_, stroke_width_);
2020-01-21 10:09:55 +08:00
cache_expired_ = true;
}
void Canvas::DrawCircle(Point const& center, float radius)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->SetCurrentBrush(stroke_brush_);
2020-02-08 00:17:31 +08:00
ctx_->DrawEllipse(center, Vec2(radius, radius), stroke_style_, stroke_width_);
2020-01-21 10:09:55 +08:00
cache_expired_ = true;
}
void Canvas::DrawEllipse(Point const& center, Vec2 const& radius)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->SetCurrentBrush(stroke_brush_);
2020-02-08 00:17:31 +08:00
ctx_->DrawEllipse(center, radius, stroke_style_, stroke_width_);
2020-01-21 10:09:55 +08:00
cache_expired_ = true;
}
void Canvas::DrawRect(Rect const& rect)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->SetCurrentBrush(stroke_brush_);
2020-02-08 00:17:31 +08:00
ctx_->DrawRectangle(rect, stroke_style_, stroke_width_);
2020-01-21 10:09:55 +08:00
cache_expired_ = true;
}
void Canvas::DrawRoundedRect(Rect const& rect, Vec2 const& radius)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->SetCurrentBrush(stroke_brush_);
2020-02-08 00:17:31 +08:00
ctx_->DrawRoundedRectangle(rect, radius, stroke_style_, stroke_width_);
2020-01-21 10:09:55 +08:00
cache_expired_ = true;
}
2020-02-05 19:56:22 +08:00
void Canvas::FillShape(ShapePtr shape)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
if (shape)
{
ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillShape(*shape);
cache_expired_ = true;
}
2020-02-05 19:56:22 +08:00
}
2020-01-21 10:09:55 +08:00
void Canvas::FillCircle(Point const& center, float radius)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillEllipse(center, Vec2(radius, radius));
cache_expired_ = true;
}
void Canvas::FillEllipse(Point const& center, Vec2 const& radius)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillEllipse(center, radius);
cache_expired_ = true;
}
2020-01-21 10:09:55 +08:00
void Canvas::FillRect(Rect const& rect)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillRectangle(rect);
cache_expired_ = true;
}
void Canvas::FillRoundedRect(Rect const& rect, Vec2 const& radius)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->SetCurrentBrush(fill_brush_);
ctx_->FillRoundedRectangle(rect, radius);
cache_expired_ = true;
}
void Canvas::DrawTexture(TexturePtr texture, const Rect* src_rect, const Rect* dest_rect)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
if (texture)
{
ctx_->DrawTexture(*texture, src_rect, dest_rect);
cache_expired_ = true;
}
}
void Canvas::DrawTextLayout(String const& text, Point const& point)
{
if (text.empty())
return;
TextLayout layout;
layout.SetStyle(text_style_);
layout.SetText(text);
DrawTextLayout(layout, point);
}
void Canvas::DrawTextLayout(TextLayout const& layout, Point const& point)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->DrawTextLayout(layout, point);
}
void Canvas::BeginPath(Point const& begin_pos)
{
2020-02-05 19:56:22 +08:00
shape_sink_.BeginPath(begin_pos);
2020-01-21 10:09:55 +08:00
}
void Canvas::EndPath(bool closed)
{
2020-02-05 19:56:22 +08:00
shape_sink_.EndPath(closed);
2020-01-21 10:09:55 +08:00
}
void Canvas::AddLine(Point const& point)
{
2020-02-05 19:56:22 +08:00
shape_sink_.AddLine(point);
2020-01-21 10:09:55 +08:00
}
void Canvas::AddLines(Vector<Point> const& points)
{
2020-02-05 19:56:22 +08:00
shape_sink_.AddLines(points);
2020-01-21 10:09:55 +08:00
}
void Canvas::AddBezier(Point const& point1, Point const& point2, Point const& point3)
{
2020-02-05 19:56:22 +08:00
shape_sink_.AddBezier(point1, point2, point3);
2020-01-21 10:09:55 +08:00
}
void Canvas::AddArc(Point const& point, Size const& radius, float rotation, bool clockwise, bool is_small)
{
2020-02-05 19:56:22 +08:00
shape_sink_.AddArc(point, radius, rotation, clockwise, is_small);
2020-01-21 10:09:55 +08:00
}
void Canvas::StrokePath()
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->SetCurrentBrush(stroke_brush_);
2020-02-08 00:17:31 +08:00
ctx_->DrawShape(*shape_sink_.GetShape(), stroke_style_, stroke_width_);
2020-01-21 10:09:55 +08:00
cache_expired_ = true;
}
void Canvas::FillPath()
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->SetCurrentBrush(fill_brush_);
2020-02-05 19:56:22 +08:00
ctx_->FillShape(*shape_sink_.GetShape());
2020-01-21 10:09:55 +08:00
cache_expired_ = true;
}
void Canvas::Clear()
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->Clear();
cache_expired_ = true;
}
void Canvas::Clear(Color const& clear_color)
{
2020-02-08 00:17:31 +08:00
KGE_ASSERT(ctx_);
2020-01-21 10:09:55 +08:00
ctx_->Clear(clear_color);
cache_expired_ = true;
}
2020-02-08 00:17:31 +08:00
void Canvas::ResizeAndClear(Size size)
2020-01-21 10:09:55 +08:00
{
2020-02-08 00:17:31 +08:00
ctx_ = TextureRenderContext::Create(size);
2020-01-21 10:09:55 +08:00
}
2020-02-08 00:17:31 +08:00
TexturePtr Canvas::ExportToTexture() const
2020-01-21 10:09:55 +08:00
{
2020-02-08 00:17:31 +08:00
UpdateCache();
return texture_cached_;
2020-01-21 10:09:55 +08:00
}
void Canvas::UpdateCache() const
{
if (cache_expired_ && ctx_)
{
if (!texture_cached_)
{
texture_cached_ = new Texture;
}
if (ctx_->GetOutput(*texture_cached_))
{
cache_expired_ = false;
}
}
}
} // namespace kiwano