Files
XCEngine/new_editor/src/XCUIBackend/ImGuiTextAtlasProvider.cpp

224 lines
6.1 KiB
C++
Raw Normal View History

2026-04-05 04:55:25 +08:00
#include "XCUIBackend/ImGuiTextAtlasProvider.h"
#include <imgui.h>
#include <imgui_internal.h>
namespace XCEngine {
namespace Editor {
namespace XCUIBackend {
namespace {
IXCUITextAtlasProvider::FontHandle MakeFontHandle(const ImFont* font) {
IXCUITextAtlasProvider::FontHandle handle = {};
handle.value = reinterpret_cast<std::uintptr_t>(font);
return handle;
}
ImFont* ResolveFontHandle(IXCUITextAtlasProvider::FontHandle handle) {
return reinterpret_cast<ImFont*>(handle.value);
}
ImFontAtlas* ResolveAtlas(::ImGuiContext* context) {
if (context == nullptr) {
return nullptr;
}
return context->IO.Fonts;
}
ImFont* ResolveDefaultFont(::ImGuiContext* context) {
ImFontAtlas* atlas = ResolveAtlas(context);
if (atlas == nullptr) {
return nullptr;
}
ImFont* font = context->IO.FontDefault;
if (font == nullptr && atlas->Fonts.Size > 0) {
font = atlas->Fonts[0];
}
return font;
}
float ResolveNominalFontSize(const ImFont& font) {
return font.LegacySize > 0.0f ? font.LegacySize : 16.0f;
}
float ResolveRequestedFontSize(const ImFont& font, float requestedFontSize) {
return requestedFontSize > 0.0f ? requestedFontSize : ResolveNominalFontSize(font);
}
bool IsFontOwnedByAtlas(const ImFont* font, const ImFontAtlas* atlas) {
return font != nullptr && atlas != nullptr && font->OwnerAtlas == atlas;
}
ImFontBaked* ResolveBakedFont(
IXCUITextAtlasProvider::FontHandle fontHandle,
ImFontAtlas* atlas,
float requestedFontSize) {
ImFont* font = ResolveFontHandle(fontHandle);
if (!IsFontOwnedByAtlas(font, atlas)) {
return nullptr;
}
const float resolvedFontSize = ResolveRequestedFontSize(*font, requestedFontSize);
if (resolvedFontSize <= 0.0f) {
return nullptr;
}
return font->GetFontBaked(resolvedFontSize);
}
} // namespace
ImGuiTextAtlasProvider::ImGuiTextAtlasProvider(::ImGuiContext* context)
: m_context(context) {
}
void ImGuiTextAtlasProvider::SetContext(::ImGuiContext* context) {
m_context = context;
}
::ImGuiContext* ImGuiTextAtlasProvider::GetContext() const {
return m_context;
}
bool ImGuiTextAtlasProvider::GetAtlasTextureView(
PixelFormat preferredFormat,
AtlasTextureView& outView) const {
outView = {};
ImFontAtlas* atlas = ResolveAtlas(ResolveContext());
if (atlas == nullptr) {
return false;
}
unsigned char* pixels = nullptr;
int width = 0;
int height = 0;
int bytesPerPixel = 0;
PixelFormat resolvedFormat = preferredFormat;
switch (preferredFormat) {
case PixelFormat::Alpha8:
atlas->GetTexDataAsAlpha8(&pixels, &width, &height, &bytesPerPixel);
break;
case PixelFormat::RGBA32:
case PixelFormat::Unknown:
default:
atlas->GetTexDataAsRGBA32(&pixels, &width, &height, &bytesPerPixel);
resolvedFormat = PixelFormat::RGBA32;
break;
}
if (pixels == nullptr || width <= 0 || height <= 0 || bytesPerPixel <= 0) {
return false;
}
outView.pixels = pixels;
outView.width = width;
outView.height = height;
outView.stride = width * bytesPerPixel;
outView.bytesPerPixel = bytesPerPixel;
outView.format = resolvedFormat;
outView.atlasStorageKey = reinterpret_cast<std::uintptr_t>(atlas);
outView.pixelDataKey = reinterpret_cast<std::uintptr_t>(pixels);
return true;
}
std::size_t ImGuiTextAtlasProvider::GetFontCount() const {
const ImFontAtlas* atlas = ResolveAtlas(ResolveContext());
return atlas != nullptr ? static_cast<std::size_t>(atlas->Fonts.Size) : 0u;
}
IXCUITextAtlasProvider::FontHandle ImGuiTextAtlasProvider::GetFont(std::size_t index) const {
const ImFontAtlas* atlas = ResolveAtlas(ResolveContext());
if (atlas == nullptr || index >= static_cast<std::size_t>(atlas->Fonts.Size)) {
return {};
}
return MakeFontHandle(atlas->Fonts[static_cast<int>(index)]);
}
IXCUITextAtlasProvider::FontHandle ImGuiTextAtlasProvider::GetDefaultFont() const {
return MakeFontHandle(ResolveDefaultFont(ResolveContext()));
}
bool ImGuiTextAtlasProvider::GetFontInfo(FontHandle fontHandle, FontInfo& outInfo) const {
outInfo = {};
ImFontAtlas* atlas = ResolveAtlas(ResolveContext());
ImFont* font = ResolveFontHandle(fontHandle);
if (!IsFontOwnedByAtlas(font, atlas)) {
return false;
}
outInfo.handle = fontHandle;
outInfo.nominalSize = ResolveNominalFontSize(*font);
return true;
}
bool ImGuiTextAtlasProvider::GetBakedFontInfo(
FontHandle fontHandle,
float fontSize,
BakedFontInfo& outInfo) const {
outInfo = {};
ImFontAtlas* atlas = ResolveAtlas(ResolveContext());
ImFontBaked* bakedFont = ResolveBakedFont(fontHandle, atlas, fontSize);
if (bakedFont == nullptr) {
return false;
}
outInfo.lineHeight = bakedFont->Size;
outInfo.ascent = bakedFont->Ascent;
outInfo.descent = bakedFont->Descent;
outInfo.rasterizerDensity = bakedFont->RasterizerDensity;
return true;
}
bool ImGuiTextAtlasProvider::FindGlyph(
FontHandle fontHandle,
float fontSize,
std::uint32_t codepoint,
GlyphInfo& outInfo) const {
outInfo = {};
if (codepoint > IM_UNICODE_CODEPOINT_MAX) {
return false;
}
ImFontAtlas* atlas = ResolveAtlas(ResolveContext());
ImFontBaked* bakedFont = ResolveBakedFont(fontHandle, atlas, fontSize);
if (bakedFont == nullptr) {
return false;
}
ImFontGlyph* glyph = bakedFont->FindGlyph(static_cast<ImWchar>(codepoint));
if (glyph == nullptr) {
return false;
}
outInfo.requestedCodepoint = codepoint;
outInfo.resolvedCodepoint = glyph->Codepoint;
outInfo.visible = glyph->Visible != 0;
outInfo.colored = glyph->Colored != 0;
outInfo.advanceX = glyph->AdvanceX;
outInfo.x0 = glyph->X0;
outInfo.y0 = glyph->Y0;
outInfo.x1 = glyph->X1;
outInfo.y1 = glyph->Y1;
outInfo.u0 = glyph->U0;
outInfo.v0 = glyph->V0;
outInfo.u1 = glyph->U1;
outInfo.v1 = glyph->V1;
return true;
}
::ImGuiContext* ImGuiTextAtlasProvider::ResolveContext() const {
return m_context;
2026-04-05 04:55:25 +08:00
}
} // namespace XCUIBackend
} // namespace Editor
} // namespace XCEngine