1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/env fontforge -script
"""Draw tree-connector glyphs directly into MnmlSymbols.ttf.
Rationale: rasterising SVGs at cell-edge coords leaves gaps between
rows. Copying JetBrainsMono's U+2502 / U+2514 renders their L visibly
thicker than the vertical, because font copy+paste drops hinting.
Construct both glyphs from a single 100u-wide rectangle primitive so
stroke thickness is guaranteed equal. Y-span matches JetBrainsMono's
box-drawing metrics (-400..1120) so the vertical links cell-to-cell
in ghostty.
Usage
-----
fontforge -script scripts/inject_tree_connectors.py \\
--target ~/Library/Fonts/MnmlSymbols.ttf \\
--shift 100
`--shift` is in font design units (JetBrainsMono em = 1000; 100 ≈ 10%
of em ≈ 0.6 cell columns). Positive = right, from the U+2502 baseline
x=250..350 → x=350..450 with --shift 100.
"""
# JetBrainsMono box-drawing metrics (from U+2502 / U+2514 outlines):
# stroke thickness: 100 units
# vertical span (│): y = -400..1120
# corner arms (└): upper arm y = 320..1120 (drops to elbow)
# horizontal y = 320..420 (100u thick)
# default x band: x = 250..350 (before shift)
= 100
= 1120
= -400 # extends into descender so │ links cell-to-cell
= 620 # top of horizontal arm — raised so the L
# turns near the row's vertical midpoint
# (icon center), not way down at descender.
= 520 # bottom of horizontal arm (unused for the
# single-contour L but kept for reference)
= 620 # matches JetBrainsMono's U+2514 horizontal span
= 250
= 350
= 600 # advance width (mono cell)
"""Emit a closed axis-aligned rectangle via a glyph pen. Wound
CLOCKWISE (top-left → top-right → bottom-right → bottom-left) in
the font's y-up coord system, which TrueType treats as a filled
outer contour. Counter-clockwise would be a HOLE and rasterisers
render those differently — that's what made the L's arm read
thicker than the plain vertical bar (2026-08-24)."""
"""Full-height vertical stroke — fills the em + descender so
consecutive rows link with no gap."""
"""L-shape as one closed contour. CoreText's autohinter was
snapping the arm's stem wider than the plain `│`. Narrow the
vertical arm to `arm_stroke` and CENTER it on the `│`'s axis
(x_left + STROKE/2), so both stems share the same column.
Horizontal arm keeps 100u thickness. (2026-08-24)"""
= 70
= + // 2
= - // 2
= + // 2
# Match horizontal thickness to the arm so the L reads uniform.
=
= -
= +
# Trace clockwise from top-left of the vertical arm.
=
=
=
=
= None
=
=
=
= +
# Clear any auto-generated hints on our two glyphs so fontforge
# can't pixel-snap the L's arm to a different width than the
# plain vertical bar (2026-08-24 — user reported L vertical arm
# rendered ~1.5× the `│` above it despite identical geometry).
=
=
=
=
# `omit-instructions` drops TrueType bytecode hints so ghostty
# rasterises straight from the outline. `round` snaps outlines to
# integer coords → both stems fall on the same pixel boundary.