diff --git a/core/base/Canvas.cpp b/core/base/Canvas.cpp index 7e78ac26..13141bcc 100644 --- a/core/base/Canvas.cpp +++ b/core/base/Canvas.cpp @@ -21,91 +21,159 @@ #include "Canvas.h" #include "render.h" #include "logs.h" +#include "Image.h" namespace easy2d { - //------------------------------------------------------- - // CanvasBrush - //------------------------------------------------------- - - CanvasBrush::CanvasBrush() - : render_target_(nullptr) - , fill_brush_(nullptr) - , line_brush_(nullptr) - , stroke_style_(nullptr) + Canvas::Canvas() + : cache_expired_(false) , stroke_width_(1.0f) - , stroke_(StrokeStyle::Miter) { - auto graphics = devices::Graphics::Instance(); - render_target_ = graphics->GetRenderTarget(); - ThrowIfFailed( - graphics->CreateSolidColorBrush(fill_brush_) + devices::Graphics::Instance()->CreateBitmapRenderTarget(render_target_) + ); + + auto properties = D2D1::BrushProperties(); + ThrowIfFailed( + render_target_->CreateSolidColorBrush( + Color(Color::White, 0.f), + properties, + &fill_brush_) ); ThrowIfFailed( - graphics->CreateSolidColorBrush(line_brush_) + render_target_->CreateSolidColorBrush( + Color(Color::White), + properties, + &stroke_brush_) ); - this->SetStrokeStyle(stroke_); + ThrowIfFailed( + render_target_->CreateSolidColorBrush( + Color(Color::White), + properties, + &text_brush_) + ); + + ThrowIfFailed( + devices::Graphics::Instance()->CreateTextRenderer( + text_renderer_, + render_target_, + text_brush_ + ) + ); + + SetTextStyle(Font{}, TextStyle{}); } - CanvasBrush::~CanvasBrush() + Canvas::Canvas(float width, float height) + : Canvas() + { + this->SetSize(width, height); + } + + Canvas::Canvas(Size const & size) + : Canvas(size.width, size.height) { } - void CanvasBrush::SetLineColor(Color const& color) + Canvas::~Canvas() { - line_brush_->SetColor(D2D_COLOR_F(color)); } - void CanvasBrush::SetFillColor(Color const& color) + void Canvas::BeginDraw() { - fill_brush_->SetColor(D2D_COLOR_F(color)); + render_target_->BeginDraw(); } - void CanvasBrush::SetStrokeWidth(float width) + void Canvas::EndDraw() + { + ThrowIfFailed( + render_target_->EndDraw() + ); + cache_expired_ = true; + } + + void Canvas::OnDraw() + { + if (cache_expired_) + { + GetBitmap(); + } + + if (bitmap_cached_) + { + devices::Graphics::Instance()->DrawBitmap(bitmap_cached_); + } + } + + void Canvas::SetStrokeColor(Color const& color) + { + stroke_brush_->SetColor(color); + } + + void Canvas::SetFillColor(Color const& color) + { + fill_brush_->SetColor(color); + } + + void Canvas::SetStrokeWidth(float width) { stroke_width_ = std::max(width, 0.f); } - void CanvasBrush::SetStrokeStyle(StrokeStyle stroke) + void Canvas::SetOutlineJoinStyle(StrokeStyle outline_join) { - stroke_style_ = devices::Graphics::Instance()->GetStrokeStyle(stroke); + outline_join_style_ = devices::Graphics::Instance()->GetStrokeStyle(outline_join); } - Color CanvasBrush::GetLineColor() const + void Canvas::SetTextStyle(Font const& font, TextStyle const & text_style) { - return line_brush_->GetColor(); + text_font_ = font; + text_style_ = text_style; + + text_renderer_->SetTextStyle( + text_style_.color, + text_style_.outline, + text_style_.outline_color, + text_style_.outline_width, + devices::Graphics::Instance()->GetStrokeStyle(text_style_.outline_stroke).Get() + ); } - Color CanvasBrush::GetFillColor() const + Color Canvas::GetStrokeColor() const + { + return stroke_brush_->GetColor(); + } + + Color Canvas::GetFillColor() const { return fill_brush_->GetColor(); } - float CanvasBrush::GetStrokeWidth() const + float Canvas::GetStrokeWidth() const { return stroke_width_; } - StrokeStyle CanvasBrush::GetStrokeStyle() const + void Canvas::SetBrushTransform(math::Matrix const & transform) { - return stroke_; + render_target_->SetTransform(ConvertToD2DMatrix(transform)); } - void CanvasBrush::DrawLine(const Point & begin, const Point & end) + void Canvas::DrawLine(const Point & begin, const Point & end) { render_target_->DrawLine( D2D1::Point2F(begin.x, begin.y), D2D1::Point2F(end.x, end.y), - line_brush_.Get(), + stroke_brush_.Get(), stroke_width_, - stroke_style_.Get() + outline_join_style_.Get() ); + cache_expired_ = true; } - void CanvasBrush::DrawCircle(const Point & center, float radius) + void Canvas::DrawCircle(const Point & center, float radius) { render_target_->DrawEllipse( D2D1::Ellipse( @@ -116,13 +184,14 @@ namespace easy2d radius, radius ), - line_brush_.Get(), + stroke_brush_.Get(), stroke_width_, - stroke_style_.Get() + outline_join_style_.Get() ); + cache_expired_ = true; } - void CanvasBrush::DrawEllipse(const Point & center, float radius_x, float radius_y) + void Canvas::DrawEllipse(const Point & center, float radius_x, float radius_y) { render_target_->DrawEllipse( D2D1::Ellipse( @@ -133,13 +202,14 @@ namespace easy2d radius_x, radius_y ), - line_brush_.Get(), + stroke_brush_.Get(), stroke_width_, - stroke_style_.Get() + outline_join_style_.Get() ); + cache_expired_ = true; } - void CanvasBrush::DrawRect(const Rect & rect) + void Canvas::DrawRect(const Rect & rect) { render_target_->DrawRectangle( D2D1::RectF( @@ -148,13 +218,14 @@ namespace easy2d rect.origin.x + rect.size.width, rect.origin.y + rect.size.height ), - line_brush_.Get(), + stroke_brush_.Get(), stroke_width_, - stroke_style_.Get() + outline_join_style_.Get() ); + cache_expired_ = true; } - void CanvasBrush::DrawRoundedRect(const Rect & rect, float radius_x, float radius_y) + void Canvas::DrawRoundedRect(const Rect & rect, float radius_x, float radius_y) { render_target_->DrawRoundedRectangle( D2D1::RoundedRect( @@ -167,13 +238,62 @@ namespace easy2d radius_x, radius_y ), - line_brush_.Get(), + stroke_brush_.Get(), stroke_width_, - stroke_style_.Get() + outline_join_style_.Get() + ); + cache_expired_ = true; + } + + void Canvas::DrawImage(spImage const & image, float opacity) + { + if (image->GetBitmap()) + { + render_target_->DrawBitmap( + image->GetBitmap().Get(), + Rect{ Point{}, image->GetSize() }, + opacity, + D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, + image->GetCropRect() + ); + cache_expired_ = true; + } + } + + void Canvas::DrawText(String const & text, Point const & point) + { + if (text.empty()) + return; + + auto graphics = devices::Graphics::Instance(); + + cpTextFormat text_format; + ThrowIfFailed( + graphics->CreateTextFormat( + text_format, + text_font_, + text_style_ + ) + ); + + cpTextLayout text_layout; + Size layout_size; + ThrowIfFailed( + graphics->CreateTextLayout( + text_layout, + layout_size, + text, + text_format, + text_style_ + ) + ); + + ThrowIfFailed( + text_layout->Draw(nullptr, text_renderer_.Get(), point.x, point.y) ); } - void CanvasBrush::FillCircle(const Point & center, float radius) + void Canvas::FillCircle(const Point & center, float radius) { render_target_->FillEllipse( D2D1::Ellipse( @@ -186,9 +306,10 @@ namespace easy2d ), fill_brush_.Get() ); + cache_expired_ = true; } - void CanvasBrush::FillEllipse(const Point & center, float radius_x, float radius_y) + void Canvas::FillEllipse(const Point & center, float radius_x, float radius_y) { render_target_->FillEllipse( D2D1::Ellipse( @@ -201,9 +322,10 @@ namespace easy2d ), fill_brush_.Get() ); + cache_expired_ = true; } - void CanvasBrush::FillRect(const Rect & rect) + void Canvas::FillRect(const Rect & rect) { render_target_->FillRectangle( D2D1::RectF( @@ -214,9 +336,10 @@ namespace easy2d ), fill_brush_.Get() ); + cache_expired_ = true; } - void CanvasBrush::FillRoundedRect(const Rect & rect, float radius_x, float radius_y) + void Canvas::FillRoundedRect(const Rect & rect, float radius_x, float radius_y) { render_target_->FillRoundedRectangle( D2D1::RoundedRect( @@ -231,38 +354,115 @@ namespace easy2d ), fill_brush_.Get() ); + cache_expired_ = true; } - - //------------------------------------------------------- - // Canvas - //------------------------------------------------------- - - Canvas::Canvas() + void Canvas::BeginPath(Point const& begin_pos) { + current_geometry_ = nullptr; + + ThrowIfFailed( + devices::Graphics::Instance()->CreatePathGeometry(current_geometry_) + ); + + ThrowIfFailed( + current_geometry_->Open(¤t_sink_) + ); + + current_sink_->BeginFigure(begin_pos, D2D1_FIGURE_BEGIN_FILLED); } - Canvas::Canvas(float width, float height) + void Canvas::EndPath(bool closed) { - this->SetClipEnabled(true); - this->SetWidth(width); - this->SetHeight(height); + if (current_sink_) + { + current_sink_->EndFigure(closed ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN); + ThrowIfFailed( + current_sink_->Close() + ); + current_sink_ = nullptr; + } } - Canvas::~Canvas() + void Canvas::AddLine(Point const & point) { + if (current_sink_) + current_sink_->AddLine(point); } - void Canvas::SetBrush(spCanvasBrush const & brush) + void Canvas::AddLines(std::vector const& points) { - brush_ = brush; + if (current_sink_) + { + if (!points.empty()) + { + size_t size = points.size(); + std::vector d2d_points(size); + for (size_t i = 0; i < size; ++i) + { + d2d_points[i] = points[i]; + } + + current_sink_->AddLines( + &d2d_points[0], + static_cast(size) + ); + } + } } - void Canvas::OnDraw() + void Canvas::AddBezier(Point const & point1, Point const & point2, Point const & point3) { - if (!brush_) - brush_ = new CanvasBrush; - - OnDraw(*brush_); + if (current_sink_) + { + current_sink_->AddBezier( + D2D1::BezierSegment( + point1, + point2, + point3 + ) + ); + } } + + void Canvas::StrokePath() + { + render_target_->DrawGeometry( + current_geometry_.Get(), + stroke_brush_.Get(), + stroke_width_, + outline_join_style_.Get() + ); + cache_expired_ = true; + } + + void Canvas::FillPath() + { + render_target_->FillGeometry( + current_geometry_.Get(), + fill_brush_.Get() + ); + cache_expired_ = true; + } + + spImage Canvas::ExportToImage() const + { + auto image = new Image(GetBitmap()); + image->Crop(Rect(Point{}, this->GetSize())); + return image; + } + + cpBitmap const& easy2d::Canvas::GetBitmap() const + { + if (cache_expired_) + { + bitmap_cached_ = nullptr; + ThrowIfFailed( + render_target_->GetBitmap(&bitmap_cached_) + ); + cache_expired_ = false; + } + return bitmap_cached_; + } + } \ No newline at end of file diff --git a/core/base/Canvas.h b/core/base/Canvas.h index 38217ee1..9ab67f99 100644 --- a/core/base/Canvas.h +++ b/core/base/Canvas.h @@ -20,19 +20,37 @@ #pragma once #include "Node.h" +#include "Font.hpp" +#include "TextStyle.hpp" +#include "TextRenderer.h" + +#undef DrawText namespace easy2d { - E2D_DECLARE_SMART_PTR(CanvasBrush); - - // 画笔 - class CanvasBrush - : public RefCounter + // 画布 + class Canvas + : public Node { public: - CanvasBrush(); + Canvas(); - virtual ~CanvasBrush(); + Canvas( + Size const& size + ); + + Canvas( + float width, + float height + ); + + virtual ~Canvas(); + + // 开始绘图 + void BeginDraw(); + + // 结束绘图 + void EndDraw(); // 画直线 void DrawLine( @@ -65,6 +83,18 @@ namespace easy2d float radius_y ); + // 画图片 + void DrawImage( + spImage const& image, + float opacity = 1.f + ); + + // 画文字 + void DrawText( + String const& text, /* 文字 */ + Point const& point /* 文字位置 */ + ); + // 填充圆形 void FillCircle( const Point& center, @@ -90,72 +120,100 @@ namespace easy2d float radius_y ); - // 设置线条颜色 - void SetLineColor( - const Color& color + // 开始绘制路径 + void BeginPath( + Point const& begin_pos /* 路径起始点 */ ); + // 结束路径 + void EndPath( + bool closed = true /* 路径是否闭合 */ + ); + + // 添加一条线段 + void AddLine( + Point const& point /* 端点 */ + ); + + // 添加多条线段 + void AddLines( + std::vector const& points + ); + + // 添加一条三次方贝塞尔曲线 + void AddBezier( + Point const& point1, /* 贝塞尔曲线的第一个控制点 */ + Point const& point2, /* 贝塞尔曲线的第二个控制点 */ + Point const& point3 /* 贝塞尔曲线的终点 */ + ); + + // 路径描边 + void StrokePath(); + + // 路径填充 + void FillPath(); + // 设置填充颜色 void SetFillColor( const Color& color ); + // 设置线条颜色 + void SetStrokeColor( + const Color& color + ); + // 设置线条宽度 void SetStrokeWidth( float width ); // 设置线条相交样式 - void SetStrokeStyle( - StrokeStyle stroke + void SetOutlineJoinStyle( + StrokeStyle outline_join ); - // 获取线条颜色 - Color GetLineColor() const; + // 设置文字画刷样式 + void SetTextStyle( + Font const& font, + TextStyle const& text_style + ); // 获取填充颜色 Color GetFillColor() const; + // 获取线条颜色 + Color GetStrokeColor() const; + // 获取线条宽度 float GetStrokeWidth() const; - // 获取线条相交样式 - StrokeStyle GetStrokeStyle() const; - - protected: - float stroke_width_; - StrokeStyle stroke_; - cpRenderTarget render_target_; - cpSolidColorBrush fill_brush_; - cpSolidColorBrush line_brush_; - cpStrokeStyle stroke_style_; - }; - - - // 画布 - class Canvas - : public Node - { - public: - Canvas(); - - Canvas( - float width, - float height + // 变换画笔 + void SetBrushTransform( + math::Matrix const& transform ); - virtual ~Canvas(); - - virtual void OnDraw(CanvasBrush& brush) = 0; - - // 设置画刷 - void SetBrush( - spCanvasBrush const& brush - ); + // 导出为图片 + spImage ExportToImage() const; virtual void OnDraw() override; - private: - spCanvasBrush brush_; + protected: + cpBitmap const& GetBitmap() const; + + protected: + mutable bool cache_expired_; + mutable cpBitmap bitmap_cached_; + float stroke_width_; + Font text_font_; + TextStyle text_style_; + cpPathGeometry current_geometry_; + cpGeometrySink current_sink_; + cpStrokeStyle outline_join_style_; + cpSolidColorBrush fill_brush_; + cpSolidColorBrush stroke_brush_; + cpSolidColorBrush text_brush_; + cpTextRenderer text_renderer_; + cpBitmapRenderTarget render_target_; }; } \ No newline at end of file diff --git a/core/base/Game.cpp b/core/base/Game.cpp index 1186602d..e23e33db 100644 --- a/core/base/Game.cpp +++ b/core/base/Game.cpp @@ -118,10 +118,10 @@ namespace easy2d const auto window = Window::Instance(); ::ShowWindow(window->GetHandle(), SW_SHOWNORMAL); ::UpdateWindow(window->GetHandle()); + window->Poll(); const int64_t min_interval = 5; auto last = time::Now(); - MSG msg = {}; while (!quit_) { @@ -142,11 +142,7 @@ namespace easy2d UpdateScene(dt); DrawScene(); - while (::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) - { - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); - } + window->Poll(); } else { @@ -279,16 +275,16 @@ namespace easy2d if (debug_enabled_) { + graphics->SetTransform(math::Matrix()); + graphics->SetOpacity(1.f); + if (curr_scene_) { - graphics->SetTransform(math::Matrix()); - graphics->SetBrushOpacity(1.f); curr_scene_->DrawBorder(); } + if (next_scene_) { - graphics->SetTransform(math::Matrix()); - graphics->SetBrushOpacity(1.f); next_scene_->DrawBorder(); } diff --git a/core/base/Image.cpp b/core/base/Image.cpp index 28525c83..c134f2a5 100644 --- a/core/base/Image.cpp +++ b/core/base/Image.cpp @@ -32,51 +32,51 @@ namespace easy2d } Image::Image(Resource const& res) - : bitmap_(nullptr) - , crop_rect_() + : Image() { this->Load(res); } Image::Image(Resource const& res, Rect const& crop_rect) - : bitmap_(nullptr) - , crop_rect_() + : Image() { this->Load(res); this->Crop(crop_rect); } Image::Image(String const& file_name) - : bitmap_(nullptr) - , crop_rect_() + : Image() { this->Load(file_name); } Image::Image(String const& file_name, const Rect & crop_rect) - : bitmap_(nullptr) - , crop_rect_() + : Image() { this->Load(file_name); this->Crop(crop_rect); } + Image::Image(cpBitmap const & bitmap) + : Image() + { + SetBitmap(bitmap); + } + Image::~Image() { } bool Image::Load(Resource const& res) { - HRESULT hr = devices::Graphics::Instance()->CreateBitmapFromResource(bitmap_, res); + cpBitmap bitmap; + HRESULT hr = devices::Graphics::Instance()->CreateBitmapFromResource(bitmap, res); if (FAILED(hr)) { logs::Errorln(hr, "Load Image from resource failed!"); return false; } - - crop_rect_.origin.x = crop_rect_.origin.y = 0; - crop_rect_.size.width = bitmap_->GetSize().width; - crop_rect_.size.height = bitmap_->GetSize().height; + SetBitmap(bitmap); return true; } @@ -93,16 +93,15 @@ namespace easy2d // 默认搜索路径,所以需要通过 File::GetPath 获取完整路径 String image_file_path = image_file.GetPath(); - HRESULT hr = devices::Graphics::Instance()->CreateBitmapFromFile(bitmap_, image_file_path); + cpBitmap bitmap; + HRESULT hr = devices::Graphics::Instance()->CreateBitmapFromFile(bitmap, image_file_path); if (FAILED(hr)) { logs::Errorln(hr, "Load Image from file failed!"); return false; } - crop_rect_.origin.x = crop_rect_.origin.y = 0; - crop_rect_.size.width = bitmap_->GetSize().width; - crop_rect_.size.height = bitmap_->GetSize().height; + SetBitmap(bitmap); return true; } @@ -192,4 +191,15 @@ namespace easy2d return bitmap_; } + void Image::SetBitmap(cpBitmap const & bitmap) + { + if (bitmap) + { + bitmap_ = bitmap; + crop_rect_.origin.x = crop_rect_.origin.y = 0; + crop_rect_.size.width = bitmap_->GetSize().width; + crop_rect_.size.height = bitmap_->GetSize().height; + } + } + } \ No newline at end of file diff --git a/core/base/Image.h b/core/base/Image.h index d7d40881..45e27df2 100644 --- a/core/base/Image.h +++ b/core/base/Image.h @@ -49,6 +49,10 @@ namespace easy2d Rect const& crop_rect /* 裁剪矩形 */ ); + explicit Image( + cpBitmap const& bitmap + ); + virtual ~Image(); // 加载图片资源 @@ -98,6 +102,11 @@ namespace easy2d cpBitmap const& GetBitmap() const; + protected: + void SetBitmap( + cpBitmap const& bitmap + ); + protected: Rect crop_rect_; cpBitmap bitmap_; diff --git a/core/base/Node.cpp b/core/base/Node.cpp index 6304189d..197b91cf 100644 --- a/core/base/Node.cpp +++ b/core/base/Node.cpp @@ -48,8 +48,8 @@ namespace easy2d , dirty_transform_(false) , order_(0) , transform_() + , opacity_(1.f) , display_opacity_(1.f) - , real_opacity_(1.f) , children_() , initial_matrix_() , final_matrix_() @@ -75,14 +75,16 @@ namespace easy2d graphics->PushClip(final_matrix_, transform_.size); } + UpdateTransform(); + if (children_.IsEmpty()) { graphics->SetTransform(final_matrix_); + graphics->SetOpacity(display_opacity_); OnDraw(); } else { - // 子节点排序 if (dirty_sort_) { children_.Sort( @@ -107,6 +109,7 @@ namespace easy2d } graphics->SetTransform(final_matrix_); + graphics->SetOpacity(display_opacity_); OnDraw(); for (spNode next; child; child = next) @@ -129,7 +132,6 @@ namespace easy2d OnUpdate(dt); UpdateActions(this, dt); UpdateTasks(dt); - UpdateTransform(); } else { @@ -151,7 +153,6 @@ namespace easy2d OnUpdate(dt); UpdateActions(this, dt); UpdateTasks(dt); - UpdateTransform(); for (spNode next; child; child = next) { @@ -167,7 +168,7 @@ namespace easy2d { if (border_) { - devices::Graphics::Instance()->DrawGeometry(border_, border_color_, 1.f, 1.5f); + devices::Graphics::Instance()->DrawGeometry(border_, border_color_, 1.5f); } for (auto child = children_.First(); child; child = child->NextItem()) @@ -248,7 +249,7 @@ namespace easy2d { if (parent_) { - display_opacity_ = real_opacity_ * parent_->display_opacity_; + display_opacity_ = opacity_ * parent_->display_opacity_; } for (auto child = children_.First(); child; child = child->NextItem()) { @@ -256,106 +257,6 @@ namespace easy2d } } - bool Node::IsVisible() const - { - return visible_; - } - - String const& Node::GetName() const - { - return name_; - } - - size_t Node::GetHashName() const - { - return hash_name_; - } - - const Point& Node::GetPosition() const - { - return transform_.position; - } - - float Node::GetWidth() const - { - return transform_.size.width * transform_.scale.x; - } - - float Node::GetHeight() const - { - return transform_.size.height * transform_.scale.y; - } - - float Node::GetRealWidth() const - { - return transform_.size.width; - } - - float Node::GetRealHeight() const - { - return transform_.size.height; - } - - const Size& Node::GetRealSize() const - { - return transform_.size; - } - - float Node::GetPivotX() const - { - return transform_.pivot.x; - } - - float Node::GetPivotY() const - { - return transform_.pivot.y; - } - - Size Node::GetSize() const - { - return Size{ GetWidth(), GetHeight() }; - } - - float Node::GetScaleX() const - { - return transform_.scale.x; - } - - float Node::GetScaleY() const - { - return transform_.scale.y; - } - - float Node::GetSkewX() const - { - return transform_.skew.x; - } - - float Node::GetSkewY() const - { - return transform_.skew.y; - } - - float Node::GetRotation() const - { - return transform_.rotation; - } - - float Node::GetOpacity() const - { - return real_opacity_; - } - - float Node::GetDisplayOpacity() const - { - return display_opacity_; - } - - int Node::GetOrder() const - { - return order_; - } - void Node::SetOrder(int order) { if (order_ == order) @@ -459,10 +360,10 @@ namespace easy2d void Node::SetOpacity(float opacity) { - if (real_opacity_ == opacity) + if (opacity_ == opacity) return; - display_opacity_ = real_opacity_ = std::min(std::max(opacity, 0.f), 1.f); + display_opacity_ = opacity_ = std::min(std::max(opacity, 0.f), 1.f); // 更新节点透明度 UpdateOpacity(); } @@ -566,11 +467,6 @@ namespace easy2d } } - spNode Node::GetParent() const - { - return parent_; - } - Rect Node::GetBounds() { return Rect(Point{}, transform_.size); diff --git a/core/base/Node.h b/core/base/Node.h index e1cee6fd..95f5cced 100644 --- a/core/base/Node.h +++ b/core/base/Node.h @@ -59,71 +59,59 @@ namespace easy2d virtual void OnUpdate(Duration const& dt) {} // 获取节点显示状态 - bool IsVisible() const; + bool IsVisible() const { return visible_; } // 获取节点名称 - String const& GetName() const; + String const& GetName() const { return name_; } // 获取节点名称的 Hash 值 - size_t GetHashName() const; + size_t GetHashName() const { return hash_name_; } // 获取节点绘图顺序 - int GetOrder() const; + int GetOrder() const { return order_; } // 获取节点坐标 - const Point& GetPosition() const; + virtual const Point& GetPosition() const { return transform_.position; } // 获取节点宽度 - float GetWidth() const; + virtual float GetWidth() const { return transform_.size.width * transform_.scale.x; } // 获取节点高度 - float GetHeight() const; - - // 获取节点宽度(不考虑缩放) - float GetRealWidth() const; - - // 获取节点高度(不考虑缩放) - float GetRealHeight() const; - - // 获取节点大小(不考虑缩放) - const Size& GetRealSize() const; - - // 获取节点的支点 - float GetPivotX() const; - - // 获取节点的支点 - float GetPivotY() const; + virtual float GetHeight() const { return transform_.size.height * transform_.scale.y; } // 获取节点大小 - Size GetSize() const; + Size GetSize() const { return Size{ GetWidth(), GetHeight() }; } + + // 获取节点的支点 + virtual float GetPivotX() const { return transform_.pivot.x; } + + // 获取节点的支点 + virtual float GetPivotY() const { return transform_.pivot.y; } // 获取节点横向缩放比例 - float GetScaleX() const; + virtual float GetScaleX() const { return transform_.scale.x; } // 获取节点纵向缩放比例 - float GetScaleY() const; + virtual float GetScaleY() const { return transform_.scale.y; } // 获取节点横向错切角度 - float GetSkewX() const; + virtual float GetSkewX() const { return transform_.skew.x; } // 获取节点纵向错切角度 - float GetSkewY() const; + virtual float GetSkewY() const { return transform_.skew.y; } // 获取节点旋转角度 - float GetRotation() const; + virtual float GetRotation() const { return transform_.rotation; } // 获取节点透明度 - float GetOpacity() const; - - // 获取显示透明度 - float GetDisplayOpacity() const; - - // 获取父节点 - spNode GetParent() const; + virtual float GetOpacity() const { return opacity_; } // 获取包围盒 virtual Rect GetBounds(); + // 获取父节点 + virtual spNode GetParent() const { return parent_; } + // 设置节点是否显示 void SetVisible( bool val @@ -248,7 +236,7 @@ namespace easy2d ); // 修改节点宽度 - virtual void SetWidth( + void SetWidth( float width ); @@ -367,7 +355,7 @@ namespace easy2d String name_; size_t hash_name_; float display_opacity_; - float real_opacity_; + float opacity_; int order_; bool visible_; bool clip_enabled_; diff --git a/core/base/Sprite.cpp b/core/base/Sprite.cpp index ce3abb28..0b5e797b 100644 --- a/core/base/Sprite.cpp +++ b/core/base/Sprite.cpp @@ -129,15 +129,9 @@ namespace easy2d void Sprite::OnDraw() { - if (image_ && image_->GetBitmap()) + if (image_) { - auto crop_pos = image_->GetCropPos(); - devices::Graphics::Instance()->DrawImage( - image_, - GetDisplayOpacity(), - Rect(Point(), GetTransform().size), - Rect(crop_pos, GetTransform().size) - ); + devices::Graphics::Instance()->DrawImage(image_); } } } \ No newline at end of file diff --git a/core/base/Text.cpp b/core/base/Text.cpp index 8b0c4527..4573522c 100644 --- a/core/base/Text.cpp +++ b/core/base/Text.cpp @@ -44,7 +44,6 @@ namespace easy2d Text::Text() : font_(text_default_font) , style_(text_default_style) - , dirty_layout_(false) { } @@ -67,8 +66,8 @@ namespace easy2d : font_(font) , style_(style) , text_(text) - , dirty_layout_(true) { + UpdateLayout(); } Text::~Text() @@ -127,7 +126,6 @@ namespace easy2d int Text::GetLineCount() { - UpdateLayout(); if (text_layout_) { DWRITE_TEXT_METRICS metrics; @@ -139,12 +137,6 @@ namespace easy2d return 0; } - Rect Text::GetBounds() - { - UpdateLayout(); - return Node::GetBounds(); - } - bool Text::IsItalic() const { return font_.italic; @@ -168,19 +160,19 @@ namespace easy2d void Text::SetText(String const& text) { text_ = text; - dirty_layout_ = true; + UpdateLayout(); } void Text::SetStyle(const TextStyle& style) { style_ = style; - dirty_layout_ = true; + UpdateLayout(); } void Text::SetFont(const Font & font) { font_ = font; - dirty_layout_ = true; + UpdateLayout(); } void Text::SetFontFamily(String const& family) @@ -188,7 +180,7 @@ namespace easy2d if (font_.family != family) { font_.family = family; - dirty_layout_ = true; + UpdateLayout(); } } @@ -197,7 +189,7 @@ namespace easy2d if (font_.size != size) { font_.size = size; - dirty_layout_ = true; + UpdateLayout(); } } @@ -206,7 +198,7 @@ namespace easy2d if (font_.weight != weight) { font_.weight = weight; - dirty_layout_ = true; + UpdateLayout(); } } @@ -220,7 +212,7 @@ namespace easy2d if (font_.italic != val) { font_.italic = val; - dirty_layout_ = true; + UpdateLayout(); } } @@ -229,7 +221,7 @@ namespace easy2d if (style_.wrap != wrap) { style_.wrap = wrap; - dirty_layout_ = true; + UpdateLayout(); } } @@ -238,7 +230,7 @@ namespace easy2d if (style_.wrap_width != wrap_width) { style_.wrap_width = std::max(wrap_width, 0.f); - dirty_layout_ = true; + UpdateLayout(); } } @@ -247,7 +239,7 @@ namespace easy2d if (style_.line_spacing != line_spacing) { style_.line_spacing = line_spacing; - dirty_layout_ = true; + UpdateLayout(); } } @@ -256,7 +248,7 @@ namespace easy2d if (style_.alignment != align) { style_.alignment = align; - dirty_layout_ = true; + UpdateLayout(); } } @@ -265,7 +257,7 @@ namespace easy2d if (style_.underline != underline) { style_.underline = underline; - dirty_layout_ = true; + UpdateLayout(); } } @@ -274,7 +266,7 @@ namespace easy2d if (style_.strikethrough != strikethrough) { style_.strikethrough = strikethrough; - dirty_layout_ = true; + UpdateLayout(); } } @@ -303,7 +295,6 @@ namespace easy2d if (text_layout_) { auto graphics = devices::Graphics::Instance(); - graphics->SetBrushOpacity(GetDisplayOpacity()); graphics->SetTextStyle( style_.color, style_.outline, @@ -315,17 +306,8 @@ namespace easy2d } } - void Text::Update(Duration const & dt) - { - UpdateLayout(); - Node::Update(dt); - } - void Text::UpdateLayout() { - if (!dirty_layout_) - return; - text_format_ = nullptr; text_layout_ = nullptr; @@ -337,75 +319,22 @@ namespace easy2d ThrowIfFailed( graphics->CreateTextFormat( text_format_, - font_ + font_, + style_ ) ); - if (style_.line_spacing == 0.f) - { - text_format_->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0); - } - else - { - text_format_->SetLineSpacing( - DWRITE_LINE_SPACING_METHOD_UNIFORM, - style_.line_spacing, - style_.line_spacing * 0.8f - ); - } - text_format_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(style_.alignment)); - text_format_->SetWordWrapping(style_.wrap ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP); + Size layout_size; + ThrowIfFailed( + graphics->CreateTextLayout( + text_layout_, + layout_size, + text_, + text_format_, + style_ + ) + ); - if (style_.wrap) - { - ThrowIfFailed( - graphics->CreateTextLayout( - text_layout_, - text_, - text_format_, - style_.wrap_width - ) - ); - - DWRITE_TEXT_METRICS metrics; - text_layout_->GetMetrics(&metrics); - this->SetSize(metrics.layoutWidth, metrics.height); - } - else - { - ThrowIfFailed( - graphics->CreateTextLayout( - text_layout_, - text_, - text_format_, - 0 - ) - ); - - DWRITE_TEXT_METRICS metrics; - text_layout_->GetMetrics(&metrics); - this->SetSize(metrics.width, metrics.height); - - ThrowIfFailed( - graphics->CreateTextLayout( - text_layout_, - text_, - text_format_, - metrics.width - ) - ); - } - - DWRITE_TEXT_RANGE range = { 0, static_cast(text_.length()) }; - if (style_.underline) - { - text_layout_->SetUnderline(true, range); - } - if (style_.strikethrough) - { - text_layout_->SetStrikethrough(true, range); - } - - dirty_layout_ = false; + this->SetSize(layout_size); } } diff --git a/core/base/Text.h b/core/base/Text.h index 1aa2769f..95fdce17 100644 --- a/core/base/Text.h +++ b/core/base/Text.h @@ -87,9 +87,6 @@ namespace easy2d // 获取文本显示行数 int GetLineCount(); - // 获取包围盒 - virtual Rect GetBounds() override; - // 是否是斜体 bool IsItalic() const; @@ -202,20 +199,16 @@ namespace easy2d TextStyle const& style ); - // 渲染文字 virtual void OnDraw() override; protected: - virtual void Update(Duration const& dt) override; - void UpdateLayout(); protected: - String text_; - Font font_; - TextStyle style_; - bool dirty_layout_; - cpTextFormat text_format_; - cpTextLayout text_layout_; + String text_; + Font font_; + TextStyle style_; + cpTextFormat text_format_; + cpTextLayout text_layout_; }; } \ No newline at end of file diff --git a/core/base/TextRenderer.cpp b/core/base/TextRenderer.cpp index 8d34e0af..539067af 100644 --- a/core/base/TextRenderer.cpp +++ b/core/base/TextRenderer.cpp @@ -24,7 +24,7 @@ namespace easy2d { - ITextRenderer::ITextRenderer(ID2D1Factory* pD2DFactory, ID2D1HwndRenderTarget* pRT, ID2D1SolidColorBrush* pBrush) + ITextRenderer::ITextRenderer(ID2D1Factory* pD2DFactory, ID2D1RenderTarget* pRT, ID2D1SolidColorBrush* pBrush) : cRefCount_(0) , pD2DFactory_(pD2DFactory) , pRT_(pRT) @@ -50,7 +50,7 @@ namespace easy2d HRESULT ITextRenderer::Create( ITextRenderer** ppTextRenderer, ID2D1Factory* pD2DFactory, - ID2D1HwndRenderTarget* pRT, + ID2D1RenderTarget* pRT, ID2D1SolidColorBrush* pBrush) { *ppTextRenderer = new (std::nothrow) ITextRenderer(pD2DFactory, pRT, pBrush); diff --git a/core/base/TextRenderer.h b/core/base/TextRenderer.h index c29c99cb..3e393138 100644 --- a/core/base/TextRenderer.h +++ b/core/base/TextRenderer.h @@ -30,7 +30,7 @@ namespace easy2d static HRESULT Create( ITextRenderer** ppTextRenderer, ID2D1Factory* pD2DFactory, - ID2D1HwndRenderTarget* pRT, + ID2D1RenderTarget* pRT, ID2D1SolidColorBrush* pBrush ); @@ -104,7 +104,7 @@ namespace easy2d private: ITextRenderer( ID2D1Factory* pD2DFactory, - ID2D1HwndRenderTarget* pRT, + ID2D1RenderTarget* pRT, ID2D1SolidColorBrush* pBrush ); @@ -117,10 +117,10 @@ namespace easy2d FLOAT fOutlineWidth; BOOL bShowOutline_; ID2D1Factory* pD2DFactory_; - ID2D1HwndRenderTarget* pRT_; + ID2D1RenderTarget* pRT_; ID2D1SolidColorBrush* pBrush_; ID2D1StrokeStyle* pCurrStrokeStyle_; }; } -E2D_DECLARE_D2D_SMART_PTR(easy2d::ITextRenderer, spTextRenderer); +E2D_DECLARE_D2D_SMART_PTR(easy2d::ITextRenderer, cpTextRenderer); diff --git a/core/base/Transform.hpp b/core/base/Transform.hpp index 5f775edb..8554d6f3 100644 --- a/core/base/Transform.hpp +++ b/core/base/Transform.hpp @@ -65,4 +65,13 @@ namespace easy2d pivot == other.pivot; } }; + + inline D2D1_MATRIX_3X2_F ConvertToD2DMatrix(math::Matrix const& matrix) + { + return D2D1_MATRIX_3X2_F{ + matrix.m[0], matrix.m[1], + matrix.m[2], matrix.m[3], + matrix.m[4], matrix.m[5] + }; + } } diff --git a/core/base/d2dres.hpp b/core/base/d2dres.hpp index ec9cfe19..4dcb327d 100644 --- a/core/base/d2dres.hpp +++ b/core/base/d2dres.hpp @@ -36,12 +36,16 @@ namespace easy2d E2D_DECLARE_D2D_SMART_PTR(IWICImagingFactory, cpImagingFactory); E2D_DECLARE_D2D_SMART_PTR(IDWriteFactory, cpWriteFactory); E2D_DECLARE_D2D_SMART_PTR(ID2D1SolidColorBrush, cpSolidColorBrush); - E2D_DECLARE_D2D_SMART_PTR(ID2D1HwndRenderTarget, cpRenderTarget); + E2D_DECLARE_D2D_SMART_PTR(ID2D1RenderTarget, cpRenderTarget); + E2D_DECLARE_D2D_SMART_PTR(ID2D1HwndRenderTarget, cpHwndRenderTarget); + E2D_DECLARE_D2D_SMART_PTR(ID2D1BitmapRenderTarget, cpBitmapRenderTarget); E2D_DECLARE_D2D_SMART_PTR(ID2D1StrokeStyle, cpStrokeStyle); E2D_DECLARE_D2D_SMART_PTR(ID2D1Layer, cpLayer); E2D_DECLARE_D2D_SMART_PTR(ID2D1Bitmap, cpBitmap); E2D_DECLARE_D2D_SMART_PTR(ID2D1Geometry, cpGeometry); + E2D_DECLARE_D2D_SMART_PTR(ID2D1PathGeometry, cpPathGeometry); + E2D_DECLARE_D2D_SMART_PTR(ID2D1GeometrySink, cpGeometrySink); E2D_DECLARE_D2D_SMART_PTR(IDWriteTextFormat, cpTextFormat); E2D_DECLARE_D2D_SMART_PTR(IDWriteTextLayout, cpTextLayout); diff --git a/core/base/logs.cpp b/core/base/logs.cpp index f84d9dc1..b147e25a 100644 --- a/core/base/logs.cpp +++ b/core/base/logs.cpp @@ -22,6 +22,8 @@ #include "logs.h" #include #include +#include +#include namespace easy2d { diff --git a/core/base/logs.h b/core/base/logs.h index 525ba414..1ebeae63 100644 --- a/core/base/logs.h +++ b/core/base/logs.h @@ -20,9 +20,6 @@ #pragma once #include "macros.h" -#include -#include -#include #ifndef E2D_LOG # ifdef E2D_DEBUG diff --git a/core/base/noncopyable.hpp b/core/base/noncopyable.hpp index 17496ea7..34281a20 100644 --- a/core/base/noncopyable.hpp +++ b/core/base/noncopyable.hpp @@ -27,7 +27,7 @@ namespace easy2d protected: Noncopyable() = default; - ~Noncopyable() {}; + virtual ~Noncopyable() {}; private: Noncopyable(const Noncopyable&) = delete; diff --git a/core/base/render.cpp b/core/base/render.cpp index 02f0a261..c9bee55e 100644 --- a/core/base/render.cpp +++ b/core/base/render.cpp @@ -24,27 +24,17 @@ #include "logs.h" #include "modules.h" #include "Image.h" +#include "Transform.hpp" namespace easy2d { namespace devices { - namespace - { - inline D2D1_MATRIX_3X2_F ConvertToD2DMatrix(math::Matrix const& matrix) - { - return D2D1_MATRIX_3X2_F{ - matrix.m[0], matrix.m[1], - matrix.m[2], matrix.m[3], - matrix.m[4], matrix.m[5] - }; - } - } - GraphicsDevice::GraphicsDevice() : fps_text_format_(nullptr) , fps_text_layout_(nullptr) , clear_color_(D2D1::ColorF(D2D1::ColorF::Black)) + , opacity_(1.f) , initialized(false) { ZeroMemory(&d2d, sizeof(D2DResources)); @@ -207,13 +197,21 @@ namespace easy2d return hr; } - HRESULT GraphicsDevice::CreateTextFormat(cpTextFormat& text_format, Font const& font) const + HRESULT GraphicsDevice::CreatePathGeometry(cpPathGeometry & geometry) const + { + if (!d2d.factory) + return E_UNEXPECTED; + + return d2d.factory->CreatePathGeometry(&geometry); + } + + HRESULT GraphicsDevice::CreateTextFormat(cpTextFormat & text_format, Font const & font, TextStyle const & text_style) const { if (!d2d.write_factory) return E_UNEXPECTED; - text_format = nullptr; - return d2d.write_factory->CreateTextFormat( + cpTextFormat text_format_tmp; + HRESULT hr = d2d.write_factory->CreateTextFormat( font.family.c_str(), nullptr, DWRITE_FONT_WEIGHT(font.weight), @@ -221,26 +219,128 @@ namespace easy2d DWRITE_FONT_STRETCH_NORMAL, font.size, L"", - &text_format - );; + &text_format_tmp + ); + + if (SUCCEEDED(hr)) + { + if (text_style.line_spacing == 0.f) + { + text_format_tmp->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0); + } + else + { + text_format_tmp->SetLineSpacing( + DWRITE_LINE_SPACING_METHOD_UNIFORM, + text_style.line_spacing, + text_style.line_spacing * 0.8f + ); + } + text_format_tmp->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(text_style.alignment)); + text_format_tmp->SetWordWrapping(text_style.wrap ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP); + text_format = text_format_tmp; + } + return hr; } - HRESULT GraphicsDevice::CreateTextLayout(cpTextLayout& text_layout, String const& text, cpTextFormat const& text_format, float wrap_width) const + HRESULT GraphicsDevice::CreateTextLayout(cpTextLayout & text_layout, Size& layout_size, String const & text, cpTextFormat const& text_format, TextStyle const & text_style) const { if (!d2d.write_factory) return E_UNEXPECTED; text_layout = nullptr; + HRESULT hr; + cpTextLayout text_layout_tmp; UINT32 length = static_cast(text.length()); - return d2d.write_factory->CreateTextLayout( - text.c_str(), - length, - text_format.Get(), - wrap_width, - 0, - &text_layout + + if (text_style.wrap) + { + hr = d2d.write_factory->CreateTextLayout( + text.c_str(), + length, + text_format.Get(), + text_style.wrap_width, + 0, + &text_layout_tmp + ); + } + else + { + hr = d2d.write_factory->CreateTextLayout( + text.c_str(), + length, + text_format.Get(), + 0, + 0, + &text_layout_tmp + ); + + DWRITE_TEXT_METRICS metrics; + text_layout_tmp->GetMetrics(&metrics); + + if (SUCCEEDED(hr)) + { + text_layout_tmp = nullptr; + hr = d2d.write_factory->CreateTextLayout( + text.c_str(), + length, + text_format.Get(), + metrics.width, + 0, + &text_layout_tmp + ); + } + } + + if (SUCCEEDED(hr)) + { + DWRITE_TEXT_METRICS metrics; + text_layout_tmp->GetMetrics(&metrics); + + if (text_style.wrap) + { + layout_size = Size(metrics.layoutWidth, metrics.height); + } + else + { + layout_size = Size(metrics.width, metrics.height); + } + + DWRITE_TEXT_RANGE range = { 0, length }; + if (text_style.underline) + { + text_layout_tmp->SetUnderline(true, range); + } + if (text_style.strikethrough) + { + text_layout_tmp->SetStrikethrough(true, range); + } + text_layout = text_layout_tmp; + } + return hr; + } + + HRESULT GraphicsDevice::CreateTextRenderer( + cpTextRenderer& text_renderer, + cpRenderTarget const& render_target, + cpSolidColorBrush const& brush + ) + { + if (!d2d.factory) + return E_UNEXPECTED; + + cpTextRenderer text_renderer_tmp; + HRESULT hr = ITextRenderer::Create( + &text_renderer_tmp, + d2d.factory.Get(), + render_target.Get(), + brush.Get() ); + + if (SUCCEEDED(hr)) + text_renderer = text_renderer_tmp; + return hr; } HRESULT GraphicsDevice::CreateLayer(cpLayer& layer) @@ -267,7 +367,6 @@ namespace easy2d HRESULT GraphicsDevice::DrawGeometry( cpGeometry const& geometry, Color const& border_color, - float opacity, float stroke_width, StrokeStyle stroke ) @@ -277,7 +376,6 @@ namespace easy2d return E_UNEXPECTED; d2d.solid_brush->SetColor(border_color); - d2d.solid_brush->SetOpacity(opacity); d2d.render_target->DrawGeometry( geometry.Get(), d2d.solid_brush.Get(), @@ -287,6 +385,24 @@ namespace easy2d return S_OK; } + HRESULT GraphicsDevice::DrawImage(spImage const & image) + { + if (!d2d.render_target) + return E_UNEXPECTED; + + if (!image->GetBitmap()) + return S_OK; + + d2d.render_target->DrawBitmap( + image->GetBitmap().Get(), + D2D1::RectF(0.f, 0.f, image->GetWidth(), image->GetHeight()), + opacity_, + D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, + image->GetCropRect() + ); + return S_OK; + } + cpStrokeStyle const& GraphicsDevice::GetStrokeStyle(StrokeStyle stroke) const { switch (stroke) @@ -304,27 +420,21 @@ namespace easy2d return d2d.miter_stroke_style; } - cpRenderTarget const & GraphicsDevice::GetRenderTarget() const - { - return d2d.render_target; - } - - HRESULT GraphicsDevice::DrawImage( - spImage const& image, - float opacity, - const Rect & dest_rect, - const Rect & source_rect + HRESULT GraphicsDevice::DrawBitmap( + cpBitmap const& bitmap ) { if (!d2d.render_target) return E_UNEXPECTED; + // Do not crop bitmap + auto rect = D2D1::RectF(0.f, 0.f, bitmap->GetSize().width, bitmap->GetSize().height); d2d.render_target->DrawBitmap( - image->GetBitmap().Get(), - dest_rect, - opacity, + bitmap.Get(), + rect, + opacity_, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, - source_rect + rect ); return S_OK; } @@ -389,6 +499,17 @@ namespace easy2d return S_OK; } + HRESULT GraphicsDevice::GetSize(Size & size) + { + if (!d2d.render_target) + return E_UNEXPECTED; + + auto rtsize = d2d.render_target->GetSize(); + size.width = rtsize.width; + size.height = rtsize.height; + return S_OK; + } + HRESULT GraphicsDevice::CreateBitmapFromFile(cpBitmap& bitmap, String const& file_path) { if (d2d.imaging_factory == nullptr || @@ -568,6 +689,15 @@ namespace easy2d return hr; } + HRESULT GraphicsDevice::CreateBitmapRenderTarget(cpBitmapRenderTarget & brt) + { + if (!d2d.render_target) + return E_UNEXPECTED; + + brt = nullptr; + return d2d.render_target->CreateCompatibleRenderTarget(&brt); + } + HRESULT GraphicsDevice::Resize(UINT32 width, UINT32 height) { if (!d2d.render_target) @@ -586,11 +716,12 @@ namespace easy2d return S_OK; } - HRESULT GraphicsDevice::SetBrushOpacity(float opacity) + HRESULT GraphicsDevice::SetOpacity(float opacity) { if (!d2d.render_target) return E_UNEXPECTED; + opacity_ = opacity; d2d.solid_brush->SetOpacity(opacity); return S_OK; } @@ -631,7 +762,16 @@ namespace easy2d if (!fps_text_format_) { ThrowIfFailed( - CreateTextFormat(fps_text_format_, Font{ L"", 20 }) + d2d.write_factory->CreateTextFormat( + L"", + nullptr, + DWRITE_FONT_WEIGHT::DWRITE_FONT_WEIGHT_NORMAL, + DWRITE_FONT_STYLE_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, + 20, + L"", + &fps_text_format_ + ) ); fps_text_format_->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); @@ -646,8 +786,16 @@ namespace easy2d last_render_time_ = time::Now(); render_times_ = 0; + fps_text_layout_ = nullptr; ThrowIfFailed( - CreateTextLayout(fps_text_layout_, fps_text, fps_text_format_, 0) + d2d.write_factory->CreateTextLayout( + fps_text, + len, + fps_text_format_.Get(), + 0, + 0, + &fps_text_layout_ + ) ); } diff --git a/core/base/render.h b/core/base/render.h index ab61b75c..d7cb492b 100644 --- a/core/base/render.h +++ b/core/base/render.h @@ -24,6 +24,7 @@ #include "Font.hpp" #include "Resource.h" #include "TextRenderer.h" +#include "TextStyle.hpp" #include "../math/Matrix.hpp" namespace easy2d @@ -37,9 +38,9 @@ namespace easy2d cpFactory factory; cpImagingFactory imaging_factory; cpWriteFactory write_factory; - spTextRenderer text_renderer; + cpTextRenderer text_renderer; cpSolidColorBrush solid_brush; - cpRenderTarget render_target; + cpHwndRenderTarget render_target; cpStrokeStyle miter_stroke_style; cpStrokeStyle bevel_stroke_style; cpStrokeStyle round_stroke_style; @@ -76,18 +77,30 @@ namespace easy2d const Size& size ) const; + HRESULT CreatePathGeometry( + cpPathGeometry& geometry + ) const; + HRESULT CreateTextFormat( cpTextFormat& text_format, - Font const& font + Font const& font, + TextStyle const& text_style ) const; HRESULT CreateTextLayout( cpTextLayout& text_layout, + Size& layout_size, String const& text, cpTextFormat const& text_format, - float wrap_width + TextStyle const& text_style ) const; + HRESULT CreateTextRenderer( + cpTextRenderer& text_renderer, + cpRenderTarget const& render_target, + cpSolidColorBrush const& brush + ); + HRESULT CreateLayer( cpLayer& layer ); @@ -96,17 +109,29 @@ namespace easy2d cpSolidColorBrush& brush ) const; + HRESULT CreateBitmapFromFile( + cpBitmap& bitmap, + String const& file_path + ); + + HRESULT CreateBitmapFromResource( + cpBitmap& bitmap, + Resource const& res + ); + + HRESULT CreateBitmapRenderTarget( + cpBitmapRenderTarget& brt + ); + cpStrokeStyle const& GetStrokeStyle( StrokeStyle stroke ) const; - cpRenderTarget const& GetRenderTarget() const; - HRESULT SetTransform( const math::Matrix& matrix ); - HRESULT SetBrushOpacity( + HRESULT SetOpacity( float opacity ); @@ -121,16 +146,16 @@ namespace easy2d HRESULT DrawGeometry( cpGeometry const& geometry, const Color& border_color, - float opacity, float stroke_width, StrokeStyle stroke = StrokeStyle::Miter ); HRESULT DrawImage( - spImage const& image, - float opacity, - const Rect& dest_rect, - const Rect& source_rect + spImage const& image + ); + + HRESULT DrawBitmap( + cpBitmap const& bitmap ); HRESULT DrawTextLayout( @@ -151,14 +176,8 @@ namespace easy2d HRESULT PopLayer(); - HRESULT CreateBitmapFromFile( - cpBitmap& bitmap, - String const& file_path - ); - - HRESULT CreateBitmapFromResource( - cpBitmap& bitmap, - Resource const& res + HRESULT GetSize( + Size& size ); HRESULT Resize( @@ -174,12 +193,13 @@ namespace easy2d ~GraphicsDevice(); protected: - bool initialized; - D2DResources d2d; - D2D1_COLOR_F clear_color_; - cpTextFormat fps_text_format_; - cpTextLayout fps_text_layout_; - std::map bitmap_cache_; + bool initialized; + float opacity_; + D2DResources d2d; + D2D1_COLOR_F clear_color_; + cpTextFormat fps_text_format_; + cpTextLayout fps_text_layout_; + std::map bitmap_cache_; }; E2D_DECLARE_SINGLETON_TYPE(GraphicsDevice, Graphics); diff --git a/core/base/window.cpp b/core/base/window.cpp index 6c599b6f..77e95504 100644 --- a/core/base/window.cpp +++ b/core/base/window.cpp @@ -220,6 +220,17 @@ namespace easy2d return scale_y; } + void WindowImpl::Poll() + { + static MSG msg = {}; + + while (::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) + { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + } + namespace { void GetContentScale(float* scale_x, float* scale_y) diff --git a/core/base/window.h b/core/base/window.h index 2ee6ac30..42dc41dd 100644 --- a/core/base/window.h +++ b/core/base/window.h @@ -24,8 +24,6 @@ namespace easy2d { - - class WindowImpl : protected Noncopyable { @@ -67,6 +65,8 @@ namespace easy2d float GetContentScaleY() const; + void Poll(); + protected: WindowImpl(); diff --git a/core/math/Matrix.hpp b/core/math/Matrix.hpp index 2a175a90..e3f46f0b 100644 --- a/core/math/Matrix.hpp +++ b/core/math/Matrix.hpp @@ -177,9 +177,9 @@ namespace easy2d float tx = math::Tan(angle_x); float ty = math::Tan(angle_y); return Matrix( - 1.f, tx, - ty, 1.f, - -center.y * tx, -center.x * ty + 1.f, -ty, + -tx, 1.f, + center.y * tx, center.x * ty ); } };