Skip to content

Commit eb7201b

Browse files
committed
Fonts: Made it possible to use PushFont()/PopFont() calls accross Begin() calls. (#3224, #3875, #6398, #7903)
1 parent ecb1962 commit eb7201b

File tree

4 files changed

+27
-7
lines changed

4 files changed

+27
-7
lines changed

docs/CHANGELOG.txt

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ Other changes:
5151
- MultiSelect+TreeNode: default open behavior is OpenOnDoubleClick + OpenOnArrow
5252
when used in a multi-select context without any OpenOnXXX flags set. (#7850)
5353
- TextLink(), TextLinkOpenURL(): change mouse cursor to Hand shape when hovered. (#7885, #7660)
54+
- Fonts: Made it possible to use PushFont()/PopFont() calls accross Begin() calls. (#3224, #3875, #6398, #7903)
5455
- Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper function because GLFW does not
5556
provide a way to do a portable sleep. (#7844)
5657
- Backends: SDL2, SDL3: ignore events of other SDL windows. (#7853) [@madebr, @ocornut]

imgui.cpp

+16-5
Original file line numberDiff line numberDiff line change
@@ -5068,6 +5068,8 @@ static void InitViewportDrawData(ImGuiViewportP* viewport)
50685068
// - If the code here changes, may need to update code of functions like NextColumn() and PushColumnClipRect():
50695069
// some frequently called functions which to modify both channels and clipping simultaneously tend to use the
50705070
// more specialized SetWindowClipRectBeforeSetChannel() to avoid extraneous updates of underlying ImDrawCmds.
5071+
// - This is analoguous to PushFont()/PopFont() in the sense that are a mixing a global stack and a window stack,
5072+
// which in the case of ClipRect is not so problematic but tends to be more restrictive for fonts.
50715073
void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect)
50725074
{
50735075
ImGuiWindow* window = GetCurrentWindow();
@@ -7574,22 +7576,31 @@ void ImGui::SetCurrentFont(ImFont* font)
75747576
g.DrawListSharedData.FontScale = g.FontScale;
75757577
}
75767578

7579+
// Use ImDrawList::_SetTextureID(), making our shared g.FontStack[] authorative against window-local ImDrawList.
7580+
// - Whereas ImDrawList::PushTextureID()/PopTextureID() is not to be used across Begin() calls.
7581+
// - Note that we don't propagate current texture id when e.g. Begin()-ing into a new window, we never really did...
7582+
// - Some code paths never really fully worked with multiple atlas textures.
7583+
// - The right-ish solution may be to remove _SetTextureID() and make AddText/RenderText lazily call PushTextureID()/PopTextureID()
7584+
// the same way AddImage() does, but then all other primitives would also need to? I don't think we should tackle this problem
7585+
// because we have a concrete need and a test bed for multiple atlas textures.
75777586
void ImGui::PushFont(ImFont* font)
75787587
{
75797588
ImGuiContext& g = *GImGui;
7580-
if (!font)
7589+
if (font == NULL)
75817590
font = GetDefaultFont();
7582-
SetCurrentFont(font);
75837591
g.FontStack.push_back(font);
7584-
g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID);
7592+
SetCurrentFont(font);
7593+
g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID);
75857594
}
75867595

75877596
void ImGui::PopFont()
75887597
{
75897598
ImGuiContext& g = *GImGui;
7590-
g.CurrentWindow->DrawList->PopTextureID();
7599+
IM_ASSERT(g.FontStack.Size > 0);
75917600
g.FontStack.pop_back();
7592-
SetCurrentFont(g.FontStack.empty() ? GetDefaultFont() : g.FontStack.back());
7601+
ImFont* font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back();
7602+
SetCurrentFont(font);
7603+
g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID);
75937604
}
75947605

75957606
void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled)

imgui.h

+1
Original file line numberDiff line numberDiff line change
@@ -3152,6 +3152,7 @@ struct ImDrawList
31523152
IMGUI_API void _OnChangedClipRect();
31533153
IMGUI_API void _OnChangedTextureID();
31543154
IMGUI_API void _OnChangedVtxOffset();
3155+
IMGUI_API void _SetTextureID(ImTextureID texture_id);
31553156
IMGUI_API int _CalcCircleAutoSegmentCount(float radius) const;
31563157
IMGUI_API void _PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step);
31573158
IMGUI_API void _PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments);

imgui_draw.cpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,6 @@ void ImDrawList::_OnChangedClipRect()
526526
CmdBuffer.pop_back();
527527
return;
528528
}
529-
530529
curr_cmd->ClipRect = _CmdHeader.ClipRect;
531530
}
532531

@@ -549,7 +548,6 @@ void ImDrawList::_OnChangedTextureID()
549548
CmdBuffer.pop_back();
550549
return;
551550
}
552-
553551
curr_cmd->TextureId = _CmdHeader.TextureId;
554552
}
555553

@@ -625,6 +623,15 @@ void ImDrawList::PopTextureID()
625623
_OnChangedTextureID();
626624
}
627625

626+
// This is used by ImGui::PushFont()/PopFont(). It works because we never use _TextureIdStack[] elsewhere than in PushTextureID()/PopTextureID().
627+
void ImDrawList::_SetTextureID(ImTextureID texture_id)
628+
{
629+
if (_CmdHeader.TextureId == texture_id)
630+
return;
631+
_CmdHeader.TextureId = texture_id;
632+
_OnChangedTextureID();
633+
}
634+
628635
// Reserve space for a number of vertices and indices.
629636
// You must finish filling your reserved data before calling PrimReserve() again, as it may reallocate or
630637
// submit the intermediate results. PrimUnreserve() can be used to release unused allocations.

0 commit comments

Comments
 (0)