(You may browse this at https://github.com/ocornut/imgui/blob/master/docs/FONTS.md or view this file with any Markdown viewer)
The code in imgui.cpp embeds a copy of ProggyClean.ttf (by Tristan Grimmer), a 13 pixels high, pixel-perfect font used by default. We embed it in the source code so you can use Dear ImGui without any file system access. ProggyClean does not scale smoothly, therefore it is recommended that you load your own file when using Dear ImGui in an application aiming to look nice and wanting to support multiple resolutions.
You may also load external .TTF/.OTF files. In the misc/fonts/ folder you can find a few suggested fonts, provided as a convenience.
Also read the FAQ: https://www.dearimgui.com/faq (there is a Fonts section!)
A vast majority of font and text related issues encountered comes from 4 things:
\
or unexpected working directory.See About Filenames. AddFontXXX() functions should assert if the filename is incorrect.
See About UTF-8 Encoding. Use the encoding viewer to confirm encoding of string literal in your source code is correct.
🆕 Since 1.92, with an up to date backend: specifying glyph ranges is unnecessary.
⏪ Before 1.92: you need to load a font with explicit glyph ranges if you want to use non-ASCII characters. See Fonts Loading Instructions. Use Debug Tools confirm loaded fonts and loaded glyph ranges.
This was a previous constraint of Dear ImGui (lifted in 1.92): when loading a font you need to specify which characters glyphs to load.
All loaded fonts glyphs are rendered into a single texture atlas ahead of time. Calling either of io.Fonts->GetTexDataAsAlpha8()
, io.Fonts->GetTexDataAsRGBA32()
or io.Fonts->Build()
will build the atlas. This is generally called by the Renderer backend, e.g. ImGui_ImplDX11_NewFrame()
calls it. If you use custom glyphs ranges, make sure the array is persistent and available during the calls to GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build()
.
🆕 Since 1.92, with an up to date backend: atlas is built incrementally and dynamically resized, this is less likely to happen
:rewind: This is often of byproduct of point 3. If you have large number of glyphs or multiple fonts, the texture may become too big for your graphics API. The typical result of failing to upload a texture is if every glyph or everything appears as empty white rectangles. Mind the fact that some graphics drivers have texture size limitation. If you are building a PC application, mind the fact that your users may use hardware with lower limitations than yours.
Some solutions:
font_config.OversampleH = 1
, this will half your texture size for a quality loss.
Note that while OversampleH = 2 looks visibly very close to 3 in most situations, with OversampleH = 1 the quality drop will be noticeable. Read about oversampling here.ImFontGlyphRangesBuilder
for this purpose and rebuilding your atlas between frames when new characters are needed. This will be the biggest win!io.Fonts.Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;
to disable rounding the texture height to the next power of two.v1.92 introduces a newer, dynamic font system. It requires backend to support the ImGuiBackendFlags_HasTextures
feature:
PushFont(NULL, new_size)
may be used anytime to change font size.See #8465 for more details.
See FAQ entry.
Load default font:
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontDefault();
Load .TTF/.OTF file with:
🆕 Since 1.92, with an up to date backend: passing a size is not necessary
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontFromFileTTF("font.ttf");
:rewind: Before 1.92, or without an up to date backend:
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels);
If you get an assert stating "Could not load font file!", your font filename is likely incorrect. Read About filenames carefully.
Load multiple fonts:
// Init
ImGuiIO& io = ImGui::GetIO();
ImFont* font1 = io.Fonts->AddFontFromFileTTF("font.ttf",);
ImFont* font2 = io.Fonts->AddFontFromFileTTF("anotherfont.otf");
In your application loop, select which font to use:
ImGui::Text("Hello"); // use the default font (which is the first loaded font)
ImGui::PushFont(font2, 0.0f); // change font, keep current size
ImGui::Text("Hello with another font");
ImGui::PopFont();
For advanced options create a ImFontConfig structure and pass it to the AddFont() function (it will be copied internally):
ImFontConfig config;
config.OversampleH = 1.0f;
ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, &config);
Combine multiple fonts into one:
🆕 Since 1.92, with an up to date backend: specifying glyph ranges is unnecessary.
// Load a first font
ImFont* font = io.Fonts->AddFontDefault();
ImFontConfig config;
config.MergeMode = true;
io.Fonts->AddFontFromFileTTF("DroidSans.ttf", 0.0f, &config); // Merge into first font to add e.g. Asian characters
io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 0.0f, &config); // Merge into first font to add Icons
io.Fonts->Build();
:rewind: Before 1.92, or without an up to date backend:
// Load a first font
ImFont* font = io.Fonts->AddFontDefault();
// Add character ranges and merge into the previous font
// The ranges array is not copied by the AddFont* functions and is used lazily
// so ensure it is available at the time of building or calling GetTexDataAsRGBA32().
static const ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 }; // Will not be copied by AddFont* so keep in scope.
ImFontConfig config;
config.MergeMode = true;
io.Fonts->AddFontFromFileTTF("DroidSans.ttf", 18.0f, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge into first font
io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 18.0f, &config, icons_ranges); // Merge into first font
io.Fonts->Build();
Add a fourth parameter to bake specific font ranges only:
🆕 Since 1.92, with an up to date backend: specifying glyph ranges is unnecessary. All the GetGlyphRangesXXX() functions are marked obsolete.
// Basic Latin, Extended Latin
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, nullptr, io.Fonts->GetGlyphRangesDefault());
// Default + Selection of 2500 Ideographs used by Simplified Chinese
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, nullptr, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
// Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, nullptr, io.Fonts->GetGlyphRangesJapanese());
See Using Custom Glyph Ranges section to create your own ranges.
Example loading and using a Japanese font:
🆕 Since 1.92, with an up to date backend:
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontFromFileTTF("NotoSansCJKjp-Medium.otf");
:rewind: Before 1.92, or without an up to date backend:
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontFromFileTTF("NotoSansCJKjp-Medium.otf", 20.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
ImGui::Text(u8"こんにちは!テスト %d", 123);
if (ImGui::Button(u8"ロード"))
{
// do stuff
}
ImGui::InputText("string", buf, IM_ARRAYSIZE(buf));
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
(settings: Dark style (left), Light style (right) / Font: NotoSansCJKjp-Medium, 20px / Rounding: 5)
ImFont* font = io.Fonts->AddFontFromMemoryTTF(data, data_size, size_pixels, ...);
IMPORTANT: AddFontFromMemoryTTF()
by default transfer ownership of the data buffer to the font atlas, which will attempt to free it on destruction.
This was to avoid an unnecessary copy, and is perhaps not a good API (a future version will redesign it).
If you want to keep ownership of the data and free it yourself, you need to clear the FontDataOwnedByAtlas
field:
ImFontConfig font_cfg;
font_cfg.FontDataOwnedByAtlas = false;
ImFont* font = io.Fonts->AddFontFromMemoryTTF(data, data_size, size_pixels, &font_cfg);
Then load the font with:
ImFont* font = io.Fonts->AddFontFromMemoryCompressedTTF(compressed_data, compressed_data_size, size_pixels, ...);
or
ImFont* font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(compressed_data_base85, size_pixels, ...);
Using an icon font (such as FontAwesome or OpenFontIcons) is an easy and practical way to use icons in your Dear ImGui application. A common pattern is to merge the icon font within your main font, so you can embed icons directly from your strings without having to change fonts back and forth.
To refer to the icon UTF-8 codepoints from your C++ code, you may use those headers files created by Juliette Foucaut: https://github.com/juliettef/IconFontCppHeaders.
So you can use ICON_FA_SEARCH
as a string that will render as a "Search" icon.
🆕 Since 1.92, with an up to date backend: specifying glyph ranges is unnecessary. You can omit this parameter. Example Setup:
// Merge icons into default tool font
#include "IconsFontAwesome.h"
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontDefault();
ImFontConfig config;
config.MergeMode = true;
config.GlyphMinAdvanceX = 13.0f; // Use if you want to make the icon monospaced
io.Fonts->AddFontFromFileTTF("fonts/fontawesome-webfont.ttf", 13.0f, &config);
:rewind: Before 1.92:
// Merge icons into default tool font
#include "IconsFontAwesome.h"
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontDefault();
ImFontConfig config;
config.MergeMode = true;
config.GlyphMinAdvanceX = 13.0f; // Use if you want to make the icon monospaced
static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
io.Fonts->AddFontFromFileTTF("fonts/fontawesome-webfont.ttf", 13.0f, &config, icon_ranges);
Example Usage:
// Usage, e.g.
ImGui::Text("%s among %d items", ICON_FA_SEARCH, count);
ImGui::Button(ICON_FA_SEARCH " Search");
// C string _literals_ can be concatenated at compilation time, e.g. "hello" " world"
// ICON_FA_SEARCH is defined as a string literal so this is the same as "A" "B" becoming "AB"
See Links below for other icons fonts and related tools.
Monospace Icons?
To make your icon look more monospace and facilitate alignment, you may want to set the ImFontConfig::GlyphMinAdvanceX
value when loading an icon font.
If you GlyphMinAdvanceX
you need to pass a font_size
to AddFontXXX()
calls, as the MinAdvanceX value will be specified for the given size and scaled otherwise.
Screenshot
Here's an application using icons ("Avoyd", https://www.avoyd.com):
🆕 Since 1.92, with an up to date backend: glyphs ranges are ignored: when loading a glyph, input fonts in the merge list are queried in order. The first font which has the glyph loads it.
‼️ If you are merging several fonts, you may have undesirable overlapping ranges. You can use ImFontConfig::GlyphExcludeRanges[]
to specify ranges to ignore in a given Input.
// Add Font Source 1 but ignore ICON_MIN_FA..ICON_MAX_FA range
static ImWchar exclude_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
ImFontConfig cfg1;
cfg1.GlyphExcludeRanges = exclude_ranges;
io.Fonts->AddFontFromFileTTF("segoeui.ttf", 0.0f, &cfg1);
// Add Font Source 2, which expects to use the range above
ImFontConfig cfg2;
cfg2.MergeMode = true;
io.Fonts->AddFontFromFileTTF("FontAwesome4.ttf", 0.0f, &cfg2);
Another (silly) example:
// Remove 'A'-'Z' from first font
static ImWchar exclude_ranges[] = { 'A', 'Z', 0 };
ImFontConfig cfg1;
cfg1.GlyphExcludeRanges = exclude_ranges;
io.Fonts->AddFontFromFileTTF("segoeui.ttf", 0.0f, &cfg1);
// Load another font to fill the gaps
ImFontConfig cfg2;
cfg2.MergeMode = true;
io.Fonts->AddFontFromFileTTF("Roboto-Medium.ttf", 0.0f, &cfg2);
You can use Metrics/Debugger->Fonts->Font->Input Glyphs Overlap Detection Tool
to see list of glyphs available in multiple font sources. This can facilitate understanding which font input is providing which glyph.
imgui_freetype.cpp
from the misc/freetype/ folder. Compile with this file and add #define IMGUI_ENABLE_FREETYPE
to your imconfig.h file or build system to automatically activate it.ImGuiFreeTypeBuilderFlags_LoadColor
flag.IMGUI_USE_WCHAR32
.io.Fonts->AddFontFromFileTTF("../../../imgui_dev/data/fonts/NotoSans-Regular.ttf", 16.0f);
static ImWchar ranges[] = { 0x1, 0x1FFFF, 0 };
static ImFontConfig cfg;
cfg.MergeMode = true;
cfg.FontLoaderFlags |= ImGuiFreeTypeLoaderFlags_LoadColor;
io.Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\seguiemj.ttf", 16.0f, &cfg);
🆕 Since 1.92, with an up to date backend: specifying glyph ranges is unnecessary. Therefore this is not really useful any more.
:rewind: You can use the ImFontGlyphRangesBuilder
helper to create glyph ranges based on text input. For example: for a game where your script is known, if you can feed your entire script to it and only build the characters the game needs.
ImVector<ImWchar> ranges;
ImFontGlyphRangesBuilder builder;
builder.AddText("Hello world"); // Add a string (here "Hello world" contains 7 unique characters)
builder.AddChar(0x7262); // Add a specific character
builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges
builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted)
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, nullptr, ranges.Data);
io.Fonts->Build(); // Build the atlas while 'ranges' is still in scope and not deleted.
🆕 Since 1.92, with an up to date backend: this system has been revamped.
TL;DR; With the new system, it is recommended that you create a custom ImFontLoader
and register your fonts with it.
AddCustomRectFontGlyph()
has been obsoleted because its API does not make much sense with resizable fonts.
You can ask questions in #8466.
:rewind: Before 1.92:
As an alternative to rendering colorful glyphs using imgui_freetype with ImGuiFreeTypeBuilderFlags_LoadColor
, you may allocate your own space in the texture atlas and write yourself into it. (This is a BETA api, use if you are familiar with dear imgui and with your rendering backend)
ImFontAtlas::AddCustomRect()
and ImFontAtlas::AddCustomRectFontGlyph()
api to register rectangles that will be packed into the font atlas texture. Register them before building the atlas, then call Build()`.ImFontAtlas::GetCustomRect(int)
to query the position/size of your rectangle within the texture, and blit/copy any graphics data of your choice into those rectangles.// Add font, then register two custom 13x13 rectangles mapped to glyph 'a' and 'b' of this font
ImFont* font = io.Fonts->AddFontDefault();
int rect_ids[2];
rect_ids[0] = io.Fonts->AddCustomRectFontGlyph(font, 'a', 13, 13, 13+1);
rect_ids[1] = io.Fonts->AddCustomRectFontGlyph(font, 'b', 13, 13, 13+1);
// Build atlas
io.Fonts->Build();
// Retrieve texture in RGBA format
unsigned char* tex_pixels = nullptr;
int tex_width, tex_height;
io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_width, &tex_height);
for (int rect_n = 0; rect_n < IM_ARRAYSIZE(rect_ids); rect_n++)
if (const ImTextureRect* rect = io.Fonts->GetCustomRect(rect_ids[rect_n]))
{
// Fill the custom rectangle with red pixels (in reality you would draw/copy your bitmap data here!)
for (int y = 0; y < rect->Height; y++)
{
ImU32* p = (ImU32*)tex_pixels + (rect->Y + y) * tex_width + (rect->X);
for (int x = rect->Width; x > 0; x--)
*p++ = IM_COL32(255, 0, 0, 255);
}
}
Please note that many new C/C++ users have issues loading their files because the filename they provide is wrong due to incorrect assumption of what is the current directory.
Two things to watch for:
(1) In C/C++ and most programming languages if you want to use a backslash \
within a string literal, you need to write it double backslash \\
. At it happens, Windows uses backslashes as a path separator, so be mindful.
io.Fonts->AddFontFromFileTTF("MyFiles\MyImage01.jpg", ...); // This is INCORRECT!!
io.Fonts->AddFontFromFileTTF("MyFiles\\MyImage01.jpg", ...); // This is CORRECT
In some situations, you may also use /
path separator under Windows.
(2) Make sure your IDE/debugger settings starts your executable from the right working (current) directory. In Visual Studio you can change your working directory in project Properties > General > Debugging > Working Directory
. People assume that their execution will start from the root folder of the project, where by default it often starts from the folder where object or executable files are stored.
io.Fonts->AddFontFromFileTTF("MyImage01.jpg", ...); // Relative filename depends on your Working Directory when running your program!
io.Fonts->AddFontFromFileTTF("../MyImage01.jpg", ...); // Load from the parent folder of your Working Directory
For non-ASCII characters display, a common user issue is not passing correctly UTF-8 encoded strings.
(1) We provide a function ImGui::DebugTextEncoding(const char* text)
which you can call to verify the content of your UTF-8 strings.
This is a convenient way to confirm that your encoding is correct.
ImGui::SeparatorText("CORRECT");
ImGui::DebugTextEncoding(u8"こんにちは");
ImGui::SeparatorText("INCORRECT");
ImGui::DebugTextEncoding("こんにちは");
You can also find this tool under Metrics/Debuggers->Tools->UTF-8 Encoding viewer
if you want to paste from clipboard, but this won't validate the UTF-8 encoding done by your compiler.
(2) To encode in UTF-8:
There are also compiler-specific ways to enforce UTF-8 encoding by default:
/utf-8
command-line flag.#pragma execution_character_set("utf-8")
inside your code./utf-8
(see commit).Or, since C++11, you can use the u8"my text"
syntax to encode literal strings as UTF-8. e.g.:
ImGui::Text(u8"hello");
ImGui::Text(u8"こんにちは"); // this will always be encoded as UTF-8
ImGui::Text("こんにちは"); // the encoding of this is depending on compiler settings/flags and may be incorrect.
Since C++20, because the C++ committee hate its users, they decided to change the u8""
syntax to not return const char*
but a new type const char8_t*
which doesn't cast to const char*
.
Because of type usage of u8""
in C++20 is a little more tedious:
ImGui::Text((const char*)u8"こんにちは");
However, you can disable this behavior completely using the compiler option /Zc:char8_t-
for MSVC and -fno-char8_t
for Clang and GCC.
You can use the Metrics/Debugger
window (available in Demo>Tools
) to browse your fonts and understand what's going on if you have an issue. You can also reach it in Demo->Tools->Style Editor->Fonts
. The same information are also available in the Style Editor under Fonts.
You can use the UTF-8 Encoding viewer
in Metrics/Debugger
to verify the content of your UTF-8 strings. From C/C++ code, you can call ImGui::DebugTextEncoding("my string");
function to verify that your UTF-8 encoding is correct.
Some fonts files are available in the misc/fonts/
folder:
Roboto-Medium.ttf, by Christian Robetson
Apache License 2.0
https://fonts.google.com/specimen/Roboto
Cousine-Regular.ttf, by Steve Matteson
Digitized data copyright (c) 2010 Google Corporation.
Licensed under the SIL Open Font License, Version 1.1
https://fonts.google.com/specimen/Cousine
DroidSans.ttf, by Steve Matteson
Apache License 2.0
https://www.fontsquirrel.com/fonts/droid-sans
ProggyClean.ttf, by Tristan Grimmer
MIT License
(recommended loading setting: Size = 13.0, GlyphOffset.y = +1)
http://www.proggyfonts.net/
ProggyTiny.ttf, by Tristan Grimmer
MIT License
(recommended loading setting: Size = 10.0, GlyphOffset.y = +1)
http://www.proggyfonts.net/
Karla-Regular.ttf, by Jonathan Pinhorn
SIL OPEN FONT LICENSE Version 1.1
Pixel Perfect:
Regular:
Or use Arial Unicode or other Unicode fonts provided with Windows for full characters coverage (not sure of their licensing).