Add Brush

This commit is contained in:
Nomango 2019-09-09 22:02:53 +08:00
parent 7f954e0c2c
commit a4d4c3a10f
16 changed files with 560 additions and 112 deletions

View File

@ -64,6 +64,7 @@
<ClInclude Include="..\src\kiwano\math\Vec2.hpp" /> <ClInclude Include="..\src\kiwano\math\Vec2.hpp" />
<ClInclude Include="..\src\kiwano\platform\Application.h" /> <ClInclude Include="..\src\kiwano\platform\Application.h" />
<ClInclude Include="..\src\kiwano\platform\modules.h" /> <ClInclude Include="..\src\kiwano\platform\modules.h" />
<ClInclude Include="..\src\kiwano\renderer\Brush.h" />
<ClInclude Include="..\src\kiwano\renderer\Color.h" /> <ClInclude Include="..\src\kiwano\renderer\Color.h" />
<ClInclude Include="..\src\kiwano\renderer\Font.h" /> <ClInclude Include="..\src\kiwano\renderer\Font.h" />
<ClInclude Include="..\src\kiwano\renderer\FontCollection.h" /> <ClInclude Include="..\src\kiwano\renderer\FontCollection.h" />
@ -127,6 +128,7 @@
<ClCompile Include="..\src\kiwano\base\Window.cpp" /> <ClCompile Include="..\src\kiwano\base\Window.cpp" />
<ClCompile Include="..\src\kiwano\platform\Application.cpp" /> <ClCompile Include="..\src\kiwano\platform\Application.cpp" />
<ClCompile Include="..\src\kiwano\platform\modules.cpp" /> <ClCompile Include="..\src\kiwano\platform\modules.cpp" />
<ClCompile Include="..\src\kiwano\renderer\Brush.cpp" />
<ClCompile Include="..\src\kiwano\renderer\Color.cpp" /> <ClCompile Include="..\src\kiwano\renderer\Color.cpp" />
<ClCompile Include="..\src\kiwano\renderer\Font.cpp" /> <ClCompile Include="..\src\kiwano\renderer\Font.cpp" />
<ClCompile Include="..\src\kiwano\renderer\FontCollection.cpp" /> <ClCompile Include="..\src\kiwano\renderer\FontCollection.cpp" />

View File

@ -306,6 +306,9 @@
<ClInclude Include="..\src\kiwano\renderer\StrokeStyle.h"> <ClInclude Include="..\src\kiwano\renderer\StrokeStyle.h">
<Filter>renderer</Filter> <Filter>renderer</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\src\kiwano\renderer\Brush.h">
<Filter>renderer</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\src\kiwano\ui\Button.cpp"> <ClCompile Include="..\src\kiwano\ui\Button.cpp">
@ -482,5 +485,8 @@
<ClCompile Include="..\src\kiwano\renderer\TextureCache.cpp"> <ClCompile Include="..\src\kiwano\renderer\TextureCache.cpp">
<Filter>renderer</Filter> <Filter>renderer</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\src\kiwano\renderer\Brush.cpp">
<Filter>renderer</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -131,8 +131,12 @@ namespace kiwano
Rect bounds = GetBounds(); Rect bounds = GetBounds();
rt->SetTransform(transform_matrix_); 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()) for (auto child = children_.first_item(); child; child = child->next_item())

View File

@ -149,10 +149,10 @@ namespace kiwano
void Canvas::DrawLine(Point const& begin, Point const& end) void Canvas::DrawLine(Point const& begin, Point const& end)
{ {
rt_.SetDefaultBrushColor(stroke_color_);
rt_.DrawLine( rt_.DrawLine(
begin, begin,
end, end,
stroke_color_,
stroke_width_, stroke_width_,
stroke_style_ stroke_style_
); );
@ -161,10 +161,10 @@ namespace kiwano
void Canvas::DrawCircle(Point const& center, Float32 radius) void Canvas::DrawCircle(Point const& center, Float32 radius)
{ {
rt_.SetDefaultBrushColor(stroke_color_);
rt_.DrawEllipse( rt_.DrawEllipse(
center, center,
Vec2(radius, radius), Vec2(radius, radius),
stroke_color_,
stroke_width_, stroke_width_,
stroke_style_ stroke_style_
); );
@ -173,10 +173,10 @@ namespace kiwano
void Canvas::DrawEllipse(Point const& center, Vec2 const& radius) void Canvas::DrawEllipse(Point const& center, Vec2 const& radius)
{ {
rt_.SetDefaultBrushColor(stroke_color_);
rt_.DrawEllipse( rt_.DrawEllipse(
center, center,
radius, radius,
stroke_color_,
stroke_width_, stroke_width_,
stroke_style_ stroke_style_
); );
@ -185,9 +185,9 @@ namespace kiwano
void Canvas::DrawRect(Rect const& rect) void Canvas::DrawRect(Rect const& rect)
{ {
rt_.SetDefaultBrushColor(stroke_color_);
rt_.DrawRectangle( rt_.DrawRectangle(
rect, rect,
stroke_color_,
stroke_width_, stroke_width_,
stroke_style_ stroke_style_
); );
@ -196,10 +196,10 @@ namespace kiwano
void Canvas::DrawRoundedRect(Rect const& rect, Vec2 const& radius) void Canvas::DrawRoundedRect(Rect const& rect, Vec2 const& radius)
{ {
rt_.SetDefaultBrushColor(stroke_color_);
rt_.DrawRoundedRectangle( rt_.DrawRoundedRectangle(
rect, rect,
radius, radius,
stroke_color_,
stroke_width_, stroke_width_,
stroke_style_ stroke_style_
); );
@ -208,39 +208,39 @@ namespace kiwano
void Canvas::FillCircle(Point const& center, Float32 radius) void Canvas::FillCircle(Point const& center, Float32 radius)
{ {
rt_.SetDefaultBrushColor(fill_color_);
rt_.FillEllipse( rt_.FillEllipse(
center, center,
Vec2(radius, radius), Vec2(radius, radius)
fill_color_
); );
cache_expired_ = true; cache_expired_ = true;
} }
void Canvas::FillEllipse(Point const& center, Vec2 const& radius) void Canvas::FillEllipse(Point const& center, Vec2 const& radius)
{ {
rt_.SetDefaultBrushColor(fill_color_);
rt_.FillEllipse( rt_.FillEllipse(
center, center,
radius, radius
fill_color_
); );
cache_expired_ = true; cache_expired_ = true;
} }
void Canvas::FillRect(Rect const& rect) void Canvas::FillRect(Rect const& rect)
{ {
rt_.SetDefaultBrushColor(fill_color_);
rt_.FillRectangle( rt_.FillRectangle(
rect, rect
fill_color_
); );
cache_expired_ = true; cache_expired_ = true;
} }
void Canvas::FillRoundedRect(Rect const& rect, Vec2 const& radius) void Canvas::FillRoundedRect(Rect const& rect, Vec2 const& radius)
{ {
rt_.SetDefaultBrushColor(fill_color_);
rt_.FillRoundedRectangle( rt_.FillRoundedRectangle(
rect, rect,
radius, radius
fill_color_
); );
cache_expired_ = true; cache_expired_ = true;
} }
@ -296,9 +296,9 @@ namespace kiwano
void Canvas::StrokePath() void Canvas::StrokePath()
{ {
rt_.SetDefaultBrushColor(stroke_color_);
rt_.DrawGeometry( rt_.DrawGeometry(
geo_sink_.GetGeometry(), geo_sink_.GetGeometry(),
stroke_color_,
stroke_width_, stroke_width_,
stroke_style_ stroke_style_
); );
@ -307,9 +307,9 @@ namespace kiwano
void Canvas::FillPath() void Canvas::FillPath()
{ {
rt_.SetDefaultBrushColor(fill_color_);
rt_.FillGeometry( rt_.FillGeometry(
geo_sink_.GetGeometry(), geo_sink_.GetGeometry()
fill_color_
); );
cache_expired_ = true; cache_expired_ = true;
} }

View File

@ -78,7 +78,8 @@ namespace kiwano
{ {
PrepareRender(rt); 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) void DebugActor::OnUpdate(Duration dt)

View File

@ -83,8 +83,6 @@ namespace kiwano
} }
void Layer::Render(RenderTarget* rt) void Layer::Render(RenderTarget* rt)
{
if (!children_.empty())
{ {
PrepareRender(rt); PrepareRender(rt);
@ -92,7 +90,6 @@ namespace kiwano
Actor::Render(rt); Actor::Render(rt);
rt->PopLayer(); rt->PopLayer();
} }
}
void Layer::HandleMessages(Event const& evt) void Layer::HandleMessages(Event const& evt)
{ {

View File

@ -101,16 +101,16 @@ namespace kiwano
{ {
PrepareRender(rt); PrepareRender(rt);
rt->SetDefaultBrushColor(stroke_color_);
rt->DrawGeometry( rt->DrawGeometry(
geo_, geo_,
stroke_color_,
stroke_width_ * 2, // twice width for widening stroke_width_ * 2, // twice width for widening
stroke_style_ stroke_style_
); );
rt->SetDefaultBrushColor(fill_color_);
rt->FillGeometry( rt->FillGeometry(
geo_, geo_
fill_color_
); );
} }
} }

View File

@ -42,6 +42,7 @@ namespace kiwano
} }
Config::Config(String const& title, UInt32 width, UInt32 height, UInt32 icon) Config::Config(String const& title, UInt32 width, UInt32 height, UInt32 icon)
: debug(false)
{ {
window.title = title; window.title = title;
window.width = width; window.width = width;
@ -50,6 +51,7 @@ namespace kiwano
} }
Config::Config(WindowConfig const& wnd_config, RenderConfig const& render_config) Config::Config(WindowConfig const& wnd_config, RenderConfig const& render_config)
: debug(false)
{ {
window = wnd_config; window = wnd_config;
render = render_config; render = render_config;

View File

@ -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<GradientStop> 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<GradientStop> 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<ID2D1Brush> 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<ID2D1SolidColorBrush*>(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<ID2D1Brush> const& brush)
{
type_ = Type::Unknown;
raw_ = brush;
if (raw_)
{
raw_->SetOpacity(opacity_);
}
}
}

166
src/kiwano/renderer/Brush.h Normal file
View File

@ -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<GradientStop> stops;
GradientExtendMode extend_mode;
LinearGradientStyle(
Point const& begin,
Point const& end,
Vector<GradientStop> const& stops,
GradientExtendMode extend_mode = GradientExtendMode::Clamp
);
};
// 径向渐变样式
struct RadialGradientStyle
{
Point center;
Vec2 offset;
Vec2 radius;
Vector<GradientStop> stops;
GradientExtendMode extend_mode;
RadialGradientStyle(
Point const& center,
Vec2 const& offset,
Vec2 const& radius,
Vector<GradientStop> 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<ID2D1Brush> brush
);
void SetBrush(ComPtr<ID2D1Brush> const& brush);
inline ComPtr<ID2D1Brush> const& GetBrush() const { return raw_; }
protected:
Type type_;
Float32 opacity_;
ComPtr<ID2D1Brush> raw_;
};
}

View File

@ -67,6 +67,11 @@ namespace kiwano
); );
} }
if (SUCCEEDED(hr))
{
current_brush_ = default_brush_;
}
return hr; return hr;
} }
@ -86,8 +91,6 @@ namespace kiwano
void RenderTarget::BeginDraw() void RenderTarget::BeginDraw()
{ {
HRESULT hr = E_FAIL;
if (collecting_status_) if (collecting_status_)
{ {
status_.start = Time::Now(); status_.start = Time::Now();
@ -97,15 +100,12 @@ namespace kiwano
if (render_target_) if (render_target_)
{ {
render_target_->BeginDraw(); render_target_->BeginDraw();
hr = S_OK;
} }
ThrowIfFailed(hr);
} }
void RenderTarget::EndDraw() void RenderTarget::EndDraw()
{ {
ThrowIfFailed(render_target_->EndDraw()); ThrowIfFailed( render_target_->EndDraw() );
if (collecting_status_) if (collecting_status_)
{ {
@ -113,26 +113,19 @@ namespace kiwano
} }
} }
void RenderTarget::DrawGeometry( void RenderTarget::DrawGeometry(Geometry const& geometry, Float32 stroke_width, StrokeStyle stroke) const
Geometry const& geometry,
Color const& stroke_color,
Float32 stroke_width,
StrokeStyle stroke
) const
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
if (!default_brush_ || !render_target_) if (!render_target_ || !current_brush_)
{ {
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
if (SUCCEEDED(hr) && geometry.GetGeometry()) if (SUCCEEDED(hr) && geometry.GetGeometry())
{ {
default_brush_->SetColor(DX::ConvertToColorF(stroke_color));
render_target_->DrawGeometry( render_target_->DrawGeometry(
geometry.GetGeometry().get(), geometry.GetGeometry().get(),
default_brush_.get(), current_brush_.get(),
stroke_width, stroke_width,
GetStrokeStyle(stroke).get() GetStrokeStyle(stroke).get()
); );
@ -143,42 +136,39 @@ namespace kiwano
ThrowIfFailed(hr); ThrowIfFailed(hr);
} }
void RenderTarget::FillGeometry(Geometry const& geometry, Color const& fill_color) const void RenderTarget::FillGeometry(Geometry const& geometry) const
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
if (!default_brush_ || !render_target_) if (!render_target_ || !current_brush_)
{ {
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
if (SUCCEEDED(hr) && geometry.GetGeometry()) if (SUCCEEDED(hr) && geometry.GetGeometry())
{ {
default_brush_->SetColor(DX::ConvertToColorF(fill_color));
render_target_->FillGeometry( render_target_->FillGeometry(
geometry.GetGeometry().get(), geometry.GetGeometry().get(),
default_brush_.get() current_brush_.get()
); );
} }
ThrowIfFailed(hr); 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; HRESULT hr = S_OK;
if (!default_brush_ || !render_target_) if (!render_target_ || !current_brush_)
{ {
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
default_brush_->SetColor(DX::ConvertToColorF(stroke_color));
render_target_->DrawLine( render_target_->DrawLine(
DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point1),
DX::ConvertToPoint2F(point2), DX::ConvertToPoint2F(point2),
default_brush_.get(), current_brush_.get(),
stroke_width, stroke_width,
GetStrokeStyle(stroke).get() GetStrokeStyle(stroke).get()
); );
@ -189,21 +179,20 @@ namespace kiwano
ThrowIfFailed(hr); 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; HRESULT hr = S_OK;
if (!default_brush_ || !render_target_)
if (!render_target_ || !current_brush_)
{ {
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
default_brush_->SetColor(DX::ConvertToColorF(stroke_color));
render_target_->DrawRectangle( render_target_->DrawRectangle(
DX::ConvertToRectF(rect), DX::ConvertToRectF(rect),
default_brush_.get(), current_brush_.get(),
stroke_width, stroke_width,
GetStrokeStyle(stroke).get() GetStrokeStyle(stroke).get()
); );
@ -214,45 +203,42 @@ namespace kiwano
ThrowIfFailed(hr); ThrowIfFailed(hr);
} }
void RenderTarget::FillRectangle(Rect const& rect, Color const& fill_color) const void RenderTarget::FillRectangle(Rect const& rect) const
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
if (!default_brush_ || !render_target_) if (!render_target_ || !current_brush_)
{ {
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
default_brush_->SetColor(DX::ConvertToColorF(fill_color));
render_target_->FillRectangle( render_target_->FillRectangle(
DX::ConvertToRectF(rect), DX::ConvertToRectF(rect),
default_brush_.get() current_brush_.get()
); );
} }
ThrowIfFailed(hr); 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; HRESULT hr = S_OK;
if (!default_brush_ || !render_target_) if (!render_target_ || !current_brush_)
{ {
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
default_brush_->SetColor(DX::ConvertToColorF(stroke_color));
render_target_->DrawRoundedRectangle( render_target_->DrawRoundedRectangle(
D2D1::RoundedRect( D2D1::RoundedRect(
DX::ConvertToRectF(rect), DX::ConvertToRectF(rect),
radius.x, radius.x,
radius.y radius.y
), ),
default_brush_.get(), current_brush_.get(),
stroke_width, stroke_width,
GetStrokeStyle(stroke).get() GetStrokeStyle(stroke).get()
); );
@ -263,49 +249,46 @@ namespace kiwano
ThrowIfFailed(hr); 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; HRESULT hr = S_OK;
if (!default_brush_ || !render_target_) if (!render_target_ || !current_brush_)
{ {
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
default_brush_->SetColor(DX::ConvertToColorF(fill_color));
render_target_->FillRoundedRectangle( render_target_->FillRoundedRectangle(
D2D1::RoundedRect( D2D1::RoundedRect(
DX::ConvertToRectF(rect), DX::ConvertToRectF(rect),
radius.x, radius.x,
radius.y radius.y
), ),
default_brush_.get() current_brush_.get()
); );
} }
ThrowIfFailed(hr); 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; HRESULT hr = S_OK;
if (!default_brush_ || !render_target_) if (!render_target_ || !current_brush_)
{ {
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
default_brush_->SetColor(DX::ConvertToColorF(stroke_color));
render_target_->DrawEllipse( render_target_->DrawEllipse(
D2D1::Ellipse( D2D1::Ellipse(
DX::ConvertToPoint2F(center), DX::ConvertToPoint2F(center),
radius.x, radius.x,
radius.y radius.y
), ),
default_brush_.get(), current_brush_.get(),
stroke_width, stroke_width,
GetStrokeStyle(stroke).get() GetStrokeStyle(stroke).get()
); );
@ -316,24 +299,23 @@ namespace kiwano
ThrowIfFailed(hr); 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; HRESULT hr = S_OK;
if (!default_brush_ || !render_target_) if (!render_target_ || !current_brush_)
{ {
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
default_brush_->SetColor(DX::ConvertToColorF(fill_color));
render_target_->FillEllipse( render_target_->FillEllipse(
D2D1::Ellipse( D2D1::Ellipse(
DX::ConvertToPoint2F(center), DX::ConvertToPoint2F(center),
radius.x, radius.x,
radius.y radius.y
), ),
default_brush_.get() current_brush_.get()
); );
} }
@ -464,7 +446,7 @@ namespace kiwano
void RenderTarget::PushLayer(LayerArea& layer) void RenderTarget::PushLayer(LayerArea& layer)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
if (!render_target_ || !default_brush_) if (!render_target_)
{ {
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
@ -540,6 +522,11 @@ namespace kiwano
return opacity_; return opacity_;
} }
Brush RenderTarget::GetCurrentBrush() const
{
return Brush( current_brush_ );
}
Matrix3x2 RenderTarget::GetGlobalTransform() const Matrix3x2 RenderTarget::GetGlobalTransform() const
{ {
return global_transform_; return global_transform_;
@ -569,7 +556,6 @@ namespace kiwano
if (fast_global_transform_) if (fast_global_transform_)
{ {
render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix)); render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix));
} }
else else
{ {
@ -602,7 +588,7 @@ namespace kiwano
void RenderTarget::SetOpacity(Float32 opacity) void RenderTarget::SetOpacity(Float32 opacity)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
if (!default_brush_) if (!current_brush_)
{ {
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
@ -612,13 +598,24 @@ namespace kiwano
if (opacity_ != opacity) if (opacity_ != opacity)
{ {
opacity_ = opacity; opacity_ = opacity;
default_brush_->SetOpacity(opacity); current_brush_->SetOpacity(opacity);
} }
} }
ThrowIfFailed(hr); 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) void RenderTarget::SetAntialiasMode(bool enabled)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;

View File

@ -20,6 +20,7 @@
#pragma once #pragma once
#include "../base/time.h" #include "../base/time.h"
#include "Brush.h"
#include "Texture.h" #include "Texture.h"
#include "Geometry.h" #include "Geometry.h"
#include "TextLayout.h" #include "TextLayout.h"
@ -55,62 +56,53 @@ namespace kiwano
void DrawGeometry( void DrawGeometry(
Geometry const& geometry, Geometry const& geometry,
Color const& stroke_color,
Float32 stroke_width, Float32 stroke_width,
StrokeStyle stroke = StrokeStyle::Miter StrokeStyle stroke = StrokeStyle::Miter
) const; ) const;
void FillGeometry( void FillGeometry(
Geometry const& geometry, Geometry const& geometry
Color const& fill_color
) const; ) const;
void DrawLine( void DrawLine(
Point const& point1, Point const& point1,
Point const& point2, Point const& point2,
Color const& stroke_color,
Float32 stroke_width, Float32 stroke_width,
StrokeStyle stroke = StrokeStyle::Miter StrokeStyle stroke = StrokeStyle::Miter
) const; ) const;
void DrawRectangle( void DrawRectangle(
Rect const& rect, Rect const& rect,
Color const& stroke_color,
Float32 stroke_width, Float32 stroke_width,
StrokeStyle stroke = StrokeStyle::Miter StrokeStyle stroke = StrokeStyle::Miter
) const; ) const;
void FillRectangle( void FillRectangle(
Rect const& rect, Rect const& rect
Color const& fill_color
) const; ) const;
void DrawRoundedRectangle( void DrawRoundedRectangle(
Rect const& rect, Rect const& rect,
Vec2 const& radius, Vec2 const& radius,
Color const& stroke_color,
Float32 stroke_width, Float32 stroke_width,
StrokeStyle stroke = StrokeStyle::Miter StrokeStyle stroke = StrokeStyle::Miter
) const; ) const;
void FillRoundedRectangle( void FillRoundedRectangle(
Rect const& rect, Rect const& rect,
Vec2 const& radius, Vec2 const& radius
Color const& fill_color
) const; ) const;
void DrawEllipse( void DrawEllipse(
Point const& center, Point const& center,
Vec2 const& radius, Vec2 const& radius,
Color const& stroke_color,
Float32 stroke_width, Float32 stroke_width,
StrokeStyle stroke = StrokeStyle::Miter StrokeStyle stroke = StrokeStyle::Miter
) const; ) const;
void FillEllipse( void FillEllipse(
Point const& center, Point const& center,
Vec2 const& radius, Vec2 const& radius
Color const& fill_color
) const; ) const;
void DrawTexture( void DrawTexture(
@ -150,12 +142,22 @@ namespace kiwano
Float32 GetOpacity() const; Float32 GetOpacity() const;
Brush GetCurrentBrush() const;
Matrix3x2 GetGlobalTransform() const; Matrix3x2 GetGlobalTransform() const;
void SetOpacity( void SetOpacity(
Float32 opacity Float32 opacity
); );
void SetCurrentBrush(
Brush const& brush
);
void SetDefaultBrushColor(
Color const& color
);
void SetTransform( void SetTransform(
const Matrix3x2& matrix const Matrix3x2& matrix
); );

View File

@ -53,6 +53,7 @@ namespace kiwano
KGE_LOG(L"Creating device resources"); KGE_LOG(L"Creating device resources");
hwnd_ = Window::GetInstance()->GetHandle(); hwnd_ = Window::GetInstance()->GetHandle();
output_size_ = Window::GetInstance()->GetSize();
d2d_res_ = nullptr; d2d_res_ = nullptr;
d3d_res_ = nullptr; d3d_res_ = nullptr;
@ -153,13 +154,13 @@ namespace kiwano
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
render_target_->SaveDrawingState(drawing_state_block_.get()); hr = d3d_res_->ClearRenderTarget(clear_color_);
BeginDraw();
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
hr = d3d_res_->ClearRenderTarget(clear_color_); render_target_->SaveDrawingState(drawing_state_block_.get());
BeginDraw();
} }
ThrowIfFailed(hr); ThrowIfFailed(hr);
@ -174,7 +175,6 @@ namespace kiwano
hr = E_UNEXPECTED; hr = E_UNEXPECTED;
} }
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
EndDraw(); EndDraw();
@ -872,6 +872,113 @@ namespace kiwano
ThrowIfFailed(hr); ThrowIfFailed(hr);
} }
void Renderer::CreateSolidBrush(Brush& brush, Color const& color)
{
HRESULT hr = S_OK;
if (!d2d_res_)
{
hr = E_UNEXPECTED;
}
ComPtr<ID2D1SolidColorBrush> 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<GradientStop> 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<const D2D1_GRADIENT_STOP*>(&stops[0]),
stops.size(),
D2D1_GAMMA_2_2,
D2D1_EXTEND_MODE(extend_mode),
&collection
);
if (SUCCEEDED(hr))
{
ComPtr<ID2D1LinearGradientBrush> 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<GradientStop> 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<const D2D1_GRADIENT_STOP*>(&stops[0]),
stops.size(),
D2D1_GAMMA_2_2,
D2D1_EXTEND_MODE(extend_mode),
&collection
);
if (SUCCEEDED(hr))
{
ComPtr<ID2D1RadialGradientBrush> 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) void Renderer::SetVSyncEnabled(bool enabled)
{ {
vsync_ = enabled; vsync_ = enabled;

View File

@ -150,6 +150,28 @@ namespace kiwano
TextureRenderTarget& render_target TextureRenderTarget& render_target
); );
void CreateSolidBrush(
Brush& brush,
Color const& color
);
void CreateLinearGradientBrush(
Brush& brush,
Point const& begin,
Point const& end,
Vector<GradientStop> const& stops,
GradientExtendMode extend_mode
);
void CreateRadialGradientBrush(
Brush& brush,
Point const& center,
Vec2 const& offset,
Vec2 const& radius,
Vector<GradientStop> const& stops,
GradientExtendMode extend_mode
);
public: public:
void Init(RenderConfig const& config); void Init(RenderConfig const& config);