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(this); + auto native_to_copy = NativePtr::Get(copy_from); + + HRESULT hr = native->CopyFromBitmap(nullptr, native_to_copy.Get(), nullptr); KGE_THROW_IF_FAILED(hr, "Copy texture data failed"); } @@ -121,10 +93,13 @@ void Texture::CopyFrom(TexturePtr copy_from, Rect const& src_rect, Point const& #if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX if (IsValid() && copy_from) { - HRESULT hr = bitmap_->CopyFromBitmap( - &D2D1::Point2U(uint32_t(dest_point.x), uint32_t(dest_point.y)), copy_from->GetBitmap().Get(), - &D2D1::RectU(uint32_t(src_rect.GetLeft()), uint32_t(src_rect.GetTop()), uint32_t(src_rect.GetRight()), - uint32_t(src_rect.GetBottom()))); + auto native = NativePtr::Get(this); + auto native_to_copy = NativePtr::Get(copy_from); + + HRESULT hr = + native->CopyFromBitmap(&D2D1::Point2U(uint32_t(dest_point.x), uint32_t(dest_point.y)), native_to_copy.Get(), + &D2D1::RectU(uint32_t(src_rect.GetLeft()), uint32_t(src_rect.GetTop()), + uint32_t(src_rect.GetRight()), uint32_t(src_rect.GetBottom()))); KGE_THROW_IF_FAILED(hr, "Copy texture data failed"); } diff --git a/src/kiwano/render/Texture.h b/src/kiwano/render/Texture.h index 7d8fbf1b..2d9f2c5c 100644 --- a/src/kiwano/render/Texture.h +++ b/src/kiwano/render/Texture.h @@ -19,9 +19,8 @@ // THE SOFTWARE. #pragma once -#include #include -#include +#include namespace kiwano { @@ -44,11 +43,15 @@ enum class InterpolationMode Nearest ///< 最邻近插值,取最邻近的像素点的颜色值 }; +/// \~chinese +/// @brief 像素大小 +typedef math::Vec2T PixelSize; + /** * \~chinese * @brief 纹理 */ -class KGE_API Texture : public virtual ObjectBase +class KGE_API Texture : public NativeObject { public: /// \~chinese @@ -71,10 +74,6 @@ public: /// @brief 加载资源 bool Load(Resource const& res); - /// \~chinese - /// @brief 是否有效 - bool IsValid() const; - /// \~chinese /// @brief 获取纹理宽度 float GetWidth() const; @@ -97,11 +96,22 @@ public: /// \~chinese /// @brief 获取像素大小 - math::Vec2T GetSizeInPixels() const; + PixelSize GetSizeInPixels() const; /// \~chinese /// @brief 获取像素插值方式 InterpolationMode GetBitmapInterpolationMode() const; + /// \~chinese + /// @brief 设置大小 + void SetSize(const Size& size); + + /// \~chinese + /// @brief 设置像素大小 + void SetSizeInPixels(const PixelSize& size); + + /// \~chinese + /// @brief 设置像素插值方式 + void SetInterpolationMode(InterpolationMode mode); /// \~chinese /// @brief 拷贝纹理 @@ -115,10 +125,6 @@ public: /// @param dest_point 拷贝至目标位置 void CopyFrom(TexturePtr copy_from, Rect const& src_rect, Point const& dest_point); - /// \~chinese - /// @brief 设置像素插值方式 - void SetInterpolationMode(InterpolationMode mode); - /// \~chinese /// @brief 设置默认的像素插值方式 static void SetDefaultInterpolationMode(InterpolationMode mode); @@ -128,62 +134,58 @@ public: static InterpolationMode GetDefaultInterpolationMode(); private: - InterpolationMode interpolation_mode_; + Size size_; + PixelSize size_in_pixels_; + InterpolationMode interpolation_mode_; static InterpolationMode default_interpolation_mode_; - -#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX -public: - /// \~chinese - /// @brief 获取源位图 - ComPtr GetBitmap() const; - - /// \~chinese - /// @brief 设置源位图 - void SetBitmap(ComPtr bitmap); - -private: - ComPtr bitmap_; - Size size_; - math::Vec2T size_in_pixels_; -#endif }; /** @} */ -inline bool Texture::IsValid() const +inline float Texture::GetWidth() const { -#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX - return bitmap_ != nullptr; -#else - return false; // not supported -#endif + return size_.x; } -#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX -inline ComPtr Texture::GetBitmap() const +inline float Texture::GetHeight() const { - return bitmap_; + return size_.y; } -inline void Texture::SetBitmap(ComPtr bitmap) +inline Size Texture::GetSize() const { - if (bitmap_ != bitmap) - { - bitmap_ = bitmap; - - if (bitmap_) - { - auto size = bitmap_->GetSize(); - auto pixel_size = bitmap_->GetPixelSize(); - - size_.x = size.width; - size_.y = size.height; - size_in_pixels_.x = pixel_size.width; - size_in_pixels_.y = pixel_size.height; - } - } + return size_; +} + +inline uint32_t Texture::GetWidthInPixels() const +{ + return size_in_pixels_.x; +} + +inline uint32_t Texture::GetHeightInPixels() const +{ + return size_in_pixels_.y; +} + +inline PixelSize Texture::GetSizeInPixels() const +{ + return size_in_pixels_; +} + +inline InterpolationMode Texture::GetBitmapInterpolationMode() const +{ + return interpolation_mode_; +} + +inline void Texture::SetSize(const Size& size) +{ + size_ = size; +} + +inline void Texture::SetSizeInPixels(const PixelSize& size) +{ + size_in_pixels_ = size; } -#endif } // namespace kiwano diff --git a/src/kiwano/utils/ResourceCache.cpp b/src/kiwano/utils/ResourceCache.cpp index 71ba748d..850c45f6 100644 --- a/src/kiwano/utils/ResourceCache.cpp +++ b/src/kiwano/utils/ResourceCache.cpp @@ -401,7 +401,7 @@ bool LoadXmlData(ResourceCache* loader, const XmlNode& elem) int rows = 0, cols = 0, max_num = -1; if (auto attr = image.attribute("id")) - id.assign(attr.value()); + id = attr.value(); if (auto attr = image.attribute("type")) type = attr.value(); if (auto attr = image.attribute("file")) @@ -452,7 +452,7 @@ bool LoadXmlData(ResourceCache* loader, const XmlNode& elem) { String id, file; if (auto attr = font.attribute("id")) - id.assign(attr.value()); + id = attr.value(); if (auto attr = font.attribute("file")) file = attr.value();