Update TextRenderer & Geometry & GeometrySink
This commit is contained in:
parent
c50755bb4b
commit
4fe6e9cd3f
|
|
@ -61,6 +61,7 @@
|
|||
<ClInclude Include="..\..\src\kiwano\renderer\Color.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\renderer\Font.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\renderer\Geometry.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\renderer\GeometrySink.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\renderer\GifImage.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\renderer\StrokeStyle.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\renderer\TextStyle.hpp" />
|
||||
|
|
@ -127,6 +128,7 @@
|
|||
<ClCompile Include="..\..\src\kiwano\renderer\Color.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\renderer\Font.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\renderer\Geometry.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\renderer\GeometrySink.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\renderer\GifImage.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\renderer\Texture.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\renderer\TextureCache.cpp" />
|
||||
|
|
|
|||
|
|
@ -270,6 +270,9 @@
|
|||
<ClInclude Include="..\..\src\kiwano\renderer\win32\helper.h">
|
||||
<Filter>renderer\win32</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\renderer\GeometrySink.h">
|
||||
<Filter>renderer</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\kiwano\ui\Button.cpp">
|
||||
|
|
@ -452,5 +455,8 @@
|
|||
<ClCompile Include="..\..\src\kiwano\core\RefCounter.cpp">
|
||||
<Filter>core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\renderer\GeometrySink.cpp">
|
||||
<Filter>renderer</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -129,6 +129,7 @@ namespace kiwano
|
|||
void Actor::PrepareToRender(RenderTarget* rt)
|
||||
{
|
||||
rt->SetTransform(transform_matrix_);
|
||||
rt->SetBrushOpacity(GetDisplayedOpacity());
|
||||
}
|
||||
|
||||
void Actor::RenderBorder(RenderTarget* rt)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#pragma once
|
||||
#include <kiwano/2d/Actor.h>
|
||||
#include <kiwano/renderer/RenderTarget.h>
|
||||
|
||||
#include <kiwano/renderer/GeometrySink.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -133,7 +133,7 @@ namespace kiwano
|
|||
/// \~chinese
|
||||
/// @brief 结束路径
|
||||
/// @param closed 路径是否闭合
|
||||
void EndPath(bool closed = true);
|
||||
void EndPath(bool closed = false);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加一条线段
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ namespace kiwano
|
|||
SetResponsible(true);
|
||||
SetCascadeOpacityEnabled(true);
|
||||
|
||||
background_brush_ = new Brush;
|
||||
background_brush_->SetColor(Color(0.0f, 0.0f, 0.0f, 0.7f));
|
||||
|
||||
debug_text_ = new TextActor;
|
||||
|
|
@ -65,6 +66,7 @@ namespace kiwano
|
|||
style.font_weight = FontWeight::Normal;
|
||||
style.line_spacing = 20.f;
|
||||
debug_text_->SetStyle(style);
|
||||
debug_text_->SetFillColor(Color::White);
|
||||
|
||||
AddListener<MouseHoverEvent>([=](Event&) { SetOpacity(0.4f); });
|
||||
AddListener<MouseOutEvent>([=](Event&) { SetOpacity(1.f); });
|
||||
|
|
|
|||
|
|
@ -174,9 +174,9 @@ namespace kiwano
|
|||
loop_count_++;
|
||||
}
|
||||
|
||||
if (frame_.raw)
|
||||
if (frame_.texture)
|
||||
{
|
||||
frame_rt_->DrawTexture(*frame_.raw, nullptr, &frame_.rect);
|
||||
frame_rt_->DrawTexture(*frame_.texture, nullptr, &frame_.rect);
|
||||
}
|
||||
|
||||
frame_rt_->EndDraw();
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ namespace kiwano
|
|||
|
||||
bool ShapeActor::ContainsPoint(const Point& point) const
|
||||
{
|
||||
return geo_.ContainsPoint(point, GetTransformMatrix());
|
||||
return geo_.ContainsPoint(point, &GetTransformMatrix());
|
||||
}
|
||||
|
||||
void ShapeActor::SetStrokeWidth(float width)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <kiwano/2d/Actor.h>
|
||||
#include <kiwano/renderer/Brush.h>
|
||||
#include <kiwano/renderer/Geometry.h>
|
||||
#include <kiwano/renderer/GeometrySink.h>
|
||||
#include <kiwano/renderer/StrokeStyle.h>
|
||||
|
||||
namespace kiwano
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ namespace kiwano
|
|||
|
||||
void Sprite::OnRender(RenderTarget* rt)
|
||||
{
|
||||
rt->DrawTexture(*frame_->GetTexture(), &frame_->GetCropRect(), &GetBounds(), GetDisplayedOpacity());
|
||||
rt->DrawTexture(*frame_->GetTexture(), &frame_->GetCropRect(), &GetBounds());
|
||||
}
|
||||
|
||||
bool Sprite::CheckVisibilty(RenderTarget* rt) const
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ namespace kiwano
|
|||
|
||||
void Stage::RenderBorder(RenderTarget* rt)
|
||||
{
|
||||
rt->SetBrushOpacity(1.0f);
|
||||
|
||||
if (!border_fill_brush_)
|
||||
{
|
||||
border_fill_brush_ = new Brush;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,19 @@ namespace kiwano
|
|||
namespace
|
||||
{
|
||||
TextStyle text_default_style;
|
||||
|
||||
void InitDefaultTextStyle()
|
||||
{
|
||||
static bool inited = false;
|
||||
if (!inited)
|
||||
{
|
||||
inited = true;
|
||||
|
||||
// 默认使用白色画刷填充文字
|
||||
text_default_style.fill_brush = new Brush;
|
||||
text_default_style.fill_brush->SetColor(Color::White);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextActor::SetDefaultStyle(TextStyle const & style)
|
||||
|
|
@ -34,6 +47,11 @@ namespace kiwano
|
|||
text_default_style = style;
|
||||
}
|
||||
|
||||
const TextStyle& TextActor::GetDefaultStyle()
|
||||
{
|
||||
return text_default_style;
|
||||
}
|
||||
|
||||
TextActor::TextActor()
|
||||
: TextActor(String())
|
||||
{
|
||||
|
|
@ -44,8 +62,12 @@ namespace kiwano
|
|||
{
|
||||
}
|
||||
|
||||
TextActor::TextActor(String const& text, const TextStyle & style)
|
||||
TextActor::TextActor(String const& text, const TextStyle& style)
|
||||
: show_underline_(false)
|
||||
, show_strikethrough_(false)
|
||||
{
|
||||
InitDefaultTextStyle();
|
||||
|
||||
SetText(text);
|
||||
SetStyle(style);
|
||||
}
|
||||
|
|
@ -60,10 +82,22 @@ namespace kiwano
|
|||
}
|
||||
|
||||
void TextActor::OnUpdate(Duration dt)
|
||||
{
|
||||
UpdateLayout();
|
||||
}
|
||||
|
||||
void TextActor::UpdateLayout()
|
||||
{
|
||||
if (text_layout_.IsDirty())
|
||||
{
|
||||
text_layout_.Update();
|
||||
|
||||
if (show_underline_)
|
||||
text_layout_.SetUnderline(true, 0, text_layout_.GetText().length());
|
||||
|
||||
if (show_strikethrough_)
|
||||
text_layout_.SetStrikethrough(true, 0, text_layout_.GetText().length());
|
||||
|
||||
SetSize(text_layout_.GetLayoutSize());
|
||||
}
|
||||
}
|
||||
|
|
@ -72,4 +106,24 @@ namespace kiwano
|
|||
{
|
||||
return text_layout_.IsValid() && Actor::CheckVisibilty(rt);
|
||||
}
|
||||
|
||||
void TextActor::SetFillColor(Color const& color)
|
||||
{
|
||||
if (!text_layout_.GetFillBrush())
|
||||
{
|
||||
BrushPtr brush = new Brush;
|
||||
text_layout_.SetFillBrush(brush);
|
||||
}
|
||||
text_layout_.GetFillBrush()->SetColor(color);
|
||||
}
|
||||
|
||||
void TextActor::SetOutlineColor(Color const& outline_color)
|
||||
{
|
||||
if (!text_layout_.GetOutlineBrush())
|
||||
{
|
||||
BrushPtr brush = new Brush;
|
||||
text_layout_.SetOutlineBrush(brush);
|
||||
}
|
||||
text_layout_.GetOutlineBrush()->SetColor(outline_color);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,6 +69,14 @@ namespace kiwano
|
|||
/// @brief 获取文本布局
|
||||
const TextLayout& GetLayout() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取填充画刷
|
||||
BrushPtr GetFillBrush() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取描边画刷
|
||||
BrushPtr GetOutlineBrush() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取字体
|
||||
FontPtr GetFont() const;
|
||||
|
|
@ -145,10 +153,19 @@ namespace kiwano
|
|||
/// @brief 设置是否显示删除线(默认值为 false)
|
||||
void SetStrikethrough(bool enable);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 更新文字布局
|
||||
/// @details 文字布局是懒更新的,手动更新文字布局以更新节点状态
|
||||
void UpdateLayout();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置默认文字样式
|
||||
static void SetDefaultStyle(TextStyle const& style);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取默认文字样式
|
||||
static const TextStyle& GetDefaultStyle();
|
||||
|
||||
void OnRender(RenderTarget* rt) override;
|
||||
|
||||
void OnUpdate(Duration dt) override;
|
||||
|
|
@ -157,6 +174,8 @@ namespace kiwano
|
|||
bool CheckVisibilty(RenderTarget* rt) const override;
|
||||
|
||||
private:
|
||||
bool show_underline_;
|
||||
bool show_strikethrough_;
|
||||
TextLayout text_layout_;
|
||||
};
|
||||
|
||||
|
|
@ -182,6 +201,16 @@ namespace kiwano
|
|||
return text_layout_;
|
||||
}
|
||||
|
||||
inline BrushPtr TextActor::GetFillBrush() const
|
||||
{
|
||||
return text_layout_.GetFillBrush();
|
||||
}
|
||||
|
||||
inline BrushPtr TextActor::GetOutlineBrush() const
|
||||
{
|
||||
return text_layout_.GetOutlineBrush();
|
||||
}
|
||||
|
||||
inline void TextActor::SetText(String const& text)
|
||||
{
|
||||
text_layout_.SetText(text);
|
||||
|
|
@ -234,12 +263,12 @@ namespace kiwano
|
|||
|
||||
inline void TextActor::SetUnderline(bool enable)
|
||||
{
|
||||
text_layout_.SetUnderline(enable, 0, text_layout_.GetText().length());
|
||||
show_underline_ = enable;
|
||||
}
|
||||
|
||||
inline void TextActor::SetStrikethrough(bool enable)
|
||||
{
|
||||
text_layout_.SetStrikethrough(enable, 0, text_layout_.GetText().length());
|
||||
show_strikethrough_ = enable;
|
||||
}
|
||||
|
||||
inline void TextActor::SetFillBrush(BrushPtr brush)
|
||||
|
|
@ -247,21 +276,11 @@ namespace kiwano
|
|||
text_layout_.SetFillBrush(brush);
|
||||
}
|
||||
|
||||
inline void TextActor::SetFillColor(Color const& color)
|
||||
{
|
||||
text_layout_.SetFillColor(color);
|
||||
}
|
||||
|
||||
inline void TextActor::SetOutlineBrush(BrushPtr brush)
|
||||
{
|
||||
text_layout_.SetOutlineBrush(brush);
|
||||
}
|
||||
|
||||
inline void TextActor::SetOutlineColor(Color const& outline_color)
|
||||
{
|
||||
text_layout_.SetOutlineColor(outline_color);
|
||||
}
|
||||
|
||||
inline void TextActor::SetOutlineWidth(float outline_width)
|
||||
{
|
||||
text_layout_.SetOutlineWidth(outline_width);
|
||||
|
|
|
|||
|
|
@ -258,19 +258,6 @@ namespace kiwano
|
|||
return TweenHelper(new kiwano::ActionWalk(duration, path, rotating, start, end));
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 构造路径行走动画
|
||||
/// @param duration 持续时长
|
||||
/// @param sink 几何形状生成器
|
||||
/// @param rotating 是否沿路径切线方向旋转
|
||||
/// @param start 路径起点(百分比)
|
||||
/// @param end 路径终点(百分比)
|
||||
static inline TweenHelper
|
||||
Walk(Duration duration, GeometrySink& sink, bool rotating = false, float start = 0.f, float end = 1.f)
|
||||
{
|
||||
return TweenHelper(new kiwano::ActionWalk(duration, sink.GetGeometry(), rotating, start, end));
|
||||
}
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 构建帧动画
|
||||
/// @param duration 动画时长
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@
|
|||
|
||||
#pragma once
|
||||
#include <kiwano/2d/action/ActionTween.h>
|
||||
#include <kiwano/renderer/Geometry.h> // Geometry, GeometrySink
|
||||
#include <kiwano/renderer/Geometry.h>
|
||||
#include <kiwano/renderer/GeometrySink.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
|
|||
|
|
@ -107,14 +107,6 @@ namespace kiwano
|
|||
/// @brief ÉčÖĂžśĎň˝ĽąäŃůĘ˝
|
||||
void SetStyle(RadialGradientStyle const& style);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief »ñȡ͸Ã÷¶È
|
||||
float GetOpacity() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief ÉèÖÃ͸Ã÷¶È
|
||||
void SetOpacity(float opacity);
|
||||
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief ťË˘ŔŕĐÍ
|
||||
|
|
@ -131,6 +123,14 @@ namespace kiwano
|
|||
Type GetType() const;
|
||||
|
||||
private:
|
||||
/// \~chinese
|
||||
/// @brief »ñȡ͸Ã÷¶È
|
||||
float GetOpacity() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief ÉèÖÃ͸Ã÷¶È
|
||||
void SetOpacity(float opacity);
|
||||
|
||||
void SetBrush(ComPtr<ID2D1Brush> brush, Type type);
|
||||
|
||||
ComPtr<ID2D1Brush> GetBrush() const;
|
||||
|
|
|
|||
|
|
@ -28,10 +28,20 @@ namespace kiwano
|
|||
}
|
||||
|
||||
bool Font::Load(String const& font_file)
|
||||
{
|
||||
return Load(Vector<String>{ font_file });
|
||||
}
|
||||
|
||||
bool Font::Load(Resource const& font_resource)
|
||||
{
|
||||
return Load(Vector<Resource>{ font_resource });
|
||||
}
|
||||
|
||||
bool Font::Load(Vector<String> const& font_file)
|
||||
{
|
||||
try
|
||||
{
|
||||
Renderer::instance().CreateFontCollection(*this, { font_file });
|
||||
Renderer::instance().CreateFontCollection(*this, font_file);
|
||||
}
|
||||
catch (std::runtime_error&)
|
||||
{
|
||||
|
|
@ -40,11 +50,11 @@ namespace kiwano
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Font::Load(Resource const& font_resource)
|
||||
bool Font::Load(Vector<Resource> const& font_resource)
|
||||
{
|
||||
try
|
||||
{
|
||||
Renderer::instance().CreateFontCollection(*this, { font_resource });
|
||||
Renderer::instance().CreateFontCollection(*this, font_resource);
|
||||
}
|
||||
catch (std::runtime_error&)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,7 +30,10 @@ namespace kiwano
|
|||
|
||||
class Renderer;
|
||||
|
||||
// ΧΦΜε
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 字体
|
||||
*/
|
||||
class Font
|
||||
: public ObjectBase
|
||||
{
|
||||
|
|
@ -39,10 +42,22 @@ namespace kiwano
|
|||
public:
|
||||
Font();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 加载字体文件
|
||||
bool Load(String const& font_file);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 加载字体资源
|
||||
bool Load(Resource const& font_resource);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 加载多个字体文件
|
||||
bool Load(Vector<String> const& font_file);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 加载多个字体资源
|
||||
bool Load(Vector<Resource> const& font_resource);
|
||||
|
||||
private:
|
||||
ComPtr<IDWriteFontCollection> GetCollection() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,16 +19,13 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano/renderer/Geometry.h>
|
||||
#include <kiwano/renderer/GeometrySink.h>
|
||||
#include <kiwano/renderer/Renderer.h>
|
||||
#include <kiwano/core/win32/helper.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
//
|
||||
// Geometry
|
||||
//
|
||||
|
||||
Geometry::Geometry()
|
||||
{
|
||||
}
|
||||
|
|
@ -92,32 +89,6 @@ namespace kiwano
|
|||
geo_.reset();
|
||||
}
|
||||
|
||||
void Geometry::CombineWith(GeometrySink& sink, Geometry input, CombineMode mode, Matrix3x2 const& input_matrix) const
|
||||
{
|
||||
if (geo_ && input.geo_)
|
||||
{
|
||||
ThrowIfFailed(
|
||||
geo_->CombineWithGeometry(
|
||||
input.geo_.get(),
|
||||
D2D1_COMBINE_MODE(mode),
|
||||
DX::ConvertToMatrix3x2F(input_matrix),
|
||||
sink.GetGeometrySink().get()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Geometry Geometry::CombineWith(Geometry input, CombineMode mode, Matrix3x2 const& input_matrix) const
|
||||
{
|
||||
GeometrySink sink;
|
||||
sink.Open();
|
||||
|
||||
CombineWith(sink, input, mode, input_matrix);
|
||||
|
||||
sink.Close();
|
||||
return sink.GetGeometry();
|
||||
}
|
||||
|
||||
float Geometry::ComputeArea() const
|
||||
{
|
||||
if (!geo_)
|
||||
|
|
@ -129,7 +100,7 @@ namespace kiwano
|
|||
return area;
|
||||
}
|
||||
|
||||
bool Geometry::ContainsPoint(Point const& point, Matrix3x2 const& transform) const
|
||||
bool Geometry::ContainsPoint(Point const& point, const Matrix3x2* transform) const
|
||||
{
|
||||
if (!geo_)
|
||||
return false;
|
||||
|
|
@ -139,6 +110,7 @@ namespace kiwano
|
|||
geo_->FillContainsPoint(
|
||||
DX::ConvertToPoint2F(point),
|
||||
DX::ConvertToMatrix3x2F(transform),
|
||||
D2D1_DEFAULT_FLATTENING_TOLERANCE,
|
||||
&ret
|
||||
);
|
||||
return !!ret;
|
||||
|
|
@ -179,136 +151,4 @@ namespace kiwano
|
|||
return output;
|
||||
}
|
||||
|
||||
//
|
||||
// GeometrySink
|
||||
//
|
||||
|
||||
GeometrySink::GeometrySink()
|
||||
{
|
||||
}
|
||||
|
||||
GeometrySink::~GeometrySink()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
GeometrySink& GeometrySink::BeginPath(Point const& begin_pos)
|
||||
{
|
||||
if (!sink_)
|
||||
{
|
||||
Open();
|
||||
}
|
||||
|
||||
sink_->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
GeometrySink& GeometrySink::EndPath(bool closed)
|
||||
{
|
||||
if (sink_)
|
||||
{
|
||||
sink_->EndFigure(closed ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN);
|
||||
|
||||
Close();
|
||||
}
|
||||
return (*this);
|
||||
}
|
||||
|
||||
GeometrySink& GeometrySink::AddLine(Point const& point)
|
||||
{
|
||||
if (!sink_) BeginPath();
|
||||
|
||||
sink_->AddLine(DX::ConvertToPoint2F(point));
|
||||
return (*this);
|
||||
}
|
||||
|
||||
GeometrySink& GeometrySink::AddLines(Vector<Point> const& points)
|
||||
{
|
||||
if (!sink_) BeginPath();
|
||||
|
||||
sink_->AddLines(
|
||||
reinterpret_cast<const D2D_POINT_2F*>(&points[0]),
|
||||
static_cast<uint32_t>(points.size())
|
||||
);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
GeometrySink& kiwano::GeometrySink::AddLines(const Point* points, size_t count)
|
||||
{
|
||||
if (!sink_) BeginPath();
|
||||
|
||||
sink_->AddLines(reinterpret_cast<const D2D_POINT_2F*>(points), UINT32(count));
|
||||
return (*this);
|
||||
}
|
||||
|
||||
GeometrySink& GeometrySink::AddBezier(Point const& point1, Point const& point2, Point const& point3)
|
||||
{
|
||||
if (!sink_) BeginPath();
|
||||
|
||||
sink_->AddBezier(
|
||||
D2D1::BezierSegment(
|
||||
DX::ConvertToPoint2F(point1),
|
||||
DX::ConvertToPoint2F(point2),
|
||||
DX::ConvertToPoint2F(point3)
|
||||
)
|
||||
);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
GeometrySink& GeometrySink::AddArc(Point const& point, Size const& radius, float rotation, bool clockwise, bool is_small)
|
||||
{
|
||||
if (!sink_) BeginPath();
|
||||
|
||||
sink_->AddArc(
|
||||
D2D1::ArcSegment(
|
||||
DX::ConvertToPoint2F(point),
|
||||
DX::ConvertToSizeF(radius),
|
||||
rotation,
|
||||
clockwise ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,
|
||||
is_small ? D2D1_ARC_SIZE_SMALL : D2D1_ARC_SIZE_LARGE
|
||||
)
|
||||
);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
Geometry GeometrySink::GetGeometry()
|
||||
{
|
||||
if (sink_)
|
||||
{
|
||||
EndPath();
|
||||
}
|
||||
|
||||
Geometry geo;
|
||||
geo.SetGeometry(path_geo_);
|
||||
return geo;
|
||||
}
|
||||
|
||||
void GeometrySink::Init()
|
||||
{
|
||||
if (!path_geo_)
|
||||
{
|
||||
Renderer::instance().CreateGeometrySink(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void GeometrySink::Open()
|
||||
{
|
||||
Init();
|
||||
|
||||
if (!sink_)
|
||||
{
|
||||
ThrowIfFailed(path_geo_->Open(&sink_));
|
||||
}
|
||||
}
|
||||
|
||||
void GeometrySink::Close()
|
||||
{
|
||||
if (sink_)
|
||||
{
|
||||
ThrowIfFailed(sink_->Close());
|
||||
|
||||
sink_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,10 @@ namespace kiwano
|
|||
class Renderer;
|
||||
class GeometrySink;
|
||||
|
||||
// 几何体
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 几何形状
|
||||
*/
|
||||
class KGE_API Geometry
|
||||
{
|
||||
friend class RenderTarget;
|
||||
|
|
@ -37,179 +40,84 @@ namespace kiwano
|
|||
public:
|
||||
Geometry();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
bool IsValid() const;
|
||||
|
||||
// 获取外切包围盒
|
||||
/// \~chinese
|
||||
/// @brief 获取外切包围盒
|
||||
Rect GetBoundingBox() const;
|
||||
|
||||
// 获取外切包围盒
|
||||
Rect GetBoundingBox(
|
||||
Matrix3x2 const& transform
|
||||
) const;
|
||||
/// \~chinese
|
||||
/// @brief 获取外切包围盒
|
||||
/// @param transform 二维变换
|
||||
Rect GetBoundingBox(Matrix3x2 const& transform) const;
|
||||
|
||||
// 判断图形是否包含点
|
||||
bool ContainsPoint(
|
||||
Point const& point,
|
||||
Matrix3x2 const& transform = Matrix3x2()
|
||||
) const;
|
||||
/// \~chinese
|
||||
/// @brief 判断图形是否包含点
|
||||
/// @param point 点
|
||||
/// @param transform 应用到点上的二维变换
|
||||
bool ContainsPoint(Point const& point, const Matrix3x2* transform = nullptr) const;
|
||||
|
||||
// 获取图形展开成一条直线的长度
|
||||
/// \~chinese
|
||||
/// @brief 获取图形展开成一条直线的长度
|
||||
float GetLength() const;
|
||||
|
||||
// 计算面积
|
||||
/// \~chinese
|
||||
/// @brief 计算图形面积
|
||||
float ComputeArea() const;
|
||||
|
||||
// 计算图形路径上点的位置和切线向量
|
||||
bool ComputePointAtLength(
|
||||
float length,
|
||||
Point& point,
|
||||
Vec2& tangent
|
||||
) const;
|
||||
/// \~chinese
|
||||
/// @brief 计算图形上点的位置和切线向量
|
||||
/// @param[in] length 点在图形上的位置,范围 [0.0 - 1.0]
|
||||
/// @param[out] point 点的位置
|
||||
/// @param[out] tangent 点的切线向量
|
||||
bool ComputePointAtLength(float length, Point& point, Vec2& tangent) const;
|
||||
|
||||
// 清除形状
|
||||
/// \~chinese
|
||||
/// @brief 清除形状
|
||||
void Clear();
|
||||
|
||||
public:
|
||||
// 几何体组合模式
|
||||
enum class CombineMode
|
||||
{
|
||||
Union, /* 并集 (A + B) */
|
||||
Intersect, /* 交集 (A + B) */
|
||||
Xor, /* 对称差集 ((A - B) + (B - A)) */
|
||||
Exclude /* 差集 (A - B) */
|
||||
};
|
||||
/// \~chinese
|
||||
/// @brief 创建线段
|
||||
/// @param begin 线段起点
|
||||
/// @param end 线段终点
|
||||
static Geometry CreateLine(Point const& begin, Point const& end);
|
||||
|
||||
// 组合几何体
|
||||
void CombineWith(
|
||||
GeometrySink& sink,
|
||||
Geometry input,
|
||||
CombineMode mode,
|
||||
Matrix3x2 const& input_matrix = Matrix3x2()
|
||||
) const;
|
||||
/// \~chinese
|
||||
/// @brief 创建矩形
|
||||
/// @param rect 矩形
|
||||
static Geometry CreateRect(Rect const& rect);
|
||||
|
||||
// 组合几何体
|
||||
Geometry CombineWith(
|
||||
Geometry input,
|
||||
CombineMode mode,
|
||||
Matrix3x2 const& input_matrix = Matrix3x2()
|
||||
) const;
|
||||
/// \~chinese
|
||||
/// @brief 创建圆角矩形
|
||||
/// @param rect 矩形
|
||||
/// @param radius 矩形圆角半径
|
||||
static Geometry CreateRoundedRect(Rect const& rect, Vec2 const& radius);
|
||||
|
||||
public:
|
||||
// 创建直线
|
||||
static Geometry CreateLine(
|
||||
Point const& begin,
|
||||
Point const& end
|
||||
);
|
||||
/// \~chinese
|
||||
/// @brief 创建圆形
|
||||
/// @param center 圆形原点
|
||||
/// @param radius 圆形半径
|
||||
static Geometry CreateCircle(Point const& center, float radius);
|
||||
|
||||
// 创建矩形
|
||||
static Geometry CreateRect(
|
||||
Rect const& rect
|
||||
);
|
||||
|
||||
// 创建圆角矩形
|
||||
static Geometry CreateRoundedRect(
|
||||
Rect const& rect,
|
||||
Vec2 const& radius
|
||||
);
|
||||
|
||||
// 创建圆形
|
||||
static Geometry CreateCircle(
|
||||
Point const& center,
|
||||
float radius
|
||||
);
|
||||
|
||||
// 创建椭圆形
|
||||
static Geometry CreateEllipse(
|
||||
Point const& center,
|
||||
Vec2 const& radius
|
||||
);
|
||||
/// \~chinese
|
||||
/// @brief 创建椭圆形
|
||||
/// @param center 椭圆原点
|
||||
/// @param radius 椭圆半径
|
||||
static Geometry CreateEllipse(Point const& center, Vec2 const& radius);
|
||||
|
||||
private:
|
||||
inline ComPtr<ID2D1Geometry> GetGeometry() const { return geo_; }
|
||||
ComPtr<ID2D1Geometry> GetGeometry() const;
|
||||
|
||||
inline void SetGeometry(ComPtr<ID2D1Geometry> geometry) { geo_ = geometry; }
|
||||
void SetGeometry(ComPtr<ID2D1Geometry> geometry);
|
||||
|
||||
private:
|
||||
ComPtr<ID2D1Geometry> geo_;
|
||||
};
|
||||
|
||||
inline ComPtr<ID2D1Geometry> Geometry::GetGeometry() const { return geo_; }
|
||||
|
||||
// 几何体生成器
|
||||
class KGE_API GeometrySink
|
||||
: protected Noncopyable
|
||||
{
|
||||
friend class Geometry;
|
||||
friend class Renderer;
|
||||
|
||||
public:
|
||||
GeometrySink();
|
||||
|
||||
~GeometrySink();
|
||||
|
||||
// 开始添加路径
|
||||
GeometrySink& BeginPath(
|
||||
Point const& begin_pos = Point{} /* 起始点 */
|
||||
);
|
||||
|
||||
// 结束路径
|
||||
GeometrySink& EndPath(
|
||||
bool closed = false /* 路径是否闭合 */
|
||||
);
|
||||
|
||||
// 添加一条线段
|
||||
GeometrySink& AddLine(
|
||||
Point const& point /* 端点 */
|
||||
);
|
||||
|
||||
// 添加多条线段
|
||||
GeometrySink& AddLines(
|
||||
Vector<Point> const& points
|
||||
);
|
||||
|
||||
// 添加多条线段
|
||||
GeometrySink& AddLines(
|
||||
const Point* points,
|
||||
size_t count
|
||||
);
|
||||
|
||||
// 添加一条三次方贝塞尔曲线
|
||||
GeometrySink& AddBezier(
|
||||
Point const& point1, /* 贝塞尔曲线的第一个控制点 */
|
||||
Point const& point2, /* 贝塞尔曲线的第二个控制点 */
|
||||
Point const& point3 /* 贝塞尔曲线的终点 */
|
||||
);
|
||||
|
||||
// 添加弧线
|
||||
GeometrySink& AddArc(
|
||||
Point const& point, /* 终点 */
|
||||
Size const& radius, /* 椭圆半径 */
|
||||
float rotation, /* 椭圆旋转角度 */
|
||||
bool clockwise = true, /* 顺时针 or 逆时针 */
|
||||
bool is_small = true /* 是否取小于 180° 的弧 */
|
||||
);
|
||||
|
||||
// 获取生成路径几何体
|
||||
Geometry GetGeometry();
|
||||
|
||||
// 打开流
|
||||
void Open();
|
||||
|
||||
// 关闭流
|
||||
void Close();
|
||||
|
||||
private:
|
||||
inline ComPtr<ID2D1PathGeometry> GetPathGeometry() const { return path_geo_; }
|
||||
|
||||
inline void SetPathGeometry(ComPtr<ID2D1PathGeometry> path) { path_geo_ = path; }
|
||||
|
||||
inline ComPtr<ID2D1GeometrySink> GetGeometrySink() const { return sink_; }
|
||||
|
||||
inline void SetGeometrySink(ComPtr<ID2D1GeometrySink> sink) { sink_ = sink; }
|
||||
|
||||
void Init();
|
||||
|
||||
private:
|
||||
ComPtr<ID2D1PathGeometry> path_geo_;
|
||||
ComPtr<ID2D1GeometrySink> sink_;
|
||||
};
|
||||
inline void Geometry::SetGeometry(ComPtr<ID2D1Geometry> geometry) { geo_ = geometry; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,186 @@
|
|||
// 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 <kiwano/renderer/GeometrySink.h>
|
||||
#include <kiwano/renderer/Renderer.h>
|
||||
#include <kiwano/core/win32/helper.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
GeometrySink::GeometrySink()
|
||||
{
|
||||
}
|
||||
|
||||
GeometrySink::~GeometrySink()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void GeometrySink::Open()
|
||||
{
|
||||
if (!IsOpened())
|
||||
{
|
||||
path_geo_.reset();
|
||||
Renderer::instance().CreateGeometrySink(*this);
|
||||
|
||||
ThrowIfFailed(path_geo_->Open(&sink_));
|
||||
}
|
||||
}
|
||||
|
||||
void GeometrySink::Close()
|
||||
{
|
||||
if (IsOpened())
|
||||
{
|
||||
ThrowIfFailed(sink_->Close());
|
||||
sink_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
bool GeometrySink::IsOpened() const
|
||||
{
|
||||
return sink_ != nullptr;
|
||||
}
|
||||
|
||||
Geometry GeometrySink::GetGeometry()
|
||||
{
|
||||
Close();
|
||||
|
||||
Geometry geo;
|
||||
geo.SetGeometry(path_geo_);
|
||||
return geo;
|
||||
}
|
||||
|
||||
GeometrySink& GeometrySink::AddGeometry(Geometry const& input, const Matrix3x2* input_matrix)
|
||||
{
|
||||
if (!IsOpened())
|
||||
{
|
||||
Open();
|
||||
}
|
||||
|
||||
ComPtr<ID2D1Geometry> geo = input.geo_;
|
||||
ThrowIfFailed(
|
||||
geo->Outline(
|
||||
DX::ConvertToMatrix3x2F(input_matrix),
|
||||
D2D1_DEFAULT_FLATTENING_TOLERANCE,
|
||||
sink_.get()
|
||||
)
|
||||
);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
GeometrySink& GeometrySink::BeginPath(Point const& begin_pos)
|
||||
{
|
||||
if (!IsOpened())
|
||||
{
|
||||
Open();
|
||||
}
|
||||
|
||||
sink_->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
GeometrySink& GeometrySink::EndPath(bool closed)
|
||||
{
|
||||
KGE_ASSERT(sink_);
|
||||
sink_->EndFigure(closed ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
GeometrySink& GeometrySink::AddLine(Point const& point)
|
||||
{
|
||||
KGE_ASSERT(sink_);
|
||||
sink_->AddLine(DX::ConvertToPoint2F(point));
|
||||
return (*this);
|
||||
}
|
||||
|
||||
GeometrySink& GeometrySink::AddLines(Vector<Point> const& points)
|
||||
{
|
||||
KGE_ASSERT(sink_);
|
||||
sink_->AddLines(
|
||||
reinterpret_cast<const D2D_POINT_2F*>(&points[0]),
|
||||
static_cast<uint32_t>(points.size())
|
||||
);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
GeometrySink& kiwano::GeometrySink::AddLines(const Point* points, size_t count)
|
||||
{
|
||||
KGE_ASSERT(sink_);
|
||||
sink_->AddLines(reinterpret_cast<const D2D_POINT_2F*>(points), UINT32(count));
|
||||
return (*this);
|
||||
}
|
||||
|
||||
GeometrySink& GeometrySink::AddBezier(Point const& point1, Point const& point2, Point const& point3)
|
||||
{
|
||||
KGE_ASSERT(sink_);
|
||||
sink_->AddBezier(
|
||||
D2D1::BezierSegment(
|
||||
DX::ConvertToPoint2F(point1),
|
||||
DX::ConvertToPoint2F(point2),
|
||||
DX::ConvertToPoint2F(point3)
|
||||
)
|
||||
);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
GeometrySink& GeometrySink::AddArc(Point const& point, Size const& radius, float rotation, bool clockwise, bool is_small)
|
||||
{
|
||||
KGE_ASSERT(sink_);
|
||||
sink_->AddArc(
|
||||
D2D1::ArcSegment(
|
||||
DX::ConvertToPoint2F(point),
|
||||
DX::ConvertToSizeF(radius),
|
||||
rotation,
|
||||
clockwise ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,
|
||||
is_small ? D2D1_ARC_SIZE_SMALL : D2D1_ARC_SIZE_LARGE
|
||||
)
|
||||
);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
GeometrySink& GeometrySink::Combine(Geometry const& geo_a, Geometry const& geo_b, CombineMode mode, const Matrix3x2* matrix)
|
||||
{
|
||||
if (!IsOpened())
|
||||
{
|
||||
Open();
|
||||
}
|
||||
|
||||
ComPtr<ID2D1Geometry> geo_a_raw = geo_a.geo_;
|
||||
ComPtr<ID2D1Geometry> geo_b_raw = geo_b.geo_;
|
||||
ThrowIfFailed(
|
||||
geo_a_raw->CombineWithGeometry(
|
||||
geo_b_raw.get(),
|
||||
D2D1_COMBINE_MODE(mode),
|
||||
DX::ConvertToMatrix3x2F(matrix),
|
||||
sink_.get()
|
||||
)
|
||||
);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
void GeometrySink::Clear()
|
||||
{
|
||||
Close();
|
||||
|
||||
path_geo_.reset();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
// 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 <kiwano/renderer/Geometry.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
class RenderTarget;
|
||||
class Renderer;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 几何形状组合方式
|
||||
enum class CombineMode
|
||||
{
|
||||
Union, ///< 并集 (A + B)
|
||||
Intersect, ///< 交集 (A + B)
|
||||
Xor, ///< 对称差集 ((A - B) + (B - A))
|
||||
Exclude ///< 差集 (A - B)
|
||||
};
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 几何形状生成器
|
||||
class KGE_API GeometrySink
|
||||
: protected Noncopyable
|
||||
{
|
||||
friend class Renderer;
|
||||
|
||||
public:
|
||||
GeometrySink();
|
||||
|
||||
~GeometrySink();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 打开输入流
|
||||
/// @details 打开流后可以使用
|
||||
void Open();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 关闭输入流
|
||||
void Close();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 输入流是否已经打开
|
||||
bool IsOpened() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取生成的几何形状
|
||||
/// @note 若还未关闭输入流,则自动关闭
|
||||
Geometry GetGeometry();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加几何形状的轮廓
|
||||
/// @param input 输入的形状
|
||||
/// @param input_matrix 应用到输入形状上的二维变换
|
||||
/// @note 若还未打开输入流,则自动打开
|
||||
GeometrySink& AddGeometry(Geometry const& input, const Matrix3x2* input_matrix = nullptr);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 开始添加路径
|
||||
/// @param begin_pos 路径起始点
|
||||
/// @note 若还未打开输入流,则自动打开
|
||||
GeometrySink& BeginPath(Point const& begin_pos = Point());
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 结束路径
|
||||
/// @param closed 路径是否闭合
|
||||
GeometrySink& EndPath(bool closed = false);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加一条线段
|
||||
/// @param point 端点
|
||||
GeometrySink& AddLine(Point const& point);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加多条线段
|
||||
/// @param points 端点集合
|
||||
GeometrySink& AddLines(Vector<Point> const& points);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加多条线段
|
||||
/// @param points 端点数组
|
||||
/// @param count 端点数量
|
||||
GeometrySink& AddLines(const Point* points, size_t count);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加一条三次方贝塞尔曲线
|
||||
/// @param point1 贝塞尔曲线的第一个控制点
|
||||
/// @param point2 贝塞尔曲线的第二个控制点
|
||||
/// @param point3 贝塞尔曲线的终点
|
||||
GeometrySink& AddBezier(Point const& point1, Point const& point2, Point const& point3);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加弧线
|
||||
/// @param point 终点
|
||||
/// @param radius 椭圆半径
|
||||
/// @param rotation 椭圆旋转角度
|
||||
/// @param clockwise 顺时针 or 逆时针
|
||||
/// @param is_small 是否取小于 180° 的弧
|
||||
GeometrySink& AddArc(Point const& point, Size const& radius, float rotation, bool clockwise = true, bool is_small = true);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 组合几何形状,并将结果输出到流中
|
||||
/// @param geo_a 输入的形状A
|
||||
/// @param geo_b 输入的形状B
|
||||
/// @param mode 组合方式
|
||||
/// @param matrix 应用到输入形状B上的二维变换
|
||||
/// @note 若还未打开输入流,则自动打开
|
||||
GeometrySink& Combine(Geometry const& geo_a, Geometry const& geo_b, CombineMode mode, const Matrix3x2* matrix = nullptr);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 清空图形
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
ComPtr<ID2D1PathGeometry> GetPathGeometry() const;
|
||||
|
||||
void SetPathGeometry(ComPtr<ID2D1PathGeometry> path);
|
||||
|
||||
ComPtr<ID2D1GeometrySink> GetGeometrySink() const;
|
||||
|
||||
void SetGeometrySink(ComPtr<ID2D1GeometrySink> sink);
|
||||
|
||||
private:
|
||||
ComPtr<ID2D1PathGeometry> path_geo_;
|
||||
ComPtr<ID2D1GeometrySink> sink_;
|
||||
};
|
||||
|
||||
inline ComPtr<ID2D1PathGeometry> GeometrySink::GetPathGeometry() const { return path_geo_; }
|
||||
|
||||
inline void GeometrySink::SetPathGeometry(ComPtr<ID2D1PathGeometry> path) { path_geo_ = path; }
|
||||
|
||||
inline ComPtr<ID2D1GeometrySink> GeometrySink::GetGeometrySink() const { return sink_; }
|
||||
|
||||
inline void GeometrySink::SetGeometrySink(ComPtr<ID2D1GeometrySink> sink) { sink_ = sink; }
|
||||
}
|
||||
|
|
@ -28,7 +28,10 @@ namespace kiwano
|
|||
|
||||
KGE_DECLARE_SMART_PTR(GifImage);
|
||||
|
||||
// GIF ͼÏñ
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief GIF图像
|
||||
*/
|
||||
class KGE_API GifImage
|
||||
: public ObjectBase
|
||||
{
|
||||
|
|
@ -37,37 +40,56 @@ namespace kiwano
|
|||
public:
|
||||
GifImage();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 加载本地GIF图片
|
||||
bool Load(String const& file_path);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 加载GIF资源
|
||||
bool Load(Resource const& res);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
bool IsValid() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取像素宽度
|
||||
uint32_t GetWidthInPixels() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取像素高度
|
||||
uint32_t GetHeightInPixels() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取帧数量
|
||||
uint32_t GetFramesCount() const;
|
||||
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief GIF帧的处置方式
|
||||
enum class DisposalType
|
||||
{
|
||||
Unknown,
|
||||
None,
|
||||
Background,
|
||||
Previous
|
||||
Unknown, ///< 未知
|
||||
None, ///< 不处理
|
||||
Background, ///< 背景
|
||||
Previous ///< 恢复前一帧
|
||||
};
|
||||
|
||||
/// \~chinese
|
||||
/// @brief GIF帧
|
||||
struct Frame
|
||||
{
|
||||
Duration delay;
|
||||
TexturePtr raw;
|
||||
Rect rect;
|
||||
DisposalType disposal_type;
|
||||
Duration delay; ///< 帧延迟
|
||||
TexturePtr texture; ///< 帧图像
|
||||
Rect rect; ///< 绘制区域
|
||||
DisposalType disposal_type; ///< 处置方式
|
||||
|
||||
Frame();
|
||||
};
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取GIF帧
|
||||
/// @param index 帧下标
|
||||
Frame GetFrame(uint32_t index);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -28,18 +28,4 @@ namespace kiwano
|
|||
{
|
||||
}
|
||||
|
||||
bool LayerArea::IsValid() const
|
||||
{
|
||||
return layer_ != nullptr;
|
||||
}
|
||||
|
||||
Size LayerArea::GetSize() const
|
||||
{
|
||||
if (layer_)
|
||||
{
|
||||
return reinterpret_cast<Size const&>(layer_->GetSize());
|
||||
}
|
||||
return Size();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,10 @@ namespace kiwano
|
|||
{
|
||||
class RenderTarget;
|
||||
|
||||
// 暠꿔
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 图层区域
|
||||
*/
|
||||
class KGE_API LayerArea
|
||||
{
|
||||
friend class RenderTarget;
|
||||
|
|
@ -33,34 +36,46 @@ namespace kiwano
|
|||
public:
|
||||
LayerArea();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
bool IsValid() const;
|
||||
|
||||
Size GetSize() const;
|
||||
/// \~chinese
|
||||
/// @brief 获取图层区域
|
||||
Rect const& GetAreaRect() const;
|
||||
|
||||
inline Rect const& GetAreaRect() const { return area_; }
|
||||
/// \~chinese
|
||||
/// @brief 获取图层透明度
|
||||
float GetOpacity() const;
|
||||
|
||||
inline float GetOpacity() const { return opacity_; }
|
||||
/// \~chinese
|
||||
/// @brief 获取几何蒙层
|
||||
Geometry const& GetMaskGeometry() const;
|
||||
|
||||
inline Geometry const& GetMaskGeometry() const { return mask_; }
|
||||
/// \~chinese
|
||||
/// @brief 获取几何蒙层变换
|
||||
Matrix3x2 const& GetMaskTransform() const;
|
||||
|
||||
inline Matrix3x2 const& GetMaskTransform() const { return mask_transform_; }
|
||||
/// \~chinese
|
||||
/// @brief 设置图层区域
|
||||
void SetAreaRect(Rect const& area);
|
||||
|
||||
// <20>零暠꿔혐堵
|
||||
inline void SetAreaRect(Rect const& area) { area_ = area; }
|
||||
/// \~chinese
|
||||
/// @brief 设置图层透明度
|
||||
void SetOpacity(float opacity);
|
||||
|
||||
// <20>零暠꿔拷츠똑
|
||||
inline void SetOpacity(float opacity) { opacity_ = opacity; }
|
||||
/// \~chinese
|
||||
/// @brief 设置几何蒙层
|
||||
void SetMaskGeometry(Geometry const& mask);
|
||||
|
||||
// <20>零섯부촁꿔
|
||||
inline void SetMaskGeometry(Geometry const& mask) { mask_ = mask; }
|
||||
|
||||
// <20>零섯부촁꿔긴뻣
|
||||
inline void SetMaskTransform(Matrix3x2 const& matrix) { mask_transform_ = matrix; }
|
||||
/// \~chinese
|
||||
/// @brief 设置几何蒙层变换
|
||||
void SetMaskTransform(Matrix3x2 const& matrix);
|
||||
|
||||
private:
|
||||
inline ComPtr<ID2D1Layer> GetLayer() const { return layer_; }
|
||||
ComPtr<ID2D1Layer> GetLayer() const;
|
||||
|
||||
inline void SetLayer(ComPtr<ID2D1Layer> layer) { layer_ = layer; }
|
||||
void SetLayer(ComPtr<ID2D1Layer> layer);
|
||||
|
||||
private:
|
||||
Rect area_;
|
||||
|
|
@ -69,4 +84,26 @@ namespace kiwano
|
|||
Matrix3x2 mask_transform_;
|
||||
ComPtr<ID2D1Layer> layer_;
|
||||
};
|
||||
|
||||
inline bool LayerArea::IsValid() const { return layer_ != nullptr; }
|
||||
|
||||
inline Rect const& LayerArea::GetAreaRect() const { return area_; }
|
||||
|
||||
inline float LayerArea::GetOpacity() const { return opacity_; }
|
||||
|
||||
inline Geometry const& LayerArea::GetMaskGeometry() const { return mask_; }
|
||||
|
||||
inline Matrix3x2 const& LayerArea::GetMaskTransform() const { return mask_transform_; }
|
||||
|
||||
inline void LayerArea::SetAreaRect(Rect const& area) { area_ = area; }
|
||||
|
||||
inline void LayerArea::SetOpacity(float opacity) { opacity_ = opacity; }
|
||||
|
||||
inline void LayerArea::SetMaskGeometry(Geometry const& mask) { mask_ = mask; }
|
||||
|
||||
inline void LayerArea::SetMaskTransform(Matrix3x2 const& matrix) { mask_transform_ = matrix; }
|
||||
|
||||
inline ComPtr<ID2D1Layer> LayerArea::GetLayer() const { return layer_; }
|
||||
|
||||
inline void LayerArea::SetLayer(ComPtr<ID2D1Layer> layer) { layer_ = layer; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ namespace kiwano
|
|||
RenderTarget::RenderTarget()
|
||||
: collecting_status_(false)
|
||||
, fast_global_transform_(true)
|
||||
, brush_opacity_(1.0f)
|
||||
, antialias_(true)
|
||||
, text_antialias_(TextAntialiasMode::GrayScale)
|
||||
{
|
||||
|
|
@ -290,12 +291,12 @@ namespace kiwano
|
|||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderTarget::DrawTexture(Texture const& texture, Rect const& src_rect, Rect const& dest_rect, float opacity)
|
||||
void RenderTarget::DrawTexture(Texture const& texture, Rect const& src_rect, Rect const& dest_rect)
|
||||
{
|
||||
DrawTexture(texture, &src_rect, &dest_rect, opacity);
|
||||
DrawTexture(texture, &src_rect, &dest_rect);
|
||||
}
|
||||
|
||||
void RenderTarget::DrawTexture(Texture const& texture, const Rect* src_rect, const Rect* dest_rect, float opacity)
|
||||
void RenderTarget::DrawTexture(Texture const& texture, const Rect* src_rect, const Rect* dest_rect)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
|
||||
|
|
@ -308,7 +309,7 @@ namespace kiwano
|
|||
render_target_->DrawBitmap(
|
||||
texture.GetBitmap().get(),
|
||||
dest_rect ? &DX::ConvertToRectF(*dest_rect) : nullptr,
|
||||
opacity,
|
||||
brush_opacity_,
|
||||
mode,
|
||||
src_rect ? &DX::ConvertToRectF(*src_rect) : nullptr
|
||||
);
|
||||
|
|
@ -321,23 +322,42 @@ namespace kiwano
|
|||
{
|
||||
KGE_ASSERT(text_renderer_ && "Text renderer has not been initialized!");
|
||||
|
||||
const TextStyle& style = layout.GetStyle();
|
||||
text_renderer_->SetStyle(
|
||||
style.fill_brush ? style.fill_brush->GetBrush().get() : nullptr,
|
||||
style.outline_brush ? style.outline_brush->GetBrush().get() : nullptr,
|
||||
style.outline_width,
|
||||
GetStrokeStyle(style.outline_stroke).get()
|
||||
);
|
||||
|
||||
HRESULT hr = layout.GetTextLayout()->Draw(nullptr, text_renderer_.get(), offset.x, offset.y);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
if (layout.IsValid())
|
||||
{
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
else
|
||||
{
|
||||
KGE_ERROR(L"Failed to draw text layout with HRESULT of %08X", hr);
|
||||
ComPtr<ID2D1Brush> fill_brush;
|
||||
ComPtr<ID2D1Brush> outline_brush;
|
||||
const TextStyle& style = layout.GetStyle();
|
||||
|
||||
if (style.fill_brush)
|
||||
{
|
||||
fill_brush = style.fill_brush->GetBrush();
|
||||
fill_brush->SetOpacity(brush_opacity_);
|
||||
}
|
||||
|
||||
if (style.outline_brush)
|
||||
{
|
||||
outline_brush = style.outline_brush->GetBrush();
|
||||
outline_brush->SetOpacity(brush_opacity_);
|
||||
}
|
||||
|
||||
HRESULT hr = text_renderer_->DrawTextLayout(
|
||||
layout.GetTextLayout().get(),
|
||||
offset.x,
|
||||
offset.y,
|
||||
fill_brush.get(),
|
||||
outline_brush.get(),
|
||||
style.outline_width,
|
||||
GetStrokeStyle(style.outline_stroke).get()
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IncreasePrimitivesCount(text_renderer_->GetLastPrimitivesCount());
|
||||
}
|
||||
else
|
||||
{
|
||||
KGE_ERROR(L"Failed to draw text layout with HRESULT of %08X", hr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -525,11 +545,11 @@ namespace kiwano
|
|||
collecting_status_ = collecting;
|
||||
}
|
||||
|
||||
void RenderTarget::IncreasePrimitivesCount() const
|
||||
void RenderTarget::IncreasePrimitivesCount(uint32_t increase) const
|
||||
{
|
||||
if (collecting_status_)
|
||||
{
|
||||
++status_.primitives;
|
||||
status_.primitives += increase;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,39 +36,54 @@ namespace kiwano
|
|||
KGE_DECLARE_SMART_PTR(RenderTarget);
|
||||
KGE_DECLARE_SMART_PTR(TextureRenderTarget);
|
||||
|
||||
// 文字抗锯齿模式
|
||||
/// \~chinese
|
||||
/// @brief 文字抗锯齿模式
|
||||
enum class TextAntialiasMode
|
||||
{
|
||||
Default, // 系统默认
|
||||
ClearType, // ClearType 抗锯齿
|
||||
GrayScale, // 灰度抗锯齿
|
||||
None // 不启用抗锯齿
|
||||
Default, ///< 系统默认
|
||||
ClearType, ///< ClearType 抗锯齿
|
||||
GrayScale, ///< 灰度抗锯齿
|
||||
None ///< 不启用抗锯齿
|
||||
};
|
||||
|
||||
|
||||
// 渲染目标
|
||||
/// \~chinese
|
||||
/// @brief 渲染目标
|
||||
/// @details 渲染目标将完成基础图元的绘制,并将绘制结果输出到特定的目标中(如窗口或纹理)
|
||||
class KGE_API RenderTarget
|
||||
: public ObjectBase
|
||||
{
|
||||
friend class Renderer;
|
||||
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
bool IsValid() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void BeginDraw();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void EndDraw();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void DrawGeometry(
|
||||
Geometry const& geometry,
|
||||
float stroke_width,
|
||||
StrokeStyle stroke = StrokeStyle::Miter
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void FillGeometry(
|
||||
Geometry const& geometry
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void DrawLine(
|
||||
Point const& point1,
|
||||
Point const& point2,
|
||||
|
|
@ -76,16 +91,22 @@ namespace kiwano
|
|||
StrokeStyle stroke = StrokeStyle::Miter
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void DrawRectangle(
|
||||
Rect const& rect,
|
||||
float stroke_width,
|
||||
StrokeStyle stroke = StrokeStyle::Miter
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void FillRectangle(
|
||||
Rect const& rect
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void DrawRoundedRectangle(
|
||||
Rect const& rect,
|
||||
Vec2 const& radius,
|
||||
|
|
@ -93,11 +114,15 @@ namespace kiwano
|
|||
StrokeStyle stroke = StrokeStyle::Miter
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void FillRoundedRectangle(
|
||||
Rect const& rect,
|
||||
Vec2 const& radius
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void DrawEllipse(
|
||||
Point const& center,
|
||||
Vec2 const& radius,
|
||||
|
|
@ -105,121 +130,179 @@ namespace kiwano
|
|||
StrokeStyle stroke = StrokeStyle::Miter
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void FillEllipse(
|
||||
Point const& center,
|
||||
Vec2 const& radius
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void DrawTexture(
|
||||
Texture const& texture,
|
||||
Rect const& src_rect,
|
||||
Rect const& dest_rect,
|
||||
float opacity = 1.0f
|
||||
Rect const& dest_rect
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void DrawTexture(
|
||||
Texture const& texture,
|
||||
const Rect* src_rect = nullptr,
|
||||
const Rect* dest_rect = nullptr,
|
||||
float opacity = 1.0f
|
||||
const Rect* dest_rect = nullptr
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void DrawTextLayout(
|
||||
TextLayout const& layout,
|
||||
Point const& offset = Point{}
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void CreateTexture(
|
||||
Texture& texture,
|
||||
math::Vec2T<uint32_t> size,
|
||||
D2D1_PIXEL_FORMAT format
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void PushClipRect(Rect const& clip_rect);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void PopClipRect();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void PushLayer(LayerArea& layer);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void PopLayer();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void Clear();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void Clear(Color const& clear_color);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
float GetBrushOpacity() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
BrushPtr GetCurrentBrush() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
Matrix3x2 GetGlobalTransform() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void SetBrushOpacity(
|
||||
float opacity
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void SetCurrentBrush(
|
||||
BrushPtr brush
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void SetTransform(
|
||||
const Matrix3x2& matrix
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void SetGlobalTransform(
|
||||
const Matrix3x2& matrix
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
void SetGlobalTransform(
|
||||
const Matrix3x2* matrix
|
||||
);
|
||||
|
||||
// 设置抗锯齿模式
|
||||
/// \~chinese
|
||||
/// @brief 设置抗锯齿模式
|
||||
void SetAntialiasMode(
|
||||
bool enabled
|
||||
);
|
||||
|
||||
// 设置文字抗锯齿模式
|
||||
/// \~chinese
|
||||
/// @brief 设置文字抗锯齿模式
|
||||
void SetTextAntialiasMode(
|
||||
TextAntialiasMode mode
|
||||
);
|
||||
|
||||
// 检查边界是否在视区内
|
||||
/// \~chinese
|
||||
/// @brief 检查边界是否在视区内
|
||||
bool CheckVisibility(
|
||||
Rect const& bounds,
|
||||
Matrix3x2 const& transform
|
||||
);
|
||||
|
||||
void Resize(
|
||||
Size const& size
|
||||
);
|
||||
/// \~chinese
|
||||
/// @brief 重设渲染目标大小
|
||||
void Resize(Size const& size);
|
||||
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief 渲染目标状态
|
||||
struct Status
|
||||
{
|
||||
int primitives;
|
||||
Time start;
|
||||
Duration duration;
|
||||
uint32_t primitives; ///< 渲染图元数量
|
||||
Time start; ///< 渲染起始时间
|
||||
Duration duration; ///< 渲染时长
|
||||
|
||||
Status() : primitives(0) {}
|
||||
Status();
|
||||
};
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 启用或禁用状态收集功能
|
||||
void SetCollectingStatus(bool collecting);
|
||||
|
||||
void IncreasePrimitivesCount() const;
|
||||
|
||||
inline Status const& GetStatus() const { return status_; }
|
||||
/// \~chinese
|
||||
/// @brief 获取渲染目标状态
|
||||
Status const& GetStatus() const;
|
||||
|
||||
protected:
|
||||
RenderTarget();
|
||||
|
||||
inline ComPtr<ID2D1RenderTarget> GetRenderTarget() const { KGE_ASSERT(render_target_); return render_target_; }
|
||||
ComPtr<ID2D1RenderTarget> GetRenderTarget() const;
|
||||
|
||||
inline ComPtr<ITextRenderer> GetTextRenderer() const { KGE_ASSERT(text_renderer_); return text_renderer_; }
|
||||
ComPtr<ITextRenderer> GetTextRenderer() const;
|
||||
|
||||
ComPtr<ID2D1StrokeStyle> GetStrokeStyle(StrokeStyle style);
|
||||
ComPtr<ID2D1StrokeStyle> GetStrokeStyle(StrokeStyle style);
|
||||
|
||||
private:
|
||||
/// \~chinese
|
||||
/// @brief 创建设备依赖资源
|
||||
HRESULT CreateDeviceResources(ComPtr<ID2D1Factory> factory, ComPtr<ID2D1RenderTarget> rt);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 销毁设备依赖资源
|
||||
void DiscardDeviceResources();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 增加渲染图元数量
|
||||
void IncreasePrimitivesCount(uint32_t increase = 1) const;
|
||||
|
||||
private:
|
||||
bool antialias_;
|
||||
bool fast_global_transform_;
|
||||
float brush_opacity_;
|
||||
TextAntialiasMode text_antialias_;
|
||||
ComPtr<ITextRenderer> text_renderer_;
|
||||
ComPtr<ID2D1RenderTarget> render_target_;
|
||||
|
|
@ -250,6 +333,8 @@ namespace kiwano
|
|||
|
||||
/// \~chinese
|
||||
/// @brief »ñÈ¡äÖȾÊä³ö
|
||||
/// @param[out] texture 纹理输出
|
||||
/// @return 操作是否成功
|
||||
bool GetOutput(Texture& texture);
|
||||
|
||||
private:
|
||||
|
|
@ -264,6 +349,33 @@ namespace kiwano
|
|||
};
|
||||
|
||||
|
||||
inline RenderTarget::Status::Status()
|
||||
: primitives(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline RenderTarget::Status const& RenderTarget::GetStatus() const
|
||||
{
|
||||
return status_;
|
||||
}
|
||||
|
||||
inline ComPtr<ID2D1RenderTarget> RenderTarget::GetRenderTarget() const
|
||||
{
|
||||
KGE_ASSERT(render_target_);
|
||||
return render_target_;
|
||||
}
|
||||
|
||||
inline ComPtr<ITextRenderer> RenderTarget::GetTextRenderer() const
|
||||
{
|
||||
KGE_ASSERT(text_renderer_);
|
||||
return text_renderer_;
|
||||
}
|
||||
|
||||
inline float RenderTarget::GetBrushOpacity() const
|
||||
{
|
||||
return brush_opacity_;
|
||||
}
|
||||
|
||||
inline BrushPtr RenderTarget::GetCurrentBrush() const
|
||||
{
|
||||
return current_brush_;
|
||||
|
|
@ -274,6 +386,11 @@ namespace kiwano
|
|||
return global_transform_;
|
||||
}
|
||||
|
||||
inline void RenderTarget::SetBrushOpacity(float opacity)
|
||||
{
|
||||
brush_opacity_ = opacity;
|
||||
}
|
||||
|
||||
inline void RenderTarget::SetGlobalTransform(const Matrix3x2& matrix)
|
||||
{
|
||||
SetGlobalTransform(&matrix);
|
||||
|
|
@ -282,6 +399,10 @@ namespace kiwano
|
|||
inline void RenderTarget::SetCurrentBrush(BrushPtr brush)
|
||||
{
|
||||
current_brush_ = brush;
|
||||
if (current_brush_)
|
||||
{
|
||||
current_brush_->SetOpacity(brush_opacity_);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool TextureRenderTarget::IsValid() const
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano/renderer/Renderer.h>
|
||||
#include <kiwano/renderer/GeometrySink.h>
|
||||
#include <kiwano/core/Logger.h>
|
||||
#include <kiwano/core/win32/helper.h>
|
||||
#include <kiwano/platform/Window.h>
|
||||
|
|
@ -66,58 +67,56 @@ namespace kiwano
|
|||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = ID3DDeviceResources::Create(&d3d_res_, hwnd_);
|
||||
}
|
||||
|
||||
// Direct2D device resources
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = ID2DDeviceResources::Create(&d2d_res_, d3d_res_->GetDXGIDevice(), d3d_res_->GetDXGISwapChain());
|
||||
}
|
||||
// Direct2D device resources
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = ID2DDeviceResources::Create(&d2d_res_, d3d_res_->GetDXGIDevice(), d3d_res_->GetDXGISwapChain());
|
||||
|
||||
// DrawingStateBlock
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetFactory()->CreateDrawingStateBlock(
|
||||
&drawing_state_block_
|
||||
);
|
||||
}
|
||||
// DrawingStateBlock
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetFactory()->CreateDrawingStateBlock(&drawing_state_block_);
|
||||
}
|
||||
|
||||
// Other device resources
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext());
|
||||
}
|
||||
// Other device resources
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = CreateDeviceResources(d2d_res_->GetFactory(), d2d_res_->GetDeviceContext());
|
||||
}
|
||||
|
||||
// FontFileLoader and FontCollectionLoader
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IFontCollectionLoader::Create(&font_collection_loader_);
|
||||
}
|
||||
// FontFileLoader and FontCollectionLoader
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IFontCollectionLoader::Create(&font_collection_loader_);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(font_collection_loader_.get());
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(font_collection_loader_.get());
|
||||
}
|
||||
|
||||
// ResourceFontFileLoader and ResourceFontCollectionLoader
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IResourceFontFileLoader::Create(&res_font_file_loader_);
|
||||
}
|
||||
// ResourceFontFileLoader and ResourceFontCollectionLoader
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IResourceFontFileLoader::Create(&res_font_file_loader_);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetDWriteFactory()->RegisterFontFileLoader(res_font_file_loader_.get());
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetDWriteFactory()->RegisterFontFileLoader(res_font_file_loader_.get());
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IResourceFontCollectionLoader::Create(&res_font_collection_loader_, res_font_file_loader_.get());
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IResourceFontCollectionLoader::Create(&res_font_collection_loader_, res_font_file_loader_.get());
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(res_font_collection_loader_.get());
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(res_font_collection_loader_.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ThrowIfFailed(hr);
|
||||
|
|
@ -424,8 +423,8 @@ namespace kiwano
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.raw = new Texture;
|
||||
frame.raw->SetBitmap(raw_bitmap);
|
||||
frame.texture = new Texture;
|
||||
frame.texture->SetBitmap(raw_bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -847,7 +846,7 @@ namespace kiwano
|
|||
if (SUCCEEDED(hr))
|
||||
{
|
||||
output = new TextureRenderTarget;
|
||||
hr = output->CreateDeviceResources(bitmap_rt, d2d_res_);
|
||||
hr = output->CreateDeviceResources(d2d_res_->GetFactory(), bitmap_rt);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
|
|
|
|||
|
|
@ -41,11 +41,14 @@ namespace kiwano
|
|||
typedef ID3D11DeviceResources ID3DDeviceResources;
|
||||
#endif
|
||||
|
||||
// 渲染设置
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 渲染设置
|
||||
*/
|
||||
struct RenderConfig
|
||||
{
|
||||
Color clear_color; // 清屏颜色
|
||||
bool vsync; // 垂直同步
|
||||
Color clear_color; ///< 清屏颜色
|
||||
bool vsync; ///< 垂直同步
|
||||
|
||||
RenderConfig(
|
||||
Color clear_color = Color::Black,
|
||||
|
|
@ -54,7 +57,10 @@ namespace kiwano
|
|||
};
|
||||
|
||||
|
||||
// 渲染器
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 渲染器
|
||||
*/
|
||||
class KGE_API Renderer
|
||||
: public Singleton<Renderer>
|
||||
, public RenderComponent
|
||||
|
|
@ -64,96 +70,173 @@ namespace kiwano
|
|||
friend Singleton<Renderer>;
|
||||
|
||||
public:
|
||||
// 设置清屏颜色
|
||||
void SetClearColor(
|
||||
Color const& clear_color
|
||||
);
|
||||
/// \~chinese
|
||||
/// @brief 获取清屏颜色
|
||||
Color const& GetClearColor() const;
|
||||
|
||||
// 开启或关闭垂直同步
|
||||
void SetVSyncEnabled(
|
||||
bool enabled
|
||||
);
|
||||
/// \~chinese
|
||||
/// @brief 设置清屏颜色
|
||||
void SetClearColor(Color const& clear_color);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 开启或关闭垂直同步
|
||||
void SetVSyncEnabled(bool enabled);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置DPI
|
||||
void SetDpi(float dpi);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建纹理
|
||||
/// @param[out] texture 纹理
|
||||
/// @param[in] file_path 图片路径
|
||||
void CreateTexture(
|
||||
Texture& texture,
|
||||
String const& file_path
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建纹理
|
||||
/// @param[out] texture 纹理
|
||||
/// @param[in] resource 图片资源
|
||||
void CreateTexture(
|
||||
Texture& texture,
|
||||
Resource const& resource
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建GIF图像
|
||||
/// @param[out] gif GIF图像
|
||||
/// @param[in] file_path 图片路径
|
||||
void CreateGifImage(
|
||||
GifImage& gif,
|
||||
String const& file_path
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建GIF图像
|
||||
/// @param[out] gif GIF图像
|
||||
/// @param[in] resource 图片资源
|
||||
void CreateGifImage(
|
||||
GifImage& gif,
|
||||
Resource const& resource
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建GIF图像帧
|
||||
/// @param[out] frame GIF图像帧
|
||||
/// @param[in] gif GIF图像
|
||||
/// @param[in] frame_index 帧下标
|
||||
void CreateGifImageFrame(
|
||||
GifImage::Frame& frame,
|
||||
GifImage const& gif,
|
||||
size_t frame_index
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建字体集
|
||||
/// @param[out] font 字体
|
||||
/// @param[in] file_paths 字体文件路径
|
||||
void CreateFontCollection(
|
||||
Font& font,
|
||||
Vector<String> const& file_paths
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建字体集
|
||||
/// @param[out] font 字体
|
||||
/// @param[in] res_arr 字体资源
|
||||
void CreateFontCollection(
|
||||
Font& font,
|
||||
Vector<Resource> const& res_arr
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建文字格式
|
||||
/// @param[out] layout 字体布局
|
||||
void CreateTextFormat(
|
||||
TextLayout& layout
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建文字布局
|
||||
/// @param[out] layout 字体布局
|
||||
void CreateTextLayout(
|
||||
TextLayout& layout
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建线段形状
|
||||
/// @param[out] geo 形状
|
||||
/// @param[in] begin_pos 线段起点
|
||||
/// @param[in] end_pos 线段终点
|
||||
void CreateLineGeometry(
|
||||
Geometry& geo,
|
||||
Point const& begin_pos,
|
||||
Point const& end_pos
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建矩形形状
|
||||
/// @param[out] geo 形状
|
||||
/// @param[in] rect 矩形大小
|
||||
void CreateRectGeometry(
|
||||
Geometry& geo,
|
||||
Rect const& rect
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建圆角矩形形状
|
||||
/// @param[out] geo 形状
|
||||
/// @param[in] rect 矩形大小
|
||||
/// @param[in] radius 圆角半径
|
||||
void CreateRoundedRectGeometry(
|
||||
Geometry& geo,
|
||||
Rect const& rect,
|
||||
Vec2 const& radius
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建椭圆形状
|
||||
/// @param[out] geo 形状
|
||||
/// @param[in] center 椭圆圆心
|
||||
/// @param[in] radius 椭圆半径
|
||||
void CreateEllipseGeometry(
|
||||
Geometry& geo,
|
||||
Point const& center,
|
||||
Vec2 const& radius
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建几何图形生成器
|
||||
/// @param[out] sink 形状生成器
|
||||
void CreateGeometrySink(
|
||||
GeometrySink& sink
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建纹理渲染目标
|
||||
/// @param[out] render_target 渲染目标
|
||||
void CreateTextureRenderTarget(
|
||||
TextureRenderTargetPtr& render_target
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建纯色画刷
|
||||
/// @param[out] brush 画刷
|
||||
/// @param[in] color 颜色
|
||||
void CreateSolidBrush(
|
||||
Brush& brush,
|
||||
Color const& color
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建线性渐变画刷
|
||||
/// @param[out] brush 画刷
|
||||
/// @param[in] begin 渐变起始点
|
||||
/// @param[in] end 渐变终止点
|
||||
/// @param[in] stops 渐变转换点集合
|
||||
/// @param[in] extend_mode 渐变扩充模式
|
||||
void CreateLinearGradientBrush(
|
||||
Brush& brush,
|
||||
Point const& begin,
|
||||
|
|
@ -162,6 +245,14 @@ namespace kiwano
|
|||
GradientExtendMode extend_mode
|
||||
);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建径向渐变画刷
|
||||
/// @param[out] brush 画刷
|
||||
/// @param[in] center 径向渐变圆心
|
||||
/// @param[in] offset 径向渐变偏移
|
||||
/// @param[in] radius 径向渐变半径
|
||||
/// @param[in] stops 渐变转换点集合
|
||||
/// @param[in] extend_mode 渐变扩充模式
|
||||
void CreateRadialGradientBrush(
|
||||
Brush& brush,
|
||||
Point const& center,
|
||||
|
|
@ -171,9 +262,22 @@ namespace kiwano
|
|||
GradientExtendMode extend_mode
|
||||
);
|
||||
|
||||
void SetDpi(
|
||||
float dpi
|
||||
);
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief 获取目标窗口
|
||||
HWND GetTargetWindow() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取渲染输出大小
|
||||
Size const& GetOutputSize() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取Direct2D设备资源
|
||||
ID2DDeviceResources* GetD2DDeviceResources();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取Direct3D设备资源
|
||||
ID3DDeviceResources* GetD3DDeviceResources();
|
||||
|
||||
public:
|
||||
void Init(RenderConfig const& config);
|
||||
|
|
@ -188,17 +292,6 @@ namespace kiwano
|
|||
|
||||
void HandleMessage(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam) override;
|
||||
|
||||
public:
|
||||
inline HWND GetTargetWindow() const { return hwnd_; }
|
||||
|
||||
inline Size const& GetOutputSize() const { return output_size_; }
|
||||
|
||||
inline Color const& GetClearColor() const { return clear_color_; }
|
||||
|
||||
inline ID2DDeviceResources* GetD2DDeviceResources() { KGE_ASSERT(d2d_res_); return d2d_res_.get(); }
|
||||
|
||||
inline ID3DDeviceResources* GetD3DDeviceResources() { KGE_ASSERT(d3d_res_); return d3d_res_.get(); }
|
||||
|
||||
private:
|
||||
Renderer();
|
||||
|
||||
|
|
@ -221,4 +314,14 @@ namespace kiwano
|
|||
ComPtr<IResourceFontFileLoader> res_font_file_loader_;
|
||||
ComPtr<IResourceFontCollectionLoader> res_font_collection_loader_;
|
||||
};
|
||||
|
||||
inline HWND Renderer::GetTargetWindow() const { return hwnd_; }
|
||||
|
||||
inline Size const& Renderer::GetOutputSize() const { return output_size_; }
|
||||
|
||||
inline Color const& Renderer::GetClearColor() const { return clear_color_; }
|
||||
|
||||
inline ID2DDeviceResources* Renderer::GetD2DDeviceResources() { KGE_ASSERT(d2d_res_); return d2d_res_.get(); }
|
||||
|
||||
inline ID3DDeviceResources* Renderer::GetD3DDeviceResources() { KGE_ASSERT(d3d_res_); return d3d_res_.get(); }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,14 @@ namespace kiwano
|
|||
/// @brief 获取文本布局大小
|
||||
Size GetLayoutSize() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief »ñÈ¡Ìî³ä»Ë¢
|
||||
BrushPtr GetFillBrush() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief »ñÈ¡Ãè±ß»Ë¢
|
||||
BrushPtr GetOutlineBrush() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置文本
|
||||
void SetText(const String& text);
|
||||
|
|
@ -96,10 +104,6 @@ namespace kiwano
|
|||
/// @brief 设置文字填充画刷
|
||||
void SetFillBrush(BrushPtr brush);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置文字填充颜色(默认值为 Color::White)
|
||||
void SetFillColor(Color const& color);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置文字斜体(默认值为 false)
|
||||
void SetItalic(bool italic);
|
||||
|
|
@ -120,10 +124,6 @@ namespace kiwano
|
|||
/// @brief 设置文字描边画刷
|
||||
void SetOutlineBrush(BrushPtr brush);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置文字描边颜色
|
||||
void SetOutlineColor(Color const& outline_color);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置文字描边线宽
|
||||
void SetOutlineWidth(float outline_width);
|
||||
|
|
@ -173,7 +173,7 @@ namespace kiwano
|
|||
|
||||
inline bool TextLayout::IsValid() const
|
||||
{
|
||||
return !!text_layout_;
|
||||
return text_layout_ != nullptr;
|
||||
}
|
||||
|
||||
inline bool TextLayout::IsDirty() const
|
||||
|
|
@ -201,16 +201,21 @@ namespace kiwano
|
|||
return text_layout_;
|
||||
}
|
||||
|
||||
inline BrushPtr TextLayout::GetFillBrush() const
|
||||
{
|
||||
return style_.fill_brush;
|
||||
}
|
||||
|
||||
inline BrushPtr TextLayout::GetOutlineBrush() const
|
||||
{
|
||||
return style_.outline_brush;
|
||||
}
|
||||
|
||||
inline void TextLayout::SetFillBrush(BrushPtr brush)
|
||||
{
|
||||
style_.fill_brush = brush;
|
||||
}
|
||||
|
||||
inline void TextLayout::SetFillColor(Color const& color)
|
||||
{
|
||||
style_.SetFillColor(color);
|
||||
}
|
||||
|
||||
inline void TextLayout::SetTextFormat(ComPtr<IDWriteTextFormat> format)
|
||||
{
|
||||
text_format_ = format;
|
||||
|
|
@ -226,11 +231,6 @@ namespace kiwano
|
|||
style_.outline_brush = brush;
|
||||
}
|
||||
|
||||
inline void TextLayout::SetOutlineColor(Color const& outline_color)
|
||||
{
|
||||
style_.SetOutlineColor(outline_color);
|
||||
}
|
||||
|
||||
inline void TextLayout::SetOutlineWidth(float outline_width)
|
||||
{
|
||||
style_.outline_width = outline_width;
|
||||
|
|
|
|||
|
|
@ -90,30 +90,16 @@ namespace kiwano
|
|||
* @param font_family 字体族
|
||||
* @param font_size 字体大小
|
||||
* @param font_weight 字体粗细
|
||||
* @param color Ìî³äÑÕÉ«
|
||||
*/
|
||||
TextStyle(const String& font_family, float font_size, uint32_t font_weight = FontWeight::Normal, Color color = Color::White);
|
||||
|
||||
void SetFillColor(Color const& color);
|
||||
|
||||
void SetOutlineColor(Color const& color);
|
||||
TextStyle(const String& font_family, float font_size, uint32_t font_weight = FontWeight::Normal);
|
||||
};
|
||||
|
||||
inline TextStyle::TextStyle()
|
||||
: font(nullptr)
|
||||
, font_family()
|
||||
, font_size(18)
|
||||
, font_weight(FontWeight::Normal)
|
||||
, italic(false)
|
||||
, alignment(TextAlign::Left)
|
||||
, wrap_width(0)
|
||||
, line_spacing(0)
|
||||
, outline_width(1.0f)
|
||||
, outline_stroke(StrokeStyle::Round)
|
||||
: TextStyle(String(), 18, FontWeight::Normal)
|
||||
{
|
||||
}
|
||||
|
||||
inline TextStyle::TextStyle(const String& font_family, float font_size, uint32_t font_weight, Color color)
|
||||
inline TextStyle::TextStyle(const String& font_family, float font_size, uint32_t font_weight)
|
||||
: font(nullptr)
|
||||
, font_family(font_family)
|
||||
, font_size(font_size)
|
||||
|
|
@ -127,22 +113,4 @@ namespace kiwano
|
|||
{
|
||||
}
|
||||
|
||||
inline void TextStyle::SetFillColor(Color const& color)
|
||||
{
|
||||
if (!fill_brush)
|
||||
{
|
||||
fill_brush = new Brush;
|
||||
}
|
||||
fill_brush->SetColor(color);
|
||||
}
|
||||
|
||||
inline void TextStyle::SetOutlineColor(Color const& color)
|
||||
{
|
||||
if (!outline_brush)
|
||||
{
|
||||
outline_brush = new Brush;
|
||||
}
|
||||
outline_brush->SetColor(color);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -176,6 +176,12 @@ namespace kiwano
|
|||
|
||||
void Texture::SetDefaultInterpolationMode(InterpolationMode mode)
|
||||
{
|
||||
default_interpolation_mode_ = mode;
|
||||
}
|
||||
|
||||
InterpolationMode Texture::GetDefaultInterpolationMode()
|
||||
{
|
||||
return default_interpolation_mode_;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,19 +28,23 @@ namespace kiwano
|
|||
class TextureRenderTarget;
|
||||
class Renderer;
|
||||
|
||||
// 插值模式
|
||||
// 插值模式指定了位图在缩放和旋转时像素颜色的计算方式
|
||||
// Linear (双线性插值): 对周围四个像素进行两次线性插值计算, 在图像放大时可能会模糊(默认)
|
||||
// Nearest (最邻近插值): 取最邻近的像素点的颜色值
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 插值模式
|
||||
* @details 插值模式指定了位图在缩放和旋转时像素颜色的计算方式
|
||||
*/
|
||||
enum class InterpolationMode
|
||||
{
|
||||
Linear, // 双线性插值
|
||||
Nearest, // 最邻近插值
|
||||
Linear, ///< 双线性插值,对周围四个像素进行两次线性插值计算, 在图像放大时可能会模糊
|
||||
Nearest, ///< 最邻近插值,取最邻近的像素点的颜色值
|
||||
};
|
||||
|
||||
KGE_DECLARE_SMART_PTR(Texture);
|
||||
|
||||
// 纹理
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 纹理
|
||||
*/
|
||||
class KGE_API Texture
|
||||
: public ObjectBase
|
||||
{
|
||||
|
|
@ -53,60 +57,81 @@ namespace kiwano
|
|||
|
||||
virtual ~Texture();
|
||||
|
||||
// 加载本地文件
|
||||
bool Load(
|
||||
String const& file_path
|
||||
);
|
||||
/// \~chinese
|
||||
/// @brief 加载本地文件
|
||||
bool Load(String const& file_path);
|
||||
|
||||
// 加载资源
|
||||
bool Load(
|
||||
Resource const& res
|
||||
);
|
||||
/// \~chinese
|
||||
/// @brief 加载资源
|
||||
bool Load(Resource const& res);
|
||||
|
||||
// 资源是否有效
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
bool IsValid() const;
|
||||
|
||||
// 获取宽度
|
||||
/// \~chinese
|
||||
/// @brief 获取纹理宽度
|
||||
float GetWidth() const;
|
||||
|
||||
// 获取高度
|
||||
/// \~chinese
|
||||
/// @brief 获取纹理高度
|
||||
float GetHeight() const;
|
||||
|
||||
// 获取大小
|
||||
/// \~chinese
|
||||
/// @brief 获取纹理大小
|
||||
Size GetSize() const;
|
||||
|
||||
// 获取像素宽度
|
||||
/// \~chinese
|
||||
/// @brief 获取像素宽度
|
||||
uint32_t GetWidthInPixels() const;
|
||||
|
||||
// 获取像素高度
|
||||
/// \~chinese
|
||||
/// @brief 获取像素高度
|
||||
uint32_t GetHeightInPixels() const;
|
||||
|
||||
// 获取像素大小
|
||||
/// \~chinese
|
||||
/// @brief 获取像素大小
|
||||
math::Vec2T<uint32_t> GetSizeInPixels() const;
|
||||
|
||||
// 获取像素插值方式
|
||||
/// \~chinese
|
||||
/// @brief 获取像素插值方式
|
||||
InterpolationMode GetBitmapInterpolationMode() const;
|
||||
|
||||
// 获取像素格式
|
||||
/// \~chinese
|
||||
/// @brief 获取像素格式
|
||||
D2D1_PIXEL_FORMAT GetPixelFormat() const;
|
||||
|
||||
// 拷贝位图内存
|
||||
/// \~chinese
|
||||
/// @brief 拷贝纹理
|
||||
/// @param copy_from 源纹理
|
||||
void CopyFrom(TexturePtr copy_from);
|
||||
|
||||
// 拷贝位图内存
|
||||
/// \~chinese
|
||||
/// @brief 拷贝纹理
|
||||
/// @param copy_from 源纹理
|
||||
/// @param src_rect 源纹理裁剪矩形
|
||||
/// @param dest_point 拷贝至目标位置
|
||||
void CopyFrom(TexturePtr copy_from, Rect const& src_rect, Point const& dest_point);
|
||||
|
||||
// 设置像素插值方式
|
||||
/// \~chinese
|
||||
/// @brief 设置像素插值方式
|
||||
void SetInterpolationMode(InterpolationMode mode);
|
||||
|
||||
// 设置默认的像素插值方式
|
||||
/// \~chinese
|
||||
/// @brief 设置默认的像素插值方式
|
||||
static void SetDefaultInterpolationMode(InterpolationMode mode);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取默认的像素插值方式
|
||||
static InterpolationMode GetDefaultInterpolationMode();
|
||||
|
||||
private:
|
||||
// 获取源位图
|
||||
/// \~chinese
|
||||
/// @brief 获取源位图
|
||||
ComPtr<ID2D1Bitmap> GetBitmap() const;
|
||||
|
||||
// 设置源位图
|
||||
/// \~chinese
|
||||
/// @brief 设置源位图
|
||||
void SetBitmap(ComPtr<ID2D1Bitmap> bitmap);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -24,22 +24,50 @@
|
|||
|
||||
namespace kiwano
|
||||
{
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 纹理缓存
|
||||
*/
|
||||
class KGE_API TextureCache
|
||||
: public Singleton<TextureCache>
|
||||
{
|
||||
friend Singleton<TextureCache>;
|
||||
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief 添加或获取纹理
|
||||
TexturePtr AddOrGetTexture(String const& file_path);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加或获取纹理
|
||||
TexturePtr AddOrGetTexture(Resource const& res);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加或获取GIF图像
|
||||
GifImagePtr AddOrGetGifImage(String const& file_path);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加或获取GIF图像
|
||||
GifImagePtr AddOrGetGifImage(Resource const& res);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 移除纹理缓存
|
||||
void RemoveTexture(String const& file_path);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 移除纹理缓存
|
||||
void RemoveTexture(Resource const& res);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 移除GIF图像缓存
|
||||
void RemoveGifImage(String const& file_path);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 移除GIF图像缓存
|
||||
void RemoveGifImage(Resource const& res);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 清空缓存
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ namespace kiwano
|
|||
device_context_->SetTarget(target_bitmap_.get());
|
||||
}
|
||||
}
|
||||
return E_NOTIMPL;
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT D2DDeviceResources::SetDpi(float dpi)
|
||||
|
|
|
|||
|
|
@ -35,7 +35,10 @@ namespace kiwano
|
|||
_In_ ID2D1RenderTarget* pRT
|
||||
);
|
||||
|
||||
STDMETHOD_(void, SetStyle)(
|
||||
STDMETHOD(DrawTextLayout)(
|
||||
_In_ IDWriteTextLayout* pTextLayout,
|
||||
float fOriginX,
|
||||
float fOriginY,
|
||||
_In_opt_ ID2D1Brush* pFillBrush,
|
||||
_In_opt_ ID2D1Brush* pOutlineBrush,
|
||||
float fOutlineWidth,
|
||||
|
|
@ -93,6 +96,8 @@ namespace kiwano
|
|||
__out float* pixelsPerDip
|
||||
);
|
||||
|
||||
STDMETHOD_(uint32_t, GetLastPrimitivesCount)();
|
||||
|
||||
public:
|
||||
unsigned long STDMETHODCALLTYPE AddRef();
|
||||
unsigned long STDMETHODCALLTYPE Release();
|
||||
|
|
@ -103,6 +108,7 @@ namespace kiwano
|
|||
|
||||
private:
|
||||
unsigned long cRefCount_;
|
||||
uint32_t cPrimitivesCount_;
|
||||
float fOutlineWidth_;
|
||||
ComPtr<ID2D1Factory> pFactory_;
|
||||
ComPtr<ID2D1RenderTarget> pRT_;
|
||||
|
|
@ -144,6 +150,7 @@ namespace kiwano
|
|||
|
||||
TextRenderer::TextRenderer()
|
||||
: cRefCount_(0)
|
||||
, cPrimitivesCount_(0)
|
||||
, fOutlineWidth_(1)
|
||||
{
|
||||
if (pRT_)
|
||||
|
|
@ -172,16 +179,27 @@ namespace kiwano
|
|||
return hr;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(void) TextRenderer::SetStyle(
|
||||
STDMETHODIMP TextRenderer::DrawTextLayout(
|
||||
_In_ IDWriteTextLayout* pTextLayout,
|
||||
float fOriginX,
|
||||
float fOriginY,
|
||||
_In_opt_ ID2D1Brush* pFillBrush,
|
||||
_In_opt_ ID2D1Brush* pOutlineBrush,
|
||||
float fOutlineWidth,
|
||||
_In_opt_ ID2D1StrokeStyle* pStrokeStyle)
|
||||
{
|
||||
if (!pTextLayout)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
cPrimitivesCount_ = 0;
|
||||
pFillBrush_ = pFillBrush;
|
||||
pOutlineBrush_ = pOutlineBrush;
|
||||
fOutlineWidth_ = fOutlineWidth;
|
||||
pCurrStrokeStyle_ = pStrokeStyle;
|
||||
|
||||
return pTextLayout->Draw(nullptr, this, fOriginX, fOriginY);
|
||||
}
|
||||
|
||||
STDMETHODIMP TextRenderer::DrawGlyphRun(
|
||||
|
|
@ -260,6 +278,8 @@ namespace kiwano
|
|||
fOutlineWidth_ * 2, // twice width for widening
|
||||
pCurrStrokeStyle_.get()
|
||||
);
|
||||
|
||||
++cPrimitivesCount_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -272,6 +292,8 @@ namespace kiwano
|
|||
glyphRun,
|
||||
pFillBrush_.get()
|
||||
);
|
||||
|
||||
++cPrimitivesCount_;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
|
@ -325,16 +347,20 @@ namespace kiwano
|
|||
fOutlineWidth_ * 2,
|
||||
pCurrStrokeStyle_.get()
|
||||
);
|
||||
|
||||
++cPrimitivesCount_;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
if (SUCCEEDED(hr) && pFillBrush_)
|
||||
{
|
||||
pRT_->FillGeometry(
|
||||
pTransformedGeometry.get(),
|
||||
pFillBrush_.get()
|
||||
);
|
||||
|
||||
++cPrimitivesCount_;
|
||||
}
|
||||
return S_OK;
|
||||
return hr;
|
||||
}
|
||||
|
||||
STDMETHODIMP TextRenderer::DrawStrikethrough(
|
||||
|
|
@ -386,16 +412,20 @@ namespace kiwano
|
|||
fOutlineWidth_ * 2,
|
||||
pCurrStrokeStyle_.get()
|
||||
);
|
||||
|
||||
++cPrimitivesCount_;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
if (SUCCEEDED(hr) && pFillBrush_)
|
||||
{
|
||||
pRT_->FillGeometry(
|
||||
pTransformedGeometry.get(),
|
||||
pFillBrush_.get()
|
||||
);
|
||||
|
||||
++cPrimitivesCount_;
|
||||
}
|
||||
return S_OK;
|
||||
return hr;
|
||||
}
|
||||
|
||||
STDMETHODIMP TextRenderer::DrawInlineObject(
|
||||
|
|
@ -451,6 +481,11 @@ namespace kiwano
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(uint32_t) TextRenderer::GetLastPrimitivesCount()
|
||||
{
|
||||
return cPrimitivesCount_;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(unsigned long) TextRenderer::AddRef()
|
||||
{
|
||||
return InterlockedIncrement(&cRefCount_);
|
||||
|
|
|
|||
|
|
@ -32,11 +32,16 @@ namespace kiwano
|
|||
_In_ ID2D1RenderTarget* pRT
|
||||
);
|
||||
|
||||
STDMETHOD_(void, SetStyle)(
|
||||
STDMETHOD(DrawTextLayout)(
|
||||
_In_ IDWriteTextLayout* pTextLayout,
|
||||
float fOriginX,
|
||||
float fOriginY,
|
||||
_In_opt_ ID2D1Brush* pFillBrush,
|
||||
_In_opt_ ID2D1Brush* pOutlineBrush,
|
||||
float fOutlineWidth,
|
||||
_In_opt_ ID2D1StrokeStyle* pStrokeStyle
|
||||
) PURE;
|
||||
|
||||
STDMETHOD_(uint32_t, GetLastPrimitivesCount)() PURE;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue