slint-ui/slint · critical

fatal: swash is unable to parse truetype font

Error message

fatal: swash is unable to parse truetype font

What it means

`get_swash_font_info` parses a fontique font blob with `swash::FontRef::from_index` and panics if swash cannot parse the data as a TrueType/OpenType font. The software renderer assumes every font the system font enumeration (fontique) returns is parseable; a corrupt, DRM-protected, or non-TrueType font file breaks that assumption. The `or_insert_with` cache means the panic happens once per (blob, index) pair, on first use.

Solutions

  1. Find and remove/repair the corrupt font file (validate all fonts with e.g. `fonttools ttx <file>` or `fc-validate`)
  2. Clear font caches (`fc-cache -f`) after fixing fonts so fontique re-enumerates clean data
  3. Restrict the fonts available to the app (point `FONTCONFIG_FILE`/`XDG_DATA_HOME` at a curated font dir with a known-good font like DejaVu)
  4. Update Slint/fontique/swash — newer versions may skip unparsable fonts instead of panicking

Example fix

// validate fonts before shipping an embedded system image
// before: broken-font.ttf present in the font dir
$ fonttools ttx broken-font.ttf   # fails => remove it
$ fc-cache -f
// after: only valid fonts in the font directory
$ ls fonts/  # DejaVuSans.ttf, Roboto-Regular.ttf ...
Defensive patterns

Strategy: fallback

Validate before calling

// validate font files at deploy time
$ fonttools ttx font.ttf  # or: fc-validate --all

Prevention

When it happens

Trigger: Text rendering via the software renderer when a font selected by fontique for the query cannot be parsed by swash: broken/corrupted font files in font directories, fonts with unsupported formats (Type 1, bitmap-only), or an out-of-range `index` into a font collection (TTC) blob.

Common situations: Linux systems with damaged fonts in `~/.fonts` or `/usr/share/fonts`; containers/minimal images with malformed font packages; custom font loading via `slint::platform::software_renderer` where a bad `.ttf`/`.ttc` is registered; font collections where the requested index is out of bounds.

Understand the failure class

Related errors


AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16). Data as JSON: /api/errors/0138368d8246d3f9. Report an issue: GitHub.

Appendix: source

Thrown at internal/renderers/software/fonts/systemfonts.rs:30

use super::super::PhysicalLength;
use super::vectorfont::VectorFont;

struct CachedFontInfo {
    swash_key: swash::CacheKey,
    swash_offset: u32,
}

i_slint_core::thread_local! {
    // swash font info cached and indexed by fontique blob id (unique incremental) and true type collection index
    static SWASH_FONTS: RefCell<HashMap<(HashedBlob, u32), CachedFontInfo>> = Default::default();
}

pub fn get_swash_font_info(blob: &fontique::Blob<u8>, index: u32) -> (swash::CacheKey, u32) {
    SWASH_FONTS.with(|font_cache| {
        let mut cache = font_cache.borrow_mut();
        let info = cache.entry((blob.clone().into(), index)).or_insert_with(move || {
            let font_ref = swash::FontRef::from_index(blob.data(), index as usize)
                .expect("fatal: swash is unable to parse truetype font");
            CachedFontInfo { swash_key: font_ref.key, swash_offset: font_ref.offset }
        });
        (info.swash_key, info.swash_offset)
    })
}

fn get_swash_font_info_for_query_font(font: &fontique::QueryFont) -> (swash::CacheKey, u32) {
    get_swash_font_info(&font.blob, font.index)
}

pub fn match_font(
    request: &super::FontRequest,
    scale_factor: super::ScaleFactor,
    collection: &mut fontique::Collection,
    source_cache: &mut fontique::SourceCache,
) -> Option<VectorFont> {
    if request.family.is_some() {
        let requested_pixel_size: PhysicalLength =

View on GitHub (pinned to bb937076de)