mirror of
https://github.com/ocornut/imgui.git
synced 2025-09-05 19:08:19 +00:00
Fonts: fixed support for multiple atlases.
Moved FontAtlasOwnedByContext to OwnerContext # Conflicts: # imgui.cpp # imgui_internal.h
This commit is contained in:
91
imgui.cpp
91
imgui.cpp
@@ -3962,13 +3962,13 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
|
||||
InputTextState.Ctx = this;
|
||||
|
||||
Initialized = false;
|
||||
FontAtlasOwnedByContext = shared_font_atlas ? false : true;
|
||||
Font = NULL;
|
||||
FontBaked = NULL;
|
||||
FontSize = FontSizeBeforeScaling = FontScale = CurrentDpiScale = 0.0f;
|
||||
FontRasterizerDensity = 1.0f;
|
||||
IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
|
||||
IO.Fonts->RefCount++;
|
||||
if (shared_font_atlas == NULL)
|
||||
IO.Fonts->OwnerContext = this;
|
||||
Time = 0.0f;
|
||||
FrameCount = 0;
|
||||
FrameCountEnded = FrameCountRendered = -1;
|
||||
@@ -4226,8 +4226,9 @@ void ImGui::Initialize()
|
||||
|
||||
// ImDrawList/ImFontAtlas are designed to function without ImGui, and 99% of it works without an ImGui context.
|
||||
// But this link allows us to facilitate/handle a few edge cases better.
|
||||
ImFontAtlas* atlas = g.IO.Fonts;
|
||||
g.DrawListSharedData.Context = &g;
|
||||
ImFontAtlasAddDrawListSharedData(g.IO.Fonts, &g.DrawListSharedData);
|
||||
RegisterFontAtlas(atlas);
|
||||
|
||||
g.Initialized = true;
|
||||
}
|
||||
@@ -4240,17 +4241,15 @@ void ImGui::Shutdown()
|
||||
IM_ASSERT_USER_ERROR(g.IO.BackendRendererUserData == NULL, "Forgot to shutdown Renderer backend?");
|
||||
|
||||
// The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame)
|
||||
if (ImFontAtlas* atlas = g.IO.Fonts)
|
||||
for (ImFontAtlas* atlas : g.FontAtlases)
|
||||
{
|
||||
ImFontAtlasRemoveDrawListSharedData(atlas, &g.DrawListSharedData);
|
||||
atlas->RefCount--;
|
||||
if (g.FontAtlasOwnedByContext)
|
||||
UnregisterFontAtlas(atlas);
|
||||
if (atlas->OwnerContext == &g)
|
||||
{
|
||||
atlas->Locked = false;
|
||||
IM_DELETE(atlas);
|
||||
}
|
||||
}
|
||||
g.IO.Fonts = NULL;
|
||||
g.DrawListSharedData.TempBuffer.clear();
|
||||
|
||||
// Cleanup of other data are conditional on actually having initialized Dear ImGui.
|
||||
@@ -4412,7 +4411,8 @@ void ImGui::GcCompactTransientMiscBuffers()
|
||||
g.MultiSelectTempDataStacked = 0;
|
||||
g.MultiSelectTempData.clear_destruct();
|
||||
TableGcCompactSettings();
|
||||
g.IO.Fonts->CompactCache();
|
||||
for (ImFontAtlas* atlas : g.FontAtlases)
|
||||
atlas->CompactCache();
|
||||
}
|
||||
|
||||
// Free up/compact internal window buffers, we can use this when a window becomes unused.
|
||||
@@ -5210,29 +5210,27 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags(const ImVec2& mouse_pos)
|
||||
static void ImGui::UpdateTexturesNewFrame()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImFontAtlas* atlas = g.IO.Fonts;
|
||||
if (g.FontAtlasOwnedByContext)
|
||||
{
|
||||
atlas->RendererHasTextures = (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures) != 0;
|
||||
ImFontAtlasUpdateNewFrame(atlas, g.FrameCount);
|
||||
}
|
||||
for (ImFontAtlas* atlas : g.FontAtlases)
|
||||
if (atlas->OwnerContext == &g)
|
||||
{
|
||||
atlas->RendererHasTextures = (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures) != 0;
|
||||
ImFontAtlasUpdateNewFrame(atlas, g.FrameCount);
|
||||
}
|
||||
}
|
||||
|
||||
// Build a single texture list
|
||||
// We want to avoid user reading from atlas->TexList[] in order to facilitate better support for multiple atlases.
|
||||
static void ImGui::UpdateTexturesEndFrame()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImFontAtlas* atlas = g.IO.Fonts;
|
||||
g.PlatformIO.Textures.resize(0);
|
||||
g.PlatformIO.Textures.reserve(atlas->TexList.Size);
|
||||
for (ImTextureData* tex : atlas->TexList)
|
||||
{
|
||||
// We provide this information so backends can decide whether to destroy textures.
|
||||
// This means in practice that if N imgui contexts are created with a shared atlas, we assume all of them have a backend initialized.
|
||||
tex->RefCount = (unsigned short)atlas->RefCount;
|
||||
g.PlatformIO.Textures.push_back(tex);
|
||||
}
|
||||
for (ImFontAtlas* atlas : g.FontAtlases)
|
||||
for (ImTextureData* tex : atlas->TexList)
|
||||
{
|
||||
// We provide this information so backends can decide whether to destroy textures.
|
||||
// This means in practice that if N imgui contexts are created with a shared atlas, we assume all of them have a backend initialized.
|
||||
tex->RefCount = (unsigned short)atlas->RefCount;
|
||||
g.PlatformIO.Textures.push_back(tex);
|
||||
}
|
||||
}
|
||||
|
||||
// Called once a frame. Followed by SetCurrentFont() which sets up the remaining data.
|
||||
@@ -5810,8 +5808,8 @@ void ImGui::EndFrame()
|
||||
UpdateTexturesEndFrame();
|
||||
|
||||
// Unlock font atlas
|
||||
ImFontAtlas* atlas = g.IO.Fonts;
|
||||
atlas->Locked = false;
|
||||
for (ImFontAtlas* atlas : g.FontAtlases)
|
||||
atlas->Locked = false;
|
||||
|
||||
// Clear Input data for next frame
|
||||
g.IO.MousePosPrev = g.IO.MousePos;
|
||||
@@ -5890,7 +5888,8 @@ void ImGui::Render()
|
||||
|
||||
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
||||
if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures)
|
||||
ImFontAtlasDebugLogTextureRequests(g.IO.Fonts);
|
||||
for (ImFontAtlas* atlas : g.FontAtlases)
|
||||
ImFontAtlasDebugLogTextureRequests(atlas);
|
||||
#endif
|
||||
|
||||
CallContextHooks(&g, ImGuiContextHookType_RenderPost);
|
||||
@@ -8596,9 +8595,9 @@ bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max)
|
||||
void ImGui::UpdateFontsNewFrame()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImFontAtlas* atlas = g.IO.Fonts;
|
||||
if ((g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures) == 0)
|
||||
atlas->Locked = true;
|
||||
for (ImFontAtlas* atlas : g.FontAtlases)
|
||||
atlas->Locked = true;
|
||||
|
||||
// We do this really unusual thing of calling *push_front()*, the reason behind that we want to support the PushFont()/NewFrame()/PopFont() idiom.
|
||||
ImFontStackData font_stack_data = { ImGui::GetDefaultFont(), ImGui::GetDefaultFont()->DefaultSize };
|
||||
@@ -8614,6 +8613,25 @@ void ImGui::UpdateFontsEndFrame()
|
||||
PopFont();
|
||||
}
|
||||
|
||||
void ImGui::RegisterFontAtlas(ImFontAtlas* atlas)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.FontAtlases.Size == 0)
|
||||
IM_ASSERT(atlas == g.IO.Fonts);
|
||||
atlas->RefCount++;
|
||||
g.FontAtlases.push_back(atlas);
|
||||
ImFontAtlasAddDrawListSharedData(atlas, &g.DrawListSharedData);
|
||||
}
|
||||
|
||||
void ImGui::UnregisterFontAtlas(ImFontAtlas* atlas)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(atlas->RefCount > 0);
|
||||
ImFontAtlasRemoveDrawListSharedData(atlas, &g.DrawListSharedData);
|
||||
g.FontAtlases.find_erase(atlas);
|
||||
atlas->RefCount--;
|
||||
}
|
||||
|
||||
// Use ImDrawList::_SetTexture(), making our shared g.FontStack[] authoritative against window-local ImDrawList.
|
||||
// - Whereas ImDrawList::PushTexture()/PopTexture() is not to be used across Begin() calls.
|
||||
// - Note that we don't propagate current texture id when e.g. Begin()-ing into a new window, we never really did...
|
||||
@@ -8670,6 +8688,7 @@ void ImGui::UpdateCurrentFontSize()
|
||||
void ImGui::SetFontRasterizerDensity(float rasterizer_density)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures);
|
||||
if (g.FontRasterizerDensity == rasterizer_density)
|
||||
return;
|
||||
g.FontRasterizerDensity = rasterizer_density;
|
||||
@@ -16104,12 +16123,12 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
}
|
||||
|
||||
// Details for Fonts
|
||||
ImFontAtlas* atlas = g.IO.Fonts;
|
||||
if (TreeNode("Fonts", "Fonts (%d), Textures (%d)", atlas->Fonts.Size, atlas->TexList.Size))
|
||||
{
|
||||
ShowFontAtlas(atlas);
|
||||
TreePop();
|
||||
}
|
||||
for (ImFontAtlas* atlas : g.FontAtlases)
|
||||
if (TreeNode((void*)atlas, "Fonts (%d), Textures (%d)", atlas->Fonts.Size, atlas->TexList.Size))
|
||||
{
|
||||
ShowFontAtlas(atlas);
|
||||
TreePop();
|
||||
}
|
||||
|
||||
// Details for Popups
|
||||
if (TreeNode("Popups", "Popups (%d)", g.OpenPopupStack.Size))
|
||||
|
1
imgui.h
1
imgui.h
@@ -3684,6 +3684,7 @@ struct ImFontAtlas
|
||||
void* FontLoaderData; // Font backend opaque storage
|
||||
unsigned int FontBuilderFlags; // [FIXME: Should be called FontLoaderFlags] Shared flags (for all fonts) for font loader. THIS IS BUILD IMPLEMENTATION DEPENDENT (e.g. . Per-font override is also available in ImFontConfig.
|
||||
int RefCount; // Number of contexts using this atlas
|
||||
ImGuiContext* OwnerContext; // Context which own the atlas will be in charge of updating and destroying it.
|
||||
|
||||
// [Obsolete]
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
|
@@ -2132,10 +2132,10 @@ struct ImGuiContextHook
|
||||
struct ImGuiContext
|
||||
{
|
||||
bool Initialized;
|
||||
bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it.
|
||||
ImGuiIO IO;
|
||||
ImGuiPlatformIO PlatformIO;
|
||||
ImGuiStyle Style;
|
||||
ImVector<ImFontAtlas*> FontAtlases; // List of font atlases used by the context (generally only contains g.IO.Fonts aka the main font atlas)
|
||||
ImFont* Font; // == FontStack.back().Font
|
||||
ImFontBaked* FontBaked; // == Font->GetFontBaked(FontSize)
|
||||
float FontSize; // == FontSizeBeforeScaling * io.FontGlobalScale * font->Scale * g.CurrentWindow->FontWindowScale. Current text height.
|
||||
@@ -3108,6 +3108,8 @@ namespace ImGui
|
||||
IMGUI_API void SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags);
|
||||
|
||||
// Fonts, drawing
|
||||
IMGUI_API void RegisterFontAtlas(ImFontAtlas* atlas);
|
||||
IMGUI_API void UnregisterFontAtlas(ImFontAtlas* atlas);
|
||||
IMGUI_API void SetCurrentFont(ImFont* font, float font_size);
|
||||
IMGUI_API void SetFontRasterizerDensity(float rasterizer_density);
|
||||
inline float GetFontRasterizerDensity() { return GImGui->FontRasterizerDensity; }
|
||||
|
Reference in New Issue
Block a user