# How to Load and Use Custom Fonts with ImFontAtlas in Dear ImGui

> Easily load and use custom fonts in Dear ImGui with ImFontAtlas. Learn how to AddFontFromFileTTF or AddFontFromMemoryTTF and Build your font atlas for unique UI.

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

---

**Dear ImGui aggregates fonts into a single GPU texture using the `ImFontAtlas` class exposed via `ImGuiIO::Fonts`, which you populate with `AddFontFromFileTTF()` or `AddFontFromMemoryTTF()` and rasterize by calling `Build()` before rendering.**

Dear ImGui's font system centers around the `ImFontAtlas` class, which packs glyph bitmaps and custom graphics into a unified texture atlas for efficient rendering. Whether you are loading system fonts or embedding TTF data directly, understanding how to configure the atlas through the `ocornut/imgui` source code ensures crisp text rendering without unnecessary texture bloat.

## Understanding the ImFontAtlas Architecture

The **ImFontAtlas** serves as a texture packer that rasterizes font glyphs and optional custom graphics into a single bitmap. According to the source code in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) (lines 3600–3717), the atlas maintains a `TexRef` identifier and manages the lifetime of font data until you explicitly clear it.

Access the global atlas instance through the **ImGuiIO** structure:

```cpp
ImGuiIO& io = ImGui::GetIO();
ImFontAtlas* atlas = io.Fonts;  // Always available after ImGui::CreateContext()

```

The atlas holds `ImFont` objects, each referencing specific glyph ranges within the shared texture.

## Loading Fonts from Files and Memory

### Loading TTF Files from Disk

The most common entry point is `AddFontFromFileTTF()`, declared in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) at line 3713. This method rasterizes a TrueType or OpenType file at a specified pixel size:

```cpp
ImGuiIO& io = ImGui::GetIO();
ImFont* font = io.Fonts->AddFontFromFileTTF("C:/Windows/Fonts/arial.ttf", 16.0f);

```

The function returns an `ImFont*` pointer that you can push onto the font stack with `ImGui::PushFont()` when you need to switch typefaces mid-frame.

### Loading from Memory Buffers

For embedded assets or encrypted font data, use `AddFontFromMemoryTTF()` (also declared at line 3713 in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)). This variant accepts a raw byte buffer and takes ownership of the memory by default:

```cpp
unsigned char* fontData = /* loaded from .ttf file */;
int fontDataSize = /* size in bytes */;
ImFont* font = io.Fonts->AddFontFromMemoryTTF(fontData, fontDataSize, 18.0f);

```

**Critical:** By default, the atlas frees this buffer after building. If you need to retain the data (for example, to rebuild the atlas later), you must configure ownership flags before adding the font.

## Configuring Fonts with ImFontConfig

The **ImFontConfig** struct (defined around line 3600 in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)) provides granular control over rasterization and memory management. Always zero-initialize the struct to ensure default values:

```cpp
ImFontConfig cfg;
cfg.SizePixels = 20.0f;
cfg.OversampleH = 3;           // Horizontal oversampling for subpixel precision
cfg.OversampleV = 3;           // Vertical oversampling
cfg.GlyphRanges = io.Fonts->GetGlyphRangesCyrillic();  // Limit glyph set
cfg.FontDataOwnedByAtlas = false;  // Keep fontData alive after Build()

ImFont* font = io.Fonts->AddFontFromMemoryTTF(fontData, size, 20.0f, &cfg);

```

### Managing Glyph Range Lifetime

As warned in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) at line 3699, the `GlyphRanges` pointer is stored internally without copying the array. The underlying data must remain valid until you call `Build()` or `GetTexDataAsRGBA32()`. Use the built-in helpers like `GetGlyphRangesDefault()`, `GetGlyphRangesChineseFull()`, or define a custom static `ImWchar` array.

### Controlling Font Data Ownership

When using `AddFontFromMemoryTTF()`, set `cfg.FontDataOwnedByAtlas = false` (as shown at line 3714 in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)) if your application manages the buffer lifetime. If left as `true` (the default), the atlas calls `IM_FREE()` on the pointer during destruction.

## Building the Atlas and GPU Integration

### Texture Generation

The atlas remains in a dirty state until you request the texture data. You can force rasterization and packing by calling:

```cpp
io.Fonts->Build();  // Returns bool indicating success

```

Alternatively, retrieving the raw pixels with `GetTexDataAsRGBA32()` or `GetTexDataAsAlpha8()` implicitly triggers a build. After building, upload the resulting texture to your GPU and store the identifier:

```cpp
unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
// ... upload to GPU ...
io.Fonts->SetTexID((ImTextureID)myTextureId);

```

### Adding Custom Rectangles for Icons

To embed colored icons or graphics alongside fonts, reserve space using the API at lines 3889–3892 in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h):

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

// After building:
io.Fonts->Build();
io.Fonts->GetCustomRect(id, &rect);
// rect.uv0 and rect.uv1 now contain normalized coordinates for ImDrawList

```

Any modification to the atlas—adding fonts or custom rectangles—invalidates the texture and requires rebuilding, which regenerates the UV coordinates.

## Optional FreeType Rasterization Backend

For superior hinting and subpixel rendering, enable the **FreeType** backend by defining `IMGUI_ENABLE_FREETYPE` before including headers. The implementation resides in [`misc/freetype/imgui_freetype.cpp`](https://github.com/ocornut/imgui/blob/main/misc/freetype/imgui_freetype.cpp).

Activate the loader before adding fonts:

```cpp
io.Fonts->SetFontLoader(ImGui::GetFreeTypeFontLoader());
ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", 16.0f);

```

This replaces the default stb_truetype rasterizer with FreeType, supporting advanced features like LCD subpixel rendering and glyph emboldening.

## Summary

- **Access the atlas** through `ImGuiIO::Fonts` after creating the ImGui context.
- **Load fonts** using `AddFontFromFileTTF()` for files or `AddFontFromMemoryTTF()` for embedded data, with signatures defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) at line 3713.
- **Configure rasterization** via `ImFontConfig` (line 3600) to control oversampling, glyph ranges, and memory ownership.
- **Preserve memory safety** by ensuring glyph range arrays outlive the build process and setting `FontDataOwnedByAtlas = false` when retaining buffers.
- **Build the texture** explicitly with `Build()` or implicitly via `GetTexDataAsRGBA32()`, then upload to your GPU backend.
- **Embed custom graphics** using `AddCustomRect()` (lines 3889–3892) for icons that share the font texture.
- **Improve quality** by enabling the FreeType loader in [`misc/freetype/imgui_freetype.cpp`](https://github.com/ocornut/imgui/blob/main/misc/freetype/imgui_freetype.cpp) for advanced hinting.

## Frequently Asked Questions

### Why does my application crash when specifying custom glyph ranges?

The `ImFontConfig::GlyphRanges` member stores a raw pointer without copying the array data. As documented in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) at line 3699, the glyph range array must remain valid in memory until the atlas is built. Store your `ImWchar` ranges as static constants or ensure they outlive the `Build()` call to prevent dangling pointer access.

### How do I prevent ImFontAtlas from deleting my font data buffer?

When using `AddFontFromMemoryTTF()`, set `cfg.FontDataOwnedByAtlas = false` in your `ImFontConfig` struct before adding the font. This flag, referenced at line 3714 in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h), tells the atlas not to call `IM_FREE()` on the buffer during destruction, allowing your application to manage the memory lifecycle independently.

### When should I call Build() on the font atlas?

Call `Build()` after adding all fonts and custom rectangles but before your first draw call, typically during application initialization or after loading a new font at runtime. If you modify the atlas later—adding fonts or custom rects—you must rebuild and re-upload the texture to the GPU, as the pixel buffer and UV coordinates change.

### Can I use colored icons with ImFontAtlas alongside my fonts?

Yes. Reserve space using `AddCustomRect(width, height)` (lines 3889–3892 in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)) to allocate a region in the atlas texture. After calling `Build()`, retrieve the UV coordinates with `GetCustomRect()` and use them with `ImDrawList::AddImage()` to render colored graphics that share the same texture as your glyphs.