diff --git a/projects/kiwano.vcxproj b/projects/kiwano.vcxproj
index 30e05eaf..5471ccdc 100644
--- a/projects/kiwano.vcxproj
+++ b/projects/kiwano.vcxproj
@@ -64,6 +64,7 @@
+
@@ -127,6 +128,7 @@
+
diff --git a/projects/kiwano.vcxproj.filters b/projects/kiwano.vcxproj.filters
index de732345..84c50126 100644
--- a/projects/kiwano.vcxproj.filters
+++ b/projects/kiwano.vcxproj.filters
@@ -306,6 +306,9 @@
renderer
+
+ renderer
+
@@ -482,5 +485,8 @@
renderer
+
+ renderer
+
\ No newline at end of file
diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp
index 49b0bd4d..9bb197e1 100644
--- a/src/kiwano/2d/Actor.cpp
+++ b/src/kiwano/2d/Actor.cpp
@@ -128,11 +128,15 @@ namespace kiwano
{
if (show_border_ && !size_.IsOrigin())
{
- Rect bounds = GetBounds();
+ Rect bounds = GetBounds();
rt->SetTransform(transform_matrix_);
- rt->FillRectangle(bounds, Color(Color::Red, .4f));
- rt->DrawRectangle(bounds, Color(Color::Red, .8f), 2.f);
+
+ rt->SetDefaultBrushColor(Color(Color::Red, .4f));
+ rt->FillRectangle(bounds);
+
+ rt->SetDefaultBrushColor(Color(Color::Red, .8f));
+ rt->DrawRectangle(bounds, 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 3a89408d..df128b82 100644
--- a/src/kiwano/2d/Canvas.cpp
+++ b/src/kiwano/2d/Canvas.cpp
@@ -149,10 +149,10 @@ namespace kiwano
void Canvas::DrawLine(Point const& begin, Point const& end)
{
+ rt_.SetDefaultBrushColor(stroke_color_);
rt_.DrawLine(
begin,
end,
- stroke_color_,
stroke_width_,
stroke_style_
);
@@ -161,10 +161,10 @@ namespace kiwano
void Canvas::DrawCircle(Point const& center, Float32 radius)
{
+ rt_.SetDefaultBrushColor(stroke_color_);
rt_.DrawEllipse(
center,
Vec2(radius, radius),
- stroke_color_,
stroke_width_,
stroke_style_
);
@@ -173,10 +173,10 @@ namespace kiwano
void Canvas::DrawEllipse(Point const& center, Vec2 const& radius)
{
+ rt_.SetDefaultBrushColor(stroke_color_);
rt_.DrawEllipse(
center,
radius,
- stroke_color_,
stroke_width_,
stroke_style_
);
@@ -185,9 +185,9 @@ namespace kiwano
void Canvas::DrawRect(Rect const& rect)
{
+ rt_.SetDefaultBrushColor(stroke_color_);
rt_.DrawRectangle(
rect,
- stroke_color_,
stroke_width_,
stroke_style_
);
@@ -196,10 +196,10 @@ namespace kiwano
void Canvas::DrawRoundedRect(Rect const& rect, Vec2 const& radius)
{
+ rt_.SetDefaultBrushColor(stroke_color_);
rt_.DrawRoundedRectangle(
rect,
radius,
- stroke_color_,
stroke_width_,
stroke_style_
);
@@ -208,39 +208,39 @@ namespace kiwano
void Canvas::FillCircle(Point const& center, Float32 radius)
{
+ rt_.SetDefaultBrushColor(fill_color_);
rt_.FillEllipse(
center,
- Vec2(radius, radius),
- fill_color_
+ Vec2(radius, radius)
);
cache_expired_ = true;
}
void Canvas::FillEllipse(Point const& center, Vec2 const& radius)
{
+ rt_.SetDefaultBrushColor(fill_color_);
rt_.FillEllipse(
center,
- radius,
- fill_color_
+ radius
);
cache_expired_ = true;
}
void Canvas::FillRect(Rect const& rect)
{
+ rt_.SetDefaultBrushColor(fill_color_);
rt_.FillRectangle(
- rect,
- fill_color_
+ rect
);
cache_expired_ = true;
}
void Canvas::FillRoundedRect(Rect const& rect, Vec2 const& radius)
{
+ rt_.SetDefaultBrushColor(fill_color_);
rt_.FillRoundedRectangle(
rect,
- radius,
- fill_color_
+ radius
);
cache_expired_ = true;
}
@@ -296,9 +296,9 @@ namespace kiwano
void Canvas::StrokePath()
{
+ rt_.SetDefaultBrushColor(stroke_color_);
rt_.DrawGeometry(
geo_sink_.GetGeometry(),
- stroke_color_,
stroke_width_,
stroke_style_
);
@@ -307,9 +307,9 @@ namespace kiwano
void Canvas::FillPath()
{
+ rt_.SetDefaultBrushColor(fill_color_);
rt_.FillGeometry(
- geo_sink_.GetGeometry(),
- fill_color_
+ geo_sink_.GetGeometry()
);
cache_expired_ = true;
}
diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp
index 565fdc5d..d5cac48a 100644
--- a/src/kiwano/2d/DebugActor.cpp
+++ b/src/kiwano/2d/DebugActor.cpp
@@ -78,7 +78,8 @@ namespace kiwano
{
PrepareRender(rt);
- rt->FillRoundedRectangle(GetBounds(), Vec2{ 5.f, 5.f }, background_color_);
+ rt->SetDefaultBrushColor(background_color_);
+ rt->FillRoundedRectangle(GetBounds(), Vec2{ 5.f, 5.f });
}
void DebugActor::OnUpdate(Duration dt)
diff --git a/src/kiwano/2d/Layer.cpp b/src/kiwano/2d/Layer.cpp
index 0c6e6d8e..da60b65f 100644
--- a/src/kiwano/2d/Layer.cpp
+++ b/src/kiwano/2d/Layer.cpp
@@ -84,14 +84,11 @@ namespace kiwano
void Layer::Render(RenderTarget* rt)
{
- if (!children_.empty())
- {
- PrepareRender(rt);
+ PrepareRender(rt);
- rt->PushLayer(area_);
- Actor::Render(rt);
- rt->PopLayer();
- }
+ rt->PushLayer(area_);
+ Actor::Render(rt);
+ rt->PopLayer();
}
void Layer::HandleMessages(Event const& evt)
diff --git a/src/kiwano/2d/ShapeActor.cpp b/src/kiwano/2d/ShapeActor.cpp
index b01477c0..362f658d 100644
--- a/src/kiwano/2d/ShapeActor.cpp
+++ b/src/kiwano/2d/ShapeActor.cpp
@@ -101,16 +101,16 @@ namespace kiwano
{
PrepareRender(rt);
+ rt->SetDefaultBrushColor(stroke_color_);
rt->DrawGeometry(
geo_,
- stroke_color_,
stroke_width_ * 2, // twice width for widening
stroke_style_
);
+ rt->SetDefaultBrushColor(fill_color_);
rt->FillGeometry(
- geo_,
- fill_color_
+ geo_
);
}
}
diff --git a/src/kiwano/base/Event.hpp b/src/kiwano/base/Event.hpp
index 88eb4d4b..b9ef63f3 100644
--- a/src/kiwano/base/Event.hpp
+++ b/src/kiwano/base/Event.hpp
@@ -45,7 +45,7 @@ namespace kiwano
};
};
- static bool Check(UInt32 type);
+ static bool Check(Int32 type);
};
// 键盘事件
@@ -65,7 +65,7 @@ namespace kiwano
};
};
- static bool Check(UInt32 type);
+ static bool Check(Int32 type);
};
// 窗口事件
@@ -96,7 +96,7 @@ namespace kiwano
};
};
- static bool Check(UInt32 type);
+ static bool Check(Int32 type);
};
// 自定义事件
@@ -110,7 +110,7 @@ namespace kiwano
// 事件
struct KGE_API Event
{
- enum Type : UInt32
+ enum Type : Int32
{
First,
@@ -144,34 +144,34 @@ namespace kiwano
Last
};
- UInt32 type;
+ Int32 type;
Actor* target;
union
{
MouseEvent mouse;
KeyboardEvent key;
- WindowEvent win;
+ WindowEvent window;
CustomEvent custom;
};
- Event(UInt32 type = Type::First) : type(type), target(nullptr) {}
+ Event(Int32 type = Type::First) : type(type), target(nullptr) {}
};
// Check-functions
- inline bool MouseEvent::Check(UInt32 type)
+ inline bool MouseEvent::Check(Int32 type)
{
return type > Event::MouseFirst && type < Event::MouseLast;
}
- inline bool KeyboardEvent::Check(UInt32 type)
+ inline bool KeyboardEvent::Check(Int32 type)
{
return type > Event::KeyFirst && type < Event::KeyLast;
}
- inline bool WindowEvent::Check(UInt32 type)
+ inline bool WindowEvent::Check(Int32 type)
{
return type > Event::WindowFirst && type < Event::WindowLast;
}
diff --git a/src/kiwano/platform/Application.cpp b/src/kiwano/platform/Application.cpp
index 3b127c28..eef496e1 100644
--- a/src/kiwano/platform/Application.cpp
+++ b/src/kiwano/platform/Application.cpp
@@ -42,6 +42,7 @@ namespace kiwano
}
Config::Config(String const& title, UInt32 width, UInt32 height, UInt32 icon)
+ : debug(false)
{
window.title = title;
window.width = width;
@@ -50,6 +51,7 @@ namespace kiwano
}
Config::Config(WindowConfig const& wnd_config, RenderConfig const& render_config)
+ : debug(false)
{
window = wnd_config;
render = render_config;
@@ -382,8 +384,8 @@ namespace kiwano
Window::GetInstance()->UpdateWindowRect();
Event evt(Event::WindowResized);
- evt.win.width = LOWORD(lparam);
- evt.win.height = HIWORD(lparam);
+ evt.window.width = LOWORD(lparam);
+ evt.window.height = HIWORD(lparam);
app->DispatchEvent(evt);
}
}
@@ -395,8 +397,8 @@ namespace kiwano
Int32 y = (Int32)(short)HIWORD(lparam);
Event evt(Event::WindowMoved);
- evt.win.x = x;
- evt.win.y = y;
+ evt.window.x = x;
+ evt.window.y = y;
app->DispatchEvent(evt);
}
break;
@@ -408,7 +410,7 @@ namespace kiwano
Window::GetInstance()->SetActive(active);
Event evt(Event::WindowFocusChanged);
- evt.win.focus = active;
+ evt.window.focus = active;
app->DispatchEvent(evt);
}
break;
@@ -418,7 +420,7 @@ namespace kiwano
// KGE_LOG(L"Window title changed");
Event evt(Event::WindowTitleChanged);
- evt.win.title = reinterpret_cast(lparam);
+ evt.window.title = reinterpret_cast(lparam);
app->DispatchEvent(evt);
}
break;
diff --git a/src/kiwano/renderer/Brush.cpp b/src/kiwano/renderer/Brush.cpp
new file mode 100644
index 00000000..1515967b
--- /dev/null
+++ b/src/kiwano/renderer/Brush.cpp
@@ -0,0 +1,142 @@
+// Copyright (c) 2016-2018 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 "Brush.h"
+#include "Renderer.h"
+#include "../base/Logger.h"
+
+namespace kiwano
+{
+ SolidColorStyle::SolidColorStyle(Color const& color)
+ : color(color)
+ {
+ }
+
+ LinearGradientStyle::LinearGradientStyle(Point const& begin, Point const& end, Vector const& stops, GradientExtendMode extend_mode)
+ : begin(begin)
+ , end(end)
+ , stops(stops)
+ , extend_mode(extend_mode)
+ {
+ }
+
+ RadialGradientStyle::RadialGradientStyle(Point const& center, Vec2 const& offset, Vec2 const& radius, Vector const& stops, GradientExtendMode extend_mode)
+ : center(center)
+ , offset(offset)
+ , radius(radius)
+ , stops(stops)
+ , extend_mode(extend_mode)
+ {
+ }
+
+ Brush::Brush()
+ : opacity_(1.f)
+ , type_(Type::Unknown)
+ {
+ }
+
+ Brush::Brush(Color const& color)
+ : Brush()
+ {
+ SetColor(color);
+ }
+
+ Brush::Brush(SolidColorStyle const& style)
+ : Brush()
+ {
+ SetStyle(style);
+ }
+
+ Brush::Brush(LinearGradientStyle const& style)
+ : Brush()
+ {
+ SetStyle(style);
+ }
+
+ Brush::Brush(RadialGradientStyle const& style)
+ : Brush()
+ {
+ SetStyle(style);
+ }
+
+ bool Brush::IsValid() const
+ {
+ return raw_ != nullptr;
+ }
+
+ Brush::Brush(ComPtr brush)
+ : Brush()
+ {
+ SetBrush(brush);
+ }
+
+ Float32 Brush::GetOpacity() const
+ {
+ return opacity_;
+ }
+
+ void Brush::SetOpacity(Float32 opacity)
+ {
+ opacity_ = opacity;
+ if (raw_)
+ {
+ raw_->SetOpacity(opacity);
+ }
+ }
+
+ void Brush::SetStyle(SolidColorStyle const& style)
+ {
+ if (type_ == Type::SolidColor && raw_)
+ {
+ auto solid_brush = dynamic_cast(raw_.get());
+ KGE_ASSERT(solid_brush != nullptr);
+ solid_brush->SetColor(DX::ConvertToColorF(style.color));
+ }
+ else
+ {
+ Renderer::GetInstance()->CreateSolidBrush(*this, style.color);
+ type_ = Type::SolidColor;
+ }
+ }
+
+ void Brush::SetStyle(LinearGradientStyle const& style)
+ {
+ Renderer::GetInstance()->CreateLinearGradientBrush(*this, style.begin, style.end, style.stops, style.extend_mode);
+ type_ = Type::LinearGradient;
+ }
+
+ void Brush::SetStyle(RadialGradientStyle const& style)
+ {
+ Renderer::GetInstance()->CreateRadialGradientBrush(*this, style.center, style.offset, style.radius, style.stops, style.extend_mode);
+ type_ = Type::RadialGradient;
+ }
+
+ void Brush::SetBrush(ComPtr const& brush)
+ {
+ type_ = Type::Unknown;
+ raw_ = brush;
+
+ if (raw_)
+ {
+ raw_->SetOpacity(opacity_);
+ }
+ }
+
+}
diff --git a/src/kiwano/renderer/Brush.h b/src/kiwano/renderer/Brush.h
new file mode 100644
index 00000000..9d7ab25f
--- /dev/null
+++ b/src/kiwano/renderer/Brush.h
@@ -0,0 +1,166 @@
+// Copyright (c) 2016-2018 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 "win32/D2DDeviceResources.h"
+
+namespace kiwano
+{
+ // 渐变转换点
+ struct GradientStop
+ {
+ Float32 offset;
+ Color color;
+
+ GradientStop() : offset(0.f), color() {}
+
+ GradientStop(Float32 offset, Color color) : offset(offset), color(color) {}
+ };
+
+
+ // 渐变扩充模式
+ // 该模式用于指定画笔如何绘制正常区域外的部分
+ // Clamp (夹模式): 重复绘制边界颜色
+ // Wrap (夹模式): 重复画笔内容
+ // Mirror (镜像模式): 反转画笔内容
+ enum class GradientExtendMode
+ {
+ Clamp,
+ Wrap,
+ Mirror
+ };
+
+
+ // 纯色样式
+ struct SolidColorStyle
+ {
+ Color color;
+
+ SolidColorStyle(Color const& color);
+ };
+
+ // 线性渐变样式
+ struct LinearGradientStyle
+ {
+ Point begin;
+ Point end;
+ Vector stops;
+ GradientExtendMode extend_mode;
+
+ LinearGradientStyle(
+ Point const& begin,
+ Point const& end,
+ Vector const& stops,
+ GradientExtendMode extend_mode = GradientExtendMode::Clamp
+ );
+ };
+
+ // 径向渐变样式
+ struct RadialGradientStyle
+ {
+ Point center;
+ Vec2 offset;
+ Vec2 radius;
+ Vector stops;
+ GradientExtendMode extend_mode;
+
+ RadialGradientStyle(
+ Point const& center,
+ Vec2 const& offset,
+ Vec2 const& radius,
+ Vector const& stops,
+ GradientExtendMode extend_mode = GradientExtendMode::Clamp
+ );
+ };
+
+ // 画笔
+ class KGE_API Brush
+ {
+ public:
+ Brush();
+
+ Brush(
+ Color const& color
+ );
+
+ Brush(
+ SolidColorStyle const& style
+ );
+
+ Brush(
+ LinearGradientStyle const& style
+ );
+
+ Brush(
+ RadialGradientStyle const& style
+ );
+
+ bool IsValid() const;
+
+ inline void SetColor(
+ Color const& color
+ )
+ {
+ SetStyle(SolidColorStyle{ color });
+ }
+
+ void SetStyle(
+ SolidColorStyle const& style
+ );
+
+ void SetStyle(
+ LinearGradientStyle const& style
+ );
+
+ void SetStyle(
+ RadialGradientStyle const& style
+ );
+
+ Float32 GetOpacity() const;
+
+ void SetOpacity(Float32 opacity);
+
+ public:
+ enum class Type
+ {
+ Unknown,
+ SolidColor, // 纯色填充
+ LinearGradient, // 线性渐变
+ RadialGradient // 径向渐变
+ };
+
+ Type GetType() const { return type_; }
+
+ public:
+ Brush(
+ ComPtr brush
+ );
+
+ void SetBrush(ComPtr const& brush);
+
+ inline ComPtr const& GetBrush() const { return raw_; }
+
+ protected:
+ Type type_;
+ Float32 opacity_;
+ ComPtr raw_;
+ };
+
+}
diff --git a/src/kiwano/renderer/RenderTarget.cpp b/src/kiwano/renderer/RenderTarget.cpp
index c6441c03..e3bacd95 100644
--- a/src/kiwano/renderer/RenderTarget.cpp
+++ b/src/kiwano/renderer/RenderTarget.cpp
@@ -67,6 +67,11 @@ namespace kiwano
);
}
+ if (SUCCEEDED(hr))
+ {
+ current_brush_ = default_brush_;
+ }
+
return hr;
}
@@ -86,8 +91,6 @@ namespace kiwano
void RenderTarget::BeginDraw()
{
- HRESULT hr = E_FAIL;
-
if (collecting_status_)
{
status_.start = Time::Now();
@@ -97,15 +100,12 @@ namespace kiwano
if (render_target_)
{
render_target_->BeginDraw();
- hr = S_OK;
}
-
- ThrowIfFailed(hr);
}
void RenderTarget::EndDraw()
{
- ThrowIfFailed(render_target_->EndDraw());
+ ThrowIfFailed( render_target_->EndDraw() );
if (collecting_status_)
{
@@ -113,26 +113,19 @@ namespace kiwano
}
}
- void RenderTarget::DrawGeometry(
- Geometry const& geometry,
- Color const& stroke_color,
- Float32 stroke_width,
- StrokeStyle stroke
- ) const
+ void RenderTarget::DrawGeometry(Geometry const& geometry, Float32 stroke_width, StrokeStyle stroke) const
{
HRESULT hr = S_OK;
- if (!default_brush_ || !render_target_)
+ if (!render_target_ || !current_brush_)
{
hr = E_UNEXPECTED;
}
if (SUCCEEDED(hr) && geometry.GetGeometry())
{
- default_brush_->SetColor(DX::ConvertToColorF(stroke_color));
-
render_target_->DrawGeometry(
geometry.GetGeometry().get(),
- default_brush_.get(),
+ current_brush_.get(),
stroke_width,
GetStrokeStyle(stroke).get()
);
@@ -143,42 +136,39 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void RenderTarget::FillGeometry(Geometry const& geometry, Color const& fill_color) const
+ void RenderTarget::FillGeometry(Geometry const& geometry) const
{
HRESULT hr = S_OK;
- if (!default_brush_ || !render_target_)
+ if (!render_target_ || !current_brush_)
{
hr = E_UNEXPECTED;
}
if (SUCCEEDED(hr) && geometry.GetGeometry())
{
- default_brush_->SetColor(DX::ConvertToColorF(fill_color));
render_target_->FillGeometry(
geometry.GetGeometry().get(),
- default_brush_.get()
+ current_brush_.get()
);
}
ThrowIfFailed(hr);
}
- void RenderTarget::DrawLine(Point const& point1, Point const& point2, Color const& stroke_color, Float32 stroke_width, StrokeStyle stroke) const
+ void RenderTarget::DrawLine(Point const& point1, Point const& point2, Float32 stroke_width, StrokeStyle stroke) const
{
HRESULT hr = S_OK;
- if (!default_brush_ || !render_target_)
+ if (!render_target_ || !current_brush_)
{
hr = E_UNEXPECTED;
}
if (SUCCEEDED(hr))
{
- default_brush_->SetColor(DX::ConvertToColorF(stroke_color));
-
render_target_->DrawLine(
DX::ConvertToPoint2F(point1),
DX::ConvertToPoint2F(point2),
- default_brush_.get(),
+ current_brush_.get(),
stroke_width,
GetStrokeStyle(stroke).get()
);
@@ -189,21 +179,20 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void RenderTarget::DrawRectangle(Rect const& rect, Color const& stroke_color, Float32 stroke_width, StrokeStyle stroke) const
+ void RenderTarget::DrawRectangle(Rect const& rect, Float32 stroke_width, StrokeStyle stroke) const
{
HRESULT hr = S_OK;
- if (!default_brush_ || !render_target_)
+
+ if (!render_target_ || !current_brush_)
{
hr = E_UNEXPECTED;
}
if (SUCCEEDED(hr))
{
- default_brush_->SetColor(DX::ConvertToColorF(stroke_color));
-
render_target_->DrawRectangle(
DX::ConvertToRectF(rect),
- default_brush_.get(),
+ current_brush_.get(),
stroke_width,
GetStrokeStyle(stroke).get()
);
@@ -214,45 +203,42 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void RenderTarget::FillRectangle(Rect const& rect, Color const& fill_color) const
+ void RenderTarget::FillRectangle(Rect const& rect) const
{
HRESULT hr = S_OK;
- if (!default_brush_ || !render_target_)
+ if (!render_target_ || !current_brush_)
{
hr = E_UNEXPECTED;
}
if (SUCCEEDED(hr))
{
- default_brush_->SetColor(DX::ConvertToColorF(fill_color));
render_target_->FillRectangle(
DX::ConvertToRectF(rect),
- default_brush_.get()
+ current_brush_.get()
);
}
ThrowIfFailed(hr);
}
- void RenderTarget::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, Color const& stroke_color, Float32 stroke_width, StrokeStyle stroke) const
+ void RenderTarget::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, Float32 stroke_width, StrokeStyle stroke) const
{
HRESULT hr = S_OK;
- if (!default_brush_ || !render_target_)
+ if (!render_target_ || !current_brush_)
{
hr = E_UNEXPECTED;
}
if (SUCCEEDED(hr))
{
- default_brush_->SetColor(DX::ConvertToColorF(stroke_color));
-
render_target_->DrawRoundedRectangle(
D2D1::RoundedRect(
DX::ConvertToRectF(rect),
radius.x,
radius.y
),
- default_brush_.get(),
+ current_brush_.get(),
stroke_width,
GetStrokeStyle(stroke).get()
);
@@ -263,49 +249,46 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void RenderTarget::FillRoundedRectangle(Rect const& rect, Vec2 const& radius, Color const& fill_color) const
+ void RenderTarget::FillRoundedRectangle(Rect const& rect, Vec2 const& radius) const
{
HRESULT hr = S_OK;
- if (!default_brush_ || !render_target_)
+ if (!render_target_ || !current_brush_)
{
hr = E_UNEXPECTED;
}
if (SUCCEEDED(hr))
{
- default_brush_->SetColor(DX::ConvertToColorF(fill_color));
render_target_->FillRoundedRectangle(
D2D1::RoundedRect(
DX::ConvertToRectF(rect),
radius.x,
radius.y
),
- default_brush_.get()
+ current_brush_.get()
);
}
ThrowIfFailed(hr);
}
- void RenderTarget::DrawEllipse(Point const& center, Vec2 const& radius, Color const& stroke_color, Float32 stroke_width, StrokeStyle stroke) const
+ void RenderTarget::DrawEllipse(Point const& center, Vec2 const& radius, Float32 stroke_width, StrokeStyle stroke) const
{
HRESULT hr = S_OK;
- if (!default_brush_ || !render_target_)
+ if (!render_target_ || !current_brush_)
{
hr = E_UNEXPECTED;
}
if (SUCCEEDED(hr))
{
- default_brush_->SetColor(DX::ConvertToColorF(stroke_color));
-
render_target_->DrawEllipse(
D2D1::Ellipse(
DX::ConvertToPoint2F(center),
radius.x,
radius.y
),
- default_brush_.get(),
+ current_brush_.get(),
stroke_width,
GetStrokeStyle(stroke).get()
);
@@ -316,24 +299,23 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void RenderTarget::FillEllipse(Point const& center, Vec2 const& radius, Color const& fill_color) const
+ void RenderTarget::FillEllipse(Point const& center, Vec2 const& radius) const
{
HRESULT hr = S_OK;
- if (!default_brush_ || !render_target_)
+ if (!render_target_ || !current_brush_)
{
hr = E_UNEXPECTED;
}
if (SUCCEEDED(hr))
{
- default_brush_->SetColor(DX::ConvertToColorF(fill_color));
render_target_->FillEllipse(
D2D1::Ellipse(
DX::ConvertToPoint2F(center),
radius.x,
radius.y
),
- default_brush_.get()
+ current_brush_.get()
);
}
@@ -464,7 +446,7 @@ namespace kiwano
void RenderTarget::PushLayer(LayerArea& layer)
{
HRESULT hr = S_OK;
- if (!render_target_ || !default_brush_)
+ if (!render_target_)
{
hr = E_UNEXPECTED;
}
@@ -540,6 +522,11 @@ namespace kiwano
return opacity_;
}
+ Brush RenderTarget::GetCurrentBrush() const
+ {
+ return Brush( current_brush_ );
+ }
+
Matrix3x2 RenderTarget::GetGlobalTransform() const
{
return global_transform_;
@@ -569,7 +556,6 @@ namespace kiwano
if (fast_global_transform_)
{
render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix));
-
}
else
{
@@ -602,7 +588,7 @@ namespace kiwano
void RenderTarget::SetOpacity(Float32 opacity)
{
HRESULT hr = S_OK;
- if (!default_brush_)
+ if (!current_brush_)
{
hr = E_UNEXPECTED;
}
@@ -612,13 +598,24 @@ namespace kiwano
if (opacity_ != opacity)
{
opacity_ = opacity;
- default_brush_->SetOpacity(opacity);
+ current_brush_->SetOpacity(opacity);
}
}
ThrowIfFailed(hr);
}
+ void RenderTarget::SetCurrentBrush(Brush const& brush)
+ {
+ current_brush_ = brush.GetBrush();
+ }
+
+ void RenderTarget::SetDefaultBrushColor(Color const& color)
+ {
+ KGE_ASSERT(default_brush_);
+ default_brush_->SetColor(DX::ConvertToColorF(color));
+ }
+
void RenderTarget::SetAntialiasMode(bool enabled)
{
HRESULT hr = S_OK;
diff --git a/src/kiwano/renderer/RenderTarget.h b/src/kiwano/renderer/RenderTarget.h
index bc95876a..d4362a02 100644
--- a/src/kiwano/renderer/RenderTarget.h
+++ b/src/kiwano/renderer/RenderTarget.h
@@ -20,6 +20,7 @@
#pragma once
#include "../base/time.h"
+#include "Brush.h"
#include "Texture.h"
#include "Geometry.h"
#include "TextLayout.h"
@@ -55,62 +56,53 @@ namespace kiwano
void DrawGeometry(
Geometry const& geometry,
- Color const& stroke_color,
Float32 stroke_width,
StrokeStyle stroke = StrokeStyle::Miter
) const;
void FillGeometry(
- Geometry const& geometry,
- Color const& fill_color
+ Geometry const& geometry
) const;
void DrawLine(
Point const& point1,
Point const& point2,
- Color const& stroke_color,
Float32 stroke_width,
StrokeStyle stroke = StrokeStyle::Miter
) const;
void DrawRectangle(
Rect const& rect,
- Color const& stroke_color,
Float32 stroke_width,
StrokeStyle stroke = StrokeStyle::Miter
) const;
void FillRectangle(
- Rect const& rect,
- Color const& fill_color
+ Rect const& rect
) const;
void DrawRoundedRectangle(
Rect const& rect,
Vec2 const& radius,
- Color const& stroke_color,
Float32 stroke_width,
StrokeStyle stroke = StrokeStyle::Miter
) const;
void FillRoundedRectangle(
Rect const& rect,
- Vec2 const& radius,
- Color const& fill_color
+ Vec2 const& radius
) const;
void DrawEllipse(
Point const& center,
Vec2 const& radius,
- Color const& stroke_color,
Float32 stroke_width,
StrokeStyle stroke = StrokeStyle::Miter
) const;
void FillEllipse(
Point const& center,
- Vec2 const& radius,
- Color const& fill_color
+ Vec2 const& radius
) const;
void DrawTexture(
@@ -150,12 +142,22 @@ namespace kiwano
Float32 GetOpacity() const;
+ Brush GetCurrentBrush() const;
+
Matrix3x2 GetGlobalTransform() const;
void SetOpacity(
Float32 opacity
);
+ void SetCurrentBrush(
+ Brush const& brush
+ );
+
+ void SetDefaultBrushColor(
+ Color const& color
+ );
+
void SetTransform(
const Matrix3x2& matrix
);
diff --git a/src/kiwano/renderer/Renderer.cpp b/src/kiwano/renderer/Renderer.cpp
index 699ba874..cb36d8d8 100644
--- a/src/kiwano/renderer/Renderer.cpp
+++ b/src/kiwano/renderer/Renderer.cpp
@@ -35,7 +35,6 @@ namespace kiwano
: hwnd_(nullptr)
, vsync_(true)
, clear_color_(Color::Black)
- , resolution_mode_(ResolutionMode::Fixed)
{
}
@@ -54,7 +53,7 @@ namespace kiwano
KGE_LOG(L"Creating device resources");
hwnd_ = Window::GetInstance()->GetHandle();
- resolution_ = output_size_ = Window::GetInstance()->GetSize();
+ output_size_ = Window::GetInstance()->GetSize();
d2d_res_ = nullptr;
d3d_res_ = nullptr;
@@ -71,19 +70,11 @@ namespace kiwano
// Direct3D device resources
if (SUCCEEDED(hr))
{
-#if defined(KGE_USE_DIRECTX10)
- hr = ID3D10DeviceResources::Create(
+ hr = ID3DDeviceResources::Create(
&d3d_res_,
d2d_res_.get(),
hwnd_
);
-#else
- hr = ID3D11DeviceResources::Create(
- &d3d_res_,
- d2d_res_.get(),
- hwnd_
- );
-#endif
}
// DrawingStateBlock
@@ -161,12 +152,6 @@ namespace kiwano
hr = E_UNEXPECTED;
}
- if (SUCCEEDED(hr))
- {
- render_target_->SaveDrawingState(drawing_state_block_.get());
- BeginDraw();
- }
-
if (SUCCEEDED(hr))
{
hr = d3d_res_->ClearRenderTarget(clear_color_);
@@ -174,8 +159,8 @@ namespace kiwano
if (SUCCEEDED(hr))
{
- SetTransform(Matrix3x2{});
- PushClipRect(Rect{ Point{}, resolution_ });
+ render_target_->SaveDrawingState(drawing_state_block_.get());
+ BeginDraw();
}
ThrowIfFailed(hr);
@@ -190,11 +175,8 @@ namespace kiwano
hr = E_UNEXPECTED;
}
-
if (SUCCEEDED(hr))
{
- PopClipRect();
-
EndDraw();
render_target_->RestoreDrawingState(drawing_state_block_.get());
@@ -890,29 +872,118 @@ namespace kiwano
ThrowIfFailed(hr);
}
+ void Renderer::CreateSolidBrush(Brush& brush, Color const& color)
+ {
+ HRESULT hr = S_OK;
+ if (!d2d_res_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ ComPtr output;
+ if (SUCCEEDED(hr))
+ {
+ hr = d2d_res_->GetDeviceContext()->CreateSolidColorBrush(DX::ConvertToColorF(color), &output);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ brush.SetBrush(output);
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void Renderer::CreateLinearGradientBrush(Brush& brush, Point const& begin, Point const& end, Vector const& stops, GradientExtendMode extend_mode)
+ {
+ HRESULT hr = S_OK;
+ if (!d2d_res_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ ID2D1GradientStopCollection* collection = nullptr;
+ hr = d2d_res_->GetDeviceContext()->CreateGradientStopCollection(
+ reinterpret_cast(&stops[0]),
+ stops.size(),
+ D2D1_GAMMA_2_2,
+ D2D1_EXTEND_MODE(extend_mode),
+ &collection
+ );
+
+ if (SUCCEEDED(hr))
+ {
+ ComPtr output;
+ hr = d2d_res_->GetDeviceContext()->CreateLinearGradientBrush(
+ D2D1::LinearGradientBrushProperties(
+ DX::ConvertToPoint2F(begin),
+ DX::ConvertToPoint2F(end)
+ ),
+ collection,
+ &output
+ );
+
+ if (SUCCEEDED(hr))
+ {
+ brush.SetBrush(output);
+ }
+ }
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void Renderer::CreateRadialGradientBrush(Brush& brush, Point const& center, Vec2 const& offset, Vec2 const& radius,
+ Vector const& stops, GradientExtendMode extend_mode)
+ {
+ HRESULT hr = S_OK;
+ if (!d2d_res_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ ID2D1GradientStopCollection* collection = nullptr;
+ hr = d2d_res_->GetDeviceContext()->CreateGradientStopCollection(
+ reinterpret_cast(&stops[0]),
+ stops.size(),
+ D2D1_GAMMA_2_2,
+ D2D1_EXTEND_MODE(extend_mode),
+ &collection
+ );
+
+ if (SUCCEEDED(hr))
+ {
+ ComPtr output;
+ hr = d2d_res_->GetDeviceContext()->CreateRadialGradientBrush(
+ D2D1::RadialGradientBrushProperties(
+ DX::ConvertToPoint2F(center),
+ DX::ConvertToPoint2F(offset),
+ radius.x,
+ radius.y
+ ),
+ collection,
+ &output
+ );
+
+ if (SUCCEEDED(hr))
+ {
+ brush.SetBrush(output);
+ }
+ }
+ }
+
+ ThrowIfFailed(hr);
+ }
+
void Renderer::SetVSyncEnabled(bool enabled)
{
vsync_ = enabled;
}
- void Renderer::SetResolution(Size const& resolution)
- {
- if (resolution_ != resolution)
- {
- resolution_ = resolution;
- UpdateResolution();
- }
- }
-
- void Renderer::SetResolutionMode(ResolutionMode mode)
- {
- if (resolution_mode_ != mode)
- {
- resolution_mode_ = mode;
- UpdateResolution();
- }
- }
-
void Renderer::SetClearColor(const Color& color)
{
clear_color_ = color;
@@ -933,58 +1004,7 @@ namespace kiwano
hr = d3d_res_->SetLogicalSize(output_size_);
}
- if (SUCCEEDED(hr))
- {
- UpdateResolution();
- }
-
ThrowIfFailed(hr);
}
- void Renderer::UpdateResolution()
- {
- switch (resolution_mode_)
- {
- case ResolutionMode::Fixed:
- {
- SetGlobalTransform(nullptr);
- break;
- }
-
- case ResolutionMode::Center:
- {
- Float32 left = math::Ceil((output_size_.x - resolution_.x) / 2);
- Float32 top = math::Ceil((output_size_.y - resolution_.y) / 2);
- SetGlobalTransform(Matrix3x2::Translation(Vec2{ left, top }));
- break;
- }
-
- case ResolutionMode::Stretch:
- {
- Float32 scalex = Float32(Int32((output_size_.x / resolution_.x) * 100 + 0.5f)) / 100;
- Float32 scaley = Float32(Int32((output_size_.y / resolution_.y) * 100 + 0.5f)) / 100;
- SetGlobalTransform(Matrix3x2::Scaling(Vec2{ scalex, scaley }));
- break;
- }
-
- case ResolutionMode::Adaptive:
- {
- Float32 scalex = Float32(Int32((output_size_.x / resolution_.x) * 100 + 0.5f)) / 100;
- Float32 scaley = Float32(Int32((output_size_.y / resolution_.y) * 100 + 0.5f)) / 100;
- if (scalex > scaley)
- {
- Float32 left = math::Ceil((output_size_.x - resolution_.x * scaley) / 2);
- SetGlobalTransform(Matrix3x2::SRT(Vec2{ left, 0 }, Vec2{ scaley, scaley }, 0));
- }
- else
- {
- Float32 top = math::Ceil((output_size_.y - resolution_.y * scalex) / 2);
- SetGlobalTransform(Matrix3x2::SRT(Vec2{ 0, top }, Vec2{ scalex, scalex }, 0));
-
- }
- break;
- }
- }
- }
-
}
diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h
index 4e14f017..86861fbb 100644
--- a/src/kiwano/renderer/Renderer.h
+++ b/src/kiwano/renderer/Renderer.h
@@ -51,20 +51,8 @@ namespace kiwano
);
};
- // 分辨率模式
- // 分辨率模式决定了将画面渲染到视区上的方式
- // Fixed (固定): 分辨率不随视区改变, 且画面始终与视区边界对齐(默认)
- // Center (居中): 分辨率不随视区改变, 且画面始终在视区上居中
- // Stretch (拉伸): 分辨率始终随视区等比例拉伸
- // Adaptive (宽高自适应): 分辨率始终保持宽高比, 且尽可能的填充视区, 可能会出现黑色边界
- enum class ResolutionMode
- {
- Fixed, /* 固定 */
- Center, /* 居中 */
- Stretch, /* 拉伸 */
- Adaptive, /* 宽高自适应 */
- };
+ // 渲染器
class KGE_API Renderer
: public Singleton
, public Component
@@ -83,16 +71,6 @@ namespace kiwano
bool enabled
);
- // 设置画面分辨率
- void SetResolution(
- Size const& resolution
- );
-
- // 设置分辨率模式
- void SetResolutionMode(
- ResolutionMode mode
- );
-
public:
void CreateTexture(
Texture& texture,
@@ -172,6 +150,28 @@ namespace kiwano
TextureRenderTarget& render_target
);
+ void CreateSolidBrush(
+ Brush& brush,
+ Color const& color
+ );
+
+ void CreateLinearGradientBrush(
+ Brush& brush,
+ Point const& begin,
+ Point const& end,
+ Vector const& stops,
+ GradientExtendMode extend_mode
+ );
+
+ void CreateRadialGradientBrush(
+ Brush& brush,
+ Point const& center,
+ Vec2 const& offset,
+ Vec2 const& radius,
+ Vector const& stops,
+ GradientExtendMode extend_mode
+ );
+
public:
void Init(RenderConfig const& config);
@@ -190,8 +190,6 @@ namespace kiwano
inline Size const& GetOutputSize() const { return output_size_; }
- inline Size const& GetResolution() const { return resolution_; }
-
inline Color const& GetClearColor() const { return clear_color_; }
inline ID2DDeviceResources* GetD2DDeviceResources() const { KGE_ASSERT(d2d_res_); return d2d_res_.get(); }
@@ -209,15 +207,11 @@ namespace kiwano
void ResizeTarget(UInt32 width, UInt32 height);
- void UpdateResolution();
-
private:
bool vsync_;
HWND hwnd_;
Color clear_color_;
Size output_size_;
- Size resolution_;
- ResolutionMode resolution_mode_;
ComPtr d2d_res_;
ComPtr d3d_res_;
diff --git a/src/kiwano/renderer/win32/TextRenderer.cpp b/src/kiwano/renderer/win32/TextRenderer.cpp
index 7b0c7502..330f64b7 100644
--- a/src/kiwano/renderer/win32/TextRenderer.cpp
+++ b/src/kiwano/renderer/win32/TextRenderer.cpp
@@ -35,12 +35,12 @@ namespace kiwano
STDMETHOD(CreateDeviceResources)();
STDMETHOD_(void, SetTextStyle)(
- _In_ Float32 opacity,
- _In_ CONST D2D1_COLOR_F &fillColor,
- _In_ BOOL outline,
- _In_ CONST D2D1_COLOR_F &outlineColor,
- _In_ Float32 outlineWidth,
- _In_ ID2D1StrokeStyle* outlineJoin
+ _In_ Float32 opacity,
+ _In_ CONST D2D1_COLOR_F &fillColor,
+ _In_ BOOL outline,
+ _In_ CONST D2D1_COLOR_F &outlineColor,
+ _In_ Float32 outlineWidth,
+ _In_ ID2D1StrokeStyle* outlineJoin
);
STDMETHOD(DrawGlyphRun)(
diff --git a/src/kiwano/renderer/win32/TextRenderer.h b/src/kiwano/renderer/win32/TextRenderer.h
index 519cc577..8b5f95e2 100644
--- a/src/kiwano/renderer/win32/TextRenderer.h
+++ b/src/kiwano/renderer/win32/TextRenderer.h
@@ -34,10 +34,10 @@ namespace kiwano
STDMETHOD_(void, SetTextStyle)(
_In_ Float32 opacity,
- _In_ CONST D2D1_COLOR_F &fillColor,
- _In_ BOOL outline,
- _In_ CONST D2D1_COLOR_F &outlineColor,
- _In_ Float32 outlineWidth,
+ _In_ CONST D2D1_COLOR_F &fillColor,
+ _In_ BOOL outline,
+ _In_ CONST D2D1_COLOR_F &outlineColor,
+ _In_ Float32 outlineWidth,
_In_ ID2D1StrokeStyle* outlineJoin
) PURE;
};