Skip to content

FreeType: Don't assume all fonts have SFNT tables #8483

@danielwe

Description

@danielwe

Escalating #8073. Please no rotten tomatoes ❤️ I've been asked to convert this to a proper issue

FreeType supports old-school BDF and PCF bitmap fonts and will include such fonts in font discovery, so any time such a font is installed on the system, Ghostty may load it (whether configured or as a fallback). However, since these are not SFNT file formats, Ghostty will throw a CopyTableError when trying to get the font's metrics, and possibly crash or corrupt the terminal state when printing codepoints that map to this font.

The getMetrics function already contains the necessary fallback calculations to get all the required metrics from a font without using tables, so what's needed is just a refactor such that these fallbacks are used when SFNT tables don't exist (currently, the fallbacks are only used for missing quantities; the existence of the tables themselves is a hardcoded assumption).

To reproduce:

  • Use Linux or another platform where Ghostty uses FreeType (i.e., not macOS).
  • Install the efont-unicode collection
    1. Don't use a package manager, as some of them will convert the fonts to the OTB format, masking the issue
    2. Download http://openlab.jp/efont/dist/unicode-bdf/efont-unicode-bdf-0.4.2.tar.bz2
    3. Extract and copy the resulting folder into ~/.local/share/fonts/
    4. Run fc-cache -fv
  • Install a modern CJK-supporting font such as Noto Sans Mono CJK (feel free to use a package manager for this)
  • Launch Ghostty with the following config:
    font-family = "JetBrains Mono"
    font-family = "Noto Sans Mono CJK"
  • Run ghostty +show-face --cp=0x6f22
    • This should print U+6F22 « 漢 » found in face “Noto Sans CJK JP”. (This is just a sanity check.)
  • Now, launch Ghostty with the following config:
    font-family = "JetBrains Mono"
    font-family = "Biwidth"
  • Again, run ghostty +show-face --cp=0x6f22
    • On tip as of this writing, this will print Unable to get face: error.CopyTableError; also, cat cjk_file.txt will print blank spaces, and nvim cjk_file.txt may corrupt the terminal state
    • On some older versions, Ghostty may crash

I started fiddling with the refactor here: main...danielwe:ghostty:bitmap_metrics. Anyone feel free to use it as a starting point. Just beware that it's far from ready. There's a bunch of needlessly duplicated code.

More importantly, one thing I learned is that there seems to be a bug in FreeType where it segfaults during resource cleanup if a BDF font is loaded. This could also be a bug in Ghostty's use of HarfBuzz's refcounting (the self.face.ref() stuff), but I wasn't able to fix the problem by messing around with that. Anyway, it's not a huge deal, as the segfault only happens as Ghostty is quitting, and BDF fonts are rare these days. But no segfault would obviously be nicer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    fontIssue within the font stack (typically src/font)

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions