egui icon indicating copy to clipboard operation
egui copied to clipboard

Can't load Material Design font because of missing missing glyph

Open sowbug opened this issue 1 year ago • 5 comments

  1. Try to load the font file called MaterialIcons-Regular.ttf located in this giant zip.
  2. Get error Failed to find replacement characters '◻' or '?' that originates from epaint-0.23.0/src/text/font.rs:364:17.

This is the code that I used to load the font file:

        let mut fonts = FontDefinitions::default();
        fonts.font_data.insert(
            Self::FONT_ICONS.to_owned(),
            FontData::from_static(include_bytes!(
                "../../../res/fonts/material-design-4.0/MaterialIcons-Regular.ttf"
            )),
        );

        fonts
            .families
            .entry(FontFamily::Name(Self::FONT_ICONS.into()))
            .or_default()
            .insert(0, Self::FONT_ICONS.to_owned());

and this is an excerpt from the egui/epaint font.rs file:

        const PRIMARY_REPLACEMENT_CHAR: char = '◻'; // white medium square
        const FALLBACK_REPLACEMENT_CHAR: char = '?'; // fallback for the fallback

        let replacement_glyph = slf
            .glyph_info_no_cache_or_fallback(PRIMARY_REPLACEMENT_CHAR)
            .or_else(|| slf.glyph_info_no_cache_or_fallback(FALLBACK_REPLACEMENT_CHAR))
            .unwrap_or_else(|| {
                panic!(
                    "Failed to find replacement characters {PRIMARY_REPLACEMENT_CHAR:?} or {FALLBACK_REPLACEMENT_CHAR:?}"
                )
            });

I think that this font family represents an edge case, because it's icons rather than letters/numbers/symbols, which means that nobody will ever use this font without knowing exactly which code points to use, which means that the concept of a replacement glyph shouldn't apply.

Clearly, it would have been better if the authors of this font file had included a glyph for the white medium square, but since they didn't, and I'd like to use the font file as-is, I don't have a good workaround at this point.

sowbug avatar Nov 03 '23 19:11 sowbug

See discussion in https://github.com/google/material-design-icons/issues/1600. It looks like glyph #0 is called .notdef and is supposed to serve as the glyph for missing glyphs. I'll see if I can update epaint to know about this.

sowbug avatar Nov 03 '23 21:11 sowbug

I tried reading the code, and it looks like ab_glyph::GlyphId(0) has a special meaning in epaint to get substituted with the replacement character. I'm not sure whether ab_glyph::GlyphId is the same as a "glyph ID" in the TTF spec, so I don't know whether ab_glyph::GlyphId(0) means glyph ID 0. But it seems like if the code that calculated replacement_glyph were replaced with something that just asked ab_glyph for information about Glyph ID 0, then it would give the same functionality, but properly using .notdef rather than heuristically identifying the glyph to render when there is no glyph to render.

sowbug avatar Nov 03 '23 22:11 sowbug

I've attached MaterialIcons-Regular.ttf.zip so you don't have to download that big zip to repro the bug.

sowbug avatar Nov 03 '23 22:11 sowbug

Same behavior with MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].ttf.

sowbug avatar Nov 06 '23 19:11 sowbug

I stumbled on the same bug, well, not necessiarly a bug, anyway, here's my workaround:

  1. Watch a series of tutorial of FontForge on YouTube, take about half hour.
  2. Open your icon font with FontForge.
  3. Put whatever glyph/vector/thingy into position 0x3F which is where the ? character should be, as long as the slot isn't empty. For example the > is empty but ? isn't:
    screenshot
  4. From menu bar go to File -> Generate Fonts, then save it to somewhere.
  5. Use the newly generated font in your code.
  6. Profit.

oing9179 avatar Dec 28 '23 15:12 oing9179

  • Closed by https://github.com/emilk/egui/pull/4542

emilk avatar Jun 18 '24 20:06 emilk