summaryrefslogtreecommitdiff
path: root/scripts/generate-cjk-glyph-atlas.sh
blob: 01a1d932ef83aa10bf211ab4686a0e3aac63f840 (plain)
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
#!/usr/bin/env bash
set -euo pipefail

export LC_ALL=C.UTF-8

SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)"
FONT_PATH="${CJK_FONT_PATH:-/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc}"
MANIFEST="$REPO_ROOT/src/LivingVillage.Desktop/Assets/cjk-glyphs.txt"
OUTPUT="$REPO_ROOT/src/LivingVillage.Desktop/Assets/cjk-glyph-atlas.png"
CELL_PIXELS=24
COLUMNS=16
POINT_SIZE=20

for command_name in convert identify; do
    if ! command -v "$command_name" >/dev/null 2>&1; then
        printf 'Required command is missing: %s\n' "$command_name" >&2
        exit 127
    fi
done

if [[ ! -f "$FONT_PATH" ]]; then
    printf 'CJK font not found: %s\n' "$FONT_PATH" >&2
    exit 2
fi

if [[ ! -f "$MANIFEST" ]]; then
    printf 'CJK glyph manifest not found: %s\n' "$MANIFEST" >&2
    exit 2
fi

mapfile -t manifest_lines < "$MANIFEST"
character_count=${#manifest_lines[@]}
if (( character_count == 0 )); then
    printf 'CJK glyph manifest is empty: %s\n' "$MANIFEST" >&2
    exit 2
fi

characters=""
declare -A seen_characters=()
for index in "${!manifest_lines[@]}"; do
    character="${manifest_lines[$index]}"
    if [[ ${#character} -ne 1 ]]; then
        printf 'CJK glyph manifest line %s must contain exactly one character: %s\n' "$((index + 1))" "$MANIFEST" >&2
        exit 2
    fi
    if [[ ${seen_characters[$character]+present} ]]; then
        printf 'CJK glyph manifest contains a duplicate character on line %s: %s\n' "$((index + 1))" "$MANIFEST" >&2
        exit 2
    fi
    seen_characters[$character]=1
    characters+="$character"
done

rows=$(( (character_count + COLUMNS - 1) / COLUMNS ))
width=$(( COLUMNS * CELL_PIXELS ))
height=$(( rows * CELL_PIXELS ))
temporary_root="$(mktemp -d)"
trap 'rm -rf "$temporary_root"' EXIT

temporary_atlas="$temporary_root/cjk-glyph-atlas.png"
convert -size "${width}x${height}" xc:none -alpha on "$temporary_atlas"

for (( index = 0; index < character_count; index++ )); do
    character="${characters:index:1}"
    column=$(( index % COLUMNS ))
    row=$(( index / COLUMNS ))
    x=$(( column * CELL_PIXELS ))
    y=$(( row * CELL_PIXELS ))
    cell="$temporary_root/cell-$index.png"
    next_atlas="$temporary_root/atlas-$index.png"

    convert \
        -size "${CELL_PIXELS}x${CELL_PIXELS}" \
        xc:none \
        -alpha on \
        -font "$FONT_PATH" \
        -pointsize "$POINT_SIZE" \
        -fill white \
        -gravity center \
        -antialias \
        -annotate +0+0 "$character" \
        "$cell"
    convert "$temporary_atlas" "$cell" -geometry "+${x}+${y}" -composite "$next_atlas"
    mv "$next_atlas" "$temporary_atlas"
done

convert "$temporary_atlas" -strip "$OUTPUT"
actual_dimensions="$(identify -format '%wx%h' "$OUTPUT")"
expected_dimensions="${width}x${height}"
if [[ "$actual_dimensions" != "$expected_dimensions" ]]; then
    printf 'Generated atlas dimensions %s; expected %s\n' "$actual_dimensions" "$expected_dimensions" >&2
    exit 1
fi

printf 'CJK_GLYPH_ATLAS=%s\n' "$OUTPUT"
printf 'CJK_GLYPH_COUNT=%s\n' "$character_count"
printf 'CJK_GLYPH_DIMENSIONS=%s\n' "$actual_dimensions"