Add NativeObject & NativePtr
This commit is contained in:
parent
1cb97ba0b2
commit
14df3ae55e
|
|
@ -78,13 +78,15 @@
|
|||
<ClInclude Include="..\..\src\kiwano\render\DirectX\D3DDeviceResourcesBase.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\FontCollectionLoader.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\helper.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\NativePtr.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\RenderContextImpl.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\RendererImpl.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\TextRenderer.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\TextureRenderContextImpl.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\Font.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\NativeObject.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\Shape.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\ShapeSink.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\ShapeMaker.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\GifImage.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\Layer.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\render\RenderContext.h" />
|
||||
|
|
@ -158,7 +160,7 @@
|
|||
<ClCompile Include="..\..\src\kiwano\render\DirectX\TextureRenderContextImpl.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\Font.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\Shape.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\ShapeSink.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\ShapeMaker.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\GifImage.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\Layer.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\render\RenderContext.cpp" />
|
||||
|
|
|
|||
|
|
@ -252,9 +252,6 @@
|
|||
<ClInclude Include="..\..\src\kiwano\render\Shape.h">
|
||||
<Filter>render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\render\ShapeSink.h">
|
||||
<Filter>render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\math\Transform.hpp">
|
||||
<Filter>math</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -318,6 +315,15 @@
|
|||
<ClInclude Include="..\..\src\kiwano\core\IntrusiveList.h">
|
||||
<Filter>core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\render\NativeObject.h">
|
||||
<Filter>render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\render\DirectX\NativePtr.h">
|
||||
<Filter>render\DirectX</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\render\ShapeMaker.h">
|
||||
<Filter>render</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\kiwano\2d\Canvas.cpp">
|
||||
|
|
@ -500,9 +506,6 @@
|
|||
<ClCompile Include="..\..\src\kiwano\render\Shape.cpp">
|
||||
<Filter>render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\render\ShapeSink.cpp">
|
||||
<Filter>render</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\render\TextureRenderContext.cpp">
|
||||
<Filter>render</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -533,5 +536,8 @@
|
|||
<ClCompile Include="..\..\src\kiwano\core\String.cpp">
|
||||
<Filter>core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\render\ShapeMaker.cpp">
|
||||
<Filter>render</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -154,7 +154,7 @@ void Actor::RenderBorder(RenderContext& ctx)
|
|||
ctx.FillRectangle(bounds);
|
||||
|
||||
ctx.SetCurrentBrush(GetStage()->GetBorderStrokeBrush());
|
||||
ctx.DrawRectangle(bounds, nullptr, 2.f);
|
||||
ctx.DrawRectangle(bounds);
|
||||
}
|
||||
|
||||
for (auto& child : children_)
|
||||
|
|
|
|||
|
|
@ -48,8 +48,6 @@ CanvasPtr Canvas::Create(Size const& size)
|
|||
|
||||
Canvas::Canvas()
|
||||
: cache_expired_(false)
|
||||
, stroke_width_(1.0f)
|
||||
, stroke_style_()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -95,10 +93,13 @@ void Canvas::SetBrushTransform(Matrix3x2 const& transform)
|
|||
ctx_->SetTransform(transform);
|
||||
}
|
||||
|
||||
void Canvas::PushLayer(Layer& layer)
|
||||
void Canvas::PushLayer(LayerPtr layer)
|
||||
{
|
||||
KGE_ASSERT(ctx_);
|
||||
ctx_->PushLayer(layer);
|
||||
if (layer)
|
||||
{
|
||||
ctx_->PushLayer(*layer);
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::PopLayer()
|
||||
|
|
@ -125,7 +126,8 @@ void Canvas::DrawShape(ShapePtr shape)
|
|||
if (shape)
|
||||
{
|
||||
ctx_->SetCurrentBrush(stroke_brush_);
|
||||
ctx_->DrawShape(*shape, stroke_style_, stroke_width_);
|
||||
ctx_->SetCurrentStrokeStyle(stroke_style_);
|
||||
ctx_->DrawShape(*shape);
|
||||
cache_expired_ = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -134,7 +136,8 @@ void Canvas::DrawLine(Point const& begin, Point const& end)
|
|||
{
|
||||
KGE_ASSERT(ctx_);
|
||||
ctx_->SetCurrentBrush(stroke_brush_);
|
||||
ctx_->DrawLine(begin, end, stroke_style_, stroke_width_);
|
||||
ctx_->SetCurrentStrokeStyle(stroke_style_);
|
||||
ctx_->DrawLine(begin, end);
|
||||
cache_expired_ = true;
|
||||
}
|
||||
|
||||
|
|
@ -142,7 +145,8 @@ void Canvas::DrawCircle(Point const& center, float radius)
|
|||
{
|
||||
KGE_ASSERT(ctx_);
|
||||
ctx_->SetCurrentBrush(stroke_brush_);
|
||||
ctx_->DrawEllipse(center, Vec2(radius, radius), stroke_style_, stroke_width_);
|
||||
ctx_->SetCurrentStrokeStyle(stroke_style_);
|
||||
ctx_->DrawEllipse(center, Vec2(radius, radius));
|
||||
cache_expired_ = true;
|
||||
}
|
||||
|
||||
|
|
@ -150,7 +154,8 @@ void Canvas::DrawEllipse(Point const& center, Vec2 const& radius)
|
|||
{
|
||||
KGE_ASSERT(ctx_);
|
||||
ctx_->SetCurrentBrush(stroke_brush_);
|
||||
ctx_->DrawEllipse(center, radius, stroke_style_, stroke_width_);
|
||||
ctx_->SetCurrentStrokeStyle(stroke_style_);
|
||||
ctx_->DrawEllipse(center, radius);
|
||||
cache_expired_ = true;
|
||||
}
|
||||
|
||||
|
|
@ -158,7 +163,8 @@ void Canvas::DrawRect(Rect const& rect)
|
|||
{
|
||||
KGE_ASSERT(ctx_);
|
||||
ctx_->SetCurrentBrush(stroke_brush_);
|
||||
ctx_->DrawRectangle(rect, stroke_style_, stroke_width_);
|
||||
ctx_->SetCurrentStrokeStyle(stroke_style_);
|
||||
ctx_->DrawRectangle(rect);
|
||||
cache_expired_ = true;
|
||||
}
|
||||
|
||||
|
|
@ -166,7 +172,8 @@ void Canvas::DrawRoundedRect(Rect const& rect, Vec2 const& radius)
|
|||
{
|
||||
KGE_ASSERT(ctx_);
|
||||
ctx_->SetCurrentBrush(stroke_brush_);
|
||||
ctx_->DrawRoundedRectangle(rect, radius, stroke_style_, stroke_width_);
|
||||
ctx_->SetCurrentStrokeStyle(stroke_style_);
|
||||
ctx_->DrawRoundedRectangle(rect, radius);
|
||||
cache_expired_ = true;
|
||||
}
|
||||
|
||||
|
|
@ -243,39 +250,40 @@ void Canvas::DrawTextLayout(TextLayoutPtr layout, Point const& point)
|
|||
|
||||
void Canvas::BeginPath(Point const& begin_pos)
|
||||
{
|
||||
shape_sink_.BeginPath(begin_pos);
|
||||
shape_maker_.BeginPath(begin_pos);
|
||||
}
|
||||
|
||||
void Canvas::EndPath(bool closed)
|
||||
{
|
||||
shape_sink_.EndPath(closed);
|
||||
shape_maker_.EndPath(closed);
|
||||
}
|
||||
|
||||
void Canvas::AddLine(Point const& point)
|
||||
{
|
||||
shape_sink_.AddLine(point);
|
||||
shape_maker_.AddLine(point);
|
||||
}
|
||||
|
||||
void Canvas::AddLines(Vector<Point> const& points)
|
||||
{
|
||||
shape_sink_.AddLines(points);
|
||||
shape_maker_.AddLines(points);
|
||||
}
|
||||
|
||||
void Canvas::AddBezier(Point const& point1, Point const& point2, Point const& point3)
|
||||
{
|
||||
shape_sink_.AddBezier(point1, point2, point3);
|
||||
shape_maker_.AddBezier(point1, point2, point3);
|
||||
}
|
||||
|
||||
void Canvas::AddArc(Point const& point, Size const& radius, float rotation, bool clockwise, bool is_small)
|
||||
{
|
||||
shape_sink_.AddArc(point, radius, rotation, clockwise, is_small);
|
||||
shape_maker_.AddArc(point, radius, rotation, clockwise, is_small);
|
||||
}
|
||||
|
||||
void Canvas::StrokePath()
|
||||
{
|
||||
KGE_ASSERT(ctx_);
|
||||
ctx_->SetCurrentBrush(stroke_brush_);
|
||||
ctx_->DrawShape(*shape_sink_.GetShape(), stroke_style_, stroke_width_);
|
||||
ctx_->SetCurrentStrokeStyle(stroke_style_);
|
||||
ctx_->DrawShape(*shape_maker_.GetShape());
|
||||
cache_expired_ = true;
|
||||
}
|
||||
|
||||
|
|
@ -283,7 +291,7 @@ void Canvas::FillPath()
|
|||
{
|
||||
KGE_ASSERT(ctx_);
|
||||
ctx_->SetCurrentBrush(fill_brush_);
|
||||
ctx_->FillShape(*shape_sink_.GetShape());
|
||||
ctx_->FillShape(*shape_maker_.GetShape());
|
||||
cache_expired_ = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#pragma once
|
||||
#include <kiwano/2d/Actor.h>
|
||||
#include <kiwano/render/ShapeSink.h>
|
||||
#include <kiwano/render/ShapeMaker.h>
|
||||
#include <kiwano/render/TextureRenderContext.h>
|
||||
|
||||
namespace kiwano
|
||||
|
|
@ -209,11 +209,6 @@ public:
|
|||
/// @param[in] brush 轮廓画刷
|
||||
void SetStrokeBrush(BrushPtr brush);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置轮廓宽度
|
||||
/// @param width 轮廓宽度
|
||||
void SetStrokeWidth(float width);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置轮廓样式
|
||||
/// @param stroke_style 轮廓样式
|
||||
|
|
@ -237,7 +232,7 @@ public:
|
|||
/// \~chinese
|
||||
/// @brief 添加一个图层
|
||||
/// @param layer 图层
|
||||
void PushLayer(Layer& layer);
|
||||
void PushLayer(LayerPtr layer);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 删除最近添加的图层
|
||||
|
|
@ -252,10 +247,6 @@ public:
|
|||
/// @brief 删除最近添加的裁剪区域
|
||||
void PopClipRect();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取轮廓宽度
|
||||
float GetStrokeWidth() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取填充画刷
|
||||
BrushPtr GetFillBrush() const;
|
||||
|
|
@ -280,9 +271,8 @@ private:
|
|||
void UpdateCache() const;
|
||||
|
||||
private:
|
||||
float stroke_width_;
|
||||
StrokeStylePtr stroke_style_;
|
||||
ShapeSink shape_sink_;
|
||||
ShapeMaker shape_maker_;
|
||||
BrushPtr fill_brush_;
|
||||
BrushPtr stroke_brush_;
|
||||
|
||||
|
|
@ -293,16 +283,6 @@ private:
|
|||
|
||||
/** @} */
|
||||
|
||||
inline float Canvas::GetStrokeWidth() const
|
||||
{
|
||||
return stroke_width_;
|
||||
}
|
||||
|
||||
inline void Canvas::SetStrokeWidth(float width)
|
||||
{
|
||||
stroke_width_ = std::max(width, 0.f);
|
||||
}
|
||||
|
||||
inline void Canvas::SetStrokeStyle(StrokeStylePtr stroke_style)
|
||||
{
|
||||
stroke_style_ = stroke_style;
|
||||
|
|
|
|||
|
|
@ -40,8 +40,14 @@ LayerActor::~LayerActor() {}
|
|||
|
||||
void LayerActor::SetOpacity(float opacity)
|
||||
{
|
||||
// Actor::SetOpacity(opacity);
|
||||
layer_.SetOpacity(opacity);
|
||||
if (layer_)
|
||||
{
|
||||
layer_->SetOpacity(opacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
Actor::SetOpacity(opacity);
|
||||
}
|
||||
}
|
||||
|
||||
bool LayerActor::DispatchEvent(Event* evt)
|
||||
|
|
@ -58,11 +64,16 @@ bool LayerActor::DispatchEvent(Event* evt)
|
|||
|
||||
void LayerActor::Render(RenderContext& ctx)
|
||||
{
|
||||
ctx.PushLayer(layer_);
|
||||
|
||||
Actor::Render(ctx);
|
||||
|
||||
ctx.PopLayer();
|
||||
if (layer_)
|
||||
{
|
||||
ctx.PushLayer(*layer_);
|
||||
Actor::Render(ctx);
|
||||
ctx.PopLayer();
|
||||
}
|
||||
else
|
||||
{
|
||||
Actor::Render(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
bool LayerActor::CheckVisibility(RenderContext& ctx) const
|
||||
|
|
|
|||
|
|
@ -52,17 +52,13 @@ public:
|
|||
bool IsSwallowEventsEnabled() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取图层区域
|
||||
Layer const& GetLayer() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取图层区域
|
||||
Layer& GetLayer();
|
||||
/// @brief 获取图层
|
||||
LayerPtr GetLayer() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置图层
|
||||
/// @param layer 图层
|
||||
void SetLayer(Layer const& layer);
|
||||
void SetLayer(LayerPtr layer);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置消息吞没功能
|
||||
|
|
@ -82,8 +78,8 @@ protected:
|
|||
bool CheckVisibility(RenderContext& ctx) const override;
|
||||
|
||||
private:
|
||||
bool swallow_;
|
||||
Layer layer_;
|
||||
bool swallow_;
|
||||
LayerPtr layer_;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
|
@ -98,17 +94,12 @@ inline void LayerActor::SetSwallowEvents(bool enabled)
|
|||
swallow_ = enabled;
|
||||
}
|
||||
|
||||
inline void LayerActor::SetLayer(Layer const& layer)
|
||||
inline void LayerActor::SetLayer(LayerPtr layer)
|
||||
{
|
||||
layer_ = layer;
|
||||
}
|
||||
|
||||
inline Layer const& LayerActor::GetLayer() const
|
||||
{
|
||||
return layer_;
|
||||
}
|
||||
|
||||
inline Layer& LayerActor::GetLayer()
|
||||
inline LayerPtr LayerActor::GetLayer() const
|
||||
{
|
||||
return layer_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,8 +58,6 @@ ShapeActorPtr ShapeActor::Create(ShapePtr shape, BrushPtr fill_brush, BrushPtr s
|
|||
}
|
||||
|
||||
ShapeActor::ShapeActor()
|
||||
: stroke_width_(1.f)
|
||||
, stroke_style_()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -108,7 +106,8 @@ void ShapeActor::OnRender(RenderContext& ctx)
|
|||
if (stroke_brush_)
|
||||
{
|
||||
ctx.SetCurrentBrush(stroke_brush_);
|
||||
ctx.DrawShape(*shape_, stroke_style_, stroke_width_ * 2 /* twice width for widening */);
|
||||
ctx.SetCurrentStrokeStyle(stroke_style_);
|
||||
ctx.DrawShape(*shape_);
|
||||
}
|
||||
|
||||
if (fill_brush_)
|
||||
|
|
@ -296,7 +295,12 @@ void PolygonActor::SetVertices(Vector<Point> const& points)
|
|||
{
|
||||
if (points.size() > 1)
|
||||
{
|
||||
SetShape(ShapeSink().BeginPath(points[0]).AddLines(&points[1], points.size() - 1).EndPath(true).GetShape());
|
||||
ShapeMakerPtr maker = ShapeMaker::Create();
|
||||
maker->BeginPath(points[0]);
|
||||
maker->AddLines(&points[1], points.size() - 1);
|
||||
maker->EndPath(true);
|
||||
|
||||
SetShape(maker->GetShape());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include <kiwano/2d/Actor.h>
|
||||
#include <kiwano/render/Brush.h>
|
||||
#include <kiwano/render/Shape.h>
|
||||
#include <kiwano/render/ShapeSink.h>
|
||||
#include <kiwano/render/ShapeMaker.h>
|
||||
#include <kiwano/render/StrokeStyle.h>
|
||||
|
||||
namespace kiwano
|
||||
|
|
@ -81,10 +81,6 @@ public:
|
|||
/// @brief 获取轮廓画刷
|
||||
BrushPtr GetStrokeBrush() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取线条宽度
|
||||
float GetStrokeWidth() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取线条样式
|
||||
StrokeStylePtr GetStrokeStyle() const;
|
||||
|
|
@ -125,10 +121,6 @@ public:
|
|||
/// @param[in] brush 轮廓画刷
|
||||
void SetStrokeBrush(BrushPtr brush);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置线条宽度,默认为 1.0
|
||||
void SetStrokeWidth(float width);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置线条样式
|
||||
void SetStrokeStyle(StrokeStylePtr stroke_style);
|
||||
|
|
@ -145,7 +137,6 @@ protected:
|
|||
private:
|
||||
BrushPtr fill_brush_;
|
||||
BrushPtr stroke_brush_;
|
||||
float stroke_width_;
|
||||
StrokeStylePtr stroke_style_;
|
||||
Rect bounds_;
|
||||
ShapePtr shape_;
|
||||
|
|
@ -381,11 +372,6 @@ inline BrushPtr ShapeActor::GetStrokeBrush() const
|
|||
return stroke_brush_;
|
||||
}
|
||||
|
||||
inline float ShapeActor::GetStrokeWidth() const
|
||||
{
|
||||
return stroke_width_;
|
||||
}
|
||||
|
||||
inline StrokeStylePtr ShapeActor::GetStrokeStyle() const
|
||||
{
|
||||
return stroke_style_;
|
||||
|
|
@ -396,11 +382,6 @@ inline ShapePtr ShapeActor::GetShape() const
|
|||
return shape_;
|
||||
}
|
||||
|
||||
inline void ShapeActor::SetStrokeWidth(float width)
|
||||
{
|
||||
stroke_width_ = std::max(width, 0.f);
|
||||
}
|
||||
|
||||
inline void ShapeActor::SetStrokeStyle(StrokeStylePtr stroke_style)
|
||||
{
|
||||
stroke_style_ = stroke_style;
|
||||
|
|
|
|||
|
|
@ -285,15 +285,6 @@ void TextActor::SetOutlineBrush(BrushPtr brush)
|
|||
}
|
||||
}
|
||||
|
||||
void TextActor::SetOutlineWidth(float outline_width)
|
||||
{
|
||||
if (style_.outline_width != outline_width)
|
||||
{
|
||||
style_.outline_width = outline_width;
|
||||
layout_->SetDefaultOutlineWidth(outline_width);
|
||||
}
|
||||
}
|
||||
|
||||
void TextActor::SetOutlineStrokeStyle(StrokeStylePtr stroke)
|
||||
{
|
||||
if (style_.outline_stroke != stroke)
|
||||
|
|
|
|||
|
|
@ -146,10 +146,6 @@ public:
|
|||
/// @brief 设置描边线条样式
|
||||
void SetOutlineStrokeStyle(StrokeStylePtr stroke);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置文字描边线宽
|
||||
void SetOutlineWidth(float outline_width);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置是否显示下划线(默认值为 false)
|
||||
void SetUnderline(bool enable);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#pragma once
|
||||
#include <kiwano/2d/action/ActionTween.h>
|
||||
#include <kiwano/render/Shape.h>
|
||||
#include <kiwano/render/ShapeSink.h>
|
||||
#include <kiwano/render/ShapeMaker.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ namespace kiwano
|
|||
*/
|
||||
struct DefaultSmartPtrRefProxy
|
||||
{
|
||||
static inline void AddRef(RefCounter* ptr)
|
||||
static inline void Retain(RefCounter* ptr)
|
||||
{
|
||||
if (ptr)
|
||||
ptr->Retain();
|
||||
|
|
@ -73,13 +73,13 @@ public:
|
|||
SmartPtr(pointer_type p)
|
||||
: ptr_(p)
|
||||
{
|
||||
typename _ProxyTy::AddRef(ptr_);
|
||||
typename _ProxyTy::Retain(ptr_);
|
||||
}
|
||||
|
||||
SmartPtr(const SmartPtr& other)
|
||||
: ptr_(other.ptr_)
|
||||
{
|
||||
typename _ProxyTy::AddRef(ptr_);
|
||||
typename _ProxyTy::Retain(ptr_);
|
||||
}
|
||||
|
||||
SmartPtr(SmartPtr&& other) noexcept
|
||||
|
|
@ -97,7 +97,7 @@ public:
|
|||
SmartPtr(const SmartPtr<_UTy, _ProxyTy>& other)
|
||||
{
|
||||
ptr_ = const_cast<pointer_type>(dynamic_cast<const_pointer_type>(other.Get()));
|
||||
typename _ProxyTy::AddRef(ptr_);
|
||||
typename _ProxyTy::Retain(ptr_);
|
||||
}
|
||||
|
||||
inline pointer_type Get() noexcept
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@
|
|||
#include <kiwano/render/Color.h>
|
||||
#include <kiwano/render/Font.h>
|
||||
#include <kiwano/render/Shape.h>
|
||||
#include <kiwano/render/ShapeSink.h>
|
||||
#include <kiwano/render/ShapeMaker.h>
|
||||
#include <kiwano/render/Texture.h>
|
||||
#include <kiwano/render/GifImage.h>
|
||||
#include <kiwano/render/Layer.h>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace kiwano
|
|||
{
|
||||
struct ComPtrProxy
|
||||
{
|
||||
static inline void AddRef(IUnknown* ptr)
|
||||
static inline void Retain(IUnknown* ptr)
|
||||
{
|
||||
if (ptr)
|
||||
ptr->AddRef();
|
||||
|
|
|
|||
|
|
@ -93,16 +93,19 @@ Brush::Brush()
|
|||
void Brush::SetColor(Color const& color)
|
||||
{
|
||||
Renderer::GetInstance().CreateBrush(*this, color);
|
||||
type_ = Brush::Type::SolidColor;
|
||||
}
|
||||
|
||||
void Brush::SetStyle(LinearGradientStyle const& style)
|
||||
{
|
||||
Renderer::GetInstance().CreateBrush(*this, style);
|
||||
type_ = Brush::Type::LinearGradient;
|
||||
}
|
||||
|
||||
void Brush::SetStyle(RadialGradientStyle const& style)
|
||||
{
|
||||
Renderer::GetInstance().CreateBrush(*this, style);
|
||||
type_ = Brush::Type::RadialGradient;
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -19,8 +19,7 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <kiwano/core/ObjectBase.h>
|
||||
#include <kiwano/render/DirectX/D2DDeviceResources.h>
|
||||
#include <kiwano/render/NativeObject.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -85,7 +84,7 @@ struct RadialGradientStyle
|
|||
* \~chinese
|
||||
* @brief 画刷
|
||||
*/
|
||||
class KGE_API Brush : public virtual ObjectBase
|
||||
class KGE_API Brush : public NativeObject
|
||||
{
|
||||
public:
|
||||
/// \~chinese
|
||||
|
|
@ -105,10 +104,6 @@ public:
|
|||
|
||||
Brush();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
bool IsValid() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置纯色画刷颜色
|
||||
void SetColor(Color const& color);
|
||||
|
|
@ -138,16 +133,6 @@ public:
|
|||
|
||||
private:
|
||||
Type type_;
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
public:
|
||||
void SetBrush(ComPtr<ID2D1Brush> brush, Type type);
|
||||
|
||||
ComPtr<ID2D1Brush> GetBrush() const;
|
||||
|
||||
private:
|
||||
ComPtr<ID2D1Brush> raw_;
|
||||
#endif
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
|
@ -157,26 +142,4 @@ inline Brush::Type Brush::GetType() const
|
|||
return type_;
|
||||
}
|
||||
|
||||
inline bool Brush::IsValid() const
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
return raw_ != nullptr;
|
||||
#else
|
||||
return false; // not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
inline void Brush::SetBrush(ComPtr<ID2D1Brush> brush, Type type)
|
||||
{
|
||||
type_ = type;
|
||||
raw_ = brush;
|
||||
}
|
||||
|
||||
inline ComPtr<ID2D1Brush> Brush::GetBrush() const
|
||||
{
|
||||
return raw_;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
// 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/render/NativeObject.h>
|
||||
#include <kiwano/platform/win32/ComPtr.hpp>
|
||||
#include <unknwn.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
class KGE_API NativePtr
|
||||
{
|
||||
public:
|
||||
template <typename _Ty, typename = typename std::enable_if<std::is_base_of<IUnknown, _Ty>::value, int>::type>
|
||||
static inline ComPtr<_Ty> Get(const NativeObject* object)
|
||||
{
|
||||
if (object)
|
||||
{
|
||||
ComPtr<IUnknown> ptr = object->GetNativePointer<ComPtr<IUnknown>>();
|
||||
if (ptr)
|
||||
{
|
||||
ComPtr<_Ty> native;
|
||||
if (SUCCEEDED(ptr->QueryInterface<_Ty>(&native)))
|
||||
return native;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename _Ty>
|
||||
static inline ComPtr<_Ty> Get(const NativeObject& object)
|
||||
{
|
||||
return NativePtr::Get<_Ty>(&object);
|
||||
}
|
||||
|
||||
template <typename _Ty>
|
||||
static inline ComPtr<_Ty> Get(NativeObjectPtr object)
|
||||
{
|
||||
return NativePtr::Get<_Ty>(object.Get());
|
||||
}
|
||||
|
||||
static inline void Set(NativeObject* object, ComPtr<IUnknown> com_ptr)
|
||||
{
|
||||
if (object)
|
||||
{
|
||||
object->SetNativePointer(com_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void Set(NativeObject& object, ComPtr<IUnknown> com_ptr)
|
||||
{
|
||||
NativePtr::Set(&object, com_ptr);
|
||||
}
|
||||
|
||||
static inline void Set(NativeObjectPtr object, ComPtr<IUnknown> com_ptr)
|
||||
{
|
||||
NativePtr::Set(object.Get(), com_ptr);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
@ -18,14 +18,14 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano/core/Logger.h>
|
||||
#include <kiwano/render/DirectX/RenderContextImpl.h>
|
||||
#include <kiwano/render/DirectX/NativePtr.h>
|
||||
#include <kiwano/core/Logger.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
RenderContextImpl::RenderContextImpl()
|
||||
{}
|
||||
RenderContextImpl::RenderContextImpl() {}
|
||||
|
||||
RenderContextImpl::~RenderContextImpl()
|
||||
{
|
||||
|
|
@ -99,12 +99,19 @@ void RenderContextImpl::DrawTexture(Texture const& texture, const Rect* src_rect
|
|||
|
||||
if (texture.IsValid())
|
||||
{
|
||||
auto mode = (texture.GetBitmapInterpolationMode() == InterpolationMode::Linear)
|
||||
? D2D1_BITMAP_INTERPOLATION_MODE_LINEAR
|
||||
: D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR;
|
||||
D2D1_BITMAP_INTERPOLATION_MODE mode;
|
||||
if (texture.GetBitmapInterpolationMode() == InterpolationMode::Linear)
|
||||
{
|
||||
mode = D2D1_BITMAP_INTERPOLATION_MODE_LINEAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR;
|
||||
}
|
||||
|
||||
render_target_->DrawBitmap(texture.GetBitmap().Get(), dest_rect ? &DX::ConvertToRectF(*dest_rect) : nullptr,
|
||||
brush_opacity_, mode, src_rect ? &DX::ConvertToRectF(*src_rect) : nullptr);
|
||||
auto bitmap = NativePtr::Get<ID2D1Bitmap>(texture);
|
||||
render_target_->DrawBitmap(bitmap.Get(), dest_rect ? &DX::ConvertToRectF(*dest_rect) : nullptr, brush_opacity_,
|
||||
mode, src_rect ? &DX::ConvertToRectF(*src_rect) : nullptr);
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
|
@ -116,30 +123,28 @@ void RenderContextImpl::DrawTextLayout(TextLayout const& layout, Point const& of
|
|||
|
||||
if (layout.IsValid())
|
||||
{
|
||||
ComPtr<ID2D1Brush> fill_brush;
|
||||
ComPtr<ID2D1Brush> outline_brush;
|
||||
ComPtr<ID2D1StrokeStyle> outline_stroke;
|
||||
auto native = NativePtr::Get<IDWriteTextLayout>(layout);
|
||||
auto fill_brush = NativePtr::Get<ID2D1Brush>(layout.GetDefaultFillBrush());
|
||||
auto outline_brush = NativePtr::Get<ID2D1Brush>(layout.GetDefaultOutlineBrush());
|
||||
auto outline_stroke = NativePtr::Get<ID2D1StrokeStyle>(layout.GetDefaultOutlineStrokeStyle());
|
||||
float outline_width = 1.0f;
|
||||
|
||||
if (layout.GetDefaultFillBrush())
|
||||
if (fill_brush)
|
||||
{
|
||||
fill_brush = layout.GetDefaultFillBrush()->GetBrush();
|
||||
fill_brush->SetOpacity(brush_opacity_);
|
||||
}
|
||||
|
||||
if (layout.GetDefaultOutlineBrush())
|
||||
if (outline_brush)
|
||||
{
|
||||
outline_brush = layout.GetDefaultOutlineBrush()->GetBrush();
|
||||
outline_brush->SetOpacity(brush_opacity_);
|
||||
}
|
||||
|
||||
if (layout.GetDefaultOutlineStrokeStyle())
|
||||
{
|
||||
outline_stroke = layout.GetDefaultOutlineStrokeStyle()->GetStrokeStyle();
|
||||
outline_width = layout.GetDefaultOutlineStrokeStyle()->GetStrokeWidth();
|
||||
}
|
||||
|
||||
float outline_width = layout.GetDefaultOutlineWidth();
|
||||
|
||||
HRESULT hr = text_renderer_->DrawTextLayout(layout.GetTextLayout().Get(), offset.x, offset.y, fill_brush.Get(),
|
||||
HRESULT hr = text_renderer_->DrawTextLayout(native.Get(), offset.x, offset.y, fill_brush.Get(),
|
||||
outline_brush.Get(), outline_width, outline_stroke.Get());
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
|
|
@ -153,66 +158,79 @@ void RenderContextImpl::DrawTextLayout(TextLayout const& layout, Point const& of
|
|||
}
|
||||
}
|
||||
|
||||
void RenderContextImpl::DrawShape(Shape const& shape, StrokeStylePtr stroke, float stroke_width)
|
||||
void RenderContextImpl::DrawShape(Shape const& shape)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
if (shape.IsValid())
|
||||
{
|
||||
ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().Get() : nullptr;
|
||||
render_target_->DrawGeometry(shape.GetGeometry().Get(), current_brush_->GetBrush().Get(), stroke_width,
|
||||
stroke_style);
|
||||
auto geometry = NativePtr::Get<ID2D1Geometry>(shape);
|
||||
auto brush = NativePtr::Get<ID2D1Brush>(current_brush_);
|
||||
auto stroke_style = NativePtr::Get<ID2D1StrokeStyle>(current_stroke_);
|
||||
float stroke_width = current_stroke_ ? current_stroke_->GetStrokeWidth() : 1.0f;
|
||||
|
||||
render_target_->DrawGeometry(geometry.Get(), brush.Get(), stroke_width, stroke_style.Get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderContextImpl::DrawLine(Point const& point1, Point const& point2, StrokeStylePtr stroke, float stroke_width)
|
||||
void RenderContextImpl::DrawLine(Point const& point1, Point const& point2)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().Get() : nullptr;
|
||||
render_target_->DrawLine(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2),
|
||||
current_brush_->GetBrush().Get(), stroke_width, stroke_style);
|
||||
auto brush = NativePtr::Get<ID2D1Brush>(current_brush_);
|
||||
auto stroke_style = NativePtr::Get<ID2D1StrokeStyle>(current_stroke_);
|
||||
float stroke_width = current_stroke_ ? current_stroke_->GetStrokeWidth() : 1.0f;
|
||||
|
||||
render_target_->DrawLine(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2), brush.Get(), stroke_width,
|
||||
stroke_style.Get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContextImpl::DrawRectangle(Rect const& rect, StrokeStylePtr stroke, float stroke_width)
|
||||
void RenderContextImpl::DrawRectangle(Rect const& rect)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().Get() : nullptr;
|
||||
render_target_->DrawRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().Get(), stroke_width,
|
||||
stroke_style);
|
||||
auto brush = NativePtr::Get<ID2D1Brush>(current_brush_);
|
||||
auto stroke_style = NativePtr::Get<ID2D1StrokeStyle>(current_stroke_);
|
||||
float stroke_width = current_stroke_ ? current_stroke_->GetStrokeWidth() : 1.0f;
|
||||
|
||||
render_target_->DrawRectangle(DX::ConvertToRectF(rect), brush.Get(), stroke_width, stroke_style.Get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContextImpl::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, StrokeStylePtr stroke,
|
||||
float stroke_width)
|
||||
void RenderContextImpl::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().Get() : nullptr;
|
||||
render_target_->DrawRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y),
|
||||
current_brush_->GetBrush().Get(), stroke_width, stroke_style);
|
||||
auto brush = NativePtr::Get<ID2D1Brush>(current_brush_);
|
||||
auto stroke_style = NativePtr::Get<ID2D1StrokeStyle>(current_stroke_);
|
||||
float stroke_width = current_stroke_ ? current_stroke_->GetStrokeWidth() : 1.0f;
|
||||
|
||||
render_target_->DrawRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y), brush.Get(),
|
||||
stroke_width, stroke_style.Get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
||||
void RenderContextImpl::DrawEllipse(Point const& center, Vec2 const& radius, StrokeStylePtr stroke, float stroke_width)
|
||||
void RenderContextImpl::DrawEllipse(Point const& center, Vec2 const& radius)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().Get() : nullptr;
|
||||
render_target_->DrawEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y),
|
||||
current_brush_->GetBrush().Get(), stroke_width, stroke_style);
|
||||
auto brush = NativePtr::Get<ID2D1Brush>(current_brush_);
|
||||
auto stroke_style = NativePtr::Get<ID2D1StrokeStyle>(current_stroke_);
|
||||
float stroke_width = current_stroke_ ? current_stroke_->GetStrokeWidth() : 1.0f;
|
||||
|
||||
render_target_->DrawEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y), brush.Get(),
|
||||
stroke_width, stroke_style.Get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
|
@ -224,7 +242,9 @@ void RenderContextImpl::FillShape(Shape const& shape)
|
|||
|
||||
if (shape.IsValid())
|
||||
{
|
||||
render_target_->FillGeometry(shape.GetGeometry().Get(), current_brush_->GetBrush().Get());
|
||||
auto brush = NativePtr::Get<ID2D1Brush>(current_brush_);
|
||||
auto geometry = NativePtr::Get<ID2D1Geometry>(shape);
|
||||
render_target_->FillGeometry(geometry.Get(), brush.Get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
|
@ -235,7 +255,8 @@ void RenderContextImpl::FillRectangle(Rect const& rect)
|
|||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
render_target_->FillRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().Get());
|
||||
auto brush = NativePtr::Get<ID2D1Brush>(current_brush_);
|
||||
render_target_->FillRectangle(DX::ConvertToRectF(rect), brush.Get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
|
@ -245,8 +266,8 @@ void RenderContextImpl::FillRoundedRectangle(Rect const& rect, Vec2 const& radiu
|
|||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
render_target_->FillRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y),
|
||||
current_brush_->GetBrush().Get());
|
||||
auto brush = NativePtr::Get<ID2D1Brush>(current_brush_);
|
||||
render_target_->FillRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y), brush.Get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
|
@ -256,8 +277,8 @@ void RenderContextImpl::FillEllipse(Point const& center, Vec2 const& radius)
|
|||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
|
||||
|
||||
render_target_->FillEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y),
|
||||
current_brush_->GetBrush().Get());
|
||||
auto brush = NativePtr::Get<ID2D1Brush>(current_brush_);
|
||||
render_target_->FillEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y), brush.Get());
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
}
|
||||
|
|
@ -272,7 +293,7 @@ void RenderContextImpl::CreateTexture(Texture& texture, math::Vec2T<uint32_t> si
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
texture.SetBitmap(saved_bitmap);
|
||||
NativePtr::Set(texture, saved_bitmap);
|
||||
}
|
||||
|
||||
KGE_THROW_IF_FAILED(hr, "Create texture failed");
|
||||
|
|
@ -281,8 +302,17 @@ void RenderContextImpl::CreateTexture(Texture& texture, math::Vec2T<uint32_t> si
|
|||
void RenderContextImpl::PushClipRect(Rect const& clip_rect)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
render_target_->PushAxisAlignedClip(DX::ConvertToRectF(clip_rect),
|
||||
antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED);
|
||||
|
||||
D2D1_ANTIALIAS_MODE mode;
|
||||
if (antialias_)
|
||||
{
|
||||
mode = D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = D2D1_ANTIALIAS_MODE_ALIASED;
|
||||
}
|
||||
render_target_->PushAxisAlignedClip(DX::ConvertToRectF(clip_rect), mode);
|
||||
}
|
||||
|
||||
void RenderContextImpl::PopClipRect()
|
||||
|
|
@ -294,35 +324,27 @@ void RenderContextImpl::PopClipRect()
|
|||
void RenderContextImpl::PushLayer(Layer& layer)
|
||||
{
|
||||
KGE_ASSERT(render_target_ && "Render target has not been initialized!");
|
||||
if (!layer.IsValid())
|
||||
{
|
||||
ComPtr<ID2D1Layer> output;
|
||||
|
||||
HRESULT hr = render_target_->CreateLayer(&output);
|
||||
auto native = NativePtr::Get<ID2D1Layer>(layer);
|
||||
auto mask = NativePtr::Get<ID2D1Geometry>(layer.GetMaskShape());
|
||||
|
||||
if (!native)
|
||||
{
|
||||
HRESULT hr = render_target_->CreateLayer(&native);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
layer.SetLayer(output);
|
||||
}
|
||||
else
|
||||
{
|
||||
KGE_THROW_IF_FAILED(hr, "Create ID2D1Layer failed");
|
||||
NativePtr::Set(layer, native);
|
||||
}
|
||||
KGE_THROW_IF_FAILED(hr, "Create ID2D1Layer failed");
|
||||
}
|
||||
|
||||
if (layer.IsValid())
|
||||
{
|
||||
ComPtr<ID2D1Geometry> mask;
|
||||
if (layer.GetMaskShape())
|
||||
mask = layer.GetMaskShape()->GetGeometry();
|
||||
auto params = D2D1::LayerParameters(DX::ConvertToRectF(layer.GetClipRect()), mask.Get(),
|
||||
antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED,
|
||||
DX::ConvertToMatrix3x2F(layer.GetMaskTransform()), layer.GetOpacity(), nullptr,
|
||||
D2D1_LAYER_OPTIONS_NONE);
|
||||
|
||||
render_target_->PushLayer(
|
||||
D2D1::LayerParameters(DX::ConvertToRectF(layer.GetClipRect()), mask.Get(),
|
||||
antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED,
|
||||
DX::ConvertToMatrix3x2F(layer.GetMaskTransform()), layer.GetOpacity(), nullptr,
|
||||
D2D1_LAYER_OPTIONS_NONE),
|
||||
layer.GetLayer().Get());
|
||||
}
|
||||
render_target_->PushLayer(params, native.Get());
|
||||
}
|
||||
|
||||
void RenderContextImpl::PopLayer()
|
||||
|
|
@ -358,7 +380,7 @@ void RenderContextImpl::SetCurrentBrush(BrushPtr brush)
|
|||
|
||||
if (current_brush_ && current_brush_->IsValid())
|
||||
{
|
||||
current_brush_->GetBrush()->SetOpacity(brush_opacity_);
|
||||
NativePtr::Get<ID2D1Brush>(current_brush_)->SetOpacity(brush_opacity_);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#pragma once
|
||||
#include <kiwano/render/RenderContext.h>
|
||||
#include <kiwano/render/DirectX/TextRenderer.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -43,15 +44,15 @@ public:
|
|||
|
||||
void DrawTextLayout(TextLayout const& layout, Point const& offset) override;
|
||||
|
||||
void DrawShape(Shape const& shape, StrokeStylePtr stroke, float stroke_width) override;
|
||||
void DrawShape(Shape const& shape) override;
|
||||
|
||||
void DrawLine(Point const& point1, Point const& point2, StrokeStylePtr stroke, float stroke_width) override;
|
||||
void DrawLine(Point const& point1, Point const& point2) override;
|
||||
|
||||
void DrawRectangle(Rect const& rect, StrokeStylePtr stroke, float stroke_width) override;
|
||||
void DrawRectangle(Rect const& rect) override;
|
||||
|
||||
void DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, StrokeStylePtr stroke, float stroke_width) override;
|
||||
void DrawRoundedRectangle(Rect const& rect, Vec2 const& radius) override;
|
||||
|
||||
void DrawEllipse(Point const& center, Vec2 const& radius, StrokeStylePtr stroke, float stroke_width) override;
|
||||
void DrawEllipse(Point const& center, Vec2 const& radius) override;
|
||||
|
||||
void FillShape(Shape const& shape) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -23,9 +23,10 @@
|
|||
#include <kiwano/core/event/WindowEvent.h>
|
||||
#include <kiwano/platform/FileSystem.h>
|
||||
#include <kiwano/platform/Application.h>
|
||||
#include <kiwano/render/ShapeSink.h>
|
||||
#include <kiwano/render/ShapeMaker.h>
|
||||
#include <kiwano/render/DirectX/TextureRenderContextImpl.h>
|
||||
#include <kiwano/render/DirectX/RendererImpl.h>
|
||||
#include <kiwano/render/DirectX/NativePtr.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -226,7 +227,10 @@ void RendererImpl::CreateTexture(Texture& texture, String const& file_path)
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
texture.SetBitmap(bitmap);
|
||||
NativePtr::Set(texture, bitmap);
|
||||
|
||||
texture.SetSize({ bitmap->GetSize().width, bitmap->GetSize().height });
|
||||
texture.SetSizeInPixels({ bitmap->GetPixelSize().width, bitmap->GetPixelSize().height });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -277,7 +281,10 @@ void RendererImpl::CreateTexture(Texture& texture, Resource const& resource)
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
texture.SetBitmap(bitmap);
|
||||
NativePtr::Set(texture, bitmap);
|
||||
|
||||
texture.SetSize({ bitmap->GetSize().width, bitmap->GetSize().height });
|
||||
texture.SetSizeInPixels({ bitmap->GetPixelSize().width, bitmap->GetPixelSize().height });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -314,7 +321,7 @@ void RendererImpl::CreateGifImage(GifImage& gif, String const& file_path)
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
gif.SetDecoder(decoder);
|
||||
NativePtr::Set(gif, decoder);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -345,7 +352,7 @@ void RendererImpl::CreateGifImage(GifImage& gif, Resource const& resource)
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
gif.SetDecoder(decoder);
|
||||
NativePtr::Set(gif, decoder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -364,7 +371,9 @@ void RendererImpl::CreateGifImageFrame(GifImage::Frame& frame, GifImage const& g
|
|||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (gif.GetDecoder() == nullptr)
|
||||
auto decoder = NativePtr::Get<IWICBitmapDecoder>(gif);
|
||||
|
||||
if (!decoder)
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
}
|
||||
|
|
@ -373,7 +382,7 @@ void RendererImpl::CreateGifImageFrame(GifImage::Frame& frame, GifImage const& g
|
|||
{
|
||||
ComPtr<IWICBitmapFrameDecode> wic_frame;
|
||||
|
||||
HRESULT hr = gif.GetDecoder()->GetFrame(UINT(frame_index), &wic_frame);
|
||||
hr = decoder->GetFrame(UINT(frame_index), &wic_frame);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
|
|
@ -383,13 +392,16 @@ void RendererImpl::CreateGifImageFrame(GifImage::Frame& frame, GifImage const& g
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1Bitmap> raw_bitmap;
|
||||
hr = d2d_res_->CreateBitmapFromConverter(raw_bitmap, nullptr, converter);
|
||||
ComPtr<ID2D1Bitmap> bitmap;
|
||||
hr = d2d_res_->CreateBitmapFromConverter(bitmap, nullptr, converter);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.texture = new Texture;
|
||||
frame.texture->SetBitmap(raw_bitmap);
|
||||
NativePtr::Set(frame.texture, bitmap);
|
||||
|
||||
frame.texture->SetSize({ bitmap->GetSize().width, bitmap->GetSize().height });
|
||||
frame.texture->SetSizeInPixels({ bitmap->GetPixelSize().width, bitmap->GetPixelSize().height });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -548,7 +560,7 @@ void RendererImpl::CreateFontCollection(Font& font, String const& file_path)
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
font.SetCollection(font_collection);
|
||||
NativePtr::Set(font, font_collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -579,7 +591,7 @@ void RendererImpl::CreateFontCollection(Font& font, Resource const& res)
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
font.SetCollection(font_collection);
|
||||
NativePtr::Set(font, font_collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -597,32 +609,32 @@ void RendererImpl::CreateTextLayout(TextLayout& layout, const String& content, c
|
|||
|
||||
if (content.empty())
|
||||
{
|
||||
layout.SetTextLayout(nullptr);
|
||||
layout.Clear();
|
||||
layout.SetDirtyFlag(TextLayout::DirtyFlag::Updated);
|
||||
return;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IDWriteTextFormat> format;
|
||||
WideString font_family = style.font_family.empty() ? L"" : string::ToWide(style.font_family);
|
||||
DWRITE_FONT_WEIGHT font_weight = DWRITE_FONT_WEIGHT(style.font_weight);
|
||||
DWRITE_FONT_STYLE font_style = style.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
|
||||
IDWriteFontCollection* collection = style.font ? style.font->GetCollection().Get() : nullptr;
|
||||
WideString font_family = style.font_family.empty() ? L"" : string::ToWide(style.font_family);
|
||||
DWRITE_FONT_WEIGHT font_weight = DWRITE_FONT_WEIGHT(style.font_weight);
|
||||
DWRITE_FONT_STYLE font_style = style.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
|
||||
auto collection = NativePtr::Get<IDWriteFontCollection>(style.font);
|
||||
|
||||
ComPtr<IDWriteTextFormat> format;
|
||||
hr = d2d_res_->CreateTextFormat(format, font_family.c_str(), collection, font_weight, font_style,
|
||||
DWRITE_FONT_STRETCH_NORMAL, style.font_size);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IDWriteTextLayout> output;
|
||||
WideString wide = string::ToWide(content);
|
||||
WideString wide = string::ToWide(content);
|
||||
|
||||
ComPtr<IDWriteTextLayout> output;
|
||||
hr = d2d_res_->CreateTextLayout(output, wide.c_str(), wide.length(), format);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
layout.SetTextLayout(output);
|
||||
NativePtr::Set(layout, output);
|
||||
layout.SetDirtyFlag(TextLayout::DirtyFlag::Updated);
|
||||
}
|
||||
}
|
||||
|
|
@ -639,29 +651,29 @@ void RendererImpl::CreateLineShape(Shape& shape, Point const& begin_pos, Point c
|
|||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ComPtr<ID2D1PathGeometry> path_geo;
|
||||
ComPtr<ID2D1GeometrySink> path_sink;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1PathGeometry> path_geo;
|
||||
hr = d2d_res_->GetFactory()->CreatePathGeometry(&path_geo);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = path_geo->Open(&path_sink);
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1GeometrySink> path_sink;
|
||||
hr = path_geo->Open(&path_sink);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
path_sink->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
|
||||
path_sink->AddLine(DX::ConvertToPoint2F(end_pos));
|
||||
path_sink->EndFigure(D2D1_FIGURE_END_OPEN);
|
||||
hr = path_sink->Close();
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
path_sink->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
|
||||
path_sink->AddLine(DX::ConvertToPoint2F(end_pos));
|
||||
path_sink->EndFigure(D2D1_FIGURE_END_OPEN);
|
||||
hr = path_sink->Close();
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
shape.SetGeometry(path_geo);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
NativePtr::Set(shape, path_geo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KGE_THROW_IF_FAILED(hr, "Create ID2D1PathGeometry failed");
|
||||
|
|
@ -683,7 +695,7 @@ void RendererImpl::CreateRectShape(Shape& shape, Rect const& rect)
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
shape.SetGeometry(output);
|
||||
NativePtr::Set(shape, output);
|
||||
}
|
||||
|
||||
KGE_THROW_IF_FAILED(hr, "Create ID2D1RectangleGeometry failed");
|
||||
|
|
@ -706,7 +718,7 @@ void RendererImpl::CreateRoundedRectShape(Shape& shape, Rect const& rect, Vec2 c
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
shape.SetGeometry(output);
|
||||
NativePtr::Set(shape, output);
|
||||
}
|
||||
|
||||
KGE_THROW_IF_FAILED(hr, "Create ID2D1RoundedRectangleGeometry failed");
|
||||
|
|
@ -729,13 +741,13 @@ void RendererImpl::CreateEllipseShape(Shape& shape, Point const& center, Vec2 co
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
shape.SetGeometry(output);
|
||||
NativePtr::Set(shape, output);
|
||||
}
|
||||
|
||||
KGE_THROW_IF_FAILED(hr, "Create ID2D1EllipseGeometry failed");
|
||||
}
|
||||
|
||||
void RendererImpl::CreateShapeSink(ShapeSink& sink)
|
||||
void RendererImpl::CreateShapeSink(ShapeMaker& maker)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
|
|
@ -743,17 +755,20 @@ void RendererImpl::CreateShapeSink(ShapeSink& sink)
|
|||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
ComPtr<ID2D1PathGeometry> output;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = d2d_res_->GetFactory()->CreatePathGeometry(&output);
|
||||
}
|
||||
ComPtr<ID2D1PathGeometry> geometry;
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
sink.SetPathGeometry(output);
|
||||
}
|
||||
hr = d2d_res_->GetFactory()->CreatePathGeometry(&geometry);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ShapePtr shape = new Shape;
|
||||
NativePtr::Set(shape, geometry);
|
||||
|
||||
maker.SetShape(shape);
|
||||
}
|
||||
}
|
||||
KGE_THROW_IF_FAILED(hr, "Create ID2D1PathGeometry failed");
|
||||
}
|
||||
|
||||
|
|
@ -769,9 +784,9 @@ void RendererImpl::CreateBrush(Brush& brush, Color const& color)
|
|||
{
|
||||
ComPtr<ID2D1SolidColorBrush> solid_brush;
|
||||
|
||||
if (brush.GetType() == Brush::Type::SolidColor && brush.GetBrush())
|
||||
if (brush.GetType() == Brush::Type::SolidColor && brush.IsValid())
|
||||
{
|
||||
hr = brush.GetBrush()->QueryInterface(&solid_brush);
|
||||
hr = NativePtr::Get<ID2D1Brush>(brush)->QueryInterface(&solid_brush);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
solid_brush->SetColor(DX::ConvertToColorF(color));
|
||||
|
|
@ -783,7 +798,7 @@ void RendererImpl::CreateBrush(Brush& brush, Color const& color)
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
brush.SetBrush(solid_brush, Brush::Type::SolidColor);
|
||||
NativePtr::Set(brush, solid_brush);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -815,7 +830,7 @@ void RendererImpl::CreateBrush(Brush& brush, LinearGradientStyle const& style)
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
brush.SetBrush(output, Brush::Type::LinearGradient);
|
||||
NativePtr::Set(brush, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -848,7 +863,7 @@ void RendererImpl::CreateBrush(Brush& brush, RadialGradientStyle const& style)
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
brush.SetBrush(output, Brush::Type::RadialGradient);
|
||||
NativePtr::Set(brush, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -856,8 +871,7 @@ void RendererImpl::CreateBrush(Brush& brush, RadialGradientStyle const& style)
|
|||
KGE_THROW_IF_FAILED(hr, "Create ID2D1RadialGradientBrush failed");
|
||||
}
|
||||
|
||||
void RendererImpl::CreateStrokeStyle(StrokeStyle& stroke_style, CapStyle cap, LineJoinStyle line_join,
|
||||
const float* dash_array, size_t dash_size, float dash_offset)
|
||||
void RendererImpl::CreateStrokeStyle(StrokeStyle& stroke_style)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
|
|
@ -867,16 +881,29 @@ void RendererImpl::CreateStrokeStyle(StrokeStyle& stroke_style, CapStyle cap, Li
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
D2D1_STROKE_STYLE_PROPERTIES style =
|
||||
D2D1::StrokeStyleProperties(D2D1_CAP_STYLE(cap), D2D1_CAP_STYLE(cap), D2D1_CAP_STYLE(cap),
|
||||
D2D1_LINE_JOIN(line_join), 10.0f, D2D1_DASH_STYLE_CUSTOM, dash_offset);
|
||||
D2D1_CAP_STYLE cap = D2D1_CAP_STYLE(stroke_style.GetCapStyle());
|
||||
D2D1_LINE_JOIN line_join = D2D1_LINE_JOIN(stroke_style.GetLineJoinStyle());
|
||||
D2D1_DASH_STYLE dash_style = D2D1_DASH_STYLE_SOLID;
|
||||
const float* dash_array = nullptr;
|
||||
uint32_t dash_count = 0;
|
||||
float dash_offset = stroke_style.GetDashOffset();
|
||||
const auto& dashes = stroke_style.GetDashArray();
|
||||
|
||||
if (!dashes.empty())
|
||||
{
|
||||
dash_array = &dashes[0];
|
||||
dash_count = uint32_t(dashes.size());
|
||||
dash_style = D2D1_DASH_STYLE_CUSTOM;
|
||||
}
|
||||
|
||||
auto params = D2D1::StrokeStyleProperties(cap, cap, cap, line_join, 10.0f, dash_style, dash_offset);
|
||||
|
||||
ComPtr<ID2D1StrokeStyle> output;
|
||||
hr = d2d_res_->GetFactory()->CreateStrokeStyle(style, dash_array, dash_size, &output);
|
||||
hr = d2d_res_->GetFactory()->CreateStrokeStyle(params, dash_array, dash_count, &output);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
stroke_style.SetStrokeStyle(output);
|
||||
NativePtr::Set(stroke_style, output);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ public:
|
|||
|
||||
void CreateEllipseShape(Shape& shape, Point const& center, Vec2 const& radius) override;
|
||||
|
||||
void CreateShapeSink(ShapeSink& sink) override;
|
||||
void CreateShapeSink(ShapeMaker& maker) override;
|
||||
|
||||
void CreateBrush(Brush& brush, Color const& color) override;
|
||||
|
||||
|
|
@ -76,8 +76,7 @@ public:
|
|||
|
||||
void CreateBrush(Brush& brush, RadialGradientStyle const& style) override;
|
||||
|
||||
void CreateStrokeStyle(StrokeStyle& stroke_style, CapStyle cap, LineJoinStyle line_join, const float* dash_array,
|
||||
size_t dash_size, float dash_offset) override;
|
||||
void CreateStrokeStyle(StrokeStyle& stroke_style) override;
|
||||
|
||||
TextureRenderContextPtr CreateTextureRenderContext(const Size* desired_size = nullptr) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <kiwano/core/Logger.h>
|
||||
#include <kiwano/render/Renderer.h>
|
||||
#include <kiwano/render/DirectX/TextureRenderContextImpl.h>
|
||||
#include <kiwano/render/DirectX/NativePtr.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -37,7 +38,10 @@ bool TextureRenderContextImpl::GetOutput(Texture& texture)
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
texture.SetBitmap(bitmap);
|
||||
NativePtr::Set(texture, bitmap);
|
||||
|
||||
texture.SetSize({ bitmap->GetSize().width, bitmap->GetSize().height });
|
||||
texture.SetSizeInPixels({ bitmap->GetPixelSize().width, bitmap->GetPixelSize().height });
|
||||
}
|
||||
}
|
||||
return SUCCEEDED(hr);
|
||||
|
|
|
|||
|
|
@ -19,10 +19,8 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <kiwano/core/ObjectBase.h>
|
||||
#include <kiwano/render/NativeObject.h>
|
||||
#include <kiwano/core/Resource.h>
|
||||
#include <kiwano/platform/win32/ComPtr.hpp>
|
||||
#include <dwrite.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -39,7 +37,7 @@ class Renderer;
|
|||
* \~chinese
|
||||
* @brief 字体
|
||||
*/
|
||||
class Font : public virtual ObjectBase
|
||||
class Font : public NativeObject
|
||||
{
|
||||
friend class Renderer;
|
||||
|
||||
|
|
@ -61,43 +59,8 @@ public:
|
|||
/// \~chinese
|
||||
/// @brief 加载字体资源
|
||||
bool Load(Resource const& resource);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
bool IsValid() const;
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
public:
|
||||
ComPtr<IDWriteFontCollection> GetCollection() const;
|
||||
|
||||
void SetCollection(ComPtr<IDWriteFontCollection> collection);
|
||||
|
||||
private:
|
||||
ComPtr<IDWriteFontCollection> collection_;
|
||||
#endif
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
inline bool Font::IsValid() const
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
return collection_ != nullptr;
|
||||
#else
|
||||
return false; // not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
inline ComPtr<IDWriteFontCollection> Font::GetCollection() const
|
||||
{
|
||||
return collection_;
|
||||
}
|
||||
|
||||
inline void Font::SetCollection(ComPtr<IDWriteFontCollection> collection)
|
||||
{
|
||||
collection_ = collection;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -49,8 +49,6 @@ GifImagePtr GifImage::Create(Resource const& res)
|
|||
|
||||
GifImage::GifImage()
|
||||
: frames_count_(0)
|
||||
, width_in_pixels_(0)
|
||||
, height_in_pixels_(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +61,8 @@ bool GifImage::Load(String const& file_path)
|
|||
if (GetGlobalMetadata())
|
||||
return true;
|
||||
|
||||
SetDecoder(nullptr);
|
||||
// Clear data
|
||||
ResetNativePointer();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -77,7 +76,8 @@ bool GifImage::Load(Resource const& res)
|
|||
if (GetGlobalMetadata())
|
||||
return true;
|
||||
|
||||
SetDecoder(nullptr);
|
||||
// Clear data
|
||||
ResetNativePointer();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -89,20 +89,29 @@ GifImage::Frame GifImage::GetFrame(uint32_t index)
|
|||
return frame;
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
#include <kiwano/render/DirectX/NativePtr.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
bool GifImage::GetGlobalMetadata()
|
||||
{
|
||||
HRESULT hr = decoder_ ? S_OK : E_FAIL;
|
||||
ComPtr<IWICBitmapDecoder> decoder = NativePtr::Get<IWICBitmapDecoder>(this);
|
||||
|
||||
HRESULT hr = decoder ? S_OK : E_FAIL;
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = decoder_->GetFrameCount(&frames_count_);
|
||||
hr = decoder->GetFrameCount(&frames_count_);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICMetadataQueryReader> metadata_reader;
|
||||
hr = decoder_->GetMetadataQueryReader(&metadata_reader);
|
||||
hr = decoder->GetMetadataQueryReader(&metadata_reader);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
|
|
@ -164,20 +173,17 @@ bool GifImage::GetGlobalMetadata()
|
|||
// 根据像素长宽比计算像素中的图像宽度和高度,只缩小图像
|
||||
if (pixel_asp_ratio > 1.f)
|
||||
{
|
||||
width_in_pixels_ = width;
|
||||
height_in_pixels_ = static_cast<uint32_t>(height / pixel_asp_ratio);
|
||||
size_in_pixels_ = { width, static_cast<uint32_t>(height / pixel_asp_ratio) };
|
||||
}
|
||||
else
|
||||
{
|
||||
width_in_pixels_ = static_cast<uint32_t>(width * pixel_asp_ratio);
|
||||
height_in_pixels_ = height;
|
||||
size_in_pixels_ = { static_cast<uint32_t>(width * pixel_asp_ratio), height };
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 值为 0, 所以像素比为 1
|
||||
width_in_pixels_ = width;
|
||||
height_in_pixels_ = height;
|
||||
size_in_pixels_ = { width, height };
|
||||
}
|
||||
}
|
||||
::PropVariantClear(&prop_val);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ KGE_DECLARE_SMART_PTR(GifImage);
|
|||
* \~chinese
|
||||
* @brief GIF图像
|
||||
*/
|
||||
class KGE_API GifImage : public virtual ObjectBase
|
||||
class KGE_API GifImage : public NativeObject
|
||||
{
|
||||
public:
|
||||
/// \~chinese
|
||||
|
|
@ -56,10 +56,6 @@ public:
|
|||
/// @brief 加载GIF资源
|
||||
bool Load(Resource const& res);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
bool IsValid() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取像素宽度
|
||||
uint32_t GetWidthInPixels() const;
|
||||
|
|
@ -68,6 +64,10 @@ public:
|
|||
/// @brief 获取像素高度
|
||||
uint32_t GetHeightInPixels() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取像素大小
|
||||
PixelSize GetSizeInPixels() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取帧数量
|
||||
uint32_t GetFramesCount() const;
|
||||
|
|
@ -105,18 +105,7 @@ private:
|
|||
|
||||
private:
|
||||
uint32_t frames_count_;
|
||||
uint32_t width_in_pixels_;
|
||||
uint32_t height_in_pixels_;
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
public:
|
||||
ComPtr<IWICBitmapDecoder> GetDecoder() const;
|
||||
|
||||
void SetDecoder(ComPtr<IWICBitmapDecoder> decoder);
|
||||
|
||||
private:
|
||||
ComPtr<IWICBitmapDecoder> decoder_;
|
||||
#endif
|
||||
PixelSize size_in_pixels_;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
|
@ -128,12 +117,17 @@ inline GifImage::Frame::Frame()
|
|||
|
||||
inline uint32_t GifImage::GetWidthInPixels() const
|
||||
{
|
||||
return width_in_pixels_;
|
||||
return size_in_pixels_.x;
|
||||
}
|
||||
|
||||
inline uint32_t GifImage::GetHeightInPixels() const
|
||||
{
|
||||
return height_in_pixels_;
|
||||
return size_in_pixels_.y;
|
||||
}
|
||||
|
||||
inline PixelSize GifImage::GetSizeInPixels() const
|
||||
{
|
||||
return size_in_pixels_;
|
||||
}
|
||||
|
||||
inline uint32_t GifImage::GetFramesCount() const
|
||||
|
|
@ -141,25 +135,4 @@ inline uint32_t GifImage::GetFramesCount() const
|
|||
return frames_count_;
|
||||
}
|
||||
|
||||
inline bool GifImage::IsValid() const
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
return decoder_ != nullptr;
|
||||
#else
|
||||
return false; // not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
inline ComPtr<IWICBitmapDecoder> GifImage::GetDecoder() const
|
||||
{
|
||||
return decoder_;
|
||||
}
|
||||
|
||||
inline void GifImage::SetDecoder(ComPtr<IWICBitmapDecoder> decoder)
|
||||
{
|
||||
decoder_ = decoder;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
namespace kiwano
|
||||
{
|
||||
|
||||
KGE_DECLARE_SMART_PTR(Layer);
|
||||
|
||||
/**
|
||||
* \addtogroup Render
|
||||
* @{
|
||||
|
|
@ -33,15 +35,11 @@ namespace kiwano
|
|||
* \~chinese
|
||||
* @brief 图层
|
||||
*/
|
||||
class KGE_API Layer
|
||||
class KGE_API Layer : public NativeObject
|
||||
{
|
||||
public:
|
||||
Layer();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
bool IsValid() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取图层裁剪区域
|
||||
Rect const& GetClipRect() const;
|
||||
|
|
@ -79,29 +77,10 @@ private:
|
|||
float opacity_;
|
||||
ShapePtr mask_;
|
||||
Matrix3x2 mask_transform_;
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
public:
|
||||
ComPtr<ID2D1Layer> GetLayer() const;
|
||||
|
||||
void SetLayer(ComPtr<ID2D1Layer> layer);
|
||||
|
||||
private:
|
||||
ComPtr<ID2D1Layer> layer_;
|
||||
#endif
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
inline bool Layer::IsValid() const
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
return layer_ != nullptr;
|
||||
#else
|
||||
return false; // not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
inline Rect const& Layer::GetClipRect() const
|
||||
{
|
||||
return clip_rect_;
|
||||
|
|
@ -142,16 +121,4 @@ inline void Layer::SetMaskTransform(Matrix3x2 const& matrix)
|
|||
mask_transform_ = matrix;
|
||||
}
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
inline ComPtr<ID2D1Layer> Layer::GetLayer() const
|
||||
{
|
||||
return layer_;
|
||||
}
|
||||
|
||||
inline void Layer::SetLayer(ComPtr<ID2D1Layer> layer)
|
||||
{
|
||||
layer_ = layer;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
// 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/core/ObjectBase.h>
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
#include <kiwano/render/DirectX/D2DDeviceResources.h>
|
||||
#endif
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
KGE_DECLARE_SMART_PTR(NativeObject);
|
||||
|
||||
/**
|
||||
* \addtogroup Render
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 含有本机指针的对象
|
||||
*/
|
||||
class KGE_API NativeObject : public virtual ObjectBase
|
||||
{
|
||||
public:
|
||||
virtual bool IsValid() const;
|
||||
|
||||
Any GetNativePointer() const;
|
||||
|
||||
template <typename _NativeTy>
|
||||
_NativeTy GetNativePointer() const;
|
||||
|
||||
void SetNativePointer(const Any& native_pointer);
|
||||
|
||||
void ResetNativePointer();
|
||||
|
||||
private:
|
||||
Any native_pointer_;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
inline bool NativeObject::IsValid() const
|
||||
{
|
||||
return native_pointer_.HasValue();
|
||||
}
|
||||
|
||||
inline Any NativeObject::GetNativePointer() const
|
||||
{
|
||||
return native_pointer_;
|
||||
}
|
||||
|
||||
template <typename _NativeTy>
|
||||
inline _NativeTy NativeObject::GetNativePointer() const
|
||||
{
|
||||
if (native_pointer_.HasValue())
|
||||
{
|
||||
return native_pointer_.Cast<_NativeTy>();
|
||||
}
|
||||
return _NativeTy();
|
||||
}
|
||||
|
||||
inline void NativeObject::SetNativePointer(const Any& native_pointer)
|
||||
{
|
||||
native_pointer_ = native_pointer;
|
||||
}
|
||||
|
||||
inline void NativeObject::ResetNativePointer()
|
||||
{
|
||||
native_pointer_.Clear();
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano/render/RenderContext.h>
|
||||
#include <kiwano/render/Renderer.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -105,4 +106,17 @@ void RenderContext::SetCurrentBrush(BrushPtr brush)
|
|||
current_brush_ = brush;
|
||||
}
|
||||
|
||||
void RenderContext::SetCurrentStrokeStyle(StrokeStylePtr stroke)
|
||||
{
|
||||
if (current_stroke_ != stroke)
|
||||
{
|
||||
current_stroke_ = stroke;
|
||||
|
||||
if (current_stroke_ && !current_stroke_->IsValid())
|
||||
{
|
||||
Renderer::GetInstance().CreateStrokeStyle(*current_stroke_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#include <kiwano/render/Layer.h>
|
||||
#include <kiwano/render/TextLayout.h>
|
||||
#include <kiwano/render/Texture.h>
|
||||
#include <kiwano/render/DirectX/TextRenderer.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -87,42 +86,30 @@ public:
|
|||
/// \~chinese
|
||||
/// @brief 绘制形状轮廓
|
||||
/// @param shape 形状
|
||||
/// @param stroke 线条样式
|
||||
/// @param stroke_width 线条宽度
|
||||
virtual void DrawShape(Shape const& shape, StrokeStylePtr stroke, float stroke_width) = 0;
|
||||
virtual void DrawShape(Shape const& shape) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 绘制线段
|
||||
/// @param point1 线段起点
|
||||
/// @param point2 线段终点
|
||||
/// @param stroke 线条样式
|
||||
/// @param stroke_width 线条宽度
|
||||
virtual void DrawLine(Point const& point1, Point const& point2, StrokeStylePtr stroke, float stroke_width) = 0;
|
||||
virtual void DrawLine(Point const& point1, Point const& point2) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 绘制矩形边框
|
||||
/// @param rect 矩形
|
||||
/// @param stroke 线条样式
|
||||
/// @param stroke_width 线条宽度
|
||||
virtual void DrawRectangle(Rect const& rect, StrokeStylePtr stroke, float stroke_width) = 0;
|
||||
virtual void DrawRectangle(Rect const& rect) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 绘制圆角矩形边框
|
||||
/// @param rect 矩形
|
||||
/// @param radius 圆角半径
|
||||
/// @param stroke 线条样式
|
||||
/// @param stroke_width 线条宽度
|
||||
virtual void DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, StrokeStylePtr stroke,
|
||||
float stroke_width) = 0;
|
||||
virtual void DrawRoundedRectangle(Rect const& rect, Vec2 const& radius) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 绘制椭圆边框
|
||||
/// @param center 圆心
|
||||
/// @param radius 椭圆半径
|
||||
/// @param stroke 线条样式
|
||||
/// @param stroke_width 线条宽度
|
||||
virtual void DrawEllipse(Point const& center, Vec2 const& radius, StrokeStylePtr stroke,
|
||||
float stroke_width) = 0;
|
||||
virtual void DrawEllipse(Point const& center, Vec2 const& radius) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 填充形状
|
||||
|
|
@ -200,9 +187,13 @@ public:
|
|||
virtual void SetBrushOpacity(float opacity);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置当前画刷
|
||||
/// @brief 设置当前使用的画刷
|
||||
virtual void SetCurrentBrush(BrushPtr brush);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置当前使用的线条样式
|
||||
virtual void SetCurrentStrokeStyle(StrokeStylePtr stroke);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置抗锯齿模式
|
||||
virtual void SetAntialiasMode(bool enabled) = 0;
|
||||
|
|
@ -265,6 +256,7 @@ protected:
|
|||
float brush_opacity_;
|
||||
TextAntialiasMode text_antialias_;
|
||||
BrushPtr current_brush_;
|
||||
StrokeStylePtr current_stroke_;
|
||||
Rect visible_size_;
|
||||
Matrix3x2 global_transform_;
|
||||
mutable Status status_;
|
||||
|
|
|
|||
|
|
@ -154,9 +154,9 @@ public:
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 创建几何图形生成器内部资源
|
||||
/// @param[out] sink 形状生成器
|
||||
/// @param[out] maker 形状生成器
|
||||
/// @throw kiwano::SystemError 创建失败时抛出
|
||||
virtual void CreateShapeSink(ShapeSink& sink) = 0;
|
||||
virtual void CreateShapeSink(ShapeMaker& maker) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建纯色画刷内部资源
|
||||
|
|
@ -188,8 +188,7 @@ public:
|
|||
/// @param[in] dash_size 虚线数组大小
|
||||
/// @param[in] dash_offset 虚线偏移量
|
||||
/// @throw kiwano::SystemError 创建失败时抛出
|
||||
virtual void CreateStrokeStyle(StrokeStyle& stroke_style, CapStyle cap, LineJoinStyle line_join,
|
||||
const float* dash_array, size_t dash_size, float dash_offset) = 0;
|
||||
virtual void CreateStrokeStyle(StrokeStyle& stroke_style) = 0;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建纹理渲染上下文
|
||||
|
|
|
|||
|
|
@ -19,22 +19,32 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano/render/Shape.h>
|
||||
#include <kiwano/render/ShapeSink.h>
|
||||
#include <kiwano/render/ShapeMaker.h>
|
||||
#include <kiwano/render/Renderer.h>
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
#include <kiwano/render/DirectX/NativePtr.h>
|
||||
#endif
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
Shape::Shape() {}
|
||||
|
||||
void Shape::Clear()
|
||||
{
|
||||
ResetNativePointer();
|
||||
}
|
||||
|
||||
Rect Shape::GetBoundingBox() const
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
Rect bounds;
|
||||
if (geo_)
|
||||
auto geometry = NativePtr::Get<ID2D1Geometry>(this);
|
||||
if (geometry)
|
||||
{
|
||||
// no matter it failed or not
|
||||
geo_->GetBounds(nullptr, DX::ConvertToRectF(&bounds));
|
||||
geometry->GetBounds(nullptr, DX::ConvertToRectF(&bounds));
|
||||
}
|
||||
return bounds;
|
||||
#else
|
||||
|
|
@ -46,10 +56,11 @@ Rect Shape::GetBoundingBox(Matrix3x2 const& transform) const
|
|||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
Rect bounds;
|
||||
if (geo_)
|
||||
auto geometry = NativePtr::Get<ID2D1Geometry>(this);
|
||||
if (geometry)
|
||||
{
|
||||
// no matter it failed or not
|
||||
geo_->GetBounds(DX::ConvertToMatrix3x2F(transform), DX::ConvertToRectF(&bounds));
|
||||
geometry->GetBounds(DX::ConvertToMatrix3x2F(transform), DX::ConvertToRectF(&bounds));
|
||||
}
|
||||
return bounds;
|
||||
#else
|
||||
|
|
@ -61,10 +72,11 @@ float Shape::GetLength() const
|
|||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
float length = 0.f;
|
||||
if (geo_)
|
||||
auto geometry = NativePtr::Get<ID2D1Geometry>(this);
|
||||
if (geometry)
|
||||
{
|
||||
// no matter it failed or not
|
||||
geo_->ComputeLength(D2D1::Matrix3x2F::Identity(), &length);
|
||||
geometry->ComputeLength(D2D1::Matrix3x2F::Identity(), &length);
|
||||
}
|
||||
return length;
|
||||
#else
|
||||
|
|
@ -75,9 +87,10 @@ float Shape::GetLength() const
|
|||
bool Shape::ComputePointAtLength(float length, Point& point, Vec2& tangent) const
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
if (geo_)
|
||||
auto geometry = NativePtr::Get<ID2D1Geometry>(this);
|
||||
if (geometry)
|
||||
{
|
||||
HRESULT hr = geo_->ComputePointAtLength(length, D2D1::Matrix3x2F::Identity(), DX::ConvertToPoint2F(&point),
|
||||
HRESULT hr = geometry->ComputePointAtLength(length, D2D1::Matrix3x2F::Identity(), DX::ConvertToPoint2F(&point),
|
||||
DX::ConvertToPoint2F(&tangent));
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
|
|
@ -88,25 +101,17 @@ bool Shape::ComputePointAtLength(float length, Point& point, Vec2& tangent) cons
|
|||
#endif
|
||||
}
|
||||
|
||||
void Shape::Clear()
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
geo_.Reset();
|
||||
#else
|
||||
return; // not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
float Shape::ComputeArea() const
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
if (!geo_)
|
||||
return 0.f;
|
||||
|
||||
float area = 0.f;
|
||||
// no matter it failed or not
|
||||
geo_->ComputeArea(D2D1::Matrix3x2F::Identity(), &area);
|
||||
return area;
|
||||
auto geometry = NativePtr::Get<ID2D1Geometry>(this);
|
||||
if (geometry)
|
||||
{
|
||||
float area = 0.f;
|
||||
// no matter it failed or not
|
||||
geometry->ComputeArea(D2D1::Matrix3x2F::Identity(), &area);
|
||||
}
|
||||
return 0.f;
|
||||
#else
|
||||
return 0.0f; // not supported
|
||||
#endif
|
||||
|
|
@ -115,12 +120,13 @@ float Shape::ComputeArea() const
|
|||
bool Shape::ContainsPoint(Point const& point, const Matrix3x2* transform) const
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
if (!geo_)
|
||||
auto geometry = NativePtr::Get<ID2D1Geometry>(this);
|
||||
if (!geometry)
|
||||
return false;
|
||||
|
||||
BOOL ret = 0;
|
||||
// no matter it failed or not
|
||||
geo_->FillContainsPoint(DX::ConvertToPoint2F(point), DX::ConvertToMatrix3x2F(transform),
|
||||
geometry->FillContainsPoint(DX::ConvertToPoint2F(point), DX::ConvertToMatrix3x2F(transform),
|
||||
D2D1_DEFAULT_FLATTENING_TOLERANCE, &ret);
|
||||
return !!ret;
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -19,12 +19,11 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <kiwano/core/ObjectBase.h>
|
||||
#include <kiwano/render/DirectX/D2DDeviceResources.h>
|
||||
#include <kiwano/render/NativeObject.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
class ShapeSink;
|
||||
class ShapeMaker;
|
||||
|
||||
KGE_DECLARE_SMART_PTR(Shape);
|
||||
|
||||
|
|
@ -37,9 +36,9 @@ KGE_DECLARE_SMART_PTR(Shape);
|
|||
* \~chinese
|
||||
* @brief 形状
|
||||
*/
|
||||
class KGE_API Shape : public virtual ObjectBase
|
||||
class KGE_API Shape : public NativeObject
|
||||
{
|
||||
friend class ShapeSink;
|
||||
friend class ShapeMaker;
|
||||
|
||||
public:
|
||||
/// \~chinese
|
||||
|
|
@ -73,10 +72,6 @@ public:
|
|||
|
||||
Shape();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
bool IsValid() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取外切包围盒
|
||||
Rect GetBoundingBox() const;
|
||||
|
|
@ -110,39 +105,8 @@ public:
|
|||
/// \~chinese
|
||||
/// @brief 清除形状
|
||||
void Clear();
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
public:
|
||||
ComPtr<ID2D1Geometry> GetGeometry() const;
|
||||
|
||||
void SetGeometry(ComPtr<ID2D1Geometry> shape);
|
||||
|
||||
private:
|
||||
ComPtr<ID2D1Geometry> geo_;
|
||||
#endif
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
inline bool Shape::IsValid() const
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
return geo_ != nullptr;
|
||||
#else
|
||||
return false; // not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
inline ComPtr<ID2D1Geometry> Shape::GetGeometry() const
|
||||
{
|
||||
return geo_;
|
||||
}
|
||||
|
||||
inline void Shape::SetGeometry(ComPtr<ID2D1Geometry> shape)
|
||||
{
|
||||
geo_ = shape;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -0,0 +1,224 @@
|
|||
// 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/render/ShapeMaker.h>
|
||||
#include <kiwano/render/Renderer.h>
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
#include <kiwano/render/DirectX/NativePtr.h>
|
||||
#endif
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
ShapeMakerPtr ShapeMaker::Create()
|
||||
{
|
||||
ShapeMakerPtr maker = new (std::nothrow) ShapeMaker;
|
||||
return maker;
|
||||
}
|
||||
|
||||
ShapeMaker::ShapeMaker() {}
|
||||
|
||||
ShapeMaker::~ShapeMaker()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void ShapeMaker::Clear()
|
||||
{
|
||||
CloseStream();
|
||||
ResetNativePointer();
|
||||
}
|
||||
|
||||
ShapePtr ShapeMaker::GetShape()
|
||||
{
|
||||
return shape_;
|
||||
}
|
||||
|
||||
bool ShapeMaker::IsStreamOpened() const
|
||||
{
|
||||
return IsValid();
|
||||
}
|
||||
|
||||
void ShapeMaker::BeginPath(Point const& begin_pos)
|
||||
{
|
||||
if (!IsStreamOpened())
|
||||
{
|
||||
OpenStream();
|
||||
}
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
auto native = NativePtr::Get<ID2D1GeometrySink>(this);
|
||||
native->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
void ShapeMaker::EndPath(bool closed)
|
||||
{
|
||||
KGE_ASSERT(IsStreamOpened());
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
auto native = NativePtr::Get<ID2D1GeometrySink>(this);
|
||||
native->EndFigure(closed ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN);
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
|
||||
this->CloseStream();
|
||||
}
|
||||
|
||||
void ShapeMaker::AddLine(Point const& point)
|
||||
{
|
||||
KGE_ASSERT(IsStreamOpened());
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
auto native = NativePtr::Get<ID2D1GeometrySink>(this);
|
||||
native->AddLine(DX::ConvertToPoint2F(point));
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
void ShapeMaker::AddLines(Vector<Point> const& points)
|
||||
{
|
||||
KGE_ASSERT(IsStreamOpened());
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
auto native = NativePtr::Get<ID2D1GeometrySink>(this);
|
||||
native->AddLines(reinterpret_cast<const D2D_POINT_2F*>(&points[0]), static_cast<uint32_t>(points.size()));
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
void kiwano::ShapeMaker::AddLines(const Point* points, size_t count)
|
||||
{
|
||||
KGE_ASSERT(IsStreamOpened());
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
auto native = NativePtr::Get<ID2D1GeometrySink>(this);
|
||||
native->AddLines(reinterpret_cast<const D2D_POINT_2F*>(points), UINT32(count));
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
void ShapeMaker::AddBezier(Point const& point1, Point const& point2, Point const& point3)
|
||||
{
|
||||
KGE_ASSERT(IsStreamOpened());
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
auto native = NativePtr::Get<ID2D1GeometrySink>(this);
|
||||
native->AddBezier(
|
||||
D2D1::BezierSegment(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2), DX::ConvertToPoint2F(point3)));
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
void ShapeMaker::AddArc(Point const& point, Size const& radius, float rotation, bool clockwise, bool is_small)
|
||||
{
|
||||
KGE_ASSERT(IsStreamOpened());
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
auto native = NativePtr::Get<ID2D1GeometrySink>(this);
|
||||
native->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));
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
ShapePtr ShapeMaker::Combine(ShapePtr shape_a, ShapePtr shape_b, CombineMode mode, const Matrix3x2* matrix)
|
||||
{
|
||||
ShapeMakerPtr maker = ShapeMaker::Create();
|
||||
maker->OpenStream();
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
if (shape_a && shape_b)
|
||||
{
|
||||
auto geo_a = NativePtr::Get<ID2D1Geometry>(shape_a);
|
||||
auto geo_b = NativePtr::Get<ID2D1Geometry>(shape_b);
|
||||
auto native = NativePtr::Get<ID2D1GeometrySink>(maker);
|
||||
|
||||
HRESULT hr = geo_a->CombineWithGeometry(geo_b.Get(), D2D1_COMBINE_MODE(mode), DX::ConvertToMatrix3x2F(matrix),
|
||||
native.Get());
|
||||
|
||||
KGE_THROW_IF_FAILED(hr, "ID2D1Geometry::CombineWithGeometry failed");
|
||||
}
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
|
||||
maker->CloseStream();
|
||||
return maker->GetShape();
|
||||
}
|
||||
|
||||
void ShapeMaker::OpenStream()
|
||||
{
|
||||
if (IsStreamOpened())
|
||||
return;
|
||||
|
||||
Renderer::GetInstance().CreateShapeSink(*this);
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
auto geometry = NativePtr::Get<ID2D1PathGeometry>(shape_);
|
||||
if (geometry)
|
||||
{
|
||||
ComPtr<ID2D1GeometrySink> native;
|
||||
|
||||
HRESULT hr = geometry->Open(&native);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
NativePtr::Set(this, native);
|
||||
}
|
||||
KGE_THROW_IF_FAILED(hr, "ID2D1PathGeometry::Open failed");
|
||||
}
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
void ShapeMaker::CloseStream()
|
||||
{
|
||||
if (!IsStreamOpened())
|
||||
return;
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
auto native = NativePtr::Get<ID2D1GeometrySink>(this);
|
||||
|
||||
HRESULT hr = native->Close();
|
||||
KGE_THROW_IF_FAILED(hr, "ID2D1PathGeometry::Close failed");
|
||||
|
||||
ResetNativePointer();
|
||||
#else
|
||||
return; // not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
void ShapeMaker::SetShape(ShapePtr shape)
|
||||
{
|
||||
shape_ = shape;
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
@ -24,13 +24,15 @@
|
|||
namespace kiwano
|
||||
{
|
||||
|
||||
KGE_DECLARE_SMART_PTR(ShapeMaker);
|
||||
|
||||
/**
|
||||
* \addtogroup Render
|
||||
* @{
|
||||
*/
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 形状组合方式
|
||||
/// @brief 形状合并方式
|
||||
enum class CombineMode
|
||||
{
|
||||
Union, ///< 并集 (A + B)
|
||||
|
|
@ -41,70 +43,57 @@ enum class CombineMode
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 形状生成器
|
||||
class KGE_API ShapeSink : protected Noncopyable
|
||||
class KGE_API ShapeMaker : public NativeObject
|
||||
{
|
||||
public:
|
||||
ShapeSink();
|
||||
|
||||
~ShapeSink();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 打开输入流
|
||||
void Open();
|
||||
/// @brief 创建形状生成器
|
||||
static ShapeMakerPtr Create();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 关闭输入流
|
||||
void Close();
|
||||
ShapeMaker();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 输入流是否已经打开
|
||||
bool IsOpened() const;
|
||||
~ShapeMaker();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取生成的形状
|
||||
/// @note 若还未关闭输入流,则自动关闭
|
||||
ShapePtr GetShape();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加形状的轮廓
|
||||
/// @param input 输入的形状
|
||||
/// @param input_matrix 应用到输入形状上的二维变换
|
||||
/// @note 若还未打开输入流,则自动打开
|
||||
ShapeSink& AddShape(ShapePtr input, const Matrix3x2* input_matrix = nullptr);
|
||||
/// @brief 清空图形
|
||||
void Clear();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 开始添加路径
|
||||
/// @brief 开始添加路径并打开输入流
|
||||
/// @param begin_pos 路径起始点
|
||||
/// @note 若还未打开输入流,则自动打开
|
||||
ShapeSink& BeginPath(Point const& begin_pos = Point());
|
||||
void BeginPath(Point const& begin_pos = Point());
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 结束路径
|
||||
/// @brief 结束路径并关闭输入流
|
||||
/// @param closed 路径是否闭合
|
||||
ShapeSink& EndPath(bool closed = false);
|
||||
void EndPath(bool closed = false);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加一条线段
|
||||
/// @param point 端点
|
||||
ShapeSink& AddLine(Point const& point);
|
||||
void AddLine(Point const& point);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加多条线段
|
||||
/// @param points 端点集合
|
||||
ShapeSink& AddLines(Vector<Point> const& points);
|
||||
void AddLines(Vector<Point> const& points);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加多条线段
|
||||
/// @param points 端点数组
|
||||
/// @param count 端点数量
|
||||
ShapeSink& AddLines(const Point* points, size_t count);
|
||||
void AddLines(const Point* points, size_t count);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加一条三次方贝塞尔曲线
|
||||
/// @param point1 贝塞尔曲线的第一个控制点
|
||||
/// @param point2 贝塞尔曲线的第二个控制点
|
||||
/// @param point3 贝塞尔曲线的终点
|
||||
ShapeSink& AddBezier(Point const& point1, Point const& point2, Point const& point3);
|
||||
void AddBezier(Point const& point1, Point const& point2, Point const& point3);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 添加弧线
|
||||
|
|
@ -113,63 +102,42 @@ public:
|
|||
/// @param rotation 椭圆旋转角度
|
||||
/// @param clockwise 顺时针 or 逆时针
|
||||
/// @param is_small 是否取小于 180° 的弧
|
||||
ShapeSink& AddArc(Point const& point, Size const& radius, float rotation, bool clockwise = true,
|
||||
bool is_small = true);
|
||||
void AddArc(Point const& point, Size const& radius, float rotation, bool clockwise = true, bool is_small = true);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 组合形状,并将结果输出到流中
|
||||
/// @brief 合并形状
|
||||
/// @param shape_a 输入的形状A
|
||||
/// @param shape_b 输入的形状B
|
||||
/// @param mode 组合方式
|
||||
/// @param mode 合并方式
|
||||
/// @param matrix 应用到输入形状B上的二维变换
|
||||
/// @note 若还未打开输入流,则自动打开
|
||||
ShapeSink& Combine(ShapePtr shape_a, ShapePtr shape_b, CombineMode mode, const Matrix3x2* matrix = nullptr);
|
||||
/// @return 返回合并后的形状
|
||||
static ShapePtr Combine(ShapePtr shape_a, ShapePtr shape_b, CombineMode mode, const Matrix3x2* matrix = nullptr);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 清空图形
|
||||
void Clear();
|
||||
/// @brief 设置生成的形状
|
||||
/// @note 应由系统调用该函数
|
||||
void SetShape(ShapePtr shape);
|
||||
|
||||
private:
|
||||
/// \~chinese
|
||||
/// @brief 打开输入流
|
||||
/// @note 应由系统调用该函数
|
||||
void OpenStream();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 关闭输入流
|
||||
/// @note 应由系统调用该函数
|
||||
void CloseStream();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 输入流是否已经打开
|
||||
/// @note 应由系统调用该函数
|
||||
bool IsStreamOpened() const;
|
||||
|
||||
private:
|
||||
ShapePtr shape_;
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
public:
|
||||
ComPtr<ID2D1PathGeometry> GetPathGeometry() const;
|
||||
|
||||
void SetPathGeometry(ComPtr<ID2D1PathGeometry> path);
|
||||
|
||||
ComPtr<ID2D1GeometrySink> GetGeometrySink() const;
|
||||
|
||||
void SetGeometrySink(ComPtr<ID2D1GeometrySink> sink);
|
||||
|
||||
private:
|
||||
ComPtr<ID2D1GeometrySink> sink_;
|
||||
ComPtr<ID2D1PathGeometry> path_geo_;
|
||||
#endif
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
inline ComPtr<ID2D1PathGeometry> ShapeSink::GetPathGeometry() const
|
||||
{
|
||||
return path_geo_;
|
||||
}
|
||||
|
||||
inline void ShapeSink::SetPathGeometry(ComPtr<ID2D1PathGeometry> path)
|
||||
{
|
||||
path_geo_ = path;
|
||||
}
|
||||
|
||||
inline ComPtr<ID2D1GeometrySink> ShapeSink::GetGeometrySink() const
|
||||
{
|
||||
return sink_;
|
||||
}
|
||||
|
||||
inline void ShapeSink::SetGeometrySink(ComPtr<ID2D1GeometrySink> sink)
|
||||
{
|
||||
sink_ = sink;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
@ -1,220 +0,0 @@
|
|||
// 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/render/ShapeSink.h>
|
||||
#include <kiwano/render/Renderer.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
ShapeSink::ShapeSink() {}
|
||||
|
||||
ShapeSink::~ShapeSink()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void ShapeSink::Open()
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
if (!IsOpened())
|
||||
{
|
||||
path_geo_.Reset();
|
||||
Renderer::GetInstance().CreateShapeSink(*this);
|
||||
|
||||
KGE_THROW_IF_FAILED(path_geo_->Open(&sink_), "Open ID2D1GeometrySink failed");
|
||||
}
|
||||
#else
|
||||
return; // not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
void ShapeSink::Close()
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
if (IsOpened())
|
||||
{
|
||||
KGE_THROW_IF_FAILED(sink_->Close(), "Close ID2D1GeometrySink failed");
|
||||
sink_.Reset();
|
||||
}
|
||||
|
||||
shape_ = new Shape;
|
||||
shape_->SetGeometry(path_geo_);
|
||||
#else
|
||||
return; // not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ShapeSink::IsOpened() const
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
return sink_ != nullptr;
|
||||
#else
|
||||
return false; // not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
ShapePtr ShapeSink::GetShape()
|
||||
{
|
||||
Close();
|
||||
return shape_;
|
||||
}
|
||||
|
||||
ShapeSink& ShapeSink::AddShape(ShapePtr input, const Matrix3x2* input_matrix)
|
||||
{
|
||||
if (!IsOpened())
|
||||
{
|
||||
Open();
|
||||
}
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
if (input && input->IsValid())
|
||||
{
|
||||
ComPtr<ID2D1Geometry> geo = input->GetGeometry();
|
||||
|
||||
HRESULT hr =
|
||||
geo->Outline(DX::ConvertToMatrix3x2F(input_matrix), D2D1_DEFAULT_FLATTENING_TOLERANCE, sink_.Get());
|
||||
KGE_THROW_IF_FAILED(hr, "Get outline of ID2D1Geometry failed");
|
||||
}
|
||||
return (*this);
|
||||
#else
|
||||
return (*this); // not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
ShapeSink& ShapeSink::BeginPath(Point const& begin_pos)
|
||||
{
|
||||
if (!IsOpened())
|
||||
{
|
||||
Open();
|
||||
}
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
sink_->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
return (*this);
|
||||
}
|
||||
|
||||
ShapeSink& ShapeSink::EndPath(bool closed)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
KGE_ASSERT(sink_);
|
||||
sink_->EndFigure(closed ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN);
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
return (*this);
|
||||
}
|
||||
|
||||
ShapeSink& ShapeSink::AddLine(Point const& point)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
KGE_ASSERT(sink_);
|
||||
sink_->AddLine(DX::ConvertToPoint2F(point));
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
return (*this);
|
||||
}
|
||||
|
||||
ShapeSink& ShapeSink::AddLines(Vector<Point> const& points)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
KGE_ASSERT(sink_);
|
||||
sink_->AddLines(reinterpret_cast<const D2D_POINT_2F*>(&points[0]), static_cast<uint32_t>(points.size()));
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
return (*this);
|
||||
}
|
||||
|
||||
ShapeSink& kiwano::ShapeSink::AddLines(const Point* points, size_t count)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
KGE_ASSERT(sink_);
|
||||
sink_->AddLines(reinterpret_cast<const D2D_POINT_2F*>(points), UINT32(count));
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
return (*this);
|
||||
}
|
||||
|
||||
ShapeSink& ShapeSink::AddBezier(Point const& point1, Point const& point2, Point const& point3)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
KGE_ASSERT(sink_);
|
||||
sink_->AddBezier(
|
||||
D2D1::BezierSegment(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2), DX::ConvertToPoint2F(point3)));
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
return (*this);
|
||||
}
|
||||
|
||||
ShapeSink& ShapeSink::AddArc(Point const& point, Size const& radius, float rotation, bool clockwise, bool is_small)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
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));
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
return (*this);
|
||||
}
|
||||
|
||||
ShapeSink& ShapeSink::Combine(ShapePtr shape_a, ShapePtr shape_b, CombineMode mode, const Matrix3x2* matrix)
|
||||
{
|
||||
if (!IsOpened())
|
||||
{
|
||||
Open();
|
||||
}
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
if (shape_a && shape_b)
|
||||
{
|
||||
ComPtr<ID2D1Geometry> geo_a_raw = shape_a->geo_;
|
||||
ComPtr<ID2D1Geometry> geo_b_raw = shape_b->geo_;
|
||||
|
||||
HRESULT hr = geo_a_raw->CombineWithGeometry(geo_b_raw.Get(), D2D1_COMBINE_MODE(mode),
|
||||
DX::ConvertToMatrix3x2F(matrix), sink_.Get());
|
||||
KGE_THROW_IF_FAILED(hr, "Combine ID2D1Geometry failed");
|
||||
}
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
return (*this);
|
||||
}
|
||||
|
||||
void ShapeSink::Clear()
|
||||
{
|
||||
Close();
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
path_geo_.Reset();
|
||||
#else
|
||||
// not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
@ -24,11 +24,18 @@
|
|||
namespace kiwano
|
||||
{
|
||||
|
||||
StrokeStylePtr StrokeStyle::Create(CapStyle cap, LineJoinStyle line_join, DashStyle dash, float dash_offset)
|
||||
StrokeStylePtr StrokeStyle::Create(float width, CapStyle cap, LineJoinStyle line_join)
|
||||
{
|
||||
return StrokeStyle::Create(width, cap, line_join, DashStyle::Solid);
|
||||
}
|
||||
|
||||
StrokeStylePtr StrokeStyle::Create(float width, CapStyle cap, LineJoinStyle line_join, DashStyle dash,
|
||||
float dash_offset)
|
||||
{
|
||||
StrokeStylePtr ptr = new (std::nothrow) StrokeStyle;
|
||||
if (ptr)
|
||||
{
|
||||
ptr->SetStrokeWidth(width);
|
||||
ptr->SetCapStyle(cap);
|
||||
ptr->SetLineJoinStyle(line_join);
|
||||
ptr->SetDashStyle(dash);
|
||||
|
|
@ -37,12 +44,13 @@ StrokeStylePtr StrokeStyle::Create(CapStyle cap, LineJoinStyle line_join, DashSt
|
|||
return ptr;
|
||||
}
|
||||
|
||||
StrokeStylePtr StrokeStyle::Create(CapStyle cap, LineJoinStyle line_join, const float* dash_array, size_t dash_size,
|
||||
float dash_offset)
|
||||
StrokeStylePtr StrokeStyle::Create(float width, CapStyle cap, LineJoinStyle line_join, const float* dash_array,
|
||||
size_t dash_size, float dash_offset)
|
||||
{
|
||||
StrokeStylePtr ptr = new (std::nothrow) StrokeStyle;
|
||||
if (ptr)
|
||||
{
|
||||
ptr->SetStrokeWidth(width);
|
||||
ptr->SetCapStyle(cap);
|
||||
ptr->SetLineJoinStyle(line_join);
|
||||
ptr->SetDashStyle(dash_array, dash_size);
|
||||
|
|
@ -55,6 +63,7 @@ StrokeStyle::StrokeStyle()
|
|||
: cap_(CapStyle::Flat)
|
||||
, line_join_(LineJoinStyle::Miter)
|
||||
, dash_offset_(0.0f)
|
||||
, stroke_width_(1.0f)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +109,6 @@ void StrokeStyle::SetDashStyle(DashStyle dash_style)
|
|||
void StrokeStyle::SetDashStyle(const Vector<float>& dash_array)
|
||||
{
|
||||
dash_array_ = dash_array;
|
||||
style_.Reset();
|
||||
}
|
||||
|
||||
void StrokeStyle::SetDashStyle(const float* dash_array, size_t dash_size)
|
||||
|
|
@ -109,20 +117,6 @@ void StrokeStyle::SetDashStyle(const float* dash_array, size_t dash_size)
|
|||
dash_array_.clear();
|
||||
else
|
||||
dash_array_.assign(dash_array, dash_array + dash_size);
|
||||
style_.Reset();
|
||||
}
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
ComPtr<ID2D1StrokeStyle> StrokeStyle::GetStrokeStyle() const
|
||||
{
|
||||
StrokeStyle& self = const_cast<StrokeStyle&>(*this);
|
||||
if (dash_array_.empty())
|
||||
Renderer::GetInstance().CreateStrokeStyle(self, cap_, line_join_, nullptr, 0, dash_offset_);
|
||||
else
|
||||
Renderer::GetInstance().CreateStrokeStyle(self, cap_, line_join_, &dash_array_[0], dash_array_.size(),
|
||||
dash_offset_);
|
||||
return style_;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -19,8 +19,7 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <kiwano/core/ObjectBase.h>
|
||||
#include <kiwano/render/DirectX/D2DDeviceResources.h>
|
||||
#include <kiwano/render/NativeObject.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -67,47 +66,59 @@ enum class DashStyle
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 线条样式
|
||||
class StrokeStyle : public virtual ObjectBase
|
||||
class StrokeStyle : public NativeObject
|
||||
{
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief 创建线条样式
|
||||
/// @param width 线条宽度
|
||||
/// @param cap 线条端点样式
|
||||
/// @param line_join 线条交点样式
|
||||
static StrokeStylePtr Create(float width, CapStyle cap = CapStyle::Flat,
|
||||
LineJoinStyle line_join = LineJoinStyle::Miter);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建线条样式
|
||||
/// @param width 线条宽度
|
||||
/// @param cap 线条端点样式
|
||||
/// @param line_join 线条交点样式
|
||||
/// @param dash 线条虚线样式
|
||||
/// @param dash_offset 线条虚线偏移量
|
||||
static StrokeStylePtr Create(CapStyle cap, LineJoinStyle line_join = LineJoinStyle::Miter,
|
||||
DashStyle dash = DashStyle::Solid, float dash_offset = 0.0f);
|
||||
static StrokeStylePtr Create(float width, CapStyle cap, LineJoinStyle line_join, DashStyle dash,
|
||||
float dash_offset = 0.0f);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建线条样式
|
||||
/// @param width 线条宽度
|
||||
/// @param cap 线条端点样式
|
||||
/// @param line_join 线条交点样式
|
||||
/// @param dash_array 线条虚线的长度与间隙数组
|
||||
/// @param dash_size 线条虚线数组大小
|
||||
/// @param dash_offset 线条虚线偏移量
|
||||
static StrokeStylePtr Create(CapStyle cap, LineJoinStyle line_join = LineJoinStyle::Miter,
|
||||
const float* dash_array = nullptr, size_t dash_size = 0, float dash_offset = 0.0f);
|
||||
static StrokeStylePtr Create(float width, CapStyle cap, LineJoinStyle line_join, const float* dash_array,
|
||||
size_t dash_size, float dash_offset = 0.0f);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 创建线条样式
|
||||
/// @tparam _DashSize 线条虚线数组大小
|
||||
/// @param width 线条宽度
|
||||
/// @param cap 线条端点样式
|
||||
/// @param line_join 线条交点样式
|
||||
/// @param dash_array 线条虚线的长度与间隙数组
|
||||
/// @param dash_offset 线条虚线偏移量
|
||||
template <size_t _DashSize>
|
||||
static inline StrokeStylePtr Create(CapStyle cap, LineJoinStyle line_join = LineJoinStyle::Miter,
|
||||
float (&dash_array)[_DashSize] = nullptr, float dash_offset = 0.0f)
|
||||
static inline StrokeStylePtr Create(float width, CapStyle cap, LineJoinStyle line_join,
|
||||
float (&dash_array)[_DashSize], float dash_offset = 0.0f)
|
||||
{
|
||||
return StrokeStyle::Create(cap, line_join, dash_array, _DashSize, dash_offset);
|
||||
return StrokeStyle::Create(width, cap, line_join, dash_array, _DashSize, dash_offset);
|
||||
}
|
||||
|
||||
StrokeStyle();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
bool IsValid() const;
|
||||
/// @brief 获取线条宽度
|
||||
/// @param width 线条宽度
|
||||
float GetStrokeWidth() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取线条端点样式
|
||||
|
|
@ -125,6 +136,11 @@ public:
|
|||
/// @brief 获取虚线偏移量
|
||||
float GetDashOffset() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置线条宽度
|
||||
/// @param width 线条宽度
|
||||
void SetStrokeWidth(float width);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置线条端点样式
|
||||
void SetCapStyle(CapStyle cap);
|
||||
|
|
@ -167,22 +183,18 @@ public:
|
|||
private:
|
||||
CapStyle cap_;
|
||||
LineJoinStyle line_join_;
|
||||
float stroke_width_;
|
||||
float dash_offset_;
|
||||
Vector<float> dash_array_;
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
public:
|
||||
ComPtr<ID2D1StrokeStyle> GetStrokeStyle() const;
|
||||
|
||||
void SetStrokeStyle(ComPtr<ID2D1StrokeStyle> style);
|
||||
|
||||
private:
|
||||
ComPtr<ID2D1StrokeStyle> style_;
|
||||
#endif
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
inline float StrokeStyle::GetStrokeWidth() const
|
||||
{
|
||||
return stroke_width_;
|
||||
}
|
||||
|
||||
inline CapStyle StrokeStyle::GetCapStyle() const
|
||||
{
|
||||
return cap_;
|
||||
|
|
@ -203,38 +215,24 @@ inline float StrokeStyle::GetDashOffset() const
|
|||
return dash_offset_;
|
||||
}
|
||||
|
||||
inline void StrokeStyle::SetStrokeWidth(float width)
|
||||
{
|
||||
stroke_width_ = width;
|
||||
}
|
||||
|
||||
inline void StrokeStyle::SetCapStyle(CapStyle cap)
|
||||
{
|
||||
cap_ = cap;
|
||||
style_.Reset();
|
||||
}
|
||||
|
||||
inline void StrokeStyle::SetLineJoinStyle(LineJoinStyle line_join)
|
||||
{
|
||||
line_join_ = line_join;
|
||||
style_.Reset();
|
||||
}
|
||||
|
||||
inline void StrokeStyle::SetDashOffset(float dash_offset)
|
||||
{
|
||||
dash_offset_ = dash_offset;
|
||||
style_.Reset();
|
||||
}
|
||||
|
||||
inline bool StrokeStyle::IsValid() const
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
return style_ != nullptr;
|
||||
#else
|
||||
return false; // not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
inline void StrokeStyle::SetStrokeStyle(ComPtr<ID2D1StrokeStyle> style)
|
||||
{
|
||||
style_ = style;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@
|
|||
#include <kiwano/render/Renderer.h>
|
||||
#include <kiwano/render/TextLayout.h>
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
#include <kiwano/render/DirectX/NativePtr.h>
|
||||
#endif
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
TextLayoutPtr TextLayout::Create()
|
||||
|
|
@ -41,7 +45,6 @@ TextLayoutPtr TextLayout::Create(const String& content, const TextStyle& style)
|
|||
|
||||
TextLayout::TextLayout()
|
||||
: dirty_flag_(DirtyFlag::Clean)
|
||||
, default_outline_width_(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -54,12 +57,16 @@ void TextLayout::Reset(const String& text, const TextStyle& style)
|
|||
SetAlignment(style.alignment);
|
||||
SetWrapWidth(style.wrap_width);
|
||||
SetLineSpacing(style.line_spacing);
|
||||
SetUnderline(style.show_underline, { 0, text.length() });
|
||||
SetStrikethrough(style.show_strikethrough, { 0, text.length() });
|
||||
|
||||
SetDefaultFillBrush(style.fill_brush);
|
||||
SetDefaultOutlineBrush(style.outline_brush);
|
||||
SetDefaultOutlineWidth(style.outline_width);
|
||||
SetDefaultOutlineStrokeStyle(style.outline_stroke);
|
||||
|
||||
if (style.show_underline)
|
||||
SetUnderline(style.show_underline, { 0, text.length() });
|
||||
|
||||
if (style.show_strikethrough)
|
||||
SetStrikethrough(style.show_strikethrough, { 0, text.length() });
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -70,10 +77,13 @@ void TextLayout::Reset(const String& text, const TextStyle& style)
|
|||
uint32_t TextLayout::GetLineCount() const
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
if (text_layout_)
|
||||
auto native = NativePtr::Get<IDWriteTextLayout>(this);
|
||||
KGE_ASSERT(native);
|
||||
|
||||
if (native)
|
||||
{
|
||||
DWRITE_TEXT_METRICS metrics;
|
||||
if (SUCCEEDED(GetTextLayout()->GetMetrics(&metrics)))
|
||||
if (SUCCEEDED(native->GetMetrics(&metrics)))
|
||||
{
|
||||
return metrics.lineCount;
|
||||
}
|
||||
|
|
@ -87,10 +97,13 @@ uint32_t TextLayout::GetLineCount() const
|
|||
Size TextLayout::GetLayoutSize() const
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
if (text_layout_)
|
||||
auto native = NativePtr::Get<IDWriteTextLayout>(this);
|
||||
KGE_ASSERT(native);
|
||||
|
||||
if (native)
|
||||
{
|
||||
DWRITE_TEXT_METRICS metrics;
|
||||
if (SUCCEEDED(GetTextLayout()->GetMetrics(&metrics)))
|
||||
if (SUCCEEDED(native->GetMetrics(&metrics)))
|
||||
{
|
||||
return (metrics.layoutWidth > 0) ? Size(metrics.layoutWidth, metrics.height)
|
||||
: Size(metrics.width, metrics.height);
|
||||
|
|
@ -105,12 +118,14 @@ Size TextLayout::GetLayoutSize() const
|
|||
void TextLayout::SetFont(FontPtr font, TextRange range)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
KGE_ASSERT(text_layout_);
|
||||
if (text_layout_)
|
||||
{
|
||||
IDWriteFontCollection* collection = font ? font->GetCollection().Get() : nullptr;
|
||||
auto native = NativePtr::Get<IDWriteTextLayout>(this);
|
||||
KGE_ASSERT(native);
|
||||
|
||||
HRESULT hr = text_layout_->SetFontCollection(collection, { range.start, range.length });
|
||||
if (native)
|
||||
{
|
||||
ComPtr<IDWriteFontCollection> collection = NativePtr::Get<IDWriteFontCollection>(font);
|
||||
|
||||
HRESULT hr = native->SetFontCollection(collection.Get(), { range.start, range.length });
|
||||
KGE_THROW_IF_FAILED(hr, "IDWriteTextLayout::SetFontCollection failed");
|
||||
|
||||
dirty_flag_ = DirtyFlag::Updated;
|
||||
|
|
@ -123,12 +138,14 @@ void TextLayout::SetFont(FontPtr font, TextRange range)
|
|||
void TextLayout::SetFontFamily(String const& family, TextRange range)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
KGE_ASSERT(text_layout_);
|
||||
if (text_layout_)
|
||||
auto native = NativePtr::Get<IDWriteTextLayout>(this);
|
||||
KGE_ASSERT(native);
|
||||
|
||||
if (native)
|
||||
{
|
||||
WideString font_family = family.empty() ? L"" : string::ToWide(family);
|
||||
|
||||
HRESULT hr = text_layout_->SetFontFamilyName(font_family.c_str(), { range.start, range.length });
|
||||
HRESULT hr = native->SetFontFamilyName(font_family.c_str(), { range.start, range.length });
|
||||
KGE_THROW_IF_FAILED(hr, "IDWriteTextLayout::SetFontFamilyName failed");
|
||||
|
||||
dirty_flag_ = DirtyFlag::Updated;
|
||||
|
|
@ -141,10 +158,12 @@ void TextLayout::SetFontFamily(String const& family, TextRange range)
|
|||
void TextLayout::SetFontSize(float size, TextRange range)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
KGE_ASSERT(text_layout_);
|
||||
if (text_layout_)
|
||||
auto native = NativePtr::Get<IDWriteTextLayout>(this);
|
||||
KGE_ASSERT(native);
|
||||
|
||||
if (native)
|
||||
{
|
||||
HRESULT hr = text_layout_->SetFontSize(size, { range.start, range.length });
|
||||
HRESULT hr = native->SetFontSize(size, { range.start, range.length });
|
||||
KGE_THROW_IF_FAILED(hr, "IDWriteTextLayout::SetFontSize failed");
|
||||
|
||||
dirty_flag_ = DirtyFlag::Updated;
|
||||
|
|
@ -157,12 +176,14 @@ void TextLayout::SetFontSize(float size, TextRange range)
|
|||
void TextLayout::SetFontWeight(uint32_t weight, TextRange range)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
KGE_ASSERT(text_layout_);
|
||||
if (text_layout_)
|
||||
auto native = NativePtr::Get<IDWriteTextLayout>(this);
|
||||
KGE_ASSERT(native);
|
||||
|
||||
if (native)
|
||||
{
|
||||
DWRITE_FONT_WEIGHT font_weight = DWRITE_FONT_WEIGHT(weight);
|
||||
|
||||
HRESULT hr = text_layout_->SetFontWeight(font_weight, { range.start, range.length });
|
||||
HRESULT hr = native->SetFontWeight(font_weight, { range.start, range.length });
|
||||
KGE_THROW_IF_FAILED(hr, "IDWriteTextLayout::SetFontWeight failed");
|
||||
|
||||
dirty_flag_ = DirtyFlag::Updated;
|
||||
|
|
@ -175,12 +196,14 @@ void TextLayout::SetFontWeight(uint32_t weight, TextRange range)
|
|||
void TextLayout::SetItalic(bool italic, TextRange range)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
KGE_ASSERT(text_layout_);
|
||||
if (text_layout_)
|
||||
auto native = NativePtr::Get<IDWriteTextLayout>(this);
|
||||
KGE_ASSERT(native);
|
||||
|
||||
if (native)
|
||||
{
|
||||
DWRITE_FONT_STYLE font_style = italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
|
||||
|
||||
HRESULT hr = text_layout_->SetFontStyle(font_style, { range.start, range.length });
|
||||
HRESULT hr = native->SetFontStyle(font_style, { range.start, range.length });
|
||||
KGE_THROW_IF_FAILED(hr, "IDWriteTextLayout::SetFontStyle failed");
|
||||
|
||||
dirty_flag_ = DirtyFlag::Updated;
|
||||
|
|
@ -193,10 +216,12 @@ void TextLayout::SetItalic(bool italic, TextRange range)
|
|||
void TextLayout::SetUnderline(bool enable, TextRange range)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
KGE_ASSERT(text_layout_);
|
||||
if (text_layout_)
|
||||
auto native = NativePtr::Get<IDWriteTextLayout>(this);
|
||||
KGE_ASSERT(native);
|
||||
|
||||
if (native)
|
||||
{
|
||||
HRESULT hr = text_layout_->SetUnderline(enable, { range.start, range.length });
|
||||
HRESULT hr = native->SetUnderline(enable, { range.start, range.length });
|
||||
KGE_THROW_IF_FAILED(hr, "IDWriteTextLayout::SetUnderline failed");
|
||||
|
||||
dirty_flag_ = DirtyFlag::Updated;
|
||||
|
|
@ -209,10 +234,12 @@ void TextLayout::SetUnderline(bool enable, TextRange range)
|
|||
void TextLayout::SetStrikethrough(bool enable, TextRange range)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
KGE_ASSERT(text_layout_);
|
||||
if (text_layout_)
|
||||
auto native = NativePtr::Get<IDWriteTextLayout>(this);
|
||||
KGE_ASSERT(native);
|
||||
|
||||
if (native)
|
||||
{
|
||||
HRESULT hr = text_layout_->SetStrikethrough(enable, { range.start, range.length });
|
||||
HRESULT hr = native->SetStrikethrough(enable, { range.start, range.length });
|
||||
KGE_THROW_IF_FAILED(hr, "IDWriteTextLayout::SetStrikethrough failed");
|
||||
|
||||
dirty_flag_ = DirtyFlag::Updated;
|
||||
|
|
@ -225,10 +252,13 @@ void TextLayout::SetStrikethrough(bool enable, TextRange range)
|
|||
void TextLayout::SetFillBrush(BrushPtr brush, TextRange range)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
KGE_ASSERT(text_layout_);
|
||||
if (text_layout_)
|
||||
auto native = NativePtr::Get<IDWriteTextLayout>(this);
|
||||
KGE_ASSERT(native);
|
||||
|
||||
if (native)
|
||||
{
|
||||
HRESULT hr = text_layout_->SetDrawingEffect(brush->GetBrush().Get(), { range.start, range.length });
|
||||
HRESULT hr =
|
||||
native->SetDrawingEffect(NativePtr::Get<ID2D1Brush>(brush).Get(), { range.start, range.length });
|
||||
KGE_THROW_IF_FAILED(hr, "IDWriteTextLayout::SetDrawingEffect failed");
|
||||
|
||||
dirty_flag_ = DirtyFlag::Updated;
|
||||
|
|
@ -249,17 +279,6 @@ void TextLayout::SetOutlineBrush(BrushPtr brush, TextRange range)
|
|||
#endif
|
||||
}
|
||||
|
||||
void TextLayout::SetOutlineWidth(float width, TextRange range)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
// TODO
|
||||
KGE_NOT_USED(range);
|
||||
SetDefaultOutlineWidth(width);
|
||||
#else
|
||||
return; // not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
void TextLayout::SetOutlineStrokeStyle(StrokeStylePtr stroke, TextRange range)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
|
|
@ -274,8 +293,10 @@ void TextLayout::SetOutlineStrokeStyle(StrokeStylePtr stroke, TextRange range)
|
|||
void TextLayout::SetAlignment(TextAlign align)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
KGE_ASSERT(text_layout_);
|
||||
if (text_layout_)
|
||||
auto native = NativePtr::Get<IDWriteTextLayout>(this);
|
||||
KGE_ASSERT(native);
|
||||
|
||||
if (native)
|
||||
{
|
||||
DWRITE_TEXT_ALIGNMENT alignment = DWRITE_TEXT_ALIGNMENT();
|
||||
switch (align)
|
||||
|
|
@ -294,7 +315,7 @@ void TextLayout::SetAlignment(TextAlign align)
|
|||
break;
|
||||
}
|
||||
|
||||
HRESULT hr = text_layout_->SetTextAlignment(alignment);
|
||||
HRESULT hr = native->SetTextAlignment(alignment);
|
||||
KGE_THROW_IF_FAILED(hr, "IDWriteTextLayout::SetTextAlignment failed");
|
||||
|
||||
dirty_flag_ = DirtyFlag::Updated;
|
||||
|
|
@ -307,27 +328,29 @@ void TextLayout::SetAlignment(TextAlign align)
|
|||
void TextLayout::SetWrapWidth(float wrap_width)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
KGE_ASSERT(text_layout_);
|
||||
if (text_layout_)
|
||||
auto native = NativePtr::Get<IDWriteTextLayout>(this);
|
||||
KGE_ASSERT(native);
|
||||
|
||||
if (native)
|
||||
{
|
||||
DWRITE_WORD_WRAPPING wrapping = (wrap_width > 0) ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP;
|
||||
|
||||
HRESULT hr = text_layout_->SetWordWrapping(wrapping);
|
||||
HRESULT hr = native->SetWordWrapping(wrapping);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (wrap_width > 0)
|
||||
{
|
||||
hr = text_layout_->SetMaxWidth(wrap_width);
|
||||
hr = native->SetMaxWidth(wrap_width);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fix the layout width when the text does not wrap
|
||||
DWRITE_TEXT_METRICS metrics;
|
||||
hr = text_layout_->GetMetrics(&metrics);
|
||||
hr = native->GetMetrics(&metrics);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = text_layout_->SetMaxWidth(metrics.width);
|
||||
hr = native->SetMaxWidth(metrics.width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -343,19 +366,21 @@ void TextLayout::SetWrapWidth(float wrap_width)
|
|||
void TextLayout::SetLineSpacing(float line_spacing)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
KGE_ASSERT(text_layout_);
|
||||
if (text_layout_)
|
||||
auto native = NativePtr::Get<IDWriteTextLayout>(this);
|
||||
KGE_ASSERT(native);
|
||||
|
||||
if (native)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
float spacing = line_spacing;
|
||||
if (spacing == 0.f)
|
||||
{
|
||||
hr = text_layout_->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0);
|
||||
hr = native->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = text_layout_->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_UNIFORM, spacing, spacing * 0.8f);
|
||||
hr = native->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_UNIFORM, spacing, spacing * 0.8f);
|
||||
}
|
||||
KGE_THROW_IF_FAILED(hr, "IDWriteTextLayout::SetLineSpacing failed");
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#pragma once
|
||||
#include <kiwano/math/Math.h>
|
||||
#include <kiwano/core/ObjectBase.h>
|
||||
#include <kiwano/render/NativeObject.h>
|
||||
#include <kiwano/render/TextStyle.hpp>
|
||||
|
||||
namespace kiwano
|
||||
|
|
@ -35,7 +35,7 @@ KGE_DECLARE_SMART_PTR(TextLayout);
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 文本布局
|
||||
class KGE_API TextLayout : public virtual ObjectBase
|
||||
class KGE_API TextLayout : public NativeObject
|
||||
{
|
||||
public:
|
||||
/// \~chinese
|
||||
|
|
@ -52,10 +52,6 @@ public:
|
|||
/// @brief 构造空的文本布局
|
||||
TextLayout();
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 文本布局是否有效
|
||||
bool IsValid() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 文本布局是否陈旧
|
||||
bool IsDirty() const;
|
||||
|
|
@ -86,10 +82,6 @@ public:
|
|||
/// @brief 获取默认描边画刷
|
||||
BrushPtr GetDefaultOutlineBrush() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取默认描边宽度
|
||||
float GetDefaultOutlineWidth() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取默认描边线条样式
|
||||
StrokeStylePtr GetDefaultOutlineStrokeStyle() const;
|
||||
|
|
@ -156,12 +148,6 @@ public:
|
|||
/// @param range 文字范围
|
||||
void SetOutlineBrush(BrushPtr brush, TextRange range);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置文字描边线宽
|
||||
/// @param width 描边线宽
|
||||
/// @param range 文字范围
|
||||
void SetOutlineWidth(float width, TextRange range);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置描边线条样式
|
||||
/// @param stroke 线条样式
|
||||
|
|
@ -191,11 +177,6 @@ public:
|
|||
/// @param brush 画刷
|
||||
void SetDefaultOutlineBrush(BrushPtr brush);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置默认文字描边线宽
|
||||
/// @param width 描边线宽
|
||||
void SetDefaultOutlineWidth(float width);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置默认描边线条样式
|
||||
/// @param stroke 线条样式
|
||||
|
|
@ -218,31 +199,11 @@ private:
|
|||
DirtyFlag dirty_flag_;
|
||||
BrushPtr default_fill_brush_;
|
||||
BrushPtr default_outline_brush_;
|
||||
float default_outline_width_;
|
||||
StrokeStylePtr default_outline_stroke_;
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
public:
|
||||
ComPtr<IDWriteTextLayout> GetTextLayout() const;
|
||||
|
||||
void SetTextLayout(ComPtr<IDWriteTextLayout> layout);
|
||||
|
||||
private:
|
||||
ComPtr<IDWriteTextLayout> text_layout_;
|
||||
#endif
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
inline bool TextLayout::IsValid() const
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
return text_layout_ != nullptr;
|
||||
#else
|
||||
return false; // not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool TextLayout::IsDirty() const
|
||||
{
|
||||
return dirty_flag_ != DirtyFlag::Clean;
|
||||
|
|
@ -250,12 +211,7 @@ inline bool TextLayout::IsDirty() const
|
|||
|
||||
inline void TextLayout::Clear()
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
text_layout_ = nullptr;
|
||||
dirty_flag_ = DirtyFlag::Updated;
|
||||
#else
|
||||
return; // not supported
|
||||
#endif
|
||||
ResetNativePointer();
|
||||
}
|
||||
|
||||
inline TextLayout::DirtyFlag TextLayout::GetDirtyFlag() const
|
||||
|
|
@ -278,11 +234,6 @@ inline BrushPtr TextLayout::GetDefaultOutlineBrush() const
|
|||
return default_outline_brush_;
|
||||
}
|
||||
|
||||
inline float TextLayout::GetDefaultOutlineWidth() const
|
||||
{
|
||||
return default_outline_width_;
|
||||
}
|
||||
|
||||
inline StrokeStylePtr TextLayout::GetDefaultOutlineStrokeStyle() const
|
||||
{
|
||||
return default_outline_stroke_;
|
||||
|
|
@ -298,26 +249,9 @@ inline void TextLayout::SetDefaultOutlineBrush(BrushPtr brush)
|
|||
default_outline_brush_ = brush;
|
||||
}
|
||||
|
||||
inline void TextLayout::SetDefaultOutlineWidth(float width)
|
||||
{
|
||||
default_outline_width_ = width;
|
||||
}
|
||||
|
||||
inline void TextLayout::SetDefaultOutlineStrokeStyle(StrokeStylePtr stroke)
|
||||
{
|
||||
default_outline_stroke_ = stroke;
|
||||
}
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
inline ComPtr<IDWriteTextLayout> TextLayout::GetTextLayout() const
|
||||
{
|
||||
return text_layout_;
|
||||
}
|
||||
|
||||
inline void TextLayout::SetTextLayout(ComPtr<IDWriteTextLayout> layout)
|
||||
{
|
||||
text_layout_ = layout;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -78,8 +78,7 @@ public:
|
|||
TextAlign alignment; ///< 对齐方式
|
||||
BrushPtr fill_brush; ///< 填充画刷
|
||||
BrushPtr outline_brush; ///< 描边画刷
|
||||
float outline_width; ///< 描边线宽
|
||||
StrokeStylePtr outline_stroke; ///< 描边线宽
|
||||
StrokeStylePtr outline_stroke; ///< 描边样式
|
||||
float wrap_width; ///< 自动换行宽度
|
||||
float line_spacing; ///< 行间距
|
||||
bool show_underline; ///< 显示下划线
|
||||
|
|
@ -116,7 +115,6 @@ inline TextStyle::TextStyle(const String& font_family, float font_size, uint32_t
|
|||
, font_weight(font_weight)
|
||||
, italic(false)
|
||||
, alignment(TextAlign::Left)
|
||||
, outline_width(1.0f)
|
||||
, wrap_width(0)
|
||||
, line_spacing(0)
|
||||
, show_underline(false)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@
|
|||
#include <kiwano/render/Renderer.h>
|
||||
#include <kiwano/render/Texture.h>
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
#include <kiwano/render/DirectX/NativePtr.h>
|
||||
#endif
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
|
|
@ -67,47 +71,15 @@ bool Texture::Load(Resource const& res)
|
|||
return IsValid();
|
||||
}
|
||||
|
||||
float Texture::GetWidth() const
|
||||
{
|
||||
return size_.x;
|
||||
}
|
||||
|
||||
float Texture::GetHeight() const
|
||||
{
|
||||
return size_.y;
|
||||
}
|
||||
|
||||
Size Texture::GetSize() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
uint32_t Texture::GetWidthInPixels() const
|
||||
{
|
||||
return size_in_pixels_.x;
|
||||
}
|
||||
|
||||
uint32_t Texture::GetHeightInPixels() const
|
||||
{
|
||||
return size_in_pixels_.y;
|
||||
}
|
||||
|
||||
math::Vec2T<uint32_t> Texture::GetSizeInPixels() const
|
||||
{
|
||||
return size_in_pixels_;
|
||||
}
|
||||
|
||||
InterpolationMode Texture::GetBitmapInterpolationMode() const
|
||||
{
|
||||
return interpolation_mode_;
|
||||
}
|
||||
|
||||
void Texture::CopyFrom(TexturePtr copy_from)
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
if (IsValid() && copy_from)
|
||||
{
|
||||
HRESULT hr = bitmap_->CopyFromBitmap(nullptr, copy_from->GetBitmap().Get(), nullptr);
|
||||
auto native = NativePtr::Get<ID2D1Bitmap>(this);
|
||||
auto native_to_copy = NativePtr::Get<ID2D1Bitmap>(copy_from);
|
||||
|
||||
HRESULT hr = native->CopyFromBitmap(nullptr, native_to_copy.Get(), nullptr);
|
||||
|
||||
KGE_THROW_IF_FAILED(hr, "Copy texture data failed");
|
||||
}
|
||||
|
|
@ -121,10 +93,13 @@ void Texture::CopyFrom(TexturePtr copy_from, Rect const& src_rect, Point const&
|
|||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
if (IsValid() && copy_from)
|
||||
{
|
||||
HRESULT hr = bitmap_->CopyFromBitmap(
|
||||
&D2D1::Point2U(uint32_t(dest_point.x), uint32_t(dest_point.y)), copy_from->GetBitmap().Get(),
|
||||
&D2D1::RectU(uint32_t(src_rect.GetLeft()), uint32_t(src_rect.GetTop()), uint32_t(src_rect.GetRight()),
|
||||
uint32_t(src_rect.GetBottom())));
|
||||
auto native = NativePtr::Get<ID2D1Bitmap>(this);
|
||||
auto native_to_copy = NativePtr::Get<ID2D1Bitmap>(copy_from);
|
||||
|
||||
HRESULT hr =
|
||||
native->CopyFromBitmap(&D2D1::Point2U(uint32_t(dest_point.x), uint32_t(dest_point.y)), native_to_copy.Get(),
|
||||
&D2D1::RectU(uint32_t(src_rect.GetLeft()), uint32_t(src_rect.GetTop()),
|
||||
uint32_t(src_rect.GetRight()), uint32_t(src_rect.GetBottom())));
|
||||
|
||||
KGE_THROW_IF_FAILED(hr, "Copy texture data failed");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,8 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <kiwano/core/ObjectBase.h>
|
||||
#include <kiwano/core/Resource.h>
|
||||
#include <kiwano/render/DirectX/D2DDeviceResources.h>
|
||||
#include <kiwano/render/NativeObject.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -44,11 +43,15 @@ enum class InterpolationMode
|
|||
Nearest ///< 最邻近插值,取最邻近的像素点的颜色值
|
||||
};
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 像素大小
|
||||
typedef math::Vec2T<uint32_t> PixelSize;
|
||||
|
||||
/**
|
||||
* \~chinese
|
||||
* @brief 纹理
|
||||
*/
|
||||
class KGE_API Texture : public virtual ObjectBase
|
||||
class KGE_API Texture : public NativeObject
|
||||
{
|
||||
public:
|
||||
/// \~chinese
|
||||
|
|
@ -71,10 +74,6 @@ public:
|
|||
/// @brief 加载资源
|
||||
bool Load(Resource const& res);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 是否有效
|
||||
bool IsValid() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取纹理宽度
|
||||
float GetWidth() const;
|
||||
|
|
@ -97,11 +96,22 @@ public:
|
|||
|
||||
/// \~chinese
|
||||
/// @brief 获取像素大小
|
||||
math::Vec2T<uint32_t> GetSizeInPixels() const;
|
||||
PixelSize GetSizeInPixels() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 获取像素插值方式
|
||||
InterpolationMode GetBitmapInterpolationMode() const;
|
||||
/// \~chinese
|
||||
/// @brief 设置大小
|
||||
void SetSize(const Size& size);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置像素大小
|
||||
void SetSizeInPixels(const PixelSize& size);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置像素插值方式
|
||||
void SetInterpolationMode(InterpolationMode mode);
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 拷贝纹理
|
||||
|
|
@ -115,10 +125,6 @@ public:
|
|||
/// @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);
|
||||
|
|
@ -128,62 +134,58 @@ public:
|
|||
static InterpolationMode GetDefaultInterpolationMode();
|
||||
|
||||
private:
|
||||
InterpolationMode interpolation_mode_;
|
||||
Size size_;
|
||||
PixelSize size_in_pixels_;
|
||||
InterpolationMode interpolation_mode_;
|
||||
|
||||
static InterpolationMode default_interpolation_mode_;
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
public:
|
||||
/// \~chinese
|
||||
/// @brief 获取源位图
|
||||
ComPtr<ID2D1Bitmap> GetBitmap() const;
|
||||
|
||||
/// \~chinese
|
||||
/// @brief 设置源位图
|
||||
void SetBitmap(ComPtr<ID2D1Bitmap> bitmap);
|
||||
|
||||
private:
|
||||
ComPtr<ID2D1Bitmap> bitmap_;
|
||||
Size size_;
|
||||
math::Vec2T<uint32_t> size_in_pixels_;
|
||||
#endif
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
inline bool Texture::IsValid() const
|
||||
inline float Texture::GetWidth() const
|
||||
{
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
return bitmap_ != nullptr;
|
||||
#else
|
||||
return false; // not supported
|
||||
#endif
|
||||
return size_.x;
|
||||
}
|
||||
|
||||
#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
|
||||
inline ComPtr<ID2D1Bitmap> Texture::GetBitmap() const
|
||||
inline float Texture::GetHeight() const
|
||||
{
|
||||
return bitmap_;
|
||||
return size_.y;
|
||||
}
|
||||
|
||||
inline void Texture::SetBitmap(ComPtr<ID2D1Bitmap> bitmap)
|
||||
inline Size Texture::GetSize() const
|
||||
{
|
||||
if (bitmap_ != bitmap)
|
||||
{
|
||||
bitmap_ = bitmap;
|
||||
|
||||
if (bitmap_)
|
||||
{
|
||||
auto size = bitmap_->GetSize();
|
||||
auto pixel_size = bitmap_->GetPixelSize();
|
||||
|
||||
size_.x = size.width;
|
||||
size_.y = size.height;
|
||||
size_in_pixels_.x = pixel_size.width;
|
||||
size_in_pixels_.y = pixel_size.height;
|
||||
}
|
||||
}
|
||||
return size_;
|
||||
}
|
||||
|
||||
inline uint32_t Texture::GetWidthInPixels() const
|
||||
{
|
||||
return size_in_pixels_.x;
|
||||
}
|
||||
|
||||
inline uint32_t Texture::GetHeightInPixels() const
|
||||
{
|
||||
return size_in_pixels_.y;
|
||||
}
|
||||
|
||||
inline PixelSize Texture::GetSizeInPixels() const
|
||||
{
|
||||
return size_in_pixels_;
|
||||
}
|
||||
|
||||
inline InterpolationMode Texture::GetBitmapInterpolationMode() const
|
||||
{
|
||||
return interpolation_mode_;
|
||||
}
|
||||
|
||||
inline void Texture::SetSize(const Size& size)
|
||||
{
|
||||
size_ = size;
|
||||
}
|
||||
|
||||
inline void Texture::SetSizeInPixels(const PixelSize& size)
|
||||
{
|
||||
size_in_pixels_ = size;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace kiwano
|
||||
|
|
|
|||
|
|
@ -401,7 +401,7 @@ bool LoadXmlData(ResourceCache* loader, const XmlNode& elem)
|
|||
int rows = 0, cols = 0, max_num = -1;
|
||||
|
||||
if (auto attr = image.attribute("id"))
|
||||
id.assign(attr.value());
|
||||
id = attr.value();
|
||||
if (auto attr = image.attribute("type"))
|
||||
type = attr.value();
|
||||
if (auto attr = image.attribute("file"))
|
||||
|
|
@ -452,7 +452,7 @@ bool LoadXmlData(ResourceCache* loader, const XmlNode& elem)
|
|||
{
|
||||
String id, file;
|
||||
if (auto attr = font.attribute("id"))
|
||||
id.assign(attr.value());
|
||||
id = attr.value();
|
||||
if (auto attr = font.attribute("file"))
|
||||
file = attr.value();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue