#pragma once #ifndef NOMINMAX #define NOMINMAX #endif #include #include #include #include #include #include #include #include #include namespace XCEngine::UI::Editor::Host { class D3D12UiTextSystem final : public ::XCEngine::UI::Editor::UIEditorTextMeasurer { public: struct RasterizedTextRun { std::vector rgbaPixels = {}; UINT width = 0u; UINT height = 0u; float offsetX = 0.0f; float offsetY = 0.0f; }; struct ShapedGlyph { Microsoft::WRL::ComPtr fontFace = {}; std::uint16_t glyphIndex = 0u; float fontEmSize = 0.0f; float originX = 0.0f; float originY = 0.0f; DWRITE_MEASURING_MODE measuringMode = DWRITE_MEASURING_MODE_NATURAL; bool isSideways = false; }; struct ShapedTextRun { std::vector glyphs = {}; float width = 0.0f; float height = 0.0f; }; struct RasterizedGlyph { std::vector rgbaPixels = {}; UINT width = 0u; UINT height = 0u; LONG boundsLeft = 0; LONG boundsTop = 0; LONG boundsRight = 0; LONG boundsBottom = 0; }; bool Initialize(); void Shutdown(); void SetDpiScale(float dpiScale); float GetDpiScale() const; const std::string& GetLastError() const; float MeasureTextWidth( const ::XCEngine::UI::Editor::UIEditorTextMeasureRequest& request) const override; float MeasureTextAdvance( const ::XCEngine::UI::Editor::UIEditorTextMeasureRequest& request) const override; bool ShapeTextRun( std::string_view text, float fontSize, ShapedTextRun& outRun, std::string& outError) const; bool RasterizeGlyph( const ShapedGlyph& glyph, RasterizedGlyph& outGlyph, std::string& outError) const; bool RasterizeTextMask( std::string_view text, float fontSize, RasterizedTextRun& outRun, std::string& outError); private: IDWriteTextFormat* GetTextFormat(float fontSize) const; static std::wstring Utf8ToWide(std::string_view text); Microsoft::WRL::ComPtr m_dwriteFactory = {}; mutable std::unordered_map> m_textFormats = {}; float m_dpiScale = 1.0f; std::string m_lastError = {}; }; } // namespace XCEngine::UI::Editor::Host