diff --git a/projects/3rd-party/Box2D/libBox2D.vcxproj b/projects/3rd-party/Box2D/libBox2D.vcxproj
index 7e2bab7c..4b720688 100644
--- a/projects/3rd-party/Box2D/libBox2D.vcxproj
+++ b/projects/3rd-party/Box2D/libBox2D.vcxproj
@@ -145,7 +145,7 @@
   
     $(SolutionDir)\output\$(PlatformToolset)\$(Platform)\$(Configuration)\
     $(SolutionDir)\build\$(PlatformToolset)\$(Platform)\$(Configuration)\$(ProjectName)\
-    true
+    false
   
   
     
diff --git a/projects/3rd-party/curl/libcurl.vcxproj b/projects/3rd-party/curl/libcurl.vcxproj
index 4fa3e9d3..a20337f3 100644
--- a/projects/3rd-party/curl/libcurl.vcxproj
+++ b/projects/3rd-party/curl/libcurl.vcxproj
@@ -62,7 +62,7 @@
   
     $(SolutionDir)\output\$(PlatformToolset)\$(Platform)\$(Configuration)\
     $(SolutionDir)\build\$(PlatformToolset)\$(Platform)\$(Configuration)\$(ProjectName)\
-    true
+    false
   
   
     
@@ -102,4 +102,4 @@
   
   
   
-
+
\ No newline at end of file
diff --git a/projects/3rd-party/curl/libcurl.vcxproj.filters b/projects/3rd-party/curl/libcurl.vcxproj.filters
index 097d9b72..8e08bade 100644
--- a/projects/3rd-party/curl/libcurl.vcxproj.filters
+++ b/projects/3rd-party/curl/libcurl.vcxproj.filters
@@ -33,6 +33,7 @@
     
       include
     
+    
   
   
     
diff --git a/projects/3rd-party/imgui/libimgui.vcxproj b/projects/3rd-party/imgui/libimgui.vcxproj
index 10ff944f..d968c315 100644
--- a/projects/3rd-party/imgui/libimgui.vcxproj
+++ b/projects/3rd-party/imgui/libimgui.vcxproj
@@ -62,7 +62,7 @@
   
     $(SolutionDir)\output\$(PlatformToolset)\$(Platform)\$(Configuration)\
     $(SolutionDir)\build\$(PlatformToolset)\$(Platform)\$(Configuration)\$(ProjectName)\
-    true
+    false
   
   
     
diff --git a/projects/Kiwano.sln b/projects/Kiwano.sln
index 12303d43..b214b404 100644
--- a/projects/Kiwano.sln
+++ b/projects/Kiwano.sln
@@ -23,42 +23,60 @@ EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
 		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 		{FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Debug|Win32.ActiveCfg = Debug|Win32
 		{FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Debug|Win32.Build.0 = Debug|Win32
 		{FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Debug|Win32.Deploy.0 = Debug|Win32
+		{FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Debug|x64.ActiveCfg = Debug|Win32
 		{FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Release|Win32.ActiveCfg = Release|Win32
 		{FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Release|Win32.Build.0 = Release|Win32
+		{FF7F943D-A89C-4E6C-97CF-84F7D8FF8EDF}.Release|x64.ActiveCfg = Release|Win32
 		{1B97937D-8184-426C-BE71-29A163DC76C9}.Debug|Win32.ActiveCfg = Debug|Win32
 		{1B97937D-8184-426C-BE71-29A163DC76C9}.Debug|Win32.Build.0 = Debug|Win32
+		{1B97937D-8184-426C-BE71-29A163DC76C9}.Debug|x64.ActiveCfg = Debug|Win32
 		{1B97937D-8184-426C-BE71-29A163DC76C9}.Release|Win32.ActiveCfg = Release|Win32
 		{1B97937D-8184-426C-BE71-29A163DC76C9}.Release|Win32.Build.0 = Release|Win32
+		{1B97937D-8184-426C-BE71-29A163DC76C9}.Release|x64.ActiveCfg = Release|Win32
 		{69DFBE92-C06F-4CF8-9495-CA9BF2E3BAF2}.Debug|Win32.ActiveCfg = Debug|Win32
 		{69DFBE92-C06F-4CF8-9495-CA9BF2E3BAF2}.Debug|Win32.Build.0 = Debug|Win32
+		{69DFBE92-C06F-4CF8-9495-CA9BF2E3BAF2}.Debug|x64.ActiveCfg = Debug|Win32
 		{69DFBE92-C06F-4CF8-9495-CA9BF2E3BAF2}.Release|Win32.ActiveCfg = Release|Win32
 		{69DFBE92-C06F-4CF8-9495-CA9BF2E3BAF2}.Release|Win32.Build.0 = Release|Win32
+		{69DFBE92-C06F-4CF8-9495-CA9BF2E3BAF2}.Release|x64.ActiveCfg = Release|Win32
 		{A7062ED8-8910-48A5-A3BC-C1612672571F}.Debug|Win32.ActiveCfg = Debug|Win32
 		{A7062ED8-8910-48A5-A3BC-C1612672571F}.Debug|Win32.Build.0 = Debug|Win32
+		{A7062ED8-8910-48A5-A3BC-C1612672571F}.Debug|x64.ActiveCfg = Debug|Win32
 		{A7062ED8-8910-48A5-A3BC-C1612672571F}.Release|Win32.ActiveCfg = Release|Win32
 		{A7062ED8-8910-48A5-A3BC-C1612672571F}.Release|Win32.Build.0 = Release|Win32
+		{A7062ED8-8910-48A5-A3BC-C1612672571F}.Release|x64.ActiveCfg = Release|Win32
 		{DF599AFB-744F-41E5-AF0C-2146F90575C8}.Debug|Win32.ActiveCfg = Debug|Win32
 		{DF599AFB-744F-41E5-AF0C-2146F90575C8}.Debug|Win32.Build.0 = Debug|Win32
+		{DF599AFB-744F-41E5-AF0C-2146F90575C8}.Debug|x64.ActiveCfg = Debug|Win32
 		{DF599AFB-744F-41E5-AF0C-2146F90575C8}.Release|Win32.ActiveCfg = Release|Win32
 		{DF599AFB-744F-41E5-AF0C-2146F90575C8}.Release|Win32.Build.0 = Release|Win32
+		{DF599AFB-744F-41E5-AF0C-2146F90575C8}.Release|x64.ActiveCfg = Release|Win32
 		{7FA1E56D-62AC-47D1-97D1-40B302724198}.Debug|Win32.ActiveCfg = Debug|Win32
 		{7FA1E56D-62AC-47D1-97D1-40B302724198}.Debug|Win32.Build.0 = Debug|Win32
+		{7FA1E56D-62AC-47D1-97D1-40B302724198}.Debug|x64.ActiveCfg = Debug|Win32
 		{7FA1E56D-62AC-47D1-97D1-40B302724198}.Release|Win32.ActiveCfg = Release|Win32
 		{7FA1E56D-62AC-47D1-97D1-40B302724198}.Release|Win32.Build.0 = Release|Win32
+		{7FA1E56D-62AC-47D1-97D1-40B302724198}.Release|x64.ActiveCfg = Release|Win32
 		{A9ABACC7-75A1-46BA-8E48-4105346D9719}.Debug|Win32.ActiveCfg = Debug|Win32
 		{A9ABACC7-75A1-46BA-8E48-4105346D9719}.Debug|Win32.Build.0 = Debug|Win32
+		{A9ABACC7-75A1-46BA-8E48-4105346D9719}.Debug|x64.ActiveCfg = Debug|Win32
 		{A9ABACC7-75A1-46BA-8E48-4105346D9719}.Release|Win32.ActiveCfg = Release|Win32
 		{A9ABACC7-75A1-46BA-8E48-4105346D9719}.Release|Win32.Build.0 = Release|Win32
+		{A9ABACC7-75A1-46BA-8E48-4105346D9719}.Release|x64.ActiveCfg = Release|Win32
 		{0CBA9295-F14D-4966-A7C4-1DD68158176C}.Debug|Win32.ActiveCfg = Debug|Win32
 		{0CBA9295-F14D-4966-A7C4-1DD68158176C}.Debug|Win32.Build.0 = Debug|Win32
+		{0CBA9295-F14D-4966-A7C4-1DD68158176C}.Debug|x64.ActiveCfg = Debug|Win32
 		{0CBA9295-F14D-4966-A7C4-1DD68158176C}.Release|Win32.ActiveCfg = Release|Win32
 		{0CBA9295-F14D-4966-A7C4-1DD68158176C}.Release|Win32.Build.0 = Release|Win32
+		{0CBA9295-F14D-4966-A7C4-1DD68158176C}.Release|x64.ActiveCfg = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/projects/kiwano-audio/kiwano-audio.vcxproj b/projects/kiwano-audio/kiwano-audio.vcxproj
index 54a0883a..dd9b4bb5 100644
--- a/projects/kiwano-audio/kiwano-audio.vcxproj
+++ b/projects/kiwano-audio/kiwano-audio.vcxproj
@@ -63,7 +63,7 @@
   
     $(SolutionDir)\output\$(PlatformToolset)\$(Platform)\$(Configuration)\
     $(SolutionDir)\build\$(PlatformToolset)\$(Platform)\$(Configuration)\$(ProjectName)\
-    true
+    false
   
   
     
diff --git a/projects/kiwano-imgui/kiwano-imgui.vcxproj b/projects/kiwano-imgui/kiwano-imgui.vcxproj
index 2f1b8d03..3b4e0927 100644
--- a/projects/kiwano-imgui/kiwano-imgui.vcxproj
+++ b/projects/kiwano-imgui/kiwano-imgui.vcxproj
@@ -62,7 +62,7 @@
   
     $(SolutionDir)\output\$(PlatformToolset)\$(Platform)\$(Configuration)\
     $(SolutionDir)\build\$(PlatformToolset)\$(Platform)\$(Configuration)\$(ProjectName)\
-    true
+    false
   
   
     
diff --git a/projects/kiwano-network/kiwano-network.vcxproj b/projects/kiwano-network/kiwano-network.vcxproj
index 4f6fbd77..e79a83ee 100644
--- a/projects/kiwano-network/kiwano-network.vcxproj
+++ b/projects/kiwano-network/kiwano-network.vcxproj
@@ -58,7 +58,7 @@
   
     $(SolutionDir)\output\$(PlatformToolset)\$(Platform)\$(Configuration)\
     $(SolutionDir)\build\$(PlatformToolset)\$(Platform)\$(Configuration)\$(ProjectName)\
-    true
+    false
   
   
     
@@ -108,4 +108,4 @@
   
   
   
-
+
\ No newline at end of file
diff --git a/projects/kiwano-physics/kiwano-physics.vcxproj b/projects/kiwano-physics/kiwano-physics.vcxproj
index a7c96cec..9d90c735 100644
--- a/projects/kiwano-physics/kiwano-physics.vcxproj
+++ b/projects/kiwano-physics/kiwano-physics.vcxproj
@@ -68,7 +68,7 @@
   
     $(SolutionDir)\output\$(PlatformToolset)\$(Platform)\$(Configuration)\
     $(SolutionDir)\build\$(PlatformToolset)\$(Platform)\$(Configuration)\$(ProjectName)\
-    true
+    false
   
   
     
diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj
index 28f90319..dad9cfe7 100644
--- a/projects/kiwano/kiwano.vcxproj
+++ b/projects/kiwano/kiwano.vcxproj
@@ -212,7 +212,7 @@
   
     $(SolutionDir)\output\$(PlatformToolset)\$(Platform)\$(Configuration)\
     $(SolutionDir)\build\$(PlatformToolset)\$(Platform)\$(Configuration)\$(ProjectName)\
-    true
+    false
   
   
     
diff --git a/src/3rd-party/curl/libs/libcrypto.lib b/src/3rd-party/curl/libs/libcrypto.lib
new file mode 100644
index 00000000..1ca381d1
Binary files /dev/null and b/src/3rd-party/curl/libs/libcrypto.lib differ
diff --git a/src/3rd-party/curl/libs/libssl.lib b/src/3rd-party/curl/libs/libssl.lib
new file mode 100644
index 00000000..346d71d6
Binary files /dev/null and b/src/3rd-party/curl/libs/libssl.lib differ
diff --git a/src/kiwano/2d/LayerActor.cpp b/src/kiwano/2d/LayerActor.cpp
index 8d433348..022169c4 100644
--- a/src/kiwano/2d/LayerActor.cpp
+++ b/src/kiwano/2d/LayerActor.cpp
@@ -38,27 +38,12 @@ LayerActor::LayerActor()
 
 LayerActor::~LayerActor() {}
 
-void LayerActor::SetClipRect(Rect const& clip_rect)
-{
-    layer_.SetClipRect(clip_rect);
-}
-
 void LayerActor::SetOpacity(float opacity)
 {
     // Actor::SetOpacity(opacity);
     layer_.SetOpacity(opacity);
 }
 
-void LayerActor::SetMaskShape(ShapePtr mask)
-{
-    layer_.SetMaskShape(mask);
-}
-
-void LayerActor::SetMaskTransform(Matrix3x2 const& transform)
-{
-    layer_.SetMaskTransform(transform);
-}
-
 bool LayerActor::DispatchEvent(Event* evt)
 {
     if (!IsVisible())
diff --git a/src/kiwano/2d/LayerActor.h b/src/kiwano/2d/LayerActor.h
index 9dd61745..943aa119 100644
--- a/src/kiwano/2d/LayerActor.h
+++ b/src/kiwano/2d/LayerActor.h
@@ -34,7 +34,7 @@ KGE_DECLARE_SMART_PTR(LayerActor);
 
 /**
  * \~chinese
- * @brief 图层
+ * @brief 图层角色
  */
 class KGE_API LayerActor : public Actor
 {
@@ -51,40 +51,29 @@ public:
     /// @brief 是否开启消息吞没
     bool IsSwallowEventsEnabled() const;
 
+    /// \~chinese
+    /// @brief 获取图层区域
+    Layer const& GetLayer() const;
+
+    /// \~chinese
+    /// @brief 获取图层区域
+    Layer& GetLayer();
+
+    /// \~chinese
+    /// @brief 设置图层
+    /// @param layer 图层
+    void SetLayer(Layer const& layer);
+
     /// \~chinese
     /// @brief 设置消息吞没功能
     /// @param enabled 是否启用
     void SetSwallowEvents(bool enabled);
 
-    /// \~chinese
-    /// @brief 设置裁剪区域
-    /// @param clip_rect 裁剪矩形
-    void SetClipRect(Rect const& clip_rect);
-
     /// \~chinese
     /// @brief 设置图层透明度
     /// @param opacity 透明度
     void SetOpacity(float opacity) override;
 
-    /// \~chinese
-    /// @brief 设置几何蒙层
-    /// @param mask 蒙层的形状
-    void SetMaskShape(ShapePtr mask);
-
-    /// \~chinese
-    /// @brief 设置几何蒙层的二维变换
-    /// @param transform 应用于蒙层的二维变换
-    void SetMaskTransform(Matrix3x2 const& transform);
-
-    /// \~chinese
-    /// @brief 设置图层区域
-    /// @param area 图层区域属性
-    void SetLayer(Layer const& layer);
-
-    /// \~chinese
-    /// @brief 获取图层区域
-    Layer const& GetLayer() const;
-
     bool DispatchEvent(Event* evt) override;
 
 protected:
@@ -118,4 +107,10 @@ inline Layer const& LayerActor::GetLayer() const
 {
     return layer_;
 }
+
+inline Layer& LayerActor::GetLayer()
+{
+    return layer_;
+}
+
 }  // namespace kiwano
diff --git a/src/kiwano/2d/ShapeActor.cpp b/src/kiwano/2d/ShapeActor.cpp
index ceebe316..3c03ef79 100644
--- a/src/kiwano/2d/ShapeActor.cpp
+++ b/src/kiwano/2d/ShapeActor.cpp
@@ -59,16 +59,6 @@ bool ShapeActor::ContainsPoint(const Point& point) const
     return shape_->ContainsPoint(point, &GetTransformMatrix());
 }
 
-void ShapeActor::SetStrokeWidth(float width)
-{
-    stroke_width_ = std::max(width, 0.f);
-}
-
-void ShapeActor::SetStrokeStyle(StrokeStylePtr stroke_style)
-{
-    stroke_style_ = stroke_style;
-}
-
 void ShapeActor::SetShape(ShapePtr shape)
 {
     shape_ = shape;
diff --git a/src/kiwano/2d/ShapeActor.h b/src/kiwano/2d/ShapeActor.h
index 4d11ebe7..1090bcbd 100644
--- a/src/kiwano/2d/ShapeActor.h
+++ b/src/kiwano/2d/ShapeActor.h
@@ -350,43 +350,62 @@ inline void ShapeActor::SetFillBrush(BrushPtr brush)
 {
     fill_brush_ = brush;
 }
+
 inline void ShapeActor::SetStrokeBrush(BrushPtr brush)
 {
     stroke_brush_ = brush;
 }
+
 inline BrushPtr ShapeActor::GetFillBrush() const
 {
     return fill_brush_;
 }
+
 inline BrushPtr ShapeActor::GetStrokeBrush() const
 {
     return stroke_brush_;
 }
+
 inline float ShapeActor::GetStrokeWidth() const
 {
     return stroke_width_;
 }
+
 inline StrokeStylePtr ShapeActor::GetStrokeStyle() const
 {
     return stroke_style_;
 }
+
 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;
+}
+
 inline Point const& LineActor::GetBeginPoint() const
 {
     return begin_;
 }
+
 inline Point const& LineActor::GetEndPoint() const
 {
     return end_;
 }
+
 inline void LineActor::SetBeginPoint(Point const& begin)
 {
     SetLine(begin, end_);
 }
+
 inline void LineActor::SetEndPoint(Point const& end)
 {
     SetLine(begin_, end);
@@ -401,6 +420,7 @@ inline Vec2 RoundedRectActor::GetRadius() const
 {
     return radius_;
 }
+
 inline Size RoundedRectActor::GetRectSize() const
 {
     return GetSize();
@@ -415,4 +435,5 @@ inline Vec2 EllipseActor::GetRadius() const
 {
     return radius_;
 }
+
 }  // namespace kiwano
diff --git a/src/kiwano/2d/TextActor.h b/src/kiwano/2d/TextActor.h
index e4210be7..04aa630c 100644
--- a/src/kiwano/2d/TextActor.h
+++ b/src/kiwano/2d/TextActor.h
@@ -66,6 +66,10 @@ public:
     /// @brief 获取文本布局
     const TextLayout& GetLayout() const;
 
+    /// \~chinese
+    /// @brief 获取文本布局
+    TextLayout& GetLayout();
+
     /// \~chinese
     /// @brief 获取文本布局大小
     Size GetLayoutSize() const;
@@ -194,6 +198,11 @@ inline const TextLayout& TextActor::GetLayout() const
     return text_layout_;
 }
 
+inline TextLayout& TextActor::GetLayout()
+{
+    return text_layout_;
+}
+
 inline Size TextActor::GetLayoutSize() const
 {
     return text_layout_.GetLayoutSize();
diff --git a/src/kiwano/render/DirectX/RenderContextImpl.cpp b/src/kiwano/render/DirectX/RenderContextImpl.cpp
index b478dcb6..a12794b5 100644
--- a/src/kiwano/render/DirectX/RenderContextImpl.cpp
+++ b/src/kiwano/render/DirectX/RenderContextImpl.cpp
@@ -133,18 +133,10 @@ void RenderContextImpl::DrawTextLayout(TextLayout const& layout, Point const& of
         }
 
         HRESULT hr = S_OK;
+        ID2D1StrokeStyle* stroke_style = style.outline_stroke ? style.outline_stroke->GetStrokeStyle().get() : nullptr;
 
-        if (style.outline_stroke)
-        {
-            hr = text_renderer_->DrawTextLayout(layout.GetTextLayout().get(), offset.x, offset.y, fill_brush.get(),
-                                                outline_brush.get(), style.outline_width,
-                                                style.outline_stroke->GetStrokeStyle().get());
-        }
-        else
-        {
-            hr = text_renderer_->DrawTextLayout(layout.GetTextLayout().get(), offset.x, offset.y, fill_brush.get(),
-                                                outline_brush.get(), style.outline_width, nullptr);
-        }
+        hr = text_renderer_->DrawTextLayout(layout.GetTextLayout().get(), offset.x, offset.y, fill_brush.get(),
+                                            outline_brush.get(), style.outline_width, stroke_style);
 
         if (SUCCEEDED(hr))
         {
@@ -164,16 +156,9 @@ void RenderContextImpl::DrawShape(Shape const& shape, StrokeStylePtr stroke, flo
 
     if (shape.IsValid())
     {
-        if (stroke)
-        {
-            render_target_->DrawGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get(), stroke_width,
-                                         stroke->GetStrokeStyle().get());
-        }
-        else
-        {
-            render_target_->DrawGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get(), stroke_width,
-                                         nullptr);
-        }
+        ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().get() : nullptr;
+        render_target_->DrawGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get(), stroke_width,
+                                     stroke_style);
 
         IncreasePrimitivesCount();
     }
@@ -184,16 +169,9 @@ void RenderContextImpl::DrawLine(Point const& point1, Point const& point2, Strok
     KGE_ASSERT(render_target_ && "Render target has not been initialized!");
     KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
 
-    if (stroke)
-    {
-        render_target_->DrawLine(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2),
-                                 current_brush_->GetBrush().get(), stroke_width, stroke->GetStrokeStyle().get());
-    }
-    else
-    {
-        render_target_->DrawLine(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2),
-                                 current_brush_->GetBrush().get(), stroke_width, nullptr);
-    }
+    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);
 
     IncreasePrimitivesCount();
 }
@@ -203,16 +181,9 @@ void RenderContextImpl::DrawRectangle(Rect const& rect, StrokeStylePtr stroke, f
     KGE_ASSERT(render_target_ && "Render target has not been initialized!");
     KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
 
-    if (stroke)
-    {
-        render_target_->DrawRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get(), stroke_width,
-                                      stroke->GetStrokeStyle().get());
-    }
-    else
-    {
-        render_target_->DrawRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get(), stroke_width,
-                                      nullptr);
-    }
+    ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().get() : nullptr;
+    render_target_->DrawRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get(), stroke_width,
+                                  stroke_style);
 
     IncreasePrimitivesCount();
 }
@@ -223,17 +194,10 @@ void RenderContextImpl::DrawRoundedRectangle(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!");
 
-    if (stroke)
-    {
-        render_target_->DrawRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y),
-                                             current_brush_->GetBrush().get(), stroke_width,
-                                             stroke->GetStrokeStyle().get());
-    }
-    else
-    {
-        render_target_->DrawRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y),
-                                             current_brush_->GetBrush().get(), stroke_width, nullptr);
-    }
+    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);
+
     IncreasePrimitivesCount();
 }
 
@@ -242,16 +206,9 @@ void RenderContextImpl::DrawEllipse(Point const& center, Vec2 const& radius, Str
     KGE_ASSERT(render_target_ && "Render target has not been initialized!");
     KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!");
 
-    if (stroke)
-    {
-        render_target_->DrawEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y),
-                                    current_brush_->GetBrush().get(), stroke_width, stroke->GetStrokeStyle().get());
-    }
-    else
-    {
-        render_target_->DrawEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y),
-                                    current_brush_->GetBrush().get(), stroke_width, nullptr);
-    }
+    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);
 
     IncreasePrimitivesCount();
 }
diff --git a/src/kiwano/render/DirectX/RenderContextImpl.h b/src/kiwano/render/DirectX/RenderContextImpl.h
index f8d95404..974d4d1f 100644
--- a/src/kiwano/render/DirectX/RenderContextImpl.h
+++ b/src/kiwano/render/DirectX/RenderContextImpl.h
@@ -39,22 +39,19 @@ public:
 
     void EndDraw() override;
 
-    void DrawTexture(Texture const& texture, const Rect* src_rect = nullptr, const Rect* dest_rect = nullptr) override;
+    void DrawTexture(Texture const& texture, const Rect* src_rect, const Rect* dest_rect) override;
 
-    void DrawTextLayout(TextLayout const& layout, Point const& offset = Point()) override;
+    void DrawTextLayout(TextLayout const& layout, Point const& offset) override;
 
-    void DrawShape(Shape const& shape, StrokeStylePtr stroke = nullptr, float stroke_width = 1.0f) override;
+    void DrawShape(Shape const& shape, StrokeStylePtr stroke, float stroke_width) override;
 
-    void DrawLine(Point const& point1, Point const& point2, StrokeStylePtr stroke = nullptr,
-                  float stroke_width = 1.0f) override;
+    void DrawLine(Point const& point1, Point const& point2, StrokeStylePtr stroke, float stroke_width) override;
 
-    void DrawRectangle(Rect const& rect, StrokeStylePtr stroke = nullptr, float stroke_width = 1.0f) override;
+    void DrawRectangle(Rect const& rect, StrokeStylePtr stroke, float stroke_width) override;
 
-    void DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, StrokeStylePtr stroke = nullptr,
-                              float stroke_width = 1.0f) override;
+    void DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, StrokeStylePtr stroke, float stroke_width) override;
 
-    void DrawEllipse(Point const& center, Vec2 const& radius, StrokeStylePtr stroke = nullptr,
-                     float stroke_width = 1.0f) override;
+    void DrawEllipse(Point const& center, Vec2 const& radius, StrokeStylePtr stroke, float stroke_width) override;
 
     void FillShape(Shape const& shape) override;
 
diff --git a/src/kiwano/render/Layer.h b/src/kiwano/render/Layer.h
index c0911040..1619d795 100644
--- a/src/kiwano/render/Layer.h
+++ b/src/kiwano/render/Layer.h
@@ -31,7 +31,7 @@ namespace kiwano
 
 /**
  * \~chinese
- * @brief 图层区域
+ * @brief 图层
  */
 class KGE_API Layer
 {
diff --git a/src/kiwano/render/RenderContext.h b/src/kiwano/render/RenderContext.h
index f70e51db..b7918744 100644
--- a/src/kiwano/render/RenderContext.h
+++ b/src/kiwano/render/RenderContext.h
@@ -89,7 +89,7 @@ public:
     /// @param shape 形状
     /// @param stroke 线条样式
     /// @param stroke_width 线条宽度
-    virtual void DrawShape(Shape const& shape, StrokeStylePtr stroke = nullptr, float stroke_width = 1.0f) = 0;
+    virtual void DrawShape(Shape const& shape, StrokeStylePtr stroke, float stroke_width) = 0;
 
     /// \~chinese
     /// @brief 绘制线段
@@ -97,15 +97,14 @@ public:
     /// @param point2 线段终点
     /// @param stroke 线条样式
     /// @param stroke_width 线条宽度
-    virtual void DrawLine(Point const& point1, Point const& point2, StrokeStylePtr stroke = nullptr,
-                          float stroke_width = 1.0f) = 0;
+    virtual void DrawLine(Point const& point1, Point const& point2, StrokeStylePtr stroke, float stroke_width) = 0;
 
     /// \~chinese
     /// @brief 绘制矩形边框
     /// @param rect 矩形
     /// @param stroke 线条样式
     /// @param stroke_width 线条宽度
-    virtual void DrawRectangle(Rect const& rect, StrokeStylePtr stroke = nullptr, float stroke_width = 1.0f) = 0;
+    virtual void DrawRectangle(Rect const& rect, StrokeStylePtr stroke, float stroke_width) = 0;
 
     /// \~chinese
     /// @brief 绘制圆角矩形边框
@@ -113,8 +112,8 @@ public:
     /// @param radius 圆角半径
     /// @param stroke 线条样式
     /// @param stroke_width 线条宽度
-    virtual void DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, StrokeStylePtr stroke = nullptr,
-                                      float stroke_width = 1.0f) = 0;
+    virtual void DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, StrokeStylePtr stroke,
+                                      float stroke_width) = 0;
 
     /// \~chinese
     /// @brief 绘制椭圆边框
@@ -122,8 +121,8 @@ public:
     /// @param radius 椭圆半径
     /// @param stroke 线条样式
     /// @param stroke_width 线条宽度
-    virtual void DrawEllipse(Point const& center, Vec2 const& radius, StrokeStylePtr stroke = nullptr,
-                             float stroke_width = 1.0f) = 0;
+    virtual void DrawEllipse(Point const& center, Vec2 const& radius, StrokeStylePtr stroke,
+                             float stroke_width) = 0;
 
     /// \~chinese
     /// @brief 填充形状
diff --git a/src/kiwano/render/StrokeStyle.cpp b/src/kiwano/render/StrokeStyle.cpp
index c0cade8a..90b03f47 100644
--- a/src/kiwano/render/StrokeStyle.cpp
+++ b/src/kiwano/render/StrokeStyle.cpp
@@ -26,41 +26,15 @@ namespace kiwano
 
 StrokeStylePtr StrokeStyle::Create(CapStyle cap, LineJoinStyle line_join, DashStyle dash, float dash_offset)
 {
-    switch (dash)
+    StrokeStylePtr ptr = new (std::nothrow) StrokeStyle;
+    if (ptr)
     {
-    case DashStyle::Solid:
-    {
-        return StrokeStyle::Create(cap, line_join, nullptr, 0, dash_offset);
+        ptr->SetCapStyle(cap);
+        ptr->SetLineJoinStyle(line_join);
+        ptr->SetDashStyle(dash);
+        ptr->SetDashOffset(dash_offset);
     }
-
-    case DashStyle::Dash:
-    {
-        float dash_array[] = { 2, 2 };
-        return StrokeStyle::Create(cap, line_join, dash_array, dash_offset);
-    }
-
-    case DashStyle::Dot:
-    {
-        float dash_array[] = { 0, 2 };
-        return StrokeStyle::Create(cap, line_join, dash_array, dash_offset);
-    }
-
-    case DashStyle::DashDot:
-    {
-        float dash_array[] = { 2, 2, 0, 2 };
-        return StrokeStyle::Create(cap, line_join, dash_array, dash_offset);
-    }
-
-    case DashStyle::DashDotDot:
-    {
-        float dash_array[] = { 2, 2, 0, 2, 0, 2 };
-        return StrokeStyle::Create(cap, line_join, dash_array, dash_offset);
-    }
-
-    default:
-        break;
-    }
-    return nullptr;
+    return ptr;
 }
 
 StrokeStylePtr StrokeStyle::Create(CapStyle cap, LineJoinStyle line_join, const float* dash_array, size_t dash_size,
@@ -69,11 +43,84 @@ StrokeStylePtr StrokeStyle::Create(CapStyle cap, LineJoinStyle line_join, const
     StrokeStylePtr ptr = new (std::nothrow) StrokeStyle;
     if (ptr)
     {
-        Renderer::GetInstance().CreateStrokeStyle(*ptr, cap, line_join, dash_array, dash_size, dash_offset);
+        ptr->SetCapStyle(cap);
+        ptr->SetLineJoinStyle(line_join);
+        ptr->SetDashStyle(dash_array, dash_size);
+        ptr->SetDashOffset(dash_offset);
     }
     return ptr;
 }
 
-StrokeStyle::StrokeStyle() {}
+StrokeStyle::StrokeStyle()
+    : cap_(CapStyle::Flat)
+    , line_join_(LineJoinStyle::Miter)
+    , dash_offset_(0.0f)
+{
+}
+
+void StrokeStyle::SetDashStyle(DashStyle dash_style)
+{
+    switch (dash_style)
+    {
+    case DashStyle::Solid:
+    {
+        dash_array_.clear();
+        break;
+    }
+
+    case DashStyle::Dash:
+    {
+        dash_array_ = { 2, 2 };
+        break;
+    }
+
+    case DashStyle::Dot:
+    {
+        dash_array_ = { 0, 2 };
+        break;
+    }
+
+    case DashStyle::DashDot:
+    {
+        dash_array_ = { 2, 2, 0, 2 };
+        break;
+    }
+
+    case DashStyle::DashDotDot:
+    {
+        dash_array_ = { 2, 2, 0, 2, 0, 2 };
+        break;
+    }
+
+    default:
+        break;
+    }
+}
+
+void StrokeStyle::SetDashStyle(const Vector& dash_array)
+{
+    dash_array_ = dash_array;
+    style_.reset();
+}
+
+void StrokeStyle::SetDashStyle(const float* dash_array, size_t dash_size)
+{
+    if (dash_size == 0)
+        dash_array_.clear();
+    else
+        dash_array_.assign(dash_array, dash_array + dash_size);
+    style_.reset();
+}
+
+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_;
+}
 
 }  // namespace kiwano
diff --git a/src/kiwano/render/StrokeStyle.h b/src/kiwano/render/StrokeStyle.h
index 7d8a129f..31fee359 100644
--- a/src/kiwano/render/StrokeStyle.h
+++ b/src/kiwano/render/StrokeStyle.h
@@ -97,8 +97,8 @@ public:
     /// @param dash_array 线条虚线的长度与间隙数组
     /// @param dash_offset 线条虚线偏移量
     template 
-    static StrokeStylePtr Create(CapStyle cap, LineJoinStyle                     line_join = LineJoinStyle::Miter,
-                                 float (&dash_array)[_DashSize] = nullptr, float dash_offset = 0.0f)
+    static inline StrokeStylePtr Create(CapStyle cap, LineJoinStyle line_join = LineJoinStyle::Miter,
+                                        float (&dash_array)[_DashSize] = nullptr, float dash_offset = 0.0f)
     {
         return StrokeStyle::Create(cap, line_join, dash_array, _DashSize, dash_offset);
     }
@@ -109,6 +109,67 @@ public:
     /// @brief 是否有效
     bool IsValid() const;
 
+    /// \~chinese
+    /// @brief 获取线条端点样式
+    CapStyle GetCapStyle() const;
+
+    /// \~chinese
+    /// @brief 获取线条交点样式
+    LineJoinStyle GetLineJoinStyle() const;
+
+    /// \~chinese
+    /// @brief 获取线条虚线的长度与间隙数组
+    const Vector& GetDashArray() const;
+
+    /// \~chinese
+    /// @brief 获取虚线偏移量
+    float GetDashOffset() const;
+
+    /// \~chinese
+    /// @brief 设置线条端点样式
+    void SetCapStyle(CapStyle cap);
+
+    /// \~chinese
+    /// @brief 设置线条交点样式
+    void SetLineJoinStyle(LineJoinStyle line_join);
+
+    /// \~chinese
+    /// @brief 设置虚线样式
+    /// @param dash_style 线条虚线样式
+    void SetDashStyle(DashStyle dash_style);
+
+    /// \~chinese
+    /// @brief 设置虚线样式
+    /// @param dash_array 线条虚线的长度与间隙数组
+    void SetDashStyle(const Vector& dash_array);
+
+    /// \~chinese
+    /// @brief 设置虚线样式
+    /// @param dash_array 线条虚线的长度与间隙数组
+    /// @param dash_size 线条虚线数组大小
+    void SetDashStyle(const float* dash_array, size_t dash_size);
+
+    /// \~chinese
+    /// @brief 设置虚线样式
+    /// @tparam _DashSize 线条虚线数组大小
+    /// @param dash_array 线条虚线的长度与间隙数组
+    template 
+    inline void SetDashStyle(float (&dash_array)[_DashSize])
+    {
+        SetDashStyle(dash_array, _DashSize);
+    }
+
+    /// \~chinese
+    /// @brief 设置虚线偏移量
+    /// @param dash_offset 线条虚线偏移量
+    void SetDashOffset(float dash_offset);
+
+private:
+    CapStyle      cap_;
+    LineJoinStyle line_join_;
+    float         dash_offset_;
+    Vector dash_array_;
+
 #if defined(KGE_WIN32)
 public:
     ComPtr GetStrokeStyle() const;
@@ -122,15 +183,48 @@ private:
 
 /** @} */
 
-inline bool StrokeStyle::IsValid() const
+inline CapStyle StrokeStyle::GetCapStyle() const
 {
-    return style_ != nullptr;
+    return cap_;
+}
+
+inline LineJoinStyle StrokeStyle::GetLineJoinStyle() const
+{
+    return line_join_;
+}
+
+inline const Vector& StrokeStyle::GetDashArray() const
+{
+    return dash_array_;
+}
+
+inline float StrokeStyle::GetDashOffset() const
+{
+    return dash_offset_;
+}
+
+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();
 }
 
 #if defined(KGE_WIN32)
-inline ComPtr StrokeStyle::GetStrokeStyle() const
+inline bool StrokeStyle::IsValid() const
 {
-    return style_;
+    return style_ != nullptr;
 }
 
 inline void StrokeStyle::SetStrokeStyle(ComPtr style)
diff --git a/src/kiwano/render/TextLayout.h b/src/kiwano/render/TextLayout.h
index c847edfd..1a601db7 100644
--- a/src/kiwano/render/TextLayout.h
+++ b/src/kiwano/render/TextLayout.h
@@ -32,7 +32,7 @@ namespace kiwano
 
 /// \~chinese
 /// @brief 文本布局
-class KGE_API TextLayout
+class KGE_API TextLayout : public Noncopyable
 {
 public:
     /// \~chinese