Skip to content

Commit 9abcb7e

Browse files
committed
ImFont: Demo, Store Used4kPagesMap[] map in ImFont to facilitate iteration on all codepoints with a large value of IM_UNICODE_MAX_CODEPOINT. Demo uses IsGlyphRangeUnused()
(cherry picked from commit e56f8f0219ef442cd9d7f513343ee19ec2c9ce91)
1 parent 949452a commit 9abcb7e

File tree

3 files changed

+29
-0
lines changed

3 files changed

+29
-0
lines changed

imgui.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2210,6 +2210,7 @@ struct ImFont
22102210
float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale()
22112211
float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize]
22122212
int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs)
2213+
ImU8 Used4kPagesMap[IM_UNICODE_MAX_CODEPOINT/4096/8]; // 2 bytes if ImWchar=ImWchar16, 34 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations accross all used codepoints.
22132214
bool DirtyLookupTables; // 1 // out //
22142215

22152216
// Methods
@@ -2235,6 +2236,7 @@ struct ImFont
22352236
IMGUI_API void AddGlyph(ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x);
22362237
IMGUI_API void AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built.
22372238
IMGUI_API void SetFallbackChar(ImWchar c);
2239+
IMGUI_API bool IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last);
22382240
};
22392241

22402242
#if defined(__clang__)

imgui_demo.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3418,6 +3418,14 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
34183418
// Display all glyphs of the fonts in separate pages of 256 characters
34193419
for (unsigned int base = 0; base < IM_UNICODE_MAX_CODEPOINT; base += 256)
34203420
{
3421+
// Skip ahead if a large bunch of glyphs are not present in the font (test in chunks of 4k)
3422+
// This is only a small optimization to reduce the number of iterations when IM_UNICODE_MAX_CODEPOINT is large.
3423+
if (!(base & 4095) && font->IsGlyphRangeUnused(base, base + 4095))
3424+
{
3425+
base += 4096 - 256;
3426+
continue;
3427+
}
3428+
34213429
int count = 0;
34223430
for (unsigned int n = 0; n < 256; n++)
34233431
count += font->FindGlyphNoFallback((ImWchar)(base + n)) ? 1 : 0;

imgui_draw.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2498,6 +2498,7 @@ ImFont::ImFont()
24982498
Scale = 1.0f;
24992499
Ascent = Descent = 0.0f;
25002500
MetricsTotalSurface = 0;
2501+
memset(Used4kPagesMap, 0, sizeof(Used4kPagesMap));
25012502
}
25022503

25032504
ImFont::~ImFont()
@@ -2529,12 +2530,17 @@ void ImFont::BuildLookupTable()
25292530
IndexAdvanceX.clear();
25302531
IndexLookup.clear();
25312532
DirtyLookupTables = false;
2533+
memset(Used4kPagesMap, 0, sizeof(Used4kPagesMap));
25322534
GrowIndex(max_codepoint + 1);
25332535
for (int i = 0; i < Glyphs.Size; i++)
25342536
{
25352537
int codepoint = (int)Glyphs[i].Codepoint;
25362538
IndexAdvanceX[codepoint] = Glyphs[i].AdvanceX;
25372539
IndexLookup[codepoint] = (ImWchar)i;
2540+
2541+
// Mark 4K page as used
2542+
const int page_n = codepoint / 4096;
2543+
Used4kPagesMap[page_n >> 3] |= 1 << (page_n & 7);
25382544
}
25392545

25402546
// Create a glyph to handle TAB
@@ -2558,6 +2564,19 @@ void ImFont::BuildLookupTable()
25582564
IndexAdvanceX[i] = FallbackAdvanceX;
25592565
}
25602566

2567+
// API is designed this way to avoid exposing the 4K page size
2568+
// e.g. use with IsGlyphRangeUnused(0, 255)
2569+
bool ImFont::IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last)
2570+
{
2571+
unsigned int page_begin = (c_begin / 4096);
2572+
unsigned int page_last = (c_last / 4096);
2573+
for (unsigned int page_n = page_begin; page_n <= page_last; page_n++)
2574+
if ((page_n >> 3) < sizeof(Used4kPagesMap))
2575+
if (Used4kPagesMap[page_n >> 3] & (1 << (page_n & 7)))
2576+
return false;
2577+
return true;
2578+
}
2579+
25612580
void ImFont::SetFallbackChar(ImWchar c)
25622581
{
25632582
FallbackChar = c;

0 commit comments

Comments
 (0)