|
1 |
+ |
# Fonts: what is shipped, what is covered, what catches the gaps
|
|
2 |
+ |
|
|
3 |
+ |
Companion to [STACK.md](STACK.md), which holds the reasoning behind each pick, and to
|
|
4 |
+ |
[ICONOGRAPHY.md](ICONOGRAPHY.md), which holds the icon tiers. This file holds the
|
|
5 |
+ |
measurement: which codepoints Alloy's own surfaces put on a screen, which of them the
|
|
6 |
+ |
shipped fonts cover, and what the fallback chain does with the rest.
|
|
7 |
+ |
|
|
8 |
+ |
Measured 2026-08-06 against the image built from `Containerfile` at `eeeb768`, read out
|
|
9 |
+ |
of `podman image mount localhost/alloy:local` rather than out of the package list. A
|
|
10 |
+ |
package list says what was requested; the mounted rootfs says what is there.
|
|
11 |
+ |
|
|
12 |
+ |
## Method, so the numbers can be re-derived
|
|
13 |
+ |
|
|
14 |
+ |
Two enumerations and a set difference.
|
|
15 |
+ |
|
|
16 |
+ |
- **What a font covers** is its `cmap` table: the Unicode subtable (format 4 or 12), with
|
|
17 |
+ |
every codepoint whose glyph id is non-zero. Not the `name` table's language claims,
|
|
18 |
+ |
which count languages and not glyphs.
|
|
19 |
+ |
- **What Alloy emits** is every non-ASCII codepoint in its own source and templates, with
|
|
20 |
+ |
Rust comments and `#[cfg(test)]` modules cut out first. A comment is never rendered and
|
|
21 |
+ |
a test fixture is never shipped, and both are full of characters that would otherwise
|
|
22 |
+ |
read as coverage requirements. Sources: `crates/`, `etc/`, `usr/`, `templates/`,
|
|
23 |
+ |
`schemas/`, `tools/`, `scripts/`.
|
|
24 |
+ |
- **What the widget stack can emit** is the same scan over `alloy_tui 5.0.0`,
|
|
25 |
+ |
`ratatui-core 0.1.2`, `ratatui-widgets 0.3.2` and `makeover 2.4.1`, the versions in
|
|
26 |
+ |
`Cargo.lock`. This is a ceiling and not a usage count: it includes symbol sets for
|
|
27 |
+ |
widgets Alloy does not draw.
|
|
28 |
+ |
|
|
29 |
+ |
## What Alloy's own surfaces emit
|
|
30 |
+ |
|
|
31 |
+ |
Eighteen distinct non-ASCII codepoints, in total, across the console, the installer TUI
|
|
32 |
+ |
and every shipped config template.
|
|
33 |
+ |
|
|
34 |
+ |
| Codepoint | Glyph | Where |
|
|
35 |
+ |
|---|---|---|
|
|
36 |
+ |
| U+00B7 | `·` | helix config, whitespace render |
|
|
37 |
+ |
| U+00BB | `»` | starship prompt character |
|
|
38 |
+ |
| U+2014 | `—` | 97 sites, string literals across the console |
|
|
39 |
+ |
| U+2022 | `•` | installer, list bullets |
|
|
40 |
+ |
| U+2026 | `…` | truncation, six sites |
|
|
41 |
+ |
| U+2191 U+2192 U+2193 U+2195 | `↑ → ↓ ↕` | starship git-status, helix whitespace |
|
|
42 |
+ |
| U+23CE | `⏎` | helix, newline render |
|
|
43 |
+ |
| U+2423 | `␣` | helix, space render |
|
|
44 |
+ |
| U+2502 | `│` | helix, indent guide |
|
|
45 |
+ |
| U+2588 U+258F U+2591 | `█ ▏ ░` | installer progress bar, helix indent guide |
|
|
46 |
+ |
| U+25B8 U+25C2 | `▸ ◂` | starship segment separators |
|
|
47 |
+ |
| U+2718 | `✘` | starship, error state |
|
|
48 |
+ |
|
|
49 |
+ |
Latin-1 punctuation, arrows, four block-element characters and one dingbat. No Private
|
|
50 |
+ |
Use Area: **Alloy itself emits no Nerd Font icons.** The PUA reasoning in
|
|
51 |
+ |
`etc/skel/.config/fontconfig/fonts.conf` and in STACK.md is entirely about third-party
|
|
52 |
+ |
consumers (starship, yazi, bottom, helix), which is worth knowing before anyone treats
|
|
53 |
+ |
the `Mono` family constraint as an Alloy-internal requirement.
|
|
54 |
+ |
|
|
55 |
+ |
## What the widget stack can reach
|
|
56 |
+ |
|
|
57 |
+ |
723 distinct non-ASCII codepoints, once tests are excluded. As ranges:
|
|
58 |
+ |
|
|
59 |
+ |
- **U+2022**, the bullet `Canvas` uses as its default marker.
|
|
60 |
+ |
- **U+2190-U+2193**, the four arrows, for scrollbar ends.
|
|
61 |
+ |
- **U+2500-U+2570** (113) box drawing: `Block` ships plain, thick, double, rounded and
|
|
62 |
+ |
dashed at three densities, so nearly the whole block is reachable.
|
|
63 |
+ |
- **U+2574-U+259F** (44) the half-lines and the block elements, for gauges, bars and the
|
|
64 |
+ |
bevel `alloy_tui` draws.
|
|
65 |
+ |
- **U+25B2 U+25B6 U+25B8 U+25BA U+25BC U+25BE U+25C4**, triangles, for selection and
|
|
66 |
+ |
scroll markers.
|
|
67 |
+ |
- **U+2800-U+28FF** (256) the full braille range, which `Canvas` uses as a sub-cell pixel
|
|
68 |
+ |
grid.
|
|
69 |
+ |
- **U+1CD00-U+1CDE5** (230) and **U+1CEA0-U+1CEAB**, Symbols for Legacy Computing:
|
|
70 |
+ |
ratatui's sextant and octant marker sets.
|
|
71 |
+ |
- **U+1FB00-U+1FB3B** (60), **U+1FB82**, **U+1FB85**, **U+1FBE6-U+1FBE7**, Symbols for
|
|
72 |
+ |
Legacy Computing Supplement, same purpose.
|
|
73 |
+ |
|
|
74 |
+ |
The last three ranges are the interesting ones: they are recent Unicode, and a font that
|
|
75 |
+ |
covers box drawing convincingly can still have nothing there.
|
|
76 |
+ |
|
|
77 |
+ |
## Coverage against the shipped fonts
|
|
78 |
+ |
|
|
79 |
+ |
| Font | Codepoints | Missing from Alloy's set | Missing from the widget ceiling |
|
|
80 |
+ |
|---|---|---|---|
|
|
81 |
+ |
| IosevkaTerm Nerd Font Mono | 17,827 | **0** | **0** |
|
|
82 |
+ |
| Atkinson Hyperlegible | 342 | 13 | 722 |
|
|
83 |
+ |
| Departure Mono NF Mono (not in the image) | 11,468 | 5 | 557 |
|
|
84 |
+ |
|
|
85 |
+ |
**The monospace answer is that there is no gap.** IosevkaTerm Nerd Font Mono covers
|
|
86 |
+ |
every codepoint Alloy emits and every codepoint the widget stack could emit, sextants and
|
|
87 |
+ |
octants included. Nothing in a terminal, the console, the installer or the greeter falls
|
|
88 |
+ |
back to anything, so the chain below is insurance rather than a working part.
|
|
89 |
+ |
|
|
90 |
+ |
**Atkinson's gaps are not gaps**, because nothing routes box drawing to a sans font.
|
|
91 |
+ |
Atkinson serves the `sans-serif` alias and `gtk-font-name`, which is proportional UI text
|
|
92 |
+ |
in GTK dialogs and the portal file chooser. The 722 it lacks are box drawing, blocks,
|
|
93 |
+ |
braille and legacy-computing, none of which any Pango surface asks for. The rule worth
|
|
94 |
+ |
writing down: **cell-grid surfaces get the mono family and the symbol sets with it;
|
|
95 |
+ |
proportional surfaces get Atkinson and never emit a symbol set.** A future surface that
|
|
96 |
+ |
breaks that rule is where this becomes a real gap.
|
|
97 |
+ |
|
|
98 |
+ |
**Departure's gaps only matter outside the running system.** It is not in the image
|
|
99 |
+ |
(STACK.md records the 2026-08-05 audit), so it can only appear in a mockup, the README,
|
|
100 |
+ |
the social card or a splash plate. Of the eighteen codepoints Alloy emits it lacks five:
|
|
101 |
+ |
`⏎` (U+23CE), `␣` (U+2423), `▸` (U+25B8), `◂` (U+25C2), `✘` (U+2718). Four of those five
|
|
102 |
+ |
are starship and helix prompt furniture, which is exactly what a terminal mockup renders,
|
|
103 |
+ |
so a mockup set in Departure loses its prompt separators silently. It also has no
|
|
104 |
+ |
braille, no sextants and no octants, so no Departure render can show a `Canvas` or a
|
|
105 |
+ |
sparkline. Use Iosevka for any mockup of a running surface, and keep Departure for
|
|
106 |
+ |
headers and brand plates, which is what STACK.md already asks for on other grounds.
|
|
107 |
+ |
|
|
108 |
+ |
## The fallback chain, in order, and which links exist
|
|
109 |
+ |
|
|
110 |
+ |
From `etc/skel/.config/fontconfig/fonts.conf`. Each `<prefer>` list is tried in order and
|
|
111 |
+ |
fontconfig skips a family the system does not have.
|
|
112 |
+ |
|
|
113 |
+ |
| Alias | Order | In the image? |
|
|
114 |
+ |
|---|---|---|
|
|
115 |
+ |
| `monospace` | IosevkaTerm Nerd Font Mono | yes, 81 faces under `iosevkaterm-nerd` |
|
|
116 |
+ |
| | Iosevka Term | no |
|
|
117 |
+ |
| | Iosevka Nerd Font | no |
|
|
118 |
+ |
| | Iosevka | no |
|
|
119 |
+ |
| | DejaVu Sans Mono | no |
|
|
120 |
+ |
| `sans-serif` | Atkinson Hyperlegible | yes |
|
|
121 |
+ |
| | Inter | no |
|
|
122 |
+ |
| | Cantarell | yes, `abattis-cantarell-vf-fonts` |
|
|
123 |
+ |
| | DejaVu Sans | no |
|
|
124 |
+ |
| `serif` | Source Serif 4 | no |
|
|
125 |
+ |
| | Source Serif Pro | no |
|
|
126 |
+ |
| | Liberation Serif | yes |
|
|
127 |
+ |
| | DejaVu Serif | no |
|
|
128 |
+ |
| `emoji` | (deliberately absent) | no emoji font is installed |
|
|
129 |
+ |
|
|
130 |
+ |
**Six of the fourteen named families are not in the image.** They cost nothing at
|
|
131 |
+ |
runtime, because `<prefer>` skips what is absent, and they are not the emoji-alias defect
|
|
132 |
+ |
(that alias changed where emoji resolved to; these do not change anything). They are a
|
|
133 |
+ |
reading hazard rather than a rendering one: the list looks like a depth of fallback that
|
|
134 |
+ |
is not there. The monospace chain in particular has exactly one live entry, so if
|
|
135 |
+ |
IosevkaTerm ever failed to install, resolution would drop past four dead names straight
|
|
136 |
+ |
into Fedora's own generic rules. Whether the dead names get deleted or annotated is GO
|
|
137 |
+ |
task `6aeeb122`.
|
|
138 |
+ |
|
|
139 |
+ |
**What actually catches a gap is the layer below this file**, and it is worth naming
|
|
140 |
+ |
because the chain above suggests otherwise:
|
|
141 |
+ |
|
|
142 |
+ |
1. `/etc/fonts/conf.d/45-latin.conf` and `60-latin.conf`, Fedora's generic-family
|
|
143 |
+ |
ordering, which is what a request resolves through once the `<prefer>` list is
|
|
144 |
+ |
exhausted.
|
|
145 |
+ |
2. `59-adwaita-mono-fonts.conf`, `59-liberation-*.conf`, the URW base-35 set: the real
|
|
146 |
+ |
substitutes present on disk for mono, sans and serif.
|
|
147 |
+ |
3. The Noto set for everything non-Latin: `NotoSans[wght].ttf` plus 24 per-script
|
|
148 |
+ |
variable faces, `NotoSansCJK-VF.ttc` and `NotoSansMonoCJK-VF.ttc`. This is the layer
|
|
149 |
+ |
the 2026-07-29 coverage fix added, and it is what stops an arbitrary web page from
|
|
150 |
+ |
rendering as rows of missing glyphs.
|
|
151 |
+ |
4. Nothing, for emoji. That is the decided position, not a gap.
|
|
152 |
+ |
|
|
153 |
+ |
## Re-running this
|
|
154 |
+ |
|
|
155 |
+ |
The scripts are not in the repo: the measurement is a one-off against a built image, and
|
|
156 |
+ |
a checked-in tool that nobody runs drifts into a lie. Re-derive it by mounting the image
|
|
157 |
+ |
and reading `cmap` tables directly. The three numbers worth re-checking after a font bump
|
|
158 |
+ |
are the IosevkaTerm coverage count (17,827 at Nerd Fonts v3.4.0), the size of Alloy's own
|
|
159 |
+ |
emitted set (18), and whether either "missing from the widget ceiling" cell is still 0.
|