diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj
index c4abc73a..6364baf3 100644
--- a/projects/kiwano/kiwano.vcxproj
+++ b/projects/kiwano/kiwano.vcxproj
@@ -78,13 +78,15 @@
+
+
-
+
@@ -158,7 +160,7 @@
-
+
diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters
index 21b248a6..fa289faa 100644
--- a/projects/kiwano/kiwano.vcxproj.filters
+++ b/projects/kiwano/kiwano.vcxproj.filters
@@ -252,9 +252,6 @@
render
-
- render
-
math
@@ -318,6 +315,15 @@
core
+
+ render
+
+
+ render\DirectX
+
+
+ render
+
@@ -500,9 +506,6 @@
render
-
- render
-
render
@@ -533,5 +536,8 @@
core
+
+ render
+
\ No newline at end of file
diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp
index 458f0353..9a8b257e 100644
--- a/src/kiwano/2d/Actor.cpp
+++ b/src/kiwano/2d/Actor.cpp
@@ -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_)
diff --git a/src/kiwano/2d/Canvas.cpp b/src/kiwano/2d/Canvas.cpp
index c778f2e9..770419f1 100644
--- a/src/kiwano/2d/Canvas.cpp
+++ b/src/kiwano/2d/Canvas.cpp
@@ -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 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;
}
diff --git a/src/kiwano/2d/Canvas.h b/src/kiwano/2d/Canvas.h
index d5580bc9..b54970ff 100644
--- a/src/kiwano/2d/Canvas.h
+++ b/src/kiwano/2d/Canvas.h
@@ -20,7 +20,7 @@
#pragma once
#include
-#include
+#include
#include
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;
diff --git a/src/kiwano/2d/LayerActor.cpp b/src/kiwano/2d/LayerActor.cpp
index 022169c4..c663556a 100644
--- a/src/kiwano/2d/LayerActor.cpp
+++ b/src/kiwano/2d/LayerActor.cpp
@@ -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
diff --git a/src/kiwano/2d/LayerActor.h b/src/kiwano/2d/LayerActor.h
index 943aa119..42a21723 100644
--- a/src/kiwano/2d/LayerActor.h
+++ b/src/kiwano/2d/LayerActor.h
@@ -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_;
}
diff --git a/src/kiwano/2d/ShapeActor.cpp b/src/kiwano/2d/ShapeActor.cpp
index bbed66fe..f0f5dddc 100644
--- a/src/kiwano/2d/ShapeActor.cpp
+++ b/src/kiwano/2d/ShapeActor.cpp
@@ -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 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());
}
}
diff --git a/src/kiwano/2d/ShapeActor.h b/src/kiwano/2d/ShapeActor.h
index a5855d5d..0211d49a 100644
--- a/src/kiwano/2d/ShapeActor.h
+++ b/src/kiwano/2d/ShapeActor.h
@@ -22,7 +22,7 @@
#include
#include
#include
-#include
+#include
#include
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;
diff --git a/src/kiwano/2d/TextActor.cpp b/src/kiwano/2d/TextActor.cpp
index d3cce1d0..da05ffa2 100644
--- a/src/kiwano/2d/TextActor.cpp
+++ b/src/kiwano/2d/TextActor.cpp
@@ -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)
diff --git a/src/kiwano/2d/TextActor.h b/src/kiwano/2d/TextActor.h
index 7bc53841..581b2028 100644
--- a/src/kiwano/2d/TextActor.h
+++ b/src/kiwano/2d/TextActor.h
@@ -146,10 +146,6 @@ public:
/// @brief 设置描边线条样式
void SetOutlineStrokeStyle(StrokeStylePtr stroke);
- /// \~chinese
- /// @brief 设置文字描边线宽
- void SetOutlineWidth(float outline_width);
-
/// \~chinese
/// @brief 设置是否显示下划线(默认值为 false)
void SetUnderline(bool enable);
diff --git a/src/kiwano/2d/action/ActionWalk.h b/src/kiwano/2d/action/ActionWalk.h
index 0ca06049..3199df80 100644
--- a/src/kiwano/2d/action/ActionWalk.h
+++ b/src/kiwano/2d/action/ActionWalk.h
@@ -21,7 +21,7 @@
#pragma once
#include
#include
-#include
+#include
namespace kiwano
{
diff --git a/src/kiwano/core/SmartPtr.hpp b/src/kiwano/core/SmartPtr.hpp
index 9b6ea8a3..8a477d59 100644
--- a/src/kiwano/core/SmartPtr.hpp
+++ b/src/kiwano/core/SmartPtr.hpp
@@ -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(dynamic_cast(other.Get()));
- typename _ProxyTy::AddRef(ptr_);
+ typename _ProxyTy::Retain(ptr_);
}
inline pointer_type Get() noexcept
diff --git a/src/kiwano/kiwano.h b/src/kiwano/kiwano.h
index af047772..a43952c9 100644
--- a/src/kiwano/kiwano.h
+++ b/src/kiwano/kiwano.h
@@ -67,7 +67,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
diff --git a/src/kiwano/platform/win32/ComPtr.hpp b/src/kiwano/platform/win32/ComPtr.hpp
index 328e9103..ebd1b82a 100644
--- a/src/kiwano/platform/win32/ComPtr.hpp
+++ b/src/kiwano/platform/win32/ComPtr.hpp
@@ -28,7 +28,7 @@ namespace kiwano
{
struct ComPtrProxy
{
- static inline void AddRef(IUnknown* ptr)
+ static inline void Retain(IUnknown* ptr)
{
if (ptr)
ptr->AddRef();
diff --git a/src/kiwano/render/Brush.cpp b/src/kiwano/render/Brush.cpp
index 6c744814..cdd67fa5 100644
--- a/src/kiwano/render/Brush.cpp
+++ b/src/kiwano/render/Brush.cpp
@@ -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
diff --git a/src/kiwano/render/Brush.h b/src/kiwano/render/Brush.h
index 1ad2d0e4..2ed82dcb 100644
--- a/src/kiwano/render/Brush.h
+++ b/src/kiwano/render/Brush.h
@@ -19,8 +19,7 @@
// THE SOFTWARE.
#pragma once
-#include
-#include
+#include
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 brush, Type type);
-
- ComPtr GetBrush() const;
-
-private:
- ComPtr 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 brush, Type type)
-{
- type_ = type;
- raw_ = brush;
-}
-
-inline ComPtr Brush::GetBrush() const
-{
- return raw_;
-}
-#endif
-
} // namespace kiwano
diff --git a/src/kiwano/render/DirectX/NativePtr.h b/src/kiwano/render/DirectX/NativePtr.h
new file mode 100644
index 00000000..5d2fc309
--- /dev/null
+++ b/src/kiwano/render/DirectX/NativePtr.h
@@ -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
+#include
+#include
+
+namespace kiwano
+{
+
+class KGE_API NativePtr
+{
+public:
+ template ::value, int>::type>
+ static inline ComPtr<_Ty> Get(const NativeObject* object)
+ {
+ if (object)
+ {
+ ComPtr ptr = object->GetNativePointer>();
+ if (ptr)
+ {
+ ComPtr<_Ty> native;
+ if (SUCCEEDED(ptr->QueryInterface<_Ty>(&native)))
+ return native;
+ }
+ }
+ return nullptr;
+ }
+
+ template
+ static inline ComPtr<_Ty> Get(const NativeObject& object)
+ {
+ return NativePtr::Get<_Ty>(&object);
+ }
+
+ template
+ static inline ComPtr<_Ty> Get(NativeObjectPtr object)
+ {
+ return NativePtr::Get<_Ty>(object.Get());
+ }
+
+ static inline void Set(NativeObject* object, ComPtr com_ptr)
+ {
+ if (object)
+ {
+ object->SetNativePointer(com_ptr);
+ }
+ }
+
+ static inline void Set(NativeObject& object, ComPtr com_ptr)
+ {
+ NativePtr::Set(&object, com_ptr);
+ }
+
+ static inline void Set(NativeObjectPtr object, ComPtr com_ptr)
+ {
+ NativePtr::Set(object.Get(), com_ptr);
+ }
+};
+
+} // namespace kiwano
diff --git a/src/kiwano/render/DirectX/RenderContextImpl.cpp b/src/kiwano/render/DirectX/RenderContextImpl.cpp
index 389089ba..9a80c1a4 100644
--- a/src/kiwano/render/DirectX/RenderContextImpl.cpp
+++ b/src/kiwano/render/DirectX/RenderContextImpl.cpp
@@ -18,14 +18,14 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include
#include
+#include
+#include
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(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 fill_brush;
- ComPtr outline_brush;
- ComPtr outline_stroke;
+ auto native = NativePtr::Get(layout);
+ auto fill_brush = NativePtr::Get(layout.GetDefaultFillBrush());
+ auto outline_brush = NativePtr::Get(layout.GetDefaultOutlineBrush());
+ auto outline_stroke = NativePtr::Get(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(shape);
+ auto brush = NativePtr::Get(current_brush_);
+ auto stroke_style = NativePtr::Get(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(current_brush_);
+ auto stroke_style = NativePtr::Get(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(current_brush_);
+ auto stroke_style = NativePtr::Get(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(current_brush_);
+ auto stroke_style = NativePtr::Get(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(current_brush_);
+ auto stroke_style = NativePtr::Get(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(current_brush_);
+ auto geometry = NativePtr::Get(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(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(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(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 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 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 output;
- HRESULT hr = render_target_->CreateLayer(&output);
+ auto native = NativePtr::Get(layer);
+ auto mask = NativePtr::Get(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 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(current_brush_)->SetOpacity(brush_opacity_);
}
}
diff --git a/src/kiwano/render/DirectX/RenderContextImpl.h b/src/kiwano/render/DirectX/RenderContextImpl.h
index 974d4d1f..c58b4f60 100644
--- a/src/kiwano/render/DirectX/RenderContextImpl.h
+++ b/src/kiwano/render/DirectX/RenderContextImpl.h
@@ -20,6 +20,7 @@
#pragma once
#include
+#include
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;
diff --git a/src/kiwano/render/DirectX/RendererImpl.cpp b/src/kiwano/render/DirectX/RendererImpl.cpp
index deb2eef5..6c5eec3a 100644
--- a/src/kiwano/render/DirectX/RendererImpl.cpp
+++ b/src/kiwano/render/DirectX/RendererImpl.cpp
@@ -23,9 +23,10 @@
#include
#include
#include
-#include
+#include
#include
#include
+#include
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(gif);
+
+ if (!decoder)
{
hr = E_INVALIDARG;
}
@@ -373,7 +382,7 @@ void RendererImpl::CreateGifImageFrame(GifImage::Frame& frame, GifImage const& g
{
ComPtr 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 raw_bitmap;
- hr = d2d_res_->CreateBitmapFromConverter(raw_bitmap, nullptr, converter);
+ ComPtr 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 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(style.font);
+ ComPtr 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 output;
- WideString wide = string::ToWide(content);
+ WideString wide = string::ToWide(content);
+ ComPtr 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 path_geo;
- ComPtr path_sink;
if (SUCCEEDED(hr))
{
+ ComPtr path_geo;
hr = d2d_res_->GetFactory()->CreatePathGeometry(&path_geo);
- }
- if (SUCCEEDED(hr))
- {
- hr = path_geo->Open(&path_sink);
- }
+ if (SUCCEEDED(hr))
+ {
+ ComPtr 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 output;
if (SUCCEEDED(hr))
{
- hr = d2d_res_->GetFactory()->CreatePathGeometry(&output);
- }
+ ComPtr 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 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(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 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);
}
}
diff --git a/src/kiwano/render/DirectX/RendererImpl.h b/src/kiwano/render/DirectX/RendererImpl.h
index fc8432a1..30e2e01a 100644
--- a/src/kiwano/render/DirectX/RendererImpl.h
+++ b/src/kiwano/render/DirectX/RendererImpl.h
@@ -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;
diff --git a/src/kiwano/render/DirectX/TextureRenderContextImpl.cpp b/src/kiwano/render/DirectX/TextureRenderContextImpl.cpp
index de2c24e1..171a06ff 100644
--- a/src/kiwano/render/DirectX/TextureRenderContextImpl.cpp
+++ b/src/kiwano/render/DirectX/TextureRenderContextImpl.cpp
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
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);
diff --git a/src/kiwano/render/Font.h b/src/kiwano/render/Font.h
index d96ec02a..82e40fd5 100644
--- a/src/kiwano/render/Font.h
+++ b/src/kiwano/render/Font.h
@@ -19,10 +19,8 @@
// THE SOFTWARE.
#pragma once
-#include
+#include
#include
-#include
-#include
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 GetCollection() const;
-
- void SetCollection(ComPtr collection);
-
-private:
- ComPtr 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 Font::GetCollection() const
-{
- return collection_;
-}
-
-inline void Font::SetCollection(ComPtr collection)
-{
- collection_ = collection;
-}
-#endif
-
} // namespace kiwano
diff --git a/src/kiwano/render/GifImage.cpp b/src/kiwano/render/GifImage.cpp
index 82256587..478510d5 100644
--- a/src/kiwano/render/GifImage.cpp
+++ b/src/kiwano/render/GifImage.cpp
@@ -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
+
+namespace kiwano
+{
+
bool GifImage::GetGlobalMetadata()
{
- HRESULT hr = decoder_ ? S_OK : E_FAIL;
+ ComPtr decoder = NativePtr::Get(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 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(height / pixel_asp_ratio);
+ size_in_pixels_ = { width, static_cast(height / pixel_asp_ratio) };
}
else
{
- width_in_pixels_ = static_cast(width * pixel_asp_ratio);
- height_in_pixels_ = height;
+ size_in_pixels_ = { static_cast(width * pixel_asp_ratio), height };
}
}
else
{
// 值为 0, 所以像素比为 1
- width_in_pixels_ = width;
- height_in_pixels_ = height;
+ size_in_pixels_ = { width, height };
}
}
::PropVariantClear(&prop_val);
diff --git a/src/kiwano/render/GifImage.h b/src/kiwano/render/GifImage.h
index b62bd766..6bb769ce 100644
--- a/src/kiwano/render/GifImage.h
+++ b/src/kiwano/render/GifImage.h
@@ -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 GetDecoder() const;
-
- void SetDecoder(ComPtr decoder);
-
-private:
- ComPtr 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 GifImage::GetDecoder() const
-{
- return decoder_;
-}
-
-inline void GifImage::SetDecoder(ComPtr decoder)
-{
- decoder_ = decoder;
-}
-#endif
-
} // namespace kiwano
diff --git a/src/kiwano/render/Layer.h b/src/kiwano/render/Layer.h
index ec3ff63a..bb50e65c 100644
--- a/src/kiwano/render/Layer.h
+++ b/src/kiwano/render/Layer.h
@@ -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 GetLayer() const;
-
- void SetLayer(ComPtr layer);
-
-private:
- ComPtr 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 Layer::GetLayer() const
-{
- return layer_;
-}
-
-inline void Layer::SetLayer(ComPtr layer)
-{
- layer_ = layer;
-}
-#endif
-
} // namespace kiwano
diff --git a/src/kiwano/render/NativeObject.h b/src/kiwano/render/NativeObject.h
new file mode 100644
index 00000000..67e54fd5
--- /dev/null
+++ b/src/kiwano/render/NativeObject.h
@@ -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
+
+#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
+#include
+#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
+ _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
+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
diff --git a/src/kiwano/render/RenderContext.cpp b/src/kiwano/render/RenderContext.cpp
index 3cdc98f6..db083dad 100644
--- a/src/kiwano/render/RenderContext.cpp
+++ b/src/kiwano/render/RenderContext.cpp
@@ -19,6 +19,7 @@
// THE SOFTWARE.
#include
+#include
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
diff --git a/src/kiwano/render/RenderContext.h b/src/kiwano/render/RenderContext.h
index b7918744..47e58a76 100644
--- a/src/kiwano/render/RenderContext.h
+++ b/src/kiwano/render/RenderContext.h
@@ -26,7 +26,6 @@
#include
#include
#include
-#include
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_;
diff --git a/src/kiwano/render/Renderer.h b/src/kiwano/render/Renderer.h
index 38bfcc2b..c6f9c694 100644
--- a/src/kiwano/render/Renderer.h
+++ b/src/kiwano/render/Renderer.h
@@ -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 创建纹理渲染上下文
diff --git a/src/kiwano/render/Shape.cpp b/src/kiwano/render/Shape.cpp
index 66e2cd54..5a6b6456 100644
--- a/src/kiwano/render/Shape.cpp
+++ b/src/kiwano/render/Shape.cpp
@@ -19,22 +19,32 @@
// THE SOFTWARE.
#include
-#include
+#include
#include
+#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
+#include
+#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(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(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(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(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(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(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
diff --git a/src/kiwano/render/Shape.h b/src/kiwano/render/Shape.h
index 40a55a60..5ad97c19 100644
--- a/src/kiwano/render/Shape.h
+++ b/src/kiwano/render/Shape.h
@@ -19,12 +19,11 @@
// THE SOFTWARE.
#pragma once
-#include
-#include
+#include
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 GetGeometry() const;
-
- void SetGeometry(ComPtr shape);
-
-private:
- ComPtr 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 Shape::GetGeometry() const
-{
- return geo_;
-}
-
-inline void Shape::SetGeometry(ComPtr shape)
-{
- geo_ = shape;
-}
-#endif
-
} // namespace kiwano
diff --git a/src/kiwano/render/ShapeMaker.cpp b/src/kiwano/render/ShapeMaker.cpp
new file mode 100644
index 00000000..72cf97ee
--- /dev/null
+++ b/src/kiwano/render/ShapeMaker.cpp
@@ -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
+#include
+
+#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
+#include
+#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(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(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(this);
+ native->AddLine(DX::ConvertToPoint2F(point));
+#else
+ // not supported
+#endif
+}
+
+void ShapeMaker::AddLines(Vector const& points)
+{
+ KGE_ASSERT(IsStreamOpened());
+
+#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
+ auto native = NativePtr::Get(this);
+ native->AddLines(reinterpret_cast(&points[0]), static_cast(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(this);
+ native->AddLines(reinterpret_cast(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(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(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(shape_a);
+ auto geo_b = NativePtr::Get(shape_b);
+ auto native = NativePtr::Get(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(shape_);
+ if (geometry)
+ {
+ ComPtr 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(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
diff --git a/src/kiwano/render/ShapeSink.h b/src/kiwano/render/ShapeMaker.h
similarity index 57%
rename from src/kiwano/render/ShapeSink.h
rename to src/kiwano/render/ShapeMaker.h
index b40a5ae3..040c998a 100644
--- a/src/kiwano/render/ShapeSink.h
+++ b/src/kiwano/render/ShapeMaker.h
@@ -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 const& points);
+ void AddLines(Vector 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 GetPathGeometry() const;
-
- void SetPathGeometry(ComPtr path);
-
- ComPtr GetGeometrySink() const;
-
- void SetGeometrySink(ComPtr sink);
-
-private:
- ComPtr sink_;
- ComPtr path_geo_;
-#endif
};
/** @} */
-#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
-inline ComPtr ShapeSink::GetPathGeometry() const
-{
- return path_geo_;
-}
-
-inline void ShapeSink::SetPathGeometry(ComPtr path)
-{
- path_geo_ = path;
-}
-
-inline ComPtr ShapeSink::GetGeometrySink() const
-{
- return sink_;
-}
-
-inline void ShapeSink::SetGeometrySink(ComPtr sink)
-{
- sink_ = sink;
-}
-#endif
-
} // namespace kiwano
diff --git a/src/kiwano/render/ShapeSink.cpp b/src/kiwano/render/ShapeSink.cpp
deleted file mode 100644
index d0ce33ab..00000000
--- a/src/kiwano/render/ShapeSink.cpp
+++ /dev/null
@@ -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
-#include
-
-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 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 const& points)
-{
-#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
- KGE_ASSERT(sink_);
- sink_->AddLines(reinterpret_cast(&points[0]), static_cast(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(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 geo_a_raw = shape_a->geo_;
- ComPtr 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
diff --git a/src/kiwano/render/StrokeStyle.cpp b/src/kiwano/render/StrokeStyle.cpp
index 5141e7e7..8b6fe331 100644
--- a/src/kiwano/render/StrokeStyle.cpp
+++ b/src/kiwano/render/StrokeStyle.cpp
@@ -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& 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 StrokeStyle::GetStrokeStyle() const
-{
- StrokeStyle& self = const_cast(*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
diff --git a/src/kiwano/render/StrokeStyle.h b/src/kiwano/render/StrokeStyle.h
index 0fd67b7d..db287a83 100644
--- a/src/kiwano/render/StrokeStyle.h
+++ b/src/kiwano/render/StrokeStyle.h
@@ -19,8 +19,7 @@
// THE SOFTWARE.
#pragma once
-#include
-#include
+#include
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
- 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 dash_array_;
-
-#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
-public:
- ComPtr GetStrokeStyle() const;
-
- void SetStrokeStyle(ComPtr style);
-
-private:
- ComPtr 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 style)
-{
- style_ = style;
-}
-#endif
-
} // namespace kiwano
diff --git a/src/kiwano/render/TextLayout.cpp b/src/kiwano/render/TextLayout.cpp
index 2f16a671..8f66e2e3 100644
--- a/src/kiwano/render/TextLayout.cpp
+++ b/src/kiwano/render/TextLayout.cpp
@@ -21,6 +21,10 @@
#include
#include
+#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
+#include
+#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(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(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(this);
+ KGE_ASSERT(native);
- HRESULT hr = text_layout_->SetFontCollection(collection, { range.start, range.length });
+ if (native)
+ {
+ ComPtr collection = NativePtr::Get(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(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(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(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(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(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(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(this);
+ KGE_ASSERT(native);
+
+ if (native)
{
- HRESULT hr = text_layout_->SetDrawingEffect(brush->GetBrush().Get(), { range.start, range.length });
+ HRESULT hr =
+ native->SetDrawingEffect(NativePtr::Get(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(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(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(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");
diff --git a/src/kiwano/render/TextLayout.h b/src/kiwano/render/TextLayout.h
index 7f011a07..14abc5d8 100644
--- a/src/kiwano/render/TextLayout.h
+++ b/src/kiwano/render/TextLayout.h
@@ -20,7 +20,7 @@
#pragma once
#include
-#include
+#include
#include
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 GetTextLayout() const;
-
- void SetTextLayout(ComPtr layout);
-
-private:
- ComPtr 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 TextLayout::GetTextLayout() const
-{
- return text_layout_;
-}
-
-inline void TextLayout::SetTextLayout(ComPtr layout)
-{
- text_layout_ = layout;
-}
-#endif
-
} // namespace kiwano
diff --git a/src/kiwano/render/TextStyle.hpp b/src/kiwano/render/TextStyle.hpp
index b0018345..a2c166ac 100644
--- a/src/kiwano/render/TextStyle.hpp
+++ b/src/kiwano/render/TextStyle.hpp
@@ -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)
diff --git a/src/kiwano/render/Texture.cpp b/src/kiwano/render/Texture.cpp
index 3d07a245..5fa9987e 100644
--- a/src/kiwano/render/Texture.cpp
+++ b/src/kiwano/render/Texture.cpp
@@ -21,6 +21,10 @@
#include
#include
+#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX
+#include
+#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 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