How to load fonts in wgpu integration with iced

Published on 2025-02-21

I currently use the wgpu integration setup for my image viewer app and needed to load custom fonts (including an icon font) without using a Compositor. In iced 0.13.1, you usually set your fonts via Settings and pass it like application(...).settings(your_settings). I found this part in iced_winit::program:run_action(), and it seems like it is the Compositor that loads fonts in the regular iced setup:

Action::LoadFont { bytes, channel } => {
    if let Some(compositor) = compositor {
        // TODO: Error handling (?)
        compositor.load_font(bytes.clone());

        let _ = channel.send(Ok(()));
    }
}

iced/graphics/src/compositor.rs:

/// Loads a font from its bytes.
fn load_font(&mut self, font: Cow<'static, [u8]>) {
    crate::text::font_system()
        .write()
        .expect("Write to font system")
        .load_font(font);
}

Compositor is not accessible in the wgpu integration example because we directly use Engine to render things, but it turns out you can directly access the FontSystem like this:

use std::borrow::Cow;
use iced_wgpu::graphics::text::font_system;

fn register_font_manually(font_data: &'static [u8]) {
    use std::sync::RwLockWriteGuard;

    // Get a mutable reference to the font system
    let font_system = font_system();
    let mut font_system_guard: RwLockWriteGuard<_> = font_system
        .write()
        .expect("Failed to acquire font system lock");

    // Load the font into the global font system
    font_system_guard.load_font(Cow::Borrowed(font_data));
}

and call it after the Engine creation in Self::Loading() block:

let engine = Engine::new(
    &adapter, &device, &queue, format, None);
engine.create_image_cache(&device); // Manually create image cache

// Manually register fonts
register_font_manually(include_bytes!("../assets/fonts/viewskater-fonts.ttf"));
register_font_manually(include_bytes!("../assets/fonts/Iosevka-Regular-ascii.ttf"));
register_font_manually(include_bytes!("../assets/fonts/Roboto-Regular.ttf"));

Now you can use icon fonts like before!