# Loading and Configuring Custom Fonts with ImFontAtlas in Dear ImGui

> Learn to load and configure custom fonts with ImFontAtlas in Dear ImGui. This guide simplifies integrating unique typography into your GUI applications, enhancing user experience.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: how-to-guide
- Published: 2026-07-14

---

**Dear ImGui uses the `ImFontAtlas` class to aggregate font glyphs and custom graphics into a single texture that your rendering backend uploads to the GPU.** You access the global atlas through `ImGuiIO::Fonts`, load TrueType or OpenType files via `AddFontFromFileTTF()`, and configure rasterization settings using the `ImFontConfig` struct.

Dear ImGui (ocornut/imgui) does not render text using system font APIs; instead, it rasterizes glyphs into a unified texture atlas that the draw list samples during rendering. The `ImFontAtlas` class manages this aggregation, handling glyph packing, texture generation, and UV coordinate mapping. Mastering this workflow is essential for applications requiring custom typefaces, icon fonts, or multilingual text support.

## Accessing the Global Font Atlas

The active Dear ImGui context exposes the font atlas through the `ImGuiIO` structure. Before the first frame, obtain the atlas pointer to begin adding fonts:

```cpp
ImGuiIO& io = ImGui::GetIO();
ImFontAtlas* atlas = io.Fonts;

```

The `io.Fonts` pointer provides access to all font-loading methods and texture data. You must configure your fonts before the first call to `ImGui::NewFrame()`, as the atlas builds its texture lazily upon first use.

## Loading Fonts from Files and Memory

Dear ImGui supports loading from both disk files and memory buffers. The `AddFontFromFileTTF()` method, declared in **imgui.h** at line 3713, is the most common entry point for loading TrueType or OpenType fonts.

### Loading from Disk

To load a font with default settings, specify the file path and pixel size:

```cpp
ImFont* myFont = io.Fonts->AddFontFromFileTTF("myfont.ttf", 18.0f);

```

If the file cannot be loaded, the function returns `NULL` and the default embedded font remains active.

### Loading from Memory

For embedded resources or encrypted font data, use `AddFontFromMemoryTTF()` as declared in **imgui.h** at line 3714. This function takes ownership of the buffer unless configured otherwise:

```cpp
unsigned char* ttfData = /* ... load file into memory ... */;
int ttfSize = /* size of the buffer */;
ImFont* font = io.Fonts->AddFontFromMemoryTTF(ttfData, ttfSize, 20.0f);

```

**Critical:** By default, the atlas assumes ownership of the memory buffer and frees it after building. Set `FontDataOwnedByAtlas = false` in the configuration struct to retain ownership.

## Configuring Font Properties with ImFontConfig

The `ImFontConfig` struct, defined in **imgui.h** around line 3600, controls rasterization quality, glyph subsets, and memory ownership. Zero-initialize the struct to ensure default values:

```cpp
ImFontConfig cfg;
cfg.GlyphRanges = io.Fonts->GetGlyphRangesDefault();
cfg.FontDataOwnedByAtlas = false;
ImFont* font = io.Fonts->AddFontFromFileTTF("arial.ttf", 16.0f, &cfg);

```

### Restricting Glyph Ranges

To reduce texture memory, limit the font to specific Unicode blocks. The `GlyphRanges` member expects a null-terminated array of inclusive ranges (min, max pairs). **Warning:** The atlas stores this pointer, not a copy, so the array must remain valid until the atlas is built, as documented in **imgui.h** at line 3699.

```cpp
// Load only Basic Latin and Cyrillic
ImFontConfig cfg;
cfg.GlyphRanges = io.Fonts->GetGlyphRangesCyrillic();
ImFont* font = io.Fonts->AddFontFromFileTTF("C:/Windows/Fonts/arial.ttf", 16.0f, &cfg);

```

### Oversampling for Quality

Increase oversampling to improve text quality at small sizes or when scaling:

```cpp
ImFontConfig cfg;
cfg.OversampleH = 3;
cfg.OversampleV = 3;
ImFont* font = io.Fonts->AddFontFromMemoryTTF(ttfData, ttfSize, 20.0f, &cfg);

```

Higher values consume more texture memory but reduce aliasing artifacts.

## Managing Font Data Ownership and Lifetime

When using `AddFontFromMemoryTTF()`, the atlas takes ownership of the font data by default. This is controlled by the `FontDataOwnedByAtlas` flag in `ImFontConfig`. If your application manages the memory lifecycle or uses static data, disable ownership transfer:

```cpp
ImFontConfig cfg;
cfg.FontDataOwnedByAtlas = false;  // Keep the buffer valid
ImFont* font = io.Fonts->AddFontFromMemoryTTF(ttfData, ttfSize, 20.0f, &cfg);

```

Failing to set this flag when necessary leads to use-after-free errors when the atlas builds.

## Adding Custom Rectangles for Icons and Graphics

The atlas supports reserving space for user-defined graphics, such as colored icons or application-specific symbols. Use `AddCustomRect()` to reserve pixels, defined in **imgui.h** at lines 3889-3892:

```cpp
ImFontAtlasRect iconRect;
ImFontAtlasRectId iconId = io.Fonts->AddCustomRect(64, 64, &iconRect);

```

After building the atlas, retrieve UV coordinates using `GetCustomRect()`:

```cpp
io.Fonts->Build();
io.Fonts->GetCustomRect(iconId, &iconRect);
// Use iconRect.uv0 and iconRect.uv1 for ImDrawList texture coordinates

```

Any modification to the atlas—adding fonts or custom rects—invalidates previous texture handles and UV coordinates. Always fetch custom rectangle data after each build.

## Building the Atlas and Uploading to GPU

The atlas generates its texture lazily when you request the pixel data. Trigger a build explicitly or let it happen on first access:

```cpp
unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);

```

For backends requiring single-channel textures, use `GetTexDataAsAlpha8()` instead. The `TexDesiredFormat` field controls the output format; default is `ImTextureFormat_RGBA32`.

After uploading to GPU, store the texture identifier:

```cpp
io.Fonts->SetTexID(myTextureId);

```

## Enabling FreeType for High-Quality Rasterization

Dear ImGui includes an optional FreeType backend for superior hinting and subpixel rendering. Enable it by defining `IMGUI_ENABLE_FREETYPE` and linking against the FreeType library. The implementation resides in **misc/freetype/imgui_freetype.cpp**.

Register the loader before adding fonts:

```cpp
#define IMGUI_ENABLE_FREETYPE
#include "imgui.h"

// Before any AddFont calls
io.Fonts->SetFontLoader(ImGui::GetFreeTypeFontLoader());
ImFont* font = io.Fonts->AddFontFromFileTTF("myfont.ttf", 16.0f);

```

This replaces the default stb_truetype rasterizer with FreeType, providing better glyph shapes at small sizes and support for LCD-optimized rendering.

## Summary

- **Access the atlas** through `ImGuiIO::Fonts` before the first frame.
- **Load fonts** using `AddFontFromFileTTF()` (**imgui.h** line 3713) or `AddFontFromMemoryTTF()` (**imgui.h** line 3714).
- **Configure rasterization** with `ImFontConfig` (**imgui.h** line 3600), setting `GlyphRanges` for Unicode subsets and `OversampleH/V` for quality.
- **Manage memory** by setting `FontDataOwnedByAtlas = false` when the buffer must outlive the atlas.
- **Add custom graphics** via `AddCustomRect()` (**imgui.h** lines 3889-3892) and retrieve UVs after building.
- **Build and upload** using `GetTexDataAsRGBA32()` or `GetTexDataAsAlpha8()`, then call `SetTexID()` with your GPU texture handle.
- **Use FreeType** by enabling `IMGUI_ENABLE_FREETYPE` and calling `SetFontLoader()` with the FreeType loader from **misc/freetype/imgui_freetype.cpp**.

## Frequently Asked Questions

### How do I load multiple fonts at different sizes?

Call `AddFontFromFileTTF()` multiple times before building the atlas. Each call returns a distinct `ImFont*` pointer that you can push to `ImGui::PushFont()` when needed:

```cpp
ImFont* font18 = io.Fonts->AddFontFromFileTTF("font.ttf", 18.0f);
ImFont* font24 = io.Fonts->AddFontFromFileTTF("font.ttf", 24.0f);
io.Fonts->Build();

```

### Why does my custom font display as blocks or question marks?

This occurs when the texture atlas lacks the requested glyphs. Ensure your `ImFontConfig::GlyphRanges` includes the Unicode codepoints you are rendering. The default range only covers Basic Latin. For CJK or Cyrillic, use the built-in helpers like `GetGlyphRangesChineseSimplifiedCommon()` or `GetGlyphRangesCyrillic()`.

### Can I update the font atlas after the application has started?

Yes, but you must rebuild the texture and re-upload it to the GPU. Clearing and repopulating the atlas invalidates previous `ImFont*` pointers and UV coordinates. Call `Clear()` on the atlas, re-add your fonts, call `Build()` or `GetTexDataAsRGBA32()`, then update your backend texture. Be sure to refresh any cached custom rectangle UVs.

### What is the difference between stb_truetype and FreeType?

Dear ImGui uses stb_truetype by default for lightweight, single-header rasterization. The optional FreeType backend (**misc/freetype/imgui_freetype.cpp**) provides advanced hinting, subpixel rendering, and better support for complex scripts. Enable FreeType by defining `IMGUI_ENABLE_FREETYPE` and setting the font loader via `SetFontLoader(ImGui::GetFreeTypeFontLoader())` before adding fonts.