#pragma once #include "NativeRenderer.h" #include #include #include namespace XCEngine::UI::Editor::Host::NativeRendererSupport { inline constexpr float kBaseDpi = 96.0f; inline constexpr float kDefaultFontSize = 16.0f; inline std::string HrToString(const char* operation, HRESULT hr) { char buffer[128] = {}; sprintf_s(buffer, "%s failed with hr=0x%08X.", operation, static_cast(hr)); return buffer; } inline float ClampDpiScale(float dpiScale) { return dpiScale > 0.0f ? dpiScale : 1.0f; } inline float ResolveFontSize(float fontSize) { return fontSize > 0.0f ? fontSize : kDefaultFontSize; } inline float SnapToPixel(float value, float dpiScale) { const float scale = ClampDpiScale(dpiScale); return std::round(value * scale); } inline D2D1_RECT_F ToD2DRect(const ::XCEngine::UI::UIRect& rect, float dpiScale) { const float left = SnapToPixel(rect.x, dpiScale); const float top = SnapToPixel(rect.y, dpiScale); const float right = SnapToPixel(rect.x + rect.width, dpiScale); const float bottom = SnapToPixel(rect.y + rect.height, dpiScale); return D2D1::RectF(left, top, right, bottom); } inline D2D1_POINT_2F ToD2DPoint( const ::XCEngine::UI::UIPoint& point, float dpiScale, float pixelOffset = 0.0f) { return D2D1::Point2F( SnapToPixel(point.x, dpiScale) + pixelOffset, SnapToPixel(point.y, dpiScale) + pixelOffset); } inline float ResolveStrokePixelOffset(float thickness) { const float roundedThickness = std::round(thickness); return std::fmod(roundedThickness, 2.0f) == 1.0f ? 0.5f : 0.0f; } inline D2D1_BITMAP_PROPERTIES1 BuildD2DBitmapProperties( DXGI_FORMAT format, D2D1_BITMAP_OPTIONS options, D2D1_ALPHA_MODE alphaMode = D2D1_ALPHA_MODE_IGNORE) { return D2D1::BitmapProperties1( options, D2D1::PixelFormat(format, alphaMode), kBaseDpi, kBaseDpi); } inline bool IsInteropTextureHandle(const ::XCEngine::UI::UITextureHandle& texture) { return texture.kind == ::XCEngine::UI::UITextureHandleKind::ShaderResourceView && texture.resourceHandle != 0u; } inline void CollectInteropTextureHandles( const ::XCEngine::UI::UIDrawData& drawData, std::vector<::XCEngine::UI::UITextureHandle>& outTextures) { outTextures.clear(); std::unordered_set seenKeys = {}; for (const ::XCEngine::UI::UIDrawList& drawList : drawData.GetDrawLists()) { for (const ::XCEngine::UI::UIDrawCommand& command : drawList.GetCommands()) { if (!IsInteropTextureHandle(command.texture) || !seenKeys.insert(command.texture.resourceHandle).second) { continue; } outTextures.push_back(command.texture); } } } } // namespace XCEngine::UI::Editor::Host::NativeRendererSupport