Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loading Chinese front is too slow on opengl2 & glfw2. #5811

Closed
kekxv opened this issue Oct 22, 2022 · 6 comments
Closed

Loading Chinese front is too slow on opengl2 & glfw2. #5811

kekxv opened this issue Oct 22, 2022 · 6 comments

Comments

@kekxv
Copy link

kekxv commented Oct 22, 2022

ImGui_ImplOpenGL2_NewFrame() takes more than 30 seconds When I load the Chinese font.

load front code

ImFont *ImGui::load_system_font(const std::string &font_name, float front_size) {
    std::string path;
    std::string font_path;
    std::vector<std::string> files;
    if(!font_name.empty()) {
        tools::get_files(tools::get_local_path(), files, font_name);
        if (!files.empty()) {
            font_path = files[0];
        }
    }
    if (font_name.empty() || !tools::exists(font_path)) {
#if defined(WIN32)
        char winpath[MAX_PATH+3];
        memset(winpath,0x00,MAX_PATH+3);
        GetWindowsDirectory(winpath, sizeof(winpath));
        path = tools::make_path(winpath,"Fonts");
#elif defined(__APPLE__)
        path = "/System/Library/Fonts";
#else
        path = "/usr/share/fonts";
#endif
        if (!tools::exists(path)) {
            return nullptr;
        }
        std::string fonts[] = {
                "PingFang.ttc",
                "DejaVuSans.ttf",
                "STHeiti Light.ttc",

                "STSONG.TTF",
                "STXINWEI.TTF",
                "STFANGSO.TTF",
                "STXINGKA.TTF",

                "msyhl.ttc",
                "msjh.ttc",
                "msyh.ttf",

                // "simsun.ttc",
                // "simfang.ttf",
        };
        for (const auto &item: fonts) {
            font_path = tools::find_exists_file(item, path);
            if (!font_path.empty()) {
                break;
            }
        }
    }
    tools::push_info("load font path : " + font_path);
    if (font_path.empty()) {
        return nullptr;
    }

    // Load Fonts
    ImGuiIO &io = ImGui::GetIO();
    // 加载并支持中文字体
    return io.Fonts->AddFontFromFileTTF(font_path.c_str(), front_size, nullptr,
                                        // io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
                                        io.Fonts->GetGlyphRangesChineseFull());
}
@kekxv kekxv changed the title load front chinese Loading Chinese front is too slow on opengl2 & glfw2. Oct 22, 2022
@thedemons
Copy link
Contributor

I don't believe this has anything to do with the backends. The reason it stuck at ImGui_ImplOpenGL2_NewFrame is due to the font hasn't been built yet so it was built on demand.

You can build it before entering the render loop using this, to see if the problem really is because of building the font:

io.Fonts->Build();

Dear ImGui has two official font rasterizers, TrueType (default option) and FreeType, this is what responsible for building the fonts, assuming you're using the TrueType rasterizer, you can measure the performance of the ImFontAtlasBuildWithStbTruetype function to make sure that's the problem.

If it is really that slow, what you could do is build once and write the atlas texture into an image, use it as a cache then load the atlas from it. It requires a lot of code and modifications so I'm not sure if I want to post it here.

@ocornut
Copy link
Owner

ocornut commented Oct 22, 2022

Its going to be slow if you load full ranges.
Until we have dynamic font atlas loading the only workarounds are: reducing OversampleH to 1 to divide the time by three, use a custom glyph range using ImGuiGlyphRangeBuilder.

See https://github.com/ocornut/imgui/blob/master/docs/FONTS.md for references.

@thedemons
Copy link
Contributor

@ocornut Also, why isn't there an option to use a cached atlas instead of building it every time making the load time longer? Is there any reason not to do so?

@rorschach-py
Copy link

GetGlyphRangesChineseFull is slow, GetGlyphRangesChineseSimplifiedCommon lacks lots of common chars
try this:

// make sure source file is utf8
// add extra chinese char, search: 通用规范汉字表 8105字  
// or load it from txt file
const char * font_char = "一丁七万丈三上下不与丐丑专且丕世丘丙业……";

ImVector<ImWchar> ranges;
ImFontGlyphRangesBuilder builder;

builder.AddRanges(io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
builder.AddText(font_char);
builder.BuildRanges(&ranges);
    
io.Fonts->AddFontFromFileTTF(CFG.font, CFG.fontsize,      NULL, ranges.Data);

@kekxv
Copy link
Author

kekxv commented Oct 23, 2022

using PingFang.ttc is fast.

slow front:

  • msyhl.ttc
  • simsun.ttc

@ocornut
Copy link
Owner

ocornut commented Mar 6, 2025

FYI, work on dynamic_fonts branch aimed to be merged in 1.92 (#8465) solves this, as glyphs are rasterized and packed on demand when they are used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants