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