Merge branch 'master' into docking

# Conflicts:
#	backends/imgui_impl_opengl3.cpp
#	imgui.cpp
This commit is contained in:
ocornut 2026-10-05 19:42:50 +02:00
commit 0f4b927e81
13 changed files with 213 additions and 107 deletions

View File

@ -1,12 +1,12 @@
(Click "Preview" to turn any http URL into a clickable link)
1. PLEASE CAREFULLY READ: [Contributing Guidelines](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md)
1. PLEASE CAREFULLY READ: [Contributing Guidelines](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md). By submitting a PR you are agreeing with the [CLA](https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#copyright--contributor-license-agreement).
2. **Make sure you're using a special branch just for this pull request**. (In git, 1 PR = 1 branch. If you update the branch the PR will be updated.)
3. Consider running the [imgui_test_suite](https://github.com/ocornut/imgui_test_engine) or adding new tests to test for expected behaviors.
4. PLEASE DO NOT SUBMIT AI SLOP OR AUTOMATED AI REPORTS. Submissions that are lacking proper human review/judgement before being passed to us are not welcome. Do not let a LLM AI write most of the text for you.
4. PLEASE DO NOT SUBMIT AI-GENERATED PROSE. ONLY SUBMIT CODE THAT YOU REVIEWED AND UNDERSTAND. Submissions that are lacking proper human review/judgement before being passed to us are not welcome.
5. Clear this template before submitting your PR.

View File

@ -26,6 +26,9 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2026-10-01: OpenGL: Added ImGui_ImplOpenGL3_SetClipOrigin() to specify clip origins (GL_LOWER_LEFT/GL_UPPER_LEFT, or use 0 to autodetect). (#2186, #3998, #3146, #3143, #8640)
// (Breaking): we now default to GL_LOWER_LEFT instead of 0=autodetect. Because 1) detection is not reliable and 2) is slow.
// 2026-10-01: OpenGL: Avoid querying glGetIntegerv(GL_CLIP_ORIGIN) multiple times when using DrawCallback_ResetRenderState. (#2186, #3998, #3146, #3143, #8640)
// 2026-09-17: OpenGL: Added support for platform_io.DrawCallback_SetSamplerFromTex. (#9378)
// 2026-09-07: OpenGL: Round framebuffer dimensions to the nearest integer instead of truncating them. (#9538, 9515, #8628)
// 2026-07-15: OpenGL: Backup and restore GL_UNPACK_ROW_LENGTH and GL_UNPACK_ALIGNMENT in UpdateTexture() to avoid corrupting caller GL state. (#8802, #9473)
@ -191,6 +194,10 @@
#define IMGUI_IMPL_OPENGL_LOADER_IMGL3W
#include "imgui_impl_opengl3_loader.h"
#endif
#ifndef GL_LOWER_LEFT
#define GL_LOWER_LEFT 0x8CA1
#define GL_UPPER_LEFT 0x8CA2
#endif
// Vertex arrays are not supported on ES2/WebGL1 unless Emscripten which uses an extension
#ifndef IMGUI_IMPL_OPENGL_ES2
@ -261,6 +268,8 @@ struct ImGui_ImplOpenGL3_Data
bool HasPolygonMode;
bool HasBindSampler;
bool HasClipOrigin;
GLenum ClipOriginRequest; // Default = GL_LOWER_LEFT. Change using ImGui_ImplOpenGL3_SetClipOrigin().
GLenum ClipOriginCurrent;
bool UseBufferSubData;
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
GLuint TexSamplers[2]; // Used if HasBindSimpler. (0=linear, 1=nearest)
@ -367,17 +376,6 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, ImGui_Impl
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
// Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
#if defined(GL_CLIP_ORIGIN)
bool clip_origin_lower_left = true;
if (bd->HasClipOrigin)
{
GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&current_clip_origin);
if (current_clip_origin == GL_UPPER_LEFT)
clip_origin_lower_left = false;
}
#endif
// Setup viewport, orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
GL_CALL(glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height));
@ -385,9 +383,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, ImGui_Impl
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
float T = draw_data->DisplayPos.y;
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
#if defined(GL_CLIP_ORIGIN)
if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left
#endif
if (bd->ClipOriginCurrent == GL_UPPER_LEFT) { float tmp = T; T = B; B = tmp; } // Swap top and bottom
const float ortho_projection[4][4] =
{
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
@ -469,6 +465,14 @@ static void ImGui_ImplOpenGL3_DrawCallback_SetSamplerFromTex(const ImDrawList*,
render_state->UseTexParameterFilter = false;
}
// Default is GL_LOWER_LEFT since 2026/10/01. Used to be auto.
void ImGui_ImplOpenGL3_SetClipOrigin(unsigned int clip_origin)
{
IM_ASSERT(clip_origin == 0 || clip_origin == GL_UPPER_LEFT || clip_origin == GL_LOWER_LEFT);
ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
bd->ClipOriginRequest = clip_origin;
}
// OpenGL3 Render function.
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
// This is in order to be able to run within an OpenGL engine that doesn't do so.
@ -530,6 +534,17 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
GLboolean last_enable_primitive_restart = (!bd->GlProfileIsES3 && bd->GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE;
#endif
// Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
bd->ClipOriginCurrent = bd->ClipOriginRequest;
if (bd->ClipOriginCurrent == 0)
{
bd->ClipOriginCurrent = GL_LOWER_LEFT;
#ifdef GL_CLIP_ORIGIN
if (bd->HasClipOrigin)
glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&bd->ClipOriginCurrent);
#endif
}
// Setup desired GL state
// Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts)
// The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound.
@ -1157,6 +1172,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
bd->HasClipOrigin = true;
}
#endif
bd->ClipOriginCurrent = bd->ClipOriginRequest = GL_LOWER_LEFT;
ImGui_ImplOpenGL3_InitMultiViewportSupport();

View File

@ -45,6 +45,9 @@ IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = nullptr to handle this manually.
IMGUI_IMPL_API void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex);
// (Advanced) Specify clip origin, same value as glClipControl() or 0 for auto-detection.
IMGUI_IMPL_API void ImGui_ImplOpenGL3_SetClipOrigin(unsigned int gl_clip_origin);
// Configuration flags to add in your imconfig file:
//#define IMGUI_IMPL_OPENGL_ES2 // Enable ES 2 (Auto-detected on Emscripten)
//#define IMGUI_IMPL_OPENGL_ES3 // Enable ES 3 (Auto-detected on iOS/Android)

View File

@ -303,6 +303,7 @@ typedef khronos_uint16_t GLushort;
#define GL_LINK_STATUS 0x8B82
#define GL_INFO_LOG_LENGTH 0x8B84
#define GL_CURRENT_PROGRAM 0x8B8D
#define GL_LOWER_LEFT 0x8CA1
#define GL_UPPER_LEFT 0x8CA2
typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);

View File

@ -47,10 +47,15 @@ Breaking Changes:
- style.CurveTessellationMaxError == sqrf(style.CurveTessellationTol).
- ImGuiTextFilter: removed `float width` parameter of `Draw(const char* filter, float width)`:
prefer using `SetNextItemWidth(float)` which is standard. Kept inline redirection function.
- Fonts: renamed `AddRemapChar()` to `AddRemapCodepoint()` (rarely used, marked internal).
(#609, #5748, #9559)
- Backends:
- DirectX12: Removed support for legacy `ImGui_ImplDX12_Init()` signature, which was
obsoleted in 1.91.6 (December 2014), because it needed to forcefully disable support
for `ImGuiBackendFlags_RendererHasTextures`. Use the new signature! (#9487)
- OpenGL3: Does not attempt to read `GL_CLIP_ORIGIN` by default as the detection is
sub-optimal and not reliable on some setup. Use `ImGui_ImplOpenGL3_SetClipOrigin(0)`
to enable auto-detection, or e.g. `ImGui_ImplOpenGL3_SetClipOrigin(GL_UPPER_LEFT)`.
Other Changes:
@ -71,14 +76,26 @@ Other Changes:
- Tables:
- Fixed a bug restoring correct .ini columns order when table use is Sortable
but had no user changes. (regression from 1.92.9). (#9519, #9108)
- Fixed a bug tracking topology changes (insert new columns in the middle)
when the table is not _Reorderable: new columns would be ordered incorrectly.
(#9570, #9108, #9572) [@lailoken]
- InpuText:
- Fixed a crash in some cases when using Home key in a WordWrap+ReadOnly field. (#9561)
- Selectable:
- Fixed `ImGuiSelectableFlags_SelectOnNav` triggering during NavInit.
- Fonts:
- Reworked `AddFontDefault()` to use `io.DisplayFrameBufferScale` as part of the heuristic
to select `AddFontDefaultVector()` by default, effectively using ProggyForever instead of
ProggyClean on most Apple/Retina setups by default.
- Added ImFont::AddRemapCodepointToGlyphIndex() allowing to access glyphs that are not
mapped to codepoints. (#9559, #5647, #609, #5748, #8466)
- imgui_freetype: Fixed blurryness rendering `AddFontDefaultVector()`. Caused by a
non-pixel aligned offset caused by `ExtraSizeScale`. (#9348, #9233) [@redpartizan, @RDMCz]
- (Internal) ImFontLoader: reworked `FontSrcContainsGlyph`, `FontBakedLoadGlyph` signatures
to take raw glyph index instead of codepoint. Added `FontSrcGetGlyphIndexFromCodepoint`.
(#9559, #5647, #9540, #8466, #8465)
- Added `IMGUI_DISABLE_STB_TRUETYPE` to completely omit the stb_truetype loader
code + stb_truetype.h code. (#9573)
- ColorEdit:
- ColorButton, ColorEdit, ColorPicker: cancel-out alpha caused by BeginDisabled() so
disabled color buttons have the same color as non-disabled oness. (#9511)
@ -114,6 +131,9 @@ Other Changes:
trivial functions when stepping into.
- Tagged various trivial functions using `IM_NODEBUGSTEP`: `ImVec2()`, `ImVec4()` etc.
and various operators.
- Fixed strict aliasing violation in `ImHashData()` affecting Clang 23 + SSE 4.2 + -flto.
Could manifest as `ImFontAtlasBakedGetId()` computation omitting font size from
the hashed data. (#9557, #9560) [@sthalik]
- IO: restore default clipboard/ime/shell platform handlers on ClearPlatformHandlers(), fixing
issues switching backends mid-session to one relying on default. (#9537, #8945, #2769) [@lstalmir]
- DrawList:
@ -136,6 +156,11 @@ Other Changes:
callback to request using the sampler associated already associated to a texture. (#9378)
- OpenGL2, OpenGL3: fixed `DrawCallback_ResetRenderState` handler not reseting all states
in the glTexParameter() path. (#9378)
- OpenGL3: added `ImGui_ImplOpenGL3_SetClipOrigin()` to specify origin between
`GL_LOWER_LEFT` (new default), `GL_UPPER_LEFT` and `0` (autodetect, old default).
- OpenGL3: avoid querying `glGetIntegerv(GL_CLIP_ORIGIN)` multiple times when using
when using default and using `DrawCallback_ResetRenderState`, at it appear to stall
some drivers. (#2186, #3998, #3146, #3143, #8640)
- SDL2: fixed querying framebuffer scale/density when using Metal without
going through a SDL_Renderer. (#5592) [@lailoken]
- SDLRenderer3: restore any temporarily modified texture scale modes at the of `RenderDrawData()`. (#9378)
@ -152,6 +177,8 @@ Other Changes:
- Examples:
- MSVC: disabled /JMC in Visual Studio projects (unnecessary overhead).
- GLFW/SDL2/SDL3+WebGPU: fixed running with wgpu-native missing `wgpuInstanceWaitAny()`. (#9377)
- GLFW+Metal: fixed mistakenly calling `ImGui_ImplGlfw_InitForOpenGL()`, which
broke multi-viewport support. (#9564) [@ypujante]
- SDL2+Metal: create Metal context without using a `SDL_Renderer`.
- QNX+OpenGL3, QNX+Vulkan: added QNX Screen examples. (#9492) [@mgorchak-blackberry]
- OSX+OpenGL3: added example_apple_opengl3/ (OSX/Cocoa + OpenGL 3.2 Core profile).

View File

@ -72,7 +72,8 @@
//---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
//#define IMGUI_USE_WCHAR32
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version.
// This is for if you already embed a copy of those library in your code and don't want duplicate code in your binary.
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
@ -102,6 +103,7 @@
//---- Use stb_truetype to build and rasterize the font atlas (default)
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
//#define IMGUI_ENABLE_STB_TRUETYPE
//#define IMGUI_DISABLE_STB_TRUETYPE
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
// This will be inlined as part of ImVec2 and ImVec4 class declarations.

View File

@ -403,6 +403,7 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
- likewise io.MousePos and GetMousePos() will use OS coordinates.
If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos.
- 2026/09/30 (1.93.0) - ImFont: renamed `AddRemapChar()` to `AddRemapCodepoint()` (rarely used, marked internal). (#609, #5748)
- 2026/09/18 (1.93.0) - ImGuiTextFilter: removed `float width` parameter of `Draw(const char* filter, float width)`: prefer using `SetNextItemWidth(float)` which is standard. Kept inline redirection function.
- 2026/08/03 (1.93.0) - Style: obsoleted `style.CurveTessellationTol (default 1.25)` which was in Pixels² unit in favor of `style.CurveTessellationMaxError` (default 1.12)` which is in Pixels unit.
- style.CurveTessellationMaxError == sqrf(style.CurveTessellationTol).
@ -2559,7 +2560,13 @@ ImGuiID ImHashData(const void* data_p, size_t data_size, ImGuiID seed)
#else
while (data + 4 <= data_end)
{
#if defined(_DEBUG) || defined(_MSC_VER)
crc = _mm_crc32_u32(crc, *(ImU32*)data);
#else
ImU32 v;
memcpy(&v, data, sizeof(ImU32)); // Avoid aliasing violation (#9557)
crc = _mm_crc32_u32(crc, v);
#endif
data += 4;
}
while (data < data_end)
@ -22505,6 +22512,7 @@ void ImGui::ShowFontAtlas(ImFontAtlas* atlas)
if (TreeNode("Loader", "Loader: \'%s\'", atlas->FontLoaderName ? atlas->FontLoaderName : "NULL"))
{
const ImFontLoader* loader_current = atlas->FontLoader;
IM_UNUSED(loader_current);
BeginDisabled(!atlas->RendererHasTextures);
#ifdef IMGUI_ENABLE_STB_TRUETYPE
const ImFontLoader* loader_stbtruetype = ImFontAtlasGetFontLoaderForStbTruetype();
@ -23655,7 +23663,8 @@ static int CalcFontGlyphSrcOverlapMask(ImFontAtlas* atlas, ImFont* font, unsigne
for (int src_n = 0; src_n < font->Sources.Size; src_n++)
{
ImFontConfig* src = font->Sources[src_n];
if (!(src->FontLoader ? src->FontLoader : atlas->FontLoader)->FontSrcContainsGlyph(atlas, src, (ImWchar)codepoint))
const ImFontLoader* loader = src->FontLoader ? src->FontLoader : atlas->FontLoader;
if (loader->FontSrcGetGlyphIndexFromCodepoint(atlas, src, (ImWchar)codepoint) == 0)
continue;
mask |= (1 << src_n);
count++;

View File

@ -4101,7 +4101,7 @@ struct ImFont
ImWchar FallbackChar; // 2-4 // out // Character used if a glyph isn't found (U+FFFD, '?')
ImU8 Used8kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/8192/8]; // 1 bytes if ImWchar=ImWchar16, 17 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 8K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints.
bool EllipsisAutoBake; // 1 // // Mark when the "..." glyph (== EllipsisChar) needs to be generated by combining multiple '.'.
ImGuiStorage RemapPairs; // 16 // // Remapping pairs when using AddRemapChar(), otherwise empty.
ImGuiStorage RemapPairs; // 16 // // Remapping pairs when using AddRemapCodepointXXX().
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
float Scale; // 4 // in // Legacy base font scale (~1.0f), multiplied by the per-window font scale which you can adjust with SetWindowFontScale()
#endif
@ -4127,8 +4127,10 @@ struct ImFont
// [Internal] Don't use!
IMGUI_API void ClearOutputData();
IMGUI_API void AddRemapChar(ImWchar from_codepoint, ImWchar to_codepoint); // Makes 'from_codepoint' character points to 'to_codepoint' glyph.
IMGUI_API void AddRemapCodepoint(ImWchar from_codepoint, ImWchar to_codepoint); // Makes 'from_codepoint' character points to 'to_codepoint' glyph.
IMGUI_API void AddRemapCodepointToGlyphIndex(ImWchar from_codepoint, int font_src_idx, int glyph_idx);
IMGUI_API bool IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last);
//inline void AddRemapChar(ImWchar from_codepoint, ImWchar to_codepoint) { AddRemapCodepoint(from_codepoint, to_codepoint); } // Renamed in 1.93.0 (Sep 2026)
};
// This is provided for consistency (but we don't actually use this)

View File

@ -3129,7 +3129,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg_in)
}
if (font_cfg->FontLoader != NULL)
{
IM_ASSERT(font_cfg->FontLoader->FontBakedLoadGlyph != NULL);
IM_ASSERT(font_cfg->FontLoader->FontSrcGetGlyphIndexFromCodepoint != NULL && font_cfg->FontLoader->FontBakedLoadGlyph != NULL);
IM_ASSERT(font_cfg->FontLoader->LoaderInit == NULL && font_cfg->FontLoader->LoaderShutdown == NULL); // FIXME-NEWATLAS: Unsupported yet.
}
// | Target w/ Implicit RefSize | Target w/ Explicit RefSize |
@ -4568,11 +4568,46 @@ static void ImFontBaked_BuildGrowIndex(ImFontBaked* baked, int new_size)
baked->IndexLookup.resize(new_size, IM_FONTGLYPH_INDEX_UNUSED);
}
static void ImFontAtlas_FontHookRemapCodepoint(ImFontAtlas* atlas, ImFont* font, ImWchar* c)
// Remap a codepoint to another codepoint
void ImFont::AddRemapCodepoint(ImWchar from_codepoint, ImWchar to_codepoint)
{
ImU32 data = (ImU32)to_codepoint;
IM_ASSERT((data & (1u << 31)) == 0);
RemapPairs.SetInt((ImGuiID)from_codepoint, (int)data);
}
static const int IMFONT_REMAPVALUE_GLYPHIDX_SHIFT = 0;
static const int IMFONT_REMAPVALUE_GLYPHIDX_MASK = 0xFFFF;
static const int IMFONT_REMAPVALUE_FONTSRCIDX_SHIFT = 16;
static const int IMFONT_REMAPVALUE_FONTSRCIDX_MASK = 0xFF0000;
// Remap a codepoint to a raw glyph index inside the font. Allows accessing glyphs which are not mapped to codepoints. (#9559)
// font_src_idx = index in font->Sources[], or -1 for last added source.
// glyph_idx = index in TTF or OTF file.
void ImFont::AddRemapCodepointToGlyphIndex(ImWchar from_codepoint, int font_src_idx, int glyph_idx)
{
if (font_src_idx == -1)
font_src_idx = Sources.Size - 1;
IM_ASSERT(font_src_idx >= 0 && font_src_idx < Sources.Size && ((font_src_idx << IMFONT_REMAPVALUE_FONTSRCIDX_SHIFT) & ~IMFONT_REMAPVALUE_FONTSRCIDX_MASK) == 0);
IM_ASSERT(glyph_idx >= 0 && ((glyph_idx << IMFONT_REMAPVALUE_GLYPHIDX_SHIFT) & ~IMFONT_REMAPVALUE_GLYPHIDX_MASK) == 0);
ImU32 data = ((ImU32)glyph_idx << IMFONT_REMAPVALUE_GLYPHIDX_SHIFT) | (font_src_idx << IMFONT_REMAPVALUE_FONTSRCIDX_SHIFT) | (1u << 31);
RemapPairs.SetInt((ImGuiID)from_codepoint, (int)data);
}
static void ImFontAtlas_FontHookRemapCodepoint(ImFontAtlas* atlas, ImFont* font, ImWchar codepoint, ImWchar* out_codepoint, int* out_font_src_idx, int* out_glyph_idx)
{
IM_UNUSED(atlas);
if (font->RemapPairs.Data.Size != 0)
*c = (ImWchar)font->RemapPairs.GetInt((ImGuiID)*c, (int)*c);
if (font->RemapPairs.Data.Size == 0)
return;
ImU32 data = (ImU32)font->RemapPairs.GetInt((ImGuiID)codepoint, (int)codepoint);
if (data & (1u << 31))
{
*out_codepoint = (ImWchar)-1;
*out_font_src_idx = (data & IMFONT_REMAPVALUE_FONTSRCIDX_MASK) >> IMFONT_REMAPVALUE_FONTSRCIDX_SHIFT;
*out_glyph_idx = (data & IMFONT_REMAPVALUE_GLYPHIDX_MASK) >> IMFONT_REMAPVALUE_GLYPHIDX_SHIFT;
return;
}
*out_codepoint = (ImWchar)data;
}
static ImFontGlyph* ImFontBaked_BuildLoadGlyph(ImFontBaked* baked, ImWchar codepoint, float* only_load_advance_x)
@ -4589,7 +4624,8 @@ static ImFontGlyph* ImFontBaked_BuildLoadGlyph(ImFontBaked* baked, ImWchar codep
// User remapping hooks
ImWchar src_codepoint = codepoint;
ImFontAtlas_FontHookRemapCodepoint(atlas, font, &codepoint);
int src_font_idx = -1, src_glyph_idx = -1;
ImFontAtlas_FontHookRemapCodepoint(atlas, font, codepoint, &src_codepoint, &src_font_idx, &src_glyph_idx);
//char utf8_buf[5];
//IMGUI_DEBUG_LOG("[font] BuildLoadGlyph U+%04X (%s)\n", (unsigned int)codepoint, ImTextCharToUtf8(utf8_buf, (unsigned int)codepoint));
@ -4602,35 +4638,47 @@ static ImFontGlyph* ImFontBaked_BuildLoadGlyph(ImFontBaked* baked, ImWchar codep
// Call backend
char* loader_user_data_p = (char*)baked->FontLoaderDatas;
int src_n = 0;
for (ImFontConfig* src : font->Sources)
char* loader_user_data_p_next = NULL;
for (int src_n = 0; src_n < font->Sources.Size; src_n++, loader_user_data_p = loader_user_data_p_next)
{
ImFontConfig* src = font->Sources[src_n];
const ImFontLoader* loader = src->FontLoader ? src->FontLoader : atlas->FontLoader;
if (!src->GlyphExcludeRanges || ImFontAtlasBuildAcceptCodepointForSource(src, codepoint))
loader_user_data_p_next = loader_user_data_p + loader->FontBakedSrcLoaderDataSize;
int glyph_index;
if (src_codepoint != (ImWchar)-1)
{
if (only_load_advance_x == NULL)
{
ImFontGlyph glyph_buf;
if (loader->FontBakedLoadGlyph(atlas, src, baked, loader_user_data_p, codepoint, &glyph_buf, NULL))
{
// FIXME: Add hooks for e.g. #7962
glyph_buf.Codepoint = src_codepoint;
glyph_buf.SourceIdx = src_n;
return ImFontAtlasBakedAddFontGlyph(atlas, baked, src, &glyph_buf);
}
}
else
{
// Special mode but only loading glyphs metrics. Will rasterize and pack later.
if (loader->FontBakedLoadGlyph(atlas, src, baked, loader_user_data_p, codepoint, NULL, only_load_advance_x))
{
ImFontAtlasBakedAddFontGlyphAdvancedX(atlas, baked, src, codepoint, *only_load_advance_x);
return NULL;
}
}
if (src->GlyphExcludeRanges && !ImFontAtlasBuildAcceptCodepointForSource(src, src_codepoint))
continue;
glyph_index = loader->FontSrcGetGlyphIndexFromCodepoint(atlas, src, src_codepoint);
}
else
{
if (src_n != src_font_idx)
continue;
glyph_index = src_glyph_idx;
}
if (glyph_index == 0)
continue;
if (only_load_advance_x == NULL)
{
ImFontGlyph glyph_buf;
glyph_buf.Codepoint = codepoint;
if (!loader->FontBakedLoadGlyph(atlas, src, baked, loader_user_data_p, glyph_index, &glyph_buf, NULL))
continue;
// FIXME: Add hooks for e.g. #7962
glyph_buf.SourceIdx = src_n;
return ImFontAtlasBakedAddFontGlyph(atlas, baked, src, &glyph_buf);
}
else
{
// Special mode but only loading glyphs metrics. Will rasterize and pack later.
if (!loader->FontBakedLoadGlyph(atlas, src, baked, loader_user_data_p, glyph_index, NULL, only_load_advance_x))
continue;
ImFontAtlasBakedAddFontGlyphAdvancedX(atlas, baked, src, codepoint, *only_load_advance_x);
return NULL;
}
loader_user_data_p += loader->FontBakedSrcLoaderDataSize;
src_n++;
}
// Lazily load fallback glyph
@ -4714,10 +4762,8 @@ struct ImGui_ImplStbTrueType_FontSrcData
float ScaleFactor;
};
static bool ImGui_ImplStbTrueType_FontSrcInit(ImFontAtlas* atlas, ImFontConfig* src)
static bool ImGui_ImplStbTrueType_FontSrcInit(ImFontAtlas*, ImFontConfig* src)
{
IM_UNUSED(atlas);
ImGui_ImplStbTrueType_FontSrcData* bd_font_data = IM_NEW(ImGui_ImplStbTrueType_FontSrcData);
IM_ASSERT(src->FontLoaderData == NULL);
@ -4749,29 +4795,27 @@ static bool ImGui_ImplStbTrueType_FontSrcInit(ImFontAtlas* atlas, ImFontConfig*
return true;
}
static void ImGui_ImplStbTrueType_FontSrcDestroy(ImFontAtlas* atlas, ImFontConfig* src)
static void ImGui_ImplStbTrueType_FontSrcDestroy(ImFontAtlas*, ImFontConfig* src)
{
IM_UNUSED(atlas);
ImGui_ImplStbTrueType_FontSrcData* bd_font_data = (ImGui_ImplStbTrueType_FontSrcData*)src->FontLoaderData;
IM_DELETE(bd_font_data);
src->FontLoaderData = NULL;
}
static bool ImGui_ImplStbTrueType_FontSrcContainsGlyph(ImFontAtlas* atlas, ImFontConfig* src, ImWchar codepoint)
static int ImGui_ImplStbTrueType_FontSrcGetGlyphIndexFromCodepoint(ImFontAtlas*, ImFontConfig* src, ImWchar codepoint)
{
IM_UNUSED(atlas);
ImGui_ImplStbTrueType_FontSrcData* bd_font_data = (ImGui_ImplStbTrueType_FontSrcData*)src->FontLoaderData;
IM_ASSERT(bd_font_data != NULL);
int glyph_index = stbtt_FindGlyphIndex(&bd_font_data->FontInfo, (int)codepoint);
return glyph_index != 0;
return stbtt_FindGlyphIndex(&bd_font_data->FontInfo, (int)codepoint);
}
static bool ImGui_ImplStbTrueType_FontBakedInit(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void*)
static bool ImGui_ImplStbTrueType_FontSrcContainsGlyph(ImFontAtlas*, ImFontConfig* src, int glyph_index)
{
IM_UNUSED(atlas);
ImGui_ImplStbTrueType_FontSrcData* bd_font_data = (ImGui_ImplStbTrueType_FontSrcData*)src->FontLoaderData;
return glyph_index > 0 && glyph_index < bd_font_data->FontInfo.numGlyphs;
}
static bool ImGui_ImplStbTrueType_FontBakedInit(ImFontAtlas*, ImFontConfig* src, ImFontBaked* baked, void*)
{
ImGui_ImplStbTrueType_FontSrcData* bd_font_data = (ImGui_ImplStbTrueType_FontSrcData*)src->FontLoaderData;
if (src->MergeMode == false)
{
@ -4787,14 +4831,12 @@ static bool ImGui_ImplStbTrueType_FontBakedInit(ImFontAtlas* atlas, ImFontConfig
return true;
}
static bool ImGui_ImplStbTrueType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void*, ImWchar codepoint, ImFontGlyph* out_glyph, float* out_advance_x)
static bool ImGui_ImplStbTrueType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void*, int glyph_index, ImFontGlyph* out_glyph, float* out_advance_x)
{
// Search for first font which has the glyph
ImGui_ImplStbTrueType_FontSrcData* bd_font_data = (ImGui_ImplStbTrueType_FontSrcData*)src->FontLoaderData;
IM_ASSERT(bd_font_data);
int glyph_index = stbtt_FindGlyphIndex(&bd_font_data->FontInfo, (int)codepoint);
if (glyph_index == 0)
return false;
IM_ASSERT(glyph_index != 0);
// Fonts unit to pixels
int oversample_h, oversample_v;
@ -4819,7 +4861,6 @@ static bool ImGui_ImplStbTrueType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontC
}
// Prepare glyph
out_glyph->Codepoint = codepoint;
out_glyph->AdvanceX = advance * scale_for_layout;
// Pack and retrieve position inside texture atlas
@ -4881,6 +4922,7 @@ const ImFontLoader* ImFontAtlasGetFontLoaderForStbTruetype()
loader.Name = "stb_truetype";
loader.FontSrcInit = ImGui_ImplStbTrueType_FontSrcInit;
loader.FontSrcDestroy = ImGui_ImplStbTrueType_FontSrcDestroy;
loader.FontSrcGetGlyphIndexFromCodepoint = ImGui_ImplStbTrueType_FontSrcGetGlyphIndexFromCodepoint;
loader.FontSrcContainsGlyph = ImGui_ImplStbTrueType_FontSrcContainsGlyph;
loader.FontBakedInit = ImGui_ImplStbTrueType_FontBakedInit;
loader.FontBakedDestroy = NULL;
@ -5354,11 +5396,6 @@ void ImFontAtlasBakedSetFontGlyphBitmap(ImFontAtlas* atlas, ImFontBaked* baked,
ImFontAtlasTextureBlockQueueUpload(atlas, tex, r->x, r->y, r->w, r->h);
}
void ImFont::AddRemapChar(ImWchar from_codepoint, ImWchar to_codepoint)
{
RemapPairs.SetInt((ImGuiID)from_codepoint, (int)to_codepoint);
}
// Find glyph, load if necessary, return fallback if missing
ImFontGlyph* ImFontBaked::FindGlyph(ImWchar c)
{
@ -5408,11 +5445,19 @@ bool ImFontBaked::IsGlyphLoaded(ImWchar c)
bool ImFont::IsGlyphInFont(ImWchar c)
{
ImFontAtlas* atlas = OwnerAtlas;
ImFontAtlas_FontHookRemapCodepoint(atlas, this, &c);
ImWchar src_codepoint = c;
int src_font_idx = -1, src_glyph_idx = -1;
ImFontAtlas_FontHookRemapCodepoint(atlas, this, c, &src_codepoint, &src_font_idx, &src_glyph_idx);
if (src_font_idx != -1)
{
ImFontConfig* src = Sources[src_font_idx];
const ImFontLoader* loader = src->FontLoader ? src->FontLoader : atlas->FontLoader;
return loader->FontSrcContainsGlyph ? loader->FontSrcContainsGlyph(atlas, src, src_glyph_idx) : false;
}
for (ImFontConfig* src : Sources)
{
const ImFontLoader* loader = src->FontLoader ? src->FontLoader : atlas->FontLoader;
if (loader->FontSrcContainsGlyph != NULL && loader->FontSrcContainsGlyph(atlas, src, c))
if (loader->FontSrcGetGlyphIndexFromCodepoint(atlas, src, c) != 0)
return true;
}
return false;

View File

@ -126,7 +126,7 @@ Index of this file:
// Enable stb_truetype by default unless FreeType is enabled.
// You can compile with both by defining both IMGUI_ENABLE_FREETYPE and IMGUI_ENABLE_STB_TRUETYPE together.
#ifndef IMGUI_ENABLE_FREETYPE
#if !defined(IMGUI_ENABLE_FREETYPE) && !defined(IMGUI_ENABLE_STB_TRUETYPE) && !defined(IMGUI_DISABLE_STB_TRUETYPE)
#define IMGUI_ENABLE_STB_TRUETYPE
#endif
@ -4229,10 +4229,11 @@ struct ImFontLoader
void (*LoaderShutdown)(ImFontAtlas* atlas);
bool (*FontSrcInit)(ImFontAtlas* atlas, ImFontConfig* src);
void (*FontSrcDestroy)(ImFontAtlas* atlas, ImFontConfig* src);
bool (*FontSrcContainsGlyph)(ImFontAtlas* atlas, ImFontConfig* src, ImWchar codepoint);
int (*FontSrcGetGlyphIndexFromCodepoint)(ImFontAtlas* atlas, ImFontConfig* src, ImWchar codepoint); // Required
bool (*FontSrcContainsGlyph)(ImFontAtlas* atlas, ImFontConfig* src, int glyph_index);
bool (*FontBakedInit)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src);
void (*FontBakedDestroy)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src);
bool (*FontBakedLoadGlyph)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src, ImWchar codepoint, ImFontGlyph* out_glyph, float* out_advance_x);
bool (*FontBakedLoadGlyph)(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src, int glyph_index, ImFontGlyph* out_glyph, float* out_advance_x); // Required
// Size of backend data, Per Baked * Per Source. Buffers are managed by core to avoid excessive allocations.
// FIXME: At this point the two other types of buffers may be managed by core to be consistent?

View File

@ -4107,6 +4107,12 @@ static int IMGUI_CDECL TableFixDisplayOrderComparer(const void* lhs, const void*
// Fix invalid display order data: compact values (0,1,3 -> 0,1,2); preserve relative order (0,3,1 -> 0,2,1); deduplicate (0,4,1,1 -> 0,3,1,2)
void ImGui::TableFixDisplayOrder(ImGuiTable* table)
{
if ((table->Flags & ImGuiTableFlags_Reorderable) == 0)
{
for (int n = 0; n < table->ColumnsCount; n++)
table->DisplayOrderToIndex[n] = table->Columns[n].DisplayOrder = (ImGuiTableColumnIdx)n;
return;
}
ImGuiContext& g = *GImGui;
g.TempBuffer.reserve((int)(sizeof(ImGuiTableFixDisplayOrderColumnData) * table->ColumnsCount)); // FIXME: Maybe wrap those two lines as a helper.
ImGuiTableFixDisplayOrderColumnData* fdo_columns = (ImGuiTableFixDisplayOrderColumnData*)(void*)g.TempBuffer.Data;

View File

@ -4239,7 +4239,7 @@ static int STB_TEXTEDIT_MOVELINESTART_IMPL(ImGuiInputTextState* obj, ImStb::STB_
const char* p_eol = ImFontCalcWordWrapPositionEx(g.Font, g.FontSize, p, text_end, obj->WrapWidth, ImDrawTextFlags_WrapKeepBlanks);
if (p == p_cursor) // If we are already on a visible beginning-of-line, return real beginning-of-line (would be same as regular handler below)
return (int)(p_bol - obj->TextSrc);
if (p_eol == p_cursor && obj->TextA[cursor] != '\n' && obj->LastMoveDirectionLR == ImGuiDir_Left)
if (p_eol == p_cursor && obj->TextSrc[cursor] != '\n' && obj->LastMoveDirectionLR == ImGuiDir_Left)
return (int)(p_bol - obj->TextSrc);
if (p_eol >= p_cursor)
return (int)(p - obj->TextSrc);
@ -5064,7 +5064,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Select the buffer to render.
const bool buf_display_from_state = (render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state;
bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0) && !is_mixed;
bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextSrc : buf)[0] == 0) && !is_mixed;
// Password pushes a temporary font with only a fallback glyph
if (is_password && !is_displaying_hint)
@ -5290,7 +5290,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{
if (flags & ImGuiInputTextFlags_EscapeClearsAll)
{
if (state->TextA.Data[0] != 0)
if (state->TextSrc[0] != 0)
{
revert_edit = true;
}
@ -5383,14 +5383,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (flags & ImGuiInputTextFlags_EscapeClearsAll)
{
// Clear input
IM_ASSERT(state->TextA.Data[0] != 0);
IM_ASSERT(state->TextSrc[0] != 0);
apply_new_text = "";
apply_new_text_length = 0;
value_changed = true;
char empty_string = 0;
stb_textedit_replace(state, state->Stb, &empty_string, 0);
}
else if (strcmp(state->TextA.Data, state->TextToRevertTo.Data) != 0)
else if (strcmp(state->TextSrc, state->TextToRevertTo.Data) != 0)
{
apply_new_text = state->TextToRevertTo.Data;
apply_new_text_length = state->TextToRevertTo.Size - 1;

View File

@ -221,17 +221,14 @@ void ImGui_ImplFreeType_FontSrcData::CloseFont()
}
}
static const FT_Glyph_Metrics* ImGui_ImplFreeType_LoadGlyph(ImGui_ImplFreeType_FontSrcData* src_data, uint32_t codepoint)
static const FT_Glyph_Metrics* ImGui_ImplFreeType_LoadGlyph(ImGui_ImplFreeType_FontSrcData* src_data, uint32_t glyph_index)
{
uint32_t glyph_index = FT_Get_Char_Index(src_data->FtFace, codepoint);
if (glyph_index == 0)
return nullptr;
// If this crash for you: FreeType 2.11.0 has a crash bug on some bitmap/colored fonts.
// - https://gitlab.freedesktop.org/freetype/freetype/-/issues/1076
// - https://github.com/ocornut/imgui/issues/4567
// - https://github.com/ocornut/imgui/issues/4566
// You can use FreeType 2.10, or the patched version of 2.11.0 in VcPkg, or probably any upcoming FreeType version.
IM_ASSERT(glyph_index != 0);
FT_Error error = FT_Load_Glyph(src_data->FtFace, glyph_index, src_data->LoadFlags);
if (error)
return nullptr;
@ -417,17 +414,15 @@ static bool ImGui_ImplFreeType_FontSrcInit(ImFontAtlas* atlas, ImFontConfig* src
return true;
}
static void ImGui_ImplFreeType_FontSrcDestroy(ImFontAtlas* atlas, ImFontConfig* src)
static void ImGui_ImplFreeType_FontSrcDestroy(ImFontAtlas*, ImFontConfig* src)
{
IM_UNUSED(atlas);
ImGui_ImplFreeType_FontSrcData* bd_font_data = (ImGui_ImplFreeType_FontSrcData*)src->FontLoaderData;
IM_DELETE(bd_font_data);
src->FontLoaderData = nullptr;
}
static bool ImGui_ImplFreeType_FontBakedInit(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src)
static bool ImGui_ImplFreeType_FontBakedInit(ImFontAtlas*, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src)
{
IM_UNUSED(atlas);
float size = baked->Size;
const float ref_size = baked->OwnerFont->Sources[0]->SizePixels;
if (src->MergeMode && src->SizePixels != 0.0f)
@ -475,9 +470,8 @@ static bool ImGui_ImplFreeType_FontBakedInit(ImFontAtlas* atlas, ImFontConfig* s
return true;
}
static void ImGui_ImplFreeType_FontBakedDestroy(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src)
static void ImGui_ImplFreeType_FontBakedDestroy(ImFontAtlas*, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src)
{
IM_UNUSED(atlas);
IM_UNUSED(baked);
IM_UNUSED(src);
ImGui_ImplFreeType_FontSrcBakedData* bd_baked_data = (ImGui_ImplFreeType_FontSrcBakedData*)loader_data_for_baked_src;
@ -486,13 +480,9 @@ static void ImGui_ImplFreeType_FontBakedDestroy(ImFontAtlas* atlas, ImFontConfig
bd_baked_data->~ImGui_ImplFreeType_FontSrcBakedData(); // ~IM_PLACEMENT_DELETE()
}
static bool ImGui_ImplFreeType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src, ImWchar codepoint, ImFontGlyph* out_glyph, float* out_advance_x)
static bool ImGui_ImplFreeType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void* loader_data_for_baked_src, int glyph_index, ImFontGlyph* out_glyph, float* out_advance_x)
{
ImGui_ImplFreeType_FontSrcData* bd_font_data = (ImGui_ImplFreeType_FontSrcData*)src->FontLoaderData;
uint32_t glyph_index = FT_Get_Char_Index(bd_font_data->FtFace, codepoint);
if (glyph_index == 0)
return false;
if (bd_font_data->BakedLastActivated != baked) // <-- could use id
{
// Activate current size
@ -501,7 +491,7 @@ static bool ImGui_ImplFreeType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConf
bd_font_data->BakedLastActivated = baked;
}
const FT_Glyph_Metrics* metrics = ImGui_ImplFreeType_LoadGlyph(bd_font_data, codepoint);
const FT_Glyph_Metrics* metrics = ImGui_ImplFreeType_LoadGlyph(bd_font_data, glyph_index);
if (metrics == nullptr)
return false;
@ -530,7 +520,6 @@ static bool ImGui_ImplFreeType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConf
const bool is_visible = (w != 0 && h != 0);
// Prepare glyph
out_glyph->Codepoint = codepoint;
out_glyph->AdvanceX = advance_x;
// Pack and retrieve position inside texture atlas
@ -573,12 +562,16 @@ static bool ImGui_ImplFreeType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConf
return true;
}
static bool ImGui_ImplFreetype_FontSrcContainsGlyph(ImFontAtlas* atlas, ImFontConfig* src, ImWchar codepoint)
static int ImGui_ImplFreetype_FontSrcGetGlyphIndexFromCodepoint(ImFontAtlas*, ImFontConfig* src, ImWchar codepoint)
{
IM_UNUSED(atlas);
ImGui_ImplFreeType_FontSrcData* bd_font_data = (ImGui_ImplFreeType_FontSrcData*)src->FontLoaderData;
int glyph_index = FT_Get_Char_Index(bd_font_data->FtFace, codepoint);
return glyph_index != 0;
return (int)FT_Get_Char_Index(bd_font_data->FtFace, codepoint);
}
static bool ImGui_ImplFreeType_FontSrcContainsGlyph(ImFontAtlas*, ImFontConfig* src, int glyph_index)
{
ImGui_ImplFreeType_FontSrcData* bd_font_data = (ImGui_ImplFreeType_FontSrcData*)src->FontLoaderData;
return glyph_index > 0 && glyph_index < bd_font_data->FtFace->num_glyphs;
}
const ImFontLoader* ImGuiFreeType::GetFontLoader()
@ -589,7 +582,8 @@ const ImFontLoader* ImGuiFreeType::GetFontLoader()
loader->LoaderShutdown = ImGui_ImplFreeType_LoaderShutdown;
loader->FontSrcInit = ImGui_ImplFreeType_FontSrcInit;
loader->FontSrcDestroy = ImGui_ImplFreeType_FontSrcDestroy;
loader->FontSrcContainsGlyph = ImGui_ImplFreetype_FontSrcContainsGlyph;
loader->FontSrcGetGlyphIndexFromCodepoint = ImGui_ImplFreetype_FontSrcGetGlyphIndexFromCodepoint;
loader->FontSrcContainsGlyph = ImGui_ImplFreeType_FontSrcContainsGlyph;
loader->FontBakedInit = ImGui_ImplFreeType_FontBakedInit;
loader->FontBakedDestroy = ImGui_ImplFreeType_FontBakedDestroy;
loader->FontBakedLoadGlyph = ImGui_ImplFreeType_FontBakedLoadGlyph;