diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 8061997cf..998b25427 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -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. diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 3c62c2229..6a381b703 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -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*)¤t_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(); diff --git a/backends/imgui_impl_opengl3.h b/backends/imgui_impl_opengl3.h index 733fc40fd..6d6325940 100644 --- a/backends/imgui_impl_opengl3.h +++ b/backends/imgui_impl_opengl3.h @@ -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) diff --git a/backends/imgui_impl_opengl3_loader.h b/backends/imgui_impl_opengl3_loader.h index 34b262dff..47f9fb364 100644 --- a/backends/imgui_impl_opengl3_loader.h +++ b/backends/imgui_impl_opengl3_loader.h @@ -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); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index bc158639f..324777259 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -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). diff --git a/imconfig.h b/imconfig.h index a25fa89af..d9c05692f 100644 --- a/imconfig.h +++ b/imconfig.h @@ -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. diff --git a/imgui.cpp b/imgui.cpp index 16d33fa68..a604fa497 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -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++; diff --git a/imgui.h b/imgui.h index a2c9f084d..310248f2d 100644 --- a/imgui.h +++ b/imgui.h @@ -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) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index bce46bcd5..86d5f097b 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -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; diff --git a/imgui_internal.h b/imgui_internal.h index 0b782b6f3..4029c3358 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -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? diff --git a/imgui_tables.cpp b/imgui_tables.cpp index b3e0458eb..5ba6cb28f 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -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; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index d7f4186e5..c7a61ac7e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -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; diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 2e2e78f7d..375863fdf 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -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;