From 0aed89e880ab861e395652ea462e50c0f9762095 Mon Sep 17 00:00:00 2001 From: s-celles Date: Mon, 17 Aug 2026 14:46:57 +0200 Subject: [PATCH] FreeType: bake color glyphs (COLR/COLRv1/sbix) as BGRA instead of an empty bitmap When ImGuiFreeTypeLoaderFlags_LoadColor is set, add FT_LOAD_RENDER to the FreeType LoadFlags so color glyphs (COLR/COLRv1/sbix/CBDT) produce a BGRA bitmap immediately during FT_Load_Glyph. In FontBakedLoadGlyph, skip the subsequent FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL) when the glyph is already a bitmap (slot->format == FT_GLYPH_FORMAT_BITMAP), because re-rendering with FT_RENDER_MODE_NORMAL discards the color layers and, for pure-COLR glyphs (no traditional outline), yields an empty bitmap -- so color emoji never bakes and AddText renders nothing. Monochrome fonts are unaffected: they have no color layers, so FT_LOAD_COLOR is a no-op for them and the existing FT_RENDER_MODE_NORMAL path runs as before (slot->format stays FT_GLYPH_FORMAT_OUTLINE until the explicit FT_Render_Glyph call). --- misc/freetype/imgui_freetype.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 79dff8bfb..7c5b7fad7 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -206,7 +206,18 @@ bool ImGui_ImplFreeType_FontSrcData::InitFont(FT_Library ft_library, const ImFon LoadFlags |= FT_LOAD_TARGET_NORMAL; if (UserFlags & ImGuiFreeTypeLoaderFlags_LoadColor) + { LoadFlags |= FT_LOAD_COLOR; + // Auto-render during FT_Load_Glyph so color glyphs (COLR/COLRv1/ + // sbix/CBDT) produce a BGRA bitmap immediately. Without + // FT_LOAD_RENDER, FT_Load_Glyph leaves the glyph unrendered and + // the later FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL) call in + // FontBakedLoadGlyph would render only the base outline (monochrome) + // -- for pure-COLR glyphs that yields an empty bitmap and the emoji + // never bakes. FontBakedLoadGlyph skips re-rendering when + // slot->format == FT_GLYPH_FORMAT_BITMAP. + LoadFlags |= FT_LOAD_RENDER; + } return true; } @@ -515,9 +526,18 @@ static bool ImGui_ImplFreeType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConf return true; } - // Render glyph into a bitmap (currently held by FreeType) + // Render glyph into a bitmap (currently held by FreeType). + // When FT_LOAD_COLOR was requested and FreeType already rendered a + // color bitmap (slot->format == FT_GLYPH_FORMAT_BITMAP, pixel_mode + // BGRA) during FT_Load_Glyph -- because we add FT_LOAD_RENDER to + // LoadFlags when LoadColor is set -- do NOT re-render with + // FT_RENDER_MODE_NORMAL, which would discard the color layers and + // for pure-COLR glyphs yield an empty bitmap. Only call + // FT_Render_Glyph when the glyph is not yet rendered (outline form). FT_Render_Mode render_mode = (bd_font_data->UserFlags & ImGuiFreeTypeLoaderFlags_Monochrome) ? FT_RENDER_MODE_MONO : FT_RENDER_MODE_NORMAL; - FT_Error error = FT_Render_Glyph(slot, render_mode); + FT_Error error = 0; + if (slot->format != FT_GLYPH_FORMAT_BITMAP) + error = FT_Render_Glyph(slot, render_mode); const FT_Bitmap* ft_bitmap = &slot->bitmap; if (error != 0 || ft_bitmap == nullptr) return false;