diff --git a/misc/fonts/README.txt b/misc/fonts/README.txt index 2287f6eaa..a3774ca77 100644 --- a/misc/fonts/README.txt +++ b/misc/fonts/README.txt @@ -120,9 +120,7 @@ In this document: Dear Imgui uses stb_truetype.h to rasterize fonts (with optional oversampling). This technique and implementation are not ideal for fonts rendered at _small sizes_, which may appear a little blurry. - There is an implementation of the ImFontAtlas builder using FreeType that you can use: - - https://github.com/ocornut/imgui_club + There is an implementation of the ImFontAtlas builder using FreeType that you can use in the misc/freetype/ folder. FreeType supports auto-hinting which tends to improve the readability of small fonts. Note that this code currently creates textures that are unoptimally too large (could be fixed with some work) diff --git a/misc/freetype/README.md b/misc/freetype/README.md new file mode 100644 index 000000000..8b5d01d43 --- /dev/null +++ b/misc/freetype/README.md @@ -0,0 +1,126 @@ +# imgui_freetype + +This is an attempt to replace stb_truetype (the default imgui's font rasterizer) with FreeType. +Currently not optimal and probably has some limitations or bugs. +By [Vuhdo](https://github.com/Vuhdo) (Aleksei Skriabin). Improvements by @mikesart. Maintained by @ocornut. + +**Usage** +1. Get latest FreeType binaries or build yourself. +2. Add imgui_freetype.h/cpp alongside your imgui sources. +3. Include imgui_freetype.h after imgui.h. +4. Call ImGuiFreeType::BuildFontAtlas() *BEFORE* calling ImFontAtlas::GetTexDataAsRGBA32() or ImFontAtlas::Build() (so normal Build() won't be called): + +```cpp +// See ImGuiFreeType::RasterizationFlags +unsigned int flags = ImGuiFreeType::DisableHinting; +ImGuiFreeType::BuildFontAtlas(io.Fonts, flags); +io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); +``` + +**Test code Usage** +```cpp +#include "misc/freetype/imgui_freetype.h" +#include "misc/freetype/imgui_freetype.cpp" + +// Load various small fonts +ImGuiIO& io = ImGui::GetIO(); +io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 13.0f); +io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 13.0f); +io.Fonts->AddFontDefault(); + +FreeTypeTest freetype_test; + +// Main Loop +while (true) +{ + if (freetype_test.UpdateRebuild()) + { + // REUPLOAD FONT TEXTURE TO GPU + // e.g ImGui_ImplGlfwGL3_InvalidateDeviceObjects() + ImGui_ImplGlfwGL3_CreateDeviceObjects() + } + ImGui::NewFrame(); + freetype_test.ShowFreetypeOptionsWindow(); + ... + } +} +``` + +**Test code** +```cpp +#include "misc/freetype/imgui_freetype.h" +#include "misc/freetype/imgui_freetype.cpp" + +struct FreeTypeTest +{ + enum FontBuildMode + { + FontBuildMode_FreeType, + FontBuildMode_Stb, + }; + + FontBuildMode BuildMode; + bool WantRebuild; + float FontsMultiply; + unsigned int FontsFlags; + + FreeTypeTest() + { + BuildMode = FontBuildMode_FreeType; + WantRebuild = true; + FontsMultiply = 1.0f; + FontsFlags = 0; + } + + // Call _BEFORE_ NewFrame() + bool UpdateRebuild() + { + if (!WantRebuild) + return false; + ImGuiIO& io = ImGui::GetIO(); + for (int n = 0; n < io.Fonts->Fonts.Size; n++) + { + io.Fonts->Fonts[n]->ConfigData->RasterizerMultiply = FontsMultiply; + io.Fonts->Fonts[n]->ConfigData->RasterizerFlags = (BuildMode == FontBuildMode_FreeType) ? FontsFlags : 0x00; + } + if (BuildMode == FontBuildMode_FreeType) + ImGuiFreeType::BuildFontAtlas(io.Fonts, FontsFlags); + else if (BuildMode == FontBuildMode_Stb) + io.Fonts->Build(); + WantRebuild = false; + return true; + } + + // Call to draw interface + void ShowFreetypeOptionsWindow() + { + ImGui::Begin("FreeType Options"); + ImGui::ShowFontSelector("Fonts"); + WantRebuild |= ImGui::RadioButton("FreeType", (int*)&BuildMode, FontBuildMode_FreeType); + ImGui::SameLine(); + WantRebuild |= ImGui::RadioButton("Stb (Default)", (int*)&BuildMode, FontBuildMode_Stb); + WantRebuild |= ImGui::DragFloat("Multiply", &FontsMultiply, 0.001f, 0.0f, 2.0f); + if (BuildMode == FontBuildMode_FreeType) + { + WantRebuild |= ImGui::CheckboxFlags("NoHinting", &FontsFlags, ImGuiFreeType::NoHinting); + WantRebuild |= ImGui::CheckboxFlags("NoAutoHint", &FontsFlags, ImGuiFreeType::NoAutoHint); + WantRebuild |= ImGui::CheckboxFlags("ForceAutoHint", &FontsFlags, ImGuiFreeType::ForceAutoHint); + WantRebuild |= ImGui::CheckboxFlags("LightHinting", &FontsFlags, ImGuiFreeType::LightHinting); + WantRebuild |= ImGui::CheckboxFlags("MonoHinting", &FontsFlags, ImGuiFreeType::MonoHinting); + WantRebuild |= ImGui::CheckboxFlags("Bold", &FontsFlags, ImGuiFreeType::Bold); + WantRebuild |= ImGui::CheckboxFlags("Oblique", &FontsFlags, ImGuiFreeType::Oblique); + } + ImGui::End(); + } +}; +``` + +**Known issues** +- Output texture has excessive resolution (lots of vertical waste) +- FreeType's memory allocator is not overridden. + +**Obligatory comparison screenshots** + +Using Windows built-in segoeui.ttf font. Open in new browser tabs, view at 1080p+. + +![freetype rasterizer](https://raw.githubusercontent.com/wiki/ocornut/imgui_club/images/freetype_20170817.png) + diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 968d7f17d..9a04ed89e 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -1,16 +1,17 @@ // Wrapper to use Freetype (instead of stb_truetype) for Dear ImGui -// Get latest version at http://www.github.com/ocornut/imgui_club -// Original code by @Vuhdo (Aleksei Skriabin) +// Get latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype +// Original code by @Vuhdo (Aleksei Skriabin). Improvements by @mikesart. Maintained by @ocornut // Changelog: -// - v0.50: (2017/08/16) imported from https://github.com/Vuhdo/imgui_freetype, updated for latest changes in ImFontAtlas, minor tweaks. +// - v0.50: (2017/08/16) imported from https://github.com/Vuhdo/imgui_freetype into http://www.github.com/ocornut/imgui_club, updated for latest changes in ImFontAtlas, minor tweaks. // - v0.51: (2017/08/26) cleanup, optimizations, support for ImFontConfig::RasterizerFlags, ImFontConfig::RasterizerMultiply. // - v0.52: (2017/09/26) fixes for imgui internal changes // - v0.53: (2017/10/22) minor inconsequential change to match change in master (removed an unnecessary statement) // - v0.54: (2018/01/22) fix for addition of ImFontAtlas::TexUvscale member +// - v0.55: (2018/02/04) moved to main imgui repository (away from http://www.github.com/ocornut/imgui_club) -// Todo/Bugs: -// - Font size has lots of waste. +// TODO: +// - Output texture has excessive resolution (lots of vertical waste) // - FreeType's memory allocator is not overridden. #include "imgui_freetype.h" diff --git a/misc/freetype/imgui_freetype.h b/misc/freetype/imgui_freetype.h index f82dbc3b4..b8062bf71 100644 --- a/misc/freetype/imgui_freetype.h +++ b/misc/freetype/imgui_freetype.h @@ -1,6 +1,6 @@ // Wrapper to use Freetype (instead of stb_truetype) for Dear ImGui -// Original code by @Vuhdo -// Get latest version at http://www.github.com/ocornut/imgui_club +// Get latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype +// Original code by @Vuhdo (Aleksei Skriabin), maintained by @ocornut #pragma once @@ -8,10 +8,10 @@ namespace ImGuiFreeType { - // Hinting greatly impacts visuals (and glyph sizes). - // When disabled, FreeType generates blurrier glyphs, more or less matches the stb's output. - // The Default hinting mode usually looks good, but may distort glyphs in an unusual way. - // The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer. + // Hinting greatly impacts visuals (and glyph sizes). + // When disabled, FreeType generates blurrier glyphs, more or less matches the stb's output. + // The Default hinting mode usually looks good, but may distort glyphs in an unusual way. + // The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer. // You can set those flags on a per font basis in ImFontConfig::RasterizerFlags. // Use the 'extra_flags' parameter of BuildFontAtlas() to force a flag on all your fonts. @@ -24,7 +24,7 @@ namespace ImGuiFreeType LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text. MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output. Bold = 1 << 5, // Styling: Should we artificially embolden the font? - Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style? + Oblique = 1 << 6 // Styling: Should we slant the font, emulating italic style? }; IMGUI_API bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags = 0);