ttf-xmind-hinted
LOW
maintainer gaougalos
0 votes
scanned 2026-11-03 02:04:04.155120
Why flagged
Uploaded within the last 14 days with 2 or fewer community votes — little peer review so far.
Triggered rules
Low
Few votes, recently uploaded
zero_votes_recent
Uploaded within the last 14 days with 2 or fewer community votes — little peer review so far.
PKGBUILD
1
# Maintainer: gaou-piou <i.am.piou@gmail.com>
2
pkgname=ttf-xmind-hinted
3
_xmver=1.001
4
_gfcommit=79b80491c6d04c1868c482af411e6e13b530b4b8
5
_nfver=3.5.1
6
pkgver="${_xmver}"
7
pkgrel=1
8
pkgdesc='Xmind (Google Fonts), a humanist sans with a wght axis and Greek/Cyrillic, re-hinted with ttfautohint for FreeType (optionally static / Nerd Fonts patched)'
9
arch=('any')
10
url='https://fonts.google.com/specimen/Xmind'
11
license=('OFL-1.1')
12
makedepends=('python' 'python-fonttools' 'fontforge' 'parallel' 'ttfautohint')
13
options=(!strip)
14
provides=('ttf-xmind')
15
conflicts=('ttf-xmind')
16
source=(
17
"XmindVF.ttf::https://raw.githubusercontent.com/google/fonts/${_gfcommit}/ofl/xmind/Xmind%5Bwght%5D.ttf"
18
"XmindItalicVF.ttf::https://raw.githubusercontent.com/google/fonts/${_gfcommit}/ofl/xmind/Xmind-Italic%5Bwght%5D.ttf"
19
"OFL.txt::https://raw.githubusercontent.com/google/fonts/${_gfcommit}/ofl/xmind/OFL.txt"
20
"font-patcher-${_nfver}.zip::https://github.com/ryanoasis/nerd-fonts/releases/download/v${_nfver}/FontPatcher.zip"
21
"make_statics.py"
22
"make_features.py"
23
"set_gasp.py"
24
"measure.py"
25
"README.md"
26
"FEATURES.md"
27
)
28
noextract=("font-patcher-${_nfver}.zip")
29
sha256sums=('64cd402ec7bb4f9343bad5e6fe63556ee16dcd74ed94e8ccfa248eaee327c3b5'
30
'2b598d050e703870183637e7fa6fe70e40fcfa6fbad96e99e688de61462f1b72'
31
'1a88595220aa4de9f2dd8c471298820bd7e7c1dbc2a8eab78356790a999e58d2'
32
'42bcb32145499a35732274c7fc48deb434ad0d2e0e118f98527c1479c6fa251a'
33
'beb35eeea921f3b0edc75f9ded1702a489a3d04c7450840b7759c8004f5954c0'
34
'200fc13d7cf288ebd10c2832a0c9e1cf5a8b7c7e4e6283311778a2df7057581e'
35
'0b0464b268525569b5fa28b4735791efb22f22829ad178629776ae3ea82d7f99'
36
'93b62a59ba50bfbee53f1825a1be7f340806d92b33a9b5849fc728f40585766f'
37
'51e21338265f43067a41a06f51599936b9de34042fee930d642661404b4fb581'
38
'7c1859e0c61f583acdc5283cfe23c51271db172c891eb02dca1ea532098d323a')
39
40
# ── What this package does ──────────────────────────────────────────────────
41
#
42
# Xmind (the Xmind Project Authors, 2025, on Google Fonts) ships as two
43
# one-axis variable fonts: Xmind[wght].ttf (upright) and Xmind-Italic[wght].ttf
44
# (a true -12 degree oblique), wght 100-900, default 400. It covers Latin,
45
# Greek and Cyrillic. The sources are pinned to the google/fonts commit above.
46
#
47
# Upstream ships NO hinting (no fpgm/cvt, glyphs without instructions, a tiny
48
# prep). At hintstyle hintmedium/hintfull FreeType then treats the face as
49
# hinted and does not run its autohinter: Xmind renders completely unhinted
50
# and the i/j/ï/ϊ dots touch the letters at small sizes (README.md section 3).
51
# This package runs ttfautohint over it. See README.md for the measurements
52
# and FEATURES.md for what the font can do.
53
#
54
# Xmind's x-height grows with weight (1040 units Thin..Regular, 1100 Black,
55
# 2048 upem) while ttfautohint takes its blue zones from the default master
56
# (Regular), so a static, hinted per weight, can follow the weight where the
57
# variable font cannot. Measured, the variable font is within a few percent of
58
# the static ones; it stays the default because one file keeps every weight.
59
#
60
# FreeType only runs TrueType bytecode at hintstyle hintmedium/hintfull. The
61
# package ships (not enabled) /usr/share/fontconfig/conf.avail/80-$pkgname.conf
62
# that turns it on for the installed families, excluding Chromium/Electron by
63
# prgname (at device scale 1 they round every advance at hintmedium).
64
#
65
# ── Build-time options ───────────────────────────────────────────────────────
66
#
67
# Run from a terminal, prepare() asks for NERD_PATCH, XM_VARIANT, FEATURE_DEFAULTS,
68
# HINTING and HINT_PRESET (Enter keeps the default). Anything already set in the
69
# environment is not asked. Without a TTY the environment / defaults apply.
70
# Answers are saved to $srcdir/.build_opts.
71
#
72
# XM_VARIANT variable|static (default: variable)
73
# variable the two variable fonts (upright + italic)
74
# static one TTF per weight (and italic), cut with the
75
# fontTools instancer and hinted on its own
76
# STATIC_WEIGHTS "100 ... 900" wght values to cut (default: all nine)
77
# STATIC_ITALIC true/false also cut the italic (default true)
78
#
79
# NERD_PATCH true/false Patch with Nerd Fonts glyphs (default: false).
80
# font-patcher drops fvar/gvar, so this forces
81
# XM_VARIANT=static. Family "Xmind Nerd Font (Mono|Propo)".
82
#
83
# HINTING true/false Hint with ttfautohint (default: true).
84
#
85
# HINT_PRESET natural|balanced|sharp|light|custom (default: natural)
86
# natural stem=nnn range 8-48 x-height 0 (closest to the
87
# outline; default)
88
# balanced stem=qsq range 8-48 x-height 14 (ttfautohint
89
# defaults; opens
90
# the dots, but
91
# dev 19.6 at 400)
92
# sharp stem=sss range 6-48 x-height 14 (distorts Thin)
93
# light stem=nnn range 12-48 x-height 0 (HiDPI)
94
# custom use the HINT_* variables below verbatim
95
# Individual knobs (override the preset; empty = preset value):
96
# HINT_MODE HINT_RANGE_MIN HINT_RANGE_MAX HINT_LIMIT HINT_XHEIGHT
97
# HINT_XSNAP_EXC HINT_DEFAULT_SCRIPT HINT_FALLBACK_SCRIPT HINT_WINCOMPAT
98
# HINT_TTFA_TABLE HINT_FAMILY_SUFFIX HINT_INTEGER_PPEM (off: it grows text on
99
# Linux, +16-19% ink at small sizes) GASP_MODE keep|sized|smooth|gridfit
100
#
101
# FEATURE_DEFAULTS "tag,tag,..." (default: empty = leave the fonts alone)
102
# Bake these GSUB features into calt so EVERY renderer applies
103
# them (fontconfig fontfeatures only reaches pango). Xmind's
104
# candidates: case (capital-height punctuation), ss03 (see
105
# FEATURES.md). make_features.py refuses aalt/ordn. Not
106
# defaults: neither is right for running text.
107
# FEATURE_FAMILY "Name" Install the result under this family instead.
108
#
109
# Examples:
110
# makepkg -si (asks, when run from a terminal)
111
# makepkg -si </dev/null (never asks: defaults only)
112
# XM_VARIANT=static makepkg -si
113
# HINT_PRESET=balanced makepkg -si
114
# NERD_PATCH=true STATIC_WEIGHTS="400 700" makepkg -si
115
# ────────────────────────────────────────────────────────────────────────────
116
117
_opt_keys=(XM_VARIANT FEATURE_DEFAULTS FEATURE_FAMILY
118
STATIC_WEIGHTS STATIC_ITALIC NERD_PATCH
119
HINTING HINT_PRESET HINT_MODE HINT_RANGE_MIN HINT_RANGE_MAX
120
HINT_LIMIT HINT_XHEIGHT HINT_XSNAP_EXC HINT_DEFAULT_SCRIPT
121
HINT_FALLBACK_SCRIPT HINT_WINCOMPAT HINT_TTFA_TABLE
122
HINT_FAMILY_SUFFIX HINT_INTEGER_PPEM GASP_MODE)
123
124
_ask_yn() {
125
local _ans
126
read -r -p " $1? [$2] " _ans || _ans=""
127
[[ "${_ans:-$2}" =~ ^[yY] ]] && _yn=true || _yn=false
128
}
129
130
# _ask_choice TITLE DEFAULT KEY:description ... -> sets _choice to a KEY.
131
_ask_choice() {
132
local _title="$1" _default="$2"; shift 2
133
local -a _items=("$@")
134
local _i _ans
135
echo " $_title:"
136
for _i in "${!_items[@]}"; do
137
printf " %d) %-12s %s%s\n" "$((_i + 1))" "${_items[$_i]%%:*}" "${_items[$_i]#*:}" \
138
"$([[ "${_items[$_i]%%:*}" == "$_default" ]] && echo " (default)")"
139
done
140
while :; do
141
read -r -p " > " _ans || _ans=""
142
if [[ -z "$_ans" ]]; then _choice="$_default"; return; fi
143
if [[ "$_ans" =~ ^[0-9]+$ ]] && (( _ans >= 1 && _ans <= ${#_items[@]} )); then
144
_choice="${_items[$((_ans - 1))]%%:*}"; return
145
fi
146
echo " Enter 1-${#_items[@]}, or press Enter for $_default."
147
done
148
}
149
150
_prompt_options() {
151
if [[ -t 0 ]]; then
152
echo ""
153
echo " $pkgname: build options (Enter = default)"
154
echo ""
155
if [[ -z "${NERD_PATCH:-}" ]]; then
156
_ask_yn "Patch with Nerd Fonts glyphs (forces static fonts)" n; NERD_PATCH=$_yn
157
fi
158
if [[ "$NERD_PATCH" != true && -z "${XM_VARIANT:-}" ]]; then
159
_ask_choice "Font set" variable \
160
"variable:two wght-axis fonts, upright + italic (recommended)" \
161
"static:one file per weight/italic, hinted per weight"
162
XM_VARIANT=$_choice
163
fi
164
if [[ "${FEATURE_DEFAULTS+set}" != set ]]; then
165
echo ""
166
echo " A font cannot declare a feature \"on by default\"; baking moves its lookups"
167
echo " into calt, which every program applies (see the header of this PKGBUILD)."
168
_ask_choice "Bake features into calt" none \
169
"none:leave the fonts as upstream ships them (default)" \
170
"case:case - capital-height punctuation, for all-caps text" \
171
"custom:type the tag list yourself"
172
case $_choice in
173
none) FEATURE_DEFAULTS="" ;;
174
case) FEATURE_DEFAULTS="case" ;;
175
custom)
176
echo " Tags, comma or space separated (e.g. \"case,ss03\"):"
177
read -r -p " > " _tags || _tags=""
178
_tags="${_tags//[[:space:]]/,}"
179
while [[ "$_tags" == *,,* ]]; do _tags="${_tags//,,/,}"; done
180
_tags="${_tags#,}"; _tags="${_tags%,}"
181
FEATURE_DEFAULTS="$_tags" ;;
182
esac
183
fi
184
if [[ -z "${HINTING:-}" ]]; then
185
_ask_yn "Hint with ttfautohint (n = unhinted, as upstream)" y; HINTING=$_yn
186
fi
187
if [[ "$HINTING" == true && -z "${HINT_PRESET:-}" ]]; then
188
_ask_choice "Hinting preset" natural \
189
"natural:stem n, 8-48px, no x-height boost (closest to the design)" \
190
"balanced:stem q, 8-48px (opens the dots, heavier distortion at 400)" \
191
"sharp:stem s, 6-48px (highest contrast, distorts Thin)" \
192
"light:stem n, 12-48px, no x-height boost (HiDPI)" \
193
"custom:use the HINT_* environment variables"
194
HINT_PRESET=$_choice
195
fi
196
echo ""
197
else
198
echo "==> Non-interactive build (no TTY): using environment variables / defaults."
199
fi
200
201
local _k
202
: > "$srcdir/.build_opts"
203
for _k in "${_opt_keys[@]}"; do
204
# "set" rather than non-empty: HINT_XSNAP_EXC="" differs from unset.
205
if [[ "${!_k+set}" == set ]]; then
206
printf '%s=%s\n' "$_k" "${!_k}" >> "$srcdir/.build_opts"
207
fi
208
done
209
}
210
211
# makepkg runs build() and package() in separate shells, so both call this.
212
_resolve_options() {
213
local _k _v
214
if [[ ! -f "$srcdir/.build_opts" ]]; then
215
echo "Error: $srcdir/.build_opts missing; run a full makepkg (prepare() writes it)." >&2
216
exit 1
217
fi
218
while IFS='=' read -r _k _v; do
219
if [[ " ${_opt_keys[*]} " == *" $_k "* ]]; then
220
printf -v "$_k" '%s' "$_v"
221
fi
222
done < "$srcdir/.build_opts"
223
224
XM_VARIANT="${XM_VARIANT:-variable}"
225
FEATURE_DEFAULTS="${FEATURE_DEFAULTS:-}"
226
FEATURE_FAMILY="${FEATURE_FAMILY:-}"
227
STATIC_WEIGHTS="${STATIC_WEIGHTS:-100 200 300 400 500 600 700 800 900}"
228
STATIC_ITALIC="${STATIC_ITALIC:-true}"
229
NERD_PATCH="${NERD_PATCH:-false}"
230
HINTING="${HINTING:-true}"
231
HINT_PRESET="${HINT_PRESET:-natural}"
232
GASP_MODE="${GASP_MODE:-keep}"
233
HINT_WINCOMPAT="${HINT_WINCOMPAT:-false}"
234
HINT_TTFA_TABLE="${HINT_TTFA_TABLE:-false}"
235
HINT_INTEGER_PPEM="${HINT_INTEGER_PPEM:-false}"
236
HINT_DEFAULT_SCRIPT="${HINT_DEFAULT_SCRIPT:-latn}"
237
HINT_FALLBACK_SCRIPT="${HINT_FALLBACK_SCRIPT:-latn}"
238
239
case "$XM_VARIANT" in
240
variable|static) ;;
241
*) echo "Error: XM_VARIANT='$XM_VARIANT' invalid (variable|static)." >&2; exit 1 ;;
242
esac
243
for _v in STATIC_ITALIC NERD_PATCH HINTING HINT_WINCOMPAT HINT_TTFA_TABLE HINT_INTEGER_PPEM; do
244
case "${!_v}" in
245
true|false) ;;
246
*) echo "Error: $_v='${!_v}' must be true or false." >&2; exit 1 ;;
247
esac
248
done
249
# font-patcher drops fvar/gvar, so patching always works on statics.
250
if [[ "$NERD_PATCH" == true && "$XM_VARIANT" == variable ]]; then
251
echo "==> Note: the variable font cannot be Nerd-patched; using XM_VARIANT=static."
252
XM_VARIANT=static
253
fi
254
for _v in ${FEATURE_DEFAULTS//,/ }; do
255
if [[ ! "$_v" =~ ^[A-Za-z0-9]{4}$ ]]; then
256
echo "Error: FEATURE_DEFAULTS: '$_v' is not a feature tag (e.g. case)." >&2
257
exit 1
258
fi
259
done
260
for _v in $STATIC_WEIGHTS; do
261
case "$_v" in
262
100|200|300|400|500|600|700|800|900) ;;
263
*) echo "Error: STATIC_WEIGHTS: '$_v' is not 100, 200, ... 900." >&2; exit 1 ;;
264
esac
265
done
266
267
local _m _lo _hi _xh
268
case "$HINT_PRESET" in
269
natural) _m=nnn; _lo=8; _hi=48; _xh=0 ;;
270
balanced) _m=qsq; _lo=8; _hi=48; _xh=14 ;;
271
sharp) _m=sss; _lo=6; _hi=48; _xh=14 ;;
272
light) _m=nnn; _lo=12; _hi=48; _xh=0 ;;
273
custom) _m=nnn; _lo=8; _hi=48; _xh=0 ;;
274
*)
275
echo "Error: unknown HINT_PRESET='$HINT_PRESET'." >&2
276
echo " Valid: natural balanced sharp light custom" >&2
277
exit 1 ;;
278
esac
279
HINT_MODE="${HINT_MODE:-$_m}"
280
HINT_RANGE_MIN="${HINT_RANGE_MIN:-$_lo}"
281
HINT_RANGE_MAX="${HINT_RANGE_MAX:-$_hi}"
282
HINT_LIMIT="${HINT_LIMIT:-$HINT_RANGE_MAX}"
283
HINT_XHEIGHT="${HINT_XHEIGHT:-$_xh}"
284
285
if [[ ! "$HINT_MODE" =~ ^[nqs]{3}$ ]]; then
286
echo "Error: HINT_MODE='$HINT_MODE' must be 3 chars from n/q/s (e.g. nnn)." >&2
287
exit 1
288
fi
289
for _v in HINT_RANGE_MIN HINT_RANGE_MAX HINT_LIMIT HINT_XHEIGHT; do
290
if [[ ! "${!_v}" =~ ^[0-9]+$ ]]; then
291
echo "Error: $_v='${!_v}' must be a non-negative integer." >&2; exit 1
292
fi
293
done
294
if (( HINT_RANGE_MIN > HINT_RANGE_MAX )); then
295
echo "Error: HINT_RANGE_MIN ($HINT_RANGE_MIN) > HINT_RANGE_MAX ($HINT_RANGE_MAX)." >&2
296
exit 1
297
fi
298
for _v in HINT_DEFAULT_SCRIPT HINT_FALLBACK_SCRIPT; do
299
if [[ ! "${!_v}" =~ ^[a-z0-9]{3,4}$ ]]; then
300
echo "Error: $_v='${!_v}' must be a script tag (e.g. latn, none)." >&2; exit 1
301
fi
302
done
303
case "$GASP_MODE" in
304
keep|sized|smooth|gridfit) ;;
305
*) echo "Error: GASP_MODE='$GASP_MODE' invalid (keep|sized|smooth|gridfit)." >&2; exit 1 ;;
306
esac
307
}
308
309
prepare() {
310
_prompt_options
311
_resolve_options # validate now, so a typo fails before the long steps
312
313
rm -rf "$srcdir/font-patcher"
314
if [[ "$NERD_PATCH" == true ]]; then
315
mkdir -p "$srcdir/font-patcher"
316
bsdtar xf "$srcdir/font-patcher-${_nfver}.zip" -C "$srcdir/font-patcher"
317
fi
318
}
319
320
# _bake_features SRCDIR: move the lookups of FEATURE_DEFAULTS into calt into
321
# $srcdir/featured. Last step on purpose: ttfautohint never sees them.
322
_bake_features() {
323
local _src="$1" _fam=()
324
[[ -n "$FEATURE_DEFAULTS" ]] || return 0
325
[[ -n "$FEATURE_FAMILY" ]] && _fam=(--family "$FEATURE_FAMILY")
326
echo "==> Baking $FEATURE_DEFAULTS into calt" \
327
"${FEATURE_FAMILY:+(installed as '$FEATURE_FAMILY')}..."
328
python "$srcdir/make_features.py" --features "$FEATURE_DEFAULTS" \
329
"${_fam[@]+"${_fam[@]}"}" -o "$srcdir/featured" "$_src"/*.ttf
330
}
331
332
build() {
333
_resolve_options
334
335
echo "==> Options: variant=$XM_VARIANT nerd=$NERD_PATCH hinting=$HINTING"
336
if [[ "$XM_VARIANT" == static ]]; then
337
echo "==> Statics: weights='$STATIC_WEIGHTS' italic=$STATIC_ITALIC"
338
fi
339
if [[ "$HINTING" == true ]]; then
340
echo "==> ttfautohint: preset=$HINT_PRESET stem=$HINT_MODE" \
341
"range=$HINT_RANGE_MIN-$HINT_RANGE_MAX limit=$HINT_LIMIT x-height=$HINT_XHEIGHT" \
342
"x-snap-exc='${HINT_XSNAP_EXC-<default>}' gasp=$GASP_MODE integer-ppem=$HINT_INTEGER_PPEM" \
343
"ttfa-table=$HINT_TTFA_TABLE${HINT_FAMILY_SUFFIX:+ suffix='$HINT_FAMILY_SUFFIX'}"
344
fi
345
346
rm -rf "$srcdir/selected" "$srcdir/patched" "$srcdir/hinted" "$srcdir/featured"
347
mkdir -p "$srcdir/selected" "$srcdir/patched" "$srcdir/hinted"
348
349
# ── Step 1: select ──────────────────────────────────────────────────────────
350
if [[ "$XM_VARIANT" == variable ]]; then
351
install -m644 "$srcdir/XmindVF.ttf" "$srcdir/selected/XmindVariable.ttf"
352
install -m644 "$srcdir/XmindItalicVF.ttf" "$srcdir/selected/XmindItalicVariable.ttf"
353
else
354
echo "==> Cutting static instances..."
355
local _w
356
for _w in $STATIC_WEIGHTS; do
357
python "$srcdir/make_statics.py" --wght "$_w" -o "$srcdir/selected" "$srcdir/XmindVF.ttf"
358
if [[ "$STATIC_ITALIC" == true ]]; then
359
python "$srcdir/make_statics.py" --wght "$_w" --italic -o "$srcdir/selected" "$srcdir/XmindItalicVF.ttf"
360
fi
361
done
362
fi
363
local _count
364
_count=$(find "$srcdir/selected" -name '*.ttf' | wc -l)
365
echo "==> Selected $_count font file(s)."
366
if (( _count == 0 )); then
367
echo "Error: no fonts produced." >&2; exit 1
368
fi
369
370
local _hintsrc="$srcdir/selected"
371
372
# ── Step 2: Nerd Fonts patching ─────────────────────────────────────────────
373
# Patch first, hint afterwards: font-patcher does not keep hint bytecode.
374
if [[ "$NERD_PATCH" == true ]]; then
375
echo "==> Patching with Nerd Fonts glyphs (this takes a while)..."
376
find "$srcdir/selected" -type f | sort | \
377
parallel --will-cite -j"$(nproc)" python "$srcdir/font-patcher/font-patcher" \
378
--variable-width-glyphs -q -c {} -out "$srcdir/patched" '>/dev/null'
379
_count=$(find "$srcdir/patched" -maxdepth 1 -name '*.ttf' | wc -l)
380
if (( _count == 0 )); then
381
echo "Error: font-patcher produced no output. See messages above." >&2; exit 1
382
fi
383
echo "==> Patched $_count font(s)."
384
_hintsrc="$srcdir/patched"
385
fi
386
387
if [[ "$HINTING" != true ]]; then
388
_bake_features "$_hintsrc"
389
return 0
390
fi
391
392
# ── Step 3: ttfautohint ─────────────────────────────────────────────────────
393
local -a _ta_opts=(
394
--hinting-range-min="$HINT_RANGE_MIN"
395
--hinting-range-max="$HINT_RANGE_MAX"
396
--hinting-limit="$HINT_LIMIT"
397
--increase-x-height="$HINT_XHEIGHT"
398
--stem-width-mode="$HINT_MODE"
399
--default-script="$HINT_DEFAULT_SCRIPT"
400
--ignore-restrictions
401
)
402
if [[ "$NERD_PATCH" == true ]]; then
403
_ta_opts+=(--fallback-script=none --fallback-scaling)
404
else
405
_ta_opts+=(--fallback-script="$HINT_FALLBACK_SCRIPT")
406
fi
407
if [[ "${HINT_XSNAP_EXC+set}" == set ]]; then
408
_ta_opts+=(--x-height-snapping-exceptions="$HINT_XSNAP_EXC")
409
fi
410
if [[ "$HINT_WINCOMPAT" == true ]]; then _ta_opts+=(--windows-compatibility); fi
411
if [[ -n "${HINT_FAMILY_SUFFIX:-}" ]]; then _ta_opts+=(--family-suffix="$HINT_FAMILY_SUFFIX"); fi
412
if [[ "$HINT_TTFA_TABLE" == true ]]; then _ta_opts+=(--ttfa-table); else _ta_opts+=(--no-info); fi
413
414
# Serial on purpose: GNU parallel splits arguments that contain spaces.
415
echo "==> Hinting with ttfautohint..."
416
local _f
417
for _f in "$_hintsrc"/*.ttf; do
418
ttfautohint "${_ta_opts[@]}" "$_f" "$srcdir/hinted/${_f##*/}"
419
done
420
421
if [[ "$HINT_INTEGER_PPEM" == true ]]; then
422
echo "==> Setting head.flags bit 3 (integer ppem)..."
423
python - "$srcdir/hinted/"*.ttf <<'PY'
424
import sys
425
from fontTools.ttLib import TTFont
426
for path in sys.argv[1:]:
427
font = TTFont(path)
428
font["head"].flags |= 1 << 3
429
font.save(path)
430
PY
431
fi
432
433
if [[ "$GASP_MODE" != keep ]]; then
434
echo "==> Applying gasp mode '$GASP_MODE'..."
435
python "$srcdir/set_gasp.py" "$GASP_MODE" "$srcdir/hinted/"*.ttf
436
fi
437
438
_bake_features "$srcdir/hinted"
439
}
440
441
package() {
442
_resolve_options
443
444
local _out="$srcdir/selected"
445
if [[ "$HINTING" == true ]]; then
446
_out="$srcdir/hinted"
447
elif [[ "$NERD_PATCH" == true ]]; then
448
_out="$srcdir/patched"
449
fi
450
if [[ -n "$FEATURE_DEFAULTS" ]]; then _out="$srcdir/featured"; fi
451
if ! compgen -G "$_out/*.ttf" >/dev/null; then
452
echo "Error: no fonts to install in $_out." >&2; exit 1
453
fi
454
local _fontdir="$pkgdir/usr/share/fonts/xmind"
455
install -Dm644 -t "$_fontdir" "$_out/"*.ttf
456
install -Dm644 "$srcdir/OFL.txt" "$pkgdir/usr/share/licenses/$pkgname/OFL.txt"
457
458
# Opt-in rendering tweak: bytecode hinting for the families this build
459
# installed. Shipped in conf.avail and deliberately not enabled.
460
if [[ "$HINTING" == true ]]; then
461
local _avail="$pkgdir/usr/share/fontconfig/conf.avail"
462
install -d "$_avail"
463
local _fam _conf="$_avail/80-$pkgname.conf"
464
local _chromium_prgnames=(chrome chromium brave helium electron code slack signal-desktop vesktop)
465
local _prg _prgtests=""
466
for _prg in "${_chromium_prgnames[@]}"; do
467
_prgtests+=" <test qual=\"all\" name=\"prgname\" compare=\"not_eq\"><string>$_prg</string></test>"$'\n'
468
done
469
{
470
echo '<?xml version="1.0" encoding="UTF-8"?>'
471
echo '<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">'
472
echo "<!-- Installed by $pkgname. NOT enabled by default. Enable with:"
473
echo ""
474
echo " sudo ln -s /usr/share/fontconfig/conf.avail/80-$pkgname.conf /etc/fonts/conf.d/"
475
echo ""
476
echo " Use the ttfautohint bytecode hints in these fonts rather than"
477
echo " FreeType's light autohinter. hintmedium, not hintfull: same rendering"
478
echo " in cairo/pango, and Blink keeps subpixel positioning at hintmedium."
479
echo " Chromium and Electron apps are excluded: at device scale 1 they use"
480
echo " linear advances only for hintslight/none, so hintmedium would round"
481
echo " every glyph advance to a whole pixel (uneven letter gaps)."
482
echo " Firefox also rounds advances at hintmedium unless"
483
echo " gfx.text.subpixel-position.force-enabled is true. See README.md. -->"
484
echo '<fontconfig>'
485
while IFS= read -r _fam; do
486
_fam="${_fam//&/&}"; _fam="${_fam//</<}"
487
cat <<EOF
488
<match target="font">
489
<test name="family" compare="eq"><string>$_fam</string></test>
490
${_prgtests%$'\n'}
491
<edit name="hinting" mode="assign"><bool>true</bool></edit>
492
<edit name="autohint" mode="assign"><bool>false</bool></edit>
493
<edit name="hintstyle" mode="assign"><const>hintmedium</const></edit>
494
</match>
495
EOF
496
done < <(python - "$_fontdir/"*.ttf <<'PY' | sort -u
497
import sys
498
from fontTools.ttLib import TTFont
499
for path in sys.argv[1:]:
500
name = TTFont(path, lazy=True)["name"]
501
print(name.getDebugName(16) or name.getDebugName(1))
502
PY
503
)
504
echo '</fontconfig>'
505
} > "$_conf"
506
chmod 644 "$_conf"
507
fi
508
509
install -Dm644 -t "$pkgdir/usr/share/doc/$pkgname" "$srcdir/README.md" "$srcdir/FEATURES.md"
510
}
511
Scan history
| Scanned at (UTC) | Severity | Rules |
|---|---|---|
| 2026-11-03 02:04:04 | Low | 1 |
| 2026-11-03 00:04:01 | Low | 1 |