# How to Load and Use Custom Fonts with the Dear ImGui Font Atlas System

> Easily load custom fonts with Dear ImGui's font atlas system. Learn how to configure ImFontConfig and add TTF files for unique UI typography in your applications.

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

---

**To load custom fonts in Dear ImGui, access the global ImFontAtlas via `ImGui::GetIO().Fonts`, configure an `ImFontConfig` struct, then call `AddFontFromFileTTF()` with your TTF path before the first frame renders.**

Dear ImGui stores all glyphs in a single GPU texture called the *font atlas*. The `ocornut/imgui` repository provides a robust API through `ImFontAtlas` (exposed via `ImGuiIO::Fonts`) that allows you to load TrueType fonts, merge icon sets, and manage typographic resources efficiently. This guide covers the complete workflow from configuration to runtime usage based on the actual implementation in [`imgui_draw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_draw.cpp) and [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h).

## Understanding the ImFontAtlas Architecture

The font atlas is owned by the `ImGuiIO` structure and initialized when you call `ImGui::CreateContext()`. All font loading operations must occur after initializing ImGui but before the first call to `ImGui::NewFrame()`, as the texture needs to be uploaded to the GPU.

In [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h), the `ImFontAtlas` class (around line 3736) exposes the primary loading methods:

- `AddFontFromFileTTF()` – Loads from disk with optional configuration
- `AddFontFromMemoryTTF()` – Loads from raw memory buffer
- `AddFontFromMemoryCompressedTTF()` – Loads pre-compressed font data
- `Build()` – Forces immediate atlas construction (usually automatic)

The atlas rasterizes glyphs on demand and packs them into a single texture, enabling efficient batch rendering of UI text.

## Step-by-Step Guide to Loading Custom Fonts

### Configure Font Settings with ImFontConfig

Before loading a font, create an `ImFontConfig` struct to control rasterization quality and glyph handling. This struct is defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) (lines 3456–3505) and copied internally, so stack allocation is safe.

```cpp
ImFontConfig cfg;
cfg.OversampleH = 1;            // Reduce texture size (quality trade-off)
cfg.OversampleV = 1;
cfg.GlyphMinAdvanceX = 13.0f;   // Force monospaced width (useful for icons)
cfg.PixelSnapH = true;          // Align glyphs to pixel grid

```

Oversampling controls anti-aliasing quality versus texture memory usage. For standard UI text, `2` is typical; for icon fonts or memory-constrained applications, use `1`.

### Load Font Files from Disk or Memory

Call `AddFontFromFileTTF()` on the font atlas. Since Dear ImGui v1.92, the size parameter is optional (pass `0.0f` for automatic selection), though explicit sizes are recommended for consistency.

```cpp
ImGuiIO& io = ImGui::GetIO();
ImFont* myFont = io.Fonts->AddFontFromFileTTF(
    "assets/fonts/Roboto-Medium.ttf", 
    16.0f,           // Size in pixels
    &cfg             // Optional config (can be NULL)
);

```

The implementation in [`imgui_draw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_draw.cpp) (lines 3241–3320) handles file reading, stb_truetype rasterization, and atlas packing. The function returns an `ImFont*` pointer you can store for later use.

### Merge Icon Fonts into the Same Atlas

To combine an icon font (like FontAwesome) with your base font, enable merge mode in the configuration and specify the glyph ranges.

```cpp
// After loading the main font
cfg.MergeMode = true;  // Merge into previous font instead of creating new
cfg.GlyphMinAdvanceX = 13.0f;

// Define icon range (example for FontAwesome)
static const ImWchar icon_ranges[] = { 0xF000, 0xF2E0, 0 };

// Load icon font at same size as base font
io.Fonts->AddFontFromFileTTF(
    "assets/fonts/fontawesome-webfont.ttf", 
    16.0f, 
    &cfg, 
    icon_ranges
);

```

Merge mode ensures icons occupy the same texture and `ImFont` object as the base text, allowing seamless mixed rendering.

### Build and Upload the Texture

Modern ImGui backends build the atlas automatically during the first frame. However, if you need the texture handle immediately (for custom engine integration), force a build:

```cpp
io.Fonts->Build();

```

The resulting texture ID is accessible via `io.Fonts->TexID`. Custom backends must upload this to the GPU; standard backends (GLFW, SDL, DirectX) handle this automatically.

## Using Custom Fonts in Your UI

### Switching Fonts at Runtime

By default, the first font added becomes the global default. To temporarily switch fonts for specific widgets, use the font stack:

```cpp
ImGui::PushFont(myFont);
ImGui::Text("This uses the custom typeface");
ImGui::Button("Custom Font Button");
ImGui::PopFont();  // Restore previous font

```

Since v1.92, you can also push a dynamic size without creating a new font entry:

```cpp
ImGui::PushFont(myFont, 24.0f);  // 24px for this scope only
ImGui::Text("Large header text");
ImGui::PopFont();

```

### Handling DPI Scaling

For high-DPI displays, avoid reloading fonts. Instead, use the built-in scaling mechanisms:

- `ImGuiStyle::ScaleAllSizes()` – Scales layout geometry
- `style.FontScaleDpi` – Global font scaling (when backend supports `ImGuiBackendFlags_HasTextures`)

See the DPI handling section in [`docs/FONTS.md`](https://github.com/ocornut/imgui/blob/main/docs/FONTS.md) for platform-specific recommendations.

## Working with Embedded and Compressed Font Data

For applications requiring standalone binaries, embed fonts as compressed byte arrays. The [`imconfig.h`](https://github.com/ocornut/imgui/blob/main/imconfig.h) file allows disabling default fonts via `IMGUI_DISABLE_DEFAULT_FONT` to reduce binary size.

```cpp
// Data typically generated by binary_to_c compression tools
extern const unsigned char Roboto_compressed_data[];
extern const int Roboto_compressed_size;

ImFontConfig cfg;
cfg.FontDataOwnedByAtlas = false;  // You retain ownership

ImFont* embeddedFont = io.Fonts->AddFontFromMemoryCompressedTTF(
    Roboto_compressed_data,
    Roboto_compressed_size,
    16.0f,
    &cfg
);

```

Set `FontDataOwnedByAtlas = false` only if you manage the memory lifetime; otherwise, ImGui copies and owns the data.

## Summary

- Access the font atlas through `ImGui::GetIO().Fonts` immediately after `ImGui::CreateContext()`
- Use `ImFontConfig` to control oversampling (`OversampleH/V`), merge mode, and glyph spacing
- Load fonts via `AddFontFromFileTTF()` (disk) or `AddFontFromMemoryCompressedTTF()` (embedded)
- Merge icon fonts by setting `cfg.MergeMode = true` and defining `ImWchar` ranges
- Switch fonts at runtime with `PushFont()`/`PopFont()`; size overrides available since v1.92
- Reference [`imgui_draw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_draw.cpp) for rasterization internals and [`docs/FONTS.md`](https://github.com/ocornut/imgui/blob/main/docs/FONTS.md) for advanced glyph range configurations

## Frequently Asked Questions

### Do I need to call Build() after adding fonts?

Usually no. Modern backends build the atlas automatically during the first `ImGui::NewFrame()` when they detect dirty font data. However, if you need the GPU texture handle immediately—such as when integrating with a custom renderer—call `io.Fonts->Build()` manually after adding all fonts.

### How do I merge icon fonts like FontAwesome?

Set `ImFontConfig::MergeMode = true` when loading the secondary font, and specify the Unicode glyph ranges you want to import using the `glyph_ranges` parameter. The icon font must be loaded at the same size as the base font to align correctly. Refer to the "Using Icon Fonts" section in [`docs/FONTS.md`](https://github.com/ocornut/imgui/blob/main/docs/FONTS.md) for range constants like `ICON_MIN_FA`.

### Can I load fonts from memory instead of files?

Yes. Use `AddFontFromMemoryTTF()` for raw TTF data or `AddFontFromMemoryCompressedTTF()` for stb_compress'd data. The latter is preferred for embedded resources to minimize binary size. Set `FontDataOwnedByAtlas = false` in the config if you will free the memory after initialization.

### How do I change font size dynamically without reloading?

Since Dear ImGui v1.92, you can push a temporary size multiplier: `ImGui::PushFont(myFont, 24.0f)` draws at 24px for that scope. For older versions, you must add the same font file multiple times with different sizes during initialization, then select the appropriate `ImFont*` pointer with `PushFont()`.