#pragma once #ifndef NOMINMAX #define NOMINMAX #endif #include "D3D12WindowInteropContext.h" #include "D3D12WindowRenderer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace XCEngine::UI::Editor::Host { class NativeRenderer : public ::XCEngine::UI::Editor::UIEditorTextMeasurer { public: bool Initialize(HWND hwnd); void Shutdown(); void SetDpiScale(float dpiScale); float GetDpiScale() const; void Resize(UINT width, UINT height); bool AttachWindowRenderer(D3D12WindowRenderer& windowRenderer); void DetachWindowRenderer(); void ReleaseWindowRendererBackBufferTargets(); bool RebuildWindowRendererBackBufferTargets(); bool HasAttachedWindowRenderer() const; bool Render(const ::XCEngine::UI::UIDrawData& drawData); bool RenderToWindowRenderer(const ::XCEngine::UI::UIDrawData& drawData); const std::string& GetLastRenderError() const; bool LoadTextureFromFile( const std::filesystem::path& path, ::XCEngine::UI::UITextureHandle& outTexture, std::string& outError); void ReleaseTexture(::XCEngine::UI::UITextureHandle& texture); float MeasureTextWidth( const ::XCEngine::UI::Editor::UIEditorTextMeasureRequest& request) const override; bool CaptureToPng( const ::XCEngine::UI::UIDrawData& drawData, UINT width, UINT height, const std::filesystem::path& outputPath, std::string& outError); private: struct NativeTextureResource { std::vector pixels = {}; Microsoft::WRL::ComPtr cachedBitmap = {}; const ID2D1RenderTarget* cachedTarget = nullptr; UINT width = 0u; UINT height = 0u; }; bool EnsureRenderTarget(); bool EnsureWindowRendererInterop(); bool EnsureWicFactory(std::string& outError); void DiscardRenderTarget(); bool CreateDeviceResources(); void ReleaseWindowRendererInterop(); void InvalidateCachedTextureBitmaps(const ID2D1RenderTarget* renderTarget); bool RenderToTarget( ID2D1RenderTarget& renderTarget, ID2D1SolidColorBrush& solidBrush, const ::XCEngine::UI::UIDrawData& drawData); bool DecodeTextureFile( const std::filesystem::path& path, NativeTextureResource& outTexture, std::string& outError); bool ResolveTextureBitmap( ID2D1RenderTarget& renderTarget, NativeTextureResource& texture, Microsoft::WRL::ComPtr& outBitmap); bool ResolveInteropBitmap( const ::XCEngine::UI::UITextureHandle& texture, Microsoft::WRL::ComPtr& outBitmap) const; void RenderCommand( ID2D1RenderTarget& renderTarget, ID2D1SolidColorBrush& solidBrush, const ::XCEngine::UI::UIDrawCommand& command, std::vector& clipStack); IDWriteTextFormat* GetTextFormat(float fontSize) const; static D2D1_COLOR_F ToD2DColor(const ::XCEngine::UI::UIColor& color); static std::wstring Utf8ToWide(std::string_view text); HWND m_hwnd = nullptr; D3D12WindowRenderer* m_windowRenderer = nullptr; Microsoft::WRL::ComPtr m_d2dFactory; Microsoft::WRL::ComPtr m_dwriteFactory; Microsoft::WRL::ComPtr m_wicFactory; Microsoft::WRL::ComPtr m_renderTarget; Microsoft::WRL::ComPtr m_solidBrush; mutable std::unordered_map> m_textFormats; std::unordered_set m_liveTextures; D3D12WindowInteropContext m_windowInterop = {}; std::string m_lastRenderError = {}; bool m_wicComInitialized = false; float m_dpiScale = 1.0f; }; } // namespace XCEngine::UI::Editor::Host