224 lines
6.1 KiB
C++
224 lines
6.1 KiB
C++
#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;
|
|
}
|
|
|
|
} // namespace XCUIBackend
|
|
} // namespace Editor
|
|
} // namespace XCEngine
|