#include "NativeRendererInternal.h" namespace XCEngine::UI::Editor::Host { using namespace NativeRendererInternal; void NativeRenderer::RenderFilledRectCommand( ID2D1RenderTarget& renderTarget, ID2D1SolidColorBrush& solidBrush, const ::XCEngine::UI::UIDrawCommand& command) { const float dpiScale = ClampDpiScale(m_dpiScale); const D2D1_RECT_F rect = ToD2DRect(command.rect, dpiScale); const float rounding = command.rounding > 0.0f ? command.rounding * dpiScale : 0.0f; if (command.rounding > 0.0f) { renderTarget.FillRoundedRectangle( D2D1::RoundedRect(rect, rounding, rounding), &solidBrush); return; } renderTarget.FillRectangle(rect, &solidBrush); } void NativeRenderer::RenderFilledRectLinearGradientCommand( ID2D1RenderTarget& renderTarget, const ::XCEngine::UI::UIDrawCommand& command) { const float dpiScale = ClampDpiScale(m_dpiScale); const D2D1_RECT_F rect = ToD2DRect(command.rect, dpiScale); const float rounding = command.rounding > 0.0f ? command.rounding * dpiScale : 0.0f; const D2D1_GRADIENT_STOP stops[2] = { D2D1::GradientStop(0.0f, ToD2DColor(command.color)), D2D1::GradientStop(1.0f, ToD2DColor(command.secondaryColor)) }; Microsoft::WRL::ComPtr stopCollection; HRESULT hr = renderTarget.CreateGradientStopCollection( stops, 2u, stopCollection.ReleaseAndGetAddressOf()); if (FAILED(hr) || !stopCollection) { return; } const D2D1_POINT_2F startPoint = command.gradientDirection == ::XCEngine::UI::UILinearGradientDirection::Vertical ? D2D1::Point2F((rect.left + rect.right) * 0.5f, rect.top) : D2D1::Point2F(rect.left, (rect.top + rect.bottom) * 0.5f); const D2D1_POINT_2F endPoint = command.gradientDirection == ::XCEngine::UI::UILinearGradientDirection::Vertical ? D2D1::Point2F((rect.left + rect.right) * 0.5f, rect.bottom) : D2D1::Point2F(rect.right, (rect.top + rect.bottom) * 0.5f); Microsoft::WRL::ComPtr gradientBrush; hr = renderTarget.CreateLinearGradientBrush( D2D1::LinearGradientBrushProperties(startPoint, endPoint), stopCollection.Get(), gradientBrush.ReleaseAndGetAddressOf()); if (FAILED(hr) || !gradientBrush) { return; } if (command.rounding > 0.0f) { renderTarget.FillRoundedRectangle( D2D1::RoundedRect(rect, rounding, rounding), gradientBrush.Get()); return; } renderTarget.FillRectangle(rect, gradientBrush.Get()); } void NativeRenderer::RenderRectOutlineCommand( ID2D1RenderTarget& renderTarget, ID2D1SolidColorBrush& solidBrush, const ::XCEngine::UI::UIDrawCommand& command) { const float dpiScale = ClampDpiScale(m_dpiScale); const D2D1_RECT_F rect = ToD2DRect(command.rect, dpiScale); const float thickness = (command.thickness > 0.0f ? command.thickness : 1.0f) * dpiScale; const float rounding = command.rounding > 0.0f ? command.rounding * dpiScale : 0.0f; if (command.rounding > 0.0f) { renderTarget.DrawRoundedRectangle( D2D1::RoundedRect(rect, rounding, rounding), &solidBrush, thickness); return; } renderTarget.DrawRectangle(rect, &solidBrush, thickness); } void NativeRenderer::RenderLineCommand( ID2D1RenderTarget& renderTarget, ID2D1SolidColorBrush& solidBrush, const ::XCEngine::UI::UIDrawCommand& command) { const float dpiScale = ClampDpiScale(m_dpiScale); const float thickness = (command.thickness > 0.0f ? command.thickness : 1.0f) * dpiScale; const float pixelOffset = ResolveStrokePixelOffset(thickness); const D2D1_POINT_2F start = ToD2DPoint(command.position, dpiScale, pixelOffset); const D2D1_POINT_2F end = ToD2DPoint(command.uvMin, dpiScale, pixelOffset); renderTarget.DrawLine(start, end, &solidBrush, thickness); } void NativeRenderer::RenderFilledTriangleCommand( ID2D1RenderTarget& renderTarget, ID2D1SolidColorBrush& solidBrush, const ::XCEngine::UI::UIDrawCommand& command) { Microsoft::WRL::ComPtr geometry; HRESULT hr = m_d2dFactory->CreatePathGeometry(geometry.ReleaseAndGetAddressOf()); if (FAILED(hr) || !geometry) { return; } Microsoft::WRL::ComPtr sink; hr = geometry->Open(sink.ReleaseAndGetAddressOf()); if (FAILED(hr) || !sink) { return; } const float dpiScale = ClampDpiScale(m_dpiScale); const D2D1_POINT_2F points[3] = { ToD2DPoint(command.position, dpiScale), ToD2DPoint(command.uvMin, dpiScale), ToD2DPoint(command.uvMax, dpiScale) }; sink->BeginFigure(points[0], D2D1_FIGURE_BEGIN_FILLED); sink->AddLines(points + 1, 2u); sink->EndFigure(D2D1_FIGURE_END_CLOSED); hr = sink->Close(); if (FAILED(hr)) { return; } renderTarget.FillGeometry(geometry.Get(), &solidBrush); } void NativeRenderer::RenderFilledCircleCommand( ID2D1RenderTarget& renderTarget, ID2D1SolidColorBrush& solidBrush, const ::XCEngine::UI::UIDrawCommand& command) { const float dpiScale = ClampDpiScale(m_dpiScale); const float radius = command.radius * dpiScale; renderTarget.FillEllipse( D2D1::Ellipse(ToD2DPoint(command.position, dpiScale), radius, radius), &solidBrush); } void NativeRenderer::RenderCircleOutlineCommand( ID2D1RenderTarget& renderTarget, ID2D1SolidColorBrush& solidBrush, const ::XCEngine::UI::UIDrawCommand& command) { const float dpiScale = ClampDpiScale(m_dpiScale); const float radius = command.radius * dpiScale; const float thickness = (command.thickness > 0.0f ? command.thickness : 1.0f) * dpiScale; renderTarget.DrawEllipse( D2D1::Ellipse(ToD2DPoint(command.position, dpiScale), radius, radius), &solidBrush, thickness); } } // namespace XCEngine::UI::Editor::Host