# How to Load Custom Fonts in Dear ImGui: A Complete Guide to ImFontAtlas

> Learn to load custom fonts in Dear ImGui using ImFontAtlas. This guide covers AddFontFromFileTTF AddFontFromMemoryTTF and the essential Build() call for seamless font integration.

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

---

**Dear ImGui loads custom fonts through the `ImFontAtlas` class, which aggregates one or more fonts into a single rasterized texture using methods like `AddFontFromFileTTF` and `AddFontFromMemoryTTF`, requiring a `Build()` call before the first frame is rendered.**

Dear ImGui (ocornut/imgui) renders all user interface text using a centralized texture atlas generated from TrueType or OpenType font files. The **ImFontAtlas** class manages the entire pipeline, from parsing font data to packing glyphs into a GPU-ready texture. Properly configuring this system is essential for supporting international character sets, icon fonts, and high-quality text rendering.

## Understanding the ImFontAtlas Architecture

The font system revolves around a single **ImFontAtlas** instance owned by the global `ImGuiIO` context. Access it via `ImGui::GetIO().Fonts`. This atlas holds the raw rasterized glyphs, a texture reference (`TexRef`), and optional custom rectangles for user-defined graphics like icons.

The atlas operates in two distinct phases: **configuration** and **build**. During configuration, you add fonts, set glyph ranges, and reserve custom rectangles. The build phase packs everything into a single texture buffer that your rendering backend uploads to the GPU.

## Loading Fonts from Files and Memory

Dear ImGui provides two primary methods for ingesting font data: loading directly from disk or importing from memory buffers.

### Loading from TTF/OTF Files

The most common approach uses `AddFontFromFileTTF`, declared in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) around line 3713. This method parses the font file, rasterizes it at the specified pixel size, and returns an `ImFont*` pointer.

```cpp
ImGuiIO& io = ImGui::GetIO();
ImFont* myFont = io.Fonts->AddFontFromFileTTF("assets/fonts/Roboto-Regular.ttf", 18.0f);

```

If you need to customize the font, pass an `ImFontConfig` pointer as the third argument and an optional glyph range specifier as the fourth.

### Loading from Memory Buffers

For embedded resources or runtime-generated fonts, use `AddFontFromMemoryTTF`. This function takes ownership of the supplied buffer by default, copying the data into the atlas unless configured otherwise.

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

```

**Critical:** Set `ImFontConfig::FontDataOwnedByAtlas = false` (as documented in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) near line 3714) if you want to retain ownership of the memory and free it yourself. If `true`, Dear ImGui allocates and owns the copy.

## Configuring Font Rendering with ImFontConfig

The **ImFontConfig** struct (defined in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) around line 3600) controls rasterization quality, glyph subsets, and memory ownership.

### Custom Glyph Ranges and Unicode Blocks

By default, Dear ImGui loads a basic Latin range. To support Cyrillic, Chinese, Japanese, or custom Unicode blocks, specify `GlyphRanges` using built-in helpers or custom arrays.

```cpp
ImFontConfig cfg;
cfg.GlyphRanges = io.Fonts->GetGlyphRangesCyrillic(); // Or GetGlyphRangesChineseFull()
ImFont* font = io.Fonts->AddFontFromFileTTF("arial.ttf", 16.0f, &cfg);

```

**Warning:** As noted in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) at line 3699, `GlyphRanges` is stored as a raw pointer. The underlying array must remain valid until you call `Build()` on the atlas.

### Oversampling and Quality Settings

For higher quality text on high-DPI displays, increase horizontal and vertical oversampling:

```cpp
ImFontConfig cfg;
cfg.OversampleH = 3;
cfg.OversampleV = 3;
cfg.PixelSnapH = true;
ImFont* hqFont = io.Fonts->AddFontFromFileTTF("font.ttf", 20.0f, &cfg);

```

## Adding Custom Rectangles for Icons

The atlas supports custom rectangular regions for images or colored icons. This API (located in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) lines 3889-3892) reserves space in the texture before the build step.

```cpp
ImFontAtlasRect iconRect;
ImFontAtlasRectId iconId = io.Fonts->AddCustomRect(64, 64, &iconRect);
// After building, fill the texture data at rect locations

```

Call `io.Fonts->GetCustomRect(iconId, &iconRect)` after `Build()` to retrieve the final UV coordinates for use in `ImDrawList` calls.

## Building and Uploading the Texture

Before rendering any text, you must finalize the atlas:

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

```

This packs all fonts and custom rectangles into a single pixel buffer. Retrieve the texture data using `GetTexDataAsRGBA32()` or `GetTexDataAsAlpha8()`, upload it to your GPU, and store the texture identifier via `SetTexID`.

**Important:** Any subsequent call that modifies the atlas—adding a new font, changing glyph ranges, or resizing—invalidates the existing texture and requires a rebuild. Always fetch custom rectangle UVs after each build operation.

## Optional FreeType Integration

For superior hinting and subpixel rendering, enable the optional FreeType loader. Define `IMGUI_ENABLE_FREETYPE` before including [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h), include [`misc/freetype/imgui_freetype.cpp`](https://github.com/ocornut/imgui/blob/main/misc/freetype/imgui_freetype.cpp) in your build, and set the custom loader:

```cpp
io.Fonts->SetFontLoader(ImGui::GetFreeTypeFontLoader());
// Now AddFontFromFileTTF uses FreeType rasterization

```

The FreeType implementation resides in [`misc/freetype/imgui_freetype.cpp`](https://github.com/ocornut/imgui/blob/main/misc/freetype/imgui_freetype.cpp) and provides advanced hinting controls compared to the default stb_truetype backend.

## Summary

- Access the global atlas via `ImGui::GetIO().Fonts` before any rendering occurs.
- Use `AddFontFromFileTTF` for disk files or `AddFontFromMemoryTTF` for embedded data.
- Configure glyph ranges via `ImFontConfig` to support international characters, ensuring the range array outlives the build process.
- Call `Build()` once after all fonts are added to generate the texture atlas.
- Reserve custom rectangles before building to embed icons alongside text.
- Enable the FreeType backend (in [`misc/freetype/imgui_freetype.cpp`](https://github.com/ocornut/imgui/blob/main/misc/freetype/imgui_freetype.cpp)) for production-quality rasterization.

## Frequently Asked Questions

### Why do some characters display as question marks or boxes?

This typically occurs when the **glyph range** specified in `ImFontConfig` does not include the Unicode codepoints you are attempting to render. Verify that you are using the correct range helper (e.g., `GetGlyphRangesChineseFull()`) or a custom array that includes the specific characters. As implemented in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h), missing glyphs fall back to the default font if available, or render as the "missing character" box if not.

### Can I load multiple fonts at different sizes simultaneously?

Yes. Call `AddFontFromFileTTF` or `AddFontFromMemoryTTF` multiple times with different size parameters and optional `ImFontConfig` structures. Each call returns a distinct `ImFont*` pointer. Switch between active fonts using `ImGui::PushFont(fontPtr)` and `ImGui::PopFont()` during your UI rendering code.

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

You must call `Build()` (or implicitly trigger it via `GetTexDataAsRGBA32`) after all font addition and configuration is complete, but **before** the first frame is rendered. Modifying the atlas after building—for example, calling `AddFontFromFileTTF` later—invalidates the existing texture and requires another build cycle as implemented in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp).

### How do I prevent Dear ImGui from copying my embedded font memory?

Set `ImFontConfig::FontDataOwnedByAtlas = false` before calling `AddFontFromMemoryTTF`. According to the source in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) near line 3714, this flag tells the atlas to reference your existing buffer rather than allocating its own copy. You remain responsible for keeping that memory valid for the duration of the atlas's lifetime and freeing it after Dear ImGui shuts down.