Files
XCEngine/new_editor/app/Rendering/Native/NativeRendererText.cpp

123 lines
3.4 KiB
C++
Raw Normal View History

#include "NativeRendererSupport.h"
#include <algorithm>
#include <cmath>
namespace XCEngine::UI::Editor::Host {
using namespace NativeRendererSupport;
float NativeRenderer::MeasureTextWidth(
const ::XCEngine::UI::Editor::UIEditorTextMeasureRequest& request) const {
if (!m_dwriteFactory || request.text.empty()) {
return 0.0f;
}
const std::wstring text = Utf8ToWide(request.text);
if (text.empty()) {
return 0.0f;
}
const float dpiScale = ClampDpiScale(m_dpiScale);
const float scaledFontSize = ResolveFontSize(request.fontSize) * dpiScale;
IDWriteTextFormat* textFormat = GetTextFormat(scaledFontSize);
if (textFormat == nullptr) {
return 0.0f;
}
Microsoft::WRL::ComPtr<IDWriteTextLayout> textLayout;
HRESULT hr = m_dwriteFactory->CreateTextLayout(
text.c_str(),
static_cast<UINT32>(text.size()),
textFormat,
4096.0f,
scaledFontSize * 2.0f,
textLayout.ReleaseAndGetAddressOf());
if (FAILED(hr) || !textLayout) {
return 0.0f;
}
DWRITE_TEXT_METRICS textMetrics = {};
hr = textLayout->GetMetrics(&textMetrics);
if (FAILED(hr)) {
return 0.0f;
}
DWRITE_OVERHANG_METRICS overhangMetrics = {};
float width = textMetrics.widthIncludingTrailingWhitespace;
if (SUCCEEDED(textLayout->GetOverhangMetrics(&overhangMetrics))) {
width += (std::max)(overhangMetrics.left, 0.0f);
width += (std::max)(overhangMetrics.right, 0.0f);
}
return std::ceil(width) / dpiScale;
}
IDWriteTextFormat* NativeRenderer::GetTextFormat(float fontSize) const {
if (!m_dwriteFactory) {
return nullptr;
}
const float resolvedFontSize = ResolveFontSize(fontSize);
const int key = static_cast<int>(std::lround(resolvedFontSize * 10.0f));
const auto found = m_textFormats.find(key);
if (found != m_textFormats.end()) {
return found->second.Get();
}
Microsoft::WRL::ComPtr<IDWriteTextFormat> textFormat;
const HRESULT hr = m_dwriteFactory->CreateTextFormat(
L"Segoe UI",
nullptr,
DWRITE_FONT_WEIGHT_REGULAR,
DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
resolvedFontSize,
L"",
textFormat.ReleaseAndGetAddressOf());
if (FAILED(hr)) {
return nullptr;
}
textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);
textFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR);
textFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
IDWriteTextFormat* result = textFormat.Get();
m_textFormats.emplace(key, std::move(textFormat));
return result;
}
D2D1_COLOR_F NativeRenderer::ToD2DColor(const ::XCEngine::UI::UIColor& color) {
return D2D1::ColorF(color.r, color.g, color.b, color.a);
}
std::wstring NativeRenderer::Utf8ToWide(std::string_view text) {
if (text.empty()) {
return {};
}
const int sizeNeeded = MultiByteToWideChar(
CP_UTF8,
0,
text.data(),
static_cast<int>(text.size()),
nullptr,
0);
if (sizeNeeded <= 0) {
return {};
}
std::wstring wideText(static_cast<size_t>(sizeNeeded), L'\0');
MultiByteToWideChar(
CP_UTF8,
0,
text.data(),
static_cast<int>(text.size()),
wideText.data(),
sizeNeeded);
return wideText;
}
} // namespace XCEngine::UI::Editor::Host