#!/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"