From e585204d82cf33938ff707ac2ce9ace50e4d1dad Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 20 Jan 2016 10:30:28 +0000 Subject: [PATCH] ImFontAtlas: heuristic increase texture width up to 4096 with 4000+ glyphs. Various comments (#491) --- extra_fonts/README.txt | 11 ++++++++++- imgui.cpp | 5 ++--- imgui_draw.cpp | 5 +++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/extra_fonts/README.txt b/extra_fonts/README.txt index cac98e980..b577b870d 100644 --- a/extra_fonts/README.txt +++ b/extra_fonts/README.txt @@ -2,6 +2,8 @@ The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' that you can use without any external files. Those are only provided as a convenience, you can load your own .TTF files. + Fonts are rasterized in a single texture at the time of calling either of io.Fonts.GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build(). + --------------------------------- LOADING INSTRUCTIONS --------------------------------- @@ -20,10 +22,17 @@ ImFontConfig config; config.OversampleH = 3; - config.OversampleV = 3; + config.OversampleV = 1; config.GlyphExtraSpacing.x = 1.0f; io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, &config); + If you have very large number of glyphs or multiple fonts: + + - Mind the fact that some graphics drivers have texture size limitation. + - Set io.Fonts.TexDesiredWidth to specify a texture width to minimize texture height (see comment in ImFontAtlas::Build function). + - You may reduce oversampling, e.g. config.OversampleH = 2 or 1. + - Reduce glyphs ranges, consider calculating them based on your source data if this is possible. + Combine two fonts into one: // Load main font diff --git a/imgui.cpp b/imgui.cpp index b3d48cf9c..35256f08a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -359,6 +359,7 @@ Q: How can I load multiple fonts? A: Use the font atlas to pack them into a single texture: + (Read extra_fonts/README.txt and the code in ImFontAtlas for more details.) ImGuiIO& io = ImGui::GetIO(); ImFont* font0 = io.Fonts->AddFontDefault(); @@ -371,7 +372,7 @@ // Options ImFontConfig config; config.OversampleH = 3; - config.OversampleV = 3; + config.OversampleV = 1; config.GlyphExtraSpacing.x = 1.0f; io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, &config); @@ -383,8 +384,6 @@ io.Fonts->LoadFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); - Read extra_fonts/README.txt or ImFontAtlas class for more details. - Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic? A: When loading a font, pass custom Unicode ranges to specify the glyphs to load. ImGui will support UTF-8 encoding across the board. Character input depends on you passing the right character code to io.AddInputCharacter(). The example applications do that. diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 618d5d847..d2a196fd8 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1244,8 +1244,9 @@ bool ImFontAtlas::Build() } } - // Start packing - TexWidth = (TexDesiredWidth > 0) ? TexDesiredWidth : (total_glyph_count > 2000) ? 2048 : (total_glyph_count > 1000) ? 1024 : 512; // Width doesn't actually matters much but some API/GPU have texture size limitations, and increasing width can decrease height. + // Start packing. We need a known width for the skyline algorithm. Using a cheap heuristic here to decide of width. User can override TexDesiredWidth if they wish. + // After packing is done, width shouldn't matter much, but some API/GPU have texture size limitations and increasing width can decrease height. + TexWidth = (TexDesiredWidth > 0) ? TexDesiredWidth : (total_glyph_count > 4000) ? 4096 : (total_glyph_count > 2000) ? 2048 : (total_glyph_count > 1000) ? 1024 : 512; TexHeight = 0; const int max_tex_height = 1024*32; stbtt_pack_context spc;