#include "NativeRendererSupport.h" namespace XCEngine::UI::Editor::Host { using namespace NativeRendererSupport; bool NativeRenderer::CaptureToPng( const ::XCEngine::UI::UIDrawData& drawData, UINT width, UINT height, const std::filesystem::path& outputPath, std::string& outError) { outError.clear(); if (width == 0 || height == 0) { outError = "CaptureToPng rejected an empty render size."; return false; } if (!m_d2dFactory || !m_dwriteFactory) { outError = "CaptureToPng requires an initialized NativeRenderer."; return false; } if (!EnsureWicFactory(outError)) { return false; } std::error_code errorCode = {}; std::filesystem::create_directories(outputPath.parent_path(), errorCode); if (errorCode) { outError = "Failed to create screenshot directory: " + outputPath.parent_path().string(); return false; } Microsoft::WRL::ComPtr bitmap; HRESULT hr = m_wicFactory->CreateBitmap( width, height, GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnLoad, bitmap.ReleaseAndGetAddressOf()); if (FAILED(hr)) { outError = HrToString("IWICImagingFactory::CreateBitmap", hr); return false; } const D2D1_RENDER_TARGET_PROPERTIES renderTargetProperties = D2D1::RenderTargetProperties( D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED), kBaseDpi, kBaseDpi); Microsoft::WRL::ComPtr offscreenRenderTarget; hr = m_d2dFactory->CreateWicBitmapRenderTarget( bitmap.Get(), renderTargetProperties, offscreenRenderTarget.ReleaseAndGetAddressOf()); if (FAILED(hr)) { outError = HrToString("ID2D1Factory::CreateWicBitmapRenderTarget", hr); return false; } Microsoft::WRL::ComPtr offscreenBrush; hr = offscreenRenderTarget->CreateSolidColorBrush( D2D1::ColorF(1.0f, 1.0f, 1.0f, 1.0f), offscreenBrush.ReleaseAndGetAddressOf()); if (FAILED(hr)) { outError = HrToString("ID2D1RenderTarget::CreateSolidColorBrush", hr); return false; } const bool rendered = RenderToTarget(*offscreenRenderTarget.Get(), *offscreenBrush.Get(), drawData); hr = offscreenRenderTarget->EndDraw(); if (!rendered || FAILED(hr)) { outError = HrToString("ID2D1RenderTarget::EndDraw", hr); return false; } const std::wstring wideOutputPath = outputPath.wstring(); Microsoft::WRL::ComPtr stream; hr = m_wicFactory->CreateStream(stream.ReleaseAndGetAddressOf()); if (FAILED(hr)) { outError = HrToString("IWICImagingFactory::CreateStream", hr); return false; } hr = stream->InitializeFromFilename(wideOutputPath.c_str(), GENERIC_WRITE); if (FAILED(hr)) { outError = HrToString("IWICStream::InitializeFromFilename", hr); return false; } Microsoft::WRL::ComPtr encoder; hr = m_wicFactory->CreateEncoder(GUID_ContainerFormatPng, nullptr, encoder.ReleaseAndGetAddressOf()); if (FAILED(hr)) { outError = HrToString("IWICImagingFactory::CreateEncoder", hr); return false; } hr = encoder->Initialize(stream.Get(), WICBitmapEncoderNoCache); if (FAILED(hr)) { outError = HrToString("IWICBitmapEncoder::Initialize", hr); return false; } Microsoft::WRL::ComPtr frame; Microsoft::WRL::ComPtr propertyBag; hr = encoder->CreateNewFrame(frame.ReleaseAndGetAddressOf(), propertyBag.ReleaseAndGetAddressOf()); if (FAILED(hr)) { outError = HrToString("IWICBitmapEncoder::CreateNewFrame", hr); return false; } hr = frame->Initialize(propertyBag.Get()); if (FAILED(hr)) { outError = HrToString("IWICBitmapFrameEncode::Initialize", hr); return false; } hr = frame->SetSize(width, height); if (FAILED(hr)) { outError = HrToString("IWICBitmapFrameEncode::SetSize", hr); return false; } WICPixelFormatGUID pixelFormat = GUID_WICPixelFormat32bppPBGRA; hr = frame->SetPixelFormat(&pixelFormat); if (FAILED(hr)) { outError = HrToString("IWICBitmapFrameEncode::SetPixelFormat", hr); return false; } hr = frame->WriteSource(bitmap.Get(), nullptr); if (FAILED(hr)) { outError = HrToString("IWICBitmapFrameEncode::WriteSource", hr); return false; } hr = frame->Commit(); if (FAILED(hr)) { outError = HrToString("IWICBitmapFrameEncode::Commit", hr); return false; } hr = encoder->Commit(); if (FAILED(hr)) { outError = HrToString("IWICBitmapEncoder::Commit", hr); return false; } return true; } } // namespace XCEngine::UI::Editor::Host