Fonts: added ImFont::AddRemapCodepointToGlyphIndex(). (#9559, #5647, #609, #5748, #8466)

This commit is contained in:
ocornut 2026-09-30 18:41:31 +02:00
parent dfa3c0c0bb
commit 7263a23f1b
2 changed files with 60 additions and 13 deletions

View File

@ -3967,7 +3967,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 AddRemapCodepoint(), 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
@ -3994,8 +3994,9 @@ struct ImFont
// [Internal] Don't use!
IMGUI_API void ClearOutputData();
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) { AddRemapCodepointToCodepoint(from_codepoint, to_codepoint); } // Renamed in 1.93.0 (Oct 2026)
//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

@ -4565,14 +4565,43 @@ static void ImFontBaked_BuildGrowIndex(ImFontBaked* baked, int new_size)
// Remap a codepoint to another codepoint
void ImFont::AddRemapCodepoint(ImWchar from_codepoint, ImWchar to_codepoint)
{
RemapPairs.SetInt((ImGuiID)from_codepoint, (int)to_codepoint);
ImU32 data = (ImU32)to_codepoint;
IM_ASSERT((data & (1u << 31)) == 0);
RemapPairs.SetInt((ImGuiID)from_codepoint, (int)data);
}
static void ImFontAtlas_FontHookRemapCodepoint(ImFontAtlas* atlas, ImFont* font, ImWchar* c)
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 +4618,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));
@ -4609,10 +4639,19 @@ static ImFontGlyph* ImFontBaked_BuildLoadGlyph(ImFontBaked* baked, ImWchar codep
const ImFontLoader* loader = src->FontLoader ? src->FontLoader : atlas->FontLoader;
loader_user_data_p_next = loader_user_data_p + loader->FontBakedSrcLoaderDataSize;
if (src->GlyphExcludeRanges && !ImFontAtlasBuildAcceptCodepointForSource(src, codepoint))
continue;
int glyph_index = loader->FontSrcGetGlyphIndexFromCodepoint(atlas, src, codepoint);
int glyph_index;
if (src_codepoint != (ImWchar)-1)
{
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;
@ -4623,7 +4662,6 @@ static ImFontGlyph* ImFontBaked_BuildLoadGlyph(ImFontBaked* baked, ImWchar codep
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.Codepoint = src_codepoint;
glyph_buf.SourceIdx = src_n;
return ImFontAtlasBakedAddFontGlyph(atlas, baked, src, &glyph_buf);
}
@ -5401,7 +5439,15 @@ 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;