Honor the Linux menu font face selected by Fontconfig #1371

Merged
bronze-ff merged 1 commit from fix/linux-menu-font-index into main 2026-11-10 04:31:24 +00:00
bronze-ff commented 2026-11-09 23:31:19 +00:00 (Migrated from github.com)

The Linux Insert menu asks Fontconfig for the file matching its regular and bold fonts. It opens face 0 even when Fontconfig selected a different face in a collection.

Read the file and index from the same match and pass the collection index to stb_truetype. The lower 16 bits select the collection face. Higher bits identify a named variable-font instance. See FreeType's face-index format.

Validation

  • With actual Fontconfig on Ubuntu under WSL and an isolated font configuration, sans-serif selected face 1 of a collection. The original loader opened face 0. The patched loader opened face 1 and found the glyph for A.
  • The new game-free regression compiles the Linux GDI loader and builds a temporary collection from two fonts already in the repo. It fails on main and passes with the change. It covers face 0, a nonzero face with packed instance bits, and a path with a space.
  • The strict Linux source runner passed the menu font and updater checks with Clang 23.1.5.

The cause of the hollow boxes in #1279 remains unconfirmed.

Compatibility with #1405: that patch checks Latin glyph coverage, while this one opens the collection face chosen by Fontconfig. I resolved the overlapping lines in a temporary combined tree and ran the font-index, Latin-coverage and #1389 UTF-8 fixtures on Linux. All three passed. The combined test stub returns the face index and logs only the font pattern.

The Linux Insert menu asks Fontconfig for the file matching its regular and bold fonts. It opens face 0 even when Fontconfig selected a different face in a collection. Read the file and index from the same match and pass the collection index to stb_truetype. The lower 16 bits select the collection face. Higher bits identify a named variable-font instance. See [FreeType's face-index format](https://freetype.org/freetype2/docs/reference/ft2-face_creation.html#ft_new_face). ### Validation - With actual Fontconfig on Ubuntu under WSL and an isolated font configuration, sans-serif selected face 1 of a collection. The original loader opened face 0. The patched loader opened face 1 and found the glyph for A. - The new game-free regression compiles the Linux GDI loader and builds a temporary collection from two fonts already in the repo. It fails on main and passes with the change. It covers face 0, a nonzero face with packed instance bits, and a path with a space. - The strict Linux source runner passed the menu font and updater checks with Clang 23.1.5. The cause of the hollow boxes in #1279 remains unconfirmed. Compatibility with #1405: that patch checks Latin glyph coverage, while this one opens the collection face chosen by Fontconfig. I resolved the overlapping lines in a temporary combined tree and ran the font-index, Latin-coverage and #1389 UTF-8 fixtures on Linux. All three passed. The combined test stub returns the face index and logs only the font pattern.
NotRexed commented 2026-11-10 03:49:56 +00:00 (Migrated from github.com)

This landed in the v2.0.12 branch (merged there for testing; it reaches main with that release), so closing. Thanks!

This landed in the v2.0.12 branch (merged there for testing; it reaches `main` with that release), so closing. Thanks!
NotRexed commented 2026-11-10 03:54:28 +00:00 (Migrated from github.com)

Reopened: closing this was a mistake on my side. It was tested in the v2.0.12 branch, and it will be merged into main here, so it shows as merged. Sorry for the noise.

Reopened: closing this was a mistake on my side. It was tested in the v2.0.12 branch, and it will be merged into main here, so it shows as merged. Sorry for the noise.
hckrman101 (Migrated from github.com) approved these changes 2026-11-10 04:18:03 +00:00
hckrman101 (Migrated from github.com) left a comment

Looks right to me.

fc-match now returns the face index and the file in one call, and the index is masked with & 0xffff before it goes to stb, which is the right thing for a Fontconfig index that carries the named-instance bits. The parsing is careful. The test builds the real loader, is registered in tests/run_all.py with a Windows skip, and I could not find a bug.

One heads-up for merge order: #1405 rewrites the same fc_match(...) calls and the InitFont line in face_load (it adds :lang=en and a Latin-letter check), so whichever lands second has to rebase, and the lang=en pattern needs to move into the face_match(...) patterns. The two are compatible otherwise. The run_all.py lines next to #1389 and #1405 will also need a trivial resolve.

Nit: if the selected face fails to load there is no fallback to face 0. The hard-coded font paths follow, so it is harmless.

Looks right to me. `fc-match` now returns the face index and the file in one call, and the index is masked with `& 0xffff` before it goes to stb, which is the right thing for a Fontconfig index that carries the named-instance bits. The parsing is careful. The test builds the real loader, is registered in `tests/run_all.py` with a Windows skip, and I could not find a bug. One heads-up for merge order: #1405 rewrites the same `fc_match(...)` calls and the `InitFont` line in `face_load` (it adds `:lang=en` and a Latin-letter check), so whichever lands second has to rebase, and the `lang=en` pattern needs to move into the `face_match(...)` patterns. The two are compatible otherwise. The `run_all.py` lines next to #1389 and #1405 will also need a trivial resolve. Nit: if the selected face fails to load there is no fallback to face 0. The hard-coded font paths follow, so it is harmless.
Commenting is not possible because the repository is archived.
No description provided.