Skip to content

Commit 6d27fec

Browse files
committed
Debug: added DebugTextEncoding() to help diagnose between text encoding issues and font loading issues. Simplified code + extracted DebugNodeFontGlyph().
Helper to diagnose issues such as #4866, #3558, #3436, #2233, #1880, #1780, #905, #832, #762, #726, #609, #565, #307)
1 parent e668890 commit 6d27fec

File tree

5 files changed

+90
-110
lines changed

5 files changed

+90
-110
lines changed

docs/CHANGELOG.txt

+3
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ Other Changes:
8787
- Stack Tool: Added option to copy item path to clipboard. (#4631)
8888
- Drawlist: Fixed PathArcTo() emitting terminating vertices too close to arc vertices. (#4993) [@thedmd]
8989
- DrawList: Fixed texture-based anti-aliasing path with RGBA textures (#5132, #3245) [@cfillion]
90+
- Debug: Added DebugTextEncoding() function to facilitate diagnosing issues when not sure about whether
91+
you have a UTF-8 text encoding issue or a font loading issue. [@LaMarche05, @ocornut]
92+
- Metrics: Added a "UTF-8 Encoding Viewer" section using the aforementioned DebugTextEncoding() function.
9093
- Misc: Fixed calling GetID("label") _before_ a widget emitting this item inside a group (such as InputInt())
9194
from causing an assertion when closing the group. (#5181).
9295
- Misc: Fixed IsAnyItemHovered() returning false when using navigation.

docs/FONTS.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ In the [misc/fonts/](https://github.com/ocornut/imgui/tree/master/misc/fonts) fo
2929

3030
- You can use the `Metrics/Debugger` window (available in `Demo>Tools`) to browse your fonts and understand what's going on if you have an issue. You can also reach it in `Demo->Tools->Style Editor->Fonts`. The same information are also available in the Style Editor under Fonts.
3131

32-
![imgui_capture_0008](https://user-images.githubusercontent.com/8225057/135429892-0e41ef8d-33c5-4991-bcf6-f997a0bcfd6b.png)
32+
![Fonts debugging](https://user-images.githubusercontent.com/8225057/135429892-0e41ef8d-33c5-4991-bcf6-f997a0bcfd6b.png)
33+
34+
- You can use the `UTF-8 Encoding viewer` in `Metrics/Debugger` to verify the content of your UTF-8 strings. From C/C++ code, you can call `ImGui::DebugTextEncoding("my string");` function to verify that your UTF-8 encoding is correct.
35+
36+
![UTF-8 Encoding viewer](https://user-images.githubusercontent.com/8225057/166505963-8a0d7899-8ee8-4558-abb2-1ae523dc02f9.png)
3337

3438
- All loaded fonts glyphs are rendered into a single texture atlas ahead of time. Calling either of `io.Fonts->GetTexDataAsAlpha8()`, `io.Fonts->GetTexDataAsRGBA32()` or `io.Fonts->Build()` will build the atlas.
3539

imgui.cpp

+80-108
Original file line numberDiff line numberDiff line change
@@ -12060,11 +12060,15 @@ static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport*, ImGuiPlatformImeDat
1206012060
//-----------------------------------------------------------------------------
1206112061
// - RenderViewportThumbnail() [Internal]
1206212062
// - RenderViewportsThumbnails() [Internal]
12063+
// - DebugTextEncoding()
1206312064
// - MetricsHelpMarker() [Internal]
12065+
// - ShowFontAtlas() [Internal]
1206412066
// - ShowMetricsWindow()
1206512067
// - DebugNodeColumns() [Internal]
1206612068
// - DebugNodeDrawList() [Internal]
1206712069
// - DebugNodeDrawCmdShowMeshAndBoundingBox() [Internal]
12070+
// - DebugNodeFont() [Internal]
12071+
// - DebugNodeFontGlyph() [Internal]
1206812072
// - DebugNodeStorage() [Internal]
1206912073
// - DebugNodeTabBar() [Internal]
1207012074
// - DebugNodeViewport() [Internal]
@@ -12127,79 +12131,40 @@ static void RenderViewportsThumbnails()
1212712131
ImGui::Dummy(bb_full.GetSize() * SCALE);
1212812132
}
1212912133

12130-
static void ShowEncodingViewerChar(ImFont* font, ImWchar c, const char* c_utf8)
12134+
// Helper tool to diagnose between text encoding issues and font loading issues. Pass your UTF-8 string and verify that there are correct.
12135+
void ImGui::DebugTextEncoding(const char* str)
1213112136
{
12132-
ImGui::TableNextColumn();
12133-
if (font->FindGlyphNoFallback(c))
12134-
ImGui::TextUnformatted(c_utf8);
12135-
else
12136-
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "(not in font)");
12137-
12138-
ImGui::TableNextColumn();
12139-
char utf8_code[] = "0x.. 0x.. 0x.. 0x..";
12140-
for (int byte_index = 0; c_utf8[byte_index]; byte_index++)
12141-
{
12142-
if (byte_index > 0)
12143-
utf8_code[byte_index * 5 - 1] = ' ';
12144-
ImFormatString(utf8_code + (byte_index * 5) + 2, 3, "%02X", (int)(unsigned char)c_utf8[byte_index]);
12145-
}
12146-
ImGui::TextUnformatted(utf8_code);
12147-
ImGui::TableNextColumn();
12148-
ImGui::Text("U+%04X", (int)c);
12149-
}
12150-
12151-
static void ShowUTF8EncodingViewer()
12152-
{
12153-
static char buf[256] = "";
12154-
static ImFontGlyphRangesBuilder range_builder;
12155-
static ImVector<ImWchar> ranges;
12156-
static bool unique_glyphs = false;
12157-
12158-
ImGui::SetNextItemWidth(-FLT_MIN);
12159-
12160-
bool rebuild = false;
12161-
rebuild |= ImGui::InputText("##Sample Text", buf, IM_ARRAYSIZE(buf));
12162-
rebuild |= ImGui::Checkbox("Sorted unique glyphs", &unique_glyphs);
12163-
if (rebuild && unique_glyphs)
12164-
{
12165-
range_builder.Clear();
12166-
range_builder.AddText(buf);
12167-
ranges.clear();
12168-
range_builder.BuildRanges(&ranges);
12169-
}
12170-
if (ImGui::BeginTable("list", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY, ImVec2(0.0f, ImGui::GetFontSize() * 15)))
12137+
Text("Text: \"%s\"", str);
12138+
if (!BeginTable("list", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit))
12139+
return;
12140+
TableSetupColumn("Offset");
12141+
TableSetupColumn("UTF-8");
12142+
TableSetupColumn("Glyph");
12143+
TableSetupColumn("Codepoint");
12144+
TableHeadersRow();
12145+
for (const char* p = str; *p != 0; )
1217112146
{
12172-
ImGui::TableSetupColumn("Glyph");
12173-
ImGui::TableSetupColumn("UTF-8");
12174-
ImGui::TableSetupColumn("Codepoint");
12175-
ImGui::TableHeadersRow();
12176-
12177-
ImFont* font = ImGui::GetFont();
12178-
if (unique_glyphs)
12179-
{
12180-
for (int range_index = 0; range_index < ranges.Size && ranges[range_index] != 0; range_index += 2)
12181-
for (ImWchar c = ranges[range_index]; c <= ranges[range_index + 1]; c++)
12182-
{
12183-
char c_utf8[4 + 1];
12184-
ImTextStrToUtf8(c_utf8, IM_ARRAYSIZE(c_utf8), &c, &c + 1);
12185-
ShowEncodingViewerChar(font, c, c_utf8);
12186-
}
12187-
}
12147+
unsigned int c;
12148+
const int c_utf8_len = ImTextCharFromUtf8(&c, p, NULL);
12149+
TableNextColumn();
12150+
Text("%d", (int)(p - str));
12151+
TableNextColumn();
12152+
for (int byte_index = 0; byte_index < c_utf8_len; byte_index++)
12153+
{
12154+
if (byte_index > 0)
12155+
SameLine();
12156+
Text("0x%02X", (int)(unsigned char)p[byte_index]);
12157+
}
12158+
TableNextColumn();
12159+
if (GetFont()->FindGlyphNoFallback((ImWchar)c))
12160+
TextUnformatted(p, p + c_utf8_len);
1218812161
else
12189-
{
12190-
for (const char* p = buf; p[0] != 0;)
12191-
{
12192-
unsigned int c;
12193-
int c_utf8_len = ImTextCharFromUtf8(&c, p, NULL);
12194-
char c_utf8[4 + 1];
12195-
memcpy(c_utf8, p, c_utf8_len);
12196-
c_utf8[c_utf8_len] = 0;
12197-
ShowEncodingViewerChar(font, (ImWchar)c, c_utf8);
12198-
p += c_utf8_len;
12199-
}
12200-
}
12201-
ImGui::EndTable();
12162+
TextUnformatted("[missing]");
12163+
TableNextColumn();
12164+
Text("U+%04X", (int)c);
12165+
p += c_utf8_len;
1220212166
}
12167+
EndTable();
1220312168
}
1220412169

1220512170
// Avoid naming collision with imgui_demo.cpp's HelpMarker() for unity builds.
@@ -12216,9 +12181,24 @@ static void MetricsHelpMarker(const char* desc)
1221612181
}
1221712182
}
1221812183

12219-
#ifndef IMGUI_DISABLE_DEMO_WINDOWS
12220-
namespace ImGui { void ShowFontAtlas(ImFontAtlas* atlas); }
12221-
#endif
12184+
// [DEBUG] List fonts in a font atlas and display its texture
12185+
void ImGui::ShowFontAtlas(ImFontAtlas* atlas)
12186+
{
12187+
for (int i = 0; i < atlas->Fonts.Size; i++)
12188+
{
12189+
ImFont* font = atlas->Fonts[i];
12190+
PushID(font);
12191+
DebugNodeFont(font);
12192+
PopID();
12193+
}
12194+
if (TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
12195+
{
12196+
ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
12197+
ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f);
12198+
Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), tint_col, border_col);
12199+
TreePop();
12200+
}
12201+
}
1222212202

1222312203
void ImGui::ShowMetricsWindow(bool* p_open)
1222412204
{
@@ -12293,6 +12273,19 @@ void ImGui::ShowMetricsWindow(bool* p_open)
1229312273
// Tools
1229412274
if (TreeNode("Tools"))
1229512275
{
12276+
bool show_encoding_viewer = TreeNode("UTF-8 Encoding viewer");
12277+
SameLine();
12278+
MetricsHelpMarker("You can also call ImGui::DebugTextEncoding() from your code with a given string to test that your UTF-8 encoding settings are correct.");
12279+
if (show_encoding_viewer)
12280+
{
12281+
static char buf[100] = "";
12282+
SetNextItemWidth(-FLT_MIN);
12283+
InputText("##Text", buf, IM_ARRAYSIZE(buf));
12284+
if (buf[0] != 0)
12285+
DebugTextEncoding(buf);
12286+
TreePop();
12287+
}
12288+
1229612289
// Stack Tool is your best friend!
1229712290
Checkbox("Show stack tool", &cfg->ShowStackTool);
1229812291
SameLine();
@@ -12360,12 +12353,6 @@ void ImGui::ShowMetricsWindow(bool* p_open)
1236012353
}
1236112354
}
1236212355

12363-
if (TreeNode("UTF-8 Encoding viewer"))
12364-
{
12365-
ShowUTF8EncodingViewer();
12366-
TreePop();
12367-
}
12368-
1236912356
// The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted.
1237012357
if (Button("Item Picker.."))
1237112358
DebugStartItemPicker();
@@ -12461,14 +12448,12 @@ void ImGui::ShowMetricsWindow(bool* p_open)
1246112448
}
1246212449

1246312450
// Details for Fonts
12464-
#ifndef IMGUI_DISABLE_DEMO_WINDOWS
1246512451
ImFontAtlas* atlas = g.IO.Fonts;
1246612452
if (TreeNode("Fonts", "Fonts (%d)", atlas->Fonts.Size))
1246712453
{
1246812454
ShowFontAtlas(atlas);
1246912455
TreePop();
1247012456
}
12471-
#endif
1247212457

1247312458
// Details for Docking
1247412459
#ifdef IMGUI_HAS_DOCK
@@ -12628,25 +12613,6 @@ void ImGui::ShowMetricsWindow(bool* p_open)
1262812613
End();
1262912614
}
1263012615

12631-
// [DEBUG] List fonts in a font atlas and display its texture
12632-
void ImGui::ShowFontAtlas(ImFontAtlas* atlas)
12633-
{
12634-
for (int i = 0; i < atlas->Fonts.Size; i++)
12635-
{
12636-
ImFont* font = atlas->Fonts[i];
12637-
PushID(font);
12638-
DebugNodeFont(font);
12639-
PopID();
12640-
}
12641-
if (TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
12642-
{
12643-
ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
12644-
ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f);
12645-
Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), tint_col, border_col);
12646-
TreePop();
12647-
}
12648-
}
12649-
1265012616
// [DEBUG] Display contents of Columns
1265112617
void ImGui::DebugNodeColumns(ImGuiOldColumns* columns)
1265212618
{
@@ -12856,17 +12822,13 @@ void ImGui::DebugNodeFont(ImFont* font)
1285612822
ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);
1285712823
const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n));
1285812824
draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));
12859-
if (glyph)
12860-
font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n));
12861-
if (glyph && IsMouseHoveringRect(cell_p1, cell_p2))
12825+
if (!glyph)
12826+
continue;
12827+
font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n));
12828+
if (IsMouseHoveringRect(cell_p1, cell_p2))
1286212829
{
1286312830
BeginTooltip();
12864-
Text("Codepoint: U+%04X", base + n);
12865-
Separator();
12866-
Text("Visible: %d", glyph->Visible);
12867-
Text("AdvanceX: %.1f", glyph->AdvanceX);
12868-
Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
12869-
Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
12831+
DebugNodeFontGlyph(font, glyph);
1287012832
EndTooltip();
1287112833
}
1287212834
}
@@ -12878,6 +12840,16 @@ void ImGui::DebugNodeFont(ImFont* font)
1287812840
TreePop();
1287912841
}
1288012842

12843+
void ImGui::DebugNodeFontGlyph(ImFont*, const ImFontGlyph* glyph)
12844+
{
12845+
Text("Codepoint: U+%04X", glyph->Codepoint);
12846+
Separator();
12847+
Text("Visible: %d", glyph->Visible);
12848+
Text("AdvanceX: %.1f", glyph->AdvanceX);
12849+
Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
12850+
Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
12851+
}
12852+
1288112853
// [DEBUG] Display contents of ImGuiStorage
1288212854
void ImGui::DebugNodeStorage(ImGuiStorage* storage, const char* label)
1288312855
{

imgui.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,7 @@ namespace ImGui
919919
IMGUI_API const char* SaveIniSettingsToMemory(size_t* out_ini_size = NULL); // return a zero-terminated string with the .ini data which you can save by your own mean. call when io.WantSaveIniSettings is set, then save data by your own mean and clear io.WantSaveIniSettings.
920920

921921
// Debug Utilities
922-
// - This is used by the IMGUI_CHECKVERSION() macro.
922+
IMGUI_API void DebugTextEncoding(const char* text);
923923
IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro.
924924

925925
// Memory Allocators

imgui_internal.h

+1
Original file line numberDiff line numberDiff line change
@@ -2871,6 +2871,7 @@ namespace ImGui
28712871
IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list, const char* label);
28722872
IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb);
28732873
IMGUI_API void DebugNodeFont(ImFont* font);
2874+
IMGUI_API void DebugNodeFontGlyph(ImFont* font, const ImFontGlyph* glyph);
28742875
IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label);
28752876
IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label);
28762877
IMGUI_API void DebugNodeTable(ImGuiTable* table);

0 commit comments

Comments
 (0)