Add XCUI new editor sandbox phase 1
This commit is contained in:
222
new_editor/src/XCUIBackend/XCUIStandaloneTextAtlasProvider.cpp
Normal file
222
new_editor/src/XCUIBackend/XCUIStandaloneTextAtlasProvider.cpp
Normal file
@@ -0,0 +1,222 @@
|
||||
#include "XCUIBackend/XCUIStandaloneTextAtlasProvider.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);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
XCUIStandaloneTextAtlasProvider::XCUIStandaloneTextAtlasProvider() {
|
||||
RebuildDefaultEditorAtlas();
|
||||
}
|
||||
|
||||
void XCUIStandaloneTextAtlasProvider::Reset() {
|
||||
m_atlas.Clear();
|
||||
m_defaultFont = nullptr;
|
||||
m_ready = false;
|
||||
}
|
||||
|
||||
bool XCUIStandaloneTextAtlasProvider::RebuildDefaultEditorAtlas() {
|
||||
Reset();
|
||||
m_ready = BuildDefaultXCUIEditorFontAtlas(m_atlas, m_defaultFont);
|
||||
return m_ready;
|
||||
}
|
||||
|
||||
bool XCUIStandaloneTextAtlasProvider::IsReady() const {
|
||||
return m_ready && ResolveDefaultFont() != nullptr;
|
||||
}
|
||||
|
||||
bool XCUIStandaloneTextAtlasProvider::GetAtlasTextureView(
|
||||
PixelFormat preferredFormat,
|
||||
AtlasTextureView& outView) const {
|
||||
outView = {};
|
||||
|
||||
ImFontAtlas* atlas = ResolveAtlas();
|
||||
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);
|
||||
resolvedFormat = PixelFormat::Alpha8;
|
||||
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 XCUIStandaloneTextAtlasProvider::GetFontCount() const {
|
||||
const ImFontAtlas* atlas = ResolveAtlas();
|
||||
return atlas != nullptr ? static_cast<std::size_t>(atlas->Fonts.Size) : 0u;
|
||||
}
|
||||
|
||||
IXCUITextAtlasProvider::FontHandle XCUIStandaloneTextAtlasProvider::GetFont(std::size_t index) const {
|
||||
const ImFontAtlas* atlas = ResolveAtlas();
|
||||
if (atlas == nullptr || index >= static_cast<std::size_t>(atlas->Fonts.Size)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return MakeFontHandle(atlas->Fonts[static_cast<int>(index)]);
|
||||
}
|
||||
|
||||
IXCUITextAtlasProvider::FontHandle XCUIStandaloneTextAtlasProvider::GetDefaultFont() const {
|
||||
return MakeFontHandle(ResolveDefaultFont());
|
||||
}
|
||||
|
||||
bool XCUIStandaloneTextAtlasProvider::GetFontInfo(FontHandle fontHandle, FontInfo& outInfo) const {
|
||||
outInfo = {};
|
||||
|
||||
ImFontAtlas* atlas = ResolveAtlas();
|
||||
ImFont* font = ResolveFontHandle(fontHandle);
|
||||
if (!IsFontOwnedByAtlas(font, atlas)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
outInfo.handle = fontHandle;
|
||||
outInfo.nominalSize = ResolveNominalFontSize(*font);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XCUIStandaloneTextAtlasProvider::GetBakedFontInfo(
|
||||
FontHandle fontHandle,
|
||||
float fontSize,
|
||||
BakedFontInfo& outInfo) const {
|
||||
outInfo = {};
|
||||
|
||||
ImFontBaked* bakedFont = ResolveBakedFont(fontHandle, ResolveAtlas(), 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 XCUIStandaloneTextAtlasProvider::FindGlyph(
|
||||
FontHandle fontHandle,
|
||||
float fontSize,
|
||||
std::uint32_t codepoint,
|
||||
GlyphInfo& outInfo) const {
|
||||
outInfo = {};
|
||||
|
||||
if (codepoint > IM_UNICODE_CODEPOINT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ImFontBaked* bakedFont = ResolveBakedFont(fontHandle, ResolveAtlas(), 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;
|
||||
}
|
||||
|
||||
::ImFontAtlas* XCUIStandaloneTextAtlasProvider::ResolveAtlas() const {
|
||||
return m_ready ? &m_atlas : nullptr;
|
||||
}
|
||||
|
||||
::ImFont* XCUIStandaloneTextAtlasProvider::ResolveDefaultFont() const {
|
||||
ImFontAtlas* atlas = ResolveAtlas();
|
||||
if (atlas == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (IsFontOwnedByAtlas(m_defaultFont, atlas)) {
|
||||
return m_defaultFont;
|
||||
}
|
||||
|
||||
return atlas->Fonts.empty() ? nullptr : atlas->Fonts[0];
|
||||
}
|
||||
|
||||
} // namespace XCUIBackend
|
||||
} // namespace Editor
|
||||
} // namespace XCEngine
|
||||
Reference in New Issue
Block a user