Skip to content

Commit

Permalink
Fonts: Made it possible to use PushFont()/PopFont() calls accross Beg…
Browse files Browse the repository at this point in the history
…in() calls. (#3224, #3875, #6398, #7903)
  • Loading branch information
ocornut committed Aug 20, 2024
1 parent ecb1962 commit eb7201b
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 7 deletions.
1 change: 1 addition & 0 deletions docs/CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Other changes:
- MultiSelect+TreeNode: default open behavior is OpenOnDoubleClick + OpenOnArrow
when used in a multi-select context without any OpenOnXXX flags set. (#7850)
- TextLink(), TextLinkOpenURL(): change mouse cursor to Hand shape when hovered. (#7885, #7660)
- Fonts: Made it possible to use PushFont()/PopFont() calls accross Begin() calls. (#3224, #3875, #6398, #7903)
- Backends: GLFW: added ImGui_ImplGlfw_Sleep() helper function because GLFW does not
provide a way to do a portable sleep. (#7844)
- Backends: SDL2, SDL3: ignore events of other SDL windows. (#7853) [@madebr, @ocornut]
Expand Down
21 changes: 16 additions & 5 deletions imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5068,6 +5068,8 @@ static void InitViewportDrawData(ImGuiViewportP* viewport)
// - If the code here changes, may need to update code of functions like NextColumn() and PushColumnClipRect():
// some frequently called functions which to modify both channels and clipping simultaneously tend to use the
// more specialized SetWindowClipRectBeforeSetChannel() to avoid extraneous updates of underlying ImDrawCmds.
// - This is analoguous to PushFont()/PopFont() in the sense that are a mixing a global stack and a window stack,
// which in the case of ClipRect is not so problematic but tends to be more restrictive for fonts.
void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect)
{
ImGuiWindow* window = GetCurrentWindow();
Expand Down Expand Up @@ -7574,22 +7576,31 @@ void ImGui::SetCurrentFont(ImFont* font)
g.DrawListSharedData.FontScale = g.FontScale;
}

// Use ImDrawList::_SetTextureID(), making our shared g.FontStack[] authorative against window-local ImDrawList.
// - Whereas ImDrawList::PushTextureID()/PopTextureID() 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...
// - Some code paths never really fully worked with multiple atlas textures.
// - The right-ish solution may be to remove _SetTextureID() and make AddText/RenderText lazily call PushTextureID()/PopTextureID()
// the same way AddImage() does, but then all other primitives would also need to? I don't think we should tackle this problem
// because we have a concrete need and a test bed for multiple atlas textures.
void ImGui::PushFont(ImFont* font)
{
ImGuiContext& g = *GImGui;
if (!font)
if (font == NULL)
font = GetDefaultFont();
SetCurrentFont(font);
g.FontStack.push_back(font);
g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID);
SetCurrentFont(font);
g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID);
}

void ImGui::PopFont()
{
ImGuiContext& g = *GImGui;
g.CurrentWindow->DrawList->PopTextureID();
IM_ASSERT(g.FontStack.Size > 0);
g.FontStack.pop_back();
SetCurrentFont(g.FontStack.empty() ? GetDefaultFont() : g.FontStack.back());
ImFont* font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back();
SetCurrentFont(font);
g.CurrentWindow->DrawList->_SetTextureID(font->ContainerAtlas->TexID);
}

void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled)
Expand Down
1 change: 1 addition & 0 deletions imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -3152,6 +3152,7 @@ struct ImDrawList
IMGUI_API void _OnChangedClipRect();
IMGUI_API void _OnChangedTextureID();
IMGUI_API void _OnChangedVtxOffset();
IMGUI_API void _SetTextureID(ImTextureID texture_id);
IMGUI_API int _CalcCircleAutoSegmentCount(float radius) const;
IMGUI_API void _PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step);
IMGUI_API void _PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments);
Expand Down
11 changes: 9 additions & 2 deletions imgui_draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,6 @@ void ImDrawList::_OnChangedClipRect()
CmdBuffer.pop_back();
return;
}

curr_cmd->ClipRect = _CmdHeader.ClipRect;
}

Expand All @@ -549,7 +548,6 @@ void ImDrawList::_OnChangedTextureID()
CmdBuffer.pop_back();
return;
}

curr_cmd->TextureId = _CmdHeader.TextureId;
}

Expand Down Expand Up @@ -625,6 +623,15 @@ void ImDrawList::PopTextureID()
_OnChangedTextureID();
}

// This is used by ImGui::PushFont()/PopFont(). It works because we never use _TextureIdStack[] elsewhere than in PushTextureID()/PopTextureID().
void ImDrawList::_SetTextureID(ImTextureID texture_id)
{
if (_CmdHeader.TextureId == texture_id)
return;
_CmdHeader.TextureId = texture_id;
_OnChangedTextureID();
}

// Reserve space for a number of vertices and indices.
// You must finish filling your reserved data before calling PrimReserve() again, as it may reallocate or
// submit the intermediate results. PrimUnreserve() can be used to release unused allocations.
Expand Down

0 comments on commit eb7201b

Please sign in to comment.