imgui_bundle icon indicating copy to clipboard operation
imgui_bundle copied to clipboard

How to load fonts with specific glyph ranges (e.g., Chinese, Japanese, Korean) using hello_imgui.load_font

Open inkydragon opened this issue 1 year ago • 12 comments
trafficstars

env:

  • Python imgui-bundle 1.3.0

https://github.com/pthom/imgui_bundle/blob/541ed1a1a25437cd196e53926676ff0c75174fff/bindings/imgui_bundle/imgui/init.pyi#L9451-L9460

struct ImFontConfig
{
	// ...

    ImVec2          GlyphExtraSpacing;      // 0, 0     // Extra spacing (in pixels) between glyphs. Only X axis is supported for now.
    ImVec2          GlyphOffset;            // 0, 0     // Offset all glyphs from this font input.
    const ImWchar*  GlyphRanges;            // NULL     // THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list).
    float           GlyphMinAdvanceX;       // 0        // Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font
    float           GlyphMaxAdvanceX;       // FLT_MAX  // Maximum AdvanceX for glyphs

	// ...
};

https://github.com/ocornut/imgui/blame/d3c3514a59bb31406c954c2b525f330e9d167845/imgui.h#L2889

Context

I want to load Chinese fonts and specify glyph_range.

test code
void LoadDefaultFont_WithFontAwesomeIcons()
{
    std::string fontFilename = "fonts/SarasaUiSC-Regular.ttf";
    if (HelloImGui::AssetExists(fontFilename))
    {
        HelloImGui::FontLoadingParams fontLoadingParams;
        fontLoadingParams.mergeFontAwesome = true;
        // NOTE
        fontLoadingParams.fontConfig.GlyphRanges =
            ImGui::GetIO().Fonts->GetGlyphRangesChineseSimplifiedCommon();
        ImFont* font = LoadFont(fontFilename, 15.f, fontLoadingParams);
        (void) font;
    }
    else
    {
        ImGui::GetIO().Fonts->AddFontDefault();
    }
}
def load_default_font_with_fa_icon():
    font_filename = "fonts/SarasaUiSC-Regular.ttf"
    if hello_imgui.asset_exists(font_filename):
        font_loading_params = hello_imgui.FontLoadingParams()
        font_loading_params.merge_font_awesome = True
        sc_cn_range = imgui.get_io().fonts.get_glyph_ranges_chinese_simplified_common()
        # font_loading_params.font_config.??? = sc_cn_range
        hello_imgui.load_font(font_filename, 15.0, font_loading_params)
        logger.info(f"Loaded font: {font_filename}")
    else:
        imgui.get_io().fonts.add_font_default()
        logger.info(f"Loaded default font.")
Workaround
def load_default_font_with_fa_icon():
    font_filename = "fonts/SarasaUiSC-Regular.ttf"
    if hello_imgui.asset_exists(font_filename):
        sc_cn_range = imgui.get_io().fonts.get_glyph_ranges_chinese_simplified_common()
        imgui.get_io().fonts.add_font_from_file_ttf(
            hello_imgui.asset_file_full_path(font_filename),
            24.0,
            glyph_ranges_as_int_list=sc_cn_range)

        # font_loading_params = hello_imgui.FontLoadingParams()
        # font_loading_params.merge_font_awesome = True
        # # font_loading_params.font_config.??? = sc_cn_range
        # hello_imgui.load_font(font_filename, 15.0, font_loading_params)
        logger.info(f"Loaded font: {font_filename}")
    else:
        imgui.get_io().fonts.add_font_default()
        logger.info(f"Loaded default font.")

inkydragon avatar Mar 29 '24 21:03 inkydragon

I don't understand your question (there is none in your message, in fact). Does your work around work?

pthom avatar Mar 29 '24 22:03 pthom

Hello,

I come back to this question after a few months, sorry for the delay.

I understand that you needed a way to translate the glyph ranges coming from Dear ImGui, into ranges used by hello_imgui.load_font.

This commit adds support for this.

Example usage:

"""Demonstrates how to load a font with Chinese characters and display them in the GUI,
using the common glyph ranges defined in by ImGui.
"""
from imgui_bundle import imgui, hello_imgui, imgui_ctx
from imgui_bundle.demos_python import demo_utils


demo_utils.set_hello_imgui_demo_assets_folder()


font_cn: imgui.ImFont = None


def load_font():
    global font_cn
    if not hello_imgui.asset_exists("fonts/NotoSerifSC-VariableFont_wght.ttf"):
        return

    # Note: this font is not provided with the ImGui bundle (too large).
    # You will need to provide it yourself, or use another font.
    font_filename = "fonts/NotoSerifSC-VariableFont_wght.ttf"

    # The range of Chinese characters is defined by ImGui as a single list of characters (List[ImWchar]), with a terminating 0.
    # (each range is a pair of successive characters in this list, with the second character being the last one in the range)
    cn_glyph_ranges_imgui = imgui.get_io().fonts.get_glyph_ranges_chinese_simplified_common()
    # We need to convert this list into a list of pairs (List[ImWcharPair]), where each pair is a range of characters.
    cn_glyph_ranges_pair = hello_imgui.translate_common_glyph_ranges(cn_glyph_ranges_imgui)

    font_loading_params = hello_imgui.FontLoadingParams()
    font_loading_params.glyph_ranges = cn_glyph_ranges_pair
    font_cn = hello_imgui.load_font(font_filename, 40.0, font_loading_params)


def gui():
    if font_cn is not None:
        with imgui_ctx.push_font(font_cn):
            imgui.text("Hello world")
            imgui.text("你好,世界")
    else:
        imgui.text("Font file not found")
        imgui.text_wrapped("""
        This font is not provided with the ImGui bundle (too large).
        You will need to provide it yourself, or use another font.
        """)


runner_params = hello_imgui.RunnerParams()
runner_params.callbacks.load_additional_fonts = load_font
runner_params.callbacks.show_gui = gui
hello_imgui.run(runner_params)

image

pthom avatar Jul 06 '24 20:07 pthom